Ocean
Loading...
Searching...
No Matches
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
18namespace Ocean
19{
20
21// Forward declaration.
22template <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 */
50template <typename T>
51using SquareMatricesT2 = std::vector<SquareMatrixT2<T>>;
52
53/**
54 * Definition of a vector holding SquareMatrix2 objects.
55 * @see SquareMatrix2
56 * @ingroup math
57 */
58using SquareMatrices2 = std::vector<SquareMatrix2>;
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 */
71template <typename T>
73{
74 template <typename U> friend class SquareMatrixT2;
75
76 public:
77
78 /**
79 * Definition of the used data type.
80 */
81 using Type = T;
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.
519};
520
521template <typename T>
523{
524 // nothing to do here
525}
526
527template <typename T>
528template <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
537template <typename T>
538inline 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
556template <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
565template <typename T>
566template <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
577template <typename T>
579{
580 ocean_assert(arrayValues);
581 memcpy(values_, arrayValues, sizeof(T) * 4);
582}
583
584template <typename T>
585template <typename U>
586SquareMatrixT2<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 {
602 values_[n] = T(arrayValues[n]);
603 }
604 }
605}
606
607template <typename T>
608SquareMatrixT2<T>::SquareMatrixT2(const T* arrayValues, const bool valuesRowAligned)
609{
610 ocean_assert(arrayValues);
611
612 if (valuesRowAligned)
613 {
614 values_[0] = arrayValues[0];
615 values_[1] = arrayValues[2];
616 values_[2] = arrayValues[1];
617 values_[3] = arrayValues[3];
618 }
619 else
620 {
621 memcpy(values_, arrayValues, sizeof(T) * 4);
622 }
623}
624
625template <typename T>
626inline SquareMatrixT2<T>::SquareMatrixT2(const T& m00, const T& m10, const T& m01, const T& m11)
627{
628 values_[0] = m00;
629 values_[1] = m10;
630
631 values_[2] = m01;
632 values_[3] = m11;
633}
634
635template <typename T>
636SquareMatrixT2<T>::SquareMatrixT2(const T eigenValue0, const T eigenValue1, const VectorT2<T>& eigenVector0, const VectorT2<T>& eigenVector1)
637{
638 ocean_assert(eigenVector0.isUnit());
639 ocean_assert(eigenVector1.isUnit());
640
641 const T determinant = eigenVector0.x() * eigenVector1.y() - eigenVector1.x() * eigenVector0.y();
642 ocean_assert(NumericT<T>::isNotEqualEps(determinant));
643
644 values_[0] = (eigenVector0.x() * eigenValue0 * eigenVector1.y() - eigenVector0.y() * eigenValue1 * eigenVector1.x()) / determinant;
645 values_[1] = (eigenValue0 - eigenValue1) * eigenVector0.y() * eigenVector1.y() / determinant;
646 values_[2] = (eigenValue1 - eigenValue0) * eigenVector0.x() * eigenVector1.x() / determinant;
647 values_[3] = (eigenVector0.x() * eigenValue1 * eigenVector1.y() - eigenVector0.y() * eigenValue0 * eigenVector1.x()) / determinant;
648}
649
650template <typename T>
652{
653 return SquareMatrixT2<T>(values_[0], values_[2], values_[1], values_[3]);
654}
655
656template <typename T>
658{
659 const T tmp = values_[1];
660 values_[1] = values_[2];
661 values_[2] = tmp;
662}
663
664template <typename T>
666{
667 SquareMatrixT2<T> result;
668
669 if (!invert(result))
670 {
671 ocean_assert(false && "Could not invert the matrix.");
672 return *this;
673 }
674
675 return result;
676}
677
678template <typename T>
680{
681 const T det = determinant();
683 {
684 return false;
685 }
686
687 const T factor = T(1.0) / det;
688
689 *this = SquareMatrixT2<T>(values_[3] * factor, -values_[1] * factor, -values_[2] * factor, values_[0] * factor);
690
691 return true;
692}
693
694template <typename T>
695inline bool SquareMatrixT2<T>::invert(SquareMatrixT2<T>& invertedMatrix) const
696{
697 const T det = determinant();
699 {
700 return false;
701 }
702
703 const T factor = T(1.0) / det;
704
705 invertedMatrix = SquareMatrixT2<T>(values_[3] * factor, -values_[1] * factor, -values_[2] * factor, values_[0] * factor);
706
707#ifdef OCEAN_INTENSIVE_DEBUG
708 if (!std::is_same<T, float>::value)
709 {
710 const SquareMatrixT2<T> test(*this * invertedMatrix);
711 const SquareMatrixT2<T> entity(true);
712
713 T sqrDistance = T(0);
714 for (unsigned int n = 0; n < 4u; ++n)
715 {
716 sqrDistance += NumericT<T>::sqr(test[n] - entity[n]);
717 }
718
719 const T distance = NumericT<T>::sqrt(sqrDistance * T(0.25));
720
721 if (NumericT<T>::isWeakEqualEps(distance) == false)
722 {
723 T absolusteAverageEnergy = 0;
724 for (unsigned int n = 0u; n < 4u; ++n)
725 {
726 absolusteAverageEnergy += NumericT<T>::abs(values_[n]);
727 }
728 absolusteAverageEnergy *= T(0.25);
729
730 // we expect/accept for each magnitude (larger than 1) a zero-inaccuracy of one magnitude (and we again comare it with the weak eps)
731
732 if (absolusteAverageEnergy <= 1)
733 {
734 ocean_assert_accuracy(!"This should never happen!");
735 }
736 else
737 {
738 const T adjustedDistance = distance / absolusteAverageEnergy;
739 ocean_assert_accuracy(NumericT<T>::isWeakEqualEps(adjustedDistance));
740 }
741 }
742 }
743#endif // OCEAN_DEBUG
744
745 return true;
746}
747
748template <typename T>
750{
751 return values_[0] * values_[3] - values_[1] * values_[2];
752}
753
754template <typename T>
756{
757 return values_[0] + values_[3];
758}
759
760template <typename T>
761inline bool SquareMatrixT2<T>::solve(const VectorT2<T>& b, VectorT2<T>& x) const
762{
763 const T determinant = (values_[0] * values_[3]) - (values_[1] * values_[2]);
764
765 if (NumericT<T>::isNotEqualEps(determinant))
766 {
767 x[0] = (values_[3] * b[0] - values_[2] * b[1]) / determinant;
768 x[1] = (values_[0] * b[1] - values_[1] * b[0]) / determinant;
769
770 return true;
771 }
772
773 return false;
774}
775
776template <typename T>
778{
779 values_[0] = T(1.0);
780 values_[1] = T(0.0);
781 values_[2] = T(0.0);
782 values_[3] = T(1.0);
783}
784
785template <typename T>
787{
788 values_[0] = T(0.0);
789 values_[1] = T(0.0);
790 values_[2] = T(0.0);
791 values_[3] = T(0.0);
792}
793
794template <typename T>
796{
797 return VectorT2<T>(values_[0], values_[1]);
798}
799
800template <typename T>
802{
803 return VectorT2<T>(values_[2], values_[3]);
804}
805
806template <typename T>
808{
809 return VectorT2<T>(values_[0], values_[3]);
810}
811
812template <typename T>
814{
815 return NumericT<T>::abs(values_[0]) + NumericT<T>::abs(values_[1]) + NumericT<T>::abs(values_[2]) + NumericT<T>::abs(values_[3]);
816}
817
818template <typename T>
819inline bool SquareMatrixT2<T>::isNull() const
820{
821 return NumericT<T>::isEqualEps(values_[0]) && NumericT<T>::isEqualEps(values_[1]) && NumericT<T>::isEqualEps(values_[2]) && NumericT<T>::isEqualEps(values_[3]);
822}
823
824template <typename T>
826{
827 return NumericT<T>::isEqual(values_[0], 1) && NumericT<T>::isEqualEps(values_[1]) && NumericT<T>::isEqualEps(values_[2]) && NumericT<T>::isEqual(values_[3], 1);
828}
829
830template <typename T>
832{
833 return NumericT<T>::isEqualEps(determinant());
834}
835
836template <typename T>
837inline bool SquareMatrixT2<T>::isSymmetric(const T epsilon) const
838{
839 ocean_assert(epsilon >= T(0));
840
841 return NumericT<T>::isEqual(values_[1], values_[2], epsilon);
842}
843
844template <typename T>
845inline bool SquareMatrixT2<T>::isEqual(const SquareMatrixT2<T>& matrix, const T eps) const
846{
847 return NumericT<T>::isEqual(values_[0], matrix.values_[0], eps) && NumericT<T>::isEqual(values_[1], matrix.values_[1], eps)
848 && NumericT<T>::isEqual(values_[2], matrix.values_[2], eps) && NumericT<T>::isEqual(values_[3], matrix.values_[3], eps);
849}
850
851template <typename T>
852inline const T* SquareMatrixT2<T>::data() const
853{
854 return values_;
855}
856
857template <typename T>
859{
860 return values_;
861}
862
863template <typename T>
864template <typename U>
865inline void SquareMatrixT2<T>::copyElements(U* arrayValues, const bool columnAligned) const
866{
867 ocean_assert(arrayValues);
868
869 if (columnAligned)
870 {
871 arrayValues[0] = U(values_[0]);
872 arrayValues[1] = U(values_[1]);
873 arrayValues[2] = U(values_[2]);
874 arrayValues[3] = U(values_[3]);
875 }
876 else
877 {
878 arrayValues[0] = U(values_[0]);
879 arrayValues[1] = U(values_[2]);
880 arrayValues[2] = U(values_[1]);
881 arrayValues[3] = U(values_[3]);
882 }
883}
884
885template <typename T>
886inline void SquareMatrixT2<T>::copyElements(T* arrayValues, const bool columnAligned) const
887{
888 ocean_assert(arrayValues);
889
890 if (columnAligned)
891 {
892 arrayValues[0] = values_[0];
893 arrayValues[1] = values_[1];
894 arrayValues[2] = values_[2];
895 arrayValues[3] = values_[3];
896 }
897 else
898 {
899 arrayValues[0] = values_[0];
900 arrayValues[1] = values_[2];
901 arrayValues[2] = values_[1];
902 arrayValues[3] = values_[3];
903 }
904}
905
906template <typename T>
907inline bool SquareMatrixT2<T>::operator==(const SquareMatrixT2<T>& matrix) const
908{
909 return isEqual(matrix);
910}
911
912template <typename T>
913inline bool SquareMatrixT2<T>::operator!=(const SquareMatrixT2<T>& matrix) const
914{
915 return !(*this == matrix);
916}
917
918template <typename T>
920{
921 return SquareMatrixT2<T>(values_[0] + matrix.values_[0], values_[1] + matrix.values_[1], values_[2] + matrix.values_[2], values_[3] + matrix.values_[3]);
922}
923
924template <typename T>
926{
927 values_[0] += matrix.values_[0];
928 values_[1] += matrix.values_[1];
929 values_[2] += matrix.values_[2];
930 values_[3] += matrix.values_[3];
931
932 return *this;
933}
934
935template <typename T>
937{
938 return SquareMatrixT2<T>(values_[0] - matrix.values_[0], values_[1] - matrix.values_[1], values_[2] - matrix.values_[2], values_[3] - matrix.values_[3]);
939}
940
941template <typename T>
943{
944 values_[0] -= matrix.values_[0];
945 values_[1] -= matrix.values_[1];
946 values_[2] -= matrix.values_[2];
947 values_[3] -= matrix.values_[3];
948
949 return *this;
950}
951
952template <typename T>
954{
955 SquareMatrixT2<T> result;
956
957 result.values_[ 0] = -values_[ 0];
958 result.values_[ 1] = -values_[ 1];
959 result.values_[ 2] = -values_[ 2];
960 result.values_[ 3] = -values_[ 3];
961
962 return result;
963}
964
965template <typename T>
967{
968 return SquareMatrixT2<T>(values_[0] * matrix.values_[0] + values_[2] * matrix.values_[1],
969 values_[1] * matrix.values_[0] + values_[3] * matrix.values_[1],
970 values_[0] * matrix.values_[2] + values_[2] * matrix.values_[3],
971 values_[1] * matrix.values_[2] + values_[3] * matrix.values_[3]);
972}
973
974template <typename T>
976{
977 *this = *this * matrix;
978 return *this;
979}
980
981template <typename T>
983{
984 return VectorT2<T>(values_[0] * vector[0] + values_[2] * vector[1],
985 values_[1] * vector[0] + values_[3] * vector[1]);
986}
987
988template <typename T>
990{
991 return SquareMatrixT2<T>(values_[0] * value, values_[1] * value, values_[2] * value, values_[3] * value);
992}
993
994template <typename T>
996{
997 values_[0] *= value;
998 values_[1] *= value;
999 values_[2] *= value;
1000 values_[3] *= value;
1001
1002 return *this;
1003}
1004
1005template <typename T>
1006inline T SquareMatrixT2<T>::operator[](const unsigned int index) const
1007{
1008 ocean_assert(index < 4u);
1009 return values_[index];
1010}
1011
1012template <typename T>
1013inline T& SquareMatrixT2<T>::operator[](const unsigned int index)
1014{
1015 ocean_assert(index < 4u);
1016 return values_[index];
1017}
1018
1019template <typename T>
1020inline T SquareMatrixT2<T>::operator()(const unsigned int row, const unsigned int column) const
1021{
1022 ocean_assert(row < 2u && column < 2u);
1023 return values_[column * 2u + row];
1024}
1025
1026template <typename T>
1027inline T& SquareMatrixT2<T>::operator()(const unsigned int row, const unsigned int column)
1028{
1029 ocean_assert(row < 2u && column < 2u);
1030 return values_[column * 2u + row];
1031}
1032
1033template <typename T>
1034inline T SquareMatrixT2<T>::operator()(const unsigned int index) const
1035{
1036 ocean_assert(index < 4u);
1037 return values_[index];
1038}
1039
1040template <typename T>
1041inline T& SquareMatrixT2<T>::operator()(const unsigned int index)
1042{
1043 ocean_assert(index < 4u);
1044 return values_[index];
1045}
1046
1047template <typename T>
1048inline const T* SquareMatrixT2<T>::operator()() const
1049{
1050 return values_;
1051}
1052
1053template <typename T>
1055{
1056 return values_;
1057}
1058
1059template <typename T>
1060inline size_t SquareMatrixT2<T>::operator()(const SquareMatrixT2<T>& matrix) const
1061{
1062 size_t seed = std::hash<T>{}(matrix.values_[0]);
1063
1064 for (unsigned int n = 1u; n < 4u; ++n)
1065 {
1066 seed ^= std::hash<T>{}(matrix.values_[n]) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1067 }
1068
1069 return seed;
1070}
1071
1072template <typename T>
1074{
1075 return 4;
1076}
1077
1078template <typename T>
1079bool SquareMatrixT2<T>::eigenSystem(T& eigenValue0, T& eigenValue1, VectorT2<T>& eigenVector0, VectorT2<T>& eigenVector1) const
1080{
1081 if (isNull())
1082 {
1083 return false;
1084 }
1085
1086 const T tr = trace();
1087 const T det = determinant();
1088
1089 if (!EquationT<T>::solveQuadratic(T(1.0), -tr, det, eigenValue0, eigenValue1))
1090 {
1091 return false;
1092 }
1093
1094 if (eigenValue0 < eigenValue1)
1095 {
1096 std::swap(eigenValue0, eigenValue1);
1097 }
1098
1099 if (NumericT<T>::isNotEqualEps(values_[2]))
1100 {
1101 const T factor = T(1.0) / values_[2];
1102 eigenVector0 = VectorT2<T>(1, (eigenValue0 - values_[0]) * factor);
1103 eigenVector1 = VectorT2<T>(1, (eigenValue1 - values_[0]) * factor);
1104 }
1105 else if (NumericT<T>::isNotEqualEps(values_[1]))
1106 {
1107 const T factor = T(1.0) / values_[1];
1108
1109 eigenVector0 = VectorT2<T>((eigenValue0 - values_[3]) * factor, T(1.0));
1110 eigenVector1 = VectorT2<T>((eigenValue1 - values_[3]) * factor, T(1.0));
1111 }
1112 else
1113 {
1114 if (NumericT<T>::isNotEqual(eigenValue0, values_[3]))
1115 {
1116 eigenVector0 = VectorT2<T>(1, values_[1] / (eigenValue0 - values_[3]));
1117 }
1118 else
1119 {
1120 if (NumericT<T>::isEqual(eigenValue0, values_[0]))
1121 {
1122 eigenVector0 = VectorT2<T>(1, 0);
1123 }
1124 else
1125 {
1126 eigenVector0 = VectorT2<T>(values_[2] / (eigenValue0 - values_[0]), T(1.0));
1127 }
1128 }
1129
1130 if (NumericT<T>::isNotEqual(values_[3], eigenValue1))
1131 {
1132 eigenVector1 = VectorT2<T>(1, values_[1] / (eigenValue1 - values_[3]));
1133 }
1134 else
1135 {
1136 if (NumericT<T>::isEqual(eigenValue1, values_[0]))
1137 {
1138 eigenVector1 = VectorT2<T>(0, 1);
1139 }
1140 else
1141 {
1142 eigenVector1 = VectorT2<T>(values_[2] / (eigenValue1 - values_[0]), T(1.0));
1143 }
1144 }
1145 }
1146
1147 eigenVector0.normalize();
1148 eigenVector1.normalize();
1149
1150 ocean_assert((std::is_same<T, float>::value) || (*this * eigenVector0).isEqual(eigenVector0 * eigenValue0, NumericT<T>::weakEps()));
1151 ocean_assert((std::is_same<T, float>::value) || (*this * eigenVector1).isEqual(eigenVector1 * eigenValue1, NumericT<T>::weakEps()));
1152
1153 return true;
1154}
1155
1156template <typename T>
1157template <typename U>
1158inline std::vector< SquareMatrixT2<T> > SquareMatrixT2<T>::matrices2matrices(const std::vector< SquareMatrixT2<U> >& matrices)
1159{
1160 std::vector< SquareMatrixT2<T> > result;
1161 result.reserve(matrices.size());
1162
1163 for (typename std::vector< SquareMatrixT2<U> >::const_iterator i = matrices.begin(); i != matrices.end(); ++i)
1164 {
1165 result.push_back(SquareMatrixT2<T>(*i));
1166 }
1167
1168 return result;
1169}
1170
1171template <>
1172template <>
1173inline std::vector< SquareMatrixT2<float> > SquareMatrixT2<float>::matrices2matrices(const std::vector< SquareMatrixT2<float> >& matrices)
1174{
1175 return matrices;
1176}
1177
1178template <>
1179template <>
1180inline std::vector< SquareMatrixT2<double> > SquareMatrixT2<double>::matrices2matrices(const std::vector< SquareMatrixT2<double> >& matrices)
1181{
1182 return matrices;
1183}
1184
1185template <typename T>
1186template <typename U>
1187inline std::vector< SquareMatrixT2<T> > SquareMatrixT2<T>::matrices2matrices(const SquareMatrixT2<U>* matrices, const size_t size)
1188{
1189 std::vector< SquareMatrixT2<T> > result;
1190 result.reserve(size);
1191
1192 for (size_t n = 0; n < size; ++n)
1193 {
1194 result.push_back(SquareMatrixT2<T>(matrices[n]));
1195 }
1196
1197 return result;
1198}
1199
1200template <typename T>
1201std::ostream& operator<<(std::ostream& stream, const SquareMatrixT2<T>& matrix)
1202{
1203 stream << "|" << matrix(0, 0) << ", " << matrix(0, 1) << "|" << std::endl;
1204 stream << "|" << matrix(1, 0) << ", " << matrix(1, 1) << "|";
1205
1206 return stream;
1207}
1208
1209template <bool tActive, typename T>
1210MessageObject<tActive>& operator<<(MessageObject<tActive>& messageObject, const SquareMatrixT2<T>& matrix)
1211{
1212 return messageObject << "|" << matrix(0, 0) << ", " << matrix(0, 1) << "|\n|" << matrix(1, 0) << ", " << matrix(1, 1) << "|";
1213}
1214
1215template <bool tActive, typename T>
1216MessageObject<tActive>& operator<<(MessageObject<tActive>&& messageObject, const SquareMatrixT2<T>& matrix)
1217{
1218 return messageObject << "|" << matrix(0, 0) << ", " << matrix(0, 1) << "|\n|" << matrix(1, 0) << ", " << matrix(1, 1) << "|";
1219}
1220
1221}
1222
1223#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:1537
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2395
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition Numeric.h:1499
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2096
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:1073
SquareMatrixT2< T > & operator=(const SquareMatrixT2< T > &)=default
Default copy assignment operator.
bool isIdentity() const
Returns whether this matrix is the identity matrix.
Definition SquareMatrix2.h:825
bool isSingular() const
Returns whether this matrix is singular (and thus cannot be inverted).
Definition SquareMatrix2.h:831
SquareMatrixT2< T > & operator+=(const SquareMatrixT2< T > &matrix)
Adds and assigns two matrices.
Definition SquareMatrix2.h:925
T norm() const
Returns the norm of this matrix that is the sum of the absolute matrix elements.
Definition SquareMatrix2.h:813
VectorT2< T > xAxis() const
Returns the x axis which is the first column of the matrix.
Definition SquareMatrix2.h:795
SquareMatrixT2< T > transposed() const
Returns the transposed of this matrix.
Definition SquareMatrix2.h:651
T Type
Definition of the used data type.
Definition SquareMatrix2.h:81
bool operator!=(const SquareMatrixT2< T > &matrix) const
Returns whether two matrices are not identical up to a small epsilon.
Definition SquareMatrix2.h:913
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:1158
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:845
T operator[](const unsigned int index) const
Element operator.
Definition SquareMatrix2.h:1006
bool isNull() const
Returns whether this matrix is a null matrix.
Definition SquareMatrix2.h:819
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:801
T trace() const
Returns the trace of the matrix which is the sum of the diagonal elements.
Definition SquareMatrix2.h:755
bool operator==(const SquareMatrixT2< T > &matrix) const
Returns whether two matrices are identical up to a small epsilon.
Definition SquareMatrix2.h:907
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:761
void toIdentity()
Sets the matrix to the identity matrix.
Definition SquareMatrix2.h:777
SquareMatrixT2< T > operator*(const SquareMatrixT2< T > &matrix) const
Multiplies two matrices.
Definition SquareMatrix2.h:966
SquareMatrixT2< T > inverted() const
Returns the inverted matrix of this matrix.
Definition SquareMatrix2.h:665
const T * data() const
Returns a pointer to the internal values.
Definition SquareMatrix2.h:852
SquareMatrixT2< T > & operator-=(const SquareMatrixT2< T > &matrix)
Subtracts and assigns two matrices.
Definition SquareMatrix2.h:942
bool isSymmetric(const T epsilon=NumericT< T >::eps()) const
Returns whether this matrix is symmetric.
Definition SquareMatrix2.h:837
T determinant() const
Returns the determinant of the matrix.
Definition SquareMatrix2.h:749
SquareMatrixT2< T > operator-() const
Returns the negative matrix of this matrix (all matrix elements are multiplied by -1).
Definition SquareMatrix2.h:953
bool invert()
Inverts this matrix in place.
Definition SquareMatrix2.h:679
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:865
T values_[4]
The four values of the matrix.
Definition SquareMatrix2.h:518
SquareMatrixT2< T > operator+(const SquareMatrixT2< T > &matrix) const
Adds two matrices.
Definition SquareMatrix2.h:919
SquareMatrixT2(const SquareMatrixT2< T > &matrix)=default
Copy constructor.
void transpose()
Transposes the matrix.
Definition SquareMatrix2.h:657
VectorT2< T > diagonal() const
Returns a 2D vector with values of the matrix diagonal.
Definition SquareMatrix2.h:807
const T * operator()() const
Access operator.
Definition SquareMatrix2.h:1048
SquareMatrixT2< T > & operator*=(const SquareMatrixT2< T > &matrix)
Multiplies and assigns two matrices.
Definition SquareMatrix2.h:975
bool eigenSystem(T &eigenValue0, T &eigenValue1, VectorT2< T > &eigenVector0, VectorT2< T > &eigenVector1) const
Performs an eigen value analysis.
Definition SquareMatrix2.h:1079
void toNull()
Sets the matrix to a zero matrix.
Definition SquareMatrix2.h:786
This class implements a vector with two elements.
Definition Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
bool isUnit(const T eps=NumericT< T >::eps()) const
Returns whether this vector is a unit vector (whether the vector has the length 1).
Definition Vector2.h:752
bool normalize()
Normalizes this vector.
Definition Vector2.h:612
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1159
std::vector< SquareMatrixT2< T > > SquareMatricesT2
Definition of a typename alias for vectors with SquareMatrixT2 objects.
Definition SquareMatrix2.h:51
std::vector< SquareMatrix2 > SquareMatrices2
Definition of a vector holding SquareMatrix2 objects.
Definition SquareMatrix2.h:58
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
std::ostream & operator<<(std::ostream &stream, const HighPerformanceStatistic &highPerformanceStatistic)
Definition HighPerformanceTimer.h:963