#include "matrix.h" #include #include #include // TODO Matrix-Funktionen implementieren /*typedef struct { unsigned int rows; //Zeilen unsigned int cols; //Spalten MatrixType *buffer; //Zeiger auf Speicherbereich Reihen*Spalten } Matrix;*/ Matrix createMatrix(unsigned int rows, unsigned int cols) { Matrix matrix; Matrix errorMatrix = {0, 0, NULL}; if (rows == 0 || cols == 0) { return errorMatrix; } matrix.rows = rows; matrix.cols = cols; matrix.buffer = malloc(rows * cols * sizeof(MatrixType)); if (matrix.buffer == NULL) { matrix.rows = 0; matrix.cols = 0; return matrix; } for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { matrix.buffer[i * matrix.cols + j] = UNDEFINED_MATRIX_VALUE; } } return matrix; } void clearMatrix(Matrix *matrix) { if (matrix->buffer != NULL) { free((*matrix).buffer); matrix->buffer = NULL; } matrix->rows = 0; matrix->cols = 0; } void setMatrixAt(const MatrixType value, Matrix matrix, const unsigned int rowIdx, // Kopie der Matrix wird übergeben const unsigned int colIdx) { if (rowIdx >= matrix.rows || colIdx >= matrix.cols || matrix.buffer == NULL) { // Speichergröße nicht überschreiten return; } matrix.buffer[rowIdx * matrix.cols + colIdx] = value; // rowIdx * matrix.cols -> Beginn der Zeile colIdx ->Spalte // innerhalb der Zeile } MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, // Kopie der Matrix wird übergeben unsigned int colIdx) { if (rowIdx >= matrix.rows || colIdx >= matrix.cols || matrix.buffer == NULL) { // Speichergröße nicht überschreiten return UNDEFINED_MATRIX_VALUE; } MatrixType value = matrix.buffer[rowIdx * matrix.cols + colIdx]; return value; } Matrix broadCastCols(const Matrix matrix, const unsigned int rows, const unsigned int cols) { Matrix copy = createMatrix( rows, cols); // Matrix 1 Kopie erstellen mit Dimensionen von Matrix2 for (int r = 0; r < rows; r++) { MatrixType value = getMatrixAt(matrix, r, 0); for (int c = 0; c < cols; c++) { setMatrixAt(value, copy, r, c); } } return copy; } Matrix broadCastRows(const Matrix matrix, const unsigned int rows, const unsigned int cols) { Matrix copy = createMatrix(rows, cols); for (int c = 0; c < cols; c++) { MatrixType value = getMatrixAt(matrix, 0, c); for (int r = 0; r < rows; r++) { setMatrixAt(value, copy, r, c); } } return copy; } Matrix add(const Matrix matrix1, const Matrix matrix2) { const unsigned int rows1 = matrix1.rows; const unsigned int rows2 = matrix2.rows; const unsigned int cols1 = matrix1.cols; const unsigned int cols2 = matrix2.cols; const int rowsEqual = ((rows1 == rows2) ? 1 : 0); const int colsEqual = ((cols1 == cols2) ? 1 : 0); if (rowsEqual && colsEqual) // addieren { Matrix result = createMatrix(rows1, cols1); // Speicher reservieren if (result.buffer == NULL) { return (Matrix){0, 0, NULL}; } for (int i = 0; i < (rows1 * cols1); i++) { // addieren result.buffer[i] = (matrix1.buffer[i] + matrix2.buffer[i]); // buffer[i] ⇔ *(buffer + i) Adresse = // Startadresse + (i * sizeof(MatrixType)) } return result; // zurückgeben } else if (rowsEqual && !colsEqual) { if (cols1 == 1) { Matrix result = createMatrix(rows2, cols2); if (result.buffer == NULL) { return (Matrix){0, 0, NULL}; } Matrix copy1 = broadCastCols(matrix1, rows2, cols2); if (!copy1.buffer) { clearMatrix(&result); return (Matrix){0, 0, NULL}; } for (unsigned int i = 0; i < rows2 * cols2; i++) { result.buffer[i] = copy1.buffer[i] + matrix2.buffer[i]; } /* freigeben, weil nicht mehr benötigt */ clearMatrix(©1); return result; // add und return } else if (cols2 == 1) { Matrix result = createMatrix(rows1, cols1); if (result.buffer == NULL) { Matrix error = {0, 0, NULL}; return error; } // Matrix2 hat nur eine Spalte -> horizontal broadcasten Matrix copy2 = broadCastCols(matrix2, rows1, cols1); for (unsigned int i = 0; i < rows1 * cols1; i++) { result.buffer[i] = matrix1.buffer[i] + copy2.buffer[i]; } // Optional: Speicher von copy2 freigeben clearMatrix(©2); return result; } else { printf("Fehlermeldung"); // vielleicht Fehlermeldung ändern zu // Programmabbruch Matrix error = {0, 0, NULL}; return error; } } else if (!rowsEqual && colsEqual) { if (rows1 == 1) { Matrix result = createMatrix(rows2, cols2); if (result.buffer == NULL) { return (Matrix){0, 0, NULL}; } Matrix copy1 = broadCastRows(matrix1, rows2, cols2); for (int i = 0; i < (rows2 * cols2); i++) { // addieren result.buffer[i] = (copy1.buffer[i] + matrix2.buffer[i]); // buffer[i] ⇔ *(buffer + i) Adresse = // Startadresse + (i * sizeof(MatrixType)) } return result; // add und return } else if (rows2 == 1) { Matrix result = createMatrix(rows1, cols1); if (result.buffer == NULL) { return (Matrix){0, 0, NULL}; } Matrix copy2 = broadCastRows(matrix2, rows1, cols1); // add und return for (int i = 0; i < (rows1 * cols1); i++) { // addieren result.buffer[i] = (matrix1.buffer[i] + copy2.buffer[i]); // buffer[i] ⇔ *(buffer + i) Adresse = // Startadresse + (i * sizeof(MatrixType)) } return result; } else { printf("Fehlermeldung"); // vielleicht Fehlermeldung ändern zu // Programmabbruch Matrix error = {0, 0, NULL}; return error; } } else { printf("Fehlermeldung"); // vielleicht Fehlermeldung ändern zu // Programmabbruch Matrix error = {0, 0, NULL}; return error; } } Matrix multiply(const Matrix matrix1, const Matrix matrix2) { // Spalten1 müssen gleich zeilen2 sein! dann multiplizieren if (matrix1.cols == matrix2.rows) { Matrix multMatrix = createMatrix(matrix1.rows, matrix2.cols); // durch neue matrix iterieren for (int r = 0; r < matrix1.rows; r++) { for (int c = 0; c < matrix2.cols; c++) { MatrixType sum = 0.0; // skalarprodukte berechnen, k damit die ganze zeile mal die ganze // spalte genommen wird quasi for (int k = 0; k < matrix1.cols; k++) { // sum+= // matrix1.buffer[r*matrix1.cols+k]*matrix2.buffer[k*matrix2.cols+c]; sum += getMatrixAt(matrix1, r, k) * getMatrixAt(matrix2, k, c); } // Ergebnisse in neue matrix speichern setMatrixAt(sum, multMatrix, r, c); } } return multMatrix; } // sonst fehler, kein multiply möglich else { Matrix errorMatrix = {0, 0, NULL}; return errorMatrix; } }