Heidelberg Educational Numerics Library Version 0.24 (from 9 September 2011)

src/lr.hh

Go to the documentation of this file.
00001 // -*- tab-width: 4; indent-tabs-mode: nil -*-
00002 #ifndef HDNUM_LR_HH
00003 #define HDNUM_LR_HH
00004 
00005 #include "vector.hh"
00006 #include "densematrix.hh"
00007 
00012 namespace hdnum {
00013 
00015   template<class T>
00016   void lr (DenseMatrix<T>& A, Array<std::size_t>& p)
00017   {
00018     if (A.rowsize()!=A.colsize() || A.rowsize()==0) 
00019       HDNUM_ERROR("need square and nonempty matrix");
00020     if (A.rowsize()!=p.size())
00021       HDNUM_ERROR("permutation vector incompatible with matrix");
00022         
00023     // transformation to upper triangular
00024     for (std::size_t k=0; k<A.rowsize()-1; ++k) 
00025       {
00026         // find pivot element and exchange rows
00027         for (std::size_t r=k; r<A.rowsize(); ++r)
00028           if (A[r][k]!=0) 
00029             {
00030               p[k] = r; // store permutation in step k
00031               if (r>k) // exchange complete row if r!=k
00032                 for (std::size_t j=0; j<A.colsize(); ++j)
00033                   {
00034                     T temp(A[k][j]);
00035                     A[k][j] = A[r][j];
00036                     A[r][j] = temp;
00037                   }
00038               break;
00039             }
00040         if (A[k][k]==0) HDNUM_ERROR("matrix is singular");
00041 
00042         // modification
00043         for (std::size_t i=k+1; i<A.rowsize(); ++i) 
00044           {
00045             T qik(A[i][k]/A[k][k]);
00046             A[i][k] = qik;
00047             for (std::size_t j=k+1; j<A.colsize(); ++j)
00048               A[i][j] -= qik * A[k][j];
00049           }
00050       }
00051   }
00052 
00054   template<class T>
00055   T abs (const T& t)
00056   {
00057     if (t<0.0)
00058       return -t;
00059     else
00060       return t;
00061   }
00062 
00064   template<class T>
00065   void lr_partialpivot (DenseMatrix<T>& A, Array<std::size_t>& p)
00066   {
00067     if (A.rowsize()!=A.colsize() || A.rowsize()==0) 
00068       HDNUM_ERROR("need square and nonempty matrix");
00069     if (A.rowsize()!=p.size())
00070       HDNUM_ERROR("permutation vector incompatible with matrix");
00071         
00072     // initialize permutation
00073     for (std::size_t k=0; k<A.rowsize(); ++k)
00074       p[k] = k;
00075 
00076     // transformation to upper triangular
00077     for (std::size_t k=0; k<A.rowsize()-1; ++k) 
00078       {
00079         // find pivot element
00080         for (std::size_t r=k+1; r<A.rowsize(); ++r)
00081           if (abs(A[r][k])>abs(A[k][k])) 
00082             p[k] = r; // store permutation in step k
00083 
00084         if (p[k]>k) // exchange complete row if r!=k
00085           for (std::size_t j=0; j<A.colsize(); ++j)
00086             {
00087               T temp(A[k][j]);
00088               A[k][j] = A[p[k]][j];
00089               A[p[k]][j] = temp;
00090             }
00091 
00092         if (A[k][k]==0) HDNUM_ERROR("matrix is singular");
00093 
00094         // modification
00095         for (std::size_t i=k+1; i<A.rowsize(); ++i) 
00096           {
00097             T qik(A[i][k]/A[k][k]);
00098             A[i][k] = qik;
00099             for (std::size_t j=k+1; j<A.colsize(); ++j)
00100               A[i][j] -= qik * A[k][j];
00101           }
00102       }
00103   }
00104 
00106   template<class T>
00107   void lr_fullpivot (DenseMatrix<T>& A, Array<std::size_t>& p, Array<std::size_t>& q)
00108   {
00109     if (A.rowsize()!=A.colsize() || A.rowsize()==0) 
00110       HDNUM_ERROR("need square and nonempty matrix");
00111     if (A.rowsize()!=p.size())
00112       HDNUM_ERROR("permutation vector incompatible with matrix");
00113 
00114     // initialize permutation
00115     for (std::size_t k=0; k<A.rowsize(); ++k)
00116       p[k] = q[k] = k;
00117 
00118     // transformation to upper triangular
00119     for (std::size_t k=0; k<A.rowsize()-1; ++k) 
00120       {
00121         // find pivot element
00122         for (std::size_t r=k; r<A.rowsize(); ++r)
00123           for (std::size_t s=k; s<A.colsize(); ++s)
00124             if (abs(A[r][s])>abs(A[k][k]))
00125               { 
00126                 p[k] = r; // store permutation in step k
00127                 q[k] = s;
00128               }
00129 
00130         if (p[k]>k) // exchange complete row if r!=k
00131           for (std::size_t j=0; j<A.colsize(); ++j)
00132             {
00133               T temp(A[k][j]);
00134               A[k][j] = A[p[k]][j];
00135               A[p[k]][j] = temp;
00136             }
00137         if (q[k]>k) // exchange complete column if s!=k
00138           for (std::size_t i=0; i<A.rowsize(); ++i)
00139             {
00140               T temp(A[i][k]);
00141               A[i][k] = A[i][q[k]];
00142               A[i][q[k]] = temp;
00143             }
00144 
00145         if (A[k][k]==0) HDNUM_ERROR("matrix is singular");
00146 
00147         // modification
00148         for (std::size_t i=k+1; i<A.rowsize(); ++i) 
00149           {
00150             T qik(A[i][k]/A[k][k]);
00151             A[i][k] = qik;
00152             for (std::size_t j=k+1; j<A.colsize(); ++j)
00153               A[i][j] -= qik * A[k][j];
00154           }
00155       }
00156   }
00157 
00159   template<class T>
00160   void permute_forward (const Array<std::size_t>& p, Vector<T>& b)
00161   {
00162     if (b.size()!=p.size())
00163       HDNUM_ERROR("permutation vector incompatible with rhs");
00164   
00165     for (std::size_t k=0; k<b.size()-1; ++k)
00166       if (p[k]!=k)
00167         {
00168           T temp(b[k]);
00169           b[k] = b[p[k]];
00170           b[p[k]] = temp;
00171         }
00172   }
00173 
00175   template<class T>
00176   void permute_backward (const Array<std::size_t>& q, Vector<T>& z)
00177   {
00178     if (z.size()!=q.size())
00179       HDNUM_ERROR("permutation vector incompatible with z");
00180   
00181     for (int k=z.size()-2; k>=0; --k)
00182       if (q[k]!=std::size_t(k))
00183         {
00184           T temp(z[k]);
00185           z[k] = z[q[k]];
00186           z[q[k]] = temp;
00187         }
00188   }
00189 
00191   template<class T>
00192   void row_equilibrate (DenseMatrix<T>& A, Vector<T>& s)
00193   {
00194     if (A.rowsize()*A.colsize()==0) 
00195       HDNUM_ERROR("need nonempty matrix");
00196     if (A.rowsize()!=s.size())
00197       HDNUM_ERROR("scaling vector incompatible with matrix");
00198   
00199     // equilibrate row sums
00200     for (std::size_t k=0; k<A.rowsize(); ++k) 
00201       {
00202         s[k] = T(0.0);
00203         for (std::size_t j=0; j<A.colsize(); ++j)
00204           s[k] += abs(A[k][j]);
00205         if (s[k]==0) HDNUM_ERROR("row sum is zero");
00206         for (std::size_t j=0; j<A.colsize(); ++j)
00207           A[k][j] /= s[k];
00208       }
00209   }
00210 
00212   template<class T>
00213   void apply_equilibrate (Vector<T>& s, Vector<T>& b)
00214   {
00215     if (s.size()!=b.size())
00216       HDNUM_ERROR("s and b incompatible");
00217   
00218     // equilibrate row sums
00219     for (std::size_t k=0; k<b.size(); ++k) 
00220       b[k] /= s[k];
00221   }
00222 
00224   template<class T>
00225   void solveL (const DenseMatrix<T>& A, Vector<T>& x, const Vector<T>& b)
00226   {
00227     if (A.rowsize()!=A.colsize() || A.rowsize()==0) 
00228       HDNUM_ERROR("need square and nonempty matrix");
00229     if (A.rowsize()!=b.size())
00230       HDNUM_ERROR("right hand side incompatible with matrix");
00231 
00232     for (std::size_t i=0; i<A.rowsize(); ++i)
00233       {
00234         T rhs(b[i]);
00235         for (std::size_t j=0; j<i; j++)
00236           rhs -= A[i][j] * x[j];
00237         x[i] = rhs;
00238       }
00239   }
00240 
00242   template<class T>
00243   void solveR (const DenseMatrix<T>& A, Vector<T>& x, const Vector<T>& b)
00244   {
00245     if (A.rowsize()!=A.colsize() || A.rowsize()==0) 
00246       HDNUM_ERROR("need square and nonempty matrix");
00247     if (A.rowsize()!=b.size())
00248       HDNUM_ERROR("right hand side incompatible with matrix");
00249 
00250     for (int i=A.rowsize()-1; i>=0; --i)
00251       {
00252         T rhs(b[i]);
00253         for (std::size_t j=i+1; j<A.colsize(); j++)
00254           rhs -= A[i][j] * x[j];
00255         x[i] = rhs/A[i][i];
00256       }
00257   }
00258 
00259 }
00260 #endif
00261