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.
518 T values[4];
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 values[n] = T(arrayValues[n]);
602 }
603}
604
605template <typename T>
606SquareMatrixT2<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
623template <typename T>
624inline 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
633template <typename T>
634SquareMatrixT2<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
662template <typename T>
664{
665 return SquareMatrixT2<T>(values[0], values[2], values[1], values[3]);
666}
667
668template <typename T>
670{
671 const T tmp = values[1];
672 values[1] = values[2];
673 values[2] = tmp;
674}
675
676template <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
690template <typename T>
692{
693 const T det = determinant();
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
706template <typename T>
707inline bool SquareMatrixT2<T>::invert(SquareMatrixT2<T>& invertedMatrix) const
708{
709 const T det = determinant();
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
753template <typename T>
755{
756 return values[0] * values[3] - values[1] * values[2];
757}
758
759template <typename T>
761{
762 return values[0] + values[3];
763}
764
765template <typename T>
766inline 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
795template <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
804template <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
813template <typename T>
815{
816 return VectorT2<T>(values[0], values[1]);
817}
818
819template <typename T>
821{
822 return VectorT2<T>(values[2], values[3]);
823}
824
825template <typename T>
827{
828 return VectorT2<T>(values[0], values[3]);
829}
830
831template <typename T>
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
837template <typename T>
838inline 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
843template <typename T>
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
849template <typename T>
851{
852 return NumericT<T>::isEqualEps(determinant());
853}
854
855template <typename T>
856inline 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
863template <typename T>
864inline 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
870template <typename T>
871inline const T* SquareMatrixT2<T>::data() const
872{
873 return values;
874}
875
876template <typename T>
878{
879 return values;
880}
881
882template <typename T>
883template <typename U>
884inline 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
904template <typename T>
905inline 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
925template <typename T>
926inline bool SquareMatrixT2<T>::operator==(const SquareMatrixT2<T>& matrix) const
927{
928 return isEqual(matrix);
929}
930
931template <typename T>
932inline bool SquareMatrixT2<T>::operator!=(const SquareMatrixT2<T>& matrix) const
933{
934 return !(*this == matrix);
935}
936
937template <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
943template <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
954template <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
960template <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
971template <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
984template <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
993template <typename T>
995{
996 *this = *this * matrix;
997 return *this;
998}
999
1000template <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
1007template <typename T>
1009{
1010 return SquareMatrixT2<T>(values[0] * value, values[1] * value, values[2] * value, values[3] * value);
1011}
1012
1013template <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
1024template <typename T>
1025inline T SquareMatrixT2<T>::operator[](const unsigned int index) const
1026{
1027 ocean_assert(index < 4u);
1028 return values[index];
1029}
1030
1031template <typename T>
1032inline T& SquareMatrixT2<T>::operator[](const unsigned int index)
1033{
1034 ocean_assert(index < 4u);
1035 return values[index];
1036}
1037
1038template <typename T>
1039inline 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
1045template <typename T>
1046inline 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
1052template <typename T>
1053inline T SquareMatrixT2<T>::operator()(const unsigned int index) const
1054{
1055 ocean_assert(index < 4u);
1056 return values[index];
1057}
1058
1059template <typename T>
1060inline T& SquareMatrixT2<T>::operator()(const unsigned int index)
1061{
1062 ocean_assert(index < 4u);
1063 return values[index];
1064}
1065
1066template <typename T>
1067inline const T* SquareMatrixT2<T>::operator()() const
1068{
1069 return values;
1070}
1071
1072template <typename T>
1074{
1075 return values;
1076}
1077
1078template <typename T>
1079inline 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
1091template <typename T>
1093{
1094 return 4;
1095}
1096
1097template <typename T>
1098bool 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
1175template <typename T>
1176template <typename U>
1177inline 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
1190template <>
1191template <>
1192inline std::vector< SquareMatrixT2<float> > SquareMatrixT2<float>::matrices2matrices(const std::vector< SquareMatrixT2<float> >& matrices)
1193{
1194 return matrices;
1195}
1196
1197template <>
1198template <>
1199inline std::vector< SquareMatrixT2<double> > SquareMatrixT2<double>::matrices2matrices(const std::vector< SquareMatrixT2<double> >& matrices)
1200{
1201 return matrices;
1202}
1203
1204template <typename T>
1205template <typename U>
1206inline 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
1219template <typename T>
1220std::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
1228template <bool tActive, typename T>
1229MessageObject<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
1234template <bool tActive, typename T>
1235MessageObject<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
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: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
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: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: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: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