Graphviz  2.29.20120524.0446
lib/neatogen/lu.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 /*
00015  * This code was (mostly) written by Ken Turkowski, who said:
00016  *
00017  * Oh, that. I wrote it in college the first time. It's open source - I think I
00018  * posted it after seeing so many people solve equations by inverting matrices
00019  * by computing minors naïvely.
00020  * -Ken
00021  *
00022  * The views represented here are mine and are not necessarily shared by
00023  * my employer.
00024         Ken Turkowski                   turk@apple.com
00025         Immersive Media Technologist    http://www.worldserver.com/turk/
00026         Apple Computer, Inc.
00027         1 Infinite Loop, MS 302-3VR
00028         Cupertino, CA 95014
00029  */
00030 
00031 
00032 
00033 /* This module solves linear equations in several variables (Ax = b) using
00034  * LU decomposition with partial pivoting and row equilibration.  Although
00035  * slightly more work than Gaussian elimination, it is faster for solving
00036  * several equations using the same coefficient matrix.  It is
00037  * particularly useful for matrix inversion, by sequentially solving the
00038  * equations with the columns of the unit matrix.
00039  *
00040  * lu_decompose() decomposes the coefficient matrix into the LU matrix,
00041  * and lu_solve() solves the series of matrix equations using the
00042  * previous LU decomposition.
00043  *
00044  *      Ken Turkowski (apple!turk)
00045  *      written 3/2/79, revised and enhanced 8/9/83.
00046  */
00047 
00048 #include <math.h>
00049 #include <neato.h>
00050 
00051 static double *scales;
00052 static double **lu;
00053 static int *ps;
00054 
00055 /* lu_decompose() decomposes the coefficient matrix A into upper and lower
00056  * triangular matrices, the composite being the LU matrix.
00057  *
00058  * The arguments are:
00059  *
00060  *      a - the (n x n) coefficient matrix
00061  *      n - the order of the matrix
00062  *
00063  *  1 is returned if the decomposition was successful,
00064  *  and 0 is returned if the coefficient matrix is singular.
00065  */
00066 
00067 int lu_decompose(double **a, int n)
00068 {
00069     register int i, j, k;
00070     int pivotindex = 0;
00071     double pivot, biggest, mult, tempf;
00072 
00073     if (lu)
00074         free_array(lu);
00075     lu = new_array(n, n, 0.0);
00076     if (ps)
00077         free(ps);
00078     ps = N_NEW(n, int);
00079     if (scales)
00080         free(scales);
00081     scales = N_NEW(n, double);
00082 
00083     for (i = 0; i < n; i++) {   /* For each row */
00084         /* Find the largest element in each row for row equilibration */
00085         biggest = 0.0;
00086         for (j = 0; j < n; j++)
00087             if (biggest < (tempf = fabs(lu[i][j] = a[i][j])))
00088                 biggest = tempf;
00089         if (biggest != 0.0)
00090             scales[i] = 1.0 / biggest;
00091         else {
00092             scales[i] = 0.0;
00093             return (0);         /* Zero row: singular matrix */
00094         }
00095         ps[i] = i;              /* Initialize pivot sequence */
00096     }
00097 
00098     for (k = 0; k < n - 1; k++) {       /* For each column */
00099         /* Find the largest element in each column to pivot around */
00100         biggest = 0.0;
00101         for (i = k; i < n; i++) {
00102             if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
00103                 biggest = tempf;
00104                 pivotindex = i;
00105             }
00106         }
00107         if (biggest == 0.0)
00108             return (0);         /* Zero column: singular matrix */
00109         if (pivotindex != k) {  /* Update pivot sequence */
00110             j = ps[k];
00111             ps[k] = ps[pivotindex];
00112             ps[pivotindex] = j;
00113         }
00114 
00115         /* Pivot, eliminating an extra variable  each time */
00116         pivot = lu[ps[k]][k];
00117         for (i = k + 1; i < n; i++) {
00118             lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
00119             if (mult != 0.0) {
00120                 for (j = k + 1; j < n; j++)
00121                     lu[ps[i]][j] -= mult * lu[ps[k]][j];
00122             }
00123         }
00124     }
00125 
00126     if (lu[ps[n - 1]][n - 1] == 0.0)
00127         return (0);             /* Singular matrix */
00128     return (1);
00129 }
00130 
00131 /* lu_solve() solves the linear equation (Ax = b) after the matrix A has
00132  * been decomposed with lu_decompose() into the lower and upper triangular
00133  * matrices L and U.
00134  *
00135  * The arguments are:
00136  *
00137  *      x - the solution vector
00138  *      b - the constant vector
00139  *      n - the order of the equation
00140 */
00141 
00142 void lu_solve(double *x, double *b, int n)
00143 {
00144     register int i, j;
00145     double dot;
00146 
00147     /* Vector reduction using U triangular matrix */
00148     for (i = 0; i < n; i++) {
00149         dot = 0.0;
00150         for (j = 0; j < i; j++)
00151             dot += lu[ps[i]][j] * x[j];
00152         x[i] = b[ps[i]] - dot;
00153     }
00154 
00155     /* Back substitution, in L triangular matrix */
00156     for (i = n - 1; i >= 0; i--) {
00157         dot = 0.0;
00158         for (j = i + 1; j < n; j++)
00159             dot += lu[ps[i]][j] * x[j];
00160         x[i] = (x[i] - dot) / lu[ps[i]][i];
00161     }
00162 }