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 0000000..ffa1002 Binary files /dev/null and b/Startcode/runMatrixTests differ