Gauss algorithm finished

This commit is contained in:
madmaurice 2016-02-15 11:20:11 +01:00
parent 77abcfee85
commit 8ba4934750

130
gauss.c
View file

@ -1,82 +1,146 @@
#include <stdio.h> #include <stdio.h>
#include <math.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
typedef struct { #define EPS 1e-100
int ** data; #define ISZERO(e) (abs(e) < EPS)
int size;
} Matrix;
Matrix matCreate(int size) { /*** GLS ***/
int** data = malloc(sizeof(int*) * size); typedef struct {
for(unsigned int row = 0; row < size; row++) data[row] = malloc(sizeof(int)*size); float ** data;
return (Matrix){data,size}; float * rs;
int size;
} GLS;
GLS glsCreate(int size) {
float** data = malloc(sizeof(float*) * size);
for(unsigned int row = 0; row < size; row++) data[row] = malloc(sizeof(float)*size);
float* rs = malloc(sizeof(float) * size);
return (GLS){data,rs,size};
} }
void matSet(Matrix m, size_t row, size_t col, int v) { void glsSet(GLS m, size_t row, size_t col, float v) {
assert(row < m.size); assert(row < m.size);
assert(col < m.size); assert(col < m.size);
m.data[row][col] = v; m.data[row][col] = v;
} }
int matGet(Matrix m, size_t row, size_t col) { float glsGet(GLS m, size_t row, size_t col) {
assert(row < m.size); assert(row < m.size);
assert(col < m.size); assert(col < m.size);
return m.data[row][col]; return m.data[row][col];
} }
void matSwapRows(Matrix m, size_t row1, size_t row2) { float glsGetRS(GLS m, size_t row) {
assert(row < m.size);
return m.rs[row];
}
void glsSetRS(GLS m, size_t row, float value) {
assert(row < m.size);
m.rs[row] = value;
}
void glsSwapRows(GLS m, size_t row1, size_t row2) {
assert(row1 < m.size); assert(row1 < m.size);
assert(row2 < m.size); assert(row2 < m.size);
int* tmp = m.data[row1]; float* tmp = m.data[row1];
m.data[row1] = m.data[row2]; m.data[row1] = m.data[row2];
m.data[row2] = tmp; m.data[row2] = tmp;
float tmp2 = m.rs[row1];
m.rs[row1] = m.rs[row2];
m.rs[row2] = tmp2;
} }
void matPrint(Matrix m) { void glsTransform(GLS m, size_t row1, float fac1, size_t row2, float fac2) {
assert(row1 < m.size);
assert(row2 < m.size);
for(unsigned int col = 0; col < m.size; col++) {
glsSet(m,row1,col, fac1 * glsGet(m,row1,col) + fac2 * glsGet(m,row2,col) );
}
glsSetRS(m, row1, fac1 * glsGetRS(m, row1) + fac2 * glsGetRS(m,row2));
}
void glsPrint(GLS m) {
for(unsigned int row = 0; row < m.size; row++) { for(unsigned int row = 0; row < m.size; row++) {
for(unsigned int col = 0; col < m.size; col++) { for(unsigned int col = 0; col < m.size; col++) {
printf("%02d ", matGet(m,row,col)); printf("%3.1f ", glsGet(m,row,col));
} }
printf("\n"); printf("| %3.1f\n", m.rs[row]);
} }
} }
void matFree(Matrix m) { void glsFree(GLS m) {
for(unsigned int row = 0; row < m.size; row++) free(m.data[row]); for(unsigned int row = 0; row < m.size; row++) free(m.data[row]);
free(m.data); free(m.data);
free(m.rs);
} }
int reorder_mat(Matrix m, int rowCol) { /*** End GLS ***/
/*** Gauss ***/
int reorder_gls(GLS m, int rowCol) {
if(rowCol >= m.size) return 1; if(rowCol >= m.size) return 1;
if(matGet(m,rowCol,rowCol) != 0) return reorder_mat(m,rowCol+1); if(!ISZERO(glsGet(m, rowCol, rowCol))) return reorder_gls(m,rowCol+1);
for(int candidate = rowCol+1; candidate < m.size; candidate++) { for(int candidate = rowCol+1; candidate < m.size; candidate++) {
if(matGet(m,candidate, rowCol) != 0) { if(!ISZERO(glsGet(m,candidate, rowCol))) {
matSwapRows(m, rowCol, candidate); glsSwapRows(m, rowCol, candidate);
if(reorder_mat(m, rowCol+1)) return 1; if(reorder_gls(m, rowCol+1)) return 1;
matSwapRows(m, rowCol, candidate); glsSwapRows(m, rowCol, candidate);
} }
} }
return 0; return 0;
} }
int solve_gauss_rec(GLS m, int rowCol) {
if(rowCol >= m.size) return 1;
if( ISZERO(glsGet(m,rowCol,rowCol)) ) return 0;
for(size_t row = rowCol+1; row < m.size; row++) {
if(ISZERO(glsGet(m,row, rowCol))) continue;
glsTransform(m, row, glsGet(m,rowCol,rowCol), rowCol, - glsGet(m,row,rowCol) );
glsSet(m,row,rowCol, 0.0f);
}
if(!solve_gauss_rec(m, rowCol+1)) return 0;
for(size_t row = 0; row < rowCol; row--) {
glsTransform(m, row, glsGet(m,rowCol,rowCol), rowCol, - glsGet(m,row,rowCol) );
glsSet(m,row,rowCol, 0.0f);
}
glsTransform(m, rowCol, 1.0f / glsGet(m,rowCol,rowCol), rowCol, 0.0f );
glsSet(m, rowCol, rowCol, 1.0f);
return 1;
}
int solve(GLS m) {
if(!reorder_gls(m,0)) return 0;
if(!solve_gauss_rec(m,0)) return 0;
return 1;
}
int main( int argc, char *argv[] ) { int main( int argc, char *argv[] ) {
Matrix m = matCreate(2); GLS m = glsCreate(2);
matSet(m,0,0,0); glsSet(m,0,0,2); glsSet(m,0,1,3); glsSetRS(m,0, 13);
matSet(m,0,1,1); glsSet(m,1,0,1); glsSet(m,1,1,2); glsSetRS(m,1, 8);
matSet(m,1,0,1);
matSet(m,1,1,0);
matPrint(m); printf("Input: \n");
glsPrint(m);
if(!reorder_mat(m,0)) { if(solve(m)) {
printf("Failed\n"); printf("Output: \n");
glsPrint(m);
} else {
printf("Failed to solve. :(\n");
} }
matPrint(m);
return 0; return 0;
} }