From 7072befbdb1dcbacdfe84dfaec27c316e73eb50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 May 2021 17:07:39 +0200 Subject: [PATCH] Math: generalize slicing and expanding to arbitrarily-sized matrices. Originally was done only for square matrices, but now I need that for converting 3x3 -> 3x4 and back (UBO packing, ugh ugh), so let's generalize. --- doc/changelog.dox | 8 +++ src/Magnum/Math/Matrix.h | 27 ++++---- src/Magnum/Math/Matrix3.h | 17 +++-- src/Magnum/Math/Matrix4.h | 17 +++-- src/Magnum/Math/RectangularMatrix.h | 52 +++++++++++++++ src/Magnum/Math/Test/Matrix3Test.cpp | 39 ++++++----- src/Magnum/Math/Test/Matrix4Test.cpp | 46 +++++++------ src/Magnum/Math/Test/MatrixTest.cpp | 58 ++++++++-------- .../Math/Test/RectangularMatrixTest.cpp | 66 +++++++++++++++++++ 9 files changed, 242 insertions(+), 88 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 971bdaec3..0c74c5c3a 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -253,6 +253,14 @@ See also: - Added @ref Math::castInto() overloads for casting between @ref UnsignedByte and @ref UnsignedShort or @ref Byte and @ref Short, and for casting between @ref Float and @ref Double +- @ref Math::RectangularMatrix is now explicitly convertible from matrices of + different sizes, with a possibility to specify whether to fill the diagonal + or leave it as zeros. This was originally available only on (square) + @ref Math::Matrix from other square matrices where it implicitly filled the + diagonal to an identity, but is now generalized for arbitrary rectangular + matrices, and with the default on @ref Math::RectangularMatrix being + zero-fill while @ref Math::Matrix stays with the identity for consistency + with other constructors. @subsubsection changelog-latest-changes-meshtools MeshTools library diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 9487065a5..53f749294 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -35,15 +35,6 @@ namespace Magnum { namespace Math { namespace Implementation { template struct MatrixDeterminant; - - template constexpr Vector valueOrIdentityVector(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) { - return {(col < otherSize && row < otherSize ? other[col][row] : - col == row ? T{1} : T{0})...}; - } - - template constexpr Vector valueOrIdentityVector(const RectangularMatrix& other) { - return valueOrIdentityVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other); - } } /** @@ -107,14 +98,21 @@ template class Matrix: public RectangularMatrix::from(std::declval()))> constexpr explicit Matrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} + /** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&, T) */ + template constexpr explicit Matrix(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: RectangularMatrix{IdentityInit, other, value} {} + + /** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit Matrix(ZeroInitT, const RectangularMatrix& other) noexcept: RectangularMatrix{ZeroInit, other} {} + /** * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest * - * If the other matrix is larger, takes only the first @cpp size @ce - * columns and rows from it; if the other matrix is smaller, it's - * expanded to an identity (ones on diagonal, zeros elsewhere). + * Equivalent to @ref Matrix(IdentityInitT, const RectangularMatrix&, T). + * Note that this default is different from @ref RectangularMatrix, + * where it's equivalent to the @ref ZeroInit variant instead. */ - template constexpr explicit Matrix(const RectangularMatrix& other) noexcept: Matrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other} {} + template constexpr explicit Matrix(const RectangularMatrix& other, T value = T(1)) noexcept: RectangularMatrix{IdentityInit, other, value} {} /** @brief Copy constructor */ constexpr /*implicit*/ Matrix(const RectangularMatrix& other) noexcept: RectangularMatrix(other) {} @@ -300,9 +298,6 @@ template class Matrix: public RectangularMatrix; - - /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ - template constexpr explicit Matrix(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) noexcept: RectangularMatrix{Implementation::valueOrIdentityVector(other)...} {} }; /** diff --git a/src/Magnum/Math/Matrix3.h b/src/Magnum/Math/Matrix3.h index 6124241e2..d988a1f30 100644 --- a/src/Magnum/Math/Matrix3.h +++ b/src/Magnum/Math/Matrix3.h @@ -234,14 +234,21 @@ template class Matrix3: public Matrix3x3 { /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix3(const U& other) noexcept: Matrix3x3(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {} + /** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&, T) */ + template constexpr explicit Matrix3(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: Matrix3x3{IdentityInit, other, value} {} + + /** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit Matrix3(ZeroInitT, const RectangularMatrix& other) noexcept: Matrix3x3{ZeroInit, other} {} + /** - * @brief Construct by slicing or expanding a matrix of a different size + * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest * - * If the other matrix is larger, takes only the first @cpp size @ce - * columns and rows from it; if the other matrix is smaller, it's - * expanded to an identity (ones on diagonal, zeros elsewhere). + * Equivalent to @ref Matrix3(IdentityInitT, const RectangularMatrix&, T). + * Note that this default is different from @ref RectangularMatrix, + * where it's equivalent to the @ref ZeroInit variant instead. */ - template constexpr explicit Matrix3(const RectangularMatrix& other) noexcept: Matrix3x3{other} {} + template constexpr explicit Matrix3(const RectangularMatrix& other, T value = T(1)) noexcept: Matrix3x3{IdentityInit, other, value} {} /** @brief Copy constructor */ constexpr /*implicit*/ Matrix3(const RectangularMatrix<3, 3, T>& other) noexcept: Matrix3x3(other) {} diff --git a/src/Magnum/Math/Matrix4.h b/src/Magnum/Math/Matrix4.h index fe03d0709..508152aa8 100644 --- a/src/Magnum/Math/Matrix4.h +++ b/src/Magnum/Math/Matrix4.h @@ -467,14 +467,21 @@ template class Matrix4: public Matrix4x4 { /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix4(const U& other): Matrix4x4(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {} + /** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&, T) */ + template constexpr explicit Matrix4(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: Matrix4x4{IdentityInit, other, value} {} + + /** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit Matrix4(ZeroInitT, const RectangularMatrix& other) noexcept: Matrix4x4{ZeroInit, other} {} + /** - * @brief Construct by slicing or expanding a matrix of a different size + * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest * - * If the other matrix is larger, takes only the first @cpp size @ce - * columns and rows from it; if the other matrix is smaller, it's - * expanded to an identity (ones on diagonal, zeros elsewhere). + * Equivalent to @ref Matrix4(IdentityInitT, const RectangularMatrix&, T). + * Note that this default is different from @ref RectangularMatrix, + * where it's equivalent to the @ref ZeroInit variant instead. */ - template constexpr explicit Matrix4(const RectangularMatrix& other) noexcept: Matrix4x4{other} {} + template constexpr explicit Matrix4(const RectangularMatrix& other, T value = T(1)) noexcept: Matrix4x4{IdentityInit, other, value} {} /** @brief Copy constructor */ constexpr /*implicit*/ Matrix4(const RectangularMatrix<4, 4, T>& other) noexcept: Matrix4x4(other) {} diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index be3469295..8a5671c5e 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -35,6 +35,23 @@ namespace Magnum { namespace Math { namespace Implementation { template struct RectangularMatrixConverter; + + template constexpr Vector valueOrZeroVector(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) { + return {(col < otherCols && row < otherRows ? other[col][row] : T{0})...}; + } + + template constexpr Vector valueOrZeroVector(const RectangularMatrix& other) { + return valueOrZeroVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other); + } + + template constexpr Vector valueOrIdentityVector(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other, T value) { + return {(col < otherCols && row < otherRows ? other[col][row] : + col == row ? value : T{0})...}; + } + + template constexpr Vector valueOrIdentityVector(const RectangularMatrix& other, T value) { + return valueOrIdentityVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other, value); + } } /** @@ -162,6 +179,35 @@ template class RectangularMatrix { */ template constexpr explicit RectangularMatrix(const RectangularMatrix& other) noexcept: RectangularMatrix(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other) {} + /** + * @brief Construct by slicing or expanding a matrix of different size, leaving the rest at zero + * @m_since_latest + * + * If the other matrix has less columns or rows, the corresponding + * vectors and components are set to zeros. + */ + template constexpr explicit RectangularMatrix(ZeroInitT, const RectangularMatrix& other) noexcept: RectangularMatrix{ZeroInit, typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other} {} + + /** + * @brief Construct by slicing or expanding a matrix of different size, leaving the rest at identity + * @m_since_latest + * + * If the other matrix has less columns or rows, the corresponding + * vectors and components are set to either zeros or @p value on the + * diagonal. + */ + template constexpr explicit RectangularMatrix(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: RectangularMatrix{IdentityInit, typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other, value} {} + + /** + * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest + * + * Equivalent to @ref RectangularMatrix(ZeroInitT, const RectangularMatrix&). + * Note that this default is different from @ref Matrix, where it's + * equivalent to the @ref IdentityInit variant instead. + */ + template constexpr explicit RectangularMatrix(const RectangularMatrix& other) noexcept: RectangularMatrix{ZeroInit, typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other} {} + /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} @@ -472,6 +518,12 @@ template class RectangularMatrix { /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& matrix) noexcept: _data{Vector(matrix[sequence])...} {} + /* Implementation for RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit RectangularMatrix(ZeroInitT, Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) noexcept: RectangularMatrix{Implementation::valueOrZeroVector(other)...} {} + + /* Implementation for RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&) */ + template constexpr explicit RectangularMatrix(IdentityInitT, Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other, T value) noexcept: RectangularMatrix{Implementation::valueOrIdentityVector(other, value)...} {} + /* Implementation for RectangularMatrix::RectangularMatrix(ZeroInitT) and RectangularMatrix::RectangularMatrix(NoInitT) */ /* MSVC 2015 can't handle {} here */ template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, U) noexcept: _data{Vector((static_cast(sequence), U{typename U::Init{}}))...} {} diff --git a/src/Magnum/Math/Test/Matrix3Test.cpp b/src/Magnum/Math/Test/Matrix3Test.cpp index 47014d65a..46999c503 100644 --- a/src/Magnum/Math/Test/Matrix3Test.cpp +++ b/src/Magnum/Math/Test/Matrix3Test.cpp @@ -105,10 +105,12 @@ struct Matrix3Test: Corrade::TestSuite::Tester { typedef Math::Deg Deg; typedef Math::Matrix2x2 Matrix2x2; +typedef Math::Matrix2x4 Matrix2x4; typedef Math::Matrix3 Matrix3; typedef Math::Matrix3 Matrix3i; typedef Math::Vector2 Vector2; typedef Math::Vector3 Vector3; +typedef Math::Vector<4, Float> Vector4; /* to avoid having to include Vector4 */ Matrix3Test::Matrix3Test() { addTests({&Matrix3Test::construct, @@ -251,22 +253,27 @@ void Matrix3Test::constructConversion() { } void Matrix3Test::constructFromDifferentSize() { - constexpr Matrix3 a{{3.0f, 5.0f, 8.0f}, - {4.5f, 4.0f, 7.0f}, - {1.0f, 2.0f, 3.0f}}; - constexpr Matrix2x2 b{Vector2{3.0f, 5.0f}, - Vector2{4.5f, 4.0f}}; - constexpr Matrix3 c{{3.0f, 5.0f, 0.0f}, - {4.5f, 4.0f, 0.0f}, - {0.0f, 0.0f, 1.0f}}; - - constexpr Matrix3 larger{b}; - CORRADE_COMPARE(larger, c); - CORRADE_COMPARE(Matrix3{b}, c); - - constexpr Matrix2x2 smaller{a}; - CORRADE_COMPARE(smaller, b); - CORRADE_COMPARE(Matrix2x2{a}, b); + /* Tested thoroughly in RectangularMatrixTest, verify just that the args + are propagated correctly (cols, rows, zero/identity, identity value) */ + constexpr Matrix2x4 a{Vector4{3.0f, 5.0f, 8.0f, -3.0f}, + Vector4{4.5f, 4.0f, 7.0f, 2.0f}}; + constexpr Matrix3 expectedIdentity{{3.0f, 5.0f, 8.0f}, + {4.5f, 4.0f, 7.0f}, + {0.0f, 0.0f, 0.5f}}; + constexpr Matrix3 expectedZero{{3.0f, 5.0f, 8.0f}, + {4.5f, 4.0f, 7.0f}, + {0.0f, 0.0f, 0.0f}}; + + constexpr Matrix3 identity1{a, 0.5f}; + constexpr Matrix3 identity2{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(identity1, expectedIdentity); + CORRADE_COMPARE(identity2, expectedIdentity); + CORRADE_COMPARE((Matrix3{a, 0.5f}), expectedIdentity); + CORRADE_COMPARE((Matrix3{IdentityInit, a, 0.5f}), expectedIdentity); + + constexpr Matrix3 zero{ZeroInit, a}; + CORRADE_COMPARE(zero, expectedZero); + CORRADE_COMPARE((Matrix3{ZeroInit, a}), expectedZero); } void Matrix3Test::constructCopy() { diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index 63f01d3e3..553ade30b 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -122,8 +122,9 @@ struct Matrix4Test: Corrade::TestSuite::Tester { typedef Math::Deg Deg; typedef Math::Rad Rad; -typedef Math::Matrix<2, Float> Matrix2x2; -typedef Math::Matrix<3, Float> Matrix3x3; +typedef Math::Matrix2x2 Matrix2x2; +typedef Math::Matrix2x3 Matrix2x3; +typedef Math::Matrix3x3 Matrix3x3; typedef Math::Matrix4 Matrix4; typedef Math::Matrix4 Matrix4i; typedef Math::Vector2 Vector2; @@ -296,24 +297,29 @@ void Matrix4Test::constructConversion() { } void Matrix4Test::constructFromDifferentSize() { - constexpr Matrix4 a{{3.0f, 5.0f, 8.0f, -3.0f}, - {4.5f, 4.0f, 7.0f, 2.0f}, - {1.0f, 2.0f, 3.0f, -1.0f}, - {7.9f, -1.0f, 8.0f, -1.5f}}; - constexpr Matrix2x2 b{Vector2{3.0f, 5.0f}, - Vector2{4.5f, 4.0f}}; - constexpr Matrix4 c{{3.0f, 5.0f, 0.0f, 0.0f}, - {4.5f, 4.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 1.0f, 0.0f}, - {0.0f, 0.0f, 0.0f, 1.0f}}; - - constexpr Matrix4 larger{b}; - CORRADE_COMPARE(larger, c); - CORRADE_COMPARE(Matrix4{b}, c); - - constexpr Matrix2x2 smaller{a}; - CORRADE_COMPARE(smaller, b); - CORRADE_COMPARE(Matrix2x2{a}, b); + /* Tested thoroughly in RectangularMatrixTest, verify just that the args + are propagated correctly (cols, rows, zero/identity, identity value) */ + constexpr Matrix2x3 a{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}}; + constexpr Matrix4 expectedIdentity{{3.0f, 5.0f, 8.0f, 0.0f}, + {4.5f, 4.0f, 7.0f, 0.0f}, + {0.0f, 0.0f, 0.5f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.5f}}; + constexpr Matrix4 expectedZero{{3.0f, 5.0f, 8.0f, 0.0f}, + {4.5f, 4.0f, 7.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}}; + + constexpr Matrix4 identity1{a, 0.5f}; + constexpr Matrix4 identity2{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(identity1, expectedIdentity); + CORRADE_COMPARE(identity2, expectedIdentity); + CORRADE_COMPARE((Matrix4{a, 0.5f}), expectedIdentity); + CORRADE_COMPARE((Matrix4{IdentityInit, a, 0.5f}), expectedIdentity); + + constexpr Matrix4 zero{ZeroInit, a}; + CORRADE_COMPARE(zero, expectedZero); + CORRADE_COMPARE((Matrix4{ZeroInit, a}), expectedZero); } void Matrix4Test::constructCopy() { diff --git a/src/Magnum/Math/Test/MatrixTest.cpp b/src/Magnum/Math/Test/MatrixTest.cpp index 6964a3655..40ad78569 100644 --- a/src/Magnum/Math/Test/MatrixTest.cpp +++ b/src/Magnum/Math/Test/MatrixTest.cpp @@ -89,14 +89,15 @@ struct MatrixTest: Corrade::TestSuite::Tester { void debug(); }; -typedef Matrix<2, Float> Matrix2x2; -typedef Matrix<3, Float> Matrix3x3; -typedef Matrix<4, Float> Matrix4x4; -typedef Matrix<4, Int> Matrix4x4i; -typedef Vector<2, Float> Vector2; -typedef Vector<3, Float> Vector3; -typedef Vector<4, Float> Vector4; -typedef Vector<4, Int> Vector4i; +typedef Math::Matrix2x2 Matrix2x2; +typedef Math::Matrix2x3 Matrix2x3; +typedef Math::Matrix3x3 Matrix3x3; +typedef Math::Matrix4x4 Matrix4x4; +typedef Math::Matrix4x4 Matrix4x4i; +typedef Math::Vector<2, Float> Vector2; +typedef Math::Vector<3, Float> Vector3; +typedef Math::Vector<4, Float> Vector4; +typedef Math::Vector<4, Int> Vector4i; typedef Math::Constants Constants; MatrixTest::MatrixTest() { @@ -248,24 +249,29 @@ void MatrixTest::constructConversion() { } void MatrixTest::constructFromDifferentSize() { - constexpr Matrix4x4 a{Vector4{3.0f, 5.0f, 8.0f, -3.0f}, - Vector4{4.5f, 4.0f, 7.0f, 2.0f}, - Vector4{1.0f, 2.0f, 3.0f, -1.0f}, - Vector4{7.9f, -1.0f, 8.0f, -1.5f}}; - constexpr Matrix2x2 b{Vector2{3.0f, 5.0f}, - Vector2{4.5f, 4.0f}}; - constexpr Matrix4x4 c{Vector4{3.0f, 5.0f, 0.0f, 0.0f}, - Vector4{4.5f, 4.0f, 0.0f, 0.0f}, - Vector4{0.0f, 0.0f, 1.0f, 0.0f}, - Vector4{0.0f, 0.0f, 0.0f, 1.0f}}; - - constexpr Matrix4x4 larger{b}; - CORRADE_COMPARE(larger, c); - CORRADE_COMPARE(Matrix4x4{b}, c); - - constexpr Matrix2x2 smaller{a}; - CORRADE_COMPARE(smaller, b); - CORRADE_COMPARE(Matrix2x2{a}, b); + /* Tested thoroughly in RectangularMatrixTest, verify just that the args + are propagated correctly (cols, rows, zero/identity, identity value) */ + constexpr Matrix2x3 a{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}}; + constexpr Matrix4x4 expectedIdentity{Vector4{3.0f, 5.0f, 8.0f, 0.0f}, + Vector4{4.5f, 4.0f, 7.0f, 0.0f}, + Vector4{0.0f, 0.0f, 0.5f, 0.0f}, + Vector4{0.0f, 0.0f, 0.0f, 0.5f}}; + constexpr Matrix4x4 expectedZero{Vector4{3.0f, 5.0f, 8.0f, 0.0f}, + Vector4{4.5f, 4.0f, 7.0f, 0.0f}, + Vector4{0.0f, 0.0f, 0.0f, 0.0f}, + Vector4{0.0f, 0.0f, 0.0f, 0.0f}}; + + constexpr Matrix4x4 identity1{a, 0.5f}; + constexpr Matrix4x4 identity2{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(identity1, expectedIdentity); + CORRADE_COMPARE(identity2, expectedIdentity); + CORRADE_COMPARE((Matrix4x4{a, 0.5f}), expectedIdentity); + CORRADE_COMPARE((Matrix4x4{IdentityInit, a, 0.5f}), expectedIdentity); + + constexpr Matrix4x4 zero{ZeroInit, a}; + CORRADE_COMPARE(zero, expectedZero); + CORRADE_COMPARE((Matrix4x4{ZeroInit, a}), expectedZero); } void MatrixTest::constructCopy() { diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index 948add31d..63b4525c3 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -65,6 +65,7 @@ struct RectangularMatrixTest: Corrade::TestSuite::Tester { void constructOneValue(); void constructOneComponent(); void constructConversion(); + void constructFromDifferentSize(); void constructFromData(); void constructFromDiagonal(); void constructCopy(); @@ -98,8 +99,13 @@ struct RectangularMatrixTest: Corrade::TestSuite::Tester { }; typedef RectangularMatrix<4, 3, Float> Matrix4x3; +typedef RectangularMatrix<4, 2, Float> Matrix4x2; typedef RectangularMatrix<3, 4, Float> Matrix3x4; +typedef RectangularMatrix<3, 3, Float> Matrix3x3; +typedef RectangularMatrix<3, 2, Float> Matrix3x2; typedef RectangularMatrix<2, 2, Float> Matrix2x2; +typedef RectangularMatrix<2, 3, Float> Matrix2x3; +typedef RectangularMatrix<2, 4, Float> Matrix2x4; typedef RectangularMatrix<2, 2, Int> Matrix2x2i; typedef Vector<4, Float> Vector4; typedef Vector<3, Float> Vector3; @@ -119,6 +125,7 @@ RectangularMatrixTest::RectangularMatrixTest() { &RectangularMatrixTest::constructOneValue, &RectangularMatrixTest::constructOneComponent, &RectangularMatrixTest::constructConversion, + &RectangularMatrixTest::constructFromDifferentSize, &RectangularMatrixTest::constructFromData, &RectangularMatrixTest::constructFromDiagonal, &RectangularMatrixTest::constructCopy, @@ -260,6 +267,65 @@ void RectangularMatrixTest::constructConversion() { CORRADE_VERIFY(std::is_nothrow_constructible::value); } +void RectangularMatrixTest::constructFromDifferentSize() { + /* Test converting to more columns, less rows */ + constexpr Matrix2x4 a{Vector4{3.0f, 5.0f, 8.0f, -3.0f}, + Vector4{4.5f, 4.0f, 7.0f, 2.0f}}; + constexpr Matrix3x2 aExpected{Vector2{3.0f, 5.0f}, + Vector2{4.5f, 4.0f}, + Vector2{0.0f, 0.0f}}; + constexpr Matrix3x3 aExpectedZero{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}, + Vector3{0.0f, 0.0f, 0.0f}}; + constexpr Matrix3x3 aExpectedIdentity{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}, + Vector3{0.0f, 0.0f, 0.5f}}; + + constexpr Matrix3x2 a2{a}; + CORRADE_COMPARE(a2, aExpected); + CORRADE_COMPARE(Matrix3x2{a}, aExpected); + + constexpr Matrix3x3 aZero1{a}; + constexpr Matrix3x3 aZero2{ZeroInit, a}; + CORRADE_COMPARE(aZero1, aExpectedZero); + CORRADE_COMPARE(aZero2, aExpectedZero); + CORRADE_COMPARE(Matrix3x3{a}, aExpectedZero); + CORRADE_COMPARE((Matrix3x3{ZeroInit, a}), aExpectedZero); + + constexpr Matrix3x3 aIdentity{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(aIdentity, aExpectedIdentity); + CORRADE_COMPARE((Matrix3x3{IdentityInit, aIdentity, 0.5f}), aExpectedIdentity); + + /* Test converting to less columns, more rows */ + constexpr Matrix4x2 b{Vector2{3.0f, 5.0f}, + Vector2{8.0f, -3.0f}, + Vector2{4.5f, 4.0f}, + Vector2{7.0f, 2.0f}}; + constexpr Matrix2x3 bExpected{Vector3{3.0f, 5.0f, 0.0f}, + Vector3{8.0f, -3.0f, 0.0f}}; + constexpr Matrix3x3 bExpectedZero{Vector3{3.0f, 5.0f, 0.0f}, + Vector3{8.0f, -3.0f, 0.0f}, + Vector3{4.5f, 4.0f, 0.0f}}; + constexpr Matrix3x3 bExpectedIdentity{Vector3{3.0f, 5.0f, 0.0f}, + Vector3{8.0f, -3.0f, 0.0f}, + Vector3{4.5f, 4.0f, 0.5f}}; + + constexpr Matrix2x3 b2{b}; + CORRADE_COMPARE(b2, bExpected); + CORRADE_COMPARE(Matrix2x3{b}, bExpected); + + constexpr Matrix3x3 bZero1{b}; + constexpr Matrix3x3 bZero2{ZeroInit, b}; + CORRADE_COMPARE(bZero1, bExpectedZero); + CORRADE_COMPARE(bZero2, bExpectedZero); + CORRADE_COMPARE(Matrix3x3{b}, bExpectedZero); + CORRADE_COMPARE((Matrix3x3{ZeroInit, b}), bExpectedZero); + + constexpr Matrix3x3 bIdentity{IdentityInit, b, 0.5f}; + CORRADE_COMPARE(bIdentity, bExpectedIdentity); + CORRADE_COMPARE((Matrix3x3{IdentityInit, bIdentity}), bExpectedIdentity); +} + void RectangularMatrixTest::constructFromData() { Float m[] = { 3.0f, 5.0f, 8.0f, 4.0f,