From 6dad1d2df29d79d2364b9e4349344ac5c6dbed0f Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 6 Nov 2026 11:25:50 +0100 Subject: [PATCH] Matrix --- Startcode/matrix.c | 155 ++++++++++++++++++++++++++++++++++++--- Startcode/matrix.h | 6 ++ Startcode/runMatrixTests | Bin 0 -> 64848 bytes 3 files changed, 151 insertions(+), 10 deletions(-) create mode 100755 Startcode/runMatrixTests diff --git a/Startcode/matrix.c b/Startcode/matrix.c index ad00628..de0d2d0 100644 --- a/Startcode/matrix.c +++ b/Startcode/matrix.c @@ -4,32 +4,167 @@ // TODO Matrix-Funktionen implementieren -Matrix createMatrix(unsigned int rows, unsigned int cols) -{ +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) +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) +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) +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) +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) +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; } \ No newline at end of file diff --git a/Startcode/matrix.h b/Startcode/matrix.h index cc640d1..26592c0 100644 --- a/Startcode/matrix.h +++ b/Startcode/matrix.h @@ -6,6 +6,12 @@ typedef float MatrixType; // TODO Matrixtyp definieren +typedef struct +{ + unsigned int rows; // Anzahl der Zeilen + unsigned int cols; // Anzahl der Spalten + MatrixType *buffer; // Zeiger auf den Speicher mit den Matrixwerten +} Matrix; Matrix createMatrix(unsigned int rows, unsigned int cols); diff --git a/Startcode/runMatrixTests b/Startcode/runMatrixTests new file mode 100755 index 0000000000000000000000000000000000000000..ffa100232c45015cb2f460c486063a9a9845df6e GIT binary patch literal 64848 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