Compare commits

..
7 Commits
39 changed files with 175 additions and 451 deletions

No files matched your search

+60 -3
View File
@@ -1,4 +1,61 @@
mnist
runTests
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.exe
*.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
*.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
Binary file not shown.
+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.
@@ -5,40 +5,37 @@
#include "unity.h"
#include "imageInput.h"
static void prepareImageFile(const char *path, unsigned short int width, unsigned short int height, unsigned int short numberOfImages, unsigned char label)
{
FILE *file = fopen(path, "wb");
if (file != NULL)
if(file != NULL)
{
const char *fileTag = "__info2_image_file_format__";
GrayScalePixelType *buffer = (GrayScalePixelType *)calloc(numberOfImages * width * height, sizeof(GrayScalePixelType));
GrayScalePixelType *zeroBuffer = (GrayScalePixelType *)calloc(numberOfImages * width * height, sizeof(GrayScalePixelType));
if (buffer != NULL)
if(zeroBuffer != NULL)
{
for (int i = 0; i < width * height; i++)
{
buffer[i] = (GrayScalePixelType)i; // füllen des buffers mit Graustufen des Pixel für Test
}
fwrite(fileTag, 1, strlen(fileTag), file);
fwrite(fileTag, sizeof(fileTag[0]), strlen(fileTag), file);
fwrite(&numberOfImages, sizeof(numberOfImages), 1, file);
fwrite(&width, sizeof(width), 1, file);
fwrite(&height, sizeof(height), 1, file);
for (int i = 0; i < numberOfImages; i++)
for(int i = 0; i < numberOfImages; i++)
{
fwrite(buffer, sizeof(GrayScalePixelType), width * height, file);
fwrite(zeroBuffer, sizeof(GrayScalePixelType), width * height, file);
fwrite(&label, sizeof(unsigned char), 1, file);
}
free(buffer);
free(zeroBuffer);
}
fclose(file);
}
}
void test_readImagesReturnsCorrectNumberOfImages(void)
{
GrayScaleImageSeries *series = NULL;
@@ -95,8 +92,7 @@ void test_readImagesReturnsCorrectLabels(void)
TEST_ASSERT_NOT_NULL(series);
TEST_ASSERT_NOT_NULL(series->labels);
TEST_ASSERT_EQUAL_UINT16(2, series->count);
for (int i = 0; i < 2; i++)
{
for (int i = 0; i < 2; i++) {
TEST_ASSERT_EQUAL_UINT8(expectedLabel, series->labels[i]);
}
clearSeries(series);
@@ -114,7 +110,7 @@ void test_readImagesFailsOnWrongFileTag(void)
{
const char *path = "testFile.info2";
FILE *file = fopen(path, "w");
if (file != NULL)
if(file != NULL)
{
fprintf(file, "some_tag ");
fclose(file);
@@ -123,43 +119,18 @@ void test_readImagesFailsOnWrongFileTag(void)
remove(path);
}
// Test der Hilfsfunktionen
void test_read_GrayScale_Pixel(void)
{
GrayScaleImageSeries *series = NULL;
const char *path = "testFile.info2";
prepareImageFile(path, 8, 8, 1, 1);
series = readImages(path);
TEST_ASSERT_NOT_NULL(series);
TEST_ASSERT_NOT_NULL(series->images);
TEST_ASSERT_EQUAL_UINT16(1, series->count);
for (int i = 0; i < (8 * 8); i++)
{
TEST_ASSERT_EQUAL_UINT8((GrayScalePixelType)i, series->images->buffer[i]);
}
clearSeries(series);
remove(path);
}
void setUp(void)
{
void setUp(void) {
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
}
void tearDown(void)
{
void tearDown(void) {
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
}
int main()
{
UNITY_BEGIN();
printf("\n============================\nImage input tests\n============================\n");
RUN_TEST(test_readImagesReturnsCorrectNumberOfImages);
RUN_TEST(test_readImagesReturnsCorrectImageWidth);
@@ -167,7 +138,6 @@ int main()
RUN_TEST(test_readImagesReturnsCorrectLabels);
RUN_TEST(test_readImagesReturnsNullOnNotExistingPath);
RUN_TEST(test_readImagesFailsOnWrongFileTag);
RUN_TEST(test_read_GrayScale_Pixel);
return UNITY_END();
}
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)
{
}
-7
View File
@@ -7,13 +7,6 @@ typedef float MatrixType;
// TODO Matrixtyp definieren
typedef struct Matrix {
MatrixType *buffer;
unsigned int rows;
unsigned int cols;
} Matrix;
Matrix createMatrix(unsigned int rows, unsigned int cols);
void clearMatrix(Matrix *matrix);
+1 -1
View File
@@ -164,7 +164,7 @@ void test_setMatrixAtFailsOnIndicesOutOfRange(void)
Matrix matrixToTest = {.rows=2, .cols=3, .buffer=buffer};
setMatrixAt(-1, matrixToTest, 2, 3);
TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, matrixToTest.buffer, matrixToTest.cols * matrixToTest.rows);
TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, matrixToTest.buffer, sizeof(buffer)/sizeof(MatrixType));
}
void setUp(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.
@@ -5,49 +5,10 @@
#include "unity.h"
#include "neuralNetwork.h"
static void prepareNeuralNetworkFile(const char *path, const NeuralNetwork nn)
{
FILE *f = fopen(path, "wb");
if (!f) return;
const char *tag = "__info2_neural_network_file_format__";
fwrite(tag, 1, strlen(tag), f);
if (nn.numberOfLayers == 0) {
fclose(f);
return;
} // In localmodel Struktur Testdateu aufruf:
// Header --> Input Dim --> Output Dim
// i. Layer weights --> biases --> nächste Dim
int input = nn.layers[0].weights.cols;
int output = nn.layers[0].weights.rows;
fwrite(&input, sizeof(int), 1, f);
fwrite(&output, sizeof(int), 1, f);
for (int i = 0; i < nn.numberOfLayers; i++)
{
const Layer *layer = &nn.layers[i];
int out = layer->weights.rows;
int in = layer->weights.cols;
fwrite(layer->weights.buffer, sizeof(MatrixType), out * in, f);
fwrite(layer->biases.buffer, sizeof(MatrixType), out * 1, f);
if (i + 1 < nn.numberOfLayers)
{
int nextOut = nn.layers[i + 1].weights.rows;
fwrite(&nextOut, sizeof(int), 1, f);
}
}
fclose(f);
// TODO
}
void test_loadModelReturnsCorrectNumberOfLayers(void)
@@ -55,15 +16,15 @@ void test_loadModelReturnsCorrectNumberOfLayers(void)
const char *path = "some__nn_test_file.info2";
MatrixType buffer1[] = {1, 2, 3, 4, 5, 6};
MatrixType buffer2[] = {1, 2, 3, 4, 5, 6};
Matrix weights1 = {.buffer = buffer1, .rows = 3, .cols = 2};
Matrix weights2 = {.buffer = buffer2, .rows = 2, .cols = 3};
Matrix weights1 = {.buffer=buffer1, .rows=3, .cols=2};
Matrix weights2 = {.buffer=buffer2, .rows=2, .cols=3};
MatrixType buffer3[] = {1, 2, 3};
MatrixType buffer4[] = {1, 2};
Matrix biases1 = {.buffer = buffer3, .rows = 3, .cols = 1};
Matrix biases2 = {.buffer = buffer4, .rows = 2, .cols = 1};
Layer layers[] = {{.weights = weights1, .biases = biases1}, {.weights = weights2, .biases = biases2}};
Matrix biases1 = {.buffer=buffer3, .rows=3, .cols=1};
Matrix biases2 = {.buffer=buffer4, .rows=2, .cols=1};
Layer layers[] = {{.weights=weights1, .biases=biases1}, {.weights=weights2, .biases=biases2}};
NeuralNetwork expectedNet = {.layers = layers, .numberOfLayers = 2};
NeuralNetwork expectedNet = {.layers=layers, .numberOfLayers=2};
NeuralNetwork netUnderTest;
prepareNeuralNetworkFile(path, expectedNet);
@@ -79,12 +40,12 @@ void test_loadModelReturnsCorrectWeightDimensions(void)
{
const char *path = "some__nn_test_file.info2";
MatrixType weightBuffer[] = {1, 2, 3, 4, 5, 6};
Matrix weights = {.buffer = weightBuffer, .rows = 3, .cols = 2};
Matrix weights = {.buffer=weightBuffer, .rows=3, .cols=2};
MatrixType biasBuffer[] = {7, 8, 9};
Matrix biases = {.buffer = biasBuffer, .rows = 3, .cols = 1};
Layer layers[] = {{.weights = weights, .biases = biases}};
Matrix biases = {.buffer=biasBuffer, .rows=3, .cols=1};
Layer layers[] = {{.weights=weights, .biases=biases}};
NeuralNetwork expectedNet = {.layers = layers, .numberOfLayers = 1};
NeuralNetwork expectedNet = {.layers=layers, .numberOfLayers=1};
NeuralNetwork netUnderTest;
prepareNeuralNetworkFile(path, expectedNet);
@@ -102,12 +63,12 @@ void test_loadModelReturnsCorrectBiasDimensions(void)
{
const char *path = "some__nn_test_file.info2";
MatrixType weightBuffer[] = {1, 2, 3, 4, 5, 6};
Matrix weights = {.buffer = weightBuffer, .rows = 3, .cols = 2};
Matrix weights = {.buffer=weightBuffer, .rows=3, .cols=2};
MatrixType biasBuffer[] = {7, 8, 9};
Matrix biases = {.buffer = biasBuffer, .rows = 3, .cols = 1};
Layer layers[] = {{.weights = weights, .biases = biases}};
Matrix biases = {.buffer=biasBuffer, .rows=3, .cols=1};
Layer layers[] = {{.weights=weights, .biases=biases}};
NeuralNetwork expectedNet = {.layers = layers, .numberOfLayers = 1};
NeuralNetwork expectedNet = {.layers=layers, .numberOfLayers=1};
NeuralNetwork netUnderTest;
prepareNeuralNetworkFile(path, expectedNet);
@@ -125,12 +86,12 @@ void test_loadModelReturnsCorrectWeights(void)
{
const char *path = "some__nn_test_file.info2";
MatrixType weightBuffer[] = {1, 2, 3, 4, 5, 6};
Matrix weights = {.buffer = weightBuffer, .rows = 3, .cols = 2};
Matrix weights = {.buffer=weightBuffer, .rows=3, .cols=2};
MatrixType biasBuffer[] = {7, 8, 9};
Matrix biases = {.buffer = biasBuffer, .rows = 3, .cols = 1};
Layer layers[] = {{.weights = weights, .biases = biases}};
Matrix biases = {.buffer=biasBuffer, .rows=3, .cols=1};
Layer layers[] = {{.weights=weights, .biases=biases}};
NeuralNetwork expectedNet = {.layers = layers, .numberOfLayers = 1};
NeuralNetwork expectedNet = {.layers=layers, .numberOfLayers=1};
NeuralNetwork netUnderTest;
prepareNeuralNetworkFile(path, expectedNet);
@@ -150,12 +111,12 @@ void test_loadModelReturnsCorrectBiases(void)
{
const char *path = "some__nn_test_file.info2";
MatrixType weightBuffer[] = {1, 2, 3, 4, 5, 6};
Matrix weights = {.buffer = weightBuffer, .rows = 3, .cols = 2};
Matrix weights = {.buffer=weightBuffer, .rows=3, .cols=2};
MatrixType biasBuffer[] = {7, 8, 9};
Matrix biases = {.buffer = biasBuffer, .rows = 3, .cols = 1};
Layer layers[] = {{.weights = weights, .biases = biases}};
Matrix biases = {.buffer=biasBuffer, .rows=3, .cols=1};
Layer layers[] = {{.weights=weights, .biases=biases}};
NeuralNetwork expectedNet = {.layers = layers, .numberOfLayers = 1};
NeuralNetwork expectedNet = {.layers=layers, .numberOfLayers=1};
NeuralNetwork netUnderTest;
prepareNeuralNetworkFile(path, expectedNet);
@@ -177,7 +138,7 @@ void test_loadModelFailsOnWrongFileTag(void)
NeuralNetwork netUnderTest;
FILE *file = fopen(path, "wb");
if (file != NULL)
if(file != NULL)
{
const char *fileTag = "info2_neural_network_file_format";
@@ -198,12 +159,12 @@ void test_clearModelSetsMembersToNull(void)
{
const char *path = "some__nn_test_file.info2";
MatrixType weightBuffer[] = {1, 2, 3, 4, 5, 6};
Matrix weights = {.buffer = weightBuffer, .rows = 3, .cols = 2};
Matrix weights = {.buffer=weightBuffer, .rows=3, .cols=2};
MatrixType biasBuffer[] = {7, 8, 9};
Matrix biases = {.buffer = biasBuffer, .rows = 3, .cols = 1};
Layer layers[] = {{.weights = weights, .biases = biases}};
Matrix biases = {.buffer=biasBuffer, .rows=3, .cols=1};
Layer layers[] = {{.weights=weights, .biases=biases}};
NeuralNetwork expectedNet = {.layers = layers, .numberOfLayers = 1};
NeuralNetwork expectedNet = {.layers=layers, .numberOfLayers=1};
NeuralNetwork netUnderTest;
prepareNeuralNetworkFile(path, expectedNet);
@@ -220,7 +181,7 @@ void test_clearModelSetsMembersToNull(void)
static void someActivation(Matrix *matrix)
{
for (int i = 0; i < matrix->rows * matrix->cols; i++)
for(int i = 0; i < matrix->rows * matrix->cols; i++)
{
matrix->buffer[i] = fabs(matrix->buffer[i]);
}
@@ -231,23 +192,23 @@ void test_predictReturnsCorrectLabels(void)
const unsigned char expectedLabels[] = {4, 2};
GrayScalePixelType imageBuffer1[] = {10, 30, 25, 17};
GrayScalePixelType imageBuffer2[] = {20, 40, 10, 128};
GrayScaleImage inputImages[] = {{.buffer = imageBuffer1, .width = 2, .height = 2}, {.buffer = imageBuffer2, .width = 2, .height = 2}};
GrayScaleImage inputImages[] = {{.buffer=imageBuffer1, .width=2, .height=2}, {.buffer=imageBuffer2, .width=2, .height=2}};
MatrixType weightsBuffer1[] = {1, -2, 3, -4, 5, -6, 7, -8};
MatrixType weightsBuffer2[] = {-9, 10, 11, 12, 13, 14};
MatrixType weightsBuffer3[] = {-15, 16, 17, 18, -19, 20, 21, 22, 23, -24, 25, 26, 27, -28, -29};
Matrix weights1 = {.buffer = weightsBuffer1, .rows = 2, .cols = 4};
Matrix weights2 = {.buffer = weightsBuffer2, .rows = 3, .cols = 2};
Matrix weights3 = {.buffer = weightsBuffer3, .rows = 5, .cols = 3};
Matrix weights1 = {.buffer=weightsBuffer1, .rows=2, .cols=4};
Matrix weights2 = {.buffer=weightsBuffer2, .rows=3, .cols=2};
Matrix weights3 = {.buffer=weightsBuffer3, .rows=5, .cols=3};
MatrixType biasBuffer1[] = {200, 0};
MatrixType biasBuffer2[] = {0, -100, 0};
MatrixType biasBuffer3[] = {0, -1000, 0, 2000, 0};
Matrix biases1 = {.buffer = biasBuffer1, .rows = 2, .cols = 1};
Matrix biases2 = {.buffer = biasBuffer2, .rows = 3, .cols = 1};
Matrix biases3 = {.buffer = biasBuffer3, .rows = 5, .cols = 1};
Layer layers[] = {{.weights = weights1, .biases = biases1, .activation = someActivation},
{.weights = weights2, .biases = biases2, .activation = someActivation},
{.weights = weights3, .biases = biases3, .activation = someActivation}};
NeuralNetwork netUnderTest = {.layers = layers, .numberOfLayers = 3};
Matrix biases1 = {.buffer=biasBuffer1, .rows=2, .cols=1};
Matrix biases2 = {.buffer=biasBuffer2, .rows=3, .cols=1};
Matrix biases3 = {.buffer=biasBuffer3, .rows=5, .cols=1};
Layer layers[] = {{.weights=weights1, .biases=biases1, .activation=someActivation}, \
{.weights=weights2, .biases=biases2, .activation=someActivation}, \
{.weights=weights3, .biases=biases3, .activation=someActivation}};
NeuralNetwork netUnderTest = {.layers=layers, .numberOfLayers=3};
unsigned char *predictedLabels = predict(netUnderTest, inputImages, 2);
TEST_ASSERT_NOT_NULL(predictedLabels);
int n = (int)(sizeof(expectedLabels) / sizeof(expectedLabels[0]));
@@ -255,13 +216,11 @@ void test_predictReturnsCorrectLabels(void)
free(predictedLabels);
}
void setUp(void)
{
void setUp(void) {
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
}
void tearDown(void)
{
void tearDown(void) {
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
}
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.
-134
View File
@@ -1,134 +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__"
// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei
static int read_header(FILE *file, unsigned short *count, unsigned short *width, unsigned short *height)
{
size_t headerLEN = strlen(FILE_HEADER_STRING);
char buffer[BUFFER_SIZE];
if (headerLEN >= BUFFER_SIZE)
{
return 0;
}
if (fread(buffer, 1, headerLEN, file) != headerLEN)
{
return 0;
}
buffer[headerLEN] = '\0';
if (strcmp(buffer, FILE_HEADER_STRING) != 0)
{
return 0;
}
if (fread(count, sizeof(unsigned short), 1, file) != 1 || fread(width, sizeof(unsigned short), 1, file) != 1 ||
fread(height, sizeof(unsigned short), 1, file) != 1)
{
return 0;
}
return 1;
}
static int read_single_image(FILE *file, GrayScaleImage *image)
{
unsigned int number_of_pixel = image->width * image->height;
if (fread(image->buffer, sizeof(GrayScalePixelType), number_of_pixel, file) != number_of_pixel) // fehler beim lesen
{
return 0;
}
return 1;
}
// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen
GrayScaleImageSeries *readImages(const char *path)
{
FILE *file = fopen(path, "rb");
if (!file)
{
return 0;
}
unsigned short count, width, height;
if (!read_header(file, &count, &width, &height))
{
fclose(file);
return 0;
}
GrayScaleImageSeries *series = malloc(sizeof(GrayScaleImageSeries));
if (!series)
{
fclose(file);
return 0;
}
series->count = count;
series->images = malloc(count * sizeof(GrayScaleImage));
series->labels = malloc(count * sizeof(unsigned char));
if (!series->images || !series->labels)
{
clearSeries(series);
fclose(file);
return 0;
}
for (int i = 0; i < count; i++)
{
series->images[i].width = width;
series->images[i].height = height;
series->images[i].buffer = malloc(width * height * sizeof(GrayScalePixelType));
if (!series->images[i].buffer)
{
clearSeries(series);
fclose(file);
return 0;
}
if (!read_single_image(file, &series->images[i]))
{
clearSeries(series);
fclose(file);
return 0;
}
if (fread(&series->labels[i], 1, 1, file) != 1)
{
clearSeries(series);
fclose(file);
return 0;
}
}
fclose(file);
return series;
}
// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt
void clearSeries(GrayScaleImageSeries *series)
{
if (series)
{
for (int i = 0; i < series->count; i++)
{
free(series->images[i].buffer);
}
free(series->images);
free(series->labels);
free(series);
}
}
-178
View File
@@ -1,178 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
#include <stdio.h>
// TODO Matrix-Funktionen implementieren
Matrix createMatrix(unsigned int rows, unsigned int cols)
{
Matrix matrix;
if (rows == 0 || cols == 0)
{
matrix.rows = 0;
matrix.cols = 0;
matrix.buffer = NULL;
return matrix;
}
matrix.rows = rows;
matrix.cols = cols;
matrix.buffer = (MatrixType *)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(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
if (rowIdx >= matrix.rows || colIdx >= matrix.cols)
{
fprintf(stderr, "Fehler: Ungültiger Index (%u, %u) bei Matrixgröße %u x %u\n", rowIdx, colIdx, matrix.rows, matrix.cols);
return; // abbruch falls fehler
}
matrix.buffer[rowIdx * matrix.cols + colIdx] = value;
}
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
if (rowIdx >= matrix.rows || colIdx >= matrix.cols)
{
fprintf(stderr, "Fehler: Ungültiger Index (%u, %u) bei Matrixgröße %u x %u\n", rowIdx, colIdx, matrix.rows, matrix.cols);
return UNDEFINED_MATRIX_VALUE;
}
return matrix.buffer[rowIdx * matrix.cols + colIdx];
}
Matrix add(const Matrix matrix1, const Matrix matrix2)
{
if (matrix1.rows == matrix2.rows && matrix1.cols == matrix2.cols) // gleiche Dimension
{
Matrix result = createMatrix(matrix1.rows, matrix1.cols);
if (result.buffer == NULL)
{
fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n");
return result;
}
for (int i = 0; i < matrix1.rows; i++)
{
for (int j = 0; j < matrix1.cols; j++)
{
result.buffer[i * result.cols + j] = matrix1.buffer[i * matrix1.cols + j] + matrix2.buffer[i * matrix2.cols + j];
}
}
return result;
}
if (matrix1.rows == matrix2.rows && matrix2.cols == 1) // Matrix 2 hat eine Spalte
{
Matrix result = createMatrix(matrix1.rows, matrix1.cols);
if(result.buffer == NULL)
{
fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n");
return result;
}
for (int i = 0; i < matrix1.rows; i++)
{
for (int j = 0; j < matrix1.cols; j++)
{
result.buffer[i * result.cols + j] = matrix1.buffer[i * matrix1.cols + j] + matrix2.buffer[i];
}
}
return result;
}
if (matrix1.rows == matrix2.rows && matrix1.cols == 1) // Matrix 1 hat eine Spalte
{
Matrix result = createMatrix(matrix2.rows, matrix2.cols);
if(result.buffer == NULL)
{
fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n");
return result;
}
for (int i = 0; i < matrix2.rows; i++)
{
for (int j = 0; j < matrix2.cols; j++)
{
result.buffer[i * result.cols + j] = matrix1.buffer[i] + matrix2.buffer[i * matrix2.cols + j];
}
}
return result;
}
// passt nicht
fprintf(stderr, "Fehler: Matrizen haben unterschiedliche Größen (%u x %u) und (%u x %u)\n",
matrix1.rows, matrix1.cols, matrix2.rows, matrix2.cols);
Matrix empty = {NULL, 0, 0};
return empty;
}
Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{
if (matrix1.cols != matrix2.rows)
{
fprintf(stderr, "Fehler: Matrizen der Dimension (%u x %u) und (%u x %u) koennen nicht multipliziert werden\n",
matrix1.rows, matrix1.cols, matrix2.rows, matrix2.cols);
Matrix empty = {NULL, 0, 0};
return empty;
}
Matrix result = createMatrix(matrix1.rows, matrix2.cols);
if (result.buffer == NULL)
{
fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n");
return result;
}
for (int i = 0; i < matrix1.rows; i++)
{
for (int j = 0; j < matrix2.cols; j++)
{
MatrixType sum = 0.0;
for (int k = 0; k < matrix1.cols; k++)
{
sum += matrix1.buffer[i * matrix1.cols + k] * matrix2.buffer[k * matrix2.cols + j];
}
result.buffer[i * result.cols + j] = sum;
}
}
return result;
}