Main Page   Namespace List   Compound List   File List   Compound Members  

jama_lu.h

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

Generated at Mon Jan 20 07:47:17 2003 for JAMA/C++ by doxygen1.2.5 written by Dimitri van Heesch, © 1997-2001