/* * From: jt@avidya.ifa.hawaii.edu * Subject: invert_c.c * Date: March 2, 2005 17:05:44 EST * To: wmwood-vasey@cfa.harvard.edu */ /* Matrix inversion routine */ /* 040509 Change MAXDEC from 1e8 to 1e10 */ /* 800902 First Fortran version */ /* 770902 First Forth version */ #include #include #define MAXSIZE 1000 #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define ABS(a) (((a) > 0) ? (a) : -(a)) #define MAXDEC 1e10 /* Maximum decrement in pivot value for singular */ invert(int n, double *a, double *det) { /* SUBROUTINE INVERT(N,A,RST,DET) Subroutine to invert a matrix, and compute the determinant. John Tonry, 9/2/80; transcribed to C 020904. INVERT's arguments: N - The dimension of the matrix A - The NxN matrix to be inverted. Upon successful inversion, A contains the inverse. A must be real*8 DET - The determinant of the matrix. DET is set to 0 for a singular matrix, and in that case, A contains garbage. return values are 0 -- normal return -2 -- matrix too large -1 -- singular matrix */ double save, pivot, onrow, cprev, cnow, decr; short int rst[MAXSIZE][2]; int i, j, k, l, mrank, isign, nrow, ncol; if(n > MAXSIZE) { fprintf(stderr, "Matrix size too big: %d > %d\n", n, MAXSIZE); return(-2); } mrank = 0; isign = 1; *det = 0.0; for(j=0; j= ABS(a[j+k*n])) continue; pivot = ABS(a[j+k*n]); nrow = j; ncol = k; } } pivot = a[nrow+ncol*n]; if(pivot == 0.0) { *det = 0; return(-1); } rst[ncol][0] = nrow; rst[ncol][1] = i; /* Swap pivot element onto the diagonal */ for(k=0; k MAXDEC) { *det = 0; return(-1); } } *det = *det + log(ABS(pivot)); if(pivot < 0) isign *= -1; mrank++; } /* Now untangle the mess */ for(j=0; j