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