Heidelberg Educational Numerics Library Version 0.24 (from 9 September 2011)
|
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