diff --git a/matrix.c b/matrix.c index ad00628..2d69389 100644 --- a/matrix.c +++ b/matrix.c @@ -4,32 +4,156 @@ // TODO Matrix-Funktionen implementieren +//Matrix dimensionieren Matrix createMatrix(unsigned int rows, unsigned int cols) { - + Matrix m; //Struktur anlegen, Varibale m von Typ Matrix + + //Sonderfall aus Unit-Test, wenn rows == 0 oder cols == 0, darf kein Speicher allokiert werden + if(rows==0 || cols==0){ + m.rows = 0; + m.cols = 0; + m.buffer = NULL; + return m; +} + + //Normalfall + m.rows = rows; // strukurvariable.feldname --> Struktur-Zugriffsoperator + m.cols = cols; + m.buffer = malloc((rows * cols) * sizeof(MatrixType)); //Speicher reserviert für Elemente + + return m; } void clearMatrix(Matrix *matrix) { - + // falls Speicher existiert (buffer NICHT NULL ist): freigeben + if(matrix->buffer != NULL) + { + free(matrix->buffer);// Speicher freigegeben aber zeigt irgendwo hin (dangling pointer) + } + + //Matrix in definierten leeren Zustand setzen + matrix->buffer = NULL; // dangling pointer zurücksetzen + matrix->rows = 0; + matrix->cols = 0; } +//Wert in Matrix schreiben und wo genau void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx) { - + // Sicherheit: wenn buffer == NULL (kein gültiger Speicher) oder Index außerhalb der Matrix --> return + if(matrix.buffer == NULL || rowIdx >= matrix.rows || colIdx >= matrix.cols) + { + return; + } + //index = Zeile * Anzahl_Spalten + Spalte + unsigned int index = rowIdx * matrix.cols + colIdx; + + // Schreibt value direkt an die berechnete Position im Matrixspeicher + matrix.buffer[index] = value; } MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx) { - + if (matrix.buffer == NULL || rowIdx >= matrix.rows || colIdx >= matrix.cols) + { + return 0; + } + + unsigned int index = rowIdx * matrix.cols + colIdx; + + return matrix.buffer[index]; } Matrix add(const Matrix matrix1, const Matrix matrix2) { - + Matrix result; + + //Zeilen müssen gleich sein + if (matrix1.rows != matrix2.rows) + { + result.rows = 0; + result.cols = 0; + result.buffer = NULL; + return result; + } + + + //Spalten müssen gleich sein (mit broadcasting) + //Fälle: gleiche Spalten ok, matrix1 hat 1 Spalte, matrix2 hat 1 Spalte + //sonst inkompatibel + if (matrix1.cols != matrix2.cols && matrix1.cols != 1 && matrix2.cols != 1) + { + result.rows = 0; + result.cols = 0; + result.buffer = NULL; + return result; + } + + result.rows = matrix1.rows; + result.cols = (matrix1.cols > matrix2.cols) ? matrix1.cols : matrix2.cols; + + result.buffer = malloc(result.rows * result.cols * sizeof(MatrixType)); + + for (unsigned int r = 0; r < result.rows; r++) + { + for (unsigned int c = 0; c < result.cols; c++) + { + // Bestimme Spalte für matrix1: + // Wenn nur 1 Spalte -> immer Spalte 0 benutzen + unsigned int c1 = (matrix1.cols == 1) ? 0 : c; + + // Bestimme Spalte für matrix2: + unsigned int c2 = (matrix2.cols == 1) ? 0 : c; + + MatrixType v1 = getMatrixAt(matrix1, r, c1); + MatrixType v2 = getMatrixAt(matrix2, r, c2); + + setMatrixAt(v1 + v2, result, r, c); + } + } + + return result; } + Matrix multiply(const Matrix matrix1, const Matrix matrix2) { - + Matrix result; + + if(matrix1.cols != matrix2.rows) + { + result.rows = 0; + result.cols = 0; + result.buffer = NULL; + return result; + } + + + result.rows = matrix1.rows; + result.cols = matrix2.cols; + + result.buffer = malloc(result.rows * result.cols * sizeof(MatrixType)); + + for (unsigned int r = 0; r < result.rows; r++) + { + for (unsigned int c = 0; c < result.cols; c++) + { + MatrixType sum = 0; + + // gemeinsame Dimension = matrix1.cols = matrix2.rows + for (unsigned int i = 0; i < matrix1.cols; i++) + { + MatrixType a = getMatrixAt(matrix1, r, i); + MatrixType b = getMatrixAt(matrix2, i, c); + + sum += a * b; + } + + setMatrixAt(sum, result, r, c); + } + } + + return result; } \ No newline at end of file diff --git a/matrix.h b/matrix.h index 43825a1..2889133 100644 --- a/matrix.h +++ b/matrix.h @@ -5,6 +5,13 @@ typedef float MatrixType; +// TODO Matrixtyp definieren +typedef struct { + unsigned int rows; + unsigned int cols; + MatrixType* buffer; //buffer Pointer zeigt auf Heap, mit malloc dort dann Speicher reservieren +} Matrix; + Matrix createMatrix(unsigned int rows, unsigned int cols); void clearMatrix(Matrix *matrix); @@ -13,4 +20,5 @@ MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int co Matrix add(const Matrix matrix1, const Matrix matrix2); Matrix multiply(const Matrix matrix1, const Matrix matrix2); + #endif \ No newline at end of file diff --git a/matrix.o b/matrix.o index f4784ba..7295845 100644 Binary files a/matrix.o and b/matrix.o differ diff --git a/neuralNetwork.o b/neuralNetwork.o index 23b768c..f3b6a32 100644 Binary files a/neuralNetwork.o and b/neuralNetwork.o differ diff --git a/neuralNetworkTests.c b/neuralNetworkTests.c index 4e1a7e8..7f57116 100644 --- a/neuralNetworkTests.c +++ b/neuralNetworkTests.c @@ -2,30 +2,23 @@ #include #include #include -#include "unity.h" +#include "unity/unity.h" #include "neuralNetwork.h" static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn) { - + //öffnet die Datei in Binär zum schreiben FILE *file = fopen(path, "wb"); if (!file) return; - + //Fester Headerstring const char *tag = "__info2_neural_network_file_format__"; fwrite(tag, sizeof(char), strlen(tag), file); - - if (nn.numberOfLayers == 0 || nn.layers == NULL) { - int zero = 0; - fwrite(&zero, sizeof(int), 1, file); // inputDim - fwrite(&zero, sizeof(int), 1, file); // outputDim - fclose(file); - return; - } - + //Bestimmt die Eingabedimension int inputDim = nn.layers[0].weights.cols; fwrite(&inputDim, sizeof(int), 1, file); + for (unsigned int i = 0; i < nn.numberOfLayers; i++) { const Layer *L = &nn.layers[i]; @@ -33,12 +26,11 @@ static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn) const Matrix *B = &L->biases; int outputDim = W->rows; - fwrite(&outputDim, sizeof(int), 1, file); - + //Anzahl der Weight-Werte size_t weightCount = (size_t)(W->rows * W->cols); - fwrite(W->buffer, sizeof(MatrixType), weightCount, file); - + fwrite(&weightCount, sizeof(size_t), 1, file); + //Anzahl der Bias-Werte size_t biasCount = (size_t)(B->rows * B->cols); fwrite(B->buffer, sizeof(MatrixType), biasCount, file); diff --git a/runMatrixTests b/runMatrixTests deleted file mode 100755 index 3de3bd9..0000000 Binary files a/runMatrixTests and /dev/null differ diff --git a/runMatrixTests.dSYM/Contents/Resources/DWARF/runMatrixTests b/runMatrixTests.dSYM/Contents/Resources/DWARF/runMatrixTests index ba2c961..7db8545 100644 Binary files a/runMatrixTests.dSYM/Contents/Resources/DWARF/runMatrixTests and b/runMatrixTests.dSYM/Contents/Resources/DWARF/runMatrixTests differ diff --git a/runNeuralNetworkTests b/runNeuralNetworkTests index 67bf8d9..2738bd2 100755 Binary files a/runNeuralNetworkTests and b/runNeuralNetworkTests differ diff --git a/runNeuralNetworkTests.dSYM/Contents/Resources/DWARF/runNeuralNetworkTests b/runNeuralNetworkTests.dSYM/Contents/Resources/DWARF/runNeuralNetworkTests index 1a4cf33..3c6553f 100644 Binary files a/runNeuralNetworkTests.dSYM/Contents/Resources/DWARF/runNeuralNetworkTests and b/runNeuralNetworkTests.dSYM/Contents/Resources/DWARF/runNeuralNetworkTests differ diff --git a/some__nn_test_file.info2 b/some__nn_test_file.info2 deleted file mode 100644 index 1e6158f..0000000 Binary files a/some__nn_test_file.info2 and /dev/null differ