home *** CD-ROM | disk | FTP | other *** search
- /* ludecomp - LU decomposition and backsolving routines. */
- /* Taken from Numerical Recipes. */
- /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
- /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
- /* You may give out copies of this software; for conditions see the */
- /* file COPYING included with this distribution. */
-
- #include "xlisp.h"
- #include "osdef.h"
- #ifdef ANSI
- #include "xlsproto.h"
- #else
- #include "xlsfun.h"
- #endif ANSI
-
- int crludcmp(mat, n, indx, mode, d)
- Matrix mat;
- IVector indx;
- int n, mode;
- double *d;
- {
- int i, imax, j, k, singular = FALSE;
- double big, temp;
- Complex cdum, csum;
- double rdum, rsum;
- CMatrix cmat = (CMatrix) mat;
- RMatrix rmat = (RMatrix) mat;
- RVector vv;
-
- vv = rvector(n);
- *d = 1.0;
-
- /* set up the pivot permutation vector */
- for (i = 0; i < n; i++) indx[i] = i;
-
- /* get scaling information for implicit pivoting */
- for (i = 0; i < n; i++) {
- big = 0.0;
- for (j = 0; j < n; j++) {
- temp = (mode == RE) ? fabs(rmat[i][j]) : modulus(cmat[i][j]);
- if (temp > big) big = temp;
- }
- if (big == 0.0) {
- vv[i] = 1.0; /* no scaling for zero rows */
- singular = TRUE;
- }
- else vv[i] = 1.0 / big;
- }
-
- /* loop over columns for Crout's method */
- for (j = 0; j < n; j++) {
- for (i = 0; i < j; i++) {
- if (mode == RE) rsum = rmat[i][j];
- else csum = cmat[i][j];
-
- for (k = 0; k < i; k++)
- if (mode == RE) rsum -= rmat[i][k] * rmat[k][j];
- else csum = csub(csum, cmul(cmat[i][k], cmat[k][j]));
-
- if (mode == RE) rmat[i][j] = rsum;
- else cmat[i][j] = csum;
- }
- big = 0.0;
- for (i = j; i < n; i++) {
- if (mode == RE) rsum = rmat[i][j];
- else csum = cmat[i][j];
-
- for (k = 0; k < j; k++)
- if (mode == RE) rsum -= rmat[i][k] * rmat[k][j];
- else csum = csub(csum, cmul(cmat[i][k], cmat[k][j]));
-
- if (mode == RE) rmat[i][j] = rsum;
- else cmat[i][j] = csum;
-
- temp = vv[i] * ((mode == RE) ? fabs(rsum) : modulus(csum));
- if (temp >= big) { big = temp; imax = i; }
- }
-
- /* interchange rows if needed */
- if (j != imax) {
- for (k = 0; k < n; k++) {
- if (mode == RE) {
- rdum = rmat[imax][k];
- rmat[imax][k] = rmat[j][k];
- rmat[j][k] = rdum;
- }
- else {
- cdum = cmat[imax][k];
- cmat[imax][k] = cmat[j][k];
- cmat[j][k] = cdum;
- }
- }
- *d = -(*d);
- vv[imax] = vv[j];
- }
- indx[j] = imax;
-
- /* divide by the pivot element */
- temp = (mode == RE) ? fabs(rmat[j][j]) : modulus(cmat[j][j]);
- if (temp == 0.0) singular = TRUE;
- else if (j < n - 1) {
- if (mode == RE) {
- rdum = 1.0 / rmat[j][j];
- for (i = j + 1; i < n; i++) rmat[i][j] *= rdum;
- }
- else {
- cdum = cdiv(cart2complex(1.0, 0.0), cmat[j][j]);
- for (i = j + 1; i < n; i++) cmat[i][j] = cmul(cmat[i][j], cdum);
- }
- }
- }
- free_vector((Vector)vv);/* cast added JKL */
- return(singular);
- }
-
- int crlubksb(a, n, indx, b, mode)
- Matrix a;
- IVector indx;
- Vector b;
- int n, mode;
- {
- int i, ii, ip, j, singular = FALSE;
- CMatrix ca = (CMatrix) a;
- CVector cb = (CVector) b;
- RMatrix ra = (RMatrix) a;
- RVector rb = (RVector) b;
- double rsum;
- Complex csum;
-
- /* forward substitute using L part */
- for (i = 0, ii = -1; i < n; i++) {
- ip = indx[i];
- if (mode == RE) {
- rsum = rb[ip];
- rb[ip] = rb[i];
- }
- else {
- csum = cb[ip];
- cb[ip] = cb[i];
- }
- if (ii >= 0)
- for (j = ii; j <= i - 1; j++)
- if (mode == RE) rsum -= ra[i][j] * rb[j];
- else csum = csub(csum, cmul(ca[i][j], cb[j]));
- else {
- if (mode == RE) {
- if (rsum != 0.0) ii = i;
- }
- else if (csum.real != 0.0 || csum.imag != 0.0) ii = i;
- }
- if (mode == RE) rb[i] = rsum;
- else cb[i] = csum;
- }
-
- /* back substitute using the U part */
- for (i = n - 1; i >= 0; i--) {
- if (mode == RE) {
- rsum = rb[i];
- for (j = i + 1; j < n; j++) rsum -= ra[i][j] * rb[j];
- if (ra[i][i] == 0.0) {
- singular = TRUE;
- break;
- }
- else rb[i] = rsum / ra[i][i];
- }
- else {
- csum = cb[i];
- for (j = i + 1; j < n; j++) csum = csub(csum, cmul(ca[i][j], cb[j]));
- if (modulus(ca[i][i]) == 0.0) {
- singular = TRUE;
- break;
- }
- else cb[i] = cdiv(csum, ca[i][i]);
- }
- }
-
- return(singular);
- }
-
-