atomicrex  0.1
An advanced atomistic model building tool
Matrix3.h
1 //
3 // Copyright (C) 2017, Alexander Stukowski and Paul Erhart
4 //
5 // This file is part of atomicrex.
6 //
7 // Atomicrex is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Atomicrex is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //
21 
22 #pragma once
23 
24 #include <array>
25 #include <ostream>
26 #include <cassert>
27 
28 #include "LinAlg.h"
29 #include "Point3.h"
30 #include "Vector3.h"
31 
32 namespace atomicrex {
33 
39 template<typename T>
40 class Matrix_3 : public std::array<Vector_3<T>,3>
41 {
42 public:
43 
45  struct Zero {};
46 
48  struct Identity {};
49 
51  typedef T element_type;
52 
55 
56  using typename std::array<Vector_3<T>, 3>::size_type;
57  using typename std::array<Vector_3<T>, 3>::difference_type;
58  using typename std::array<Vector_3<T>, 3>::value_type;
59  using typename std::array<Vector_3<T>, 3>::iterator;
60  using typename std::array<Vector_3<T>, 3>::const_iterator;
61 
62 public:
63 
66  Matrix_3() {}
67 
70  constexpr Matrix_3(T m11, T m12, T m13,
71  T m21, T m22, T m23,
72  T m31, T m32, T m33)
73  : std::array<Vector_3<T>,3>{{Vector_3<T>(m11,m21,m31),
74  Vector_3<T>(m12,m22,m32),
75  Vector_3<T>(m13,m23,m33)}} {}
76 
78  constexpr Matrix_3(const column_type& c1, const column_type& c2, const column_type& c3)
79  : std::array<Vector_3<T>,3>{{c1, c2, c3}} {}
80 
83  constexpr Matrix_3(Zero)
84  : std::array<Vector_3<T>,3>{{typename Vector_3<T>::Zero(), typename Vector_3<T>::Zero(), typename Vector_3<T>::Zero()}} {}
85 
88  constexpr Matrix_3(Identity)
89  : std::array<Vector_3<T>,3>{{Vector_3<T>(T(1),T(0),T(0)),
90  Vector_3<T>(T(0),T(1),T(0)),
91  Vector_3<T>(T(0),T(0),T(1))}} {}
92 
94  template<typename U>
95  constexpr explicit operator Matrix_3<U>() const {
96  return Matrix_3<U>(
97  static_cast<U>((*this)(0,0)), static_cast<U>((*this)(0,1)), static_cast<U>((*this)(0,2)),
98  static_cast<U>((*this)(1,0)), static_cast<U>((*this)(1,1)), static_cast<U>((*this)(1,2)),
99  static_cast<U>((*this)(2,0)), static_cast<U>((*this)(2,1)), static_cast<U>((*this)(2,2)));
100  }
101 
103  static constexpr size_type row_count() { return 3; }
104 
106  static constexpr size_type col_count() { return 3; }
107 
112  constexpr inline T operator()(size_type row, size_type col) const {
113  return (*this)[col][row];
114  }
115 
120  inline T& operator()(size_type row, size_type col) {
121  return (*this)[col][row];
122  }
123 
127  constexpr const column_type& column(size_type col) const {
128  return (*this)[col];
129  }
130 
136  column_type& column(size_type col) {
137  return (*this)[col];
138  }
139 
145  constexpr Vector_3<T> row(size_type row) const {
146  return { (*this)[0][row], (*this)[1][row], (*this)[2][row] };
147  }
148 
150  const element_type* elements() const {
151  return column(0).data();
152  }
153 
155  element_type* elements() {
156  return column(0).data();
157  }
158 
160  void setZero() {
161  (*this)[0].setZero();
162  (*this)[1].setZero();
163  (*this)[2].setZero();
164  }
165 
167  Matrix_3& operator=(Zero) {
168  setZero();
169  return *this;
170  }
171 
173  void setIdentity() {
174  (*this)[0] = Vector_3<T>(1,0,0);
175  (*this)[1] = Vector_3<T>(0,1,0);
176  (*this)[2] = Vector_3<T>(0,0,1);
177  }
178 
180  Matrix_3& operator=(Identity) {
181  setIdentity();
182  return *this;
183  }
184 
186 
189  constexpr bool operator==(const Matrix_3& b) const {
190  return (b[0] == (*this)[0]) && (b[1] == (*this)[1]) && (b[2] == (*this)[2]);
191  }
192 
195  constexpr bool operator!=(const Matrix_3& b) const {
196  return !(*this == b);
197  }
198 
204  inline bool equals(const Matrix_3& m, T tolerance = T(FLOATTYPE_EPSILON)) const {
205  for(size_type i = 0; i < col_count(); i++)
206  if(!column(i).equals(m.column(i), tolerance)) return false;
207  return true;
208  }
209 
213  inline bool isZero(T tolerance = T(FLOATTYPE_EPSILON)) const {
214  for(size_type i = 0; i < col_count(); i++)
215  if(!column(i).isZero(tolerance)) return false;
216  return true;
217  }
218 
220 
224  Matrix_3 inverse() const {
225  T det = determinant();
226  assert(det != T(0));
227  return Matrix_3(((*this)[1][1]*(*this)[2][2] - (*this)[1][2]*(*this)[2][1])/det,
228  ((*this)[2][0]*(*this)[1][2] - (*this)[1][0]*(*this)[2][2])/det,
229  ((*this)[1][0]*(*this)[2][1] - (*this)[1][1]*(*this)[2][0])/det,
230  ((*this)[2][1]*(*this)[0][2] - (*this)[0][1]*(*this)[2][2])/det,
231  ((*this)[0][0]*(*this)[2][2] - (*this)[2][0]*(*this)[0][2])/det,
232  ((*this)[0][1]*(*this)[2][0] - (*this)[0][0]*(*this)[2][1])/det,
233  ((*this)[0][1]*(*this)[1][2] - (*this)[1][1]*(*this)[0][2])/det,
234  ((*this)[0][2]*(*this)[1][0] - (*this)[0][0]*(*this)[1][2])/det,
235  ((*this)[0][0]*(*this)[1][1] - (*this)[1][0]*(*this)[0][1])/det);
236  }
237 
244  bool inverse(Matrix_3& result, T epsilon = T(FLOATTYPE_EPSILON)) const {
245  T det = determinant();
246  if(std::abs(det) <= epsilon) return false;
247  result = Matrix_3(((*this)[1][1]*(*this)[2][2] - (*this)[1][2]*(*this)[2][1])/det,
248  ((*this)[2][0]*(*this)[1][2] - (*this)[1][0]*(*this)[2][2])/det,
249  ((*this)[1][0]*(*this)[2][1] - (*this)[1][1]*(*this)[2][0])/det,
250  ((*this)[2][1]*(*this)[0][2] - (*this)[0][1]*(*this)[2][2])/det,
251  ((*this)[0][0]*(*this)[2][2] - (*this)[2][0]*(*this)[0][2])/det,
252  ((*this)[0][1]*(*this)[2][0] - (*this)[0][0]*(*this)[2][1])/det,
253  ((*this)[0][1]*(*this)[1][2] - (*this)[1][1]*(*this)[0][2])/det,
254  ((*this)[0][2]*(*this)[1][0] - (*this)[0][0]*(*this)[1][2])/det,
255  ((*this)[0][0]*(*this)[1][1] - (*this)[1][0]*(*this)[0][1])/det);
256  return true;
257  }
258 
260  constexpr inline T determinant() const {
261  return(((*this)[0][0]*(*this)[1][1] - (*this)[0][1]*(*this)[1][0])*((*this)[2][2])
262  -((*this)[0][0]*(*this)[1][2] - (*this)[0][2]*(*this)[1][0])*((*this)[2][1])
263  +((*this)[0][1]*(*this)[1][2] - (*this)[0][2]*(*this)[1][1])*((*this)[2][0]));
264  }
265 
267  constexpr Matrix_3 transposed() const {
268  return Matrix_3((*this)[0][0], (*this)[0][1], (*this)[0][2],
269  (*this)[1][0], (*this)[1][1], (*this)[1][2],
270  (*this)[2][0], (*this)[2][1], (*this)[2][2]);
271  }
272 
277  inline constexpr T prodrow(const Point_3<T>& p, typename Point_3<T>::size_type index) const {
278  return (*this)[0][index] * p[0] + (*this)[1][index] * p[1] + (*this)[2][index] * p[2];
279  }
280 
285  inline constexpr T prodrow(const Vector_3<T>& v, typename Vector_3<T>::size_type index) const {
286  return (*this)[0][index] * v[0] + (*this)[1][index] * v[1] + (*this)[2][index] * v[2];
287  }
288 
293  constexpr bool isOrthogonalMatrix(T epsilon = T(FLOATTYPE_EPSILON)) const {
294  return
295  (std::abs((*this)[0][0]*(*this)[1][0] + (*this)[0][1]*(*this)[1][1] + (*this)[0][2]*(*this)[1][2]) <= epsilon) &&
296  (std::abs((*this)[0][0]*(*this)[2][0] + (*this)[0][1]*(*this)[2][1] + (*this)[0][2]*(*this)[2][2]) <= epsilon) &&
297  (std::abs((*this)[1][0]*(*this)[2][0] + (*this)[1][1]*(*this)[2][1] + (*this)[1][2]*(*this)[2][2]) <= epsilon) &&
298  (std::abs((*this)[0][0]*(*this)[0][0] + (*this)[0][1]*(*this)[0][1] + (*this)[0][2]*(*this)[0][2] - T(1)) <= epsilon) &&
299  (std::abs((*this)[1][0]*(*this)[1][0] + (*this)[1][1]*(*this)[1][1] + (*this)[1][2]*(*this)[1][2] - T(1)) <= epsilon) &&
300  (std::abs((*this)[2][0]*(*this)[2][0] + (*this)[2][1]*(*this)[2][1] + (*this)[2][2]*(*this)[2][2] - T(1)) <= epsilon);
301  }
302 
309  constexpr bool isRotationMatrix(T epsilon = T(FLOATTYPE_EPSILON)) const {
310  return isOrthogonalMatrix(epsilon) && (std::abs(determinant() - T(1)) <= epsilon);
311  }
312 
324  void orthonormalize() {
325 
326  // Compute q0.
327  (*this)[0].normalize();
328 
329  // Compute q1.
330  T dot0 = (*this)[0].dot((*this)[1]);
331  (*this)[1][0] -= dot0 * (*this)[0][0];
332  (*this)[1][1] -= dot0 * (*this)[0][1];
333  (*this)[1][2] -= dot0 * (*this)[0][2];
334  (*this)[1].normalize();
335 
336  // compute q2
337  dot0 = (*this)[0].dot((*this)[2]);
338  T dot1 = (*this)[1].dot((*this)[2]);
339  (*this)[2][0] -= dot0*(*this)[0][0] + dot1*(*this)[1][0];
340  (*this)[2][1] -= dot0*(*this)[0][1] + dot1*(*this)[1][1];
341  (*this)[2][2] -= dot0*(*this)[0][2] + dot1*(*this)[1][2];
342  (*this)[2].normalize();
343  }
344 
345 };
346 
349 template<typename T>
350 constexpr inline Vector_3<T> operator*(const Matrix_3<T>& m, const Vector_3<T>& v)
351 {
352  return { m(0,0)*v[0] + m(0,1)*v[1] + m(0,2)*v[2],
353  m(1,0)*v[0] + m(1,1)*v[1] + m(1,2)*v[2],
354  m(2,0)*v[0] + m(2,1)*v[1] + m(2,2)*v[2] };
355 }
356 
359 template<typename T>
360 constexpr inline Point_3<T> operator*(const Matrix_3<T>& m, const Point_3<T>& p)
361 {
362  return { m(0,0)*p[0] + m(0,1)*p[1] + m(0,2)*p[2],
363  m(1,0)*p[0] + m(1,1)*p[1] + m(1,2)*p[2],
364  m(2,0)*p[0] + m(2,1)*p[1] + m(2,2)*p[2] };
365 }
366 
369 template<typename T>
370 constexpr inline Matrix_3<T> operator*(const Matrix_3<T>& a, const Matrix_3<T>& b)
371 {
372 #if 1
373  return Matrix_3<T>(
374  a(0,0)*b(0,0) + a(0,1)*b(1,0) + a(0,2)*b(2,0),
375  a(0,0)*b(0,1) + a(0,1)*b(1,1) + a(0,2)*b(2,1),
376  a(0,0)*b(0,2) + a(0,1)*b(1,2) + a(0,2)*b(2,2),
377 
378  a(1,0)*b(0,0) + a(1,1)*b(1,0) + a(1,2)*b(2,0),
379  a(1,0)*b(0,1) + a(1,1)*b(1,1) + a(1,2)*b(2,1),
380  a(1,0)*b(0,2) + a(1,1)*b(1,2) + a(1,2)*b(2,2),
381 
382  a(2,0)*b(0,0) + a(2,1)*b(1,0) + a(2,2)*b(2,0),
383  a(2,0)*b(0,1) + a(2,1)*b(1,1) + a(2,2)*b(2,1),
384  a(2,0)*b(0,2) + a(2,1)*b(1,2) + a(2,2)*b(2,2)
385  );
386 #else
387  Matrix_3<T> m;
388  for(typename Matrix_3<T>::size_type col = 0; col < 3; col++) {
389  for(typename Matrix_3<T>::size_type row = 0; row < 3; row++) {
390  T v{0};
391  for(typename Matrix_3<T>::size_type k = 0; k < 3; k++)
392  v += a(row, k) * b(k, col);
393  m(row, col) = v;
394  }
395  }
396  return m;
397 #endif
398 }
399 
400 
402 template<typename T>
403 inline Matrix_3<T> operator-(const Matrix_3<T>& a, const Matrix_3<T>& b)
404 {
405  Matrix_3<T> m;
406  for(typename Matrix_3<T>::size_type col = 0; col < 3; col++) {
407  for(typename Matrix_3<T>::size_type row = 0; row < 3; row++) {
408  m(row, col) = a(row, col) - b(row, col);
409  }
410  }
411  return m;
412 }
413 
414 
415 
418 template<typename T>
419 constexpr inline Matrix_3<T> operator*(const Matrix_3<T>& a, T s)
420 {
421 #if 1
422  return Matrix_3<T>(
423  a(0,0)*s, a(0,1)*s, a(0,2)*s,
424  a(1,0)*s, a(1,1)*s, a(1,2)*s,
425  a(2,0)*s, a(2,1)*s, a(2,2)*s
426  );
427 #else
428  Matrix_3<T> m;
429  for(typename Matrix_3<T>::size_type i = 0; i < 3; i++) {
430  for(typename Matrix_3<T>::size_type j = 0; j < 3; j++) {
431  m(i, j) = a(i, j) * s;
432  }
433  }
434  return m;
435 #endif
436 }
437 
440 template<typename T>
441 constexpr inline Matrix_3<T> operator*(T s, const Matrix_3<T>& a) {
442  return a * s;
443 }
444 
447 template<typename T>
448 inline std::ostream& operator<<(std::ostream &os, const Matrix_3<T>& m) {
449  for(typename Matrix_3<T>::size_type row = 0; row < m.row_count(); row++)
450  os << m.row(row) << std::endl;
451  return os;
452 }
453 
459 
460 } // End of namespace
A point in 3d space.
Definition: Point3.h:84
A 3x3 matrix.
Definition: Matrix3.h:40
Matrix_3()
Empty default constructor that does not initialize the matrix elements (for performance reasons)...
Definition: Matrix3.h:66
constexpr Matrix_3< T > operator*(T s, const Matrix_3< T > &a)
Multiplies a matrix with a scalar value.
Definition: Matrix3.h:441
constexpr Matrix_3< T > operator*(const Matrix_3< T > &a, T s)
Multiplies a matrix with a scalar value.
Definition: Matrix3.h:419
constexpr Point_3< T > operator*(const Matrix_3< T > &m, const Point_3< T > &p)
Computes the product of a matrix and a point. This is the same as a matrix-vector product...
Definition: Matrix3.h:360
constexpr Matrix_3< T > operator*(const Matrix_3< T > &a, const Matrix_3< T > &b)
Computes the product of two matrices.
Definition: Matrix3.h:370
This file collects the definition of classes that define various simple crystal structures.
Definition: Atomicrex.h:67
Matrix_3< T > operator-(const Matrix_3< T > &a, const Matrix_3< T > &b)
Subtracts a 3x3 matrix from a 3x3 Matrix.
Definition: Matrix3.h:403
T element_type
The type of a single element of the matrix.
Definition: Matrix3.h:51
An empty type that denotes the vector (0,0,0).
Definition: Vector3.h:70
An empty type that denotes a 3x3 matrix with all elements equal to zero.
Definition: Matrix3.h:45
Vector_3< T > column_type
The type of a single column of the matrix.
Definition: Matrix3.h:54
constexpr Matrix_3(T m11, T m12, T m13, T m21, T m22, T m23, T m31, T m32, T m33)
Constructor that initializes all 9 elements of the matrix to the given values.
Definition: Matrix3.h:70
A vector with three components.
Definition: Vector3.h:65
An empty type that denotes the 3x3 identity matrix.
Definition: Matrix3.h:48
constexpr Vector_3< T > operator*(const Matrix_3< T > &m, const Vector_3< T > &v)
Computes the product of a matrix and a vector.
Definition: Matrix3.h:350