#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define Z 8
float** request(rows,cols)
{
float **matrix;
int i;
matrix=malloc(rows*sizeof(float*));
for (i=0;i<rows;i++)
matrix[i]=malloc(cols*sizeof(float));
return matrix;
}
void libera(float **pointer, int sizei)
{
int i;
for (i=0;i<sizei;i++)
free(pointer[i]);
free(pointer);
}
void pinta(float **A, int rows, int cols, int decimal)
{
int i,j;
for (i=0;i<rows;i++)
{
for (j=0;j<cols;j++)
{
if (decimal)
printf("%3.2f ",A[i][j]);
else
printf("%3.0f ",A[i][j]);
}
printf("\n");
}
printf("---------------------------------------------------\n");
}
/* See pg 106 Kernighan & Ritchie (Prentice Hall) */
void swap(float *px, float *py)
{
float tmp;
tmp=*px;
*px=*py;
*py=tmp;
}
float** eye(int order)
{
int l,m;
float **I;
I=request(order,order);
for (l=0;l<order;l++)
for (m=0;m<order;m++)
I[l][m]=0;
for (l=0;l<order;l++)
I[l][l]=1;
return I;
}
/* Gauss-Jordan */
/* http://www.cs.caltech.edu/courses/cs171/c2-1.pdf */
/* Original method solves Ax=B and B is not necessarily the Identity as here is */
/* float** inverse(float** A, int n, float** B, int m) */
float** inverse(float** input, int n)
{
float **b,**A;
int i,icol,irow,j,k,l,ll,*indxc,*indxr,*ipiv,m=n;
float big,dum,pivinv;
A=request(n,n);
for (i=0;i<n;i++)
for (j=0;j<n;j++)
A[i][j]=input[i][j];
b=eye(m);
indxc=malloc(n*sizeof(int));
indxr=malloc(n*sizeof(int));
ipiv=malloc(n*sizeof(int));
for (j=0;j<n;j++)
ipiv[j]=0;
for (i=0;i<n;i++)
{
big=0;
for (j=0;j<n;j++)
{
if (ipiv[j]!=1)
{
for (k=0;k<n;k++)
{
if (ipiv[k]==0)
{
if (fabs(A[j][k])>=big)
{
big=fabs(A[j][k]);
irow=j;
icol=k;
}
}
}
}
}
++(ipiv[icol]);
if (irow!=icol)
{
for (l=0;l<n;l++)
swap(&A[irow][l],&A[icol][l]);
for (l=0;l<m;l++)
swap(&b[irow][1],&b[icol][l]);
}
indxr[i]=irow;
indxc[i]=icol;
if (A[icol][icol]==0)
printf("Error: singular matrix (result will be wrong) \n");
else
pivinv=1/A[icol][icol];
A[icol][icol]=1;
for (l=0;l<n;l++)
{
A[icol][l]=A[icol][l]*pivinv;
b[icol][l]=b[icol][l]*pivinv;
}
for (ll=0;ll<n;ll++)
{
if (ll!=icol)
{
dum=A[ll][icol];
A[ll][icol]=0;
for (l=0;l<n;l++)
{
A[ll][l]=A[ll][l]-(A[icol][l]*dum);
b[ll][l]=b[ll][l]-(b[icol][l]*dum);
}
}
}
}
for (l=n-1;l>=0;l--)
{
if (indxr[l]!=indxc[l])
{
for (k=0;k<n;k++)
swap(&A[k][indxr[l]],&A[k][indxc[l]]);
}
}
free(indxc);
free(indxr);
free(ipiv);
libera(b,n);
return A;
}
float** scalar_division(float **matrix, int rows, int cols, float scalar)
{
float **result;
int i,j;
result=request(rows,cols);
for (i=0;i<rows;i++)
for (j=0;j<cols;j++)
result[i][j]=matrix[i][j]/scalar;
return result;
}
float** scalar_product(float **matrix, int rows, int cols, float scalar)
{
float **result;
int i,j;
result=request(rows,cols);
for (i=0;i<rows;i++)
for (j=0;j<cols;j++)
result[i][j]=matrix[i][j]*scalar;
return result;
}
float** dot_product(float **A, float **B,int rows, int cols)
{
int i,j;
float **dot_product;
dot_product=request(rows,cols);
for (i=0;i<rows;i++)
for (j=0;j<cols;j++)
dot_product[i][j]=A[i][j]*B[i][j];
return dot_product;
}
float** matrix_product(float **A, float **B,int Arows, int Acols, int Brows, int Bcols)
{
float **product,sumatorio;
int i,j,l;
if ((Arows==Bcols)&&(Acols==Brows))
{
product=request(Arows,Arows);
for (i=0;i<Arows;i++)
for (j=0;j<Arows;j++)
{
sumatorio=0;
for (l=0;l<Acols;l++)
sumatorio=sumatorio+(A[i][l]*B[l][j]);
product[i][j]=sumatorio;
}
return product;
}
else
return NULL;
}
int main()
{
float source[Z][Z]={
{157,157,159,154,158,154,155,158},{158,158,156,155,157,158,155,159},
{160,157,156,153,156,171,156,155},{154,158,156,155,154,160,159,155},
{151,160,157,156,156,155,155,159},{158,159,155,156,154,171,157,155},
{153,155,158,157,155,157,153,156},{159,158,154,157,155,156,155,153}};
float **A,**B,**C,**D,**I,**iA;
int i,j,z=Z;
A=request(z,z);
for (i=0;i<z;i++)
for (j=0;j<z;j++)
A[i][j]=source[i][j];
printf("A:\n");
pinta(A,z,z,0);
B=scalar_division(A,z,z,10);
printf("B=A/10\n");
pinta(B,z,z,1);
C=dot_product(B,B,z,z);
printf("C = B .x B :\n");
pinta(C,z,z,1);
D=matrix_product(A,B,z,z,z,z);
printf("D = A x B :\n");
pinta(D,z,z,1);
printf("Inv(A): \n");
iA=inverse(A,z);
pinta(iA,z,z,1);
printf("I = Inv(A) x A \n");
I=matrix_product(iA,A,z,z,z,z);
pinta(I,z,z,0);
libera(A,z);
libera(B,z);
libera(C,z);
libera(D,z);
libera(I,z);
}