diff --git a/build.bat b/build.bat index cebd95d..4d9109d 100644 --- a/build.bat +++ b/build.bat @@ -1,3 +1,3 @@ @echo off -gcc -Wall -g -std=c99 %1.c -o %1.exe +gcc -Wall -g -lm -std=c99 main.c -o main.exe @echo on diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..2a4c4fa --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +gcc -Wall -g -std=c99 -lm main.c -o main diff --git a/main b/main new file mode 100644 index 0000000..45ce197 Binary files /dev/null and b/main differ diff --git a/main.c b/main.c index ab9b6ba..5f9c9d5 100644 --- a/main.c +++ b/main.c @@ -41,18 +41,20 @@ void flushStdin(void); bool load(const char* filename, Matrix* A, Vector* b, Vector* x); Vector* solve(Method method, Matrix* A, Vector* b, Vector* x, double e); +Vector* solveJacobi(Matrix* A, Vector* b, Vector* x, double e); +Vector* solveGaussSeidel(Matrix* A, Vector* b, Vector* x, double e); int readMatrixLine(FILE* file, double* matrixLine, int maxCols); int main(int argc, char* argv[]) { char filePath[MAX_FILE_PATH_LENGTH]; - if(argc >= 2) { - strncpy(filePath, argv[1], MAX_FILE_PATH_LENGTH); - } else { + if(argc >= 2) { // If arguments specified + strncpy(filePath, argv[1], MAX_FILE_PATH_LENGTH); // use first argument as filePath + } else { // Otherwise read from stdin puts("Please enter the path of the file you'd like to open"); int result = scanf("%" STR(MAX_FILE_PATH_LENGTH) "[^\n]", filePath); - if(result == EOF || result == 0 || filePath[0] == 0) { + if(result == EOF || result == 0 || filePath[0] == 0) { // If an error occured or no text has been entered -> exit return 0; } if(result != 1) { @@ -72,12 +74,12 @@ int main(int argc, char* argv[]) { if(load(filePath, matrix, b, x)) { // Debug outputs - //puts("Data successfully loaded\nMatrix A:"); - //printMatrix(matrix); - //puts("Vector b:"); - //printVector(b); - //puts("Vector x:"); - //printVector(x); + puts("Data successfully loaded\nMatrix A:"); + printMatrix(matrix); + puts("Vector b:"); + printVector(b); + puts("Vector x:"); + printVector(x); puts("Please enter the algorithm to use:\n\t0: Jacobi (default)\n\t1: Gauss-Seidel"); int algorithm; @@ -87,15 +89,16 @@ int main(int argc, char* argv[]) { if(algorithm == EOF) { goto end; } - if(algorithm == '0' || algorithm == '1') { - algorithm -= '0'; - break; - } if(algorithm == '\n' || algorithm == 0) { puts("Defaulting to Jacobi"); algorithm = 0; break; } + flushStdin(); + if(algorithm == '0' || algorithm == '1') { + algorithm -= '0'; + break; + } fputs("Please enter 0, 1 or leave empty to exit!\n", stderr); } @@ -107,15 +110,52 @@ int main(int argc, char* argv[]) { if(scan == EOF) { goto end; } + flushStdin(); if(scan == 1) { break; } - flushStdin(); fputs("Invalid input - please enter a valid floating point number!\n", stderr); } Vector* result = solve(algorithm, matrix, b, x, e); - free(result); + if(result == NULL) { + fputs("Failed to run the algorithm!\n", stderr); + returnCode = 100; + } else { + int input; + while(true) { + puts("Choose what to output:\n\t0: Only the final result (default)\n\t1: All the iteration steps"); + input = getchar(); + if(input == '\n') { + puts("Defaulting to final result"); + input = 0; + } else { + flushStdin(); + } + if(input == 0 || input == '\n' || input == '0') { + puts("Showing final result:"); + int i = 0; + while(result[++i].n != 0 && i < MAX_ITERATION_STEPS) + free(result[i-1].data); + printVector(&result[i-1]); + free(result[i-1].data); + break; + } + if(input == '1') { + puts("Showing all iterations:"); + for(int i = 0; i < MAX_ITERATION_STEPS; i++) { + printVector(&result[i]); + if(result[i].n == 0) { + break; + } + free(result[i].data); + } + break; + } + fputs("Please enter 0, 1 or leave empty!", stderr); + }; + free(result); + } break; } else { fputs("Failed to load data from file.\nEnter new file path or leave empty to exit.\n", stderr); @@ -253,21 +293,88 @@ void flushStdin(void) { } Vector* solve(Method method, Matrix* A, Vector* b, Vector* x, double e) { - Vector* vectors = malloc(sizeof(Vector) * (MAX_ITERATION_STEPS + 1)); + if(method == JACOBI) { + return solveJacobi(A, b, x, e); + } else { + return solveGaussSeidel(A, b, x, e); + } +} - // MAX_ITERATION_STEPS enthält die maximal zulässige Anzahl an Iterationsschritten (100) - // Die einzelnen Vektoren müssen noch mit initVector initialisiert werden +Vector* solveJacobi(Matrix* A, Vector* b, Vector* x, double e) { + Vector* history = malloc(sizeof(Vector) * (MAX_ITERATION_STEPS + 1)); + initVector(history, x->n); + memcpy(history[0].data, b->data, b->n * sizeof(double)); + double delta; + int i, j, steps = 1; + double value; + double* data; - // HIER kommt der Code hin ;) + do { + delta = 0.; - // on success - // Sei x die Anzahl der durchgeführten Iterationschritte. Dann setzt vectors[x+1].n = 0. Damit weiß das folgende Programm wie viele Schritte getätigt wurden. - return vectors; + initVector(&history[steps], x->n); + data = history[steps].data; - // on failure - free(vectors); - return NULL; + for(i = 0; i < x->n; i++) { + value = b->data[i]; + for(j = 0; j < x->n; j++) { + if(i != j) + value -= history[steps-1].data[i] * A->data[i][j]; + } + data[i] = value / A->data[i][i]; + + delta = fmax(delta, fabs(data[i] - history[steps - 1].data[i])); + } + + steps++; + } while(delta > e && steps < MAX_ITERATION_STEPS); + + if(steps < MAX_ITERATION_STEPS) { + history[steps].n = 0; + } + + return history; +} + +Vector* solveGaussSeidel(Matrix* A, Vector* b, Vector* x, double e) { + Vector* history = malloc(sizeof(Vector) * (MAX_ITERATION_STEPS + 1)); + + initVector(history, x->n); + memcpy(history[0].data, b->data, x->n * sizeof(double)); + + double delta; + int i, k, steps = 1; + double* data; + double value; + + do { + delta = 0.; + + initVector(&history[steps], x->n); + data = history[steps].data; + + for(k = 0; k < x->n; k++) { + value = b->data[k]; + for(i = 0; i < k; i++) { + value -= A->data[k][i] * data[i]; + } + for(i = k + 1; i < x->n; i++) { + value -= A->data[k][i] * history[steps - 1].data[i]; + } + data[k] = value / A->data[k][k]; + + delta = fmax(delta, fabs(data[k] - history[steps - 1].data[k])); + } + + steps++; + } while(delta > e && steps < MAX_ITERATION_STEPS); + + if(steps < MAX_ITERATION_STEPS) { + history[steps].n = 0; + } + + return history; } inline Matrix* createMatrix(void) { @@ -292,7 +399,7 @@ inline void freeMatrix(Matrix* matrix) { void printMatrix(Matrix* matrix) { for(int i = 0; i < matrix->n; i++) { for(int j = 0; j < matrix->n; j++) { - printf("%lf, ", matrix->data[i][j]); + printf("%le, ", matrix->data[i][j]); } puts(""); } @@ -316,7 +423,7 @@ inline void freeVector(Vector* vector) { void printVector(Vector* vector) { for(int i = 0; i < vector->n; i++) { - printf("%lf, ", vector->data[i]); + printf("%le, ", vector->data[i]); } puts(""); }