/* qinv.c - Code file for some quick matrix inverse routines. * (C) Copyright 1999 by John Halleck * All Rights Reserved */ /* Version of September 8th, 1999 */ #include "errors.h" /* We use the package wide standard error codes. */ #include "vec.h" /* We make use of the vector routines. */ #include "mat.h" /* We make use of the matrix routines. */ /* #include "matdebug.h" */ /* DEBUG */ /* =============== Inverse without an attempt to pivot ====================== */ /* Non-pivoting inverse. Clearly not a general inverse */ static error invnp (int size, matrix result, matrix working) { /* Result should either be the identity matrix, or should be * the result of pivoting the identity matrix to match * whatever pivoting was done to the working array. */ error status; /* Place to capture status of routines we call */ int i, j; /* Indices for loops. (Yes, I used to program in ForTran) */ double *diag, dvalue; /* A diagonal element */ double *leading, lvalue; /* leading non-zero value on a row */ double *workrow, *resultrow; /* The row we are working on. */ double *worksub, *resultsub; /* The other rows we are clearing out. */ /* A stable way to invert a positive definite matrix * is to use elementary matrix transformations to reduce it * the identity, while using the same transformations to transform * the identity to the inverse. */ /* Oddly enough, this routine should be much cleaner in Pascal */ if (!result || !working) return ERRnil; /* Arrays must exist */ if (size<1) return ERRsize; /* with reasonable sizes */ if (result==working) return ERRsame; /* And can't be the same arrays. */ workrow = (double *) working; resultrow = (double *) result; diag = workrow; for (i=0; i currentmax) { currentmax = testmax; /* Max value so far */ rowofmax = rowoftest; resrowofmax = rowofres; /* Row (in each array) where we found the max values */ } } /* (The max value had better be greater than 0) */ if (currentmax == 0.0) return ERRnumeric; /* If the max value is not the current row, swap them. */ if (rowofmax != workrow) { /* swap */ if ((status = vecswp (size, workrow, rowofmax))) return status; if ((status = vecswp (size, resrow, resrowofmax))) return status; } workrow += size; resrow += size; } /* Return the non-pivoting inverse */ return invnp (size, result, working); }