// Two functions // // void gaussjinv(float **a, int n) // // Get matrix A(nxn) and transform it into A^(-1). // Outputs error if A^(-1) doesn't exist // // void gaussj(float **a, int n, float **b, int m) // // Get matrix A(nxn) and transform it into A^(-1). // Parallelly right-hand vectors B from the equasion AX=B // are transformed into the set of solutions. // **b points to the matrix of m vectors B. // So that is the same as solving every system AX=B, but much faster #include #include #include #define NR_END 1 #define FREE_ARG char* #define SWAP(a,b) {temp=(a);(a)=(b);(b)=temp;} void runerror(char error_text[]) { fprintf(stderr,"Run-time error...\n"); fprintf(stderr,"%s\n",error_text); fprintf(stderr,"...now exiting to system...\n"); exit(1); } int *ivector(long nl, long nh) /* allocate an int vector with subscript range v[nl..nh] */ { int *v; v=(int *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(int))); if (!v) runerror("allocation failure in ivector()"); return v-nl+NR_END; } float **matrix(long nrl, long nrh, long ncl, long nch) /* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */ { long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; float **m; /* allocate pointers to rows */ m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*))); if (!m) runerror("allocation failure 1 in matrix()"); m += NR_END; m -= nrl; /* allocate rows and set pointers to them */ m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float))); if (!m[nrl]) runerror("allocation failure 2 in matrix()"); m[nrl] += NR_END; m[nrl] -= ncl; for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; /* return pointer to array of pointers to rows */ return m; } void free_ivector(int *v, long nl, long nh) /* free an int vector allocated with ivector() */ { free((FREE_ARG) (v+nl-NR_END)); } void free_matrix(float **m, long nrl, long nrh, long ncl, long nch) /* free a float matrix allocated by matrix() */ { free((FREE_ARG) (m[nrl]+ncl-NR_END)); free((FREE_ARG) (m+nrl-NR_END)); } void gaussjinv(float **a, int n) { // Taken from Nrecipes and slightly modified. // Get matrix A(nxn) and transform it into A^(-1). // Outputs error if A^(-1) doesn't exist int *indxc,*indxr,*ipiv; // indexr and indexc track column permutation int i,icol,irow,j,k,l,ll; float big,dum,pivinv,temp; indxc=ivector(1,n); indxr=ivector(1,n); ipiv=ivector(1,n); for (j=1;j<=n;j++) ipiv[j]=0; for (i=1;i<=n;i++) { big=0.0; // Looking for pivot for (j=1;j<=n;j++) if (ipiv[j] != 1) for (k=1;k<=n;k++) { if (ipiv[k] == 0) { if (fabs(a[j][k]) >= big) { big=fabs(a[j][k]); irow=j; icol=k; } } else if (ipiv[k] > 1) runerror("gaussj: Singular Matrix-1"); } ++(ipiv[icol]); // Pivot found - interchanging rows if (irow != icol) { for (l=1;l<=n;l++) SWAP(a[irow][l],a[icol][l]) } indxr[i]=irow; indxc[i]=icol; if (a[icol][icol] == 0.0) runerror("gaussj: Singular Matrix-2"); pivinv=1.0/a[icol][icol]; a[icol][icol]=1.0; for (l=1;l<=n;l++) a[icol][l] *= pivinv; for (ll=1;ll<=n;ll++) if (ll != icol) { dum=a[ll][icol]; a[ll][icol]=0.0; for (l=1;l<=n;l++) a[ll][l] -= a[icol][l]*dum; } } for (l=n;l>=1;l--) { if (indxr[l] != indxc[l]) for (k=1;k<=n;k++) SWAP(a[k][indxr[l]],a[k][indxc[l]]); } free_ivector(ipiv,1,n); free_ivector(indxr,1,n); free_ivector(indxc,1,n); } void gaussj(float **a, int n, float **b, int m) { int *indxc,*indxr,*ipiv; // indexr and indexc track column permutation int i,icol,irow,j,k,l,ll; float big,dum,pivinv,temp; indxc=ivector(1,n); indxr=ivector(1,n); ipiv=ivector(1,n); for (j=1;j<=n;j++) ipiv[j]=0; for (i=1;i<=n;i++) { big=0.0; // Looking for pivot for (j=1;j<=n;j++) if (ipiv[j] != 1) for (k=1;k<=n;k++) { if (ipiv[k] == 0) { if (fabs(a[j][k]) >= big) { big=fabs(a[j][k]); irow=j; icol=k; } } else if (ipiv[k] > 1) runerror("gaussj: Singular Matrix-1"); } ++(ipiv[icol]); // Pivot found - interchanging rows if (irow != icol) { for (l=1;l<=n;l++) SWAP(a[irow][l],a[icol][l]) for (l=1;l<=m;l++) SWAP(b[irow][l],b[icol][l]) } indxr[i]=irow; indxc[i]=icol; if (a[icol][icol] == 0.0) runerror("gaussj: Singular Matrix-2"); pivinv=1.0/a[icol][icol]; a[icol][icol]=1.0; for (l=1;l<=n;l++) a[icol][l] *= pivinv; for (l=1;l<=m;l++) b[icol][l] *= pivinv; for (ll=1;ll<=n;ll++) if (ll != icol) { dum=a[ll][icol]; a[ll][icol]=0.0; for (l=1;l<=n;l++) a[ll][l] -= a[icol][l]*dum; for (l=1;l<=m;l++) b[ll][l] -= b[icol][l]*dum; } } for (l=n;l>=1;l--) { if (indxr[l] != indxc[l]) for (k=1;k<=n;k++) SWAP(a[k][indxr[l]],a[k][indxc[l]]); } free_ivector(ipiv,1,n); free_ivector(indxr,1,n); free_ivector(indxc,1,n); } void main() { // TESTING gaussjinv float **mat; mat=matrix(1,2,1,2); // Standart 2x2 matrix mat[1][1]=1; mat[1][2]=0; mat[2][1]=1; mat[2][2]=1; printf("Got matrix: \n%f %f\n%f %f",mat[1][1],mat[1][2],mat[2][1],mat[2][2]); gaussjinv(mat,2); printf("\n\nTransformed it into: \n%f %f\n%f %f",mat[1][1],mat[1][2],mat[2][1],mat[2][2]); free_matrix(mat,1,2,1,2); }