Blender V2.61 - r43446

jama_lu.h

Go to the documentation of this file.
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 */