Ocean
SquareMatrix2.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_MATH_SQUARE_MATRIX_2_H
9 #define META_OCEAN_MATH_SQUARE_MATRIX_2_H
10 
11 #include "ocean/math/Math.h"
12 #include "ocean/math/Equation.h"
13 #include "ocean/math/Numeric.h"
14 #include "ocean/math/Vector2.h"
15 
16 #include <vector>
17 
18 namespace Ocean
19 {
20 
21 // Forward declaration.
22 template <typename T> class SquareMatrixT2;
23 
24 /**
25  * Definition of the SquareMatrix2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
26  * @see SquareMatrixT2
27  * @ingroup math
28  */
30 
31 /**
32  * Instantiation of the SquareMatrixT2 template class using a double precision float data type.
33  * @see SquareMatrixT2
34  * @ingroup math
35  */
37 
38 /**
39  * Instantiation of the SquareMatrixT2 template class using a single precision float data type.
40  * @see SquareMatrixT2
41  * @ingroup math
42  */
44 
45 /**
46  * Definition of a typename alias for vectors with SquareMatrixT2 objects.
47  * @see SquareMatrixT2
48  * @ingroup math
49  */
50 template <typename T>
51 using SquareMatricesT2 = std::vector<SquareMatrixT2<T>>;
52 
53 /**
54  * Definition of a vector holding SquareMatrix2 objects.
55  * @see SquareMatrix2
56  * @ingroup math
57  */
58 typedef std::vector<SquareMatrix2> SquareMatrices2;
59 
60 /**
61  * This class implements a 2x2 square matrix.
62  * The four values are stored in a column aligned order with indices:
63  * <pre>
64  * | 0 2 |
65  * | 1 3 |
66  * </pre>
67  * @tparam T Data type of matrix elements
68  * @see SquareMatrix2, SquareMatrixF2, SquareMatrixD2.
69  * @ingroup math
70  */
71 template <typename T>
73 {
74  template <typename U> friend class SquareMatrixT2;
75 
76  public:
77 
78  /**
79  * Definition of the used data type.
80  */
81  typedef T Type;
82 
83  public:
84 
85  /**
86  * Creates a new SquareMatrixT2 object with undefined elements.
87  * Beware: This matrix is neither a zero nor an entity matrix!
88  */
89  inline SquareMatrixT2();
90 
91  /**
92  * Copy constructor.
93  * @param matrix The matrix to copy
94  */
95  SquareMatrixT2(const SquareMatrixT2<T>& matrix) = default;
96 
97  /**
98  * Copy constructor for a matrix with difference element data type than T.
99  * @param matrix The matrix to copy
100  * @tparam U The element data type of the second matrix
101  */
102  template <typename U>
103  inline explicit SquareMatrixT2(const SquareMatrixT2<U>& matrix);
104 
105  /**
106  * Creates a new SquareMatrixT2 object.
107  * @param setToIdentity Determines whether an identity matrix will be created, otherwise the matrix is initialized with zeros
108  */
109  inline explicit SquareMatrixT2(const bool setToIdentity);
110 
111  /**
112  * Creates a new SquareMatrixT2 object by a given diagonal vector.
113  * @param diagonal Diagonal vector for the new matrix
114  */
115  inline explicit SquareMatrixT2(const VectorT2<T>& diagonal);
116 
117  /**
118  * Creates a new SquareMatrixT2 object by four elements of float type U.
119  * @param arrayValues The four matrix elements defining the new matrix, must be valid
120  * @tparam U The floating point type of the given elements
121  */
122  template <typename U>
123  explicit SquareMatrixT2(const U* arrayValues);
124 
125  /**
126  * Creates a new SquareMatrixT2 object by four elements.
127  * @param arrayValues The four matrix elements defining the new matrix, must be valid
128  */
129  explicit SquareMatrixT2(const T* arrayValues);
130 
131  /**
132  * Creates a new SquareMatrixT2 object by four elements.
133  * @param arrayValues The four matrix elements defining the new matrix, must be valid
134  * @param valuesRowAligned True, if the given values are stored in a row aligned order; False, if the values are stored in a column aligned order (which is the default case for this matrix)
135  * @tparam U The floating point type of the given elements
136  */
137  template <typename U>
138  SquareMatrixT2(const U* arrayValues, const bool valuesRowAligned);
139 
140  /**
141  * Creates a new SquareMatrixT2 object by four elements.
142  * @param arrayValues The four matrix elements defining the new matrix, must be valid
143  * @param valuesRowAligned True, if the given values are stored in a row aligned order; False, if the values are stored in a column aligned order (which is the default case for this matrix)
144  */
145  SquareMatrixT2(const T* arrayValues, const bool valuesRowAligned);
146 
147  /**
148  * Creates a 2x2 rotation matrix by 4 given matrix elements.
149  * @param m00 Element of the first row and first column
150  * @param m10 Element of the second row and first column
151  * @param m01 Element of the first row and second column
152  * @param m11 Element of the second row and second column
153  */
154  inline SquareMatrixT2(const T& m00, const T& m10, const T& m01, const T& m11);
155 
156  /**
157  * Creates a covariance matrix by two eigen values and two corresponding eigen vectors.
158  * @param eigenValue0 First eigen value
159  * @param eigenValue1 Second eigen value
160  * @param eigenVector0 First eigen vector
161  * @param eigenVector1 Second eigen vector
162  */
163  SquareMatrixT2(const T eigenValue0, const T eigenValue1, const VectorT2<T>& eigenVector0, const VectorT2<T>& eigenVector1);
164 
165  /**
166  * Returns the transposed of this matrix.
167  * @return Transposed matrix
168  */
169  inline SquareMatrixT2<T> transposed() const;
170 
171  /**
172  * Transposes the matrix.
173  */
174  inline void transpose();
175 
176  /**
177  * Returns the inverted matrix of this matrix.
178  * This matrix must not be singular.<br>
179  * Beware: This function does not throw an exception if the matrix cannot be inverted.<br>
180  * Thus, ensure that the matrix is invertible before calling this function.<br>
181  * Even better: avoid the usage of this function and call invert() instead.<br>
182  * In case, this matrix is not invertible, this matrix will be returned instead.
183  * @return The inverted matrix
184  * @see invert(), isSingular().
185  */
186  inline SquareMatrixT2<T> inverted() const;
187 
188  /**
189  * Inverts this matrix in place.
190  * @return True, if the matrix is not singular and could be inverted
191  * @see inverted(), solve().
192  */
193  inline bool invert();
194 
195  /**
196  * Inverts the matrix and returns the result as parameter.
197  * @param invertedMatrix The resulting inverted matrix
198  * @return True, if the matrix is not singular and could be inverted
199  * @see inverted(), solve().
200  */
201  inline bool invert(SquareMatrixT2<T>& invertedMatrix) const;
202 
203  /**
204  * Returns the determinant of the matrix.
205  * @return Matrix determinant
206  */
207  inline T determinant() const;
208 
209  /**
210  * Returns the trace of the matrix which is the sum of the diagonal elements.
211  * @return Trace of the matrix
212  */
213  inline T trace() const;
214 
215  /**
216  * Solve a simple 2x2 system of linear equations: Ax = b
217  * Beware: The system of linear equations is assumed to be fully determined.
218  * @param b The right-hand side vector
219  * @param x The resulting solution vector
220  * @return True, if the system could be solved
221  * @see invert(), inverted().
222  */
223  inline bool solve(const VectorT2<T>& b, VectorT2<T>& x) const;
224 
225  /**
226  * Sets the matrix to the identity matrix.
227  */
228  inline void toIdentity();
229 
230  /**
231  * Sets the matrix to a zero matrix.
232  * @see isNull();
233  */
234  inline void toNull();
235 
236  /**
237  * Returns the x axis which is the first column of the matrix.
238  * @return Vector with the first column
239  */
240  inline VectorT2<T> xAxis() const;
241 
242  /**
243  * Returns the y axis which is the middle column of the matrix.
244  * @return Vector with the middle column
245  */
246  inline VectorT2<T> yAxis() const;
247 
248  /**
249  * Returns a 2D vector with values of the matrix diagonal.
250  * @return Vector with diagonal values
251  */
252  inline VectorT2<T> diagonal() const;
253 
254  /**
255  * Returns the norm of this matrix that is the sum of the absolute matrix elements.
256  * @return Matrix norm
257  */
258  inline T norm() const;
259 
260  /**
261  * Returns whether this matrix is a null matrix.
262  * @return True, if so
263  */
264  inline bool isNull() const;
265 
266  /**
267  * Returns whether this matrix is the identity matrix.
268  * @return True, if so
269  */
270  inline bool isIdentity() const;
271 
272  /**
273  * Returns whether this matrix is singular (and thus cannot be inverted).
274  * A matrix is singular if the determinant of a matrix is 0.<br>
275  * @return True, if so
276  */
277  inline bool isSingular() const;
278 
279  /**
280  * Returns whether this matrix is symmetric.
281  * @param epsilon The epsilon threshold to be used, with range [0, infinity)
282  * @return True, if so
283  */
284  bool isSymmetric(const T epsilon = NumericT<T>::eps()) const;
285 
286  /**
287  * Returns whether two matrices are almost identical up to a specified epsilon.
288  * @param matrix Second matrix that will be checked
289  * @param eps The epsilon threshold to be used, with range [0, infinity)
290  * @return True, if so
291  */
292  inline bool isEqual(const SquareMatrixT2<T>& matrix, const T eps = NumericT<T>::eps()) const;
293 
294  /**
295  * Performs an eigen value analysis.
296  * @param eigenValue0 First eigen value
297  * @param eigenValue1 Second eigen value
298  * @param eigenVector0 First eigen vector
299  * @param eigenVector1 Second eigen vector
300  * @return True, if succeeded
301  */
302  bool eigenSystem(T& eigenValue0, T& eigenValue1, VectorT2<T>& eigenVector0, VectorT2<T>& eigenVector1) const;
303 
304  /**
305  * Returns a pointer to the internal values.
306  * @return Pointer to the internal values
307  */
308  inline const T* data() const;
309 
310  /**
311  * Returns a pointer to the internal values.
312  * @return Pointer to the internal values
313  */
314  inline T* data();
315 
316  /**
317  * Copies the elements of this matrix to an array with floating point values of type U.
318  * @param arrayValues Array with 4 floating point values of type U receiving the elements of this matrix
319  * @param columnAligned True, if the target elements are column aligned, false to target row aligned elements
320  * @tparam U Floating point type
321  */
322  template <typename U>
323  inline void copyElements(U* arrayValues, const bool columnAligned = true) const;
324 
325  /**
326  * Copies the elements of this matrix to an array with floating point values of type T.
327  * @param arrayValues Array with 4 floating point values of type T receiving the elements of this matrix
328  * @param columnAligned True, if the target elements are column aligned, false to target row aligned elements
329  */
330  inline void copyElements(T* arrayValues, const bool columnAligned = true) const;
331 
332  /**
333  * Default copy assignment operator.
334  * @return Reference to this object
335  */
337 
338  /**
339  * Returns whether two matrices are identical up to a small epsilon.
340  * @param matrix Right operand
341  * @return True, if so
342  */
343  inline bool operator==(const SquareMatrixT2<T>& matrix) const;
344 
345  /**
346  * Returns whether two matrices are not identical up to a small epsilon.
347  * @param matrix Right operand
348  * @return True, if so
349  */
350  inline bool operator!=(const SquareMatrixT2<T>& matrix) const;
351 
352  /**
353  * Adds two matrices.
354  * @param matrix Right operand
355  * @return Sum matrix
356  */
357  inline SquareMatrixT2<T> operator+(const SquareMatrixT2<T>& matrix) const;
358 
359  /**
360  * Adds and assigns two matrices.
361  * @param matrix Right operand
362  * @return Reference to this object
363  */
364  inline SquareMatrixT2<T>& operator+=(const SquareMatrixT2<T>& matrix);
365 
366  /**
367  * Subtracts two matrices.
368  * @param matrix Right operand
369  * @return Difference matrix
370  */
371  inline SquareMatrixT2<T> operator-(const SquareMatrixT2<T>& matrix) const;
372 
373  /**
374  * Subtracts and assigns two matrices.
375  * @param matrix Right operand
376  * @return Reference to this object
377  */
378  inline SquareMatrixT2<T>& operator-=(const SquareMatrixT2<T>& matrix);
379 
380  /**
381  * Returns the negative matrix of this matrix (all matrix elements are multiplied by -1).
382  * @return Resulting negative matrix
383  */
384  inline SquareMatrixT2<T> operator-() const;
385 
386  /**
387  * Multiplies two matrices.
388  * @param matrix Right operand
389  * @return Product matrix
390  */
391  inline SquareMatrixT2<T> operator*(const SquareMatrixT2<T>& matrix) const;
392 
393  /**
394  * Multiplies and assigns two matrices.
395  * @param matrix Right operand
396  * @return Reference to this object
397  */
398  inline SquareMatrixT2<T>& operator*=(const SquareMatrixT2<T>& matrix);
399 
400  /**
401  * Multiply operator for a 2D vector.
402  * @param vector Right operand
403  * @return Resulting 2D vector
404  */
405  inline VectorT2<T> operator*(const VectorT2<T>& vector) const;
406 
407  /**
408  * Multiplies this matrix with a scalar value.
409  * @param value Right operand
410  * @return Resulting matrix
411  */
412  inline SquareMatrixT2<T> operator*(const T value) const;
413 
414  /**
415  * Multiplies and assigns this matrix with a scalar value.
416  * @param value right operand
417  * @return Reference to this object
418  */
419  inline SquareMatrixT2<T>& operator*=(const T value);
420 
421  /**
422  * Element operator.
423  * Beware: No range check will be done!
424  * @param index Index of the element to return [0, 4]
425  * @return Specified element
426  */
427  inline T operator[](const unsigned int index) const;
428 
429  /**
430  * Element operator.
431  * Beware: No range check will be done!
432  * @param index Index of the element to return [0, 4]
433  * @return Specified element
434  */
435  inline T& operator[](const unsigned int index);
436 
437  /**
438  * Element operator.
439  * Beware: No range check will be done!
440  * @param row Row of the element to return [0, 1]
441  * @param column Column of the element to return [0, 1]
442  * @return Specified element
443  */
444  inline T operator()(const unsigned int row, const unsigned int column) const;
445 
446  /**
447  * Element operator.
448  * Beware: No range check will be done!
449  * @param row Row of the element to return [0, 1]
450  * @param column Column of the element to return [0, 1]
451  * @return Specified element
452  */
453  inline T& operator()(const unsigned int row, const unsigned int column);
454 
455  /**
456  * Element operator.
457  * Beware: No range check will be done!
458  * @param index Index of the element to return [0, 8]
459  * @return Specified element
460  */
461  inline T operator()(const unsigned int index) const;
462 
463  /**
464  * Element operator.
465  * Beware: No range check will be done!
466  * @param index Index of the element to return [0, 8]
467  * @return Specified element
468  */
469  inline T& operator()(const unsigned int index);
470 
471  /**
472  * Access operator.
473  * @return Pointer to the internal values
474  */
475  inline const T* operator()() const;
476 
477  /**
478  * Access operator.
479  * @return Pointer to the internal values
480  */
481  inline T* operator()();
482 
483  /**
484  * Hash function.
485  * @param matrix The matrix for which the hash value will be determined
486  * @return The resulting hash value
487  */
488  inline size_t operator()(const SquareMatrixT2<T>& matrix) const;
489 
490  /**
491  * Returns the number of elements this matrix has.
492  * @return The number of elements, always 4
493  */
494  static inline size_t elements();
495 
496  /**
497  * Converts matrices with specific data type to matrices with different data type.
498  * @param matrices The matrices to convert
499  * @return The converted matrices
500  * @tparam U The element data type of the matrices to convert
501  */
502  template <typename U>
503  static inline std::vector< SquareMatrixT2<T> > matrices2matrices(const std::vector< SquareMatrixT2<U> >& matrices);
504 
505  /**
506  * Converts matrices with specific data type to matrices with different data type.
507  * @param matrices The matrices to convert
508  * @param size The number of matrices to convert
509  * @return The converted matrices
510  * @tparam U The element data type of the matrices to convert
511  */
512  template <typename U>
513  static inline std::vector< SquareMatrixT2<T> > matrices2matrices(const SquareMatrixT2<U>* matrices, const size_t size);
514 
515  protected:
516 
517  /// The four values of the matrix.
518  T values[4];
519 };
520 
521 template <typename T>
523 {
524  // nothing to do here
525 }
526 
527 template <typename T>
528 template <typename U>
530 {
531  values[0] = T(matrix.values[0]);
532  values[1] = T(matrix.values[1]);
533  values[2] = T(matrix.values[2]);
534  values[3] = T(matrix.values[3]);
535 }
536 
537 template <typename T>
538 inline SquareMatrixT2<T>::SquareMatrixT2(const bool setToIdentity)
539 {
540  if (setToIdentity)
541  {
542  values[0] = T(1.0);
543  values[1] = T(0.0);
544  values[2] = T(0.0);
545  values[3] = T(1.0);
546  }
547  else
548  {
549  values[0] = T(0.0);
550  values[1] = T(0.0);
551  values[2] = T(0.0);
552  values[3] = T(0.0);
553  }
554 }
555 
556 template <typename T>
558 {
559  values[0] = diagonal[0];
560  values[1] = T(0.0);
561  values[2] = T(0.0);
562  values[3] = diagonal[1];
563 }
564 
565 template <typename T>
566 template <typename U>
568 {
569  ocean_assert(arrayValues);
570 
571  for (unsigned int n = 0u; n < 4u; ++n)
572  {
573  values[n] = T(arrayValues[n]);
574  }
575 }
576 
577 template <typename T>
579 {
580  ocean_assert(arrayValues);
581  memcpy(values, arrayValues, sizeof(T) * 4);
582 }
583 
584 template <typename T>
585 template <typename U>
586 SquareMatrixT2<T>::SquareMatrixT2(const U* arrayValues, const bool valuesRowAligned)
587 {
588  ocean_assert(arrayValues);
589 
590  if (valuesRowAligned)
591  {
592  values[0] = T(arrayValues[0]);
593  values[1] = T(arrayValues[2]);
594  values[2] = T(arrayValues[1]);
595  values[3] = T(arrayValues[3]);
596 
597  }
598  else
599  {
600  for (unsigned int n = 0u; n < 4u; ++n)
601  values[n] = T(arrayValues[n]);
602  }
603 }
604 
605 template <typename T>
606 SquareMatrixT2<T>::SquareMatrixT2(const T* arrayValues, const bool valuesRowAligned)
607 {
608  ocean_assert(arrayValues);
609 
610  if (valuesRowAligned)
611  {
612  values[0] = arrayValues[0];
613  values[1] = arrayValues[2];
614  values[2] = arrayValues[1];
615  values[3] = arrayValues[3];
616  }
617  else
618  {
619  memcpy(values, arrayValues, sizeof(T) * 4);
620  }
621 }
622 
623 template <typename T>
624 inline SquareMatrixT2<T>::SquareMatrixT2(const T& m00, const T& m10, const T& m01, const T& m11)
625 {
626  values[0] = m00;
627  values[1] = m10;
628 
629  values[2] = m01;
630  values[3] = m11;
631 }
632 
633 template <typename T>
634 SquareMatrixT2<T>::SquareMatrixT2(const T eigenValue0, const T eigenValue1, const VectorT2<T>& eigenVector0, const VectorT2<T>& eigenVector1)
635 {
636  ocean_assert(NumericT<T>::isEqual(eigenVector0.length(), T(1.0)));
637  ocean_assert(NumericT<T>::isEqual(eigenVector1.length(), T(1.0)));
638 
639  const T det = eigenVector0.x() * eigenVector1.y() - eigenVector1.x() * eigenVector0.y();
640  ocean_assert(NumericT<T>::isNotEqualEps(det));
641 
642  values[0] = (eigenVector0.x() * eigenValue0 * eigenVector1.y() - eigenVector0.y() * eigenValue1 * eigenVector1.x()) / det;
643  values[1] = (eigenValue0 - eigenValue1) * eigenVector0.y() * eigenVector1.y() / det;
644  values[2] = (eigenValue1 - eigenValue0) * eigenVector0.x() * eigenVector1.x() / det;
645  values[3] = (eigenVector0.x() * eigenValue1 * eigenVector1.y() - eigenVector0.y() * eigenValue0 * eigenVector1.x()) / det;
646 
647 #ifdef OCEAN_DEBUG
648  if (!std::is_same<Scalar, float>::value)
649  {
650  T debugEigenValue0, debugEigenValue1;
651  VectorT2<T> debugEigenVector0, debugEigenVector1;
652  ocean_assert(eigenSystem(debugEigenValue0, debugEigenValue1, debugEigenVector0, debugEigenVector1));
653 
654  ocean_assert(NumericT<T>::isEqual(debugEigenValue0, eigenValue0, NumericT<T>::eps() * 10));
655  ocean_assert(NumericT<T>::isEqual(debugEigenValue1, eigenValue1, NumericT<T>::eps() * 10));
656  ocean_assert(debugEigenVector0.isEqual(eigenVector0, NumericT<T>::weakEps() * 10) || debugEigenVector0.isEqual(-eigenVector0, NumericT<T>::weakEps() * 10));
657  ocean_assert(debugEigenVector1.isEqual(eigenVector1, NumericT<T>::weakEps() * 10) || debugEigenVector1.isEqual(-eigenVector1, NumericT<T>::weakEps() * 10));
658  }
659 #endif // OCEAN_DEBUG
660 }
661 
662 template <typename T>
664 {
665  return SquareMatrixT2<T>(values[0], values[2], values[1], values[3]);
666 }
667 
668 template <typename T>
670 {
671  const T tmp = values[1];
672  values[1] = values[2];
673  values[2] = tmp;
674 }
675 
676 template <typename T>
678 {
679  SquareMatrixT2<T> result;
680 
681  if (!invert(result))
682  {
683  ocean_assert(false && "Could not invert the matrix.");
684  return *this;
685  }
686 
687  return result;
688 }
689 
690 template <typename T>
692 {
693  const T det = determinant();
694  if (NumericT<T>::isEqualEps(det))
695  {
696  return false;
697  }
698 
699  const T factor = T(1.0) / det;
700 
701  *this = SquareMatrixT2<T>(values[3] * factor, -values[1] * factor, -values[2] * factor, values[0] * factor);
702 
703  return true;
704 }
705 
706 template <typename T>
707 inline bool SquareMatrixT2<T>::invert(SquareMatrixT2<T>& invertedMatrix) const
708 {
709  const T det = determinant();
710  if (NumericT<T>::isEqualEps(det))
711  {
712  return false;
713  }
714 
715  const T factor = T(1.0) / det;
716 
717  invertedMatrix = SquareMatrixT2<T>(values[3] * factor, -values[1] * factor, -values[2] * factor, values[0] * factor);
718 
719 #ifdef OCEAN_INTENSIVE_DEBUG
720  if (!std::is_same<T, float>::value)
721  {
722  const SquareMatrixT2<T> test(*this * invertedMatrix);
723  const SquareMatrixT2<T> entity(true);
724 
725  T sqrDistance = T(0);
726  for (unsigned int n = 0; n < 4u; ++n)
727  sqrDistance += NumericT<T>::sqr(test[n] - entity[n]);
728  const T distance = NumericT<T>::sqrt(sqrDistance * T(0.25));
729 
730  if (NumericT<T>::isWeakEqualEps(distance) == false)
731  {
732  T absolusteAverageEnergy = 0;
733  for (unsigned int n = 0u; n < 4u; ++n)
734  absolusteAverageEnergy += NumericT<T>::abs(values[n]);
735  absolusteAverageEnergy *= T(0.25);
736 
737  // we expect/accept for each magnitude (larger than 1) a zero-inaccuracy of one magnitude (and we again comare it with the weak eps)
738 
739  if (absolusteAverageEnergy <= 1)
740  ocean_assert_accuracy(!"This should never happen!");
741  else
742  {
743  const T adjustedDistance = distance / absolusteAverageEnergy;
744  ocean_assert_accuracy(NumericT<T>::isWeakEqualEps(adjustedDistance));
745  }
746  }
747  }
748 #endif // OCEAN_DEBUG
749 
750  return true;
751 }
752 
753 template <typename T>
755 {
756  return values[0] * values[3] - values[1] * values[2];
757 }
758 
759 template <typename T>
760 inline T SquareMatrixT2<T>::trace() const
761 {
762  return values[0] + values[3];
763 }
764 
765 template <typename T>
766 inline bool SquareMatrixT2<T>::solve(const VectorT2<T>& b, VectorT2<T>& x) const
767 {
768  // Solve this system of linear equations using the good ol' Gauss elimination
769  //
770  // Step 0:
771  // |a0 a2| |x0| |b0|
772  // |a1 a3| x |x1| = |b1|
773  //
774  //
775  // Step 1:
776  // |a0 a2| |x0| |b0|
777  // |0 u0| x |x1| = |v0| <- (row1 * a0) - (row0 * a1)
778  //
779  const T u0 = (values[0] * values[3]) - (values[1] * values[2]);
780  const T v0 = (values[0] * b[1]) - (values[1] * b[0]);
781 
782  // x1 = v0 / u0
783 
785  {
786  x[1] = v0 / u0;
787  x[0] = (b[0] - (values[2] * x[1])) / values[0];
788 
789  return true;
790  }
791 
792  return false;
793 }
794 
795 template <typename T>
797 {
798  values[0] = T(1.0);
799  values[1] = T(0.0);
800  values[2] = T(0.0);
801  values[3] = T(1.0);
802 }
803 
804 template <typename T>
806 {
807  values[0] = T(0.0);
808  values[1] = T(0.0);
809  values[2] = T(0.0);
810  values[3] = T(0.0);
811 }
812 
813 template <typename T>
815 {
816  return VectorT2<T>(values[0], values[1]);
817 }
818 
819 template <typename T>
821 {
822  return VectorT2<T>(values[2], values[3]);
823 }
824 
825 template <typename T>
827 {
828  return VectorT2<T>(values[0], values[3]);
829 }
830 
831 template <typename T>
832 inline T SquareMatrixT2<T>::norm() const
833 {
834  return NumericT<T>::abs(values[0]) + NumericT<T>::abs(values[1]) + NumericT<T>::abs(values[2]) + NumericT<T>::abs(values[3]);
835 }
836 
837 template <typename T>
838 inline bool SquareMatrixT2<T>::isNull() const
839 {
840  return NumericT<T>::isEqualEps(values[0]) && NumericT<T>::isEqualEps(values[1]) && NumericT<T>::isEqualEps(values[2]) && NumericT<T>::isEqualEps(values[3]);
841 }
842 
843 template <typename T>
844 inline bool SquareMatrixT2<T>::isIdentity() const
845 {
846  return NumericT<T>::isEqual(values[0], 1) && NumericT<T>::isEqualEps(values[1]) && NumericT<T>::isEqualEps(values[2]) && NumericT<T>::isEqual(values[3], 1);
847 }
848 
849 template <typename T>
850 inline bool SquareMatrixT2<T>::isSingular() const
851 {
852  return NumericT<T>::isEqualEps(determinant());
853 }
854 
855 template <typename T>
856 inline bool SquareMatrixT2<T>::isSymmetric(const T epsilon) const
857 {
858  ocean_assert(epsilon >= T(0));
859 
860  return NumericT<T>::isEqual(values[1], values[2], epsilon);
861 }
862 
863 template <typename T>
864 inline bool SquareMatrixT2<T>::isEqual(const SquareMatrixT2<T>& matrix, const T eps) const
865 {
866  return NumericT<T>::isEqual(values[0], matrix.values[0], eps) && NumericT<T>::isEqual(values[1], matrix.values[1], eps)
867  && NumericT<T>::isEqual(values[2], matrix.values[2], eps) && NumericT<T>::isEqual(values[3], matrix.values[3], eps);
868 }
869 
870 template <typename T>
871 inline const T* SquareMatrixT2<T>::data() const
872 {
873  return values;
874 }
875 
876 template <typename T>
878 {
879  return values;
880 }
881 
882 template <typename T>
883 template <typename U>
884 inline void SquareMatrixT2<T>::copyElements(U* arrayValues, const bool columnAligned) const
885 {
886  ocean_assert(arrayValues);
887 
888  if (columnAligned)
889  {
890  arrayValues[0] = U(values[0]);
891  arrayValues[1] = U(values[1]);
892  arrayValues[2] = U(values[2]);
893  arrayValues[3] = U(values[3]);
894  }
895  else
896  {
897  arrayValues[0] = U(values[0]);
898  arrayValues[1] = U(values[2]);
899  arrayValues[2] = U(values[1]);
900  arrayValues[3] = U(values[3]);
901  }
902 }
903 
904 template <typename T>
905 inline void SquareMatrixT2<T>::copyElements(T* arrayValues, const bool columnAligned) const
906 {
907  ocean_assert(arrayValues);
908 
909  if (columnAligned)
910  {
911  arrayValues[0] = values[0];
912  arrayValues[1] = values[1];
913  arrayValues[2] = values[2];
914  arrayValues[3] = values[3];
915  }
916  else
917  {
918  arrayValues[0] = values[0];
919  arrayValues[1] = values[2];
920  arrayValues[2] = values[1];
921  arrayValues[3] = values[3];
922  }
923 }
924 
925 template <typename T>
926 inline bool SquareMatrixT2<T>::operator==(const SquareMatrixT2<T>& matrix) const
927 {
928  return isEqual(matrix);
929 }
930 
931 template <typename T>
932 inline bool SquareMatrixT2<T>::operator!=(const SquareMatrixT2<T>& matrix) const
933 {
934  return !(*this == matrix);
935 }
936 
937 template <typename T>
939 {
940  return SquareMatrixT2<T>(values[0] + matrix.values[0], values[1] + matrix.values[1], values[2] + matrix.values[2], values[3] + matrix.values[3]);
941 }
942 
943 template <typename T>
945 {
946  values[0] += matrix.values[0];
947  values[1] += matrix.values[1];
948  values[2] += matrix.values[2];
949  values[3] += matrix.values[3];
950 
951  return *this;
952 }
953 
954 template <typename T>
956 {
957  return SquareMatrixT2<T>(values[0] - matrix.values[0], values[1] - matrix.values[1], values[2] - matrix.values[2], values[3] - matrix.values[3]);
958 }
959 
960 template <typename T>
962 {
963  values[0] -= matrix.values[0];
964  values[1] -= matrix.values[1];
965  values[2] -= matrix.values[2];
966  values[3] -= matrix.values[3];
967 
968  return *this;
969 }
970 
971 template <typename T>
973 {
974  SquareMatrixT2<T> result;
975 
976  result.values[ 0] = -values[ 0];
977  result.values[ 1] = -values[ 1];
978  result.values[ 2] = -values[ 2];
979  result.values[ 3] = -values[ 3];
980 
981  return result;
982 }
983 
984 template <typename T>
986 {
987  return SquareMatrixT2<T>(values[0] * matrix.values[0] + values[2] * matrix.values[1],
988  values[1] * matrix.values[0] + values[3] * matrix.values[1],
989  values[0] * matrix.values[2] + values[2] * matrix.values[3],
990  values[1] * matrix.values[2] + values[3] * matrix.values[3]);
991 }
992 
993 template <typename T>
995 {
996  *this = *this * matrix;
997  return *this;
998 }
999 
1000 template <typename T>
1002 {
1003  return VectorT2<T>(values[0] * vector[0] + values[2] * vector[1],
1004  values[1] * vector[0] + values[3] * vector[1]);
1005 }
1006 
1007 template <typename T>
1009 {
1010  return SquareMatrixT2<T>(values[0] * value, values[1] * value, values[2] * value, values[3] * value);
1011 }
1012 
1013 template <typename T>
1015 {
1016  values[0] *= value;
1017  values[1] *= value;
1018  values[2] *= value;
1019  values[3] *= value;
1020 
1021  return *this;
1022 }
1023 
1024 template <typename T>
1025 inline T SquareMatrixT2<T>::operator[](const unsigned int index) const
1026 {
1027  ocean_assert(index < 4u);
1028  return values[index];
1029 }
1030 
1031 template <typename T>
1032 inline T& SquareMatrixT2<T>::operator[](const unsigned int index)
1033 {
1034  ocean_assert(index < 4u);
1035  return values[index];
1036 }
1037 
1038 template <typename T>
1039 inline T SquareMatrixT2<T>::operator()(const unsigned int row, const unsigned int column) const
1040 {
1041  ocean_assert(row < 2u && column < 2u);
1042  return values[column * 2u + row];
1043 }
1044 
1045 template <typename T>
1046 inline T& SquareMatrixT2<T>::operator()(const unsigned int row, const unsigned int column)
1047 {
1048  ocean_assert(row < 2u && column < 2u);
1049  return values[column * 2u + row];
1050 }
1051 
1052 template <typename T>
1053 inline T SquareMatrixT2<T>::operator()(const unsigned int index) const
1054 {
1055  ocean_assert(index < 4u);
1056  return values[index];
1057 }
1058 
1059 template <typename T>
1060 inline T& SquareMatrixT2<T>::operator()(const unsigned int index)
1061 {
1062  ocean_assert(index < 4u);
1063  return values[index];
1064 }
1065 
1066 template <typename T>
1067 inline const T* SquareMatrixT2<T>::operator()() const
1068 {
1069  return values;
1070 }
1071 
1072 template <typename T>
1074 {
1075  return values;
1076 }
1077 
1078 template <typename T>
1079 inline size_t SquareMatrixT2<T>::operator()(const SquareMatrixT2<T>& matrix) const
1080 {
1081  size_t seed = std::hash<T>{}(matrix.values[0]);
1082 
1083  for (unsigned int n = 1u; n < 4u; ++n)
1084  {
1085  seed ^= std::hash<T>{}(matrix.values[n]) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1086  }
1087 
1088  return seed;
1089 }
1090 
1091 template <typename T>
1093 {
1094  return 4;
1095 }
1096 
1097 template <typename T>
1098 bool SquareMatrixT2<T>::eigenSystem(T& eigenValue0, T& eigenValue1, VectorT2<T>& eigenVector0, VectorT2<T>& eigenVector1) const
1099 {
1100  if (isNull())
1101  {
1102  return false;
1103  }
1104 
1105  const T tr = trace();
1106  const T det = determinant();
1107 
1108  if (!EquationT<T>::solveQuadratic(T(1.0), -tr, det, eigenValue0, eigenValue1))
1109  {
1110  return false;
1111  }
1112 
1113  if (eigenValue0 < eigenValue1)
1114  {
1115  std::swap(eigenValue0, eigenValue1);
1116  }
1117 
1118  if (NumericT<T>::isNotEqualEps(values[2]))
1119  {
1120  const T factor = T(1.0) / values[2];
1121  eigenVector0 = VectorT2<T>(1, (eigenValue0 - values[0]) * factor);
1122  eigenVector1 = VectorT2<T>(1, (eigenValue1 - values[0]) * factor);
1123  }
1124  else if (NumericT<T>::isNotEqualEps(values[1]))
1125  {
1126  const T factor = T(1.0) / values[1];
1127 
1128  eigenVector0 = VectorT2<T>((eigenValue0 - values[3]) * factor, T(1.0));
1129  eigenVector1 = VectorT2<T>((eigenValue1 - values[3]) * factor, T(1.0));
1130  }
1131  else
1132  {
1133  if (NumericT<T>::isNotEqual(eigenValue0, values[3]))
1134  {
1135  eigenVector0 = VectorT2<T>(1, values[1] / (eigenValue0 - values[3]));
1136  }
1137  else
1138  {
1139  if (NumericT<T>::isEqual(eigenValue0, values[0]))
1140  {
1141  eigenVector0 = VectorT2<T>(1, 0);
1142  }
1143  else
1144  {
1145  eigenVector0 = VectorT2<T>(values[2] / (eigenValue0 - values[0]), T(1.0));
1146  }
1147  }
1148 
1149  if (NumericT<T>::isNotEqual(values[3], eigenValue1))
1150  {
1151  eigenVector1 = VectorT2<T>(1, values[1] / (eigenValue1 - values[3]));
1152  }
1153  else
1154  {
1155  if (NumericT<T>::isEqual(eigenValue1, values[0]))
1156  {
1157  eigenVector1 = VectorT2<T>(0, 1);
1158  }
1159  else
1160  {
1161  eigenVector1 = VectorT2<T>(values[2] / (eigenValue1 - values[0]), T(1.0));
1162  }
1163  }
1164  }
1165 
1166  eigenVector0.normalize();
1167  eigenVector1.normalize();
1168 
1169  ocean_assert((std::is_same<T, float>::value) || (*this * eigenVector0).isEqual(eigenVector0 * eigenValue0, NumericT<T>::weakEps()));
1170  ocean_assert((std::is_same<T, float>::value) || (*this * eigenVector1).isEqual(eigenVector1 * eigenValue1, NumericT<T>::weakEps()));
1171 
1172  return true;
1173 }
1174 
1175 template <typename T>
1176 template <typename U>
1177 inline std::vector< SquareMatrixT2<T> > SquareMatrixT2<T>::matrices2matrices(const std::vector< SquareMatrixT2<U> >& matrices)
1178 {
1179  std::vector< SquareMatrixT2<T> > result;
1180  result.reserve(matrices.size());
1181 
1182  for (typename std::vector< SquareMatrixT2<U> >::const_iterator i = matrices.begin(); i != matrices.end(); ++i)
1183  {
1184  result.push_back(SquareMatrixT2<T>(*i));
1185  }
1186 
1187  return result;
1188 }
1189 
1190 template <>
1191 template <>
1192 inline std::vector< SquareMatrixT2<float> > SquareMatrixT2<float>::matrices2matrices(const std::vector< SquareMatrixT2<float> >& matrices)
1193 {
1194  return matrices;
1195 }
1196 
1197 template <>
1198 template <>
1199 inline std::vector< SquareMatrixT2<double> > SquareMatrixT2<double>::matrices2matrices(const std::vector< SquareMatrixT2<double> >& matrices)
1200 {
1201  return matrices;
1202 }
1203 
1204 template <typename T>
1205 template <typename U>
1206 inline std::vector< SquareMatrixT2<T> > SquareMatrixT2<T>::matrices2matrices(const SquareMatrixT2<U>* matrices, const size_t size)
1207 {
1208  std::vector< SquareMatrixT2<T> > result;
1209  result.reserve(size);
1210 
1211  for (size_t n = 0; n < size; ++n)
1212  {
1213  result.push_back(SquareMatrixT2<T>(matrices[n]));
1214  }
1215 
1216  return result;
1217 }
1218 
1219 template <typename T>
1220 std::ostream& operator<<(std::ostream& stream, const SquareMatrixT2<T>& matrix)
1221 {
1222  stream << "|" << matrix(0, 0) << ", " << matrix(0, 1) << "|" << std::endl;
1223  stream << "|" << matrix(1, 0) << ", " << matrix(1, 1) << "|";
1224 
1225  return stream;
1226 }
1227 
1228 template <bool tActive, typename T>
1229 MessageObject<tActive>& operator<<(MessageObject<tActive>& messageObject, const SquareMatrixT2<T>& matrix)
1230 {
1231  return messageObject << "|" << matrix(0, 0) << ", " << matrix(0, 1) << "|\n|" << matrix(1, 0) << ", " << matrix(1, 1) << "|";
1232 }
1233 
1234 template <bool tActive, typename T>
1235 MessageObject<tActive>& operator<<(MessageObject<tActive>&& messageObject, const SquareMatrixT2<T>& matrix)
1236 {
1237  return messageObject << "|" << matrix(0, 0) << ", " << matrix(0, 1) << "|\n|" << matrix(1, 0) << ", " << matrix(1, 1) << "|";
1238 }
1239 
1240 }
1241 
1242 #endif // META_OCEAN_MATH_SQUARE_MATRIX_2_H
This class provides several functions to solve equations with different degree using floating point v...
Definition: Equation.h:53
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static T abs(const T value)
Returns the absolute value of a given value.
Definition: Numeric.h:1220
static T sqrt(const T value)
Returns the square root of a given value.
Definition: Numeric.h:1533
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition: Numeric.h:2386
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition: Numeric.h:2087
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition: Numeric.h:2237
This class implements a 2x2 square matrix.
Definition: SquareMatrix2.h:73
static size_t elements()
Returns the number of elements this matrix has.
Definition: SquareMatrix2.h:1092
bool isIdentity() const
Returns whether this matrix is the identity matrix.
Definition: SquareMatrix2.h:844
bool isSingular() const
Returns whether this matrix is singular (and thus cannot be inverted).
Definition: SquareMatrix2.h:850
SquareMatrixT2< T > & operator+=(const SquareMatrixT2< T > &matrix)
Adds and assigns two matrices.
Definition: SquareMatrix2.h:944
T norm() const
Returns the norm of this matrix that is the sum of the absolute matrix elements.
Definition: SquareMatrix2.h:832
VectorT2< T > xAxis() const
Returns the x axis which is the first column of the matrix.
Definition: SquareMatrix2.h:814
SquareMatrixT2< T > transposed() const
Returns the transposed of this matrix.
Definition: SquareMatrix2.h:663
bool operator!=(const SquareMatrixT2< T > &matrix) const
Returns whether two matrices are not identical up to a small epsilon.
Definition: SquareMatrix2.h:932
static std::vector< SquareMatrixT2< T > > matrices2matrices(const std::vector< SquareMatrixT2< U > > &matrices)
Converts matrices with specific data type to matrices with different data type.
Definition: SquareMatrix2.h:1177
bool isEqual(const SquareMatrixT2< T > &matrix, const T eps=NumericT< T >::eps()) const
Returns whether two matrices are almost identical up to a specified epsilon.
Definition: SquareMatrix2.h:864
SquareMatrixT2< T > & operator=(const SquareMatrixT2< T > &)=default
Default copy assignment operator.
T operator[](const unsigned int index) const
Element operator.
Definition: SquareMatrix2.h:1025
bool isNull() const
Returns whether this matrix is a null matrix.
Definition: SquareMatrix2.h:838
friend class SquareMatrixT2
Definition: SquareMatrix2.h:74
VectorT2< T > yAxis() const
Returns the y axis which is the middle column of the matrix.
Definition: SquareMatrix2.h:820
T trace() const
Returns the trace of the matrix which is the sum of the diagonal elements.
Definition: SquareMatrix2.h:760
bool operator==(const SquareMatrixT2< T > &matrix) const
Returns whether two matrices are identical up to a small epsilon.
Definition: SquareMatrix2.h:926
bool solve(const VectorT2< T > &b, VectorT2< T > &x) const
Solve a simple 2x2 system of linear equations: Ax = b Beware: The system of linear equations is assum...
Definition: SquareMatrix2.h:766
void toIdentity()
Sets the matrix to the identity matrix.
Definition: SquareMatrix2.h:796
SquareMatrixT2< T > operator*(const SquareMatrixT2< T > &matrix) const
Multiplies two matrices.
Definition: SquareMatrix2.h:985
SquareMatrixT2< T > inverted() const
Returns the inverted matrix of this matrix.
Definition: SquareMatrix2.h:677
const T * data() const
Returns a pointer to the internal values.
Definition: SquareMatrix2.h:871
SquareMatrixT2< T > & operator-=(const SquareMatrixT2< T > &matrix)
Subtracts and assigns two matrices.
Definition: SquareMatrix2.h:961
bool isSymmetric(const T epsilon=NumericT< T >::eps()) const
Returns whether this matrix is symmetric.
Definition: SquareMatrix2.h:856
T determinant() const
Returns the determinant of the matrix.
Definition: SquareMatrix2.h:754
T values[4]
The four values of the matrix.
Definition: SquareMatrix2.h:518
T Type
Definition of the used data type.
Definition: SquareMatrix2.h:81
SquareMatrixT2< T > operator-() const
Returns the negative matrix of this matrix (all matrix elements are multiplied by -1).
Definition: SquareMatrix2.h:972
bool invert()
Inverts this matrix in place.
Definition: SquareMatrix2.h:691
void copyElements(U *arrayValues, const bool columnAligned=true) const
Copies the elements of this matrix to an array with floating point values of type U.
Definition: SquareMatrix2.h:884
SquareMatrixT2< T > operator+(const SquareMatrixT2< T > &matrix) const
Adds two matrices.
Definition: SquareMatrix2.h:938
SquareMatrixT2(const SquareMatrixT2< T > &matrix)=default
Copy constructor.
void transpose()
Transposes the matrix.
Definition: SquareMatrix2.h:669
VectorT2< T > diagonal() const
Returns a 2D vector with values of the matrix diagonal.
Definition: SquareMatrix2.h:826
const T * operator()() const
Access operator.
Definition: SquareMatrix2.h:1067
SquareMatrixT2< T > & operator*=(const SquareMatrixT2< T > &matrix)
Multiplies and assigns two matrices.
Definition: SquareMatrix2.h:994
bool eigenSystem(T &eigenValue0, T &eigenValue1, VectorT2< T > &eigenVector0, VectorT2< T > &eigenVector1) const
Performs an eigen value analysis.
Definition: SquareMatrix2.h:1098
void toNull()
Sets the matrix to a zero matrix.
Definition: SquareMatrix2.h:805
This class implements a vector with two elements.
Definition: Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
bool isEqual(const VectorT2< T > &vector, const T eps) const
Returns whether two vectors are equal up to a specified epsilon.
Definition: Vector2.h:746
T length() const
Returns the length of the vector.
Definition: Vector2.h:615
bool normalize()
Normalizes this vector.
Definition: Vector2.h:600
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition: base/Utilities.h:1089
std::vector< SquareMatrixT2< T > > SquareMatricesT2
Definition of a typename alias for vectors with SquareMatrixT2 objects.
Definition: SquareMatrix2.h:51
SquareMatrixT2< float > SquareMatrixF2
Instantiation of the SquareMatrixT2 template class using a single precision float data type.
Definition: SquareMatrix2.h:43
SquareMatrixT2< Scalar > SquareMatrix2
Definition of the SquareMatrix2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with ...
Definition: SquareMatrix2.h:22
SquareMatrixT2< double > SquareMatrixD2
Instantiation of the SquareMatrixT2 template class using a double precision float data type.
Definition: SquareMatrix2.h:36
std::vector< SquareMatrix2 > SquareMatrices2
Definition of a vector holding SquareMatrix2 objects.
Definition: SquareMatrix2.h:58
OCEAN_TEST_TRACKING_OCULUSTAGS_EXPORT bool test(const double testDuration, Worker &worker, const std::string &testFunctions=std::string())
Tests the entire tracking Oculus Tags library.
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15
std::ostream & operator<<(std::ostream &stream, const HighPerformanceStatistic &highPerformanceStatistic)
Definition: HighPerformanceTimer.h:963