#include #include #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; }