Blender V2.61 - r43446
|
00001 00004 #ifndef JAMA_LU_H 00005 #define JAMA_LU_H 00006 00007 #include "tnt.h" 00008 #include <algorithm> 00009 //for min(), max() below 00010 00011 using namespace TNT; 00012 using namespace std; 00013 00014 namespace JAMA 00015 { 00016 00029 template <class Real> 00030 class LU 00031 { 00032 00033 00034 00035 /* Array for internal storage of decomposition. */ 00036 Array2D<Real> LU_; 00037 int m, n, pivsign; 00038 Array1D<int> piv; 00039 00040 00041 Array2D<Real> permute_copy(const Array2D<Real> &A, 00042 const Array1D<int> &piv, int j0, int j1) 00043 { 00044 int piv_length = piv.dim(); 00045 00046 Array2D<Real> X(piv_length, j1-j0+1); 00047 00048 00049 for (int i = 0; i < piv_length; i++) 00050 for (int j = j0; j <= j1; j++) 00051 X[i][j-j0] = A[piv[i]][j]; 00052 00053 return X; 00054 } 00055 00056 Array1D<Real> permute_copy(const Array1D<Real> &A, 00057 const Array1D<int> &piv) 00058 { 00059 int piv_length = piv.dim(); 00060 if (piv_length != A.dim()) 00061 return Array1D<Real>(); 00062 00063 Array1D<Real> x(piv_length); 00064 00065 00066 for (int i = 0; i < piv_length; i++) 00067 x[i] = A[piv[i]]; 00068 00069 return x; 00070 } 00071 00072 00073 public : 00074 00080 LU (const Array2D<Real> &A) : LU_(A.copy()), m(A.dim1()), n(A.dim2()), 00081 piv(A.dim1()) 00082 00083 { 00084 00085 // Use a "left-looking", dot-product, Crout/Doolittle algorithm. 00086 00087 00088 for (int i = 0; i < m; i++) { 00089 piv[i] = i; 00090 } 00091 pivsign = 1; 00092 Real *LUrowi = 0;; 00093 Array1D<Real> LUcolj(m); 00094 00095 // Outer loop. 00096 00097 for (int j = 0; j < n; j++) { 00098 00099 // Make a copy of the j-th column to localize references. 00100 00101 for (int i = 0; i < m; i++) { 00102 LUcolj[i] = LU_[i][j]; 00103 } 00104 00105 // Apply previous transformations. 00106 00107 for (int i = 0; i < m; i++) { 00108 LUrowi = LU_[i]; 00109 00110 // Most of the time is spent in the following dot product. 00111 00112 int kmax = min(i,j); 00113 double s = 0.0; 00114 for (int k = 0; k < kmax; k++) { 00115 s += LUrowi[k]*LUcolj[k]; 00116 } 00117 00118 LUrowi[j] = LUcolj[i] -= s; 00119 } 00120 00121 // Find pivot and exchange if necessary. 00122 00123 int p = j; 00124 for (int i = j+1; i < m; i++) { 00125 if (abs(LUcolj[i]) > abs(LUcolj[p])) { 00126 p = i; 00127 } 00128 } 00129 if (p != j) { 00130 int k=0; 00131 for (k = 0; k < n; k++) { 00132 double t = LU_[p][k]; 00133 LU_[p][k] = LU_[j][k]; 00134 LU_[j][k] = t; 00135 } 00136 k = piv[p]; 00137 piv[p] = piv[j]; 00138 piv[j] = k; 00139 pivsign = -pivsign; 00140 } 00141 00142 // Compute multipliers. 00143 00144 if ((j < m) && (LU_[j][j] != 0.0)) { 00145 for (int i = j+1; i < m; i++) { 00146 LU_[i][j] /= LU_[j][j]; 00147 } 00148 } 00149 } 00150 } 00151 00152 00158 int isNonsingular () { 00159 for (int j = 0; j < n; j++) { 00160 if (LU_[j][j] == 0) 00161 return 0; 00162 } 00163 return 1; 00164 } 00165 00170 Array2D<Real> getL () { 00171 Array2D<Real> L_(m,n); 00172 for (int i = 0; i < m; i++) { 00173 for (int j = 0; j < n; j++) { 00174 if (i > j) { 00175 L_[i][j] = LU_[i][j]; 00176 } else if (i == j) { 00177 L_[i][j] = 1.0; 00178 } else { 00179 L_[i][j] = 0.0; 00180 } 00181 } 00182 } 00183 return L_; 00184 } 00185 00190 Array2D<Real> getU () { 00191 Array2D<Real> U_(n,n); 00192 for (int i = 0; i < n; i++) { 00193 for (int j = 0; j < n; j++) { 00194 if (i <= j) { 00195 U_[i][j] = LU_[i][j]; 00196 } else { 00197 U_[i][j] = 0.0; 00198 } 00199 } 00200 } 00201 return U_; 00202 } 00203 00208 Array1D<int> getPivot () { 00209 return piv; 00210 } 00211 00212 00217 Real det () { 00218 if (m != n) { 00219 return Real(0); 00220 } 00221 Real d = Real(pivsign); 00222 for (int j = 0; j < n; j++) { 00223 d *= LU_[j][j]; 00224 } 00225 return d; 00226 } 00227 00234 Array2D<Real> solve (const Array2D<Real> &B) 00235 { 00236 00237 /* Dimensions: A is mxn, X is nxk, B is mxk */ 00238 00239 if (B.dim1() != m) { 00240 return Array2D<Real>(0,0); 00241 } 00242 if (!isNonsingular()) { 00243 return Array2D<Real>(0,0); 00244 } 00245 00246 // Copy right hand side with pivoting 00247 int nx = B.dim2(); 00248 00249 00250 Array2D<Real> X = permute_copy(B, piv, 0, nx-1); 00251 00252 // Solve L*Y = B(piv,:) 00253 for (int k = 0; k < n; k++) { 00254 for (int i = k+1; i < n; i++) { 00255 for (int j = 0; j < nx; j++) { 00256 X[i][j] -= X[k][j]*LU_[i][k]; 00257 } 00258 } 00259 } 00260 // Solve U*X = Y; 00261 for (int k = n-1; k >= 0; k--) { 00262 for (int j = 0; j < nx; j++) { 00263 X[k][j] /= LU_[k][k]; 00264 } 00265 for (int i = 0; i < k; i++) { 00266 for (int j = 0; j < nx; j++) { 00267 X[i][j] -= X[k][j]*LU_[i][k]; 00268 } 00269 } 00270 } 00271 return X; 00272 } 00273 00274 00284 Array1D<Real> solve (const Array1D<Real> &b) 00285 { 00286 00287 /* Dimensions: A is mxn, X is nxk, B is mxk */ 00288 00289 if (b.dim1() != m) { 00290 return Array1D<Real>(); 00291 } 00292 if (!isNonsingular()) { 00293 return Array1D<Real>(); 00294 } 00295 00296 00297 Array1D<Real> x = permute_copy(b, piv); 00298 00299 // Solve L*Y = B(piv) 00300 for (int k = 0; k < n; k++) { 00301 for (int i = k+1; i < n; i++) { 00302 x[i] -= x[k]*LU_[i][k]; 00303 } 00304 } 00305 00306 // Solve U*X = Y; 00307 for (int k = n-1; k >= 0; k--) { 00308 x[k] /= LU_[k][k]; 00309 for (int i = 0; i < k; i++) 00310 x[i] -= x[k]*LU_[i][k]; 00311 } 00312 00313 00314 return x; 00315 } 00316 00317 }; /* class LU */ 00318 00319 } /* namespace JAMA */ 00320 00321 #endif 00322 /* JAMA_LU_H */