generated from freudenreichan/info2Praktikum-NeuronalesNetz
223 lines
9.0 KiB
C
223 lines
9.0 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "matrix.h"
|
|
|
|
Matrix createMatrix(unsigned int rows, unsigned int cols){
|
|
/*
|
|
unsigned int memory_depth = 0;
|
|
memory_depth = rows * cols; //Meine Speichertiefe ist die Anzahl meiner Spalten mal die Reihen
|
|
|
|
unsigned int memory_reservation = 0;
|
|
memory_reservation = memory_depth * sizeof(MatrixType); //Nimmt die Speichertiefe mal die größe der einzelnen Speicherinhalte (float)
|
|
|
|
Matrix.buffer = malloc(memory_reservation); //Reserviert den Speicher und gibt den Zeiger auf die erste Speicheradresse dem zeiger buffer (malloc "merkt" sich die Speichergröße an der adresse buffer)
|
|
*/
|
|
|
|
Matrix matrix = {0, 0, NULL}; //Matrix ist der Datentyp (im struct bestimmt). wir brauchen hier aber eine lokale variable (!NIX GLOBAL!) daher ist matrix eine Variable vom Typ Matrix.
|
|
//Leere Matrix als Ausgangszustand erstellen
|
|
|
|
// Prüfen, ob die Dimensionen gültig sind
|
|
if (rows == 0 || cols == 0) {
|
|
fprintf(stderr, "Error, invalid matrix dimensions...\n");
|
|
return matrix;
|
|
}
|
|
|
|
//Richtige Dimensionen speichern
|
|
matrix.rows = rows;
|
|
matrix.cols = cols;
|
|
matrix.buffer = malloc(rows * cols * sizeof(MatrixType)); //Reserviert den Speicher und gibt den Zeiger auf die erste Speicheradresse dem zeiger buffer (malloc "merkt" sich die Speichergröße an der adresse buffer)
|
|
|
|
if (matrix.buffer == NULL) {
|
|
fprintf(stderr, "Error, matrix could not be created...\n");
|
|
matrix.rows = 0;
|
|
matrix.cols = 0;
|
|
}
|
|
|
|
return matrix;
|
|
}
|
|
|
|
|
|
|
|
void clearMatrix(Matrix *matrix){ //*matrix greift auf die einträge im Struct Matrix zu
|
|
|
|
if (matrix == NULL) { //Wenn Matrix schon leer ist, mach nichts
|
|
return;
|
|
}
|
|
|
|
free(matrix->buffer); //Mit free wird die dynamische Speichergröße (die sich malloc gemerkt hat und mit der adresse von buffer verknüpft hat) wieder freigegeben
|
|
|
|
matrix->buffer = NULL; //matrix->buffer = NULL ist das gleiche wie (*matrix).buffer = NULL / Setzt den Zeiger auf 0
|
|
matrix->rows = 0; //Wir greifen auf einen zeiger in struct zu deswegen (*matrix)[zeiger auf] .buffer[variable im struct] !Klammer weil . stärker bindet als *!
|
|
matrix->cols = 0;
|
|
}
|
|
|
|
|
|
|
|
void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx){
|
|
|
|
if (rowIdx >= matrix.rows || colIdx >= matrix.cols) { //Gibt fehler bei falschen Idx werten aus / !Arraysyntax beachten, bei 5 rows ist im Array 0 bis 4 deviniert!
|
|
fprintf(stderr, "Error, the value could not be saved to the matrix...\n");
|
|
return;
|
|
}
|
|
|
|
unsigned int memorybuffer = 0;
|
|
unsigned int columnlength = matrix.cols;
|
|
|
|
memorybuffer = (rowIdx * columnlength)+colIdx; //Erklärung in "getMatrixAt"
|
|
matrix.buffer[memorybuffer] = value;
|
|
}
|
|
|
|
|
|
|
|
MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx){
|
|
|
|
if (rowIdx >= matrix.rows || colIdx >= matrix.cols) { //Gibt fehler bei falschen Idx werten aus / !Arraysyntax beachten, bei 5 rows ist im Array 0 bis 4 deviniert!
|
|
return UNDEFINED_MATRIX_VALUE;
|
|
}
|
|
|
|
unsigned int memorybuffer = 0; //variable für den Eintrag an der gesuchten stelle
|
|
unsigned int columnlength = matrix.cols; //maximale länge einer Zeile
|
|
|
|
memorybuffer = (rowIdx * columnlength)+colIdx; //Bsp. Matrix = 5 Spalten und 4 Zeilen. Gesucht ist Zeile 3, Spalte 2. In meinem Eindimensionalen Array ist das 12
|
|
//(2*4)+2 = 12 /Ich gehe erst die vollen Zeilen durch, dann die Position in der Zeile
|
|
//!Zeilen und Spalten beginnen bei 0 (Array syntax)!
|
|
return matrix.buffer[memorybuffer]; //Gibt den Matrixwert an der ausgerechnenten Stelle zurück / ![] für Arraywert!
|
|
}
|
|
|
|
|
|
|
|
Matrix add(const Matrix matrix1, const Matrix matrix2){
|
|
|
|
// Leere Ergebnismatrix für Fehlerfälle erstellen
|
|
Matrix summatrix = {0, 0, NULL};
|
|
|
|
|
|
// Prüfen, ob beide Matrizen Speicher besitzen
|
|
if(matrix1.buffer == NULL || matrix2.buffer == NULL){
|
|
fprintf(stderr, "Error, one or more matrices without memory...\n");
|
|
return summatrix;
|
|
}
|
|
|
|
|
|
// Prüfen, ob die Zeilenanzahl übereinstimmt, weil nur zwei Matrizen mit den exakt gleichen Dimmensionen addiert werden dürfen
|
|
if(matrix1.rows != matrix2.rows){
|
|
fprintf(stderr, "Error, incompatible matrix dimensions...\n");
|
|
return summatrix;
|
|
}
|
|
|
|
|
|
// Spaltenanzahl der Ergebnismatrix bestimmen
|
|
unsigned int resultcols = 0;
|
|
|
|
if(matrix1.cols == matrix2.cols){ //Kein Spaltenvektor, beide gleich groß
|
|
resultcols = matrix1.cols;
|
|
}
|
|
else if(matrix1.cols == 1){ //Matrix 1 ist Spaltenvektor -> Matrix 2 gibt Spaltengröße vor
|
|
resultcols = matrix2.cols;
|
|
}
|
|
else if(matrix2.cols == 1){ //Matrix 2 ist Spaltenvektor -> Matrix 1 gibt Spaltengröße vor
|
|
resultcols = matrix1.cols;
|
|
}
|
|
else{ //Kein Spaltenvektor, beide unterschiedlich groß -> Fehler
|
|
fprintf(stderr, "Error, incompatible matrix dimensions...\n");
|
|
return summatrix;
|
|
}
|
|
|
|
|
|
//Ergebnismatrix mit der richtigen Dimmension erstellen
|
|
summatrix = createMatrix(matrix1.rows, resultcols);
|
|
|
|
if(summatrix.buffer == NULL){ //Prüfen ob Matrix erfolgreich erstellt wurde
|
|
fprintf(stderr, "Error, memory allocation failed...\n");
|
|
return summatrix;
|
|
}
|
|
|
|
|
|
// Addition durchführen
|
|
for(unsigned int i = 0; i < summatrix.rows; i++){ //Zeilenanzahl erhöhen
|
|
for(unsigned int j = 0; j < summatrix.cols; j++){ //Spaltenanzahl erhöhen
|
|
|
|
MatrixType value1 = 0; //Platzhalterwerte bis bestimmt ist ob es ein Spaltenvektor ist oder nicht
|
|
MatrixType value2 = 0; //Platzhalterwerte bis bestimmt ist ob es ein Spaltenvektor ist oder nicht
|
|
|
|
// Wert aus Matrix 1 holen
|
|
if(matrix1.cols == 1){ //Für Spaltenvektor
|
|
value1 = getMatrixAt(matrix1, i, 0);
|
|
}
|
|
else{ //Für normale Matrix
|
|
value1 = getMatrixAt(matrix1, i, j);
|
|
}
|
|
|
|
// Wert aus Matrix 2 holen
|
|
if(matrix2.cols == 1){ //Für Spaltenvektor
|
|
value2 = getMatrixAt(matrix2, i, 0);
|
|
}
|
|
else{ //Für normale Matrix
|
|
value2 = getMatrixAt(matrix2, i, j);
|
|
}
|
|
|
|
// Werte addieren und speichern
|
|
summatrix.buffer[(i * summatrix.cols) + j] = value1 + value2; //Wert in neue matrix eintragen/!Erklärung von [(i* summatrix.cols) + j] in "getMatrixAt"!
|
|
}
|
|
}
|
|
|
|
return summatrix;
|
|
}
|
|
|
|
|
|
|
|
Matrix multiply(const Matrix matrix1, const Matrix matrix2){
|
|
|
|
//!wenn ich eine 3x4 mit einer 4x3 matrix multipliziere kommt eine 3x3 raus!
|
|
// 3x4 mit 5x3 ist mathematisch nicht möglich!
|
|
// A ⋅ B ist im Allgemeinen nicht dasselbe wie B ⋅ A -> Kein Tausch von A & B nötig wenn m nicht gleich groß ist (n x m) * (m x k)
|
|
|
|
// Leere Ergebnismatrix für Fehlerfälle erstellen
|
|
Matrix multmatrix = {0, 0, NULL};
|
|
|
|
// Prüfen, ob beide Matrizen Speicher besitzen
|
|
if(matrix1.buffer == NULL || matrix2.buffer == NULL){
|
|
fprintf(stderr, "Error, one or more matrices without memory...\n");
|
|
return multmatrix;
|
|
}
|
|
|
|
|
|
// Prüfen, ob Matrizen multipliziert werden dürfen
|
|
// (n x m) * (m x k) = (n x k) / Spalten der ersten Matrix == Zeilen der zweitne Matrix
|
|
if(matrix1.cols != matrix2.rows){ //Sind die beiden Ungleich, darf nicht gerechnet werden
|
|
fprintf(stderr, "Error, incompatible matrix dimensions...\n");
|
|
return multmatrix;
|
|
}
|
|
|
|
|
|
//Ergebnismatrix mit der richtigen Dimmension erstellen
|
|
multmatrix = createMatrix(matrix1.rows, matrix2.cols);
|
|
|
|
if(multmatrix.buffer == NULL){ //Prüfen ob Matrix erfolgreich erstellt wurde
|
|
fprintf(stderr, "Error, memory allocation failed...\n");
|
|
return multmatrix;
|
|
}
|
|
|
|
|
|
//Multiplikation durchführen
|
|
//Es ist immer: Ergebnismatrix [row,col] = Summe aller {matrix1[row1]*matrix2[col1]}
|
|
|
|
for(unsigned int i = 0; i < multmatrix.rows; i++){ //Zeilenanzahl erhöhen
|
|
for(unsigned int j = 0; j < multmatrix.cols; j++){ //Spaltenanzahl erhöhen
|
|
|
|
MatrixType summe = 0;
|
|
|
|
// Skalarprodukt aus Zeile und Spalte berechnen
|
|
for(unsigned int k = 0; k < matrix1.cols; k++){
|
|
summe = summe + (getMatrixAt(matrix1, i, k) * getMatrixAt(matrix2, k, j));
|
|
}
|
|
|
|
multmatrix.buffer[(i * multmatrix.cols) + j] = summe;
|
|
}
|
|
}
|
|
|
|
return multmatrix;
|
|
}
|