Browse Source

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.
pull/518/head
Vladimír Vondruš 5 years ago
parent
commit
7072befbdb
  1. 8
      doc/changelog.dox
  2. 27
      src/Magnum/Math/Matrix.h
  3. 17
      src/Magnum/Math/Matrix3.h
  4. 17
      src/Magnum/Math/Matrix4.h
  5. 52
      src/Magnum/Math/RectangularMatrix.h
  6. 39
      src/Magnum/Math/Test/Matrix3Test.cpp
  7. 46
      src/Magnum/Math/Test/Matrix4Test.cpp
  8. 58
      src/Magnum/Math/Test/MatrixTest.cpp
  9. 66
      src/Magnum/Math/Test/RectangularMatrixTest.cpp

8
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

27
src/Magnum/Math/Matrix.h

@ -35,15 +35,6 @@ namespace Magnum { namespace Math {
namespace Implementation {
template<std::size_t, class> struct MatrixDeterminant;
template<std::size_t size, std::size_t col, std::size_t otherSize, class T, std::size_t ...row> constexpr Vector<size, T> valueOrIdentityVector(Corrade::Containers::Implementation::Sequence<row...>, const RectangularMatrix<otherSize, otherSize, T>& other) {
return {(col < otherSize && row < otherSize ? other[col][row] :
col == row ? T{1} : T{0})...};
}
template<std::size_t size, std::size_t col, std::size_t otherSize, class T> constexpr Vector<size, T> valueOrIdentityVector(const RectangularMatrix<otherSize, otherSize, T>& other) {
return valueOrIdentityVector<size, col>(typename Corrade::Containers::Implementation::GenerateSequence<size>::Type{}, other);
}
}
/**
@ -107,14 +98,21 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
/** @brief Construct matrix from external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<size, size, T, U>::from(std::declval<U>()))> constexpr explicit Matrix(const U& other): RectangularMatrix<size, size, T>(Implementation::RectangularMatrixConverter<size, size, T, U>::from(other)) {}
/** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>&, T) */
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>& other, T value = T(1)) noexcept: RectangularMatrix<size, size, T>{IdentityInit, other, value} {}
/** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>&) */
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>& other) noexcept: RectangularMatrix<size, size, T>{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<otherCols, otherRows, T>&, T).
* Note that this default is different from @ref RectangularMatrix,
* where it's equivalent to the @ref ZeroInit variant instead.
*/
template<std::size_t otherSize> constexpr explicit Matrix(const RectangularMatrix<otherSize, otherSize, T>& other) noexcept: Matrix<size, T>{typename Corrade::Containers::Implementation::GenerateSequence<size>::Type{}, other} {}
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix(const RectangularMatrix<otherCols, otherRows, T>& other, T value = T(1)) noexcept: RectangularMatrix<size, size, T>{IdentityInit, other, value} {}
/** @brief Copy constructor */
constexpr /*implicit*/ Matrix(const RectangularMatrix<size, size, T>& other) noexcept: RectangularMatrix<size, size, T>(other) {}
@ -300,9 +298,6 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
private:
friend struct Implementation::MatrixDeterminant<size, T>;
/* Implementation for RectangularMatrix<cols, rows, T>::RectangularMatrix(const RectangularMatrix<cols, rows, U>&) */
template<std::size_t otherSize, std::size_t ...col> constexpr explicit Matrix(Corrade::Containers::Implementation::Sequence<col...>, const RectangularMatrix<otherSize, otherSize, T>& other) noexcept: RectangularMatrix<size, size, T>{Implementation::valueOrIdentityVector<size, col>(other)...} {}
};
/**

17
src/Magnum/Math/Matrix3.h

@ -234,14 +234,21 @@ template<class T> class Matrix3: public Matrix3x3<T> {
/** @brief Construct a matrix from external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(std::declval<U>()))> constexpr explicit Matrix3(const U& other) noexcept: Matrix3x3<T>(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {}
/** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>&, T) */
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix3(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>& other, T value = T(1)) noexcept: Matrix3x3<T>{IdentityInit, other, value} {}
/** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>&) */
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix3(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>& other) noexcept: Matrix3x3<T>{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<otherCols, otherRows, T>&, T).
* Note that this default is different from @ref RectangularMatrix,
* where it's equivalent to the @ref ZeroInit variant instead.
*/
template<std::size_t otherSize> constexpr explicit Matrix3(const RectangularMatrix<otherSize, otherSize, T>& other) noexcept: Matrix3x3<T>{other} {}
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix3(const RectangularMatrix<otherCols, otherRows, T>& other, T value = T(1)) noexcept: Matrix3x3<T>{IdentityInit, other, value} {}
/** @brief Copy constructor */
constexpr /*implicit*/ Matrix3(const RectangularMatrix<3, 3, T>& other) noexcept: Matrix3x3<T>(other) {}

