Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

tnt_lu.h

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

Generated on Fri Sep 16 11:02:17 2005 for spuc by  doxygen 1.4.4