| 1 | /* $Id$ $Revision$ */ | 
|---|
| 2 | /* vim:set shiftwidth=4 ts=8: */ | 
|---|
| 3 |  | 
|---|
| 4 | /************************************************************************* | 
|---|
| 5 | * Copyright (c) 2011 AT&T Intellectual Property | 
|---|
| 6 | * All rights reserved. This program and the accompanying materials | 
|---|
| 7 | * are made available under the terms of the Eclipse Public License v1.0 | 
|---|
| 8 | * which accompanies this distribution, and is available at | 
|---|
| 9 | * http://www.eclipse.org/legal/epl-v10.html | 
|---|
| 10 | * | 
|---|
| 11 | * Contributors: See CVS logs. Details at http://www.graphviz.org/ | 
|---|
| 12 | *************************************************************************/ | 
|---|
| 13 |  | 
|---|
| 14 | /* | 
|---|
| 15 | * This code was (mostly) written by Ken Turkowski, who said: | 
|---|
| 16 | * | 
|---|
| 17 | * Oh, that. I wrote it in college the first time. It's open source - I think I | 
|---|
| 18 | * posted it after seeing so many people solve equations by inverting matrices | 
|---|
| 19 | * by computing minors naïvely. | 
|---|
| 20 | * -Ken | 
|---|
| 21 | * | 
|---|
| 22 | * The views represented here are mine and are not necessarily shared by | 
|---|
| 23 | * my employer. | 
|---|
| 24 | Ken Turkowski			turk@apple.com | 
|---|
| 25 | Immersive Media Technologist 	http://www.worldserver.com/turk/ | 
|---|
| 26 | Apple Computer, Inc. | 
|---|
| 27 | 1 Infinite Loop, MS 302-3VR | 
|---|
| 28 | Cupertino, CA 95014 | 
|---|
| 29 | */ | 
|---|
| 30 |  | 
|---|
| 31 |  | 
|---|
| 32 |  | 
|---|
| 33 | /* This module solves linear equations in several variables (Ax = b) using | 
|---|
| 34 | * LU decomposition with partial pivoting and row equilibration.  Although | 
|---|
| 35 | * slightly more work than Gaussian elimination, it is faster for solving | 
|---|
| 36 | * several equations using the same coefficient matrix.  It is | 
|---|
| 37 | * particularly useful for matrix inversion, by sequentially solving the | 
|---|
| 38 | * equations with the columns of the unit matrix. | 
|---|
| 39 | * | 
|---|
| 40 | * lu_decompose() decomposes the coefficient matrix into the LU matrix, | 
|---|
| 41 | * and lu_solve() solves the series of matrix equations using the | 
|---|
| 42 | * previous LU decomposition. | 
|---|
| 43 | * | 
|---|
| 44 | *	Ken Turkowski (apple!turk) | 
|---|
| 45 | *	written 3/2/79, revised and enhanced 8/9/83. | 
|---|
| 46 | */ | 
|---|
| 47 |  | 
|---|
| 48 | #include <math.h> | 
|---|
| 49 | #include <neato.h> | 
|---|
| 50 |  | 
|---|
| 51 | static double *scales; | 
|---|
| 52 | static double **lu; | 
|---|
| 53 | static int *ps; | 
|---|
| 54 |  | 
|---|
| 55 | /* lu_decompose() decomposes the coefficient matrix A into upper and lower | 
|---|
| 56 | * triangular matrices, the composite being the LU matrix. | 
|---|
| 57 | * | 
|---|
| 58 | * The arguments are: | 
|---|
| 59 | * | 
|---|
| 60 | *	a - the (n x n) coefficient matrix | 
|---|
| 61 | *	n - the order of the matrix | 
|---|
| 62 | * | 
|---|
| 63 | *  1 is returned if the decomposition was successful, | 
|---|
| 64 | *  and 0 is returned if the coefficient matrix is singular. | 
|---|
| 65 | */ | 
|---|
| 66 |  | 
|---|
| 67 | int lu_decompose(double **a, int n) | 
|---|
| 68 | { | 
|---|
| 69 | register int i, j, k; | 
|---|
| 70 | int pivotindex = 0; | 
|---|
| 71 | double pivot, biggest, mult, tempf; | 
|---|
| 72 |  | 
|---|
| 73 | if (lu) | 
|---|
| 74 | free_array(lu); | 
|---|
| 75 | lu = new_array(n, n, 0.0); | 
|---|
| 76 | if (ps) | 
|---|
| 77 | free(ps); | 
|---|
| 78 | ps = N_NEW(n, int); | 
|---|
| 79 | if (scales) | 
|---|
| 80 | free(scales); | 
|---|
| 81 | scales = N_NEW(n, double); | 
|---|
| 82 |  | 
|---|
| 83 | for (i = 0; i < n; i++) {	/* For each row */ | 
|---|
| 84 | /* Find the largest element in each row for row equilibration */ | 
|---|
| 85 | biggest = 0.0; | 
|---|
| 86 | for (j = 0; j < n; j++) | 
|---|
| 87 | if (biggest < (tempf = fabs(lu[i][j] = a[i][j]))) | 
|---|
| 88 | biggest = tempf; | 
|---|
| 89 | if (biggest != 0.0) | 
|---|
| 90 | scales[i] = 1.0 / biggest; | 
|---|
| 91 | else { | 
|---|
| 92 | scales[i] = 0.0; | 
|---|
| 93 | return (0);		/* Zero row: singular matrix */ | 
|---|
| 94 | } | 
|---|
| 95 | ps[i] = i;		/* Initialize pivot sequence */ | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | for (k = 0; k < n - 1; k++) {	/* For each column */ | 
|---|
| 99 | /* Find the largest element in each column to pivot around */ | 
|---|
| 100 | biggest = 0.0; | 
|---|
| 101 | for (i = k; i < n; i++) { | 
|---|
| 102 | if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) { | 
|---|
| 103 | biggest = tempf; | 
|---|
| 104 | pivotindex = i; | 
|---|
| 105 | } | 
|---|
| 106 | } | 
|---|
| 107 | if (biggest == 0.0) | 
|---|
| 108 | return (0);		/* Zero column: singular matrix */ | 
|---|
| 109 | if (pivotindex != k) {	/* Update pivot sequence */ | 
|---|
| 110 | j = ps[k]; | 
|---|
| 111 | ps[k] = ps[pivotindex]; | 
|---|
| 112 | ps[pivotindex] = j; | 
|---|
| 113 | } | 
|---|
| 114 |  | 
|---|
| 115 | /* Pivot, eliminating an extra variable  each time */ | 
|---|
| 116 | pivot = lu[ps[k]][k]; | 
|---|
| 117 | for (i = k + 1; i < n; i++) { | 
|---|
| 118 | lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot; | 
|---|
| 119 | if (mult != 0.0) { | 
|---|
| 120 | for (j = k + 1; j < n; j++) | 
|---|
| 121 | lu[ps[i]][j] -= mult * lu[ps[k]][j]; | 
|---|
| 122 | } | 
|---|
| 123 | } | 
|---|
| 124 | } | 
|---|
| 125 |  | 
|---|
| 126 | if (lu[ps[n - 1]][n - 1] == 0.0) | 
|---|
| 127 | return (0);		/* Singular matrix */ | 
|---|
| 128 | return (1); | 
|---|
| 129 | } | 
|---|
| 130 |  | 
|---|
| 131 | /* lu_solve() solves the linear equation (Ax = b) after the matrix A has | 
|---|
| 132 | * been decomposed with lu_decompose() into the lower and upper triangular | 
|---|
| 133 | * matrices L and U. | 
|---|
| 134 | * | 
|---|
| 135 | * The arguments are: | 
|---|
| 136 | * | 
|---|
| 137 | *	x - the solution vector | 
|---|
| 138 | *	b - the constant vector | 
|---|
| 139 | *	n - the order of the equation | 
|---|
| 140 | */ | 
|---|
| 141 |  | 
|---|
| 142 | void lu_solve(double *x, double *b, int n) | 
|---|
| 143 | { | 
|---|
| 144 | register int i, j; | 
|---|
| 145 | double dot; | 
|---|
| 146 |  | 
|---|
| 147 | /* Vector reduction using U triangular matrix */ | 
|---|
| 148 | for (i = 0; i < n; i++) { | 
|---|
| 149 | dot = 0.0; | 
|---|
| 150 | for (j = 0; j < i; j++) | 
|---|
| 151 | dot += lu[ps[i]][j] * x[j]; | 
|---|
| 152 | x[i] = b[ps[i]] - dot; | 
|---|
| 153 | } | 
|---|
| 154 |  | 
|---|
| 155 | /* Back substitution, in L triangular matrix */ | 
|---|
| 156 | for (i = n - 1; i >= 0; i--) { | 
|---|
| 157 | dot = 0.0; | 
|---|
| 158 | for (j = i + 1; j < n; j++) | 
|---|
| 159 | dot += lu[ps[i]][j] * x[j]; | 
|---|
| 160 | x[i] = (x[i] - dot) / lu[ps[i]][i]; | 
|---|
| 161 | } | 
|---|
| 162 | } | 
|---|
| 163 |  | 
|---|