Files
2026-11-06 11:25:50 +01:00

170 lines
5.9 KiB
C

#include <stdlib.h>
#include <string.h>
#include "matrix.h"
// TODO Matrix-Funktionen implementieren
Matrix createMatrix(unsigned int rows, unsigned int cols) // eine Matrix mit ner bestimmten Anzahl an Zeilen und Spalten erstellen und benötigten Speicher reservieren
{
// leere Matrix erstellen:
Matrix matrix = {0, 0, NULL};
if (rows == 0 || cols == 0) // Matrizen mit null Zeilen oder Spalten sind nicht erlaubt
{
return matrix;
}
// Speicher für alle Matrixelemente reservieren:
matrix.buffer = (MatrixType *)calloc(rows * cols, sizeof(MatrixType));
// prüfen, ob die Speicherreservierung erfolgreich war:
if (matrix.buffer != NULL)
{
matrix.rows = rows;
matrix.cols = cols;
}
return matrix;
}
void clearMatrix(Matrix *matrix) // den dynamisch reservierten Speicher einer Matrix freigeben und die Matrix zurücksetzen
{
if (matrix != NULL) // prüfen, ob ein gültiger Zeiger übergeben wurde
{
free(matrix->buffer); // reservierten Speicher freigeben
// Matrix auf Ausgangszustand zurücksetzen:(kann sonst zu Speicherlecks (Memory Leaks) führen, da dynamische Speicher weiterhin belegt bleibt)
matrix->buffer = NULL;
matrix->rows = 0;
matrix->cols = 0;
}
}
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx) // einen bestimmten Wert an einer bestimmten Position der Matrix speichern
{
// prüfen, ob die Matrix gültig ist und die Indizes innerhalb der Matrixgrenzen liegen:
if (matrix.buffer == NULL || rowIdx >= matrix.rows || colIdx >= matrix.cols)
{
return;
}
unsigned int index = rowIdx * matrix.cols + colIdx; // Position im eindimensionalen Speicher berechnen
matrix.buffer[index] = value; // Wert an der gewünschten Position speichern
}
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx) // einen Wert an einer bestimmten Position auslesen
{
// prüfen, ob die Matrix gültig ist und die Indizes innerhalb der Matrixgrenzen liegen:
if (matrix.buffer == NULL || rowIdx >= matrix.rows || colIdx >= matrix.cols)
{
return UNDEFINED_MATRIX_VALUE; // in matrix.h def.
}
unsigned int index = rowIdx * matrix.cols + colIdx; // eindimensionalen Index berechnen
return matrix.buffer[index]; // Wert an der gewünschten Position zurückgeben
}
Matrix add(const Matrix matrix1, const Matrix matrix2) // zwei Matrizen addieren
{
Matrix result = {0, 0, NULL}; // zunächst eine leere Ergebnismatrix erstellen
// ungültige Eingabematrizen überprüfen:
if (matrix1.buffer == NULL || matrix2.buffer == NULL || matrix1.rows == 0 || matrix1.cols == 0 || matrix2.rows == 0 || matrix2.cols == 0)
{
return result;
}
// Fall 1: Beide Matrizen haben dieselben Dimensionen:
if (matrix1.rows == matrix2.rows &&
matrix1.cols == matrix2.cols)
{
result = createMatrix(matrix1.rows, matrix1.cols);
if (result.buffer == NULL)
{
return result;
}
for (unsigned int i = 0; i < matrix1.rows * matrix1.cols; i++) // alle Elemente paarweise addieren
{
result.buffer[i] = matrix1.buffer[i] + matrix2.buffer[i];
}
}
// Fall 2: Broadcasting mit einem Spaltenvektor:
else if (matrix1.rows == matrix2.rows && (matrix1.cols == 1 || matrix2.cols == 1))
{
// die Matrix mit mehr Spalten bestimmt die Ergebnisgröße:
const Matrix *matrix = &matrix1;
const Matrix *vector = &matrix2;
if (matrix1.cols == 1) // falls matrix1 der Spaltenvektor ist, werden die Rollen der beiden Eingabematrizen vertauscht (Broadcasting soll in beiden Reihenfolgen funktionieren)
{
matrix = &matrix2;
vector = &matrix1;
}
result = createMatrix(matrix->rows, matrix->cols);
if (result.buffer == NULL)
{
return result;
}
for (unsigned int row = 0; row < matrix->rows; row++) // jeden Matrixwert mit dem Vektorwert seiner Zeile addieren
{
for (unsigned int col = 0; col < matrix->cols; col++)
{
result.buffer[row * matrix->cols + col] =
matrix->buffer[row * matrix->cols + col]
+ vector->buffer[row];
}
}
}
return result; // wenn keine der beiden Varianten möglich ist, bleibt Ergebnismatrix leer
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2) // zwei Matrizen multiplizieren
{
Matrix result = {0, 0, NULL}; // leere Ergebnismatrix
// prüfen, ob beide Eingabematrizen gültig sind:
if (matrix1.buffer == NULL || matrix2.buffer == NULL || matrix1.rows == 0 || matrix1.cols == 0 || matrix2.rows == 0 || matrix2.cols == 0)
{
return result;
}
if (matrix1.cols != matrix2.rows) // Spaltenanzahl der ersten Matrix muss der Zeilenanzahl der zweiten Matrix entsprechen
{
return result;
}
result = createMatrix(matrix1.rows, matrix2.cols); // Ergebnis hat so viele Zeilen wie matrix1 und so viele Spalten wie matrix2
if (result.buffer == NULL)
{
return result;
}
for (unsigned int row = 0; row < matrix1.rows; row++) // Durchführung Matrixmultiplikation...
{
for (unsigned int col = 0; col < matrix2.cols; col++)
{
MatrixType sum = 0; // Summe für das aktuelle Ergebniselement
for (unsigned int k = 0; k < matrix1.cols; k++)
{
sum += matrix1.buffer[row * matrix1.cols + k] * matrix2.buffer[k * matrix2.cols + col];
// "row" durchläuft Zeilen d. ersten Matrix; "col" durchläuft Zeilen d. zweiten Matrix; "k" berechnet Summe d. Produkte
}
result.buffer[row * result.cols + col] = sum; // berechnetes Ergebnis speichern
}
}
return result;
}