Virtual Testbed
Ship dynamics simulator for extreme conditions
linear_algebra.hh
1 #ifndef VTESTBED_LINALG_LINEAR_ALGEBRA_HH
2 #define VTESTBED_LINALG_LINEAR_ALGEBRA_HH
3 
4 #include <stdexcept>
5 
6 #include <vtestbed/base/blitz.hh>
7 #include <vtestbed/linalg/types.hh>
8 
9 namespace vtb {
10 
11  namespace linalg {
12 
14 
15  public:
16 
17  Invalid_matrix() = default;
18 
19  inline explicit
20  Invalid_matrix(const char* msg): std::runtime_error(msg) {}
21 
22  };
23 
24  inline float conj(float x) { return x; }
25  inline float conj(double x) { return x; }
26 
27  template <class T>
28  inline std::complex<T>
29  conj(const std::complex<T>& z) {
30  return std::conj(z);
31  }
32 
33  template <class T>
34  class Vector: public blitz::Array<T,1> {
35 
36  private:
37  typedef blitz::Array<T,1> base_type;
38 
39  public:
40  using base_type::base_type;
41  using base_type::operator=;
42  using base_type::operator();
43 
44  inline
45  Vector(base_type rhs):
46  base_type(rhs) {}
47 
48  };
49 
50  template <class T>
51  class Matrix: public blitz::Array<T,2> {
52 
53  private:
54  typedef blitz::Array<T,2> base_type;
55 
56  public:
57  using base_type::base_type;
58  using base_type::operator=;
59 
60  inline
61  Matrix(base_type rhs):
62  base_type(rhs) {}
63 
64  inline bool
65  is_square() const {
66  return this->rows() == this->cols();
67  }
68 
69  bool
70  is_symmetric() const;
71 
72  bool
73  is_symmetric(T eps) const;
74 
77  bool
78  is_positive_definite() const;
79 
80  bool
81  is_toeplitz() const;
82 
83  bool
84  is_toeplitz(T eps) const;
85 
86  inline Square_matrix<T>
87  inverse() const;
88 
89  inline Square_matrix<T>&
90  inverse_self();
91 
92  inline Matrix<T>
93  transpose() const {
94  Matrix<T> tmp(*this);
95  tmp.base_type::transpose(1, 0);
96  return tmp;
97  }
98 
99  inline void
100  transpose_self() {
101  this->base_type::transposeSelf(1, 0);
102  }
103 
104  };
105 
106  template <class T>
107  class Square_matrix: public Matrix<T> {
108 
109  public:
110  using Matrix<T>::Matrix;
111  using Matrix<T>::operator=;
112  using Matrix<T>::operator();
113 
114  };
115 
116  template <class T>
118 
119  private:
120  typedef Square_matrix<T> base_type;
121 
122  public:
123  using base_type::base_type;
124  using base_type::operator=;
125  using base_type::operator();
126 
134  Vector<T>
135  forward_substitution(const Vector<T>& b) const;
136 
144  Vector<T>
145  backward_substitution(const Vector<T>& y) const;
146 
147  inline Vector<T>
148  solve(const Vector<T>& b) const {
150  }
151 
152  };
153 
154  template <class T>
156 
157  private:
158  typedef Lower_triangular_matrix<T> base_type;
159 
160  friend class Symmetric_matrix<T>;
161 
162  private:
163  Vector<T> _diagonal;
164 
165  public:
166  using base_type::base_type;
167  using base_type::operator=;
168  using base_type::operator();
169 
170  inline Vector<T>
171  solve(const Vector<T>& b) const {
172  Vector<T> y(this->forward_substitution(b) / this->_diagonal);
173  return this->backward_substitution(y);
174  }
175 
176  };
177 
178  template <class T>
179  class Symmetric_matrix: public Square_matrix<T> {
180 
181  private:
182  typedef Square_matrix<T> base_type;
183 
184  public:
185  using base_type::base_type;
186  using base_type::operator=;
187  using base_type::operator();
188 
190  cholesky_indefinite() const;
191 
200  Vector<T>
201  eigen_values(T eps, int nsweeps) const;
202 
203  };
204 
205  template <class T>
207 
208  private:
209  typedef Symmetric_matrix<T> base_type;
210 
211  public:
212  using base_type::base_type;
213  using base_type::operator=;
214  using base_type::operator();
215 
223  cholesky() const;
224 
225  };
226 
227  template <class T>
229 
230  private:
231  typedef Square_matrix<T> base_type;
232  typedef Vector<int> int_array_type;
233 
234  private:
235  int_array_type _permutations;
236  int _npermutations = 0;
237 
238  public:
239  using base_type::base_type;
240  using base_type::operator=;
241  using base_type::operator();
242 
243  inline const int_array_type&
244  permutations() const noexcept {
245  return this->_permutations;
246  }
247 
249  inverse() const;
250 
251  inline Square_matrix<T>&
252  inverse_self() {
253  Square_matrix<T> m = this->inverse();
254  this->reference(m);
255  return *this;
256  }
257 
258  Vector<T>
259  solve(const Vector<T>& b) const;
260 
262  lower_upper_triangular_self();
263 
264  T
265  determinant() const;
266 
267  };
268 
269  template <class T>
271  lower_upper_triangular(const Matrix<T>& rhs) {
272  Lower_upper_triangular_matrix<T> tmp(rhs.shape());
273  tmp = rhs;
274  tmp.lower_upper_triangular_self();
275  return tmp;
276  }
277 
278  template <class NewMatrix, class OldMatrix>
279  inline const NewMatrix&
280  matrix_cast(const OldMatrix& rhs) {
281  return static_cast<const NewMatrix&>(rhs);
282  }
283 
284  template <class NewMatrix, class OldMatrix>
285  inline NewMatrix&
286  matrix_cast(OldMatrix& rhs) {
287  return static_cast<NewMatrix&>(rhs);
288  }
289 
290  template <class T>
291  Vector<T>
292  product(const Matrix<T>& lhs, const Vector<T>& rhs);
293 
294  template <class T>
295  inline Vector<T>
296  operator*(const Matrix<T>& lhs, const Vector<T>& rhs) {
297  return product<T>(lhs, rhs);
298  }
299 
300  template <class T>
301  Matrix<T>
302  product(const Matrix<T>& lhs, const Matrix<T>& rhs);
303 
304  template <class T>
305  inline Matrix<T>
306  operator*(const Matrix<T>& lhs, const Matrix<T>& rhs) {
307  return product<T>(lhs, rhs);
308  }
309 
310  template <class T>
311  inline T
312  det(const Lower_upper_triangular_matrix<T>& rhs) {
313  return rhs.determinant();
314  }
315 
316  template <class T>
317  inline T
318  det(const Square_matrix<T>& rhs) {
319  return det(lower_upper_triangular(rhs));
320  }
321 
322  template <class T>
323  inline T
324  inverse(const Lower_upper_triangular_matrix<T>& rhs) {
325  return rhs.inverse();
326  }
327 
328  template <class T>
329  inline T
330  inverse(const Square_matrix<T>& rhs) {
331  return inverse(lower_upper_triangular(rhs));
332  }
333 
334  template <class T>
335  inline T
336  trace(const Square_matrix<T>& rhs) {
337  T sum{0};
338  const int n = rhs.nrows();
339  for (int i=0; i<n; ++i) {
340  sum += rhs(i,i);
341  }
342  return sum;
343  }
344 
345  template <class T>
346  inline Square_matrix<T>
347  Matrix<T>::inverse() const {
348  return lower_upper_triangular(*this).inverse();
349  }
350 
351  template <class T>
352  inline Square_matrix<T>&
353  Matrix<T>::inverse_self() {
354  this->reference(lower_upper_triangular(*this).inverse());
355  return matrix_cast<Square_matrix<T>>(*this);
356  }
357 
358  template <class T>
359  inline Vector<T>
360  solve(
361  const Lower_upper_triangular_matrix<T>& lhs,
362  const Vector<T>& rhs
363  ) {
364  return lhs.solve(rhs);
365  }
366 
367  template <class T>
368  inline Vector<T>
369  solve(const Square_matrix<T>& lhs, const Vector<T>& rhs) {
370  return solve(lower_upper_triangular(lhs), rhs);
371  }
372 
373  template <class T>
374  inline Vector<T>
375  solve(const Symmetric_matrix<T>& lhs, const Vector<T>& rhs) {
376  return lhs.cholesky_indefinite().solve(rhs);
377  }
378 
379  template <class T>
380  inline Vector<T>
381  solve(const Positive_definite_matrix<T>& lhs, const Vector<T>& rhs) {
382  return lhs.cholesky().solve(rhs);
383  }
384 
385  template <class T>
386  inline Vector<T>
387  eigen_values(const Symmetric_matrix<T>& rhs, T eps, int nsweeps) {
388  return rhs.eigen_values(eps, nsweeps);
389  }
390 
391  }
392 
393 }
394 
395 #endif // vim:filetype=cpp
Vector< T > backward_substitution(const Vector< T > &y) const
Backward substitution.
bool is_positive_definite() const
Vector< T > eigen_values(T eps, int nsweeps) const
Compute eigen values.
Main namespace.
Definition: convert.hh:9
Lower_triangular_matrix< T > cholesky() const
Cholesky decomposition.
Vector< T > forward_substitution(const Vector< T > &b) const
Forward substitution.