Chemical Data Processing Library C++ API - Version 1.4.0
LUDecomposition.hpp
Go to the documentation of this file.
1 /*
2  * LUDecomposition.hpp
3  *
4  * Copyright (C) 2003 Thomas Seidel <thomas.seidel@univie.ac.at>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
27 #ifndef CDPL_MATH_LUDECOMPOSITION_HPP
28 #define CDPL_MATH_LUDECOMPOSITION_HPP
29 
30 #include <algorithm>
31 
35 
36 
37 namespace CDPL
38 {
39 
40  namespace Math
41  {
42 
49  template <typename E>
50  typename E::SizeType
52  {
53  typedef typename E::SizeType SizeType;
54  typedef typename E::ValueType ValueType;
55  typedef typename MatrixRange<E>::RangeType MatrixRangeType;
56  typedef typename VectorRange<MatrixRow<E> >::RangeType RowRangeType;
57  typedef typename VectorRange<MatrixColumn<E> >::RangeType ColumnRangeType;
58 
59  SizeType size1 = e().getSize1();
60  SizeType size2 = e().getSize2();
61  SizeType size = std::min(size1, size2);
62 
63  if (size == 0)
64  return 0;
65 
66  SizeType singular = 0;
67 
68  for (SizeType i = 0; i < size; i++) {
69  MatrixColumn<E> col_i(column(e, i));
70  MatrixRow<E> row_i(row(e, i));
71 
72  if (e()(i, i) != ValueType(0)) {
73  ValueType m_inv = ValueType(1) / e()(i, i);
74  range(col_i, ColumnRangeType(i + 1, size1)) *= m_inv;
75 
76  } else if (singular == 0)
77  singular = i + 1;
78 
79  range(e, MatrixRangeType(i + 1, size1), MatrixRangeType(i + 1, size2))
80  .minusAssign(outerProd(range(col_i, ColumnRangeType(i + 1, size1)),
81  range(row_i, RowRangeType(i + 1, size2))));
82  }
83 
84  return singular;
85  }
86 
97  template <typename E, typename PV, typename T>
98  typename E::SizeType
99  luDecompose(MatrixExpression<E>& e, PV& pv, T& num_row_swaps)
100  {
101  typedef typename E::SizeType SizeType;
102  typedef typename E::ValueType ValueType;
103  typedef typename MatrixRange<E>::RangeType MatrixRangeType;
104  typedef typename VectorRange<MatrixRow<E> >::RangeType RowRangeType;
105  typedef typename VectorRange<MatrixColumn<E> >::RangeType ColumnRangeType;
106 
107  SizeType size1 = e().getSize1();
108  SizeType size2 = e().getSize2();
109  SizeType size = std::min(size1, size2);
110 
111  num_row_swaps = 0;
112 
113  if (size == 0)
114  return 0;
115 
116  SizeType singular = 0;
117 
118  for (SizeType i = 0; i < size; i++) {
119  MatrixColumn<E> col_i(column(e, i));
120  MatrixRow<E> row_i(row(e, i));
121  SizeType norm_inf_idx = i + normInfIndex(range(col_i, ColumnRangeType(i, size1)));
122 
123  if (e()(norm_inf_idx, i) != ValueType(0)) {
124  pv[i] = norm_inf_idx;
125 
126  if (norm_inf_idx != i) {
127  row(e, norm_inf_idx).swap(row_i);
128  num_row_swaps++;
129  }
130 
131  ValueType m_inv = ValueType(1) / e()(i, i);
132  range(col_i, ColumnRangeType(i + 1, size1)) *= m_inv;
133 
134  } else if (singular == 0)
135  singular = i + 1;
136 
137  range(e, MatrixRangeType(i + 1, size1), MatrixRangeType(i + 1, size2))
138  .minusAssign(outerProd(range(col_i, ColumnRangeType(i + 1, size1)),
139  range(row_i, RowRangeType(i + 1, size2))));
140  }
141 
142  return singular;
143  }
144 
152  template <typename E, typename PV>
153  void
154  swapRows(VectorExpression<E>& e, const PV& pv)
155  {
156  typedef typename E::SizeType SizeType;
157 
158  for (SizeType i = 0, size = e().getSize(); i < size; i++) {
159  if (i != SizeType(pv[i]))
160  std::swap(e()(i), e()(pv[i]));
161  }
162  }
163 
171  template <typename E, typename PV>
172  void
173  swapRows(MatrixExpression<E>& e, const PV& pv)
174  {
175  typedef typename E::SizeType SizeType;
176 
177  for (SizeType i = 0, size = e().getSize1(); i < size; i++) {
178  if (i != SizeType(pv[i])) {
179  MatrixRow<E> other_row(e(), pv[i]);
180  row(e, i).swap(other_row);
181  }
182  }
183  }
184 
193  template <typename E1, typename E2>
194  bool
196  {
197  if (!solveUnitLower(lu, b))
198  return false;
199 
200  return solveUpper(lu, b);
201  }
202 
213  template <typename E1, typename E2, typename PV>
214  bool
216  {
217  swapRows(b, pv);
218 
219  return luSubstitute(lu, b);
220  }
221 
230  template <typename E1, typename E2>
231  bool
233  {
234  if (!solveUnitLower(lu, b))
235  return false;
236 
237  return solveUpper(lu, b);
238  }
239 
250  template <typename E1, typename E2, typename PV>
251  bool
253  {
254  swapRows(b, pv);
255 
256  return luSubstitute(lu, b);
257  }
258  } // namespace Math
259 } // namespace CDPL
260 
261 #endif // CDPL_MATH_LUDECOMPOSITION_HPP
Functions for solving linear equations.
Definition of matrix proxy types.
Definition of vector proxy types.
Vector-expression proxy that views a single column of an underlying matrix.
Definition: MatrixProxy.hpp:320
CRTP base class for all matrix expression types.
Definition: Expression.hpp:104
Vector-expression proxy that views a single row of an underlying matrix.
Definition: MatrixProxy.hpp:53
CRTP base class for all vector expression types.
Definition: Expression.hpp:66
Vector-expression proxy that views a contiguous half-open subrange of an underlying vector.
Definition: VectorProxy.hpp:52
constexpr unsigned int T
Specifies Hydrogen (Tritium).
Definition: AtomType.hpp:67
bool luSubstitute(const MatrixExpression< E1 > &lu, VectorExpression< E2 > &b)
Solves for b in place, given the LU decomposition lu (without pivoting).
Definition: LUDecomposition.hpp:195
bool solveUpper(const MatrixExpression< E1 > &e1, VectorExpression< E2 > &e2)
Solves in place by back-substitution, where e1 is an upper-triangular matrix.
Definition: LinearSolve.hpp:202
VectorNormInfinityIndex< E >::ResultType normInfIndex(const VectorExpression< E > &e)
Returns the (first) index at which the vector expression e attains its L∞ norm.
Definition: VectorExpression.hpp:966
MatrixColumn< M > column(MatrixExpression< M > &e, typename MatrixColumn< M >::SizeType j)
Returns a mutable column proxy for column j of the matrix expression e.
Definition: MatrixProxy.hpp:1259
MatrixRow< M > row(MatrixExpression< M > &e, typename MatrixRow< M >::SizeType i)
Returns a mutable row proxy for row i of the matrix expression e.
Definition: MatrixProxy.hpp:1231
MatrixRange< E > range(MatrixExpression< E > &e, const typename MatrixRange< E >::RangeType &r1, const typename MatrixRange< E >::RangeType &r2)
Returns a mutable matrix range proxy viewing rows in r1 and columns in r2 of e.
Definition: MatrixProxy.hpp:1288
VectorMatrixBinaryTraits< E1, E2, ScalarMultiplication< typename E1::ValueType, typename E2::ValueType > >::ResultType outerProd(const VectorExpression< E1 > &e1, const VectorExpression< E2 > &e2)
Returns the outer product of the vector expressions e1 and e2 as a matrix expression .
Definition: MatrixExpression.hpp:1409
bool solveUnitLower(const MatrixExpression< E1 > &e1, VectorExpression< E2 > &e2)
Solves in place by forward-substitution, where e1 is a unit lower-triangular matrix (1 on the diagon...
Definition: LinearSolve.hpp:91
void swapRows(VectorExpression< E > &e, const PV &pv)
Applies the permutation vector pv to the vector expression e by swapping element i with element pv[i]...
Definition: LUDecomposition.hpp:154
E::SizeType luDecompose(MatrixExpression< E > &e)
Computes an in-place LU decomposition of the matrix e without partial pivoting.
Definition: LUDecomposition.hpp:51
The namespace of the Chemical Data Processing Library.