From b648f9674c767fbde54807d928e539c6cd595c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 5 Jan 2014 19:52:26 +0100 Subject: [PATCH] Math: constexpr *Matrix::{fromDiagonal,diagonal}() and also Matrix(T). Besides all the good things it is now possible to do even more insane and useless constexpr-fu: constexpr auto a = Math::Matrix3x3::fromDiagonal({1, 3, 2}); /* 7 0 0 7 */ constexpr Math::Matrix c(7); --- src/Math/Matrix.h | 6 +-- src/Math/Matrix3.h | 7 +--- src/Math/Matrix4.h | 8 +--- src/Math/RectangularMatrix.h | 51 ++++++++++++++----------- src/Math/Test/MatrixTest.cpp | 6 +-- src/Math/Test/RectangularMatrixTest.cpp | 30 ++++++++------- 6 files changed, 51 insertions(+), 57 deletions(-) diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index 0a4165e21..f6f998cd4 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -69,12 +69,8 @@ template class Matrix: public RectangularMatrix(typename Implementation::GenerateSequence::Type(), Vector(value)) {} /** * @brief %Matrix from column vectors diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index cbcc8e972..60a64ddcd 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -128,13 +128,8 @@ template class Matrix3: public Matrix<3, T> { * Creates identity matrix. You can also explicitly call this * constructor with `Matrix3 m(Matrix3::Identity);`. Optional parameter * @p value allows you to specify value on diagonal. - * @todo Use constexpr implementation in Matrix, when done */ - constexpr /*implicit*/ Matrix3(typename Matrix<3, T>::IdentityType = (Matrix<3, T>::Identity), T value = T(1)): Matrix<3, T>( - Vector<3, T>(value, T(0), T(0)), - Vector<3, T>( T(0), value, T(0)), - Vector<3, T>( T(0), T(0), value) - ) {} + constexpr /*implicit*/ Matrix3(typename Matrix<3, T>::IdentityType identity = (Matrix<3, T>::Identity), T value = T(1)): Matrix<3, T>(identity, value) {} /** @brief %Matrix from column vectors */ constexpr /*implicit*/ Matrix3(const Vector3& first, const Vector3& second, const Vector3& third): Matrix<3, T>(first, second, third) {} diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index c71dfe634..e1270c132 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -190,14 +190,8 @@ template class Matrix4: public Matrix<4, T> { * Creates identity matrix. You can also explicitly call this * constructor with `Matrix4 m(Matrix4::Identity);`. Optional parameter * @p value allows you to specify value on diagonal. - * @todo Use constexpr implementation in Matrix, when done */ - constexpr /*implicit*/ Matrix4(typename Matrix<4, T>::IdentityType = (Matrix<4, T>::Identity), T value = T(1)): Matrix<4, T>( - Vector<4, T>(value, T(0), T(0), T(0)), - Vector<4, T>( T(0), value, T(0), T(0)), - Vector<4, T>( T(0), T(0), value, T(0)), - Vector<4, T>( T(0), T(0), T(0), value) - ) {} + constexpr /*implicit*/ Matrix4(typename Matrix<4, T>::IdentityType = (Matrix<4, T>::Identity), T value = T(1)): Matrix<4, T>({}, value) {} /** @brief %Matrix from column vectors */ constexpr /*implicit*/ Matrix4(const Vector4& first, const Vector4& second, const Vector4& third, const Vector4& fourth): Matrix<4, T>(first, second, third, fourth) {} diff --git a/src/Math/RectangularMatrix.h b/src/Math/RectangularMatrix.h index 244100af0..311d545c7 100644 --- a/src/Math/RectangularMatrix.h +++ b/src/Math/RectangularMatrix.h @@ -84,14 +84,6 @@ template class RectangularMatrix { return *reinterpret_cast*>(data); } - /** - * @brief Construct diagonal matrix - * - * @see diagonal() - * @todo make this constexpr - */ - static RectangularMatrix fromDiagonal(const Vector& diagonal); - /** * @brief Construct matrix from vector * @@ -103,6 +95,15 @@ template class RectangularMatrix { return *reinterpret_cast*>(vector.data()); } + /** + * @brief Construct diagonal matrix + * + * @see diagonal() + */ + constexpr static RectangularMatrix fromDiagonal(const Vector& diagonal) { + return RectangularMatrix(typename Implementation::GenerateSequence::Type(), diagonal); + } + /** @brief Construct zero-filled matrix */ constexpr /*implicit*/ RectangularMatrix() {} @@ -342,9 +343,8 @@ template class RectangularMatrix { * @brief Values on diagonal * * @see fromDiagonal() - * @todo constexpr */ - Vector diagonal() const; + constexpr Vector diagonal() const; /** * @brief Convert matrix to vector @@ -359,10 +359,16 @@ template class RectangularMatrix { return *reinterpret_cast*>(data()); } + protected: + /* Implementation for RectangularMatrix::fromDiagonal() and Matrix(T) */ + template constexpr explicit RectangularMatrix(Implementation::Sequence, const Vector& diagonal); + private: /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ template constexpr explicit RectangularMatrix(Implementation::Sequence, const RectangularMatrix& matrix): _data{Vector(matrix[sequence])...} {} + template constexpr Vector diagonalInternal(Implementation::Sequence) const; + Vector _data[cols]; }; @@ -593,15 +599,17 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit } #endif -template inline RectangularMatrix RectangularMatrix::fromDiagonal(const Vector& diagonal) { - RectangularMatrix out; - - for(std::size_t i = 0; i != DiagonalSize; ++i) - out[i][i] = diagonal[i]; - - return out; +namespace Implementation { + template inline constexpr Vector diagonalMatrixColumn2(Implementation::Sequence, const T& number) { + return {(sequence == i ? number : T(0))...}; + } + template inline constexpr Vector diagonalMatrixColumn(const T& number) { + return diagonalMatrixColumn2(typename Implementation::GenerateSequence::Type(), number); + } } +template template inline constexpr RectangularMatrix::RectangularMatrix(Implementation::Sequence, const Vector& diagonal): _data{Implementation::diagonalMatrixColumn(sequence < DiagonalSize ? diagonal[sequence] : T{})...} {} + template inline Vector RectangularMatrix::row(std::size_t row) const { Vector out; @@ -641,13 +649,10 @@ template inline RectangularMatrix auto RectangularMatrix::diagonal() const -> Vector { - Vector out; - - for(std::size_t i = 0; i != DiagonalSize; ++i) - out[i] = _data[i][i]; +template inline constexpr auto RectangularMatrix::diagonal() const -> Vector { return diagonalInternal(typename Implementation::GenerateSequence::Type()); } - return out; +template template inline constexpr auto RectangularMatrix::diagonalInternal(Implementation::Sequence) const -> Vector { + return {(*this)[sequence][sequence]...}; } }} diff --git a/src/Math/Test/MatrixTest.cpp b/src/Math/Test/MatrixTest.cpp index 5e8c905b9..ff67f4e30 100644 --- a/src/Math/Test/MatrixTest.cpp +++ b/src/Math/Test/MatrixTest.cpp @@ -126,9 +126,9 @@ void MatrixTest::construct() { } void MatrixTest::constructIdentity() { - Matrix4x4 identity; - Matrix4x4 identity2(Matrix4x4::Identity); - Matrix4x4 identity3(Matrix4x4::Identity, 4.0f); + constexpr Matrix4x4 identity; + constexpr Matrix4x4 identity2(Matrix4x4::Identity); + constexpr Matrix4x4 identity3(Matrix4x4::Identity, 4.0f); Matrix4x4 identityExpected(Vector4(1.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 1.0f, 0.0f, 0.0f), diff --git a/src/Math/Test/RectangularMatrixTest.cpp b/src/Math/Test/RectangularMatrixTest.cpp index 872c253ee..d53544fa4 100644 --- a/src/Math/Test/RectangularMatrixTest.cpp +++ b/src/Math/Test/RectangularMatrixTest.cpp @@ -181,18 +181,20 @@ void RectangularMatrixTest::constructFromData() { } void RectangularMatrixTest::constructFromDiagonal() { - Vector3 diagonal(-1.0f, 5.0f, 11.0f); + constexpr Vector3 diagonal(-1.0f, 5.0f, 11.0f); + constexpr auto a = Matrix3x4::fromDiagonal(diagonal); Matrix3x4 expectedA(Vector4(-1.0f, 0.0f, 0.0f, 0.0f), Vector4( 0.0f, 5.0f, 0.0f, 0.0f), Vector4( 0.0f, 0.0f, 11.0f, 0.0f)); - CORRADE_COMPARE(Matrix3x4::fromDiagonal(diagonal), expectedA); + CORRADE_COMPARE(a, expectedA); + constexpr auto b = Matrix4x3::fromDiagonal(diagonal); Matrix4x3 expectedB(Vector3(-1.0f, 0.0f, 0.0f), Vector3( 0.0f, 5.0f, 0.0f), Vector3( 0.0f, 0.0f, 11.0f), Vector3( 0.0f, 0.0f, 0.0f)); - CORRADE_COMPARE(Matrix4x3::fromDiagonal(diagonal), expectedB); + CORRADE_COMPARE(b, expectedB); } void RectangularMatrixTest::constructCopy() { @@ -387,16 +389,18 @@ void RectangularMatrixTest::transposed() { void RectangularMatrixTest::diagonal() { Vector3 diagonal(-1.0f, 5.0f, 11.0f); - Matrix4x3 a(Vector3(-1.0f, 1.0f, 3.0f), - Vector3( 4.0f, 5.0f, 7.0f), - Vector3( 8.0f, 9.0f, 11.0f), - Vector3(12.0f, 13.0f, 15.0f)); - CORRADE_COMPARE(a.diagonal(), diagonal); - - Matrix3x4 b(Vector4(-1.0f, 4.0f, 8.0f, 12.0f), - Vector4( 1.0f, 5.0f, 9.0f, 13.0f), - Vector4( 3.0f, 7.0f, 11.0f, 15.0f)); - CORRADE_COMPARE(b.diagonal(), diagonal); + constexpr Matrix4x3 a(Vector3(-1.0f, 1.0f, 3.0f), + Vector3( 4.0f, 5.0f, 7.0f), + Vector3( 8.0f, 9.0f, 11.0f), + Vector3(12.0f, 13.0f, 15.0f)); + constexpr Vector3 aDiagonal = a.diagonal(); + CORRADE_COMPARE(aDiagonal, diagonal); + + constexpr Matrix3x4 b(Vector4(-1.0f, 4.0f, 8.0f, 12.0f), + Vector4( 1.0f, 5.0f, 9.0f, 13.0f), + Vector4( 3.0f, 7.0f, 11.0f, 15.0f)); + constexpr Vector3 bDiagonal = b.diagonal(); + CORRADE_COMPARE(bDiagonal, diagonal); } void RectangularMatrixTest::vector() {