Heidelberg Educational Numerics Library  Version 0.24 (from 9 September 2011)
lr.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil -*-
2 #ifndef HDNUM_LR_HH
3 #define HDNUM_LR_HH
4 
5 #include "vector.hh"
6 #include "densematrix.hh"
7 
12 namespace hdnum {
13 
15  template<class T>
17  {
18  if (A.rowsize()!=A.colsize() || A.rowsize()==0)
19  HDNUM_ERROR("need square and nonempty matrix");
20  if (A.rowsize()!=p.size())
21  HDNUM_ERROR("permutation vector incompatible with matrix");
22 
23  // transformation to upper triangular
24  for (std::size_t k=0; k<A.rowsize()-1; ++k)
25  {
26  // find pivot element and exchange rows
27  for (std::size_t r=k; r<A.rowsize(); ++r)
28  if (A[r][k]!=0)
29  {
30  p[k] = r; // store permutation in step k
31  if (r>k) // exchange complete row if r!=k
32  for (std::size_t j=0; j<A.colsize(); ++j)
33  {
34  T temp(A[k][j]);
35  A[k][j] = A[r][j];
36  A[r][j] = temp;
37  }
38  break;
39  }
40  if (A[k][k]==0) HDNUM_ERROR("matrix is singular");
41 
42  // modification
43  for (std::size_t i=k+1; i<A.rowsize(); ++i)
44  {
45  T qik(A[i][k]/A[k][k]);
46  A[i][k] = qik;
47  for (std::size_t j=k+1; j<A.colsize(); ++j)
48  A[i][j] -= qik * A[k][j];
49  }
50  }
51  }
52 
54  template<class T>
55  T abs (const T& t)
56  {
57  if (t<0.0)
58  return -t;
59  else
60  return t;
61  }
62 
64  template<class T>
66  {
67  if (A.rowsize()!=A.colsize() || A.rowsize()==0)
68  HDNUM_ERROR("need square and nonempty matrix");
69  if (A.rowsize()!=p.size())
70  HDNUM_ERROR("permutation vector incompatible with matrix");
71 
72  // initialize permutation
73  for (std::size_t k=0; k<A.rowsize(); ++k)
74  p[k] = k;
75 
76  // transformation to upper triangular
77  for (std::size_t k=0; k<A.rowsize()-1; ++k)
78  {
79  // find pivot element
80  for (std::size_t r=k+1; r<A.rowsize(); ++r)
81  if (abs(A[r][k])>abs(A[k][k]))
82  p[k] = r; // store permutation in step k
83 
84  if (p[k]>k) // exchange complete row if r!=k
85  for (std::size_t j=0; j<A.colsize(); ++j)
86  {
87  T temp(A[k][j]);
88  A[k][j] = A[p[k]][j];
89  A[p[k]][j] = temp;
90  }
91 
92  if (A[k][k]==0) HDNUM_ERROR("matrix is singular");
93 
94  // modification
95  for (std::size_t i=k+1; i<A.rowsize(); ++i)
96  {
97  T qik(A[i][k]/A[k][k]);
98  A[i][k] = qik;
99  for (std::size_t j=k+1; j<A.colsize(); ++j)
100  A[i][j] -= qik * A[k][j];
101  }
102  }
103  }
104 
106  template<class T>
108  {
109  if (A.rowsize()!=A.colsize() || A.rowsize()==0)
110  HDNUM_ERROR("need square and nonempty matrix");
111  if (A.rowsize()!=p.size())
112  HDNUM_ERROR("permutation vector incompatible with matrix");
113 
114  // initialize permutation
115  for (std::size_t k=0; k<A.rowsize(); ++k)
116  p[k] = q[k] = k;
117 
118  // transformation to upper triangular
119  for (std::size_t k=0; k<A.rowsize()-1; ++k)
120  {
121  // find pivot element
122  for (std::size_t r=k; r<A.rowsize(); ++r)
123  for (std::size_t s=k; s<A.colsize(); ++s)
124  if (abs(A[r][s])>abs(A[k][k]))
125  {
126  p[k] = r; // store permutation in step k
127  q[k] = s;
128  }
129 
130  if (p[k]>k) // exchange complete row if r!=k
131  for (std::size_t j=0; j<A.colsize(); ++j)
132  {
133  T temp(A[k][j]);
134  A[k][j] = A[p[k]][j];
135  A[p[k]][j] = temp;
136  }
137  if (q[k]>k) // exchange complete column if s!=k
138  for (std::size_t i=0; i<A.rowsize(); ++i)
139  {
140  T temp(A[i][k]);
141  A[i][k] = A[i][q[k]];
142  A[i][q[k]] = temp;
143  }
144 
145  if (A[k][k]==0) HDNUM_ERROR("matrix is singular");
146 
147  // modification
148  for (std::size_t i=k+1; i<A.rowsize(); ++i)
149  {
150  T qik(A[i][k]/A[k][k]);
151  A[i][k] = qik;
152  for (std::size_t j=k+1; j<A.colsize(); ++j)
153  A[i][j] -= qik * A[k][j];
154  }
155  }
156  }
157 
159  template<class T>
161  {
162  if (b.size()!=p.size())
163  HDNUM_ERROR("permutation vector incompatible with rhs");
164 
165  for (std::size_t k=0; k<b.size()-1; ++k)
166  if (p[k]!=k)
167  {
168  T temp(b[k]);
169  b[k] = b[p[k]];
170  b[p[k]] = temp;
171  }
172  }
173 
175  template<class T>
177  {
178  if (z.size()!=q.size())
179  HDNUM_ERROR("permutation vector incompatible with z");
180 
181  for (int k=z.size()-2; k>=0; --k)
182  if (q[k]!=std::size_t(k))
183  {
184  T temp(z[k]);
185  z[k] = z[q[k]];
186  z[q[k]] = temp;
187  }
188  }
189 
191  template<class T>
193  {
194  if (A.rowsize()*A.colsize()==0)
195  HDNUM_ERROR("need nonempty matrix");
196  if (A.rowsize()!=s.size())
197  HDNUM_ERROR("scaling vector incompatible with matrix");
198 
199  // equilibrate row sums
200  for (std::size_t k=0; k<A.rowsize(); ++k)
201  {
202  s[k] = T(0.0);
203  for (std::size_t j=0; j<A.colsize(); ++j)
204  s[k] += abs(A[k][j]);
205  if (s[k]==0) HDNUM_ERROR("row sum is zero");
206  for (std::size_t j=0; j<A.colsize(); ++j)
207  A[k][j] /= s[k];
208  }
209  }
210 
212  template<class T>
214  {
215  if (s.size()!=b.size())
216  HDNUM_ERROR("s and b incompatible");
217 
218  // equilibrate row sums
219  for (std::size_t k=0; k<b.size(); ++k)
220  b[k] /= s[k];
221  }
222 
224  template<class T>
225  void solveL (const DenseMatrix<T>& A, Vector<T>& x, const Vector<T>& b)
226  {
227  if (A.rowsize()!=A.colsize() || A.rowsize()==0)
228  HDNUM_ERROR("need square and nonempty matrix");
229  if (A.rowsize()!=b.size())
230  HDNUM_ERROR("right hand side incompatible with matrix");
231 
232  for (std::size_t i=0; i<A.rowsize(); ++i)
233  {
234  T rhs(b[i]);
235  for (std::size_t j=0; j<i; j++)
236  rhs -= A[i][j] * x[j];
237  x[i] = rhs;
238  }
239  }
240 
242  template<class T>
243  void solveR (const DenseMatrix<T>& A, Vector<T>& x, const Vector<T>& b)
244  {
245  if (A.rowsize()!=A.colsize() || A.rowsize()==0)
246  HDNUM_ERROR("need square and nonempty matrix");
247  if (A.rowsize()!=b.size())
248  HDNUM_ERROR("right hand side incompatible with matrix");
249 
250  for (int i=A.rowsize()-1; i>=0; --i)
251  {
252  T rhs(b[i]);
253  for (std::size_t j=i+1; j<A.colsize(); j++)
254  rhs -= A[i][j] * x[j];
255  x[i] = rhs/A[i][i];
256  }
257  }
258 
259 }
260 #endif
261 
Class with mathematical vector operations.
Definition: vector.hh:28
void lr_fullpivot(DenseMatrix< T > &A, Vector< std::size_t > &p, Vector< std::size_t > &q)
lr decomposition of A with full pivoting
Definition: lr.hh:107
void permute_backward(const Vector< std::size_t > &q, Vector< T > &z)
apply permutations to a solution vector
Definition: lr.hh:176
void solveR(const DenseMatrix< T > &A, Vector< T > &x, const Vector< T > &b)
Assume R = upper triangle of A and solve R x = b.
Definition: lr.hh:243
void row_equilibrate(DenseMatrix< T > &A, Vector< T > &s)
perform a row equilibration of a matrix; return scaling for later use
Definition: lr.hh:192
void apply_equilibrate(Vector< T > &s, Vector< T > &b)
apply row equilibration to right hand side vector
Definition: lr.hh:213
void solveL(const DenseMatrix< T > &A, Vector< T > &x, const Vector< T > &b)
Assume L = lower triangle of A with l_ii=1, solve L x = b.
Definition: lr.hh:225
size_t rowsize() const
get number of rows of the matrix
Definition: densematrix.hh:121
size_t colsize() const
get number of columns of the matrix
Definition: densematrix.hh:141
Class with mathematical matrix operations.
Definition: densematrix.hh:26
void lr_partialpivot(DenseMatrix< T > &A, Vector< std::size_t > &p)
lr decomposition of A with column pivoting
Definition: lr.hh:65
void permute_forward(const Vector< std::size_t > &p, Vector< T > &b)
apply permutations to a right hand side vector
Definition: lr.hh:160
T abs(const T &t)
our own abs class that works also for multiprecision types
Definition: lr.hh:55
Definition: densematrix.hh:21
void lr(DenseMatrix< T > &A, Vector< std::size_t > &p)
compute lr decomposition of A with first nonzero pivoting
Definition: lr.hh:16