17
src/Magnum/Math/Matrix4.h

@ -467,14 +467,21 @@ template<class T> class Matrix4: public Matrix4x4<T> {
/** @brief Construct a matrix from external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(std::declval<U>()))> constexpr explicit Matrix4(const U& other): Matrix4x4<T>(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {}
/** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>&, T) */
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix4(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>& other, T value = T(1)) noexcept: Matrix4x4<T>{IdentityInit, other, value} {}
/** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>&) */
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix4(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>& other) noexcept: Matrix4x4<T>{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<otherCols, otherRows, T>&, T).
* Note that this default is different from @ref RectangularMatrix,
* where it's equivalent to the @ref ZeroInit variant instead.
*/
template<std::size_t otherSize> constexpr explicit Matrix4(const RectangularMatrix<otherSize, otherSize, T>& other) noexcept: Matrix4x4<T>{other} {}
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit Matrix4(const RectangularMatrix<otherCols, otherRows, T>& other, T value = T(1)) noexcept: Matrix4x4<T>{IdentityInit, other, value} {}
/** @brief Copy constructor */
constexpr /*implicit*/ Matrix4(const RectangularMatrix<4, 4, T>& other) noexcept: Matrix4x4<T>(other) {}

52
src/Magnum/Math/RectangularMatrix.h

@ -35,6 +35,23 @@ namespace Magnum { namespace Math {
namespace Implementation {
template<std::size_t, std::size_t, class, class> struct RectangularMatrixConverter;
template<std::size_t cols, std::size_t rows, std::size_t otherCols, std::size_t otherRows, class T, std::size_t col, std::size_t ...row> constexpr Vector<rows, T> valueOrZeroVector(Corrade::Containers::Implementation::Sequence<row...>, const RectangularMatrix<otherCols, otherRows, T>& other) {
return {(col < otherCols && row < otherRows ? other[col][row] : T{0})...};
}
template<std::size_t cols, std::size_t rows, std::size_t otherCols, std::size_t otherRows, class T, std::size_t col> constexpr Vector<rows, T> valueOrZeroVector(const RectangularMatrix<otherCols, otherRows, T>& other) {
return valueOrZeroVector<cols, rows, otherCols, otherRows, T, col>(typename Corrade::Containers::Implementation::GenerateSequence<rows>::Type{}, other);
}
template<std::size_t cols, std::size_t rows, std::size_t otherCols, std::size_t otherRows, class T, std::size_t col, std::size_t ...row> constexpr Vector<rows, T> valueOrIdentityVector(Corrade::Containers::Implementation::Sequence<row...>, const RectangularMatrix<otherCols, otherRows, T>& other, T value) {
return {(col < otherCols && row < otherRows ? other[col][row] :
col == row ? value : T{0})...};
}
template<std::size_t cols, std::size_t rows, std::size_t otherCols, std::size_t otherRows, class T, std::size_t col> constexpr Vector<rows, T> valueOrIdentityVector(const RectangularMatrix<otherCols, otherRows, T>& other, T value) {
return valueOrIdentityVector<cols, rows, otherCols, otherRows, T, col>(typename Corrade::Containers::Implementation::GenerateSequence<rows>::Type{}, other, value);
}
}
/**
@ -162,6 +179,35 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
*/
template<class U> constexpr explicit RectangularMatrix(const RectangularMatrix<cols, rows, U>& other) noexcept: RectangularMatrix(typename Corrade::Containers::Implementation::GenerateSequence<cols>::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<std::size_t otherCols, std::size_t otherRows> constexpr explicit RectangularMatrix(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>& other) noexcept: RectangularMatrix<cols, rows, T>{ZeroInit, typename Corrade::Containers::Implementation::GenerateSequence<cols>::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<std::size_t otherCols, std::size_t otherRows> constexpr explicit RectangularMatrix(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>& other, T value = T(1)) noexcept: RectangularMatrix<cols, rows, T>{IdentityInit, typename Corrade::Containers::Implementation::GenerateSequence<cols>::Type{}, other, value} {}
/**
* @brief Construct by slicing or expanding a matrix of different size
* @m_since_latest
*
* Equivalent to @ref RectangularMatrix(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>&).
* Note that this default is different from @ref Matrix, where it's
* equivalent to the @ref IdentityInit variant instead.
*/
template<std::size_t otherCols, std::size_t otherRows> constexpr explicit RectangularMatrix(const RectangularMatrix<otherCols, otherRows, T>& other) noexcept: RectangularMatrix<cols, rows, T>{ZeroInit, typename Corrade::Containers::Implementation::GenerateSequence<cols>::Type{}, other} {}
/** @brief Construct a matrix from external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<cols, rows, T, U>::from(std::declval<U>()))> constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter<cols, rows, T, U>::from(other)) {}
@ -472,6 +518,12 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/* Implementation for RectangularMatrix<cols, rows, T>::RectangularMatrix(const RectangularMatrix<cols, rows, U>&) */
template<class U, std::size_t ...sequence> constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence<sequence...>, const RectangularMatrix<cols, rows, U>& matrix) noexcept: _data{Vector<rows, T>(matrix[sequence])...} {}
/* Implementation for RectangularMatrix<cols, rows, T>::RectangularMatrix(ZeroInitT, const RectangularMatrix<otherCols, otherRows, T>&) */
template<std::size_t otherCols, std::size_t otherRows, std::size_t ...col> constexpr explicit RectangularMatrix(ZeroInitT, Corrade::Containers::Implementation::Sequence<col...>, const RectangularMatrix<otherCols, otherRows, T>& other) noexcept: RectangularMatrix<cols, rows, T>{Implementation::valueOrZeroVector<cols, rows, otherCols, otherRows, T, col>(other)...} {}
/* Implementation for RectangularMatrix<cols, rows, T>::RectangularMatrix(IdentityInitT, const RectangularMatrix<otherCols, otherRows, T>&) */
template<std::size_t otherCols, std::size_t otherRows, std::size_t ...col> constexpr explicit RectangularMatrix(IdentityInitT, Corrade::Containers::Implementation::Sequence<col...>, const RectangularMatrix<otherCols, otherRows, T>& other, T value) noexcept: RectangularMatrix<cols, rows, T>{Implementation::valueOrIdentityVector<cols, rows, otherCols, otherRows, T, col>(other, value)...} {}
/* Implementation for RectangularMatrix<cols, rows, T>::RectangularMatrix(ZeroInitT) and RectangularMatrix<cols, rows, T>::RectangularMatrix(NoInitT) */
/* MSVC 2015 can't handle {} here */
template<class U, std::size_t ...sequence> constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence<sequence...>, U) noexcept: _data{Vector<rows, T>((static_cast<void>(sequence), U{typename U::Init{}}))...} {}

39
src/Magnum/Math/Test/Matrix3Test.cpp

@ -105,10 +105,12 @@ struct Matrix3Test: Corrade::TestSuite::Tester {
typedef Math::Deg<Float> Deg;
typedef Math::Matrix2x2<Float> Matrix2x2;
typedef Math::Matrix2x4<Float> Matrix2x4;
typedef Math::Matrix3<Float> Matrix3;
typedef Math::Matrix3<Int> Matrix3i;
typedef Math::Vector2<Float> Vector2;
typedef Math::Vector3<Float> 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() {

46
src/Magnum/Math/Test/Matrix4Test.cpp

@ -122,8 +122,9 @@ struct Matrix4Test: Corrade::TestSuite::Tester {
typedef Math::Deg<Float> Deg;
typedef Math::Rad<Float> Rad;
typedef Math::Matrix<2, Float> Matrix2x2;
typedef Math::Matrix<3, Float> Matrix3x3;
typedef Math::Matrix2x2<Float> Matrix2x2;
typedef Math::Matrix2x3<Float> Matrix2x3;
typedef Math::Matrix3x3<Float> Matrix3x3;
typedef Math::Matrix4<Float> Matrix4;
typedef Math::Matrix4<Int> Matrix4i;
typedef Math::Vector2<Float> 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() {

58
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<Float> Matrix2x2;
typedef Math::Matrix2x3<Float> Matrix2x3;
typedef Math::Matrix3x3<Float> Matrix3x3;
typedef Math::Matrix4x4<Float> Matrix4x4;
typedef Math::Matrix4x4<Int> 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<Float> 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() {

66
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<Matrix2x2, Matrix2x2i>::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,

Loading…
Cancel
Save