/*
* mtrxmath.c
*
* Jeff Craig <luserjeff@linuxfreemail.com>
*
* Licensed under the GNU GPL
*/
#include "mtrxmath.h"
/* Displays usage options */
void display_options(void)
{
fprintf(stderr,"Usage: mtrxmath [options] <file1> <file2>\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;index<show->rows;index++) {
for(index2=0;index2<show->columns;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;index<input->rows;index++) {
for(index2=0;index2<input->columns;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;i<m->rows;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);
}
syntax highlighted by Code2HTML, v. 0.9.1