/* * mtrxmath.c * * Jeff Craig * * Licensed under the GNU GPL */ #include "mtrxmath.h" /* Displays usage options */ void display_options(void) { fprintf(stderr,"Usage: mtrxmath [options] \n"); fputs("\t-h or --help \tDisplay this help.\n",stderr); fputs("\t-a or --add \tPerform matrix addition.\n",stderr); fputs("\t-s or --subtract \tPerform matrix subtraction.\n",stderr); fputs("\t-m or --multiply \tPerform matrix multiplication.\n",stderr); fputs("\t-D or --determinant\t Find the determinant of a Matrix.\n",stderr); fputs("\t-d or --divide \tPerform Matrix division.\n",stderr); fputs("\t-i or --invert \tFind the Inverse of a Matrix.\n\n",stderr); fputs("\tThe file1 and file2 parts are optional, and can be used to specify\n",stderr); fputs("\tfiles to load the matrices from. Must have one matrix per file\n",stderr); fputs("\tand you must load them in order \x28you can't load the second matrix\n",stderr); fputs("\tbut not the first\x29\n\n",stderr); } int main (int argc, char **argv) { int optch,indlopts=0, cmdopt = 0; static char optstring[] = "asmDdhir"; FILE* file = stdin; static struct option lopts[] = { { "help", 0, 0, 'h' }, { "add", 0, 0, 'a' }, { "subtract", 0, 0, 's' }, { "multiply", 0, 0, 'm' }, { "determinant", 0, 0, 'D' }, { "divide", 0, 0, 'd' }, { "invert", 0, 0, 'i' }, { "reduce", 0, 0, 'r' }, { 0, 0, 0, 0 } }; MATRIX_PTR foo, bar, final; float det; while ( (optch = getopt_long(argc,argv,optstring,lopts,&indlopts)) != EOF ) switch (optch) { case 'a' : cmdopt = ADD; break; case 's' : cmdopt = SUBTRACT; break; case 'm' : cmdopt = MULTIPLY; break; case 'd' : cmdopt = DIVIDE; break; case 'D' : cmdopt = DETERMINANT; break; case 'i' : cmdopt = INVERT; break; case 'r' : cmdopt = REDUCE; break; case 'h' : case '?' : display_options(); exit(1); } if(cmdopt == 0) { display_options(); exit(1); } if(argc < 3) { printf("First Matrix\n"); foo = collect_matrix(stdin); } else { if ((file = fopen(argv[2],"r")) == NULL) die("Error opening file"); foo = collect_matrix(file); fclose(file); } if (cmdopt==DETERMINANT) { det = determinant(foo); printf("Determinant = %f\n",det); exit(0); } if (cmdopt==INVERT) { final = inverse(foo); show_matrix(final); exit(0); } if (cmdopt==REDUCE) { int x,y; printf("Where do you want to cut the matrix?"); scanf("%i %i",&x,&y); final = reduce_matrix(x,y,foo); show_matrix(final); exit(0); } if(argc < 4) { printf("Second Matrix\n"); bar = collect_matrix(stdin); } else { if ((file = fopen(argv[3],"r")) == NULL) die("Error opening file"); bar = collect_matrix(file); fclose(file); } if(cmdopt==ADD) final = matrix_add(foo,bar); if(cmdopt==SUBTRACT) final = matrix_sub(foo,bar); if(cmdopt==MULTIPLY) final = matrix_multiply(foo,bar); if(cmdopt==DIVIDE) final = matrix_divide(foo,bar); if (final==NULL) die("No Solution"); show_matrix(final); return(0); } /* * This Code draws out a matrix of any size onto the console * limits the floating-point precision to 3 places past the * decimal */ void show_matrix(MATRIX_PTR show) { int index, index2; for(index=0;indexrows;index++) { for(index2=0;index2columns;index2++) { printf("%.3f\t",show->matrix[index][index2]); } printf("\n"); } } /* * This code takes keyboard input and places it into a matrix * I have gotten reports of problems with non-us character sets */ MATRIX_PTR collect_matrix(FILE* file) { MATRIX_PTR input; unsigned int rows, columns; int index, index2; if ( file == stdin ) printf("Rows: "); while((fscanf(file,"%u",&rows)!=1)) { fscanf(file,"%*s"); if (file==stdin) printf("Invalid input. Rows: "); } if (file == stdin) printf("Columns: "); while((fscanf(file,"%u",&columns)!=1)) { fscanf(file,"%*s"); if (file==stdin) printf("Invalid input. Columns: "); } input = alloc_matrix(rows, columns); for(index=0;indexrows;index++) { for(index2=0;index2columns;index2++) { if (file == stdin) printf("Value for %i,%i: ",index,index2); while(fscanf(file,"%f",&input->matrix[index][index2])!=1) { fscanf(file,"%*s"); if (file == stdin) printf("Invalid input. Value for %i, %i: ",index,index2); } } } return(input); } /* * This code allocates a MATRIX structure */ MATRIX_PTR alloc_matrix(unsigned int rows, unsigned int columns) { MATRIX_PTR m; int i; m = (MATRIX_PTR)malloc(sizeof(*m)); if (m == NULL) die("MALLOC error"); m->rows = rows; m->columns = columns; m->matrix = calloc(m->rows,sizeof(float*)); if(m->matrix == NULL) die("MALLOC error"); for(i=0;irows;i++) { m->matrix[i]=calloc(m->columns,sizeof(float)); if(m->matrix[i] == NULL) die("MALLOC error"); } return m; } /* * This function frees a MATRIX structure */ void free_matrix(MATRIX_PTR m) { if (m) { if (m->matrix) free(m->matrix); free(m); } } void die(const char* msg) { printf("%s\n", msg); exit(1); }