|
Graphviz
2.29.20120524.0446
|
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 }
1.7.5