|
Blender
V2.59
|
00001 00005 /* 00006 00007 * 00008 * Template Numerical Toolkit (TNT): Linear Algebra Module 00009 * 00010 * Mathematical and Computational Sciences Division 00011 * National Institute of Technology, 00012 * Gaithersburg, MD USA 00013 * 00014 * 00015 * This software was developed at the National Institute of Standards and 00016 * Technology (NIST) by employees of the Federal Government in the course 00017 * of their official duties. Pursuant to title 17 Section 105 of the 00018 * United States Code, this software is not subject to copyright protection 00019 * and is in the public domain. The Template Numerical Toolkit (TNT) is 00020 * an experimental system. NIST assumes no responsibility whatsoever for 00021 * its use by other parties, and makes no guarantees, expressed or implied, 00022 * about its quality, reliability, or any other characteristic. 00023 * 00024 * BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE 00025 * see http://math.nist.gov/tnt for latest updates. 00026 * 00027 */ 00028 00029 00030 00031 #ifndef LU_H 00032 #define LU_H 00033 00034 // Solve system of linear equations Ax = b. 00035 // 00036 // Typical usage: 00037 // 00038 // Matrix(double) A; 00039 // Vector(Subscript) ipiv; 00040 // Vector(double) b; 00041 // 00042 // 1) LU_Factor(A,ipiv); 00043 // 2) LU_Solve(A,ipiv,b); 00044 // 00045 // Now b has the solution x. Note that both A and b 00046 // are overwritten. If these values need to be preserved, 00047 // one can make temporary copies, as in 00048 // 00049 // O) Matrix(double) T = A; 00050 // 1) LU_Factor(T,ipiv); 00051 // 1a) Vector(double) x=b; 00052 // 2) LU_Solve(T,ipiv,x); 00053 // 00054 // See details below. 00055 // 00056 00057 00058 // for fabs() 00059 // 00060 #include <cmath> 00061 00062 // right-looking LU factorization algorithm (unblocked) 00063 // 00064 // Factors matrix A into lower and upper triangular matrices 00065 // (L and U respectively) in solving the linear equation Ax=b. 00066 // 00067 // 00068 // Args: 00069 // 00070 // A (input/output) Matrix(1:n, 1:n) In input, matrix to be 00071 // factored. On output, overwritten with lower and 00072 // upper triangular factors. 00073 // 00074 // indx (output) Vector(1:n) Pivot vector. Describes how 00075 // the rows of A were reordered to increase 00076 // numerical stability. 00077 // 00078 // Return value: 00079 // 00080 // int (0 if successful, 1 otherwise) 00081 // 00082 // 00083 00084 00085 namespace TNT 00086 { 00087 00088 template <class MaTRiX, class VecToRSubscript> 00089 int LU_factor( MaTRiX &A, VecToRSubscript &indx) 00090 { 00091 assert(A.lbound() == 1); // currently for 1-offset 00092 assert(indx.lbound() == 1); // vectors and matrices 00093 00094 Subscript M = A.num_rows(); 00095 Subscript N = A.num_cols(); 00096 00097 if (M == 0 || N==0) return 0; 00098 if (indx.dim() != M) 00099 indx.newsize(M); 00100 00101 Subscript i=0,j=0,k=0; 00102 Subscript jp=0; 00103 00104 typename MaTRiX::element_type t; 00105 00106 Subscript minMN = (M < N ? M : N) ; // min(M,N); 00107 00108 for (j=1; j<= minMN; j++) 00109 { 00110 00111 // find pivot in column j and test for singularity. 00112 00113 jp = j; 00114 t = fabs(A(j,j)); 00115 for (i=j+1; i<=M; i++) 00116 if ( fabs(A(i,j)) > t) 00117 { 00118 jp = i; 00119 t = fabs(A(i,j)); 00120 } 00121 00122 indx(j) = jp; 00123 00124 // jp now has the index of maximum element 00125 // of column j, below the diagonal 00126 00127 if ( A(jp,j) == 0 ) 00128 return 1; // factorization failed because of zero pivot 00129 00130 00131 if (jp != j) // swap rows j and jp 00132 for (k=1; k<=N; k++) 00133 { 00134 t = A(j,k); 00135 A(j,k) = A(jp,k); 00136 A(jp,k) =t; 00137 } 00138 00139 if (j<M) // compute elements j+1:M of jth column 00140 { 00141 // note A(j,j), was A(jp,p) previously which was 00142 // guarranteed not to be zero (Label #1) 00143 // 00144 typename MaTRiX::element_type recp = 1.0 / A(j,j); 00145 00146 for (k=j+1; k<=M; k++) 00147 A(k,j) *= recp; 00148 } 00149 00150 00151 if (j < minMN) 00152 { 00153 // rank-1 update to trailing submatrix: E = E - x*y; 00154 // 00155 // E is the region A(j+1:M, j+1:N) 00156 // x is the column vector A(j+1:M,j) 00157 // y is row vector A(j,j+1:N) 00158 00159 Subscript ii,jj; 00160 00161 for (ii=j+1; ii<=M; ii++) 00162 for (jj=j+1; jj<=N; jj++) 00163 A(ii,jj) -= A(ii,j)*A(j,jj); 00164 } 00165 } 00166 00167 return 0; 00168 } 00169 00170 00171 00172 00173 template <class MaTRiX, class VecToR, class VecToRSubscripts> 00174 int LU_solve(const MaTRiX &A, const VecToRSubscripts &indx, VecToR &b) 00175 { 00176 assert(A.lbound() == 1); // currently for 1-offset 00177 assert(indx.lbound() == 1); // vectors and matrices 00178 assert(b.lbound() == 1); 00179 00180 Subscript i,ii=0,ip,j; 00181 Subscript n = b.dim(); 00182 typename MaTRiX::element_type sum = 0.0; 00183 00184 for (i=1;i<=n;i++) 00185 { 00186 ip=indx(i); 00187 sum=b(ip); 00188 b(ip)=b(i); 00189 if (ii) 00190 for (j=ii;j<=i-1;j++) 00191 sum -= A(i,j)*b(j); 00192 else if (sum) ii=i; 00193 b(i)=sum; 00194 } 00195 for (i=n;i>=1;i--) 00196 { 00197 sum=b(i); 00198 for (j=i+1;j<=n;j++) 00199 sum -= A(i,j)*b(j); 00200 b(i)=sum/A(i,i); 00201 } 00202 00203 return 0; 00204 } 00205 00206 } // namespace TNT 00207 00208 #endif // LU_H 00209