Blender  V2.59
lu.h
Go to the documentation of this file.
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