Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Tools/Math/LA_Lu_decomp.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 #include <math.h>
00003 #include <assert.h>
00004 #include "LA_Lu_decomp.h"
00005 #include "LA_Vector.h"
00006 #include "LA_Exception.h"
00007 //------------------------------------------------------------------------------
00008 namespace LA
00009 {
00010 //------------------------------------------------------------------------------
00011 LU::LU(const Matrix& M)
00012 : LU_(M), m(M.rows()), n(M.columns()), piv(M.rows())
00013 {
00014   // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
00015   int i = 0;
00016   int j = 0;
00017   int k = 0;
00018 
00019   for (i = 0; i < m; i++)
00020   {
00021      piv[i] = i;
00022   }
00023   pivsign = 1;
00024   Vector LUcolj(m);
00025 
00026   // Outer loop.
00027   for (j = 0; j < n; j++)
00028   {
00029     // Make a copy of the j-th column to localize references.
00030     for (i = 0; i < m; i++)
00031     {
00032       LUcolj[i] = LU_[i][j];
00033     }
00034 
00035     // Apply previous transformations.
00036     for (i = 0; i < m; i++)
00037     {
00038       Vector& LUrowi = LU_[i];
00039 
00040       // Most of the time is spent in the following dot product.
00041       int kmax = (i < j)? i: j;
00042       double s = 0.0;
00043       for (k = 0; k < kmax; k++)
00044       {
00045         s += LUrowi[k]*LUcolj[k];
00046       }
00047 
00048       LUrowi[j] = LUcolj[i] -= s;
00049     }
00050 
00051     // Find pivot and exchange if necessary.
00052     int p = j;
00053     for (i = j+1; i < m; i++)
00054     {
00055       if (fabs(LUcolj[i]) > fabs(LUcolj[p]))
00056       {
00057         p = i;
00058       }
00059     }
00060     if (p != j)
00061     {
00062       for (k = 0; k < n; k++)
00063       {
00064         double t = LU_[p][k]; 
00065         LU_[p][k] = LU_[j][k]; 
00066         LU_[j][k] = t;
00067       }
00068       k = piv[p]; 
00069       piv[p] = piv[j]; 
00070       piv[j] = k;
00071       pivsign = -pivsign;
00072     }
00073 
00074     // Compute multipliers.
00075     if ((j < m) && (LU_[j][j] != 0.0))
00076     {
00077       for (i = j+1; i < m; i++)
00078       {
00079         LU_[i][j] /= LU_[j][j];
00080       }
00081     }
00082   }
00083 }
00084 //------------------------------------------------------------------------------
00085 bool LU::singular() const
00086 {
00087   for (int j = 0; j < n; j++)
00088   {
00089     if (LU_[j][j] == 0.0)
00090       return true;
00091   }
00092   return false;
00093 }
00094 //------------------------------------------------------------------------------
00095 double LU::det() const
00096 {
00097   assert(m == n);
00098   double d = (double)pivsign;
00099   for (int j = 0; j < n; j++)
00100   {
00101     d *= LU_[j][j];
00102   }
00103   return d;
00104 }
00105 //------------------------------------------------------------------------------
00106 Vector LU::solve(const Vector& b) const
00107 {
00108   assert(b.dim() == m);
00109   if (singular())
00110     throw Exception(Exception::SingularMatrix);
00111 
00112   Vector x = permute_copy(b, piv);
00113   int i, k;
00114 
00115   for (k = 0; k < (int)n; k++)
00116   {
00117     for (i = k+1; i < (int)n; i++)
00118     {
00119       x[i] -= x[k]*LU_[i][k];
00120     }
00121   }
00122       
00123   for (k = (int)n-1; k >= 0; k--)
00124   {
00125     x[k] /= LU_[k][k];
00126     for (int i = 0; i < k; i++) 
00127       x[i] -= x[k]*LU_[i][k];
00128   }
00129   return x;
00130 }
00131 //------------------------------------------------------------------------------
00132 Matrix LU::inverse() const
00133 {
00134   assert(m == n);
00135   
00136   Matrix M(n, n);
00137   for (int i = 0; i < n; ++i)
00138   {
00139     Vector b(n);
00140     b[i] = 1.0;
00141     M.set_column(i + 1, solve(b));
00142   }
00143   return M;
00144 }
00145 //------------------------------------------------------------------------------
00146 Vector LU::permute_copy(const Vector& A, const std::vector<int>& piv) const
00147 {
00148   int piv_length = (int)piv.size();
00149   assert(piv_length == A.dim());
00150   
00151   Vector x(piv_length);
00152   for (int i = 0; i < piv_length; i++) 
00153     x[i] = A[piv[i]];
00154 
00155   return x;
00156 }
00157 //------------------------------------------------------------------------------
00158 }
00159 //------------------------------------------------------------------------------

Generated on Mon Mar 20 22:00:06 2006 for GT2005 by doxygen 1.3.6