Files
Info2-Pr-NeuroNetz/Startcode/matrix.c
T
Manuel GlockandClaude Opus 5.5 4d6a86f293 Pflichtaufgaben fertig: Matrix-Fixes, Bilder einlesen, NN-Testdatei
- matrix.c: multiply summiert in MatrixType statt int (Nachkommastellen
  gingen verloren), clearMatrix gibt Speicher frei, Indexpruefung pro
  Zeile/Spalte, NULL-Pruefungen in add/multiply
- imageInput.c: fseek-Spruenge entfernt, Dateikopf pruefen, Lesefehler
  behandeln, clearSeries implementiert
- neuralNetworkTests.c: prepareNeuralNetworkFile implementiert
- neuralNetwork.c: clearModel gibt das Layer-Array frei (Speicherleck)
- Zusaetzliche Unittests fuer Matrix und Bildeinlesen
- Testartefakte und Testprogramme in .gitignore, testFile.info2 entfernt

Alle 33 Tests gruen, keine Warnungen, 87.37 % Genauigkeit (wie Referenz).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 12:19:07 +01:00

169 lines
4.5 KiB
C

#include <stdlib.h>
#include <string.h>
#include "matrix.h"
// TODO Matrix-Funktionen implementieren
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
Matrix m;
if (rows == 0 || cols == 0)
//Ueberprüfen, ob ungültige Werte für Matrix vorhanden
{
m.rows = 0;
m.cols = 0;
m.buffer = NULL;
return m;
}
m.rows = rows;
m.cols = cols;
m.buffer = (MatrixType*)calloc(rows*cols, sizeof(MatrixType));
//Bei Fehlschalg gibt calloc entweder NULL oder Zeiger verschieden von NULL aus
if (m.buffer == NULL)
//Kein Speicher: leere Matrix zurueckgeben, damit Groesse und Puffer zusammenpassen
{
m.rows = 0;
m.cols = 0;
}
return m;
}
void clearMatrix(Matrix *matrix)
{
if (matrix != NULL)
{
free(matrix->buffer);
//Speicher leeren
matrix->buffer = NULL;
matrix->rows = 0;
matrix->cols = 0;
}
}
static int isValidIndex(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
//Zeile und Spalte einzeln pruefen: sonst wuerde z.B. (0, cols) faelschlich auf (1, 0) zugreifen
return matrix.buffer != NULL && rowIdx < matrix.rows && colIdx < matrix.cols;
}
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
if(isValidIndex(matrix, rowIdx, colIdx))
{
matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
}
}
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
MatrixType value = UNDEFINED_MATRIX_VALUE;
if(isValidIndex(matrix, rowIdx, colIdx))
{
value = matrix.buffer[rowIdx * matrix.cols + colIdx];
}
return value;
}
Matrix add(const Matrix matrix1, const Matrix matrix2)
{
typedef enum {elemt_add, broadcast} Addiermodi;
Addiermodi modus;
Matrix m = {NULL, 0, 0};
if(matrix1.buffer == NULL || matrix2.buffer == NULL)
{
return m;
}
//Elementweise zuerst pruefen: zwei Spaltenvektoren gleicher Groesse sind ein normaler elementweiser Fall
if((matrix1.rows == matrix2.rows) && (matrix1.cols == matrix2.cols))
{
modus = elemt_add;
}
else if((matrix1.cols == 1 || matrix2.cols ==1) && (matrix1.rows == matrix2.rows))
{
modus = broadcast;
}
else
{
return m;
}
if(modus == elemt_add)
{
m = createMatrix(matrix1.rows, matrix1.cols);
if(m.buffer == NULL)
{
return m;
}
for(unsigned int i = 0; i< matrix1.rows; i++)
{
for(unsigned int j = 0; j < matrix1.cols ; j++)
{
m.buffer[i*matrix1.cols+j] = matrix1.buffer[i*matrix1.cols+j] + matrix2.buffer[i*matrix1.cols+j];
}
}
return m;
}
else if(modus == broadcast)
{
if(matrix1.cols == 1)
{
m = createMatrix(matrix2.rows, matrix2.cols);
for(unsigned int i = 0; i< m.rows; i++)
{
for(unsigned int j = 0; j < m.cols ; j++)
{
m.buffer[i*matrix2.cols+j] = matrix2.buffer[i*matrix2.cols+j] + matrix1.buffer[i*matrix1.cols];
}
}
}
else
{
m = createMatrix(matrix1.rows, matrix1.cols);
for(unsigned int i = 0; i< m.rows; i++)
{
for(unsigned int j = 0; j < m.cols ; j++)
{
m.buffer[i*matrix1.cols+j] = matrix1.buffer[i*matrix1.cols+j] + matrix2.buffer[i*matrix2.cols];
}
}
}
}
return m;
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{
if(matrix1.buffer == NULL || matrix2.buffer == NULL || matrix1.cols != matrix2.rows)
{
Matrix failure = {NULL, 0, 0};
return failure;
}
Matrix m = createMatrix(matrix1.rows, matrix2.cols);
//Reihenfolge i-k-j statt i-j-k: matrix2 und m werden zeilenweise am Stueck durchlaufen.
//m startet dank calloc mit 0, daher wird direkt aufaddiert.
for(unsigned int i = 0; i < m.rows; i++)
{
for(unsigned int k = 0; k < matrix1.cols; k++)
{
MatrixType factor = matrix1.buffer[i*matrix1.cols+k];
//MatrixType statt int, hat die zahlen gerundet.
for(unsigned int j = 0; j < m.cols ; j++)
{
m.buffer[i*m.cols+j] += factor * matrix2.buffer[k*matrix2.cols+j];
}
}
}
return m;
}