2 Commits
Author SHA1 Message Date
Anja Freudenreich 447e77a7bf updating 2026-09-17 14:46:11 +02:00
Anja Freudenreich a6749f07d1 updating 2026-09-17 14:45:27 +02:00
38 changed files with 119 additions and 357 deletions

No files matched your search

+59 -6
View File
@@ -1,8 +1,61 @@
mnist
runTests
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
runMatrixTests
runImageInputTests
runNeuralNetworkTests
.vscode
*.out
*.app
*.i*86
*.x86_64
*.hex
Startcode/mnist
Startcode/runTests
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# IDE folders
.vscode/
.idea/
# macOS
.DS_Store
+22
View File
@@ -0,0 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "imageInput.h"
#define BUFFER_SIZE 100
#define FILE_HEADER_STRING "__info2_image_file_format__"
// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
GrayScaleImageSeries *readImages(const char *path)
{
GrayScaleImageSeries *series = NULL;
return series;
}
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
void clearSeries(GrayScaleImageSeries *series)
{
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+35
View File
@@ -0,0 +1,35 @@
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
// TODO Matrix-Funktionen implementieren
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
}
void clearMatrix(Matrix *matrix)
{
}
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
}
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
}
Matrix add(const Matrix matrix1, const Matrix matrix2)
{
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{
}
+2 -7
View File
@@ -5,14 +5,8 @@
typedef float MatrixType;
// Matrixtyp
typedef struct Matrix
{
size_t rows;
size_t cols;
MatrixType *buffer;
// TODO Matrixtyp definieren
} Matrix;
Matrix createMatrix(unsigned int rows, unsigned int cols);
void clearMatrix(Matrix *matrix);
@@ -21,4 +15,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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,30 +6,9 @@
#include "neuralNetwork.h"
static void erzeugeMatrix(FILE *file, const Matrix *m)
{
fwrite(&m->rows, sizeof(int), 1, file);
fwrite(&m->cols, sizeof(int), 1, file);
fwrite(m->buffer, sizeof(MatrixType), m->rows * m->cols, file);
}
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
{
FILE *file = fopen(path, "wb");
if (!file)
return;
const char *header = "__info2_neural_network_file_format__";
fwrite(header, sizeof(char), strlen(header), file);
fwrite(&nn.numberOfLayers, sizeof(int), 1, file);
for (int i = 0; i < nn.numberOfLayers; i++)
{
erzeugeMatrix(file, &nn.layers[i].weights);
erzeugeMatrix(file, &nn.layers[i].biases);
}
fclose(file);
// TODO
}
void test_loadModelReturnsCorrectNumberOfLayers(void)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-170
View File
@@ -1,170 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "imageInput.h"
#define BUFFER_SIZE 100
#define FILE_HEADER_STRING "__info2_image_file_format__"
typedef enum
{
IMG_SUCCESS = 0,
IMG_ERR_INVALID_HEADER, // Header did not match
IMG_ERR_READ, // Failed to read from file, maybe it's too short
IMG_ERR, // General Error
} ImageError;
static ImageError checkHeader(FILE *file);
static ImageError readPictureParams(unsigned short *number, unsigned short *width, unsigned short *height, FILE *file);
static ImageError readImage(size_t numPixels, GrayScalePixelType *pixelBuffer, unsigned char *label, FILE *file);
static ImageError parseImageFile(FILE *file, GrayScaleImageSeries *series);
GrayScaleImageSeries *readImages(const char *path)
{
// It's very important to call calloc here because otherwise clearSeries() might try to free random memory
GrayScaleImageSeries *series = calloc(1, sizeof(GrayScaleImageSeries));
if (series == NULL)
{
return NULL;
}
FILE *file = fopen(path, "rb");
// If fopen() failed
if (file == NULL)
{
clearSeries(series);
series = NULL;
return NULL;
}
// Try to parse the whole file. If anything fails memory is freed
if (parseImageFile(file, series))
{
clearSeries(series);
series = NULL; // Return NULL after the file is properly closed
}
fclose(file);
return series;
}
static ImageError parseImageFile(FILE *file, GrayScaleImageSeries *series)
{
if (checkHeader(file))
{
return IMG_ERR; // header check failed
}
unsigned short imgCNT, width, height;
if (readPictureParams(&imgCNT, &width, &height, file))
{
return IMG_ERR; // read failed
}
size_t pixels = width * height;
// The images contain more pointers, definitely use calloc here
series->images = calloc(imgCNT, sizeof(GrayScaleImage));
if (series->images == NULL)
{
return IMG_ERR;
}
series->labels = malloc(imgCNT * sizeof(unsigned char));
if (series->labels == NULL)
{
return IMG_ERR;
}
series->count = imgCNT;
// Read every image and it's label
for (size_t imageIdx = 0; imageIdx < imgCNT; imageIdx++)
{
GrayScaleImage *curImage = &series->images[imageIdx];
curImage->buffer = malloc(sizeof(GrayScalePixelType) * pixels);
if (curImage->buffer == NULL)
{
return IMG_ERR;
}
curImage->width = width;
curImage->height = height;
if (readImage(pixels, curImage->buffer, &series->labels[imageIdx], file))
{
return IMG_ERR;
}
}
return IMG_SUCCESS;
}
static ImageError checkHeader(FILE *file)
{
size_t len = strlen(FILE_HEADER_STRING);
char headerBuf[len + 1];
size_t charsRead = fread(headerBuf, 1, len, file);
// Check if the file is to short
if (charsRead < len)
{
return IMG_ERR_READ;
}
headerBuf[len] = '\0'; // Terminate string
return strcmp(headerBuf, FILE_HEADER_STRING) == 0 ? IMG_SUCCESS : IMG_ERR_INVALID_HEADER;
}
static ImageError readPictureParams(unsigned short *number, unsigned short *width, unsigned short *height, FILE *file)
{
// number of images
if (1 != fread(number, sizeof(unsigned short), 1, file))
{
return IMG_ERR_READ;
}
// image width
if (1 != fread(width, sizeof(unsigned short), 1, file))
{
return IMG_ERR_READ;
}
// height
if (1 != fread(height, sizeof(unsigned short), 1, file))
{
return IMG_ERR_READ;
}
return IMG_SUCCESS;
}
// Read 1 image and it's label
static ImageError readImage(size_t numPixels, GrayScalePixelType *pixelBuffer, unsigned char *label, FILE *file)
{
if (numPixels > fread(pixelBuffer, sizeof(GrayScalePixelType), numPixels, file))
{
return IMG_ERR_READ;
}
if (1 != fread(label, sizeof(unsigned char), 1, file))
{
return IMG_ERR_READ;
}
return IMG_SUCCESS;
}
// Frees memory for each image buffer, image, label and finally series
void clearSeries(GrayScaleImageSeries *series)
{
if (series)
{
int seriesLen = series->count;
for (size_t imageIdx = 0; imageIdx < seriesLen; imageIdx++)
{
free(series->images[imageIdx].buffer);
}
free(series->images);
free(series->labels);
free(series);
}
}
-152
View File
@@ -1,152 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
#include <stdio.h>
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
Matrix mat = {.rows = rows, .cols = cols};
// If one dimension is 0, return both dimensions as 0 and don't init the array/buffer.
if (rows == 0 || cols == 0)
{
mat.rows = 0;
mat.cols = 0;
return mat;
}
// allocate contiguous and 0 initialized memory
mat.buffer = calloc(rows * cols, sizeof(MatrixType));
// check if calloc failed
if (mat.buffer == NULL)
{
clearMatrix(&mat);
perror("could not allocate memory");
}
return mat;
}
// reduce the dimensions to (0, 0) and free the memory
void clearMatrix(Matrix *matrix)
{
free(matrix->buffer);
matrix->buffer = NULL;
matrix->cols = 0;
matrix->rows = 0;
}
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
// do nothing if idx is not in array or matrix buffer is NULL
if (!(rowIdx < matrix.rows) || !(colIdx < matrix.cols) || matrix.buffer == NULL)
{
return;
}
matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
}
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
// return UNDEFINED_MATRIX_VALUE if idx is not in array or matrix buffer is NULL
if (!(rowIdx < matrix.rows) || !(colIdx < matrix.cols) || matrix.buffer == NULL)
{
return UNDEFINED_MATRIX_VALUE;
}
return matrix.buffer[rowIdx * matrix.cols + colIdx];
};
Matrix add(const Matrix matrix1, const Matrix matrix2)
{
Matrix resMat = (matrix1.cols > matrix2.cols) ? createMatrix(matrix1.rows, matrix1.cols) : createMatrix(matrix2.rows, matrix2.cols);
if (resMat.buffer == NULL)
{
return createMatrix(0, 0);
}
if (matrix1.cols != matrix2.cols)
{
if (matrix1.rows != matrix2.rows)
{
clearMatrix(&resMat);
return resMat;
}
else if (matrix1.cols == 1)
{
// broadcast vector
for (size_t m = 0; m < matrix2.rows; m++)
{
for (size_t n = 0; n < matrix2.cols; n++)
{
setMatrixAt(getMatrixAt(matrix2, m, n) + getMatrixAt(matrix1, m, 0), resMat, m, n);
}
}
return resMat;
}
else if (matrix2.cols == 1)
{
// broadcast vector
for (size_t m = 0; m < matrix1.rows; m++)
{
for (size_t n = 0; n < matrix1.cols; n++)
{
setMatrixAt(getMatrixAt(matrix1, m, n) + getMatrixAt(matrix2, m, 0), resMat, m, n);
}
}
return resMat;
}
else
{
clearMatrix(&resMat);
return resMat;
}
}
for (size_t m = 0; m < matrix1.rows; m++)
{
for (size_t n = 0; n < matrix1.cols; n++)
{
setMatrixAt(getMatrixAt(matrix1, m, n) + getMatrixAt(matrix2, m, n), resMat, m, n);
}
}
return resMat;
}
Matrix multiply(const Matrix A, const Matrix B)
{
if (A.cols != B.rows || A.buffer == NULL || B.buffer == NULL)
{
return createMatrix(0, 0);
}
int rows = A.rows, cols = B.cols;
Matrix C = createMatrix(rows, cols);
if (C.buffer == NULL)
{
return createMatrix(0, 0);
}
// M = Rows, K = Common Dim, N = Cols
size_t M = A.rows, K = A.cols, N = B.cols;
for (size_t i = 0; i < M; i++)
{
for (size_t k = 0; k < K; k++)
{
MatrixType valA = A.buffer[i * K + k];
for (size_t j = 0; j < N; j++)
{
// C[i, j] += A[i, k] * B[k, j];
// M x N, M x K, K x N
C.buffer[i * N + j] += valA * B.buffer[k * N + j];
}
}
}
return C;
}