#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define MAXNOP 50 /*Max number of operations allowed */
struct m{
size_t row;
size_t col;
double *data;
};
struct m add(struct m *A, struct m *B, double n);
struct m multiply(struct m *A, struct m *B);
void f(double x);
void print_matrix(struct m *A);
void transpose(struct m *A);
double determinant(size_t n, struct m *A);
void scalar_product(double scalar, struct m *B);
void inverse(size_t n, struct m *A);
int main(int argc, char *argv[]){
struct m *matrix;
int id = 0; /* id of a matrix */
size_t ncol,nrow; /* No of columns of a matrix*/
ncol = nrow = 0;
int nop = 0; /*No of operators*/
int off = 0;
int i;
int n;
double *d;
int maxc
=argc
>2?atoi(argv
[2])*atoi(argv
[2]):100; /*define max dimension of a matrix */ char buf[maxc]; /*to store each lines of file */
char *p = buf;
char op[MAXNOP];
for (i=0; i < MAXNOP; i++)
op[i]='?';
FILE
*fp
= argc
> 1 ? fopen (argv
[1], "r") : stdin
;
if (!(matrix
= malloc(maxc
*sizeof *matrix
))) { return 1;
}
/*Read file line by line */
while (fgets (buf
, maxc
, fp
)){
if (nrow == 0){
/* allocate/validate max no. of matrix */
d
= matrix
[id
].
data = malloc(sizeof(double) * 10 * 10); }
/*check if line contains operator */
if ( (!isdigit(*buf
) && buf
[1] =='\n') || buf
[0] =='^') {
if (buf[0] =='^' && buf[1] == '-' && buf[2] =='1')
op[nop++] = 'i'; /* matrix inverse operation */
else
op[nop++] = *buf;
matrix[id].col = ncol;
matrix[id].row = nrow;
nrow = ncol = 0;
id++;
continue;
}
else /* read integers in a line into d */
{
while (sscanf (p
+ off
, "%lf%n", d
, &n
) == 1) { d++;
if(nrow == 0)
ncol++;
off += n;
}
nrow++;
off = 0;
}
} /*end of while fgets cycle */
/*Assign last matrix No of columns and rows */
matrix[id].col = ncol;
matrix[id].row = nrow;
/*Printing the matrices and operations */
for(i=0; i <= id; i++){
print_matrix(&matrix[i]);
if (op[i] == '*' || op[i] == '-' || op[i] =='+' || op[i] =='t' || op[i] =='T')
}
if(nop == 0){ /*Check if there are unary operations to perform*/
if(op[0] == '?'){
printf("The determinant is:\n"); f(determinant(matrix[0].row, &matrix[0]));
return 0;
}
}
if (nop == 1){
if(op[0] == 't' || op[0] == 'T'){
transpose(&matrix[0]);
print_matrix(&matrix[0]); /*Print the result */
return 0;
}
if(op[0] == 'i'){
if(matrix[0].row != matrix[0].col)
printf("Error: You can only calculate the inverse of square matrices\n"); inverse(matrix[0].row, &matrix[0]);
printf("The inverse matrix is:\n"); print_matrix(&matrix[0]);
return 0;
}
}
/*Transpose the matrices */
for(i=0; i < nop; i++){
if(op[i] == 't' || op[i] == 'T')
transpose(&matrix[0]);
}
for(i=0; i <= nop; i+=2)
{
if (op[i] == '+' && op[i+1] == '?'){
matrix[i+1] = add(&matrix[i],&matrix[i+1],+1);
break;
}
else if(op[i] == '*' && op[i+1] == '?'){
if (matrix[i].row == 1 && matrix[i].col == 1)
scalar_product(matrix[i].data[0], &matrix[i+1]); //Multiplication of Scalar per matrix
else{
matrix[i+1] = multiply(&matrix[i],&matrix[i+1]);
matrix[i+2] = multiply(&matrix[i+1],&matrix[i+2]);
}
break;
}
else if (op[i] == '-' && op[i+1] == '?'){
matrix[i+1] = add(&matrix[i],&matrix[i+1],-1);
break;
}
if(op[i] == '*' && op[i+1] == '*'){
if (matrix[i].row == 1 && matrix[i].col == 1)
scalar_product(matrix[i].data[0], &matrix[i+1]); //Multiplication of Scalar per matrix
else{
matrix[i+1] = multiply(&matrix[i],&matrix[i+1]);
matrix[i+2] = multiply(&matrix[i+1],&matrix[i+2]);
}
}
if(op[i] == '*' && op[i+1] == '+'){
if (matrix[i].row == 1 && matrix[i].col == 1)
scalar_product(matrix[i].data[0],&matrix[i+1]); //Multiplication of Scalar per matrix
else{
matrix[i+1] = multiply(&matrix[i],&matrix[i+1]);
matrix[i+2] = add(&matrix[i+1],&matrix[i+2],+1);
}
}
else if (op[i] == '+' && op[i+1] == '*'){
matrix[i+1] = multiply(&matrix[i],&matrix[i+2]);
matrix[i+2] = add(&matrix[i],&matrix[i+1],+1);
}
else if (op[i] == '-' && op[i+1] == '*'){
matrix[i+1] = multiply(&matrix[i],&matrix[i+2]);
matrix[i+2] = add(&matrix[i],&matrix[i+1],-1);
}
}
print_matrix(&matrix[id]); /*Print the result */
return 0;
}
struct m multiply(struct m *A, struct m *B)
{
size_t i, j, k;
struct m C;
C.
data = malloc(sizeof(double) * A
->row
* B
->col
);
C.row = A->row;
C.col = B->col;
for (i=0; i< C.row; i++)
for (j=0; j < C.col; j++)
C.data[i * C.col + j] = 0;
// Multiplying matrix A and B and storing in C.
for(i = 0; i < A->row; ++i)
for(j = 0; j < B->col; ++j)
for(k=0; k < A->col; ++k)
C.data[i * C.col + j] += A->data[i * A->col + k] * B->data[k * B->col + j];
return C;
}
struct m add(struct m *A, struct m *B, double n)
{
if ( (A->row != B->row) || (A->col != B->col) ){
printf("Error: You can't sum up matrix of different dimension\n"); }
size_t i, j;
struct m C;
C.
data = malloc(sizeof(double) * A
->row
* B
->col
); C.row = A->row;
C.col = A->col;
for (i=0; i< C.row; i++)
for (j=0; j < C.col; j++)
C.data[i * C.col + j] = A->data[i * A->col + j] + n *B->data[i * B->col + j];
return C;
}
void f(double x)
{
}
/*printing a Matrix*/
void print_matrix(struct m *A){
size_t i,j;
double *tmp = A->data;
for(i=0; i < A->row; i++){
for(j=0; j < A->col; j++){
f(*(tmp++));
}
}
}
void scalar_product(double scalar, struct m *B)
{
size_t i,j;
for(i=0; i < B->row; i++)
for(j=0; j < B->col; j++)
B->data[i * B->col + j] = scalar * B->data[i * B->col + j];
}
double determinant(size_t n, struct m *A)
{
size_t i,j,i_count,j_count, count=0;
double det = 0;
if(n < 1)
{
}
if(n==1) return A->data[0];
if(n==2) return (A->data[0]* A->data[1 * A->col + 1] - A->data[0 + 1] * A->data[1*A->col + 0]);
else{
struct m C;
C.row = A->row-1;
C.col = A->col-1;
C.
data = malloc(sizeof(double) * (A
->row
-1) * (A
->col
-1));
for(count=0; count < n; count++)
{
//Creating array of Minors
i_count = 0;
for(i=1; i<n; i++)
{
j_count=0;
for(j = 0; j < n; j++)
{
if(j == count)
continue; // don't copy the minor column element
C.data[i_count * C.col + j_count] = A->data[i * A->col + j];
j_count++;
}
i_count++;
}
det
+= pow(-1, count
) * A
->data
[0 + count
] * determinant
(n
-1,&C
);//Recursive call }
return det;
}
}
void transpose(struct m *A)
{
struct m C;
C.
data = malloc(sizeof(double) * A
->row
* A
->col
);
C.row = A->col;
C.col = A->row;
size_t i, j;
for (i = 0; i < C.row; i++)
for (j = 0; j < C.col; j++)
C.data[i * C.col + j] = A->data[j * A->col + i];
*A = C;
}
void inverse(size_t n, struct m *A) /*Calculate the inverse of A */
{
double Rdata[(n-1)*(n-1)]; // remaining data values
struct m R = { n-1, n-1, Rdata }; // matrix structure for them
for (count = 0; count < n*n; count++) // Create n*n Matrix of Minors
{
int row = count/n, col = count%n;
for (i_count = i = 0; i < n; i++)
if (i != row) // don't copy the current row
{
for (j_count = j = 0; j < n; j++)
if (j != col) // don't copy the current column
Rdata[i_count*R.col+j_count++] = A->data[i*A->col+j];
i_count++;
}
// transpose by swapping row and column
C.
data[col
*C.
col+row
] = pow(-1, row
&1 ^ col
&1) * determinant
(n
-1, &R
) / det
; }
}