Browse Source

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<Int>::fromDiagonal({1, 3, 2});

   /* 7 0
      0 7 */
   constexpr Math::Matrix<a.diagonal()[2], Int> c(7);
pull/51/head
Vladimír Vondruš 13 years ago
parent
commit
b648f9674c
  1. 6
      src/Math/Matrix.h
  2. 7
      src/Math/Matrix3.h
  3. 8
      src/Math/Matrix4.h
  4. 51
      src/Math/RectangularMatrix.h
  5. 6
      src/Math/Test/MatrixTest.cpp
  6. 30
      src/Math/Test/RectangularMatrixTest.cpp

6
src/Math/Matrix.h

@ -69,12 +69,8 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
* You can also explicitly call this constructor with
* `Matrix m(Matrix::Identity);`. Optional parameter @p value allows
* you to specify value on diagonal.
* @todo use constexpr fromDiagonal() for this when it's done
*/
/*implicit*/ Matrix(IdentityType = Identity, T value = T(1)) {
for(std::size_t i = 0; i != size; ++i)
(*this)[i][i] = value;
}
constexpr /*implicit*/ Matrix(IdentityType = Identity, T value = T(1)): RectangularMatrix<size, size, T>(typename Implementation::GenerateSequence<size>::Type(), Vector<size, T>(value)) {}
/**
* @brief %Matrix from column vectors

7
src/Math/Matrix3.h

@ -128,13 +128,8 @@ template<class T> 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<T>& first, const Vector3<T>& second, const Vector3<T>& third): Matrix<3, T>(first, second, third) {}

8
src/Math/Matrix4.h

@ -190,14 +190,8 @@ template<class T> 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<T>& first, const Vector4<T>& second, const Vector4<T>& third, const Vector4<T>& fourth): Matrix<4, T>(first, second, third, fourth) {}

51
src/Math/RectangularMatrix.h

@ -84,14 +84,6 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
return *reinterpret_cast<const RectangularMatrix<cols, rows, T>*>(data);
}
/**
* @brief Construct diagonal matrix
*
* @see diagonal()
* @todo make this constexpr
*/
static RectangularMatrix<cols, rows, T> fromDiagonal(const Vector<DiagonalSize, T>& diagonal);
/**
* @brief Construct matrix from vector
*
@ -103,6 +95,15 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
return *reinterpret_cast<const RectangularMatrix<cols, rows, T>*>(vector.data());
}
/**
* @brief Construct diagonal matrix
*
* @see diagonal()
*/
constexpr static RectangularMatrix<cols, rows, T> fromDiagonal(const Vector<DiagonalSize, T>& diagonal) {
return RectangularMatrix(typename Implementation::GenerateSequence<cols>::Type(), diagonal);
}
/** @brief Construct zero-filled matrix */
constexpr /*implicit*/ RectangularMatrix() {}
@ -342,9 +343,8 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* @brief Values on diagonal
*
* @see fromDiagonal()
* @todo constexpr
*/
Vector<DiagonalSize, T> diagonal() const;
constexpr Vector<DiagonalSize, T> diagonal() const;
/**
* @brief Convert matrix to vector
@ -359,10 +359,16 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
return *reinterpret_cast<const Vector<rows*cols, T>*>(data());
}
protected:
/* Implementation for RectangularMatrix<cols, rows, T>::fromDiagonal() and Matrix<size, T>(T) */
template<std::size_t ...sequence> constexpr explicit RectangularMatrix(Implementation::Sequence<sequence...>, const Vector<DiagonalSize, T>& diagonal);
private:
/* Implementation for RectangularMatrix<cols, rows, T>::RectangularMatrix(const RectangularMatrix<cols, rows, U>&) */
template<class U, std::size_t ...sequence> constexpr explicit RectangularMatrix(Implementation::Sequence<sequence...>, const RectangularMatrix<cols, rows, U>& matrix): _data{Vector<rows, T>(matrix[sequence])...} {}
template<std::size_t ...sequence> constexpr Vector<DiagonalSize, T> diagonalInternal(Implementation::Sequence<sequence...>) const;
Vector<rows, T> _data[cols];
};
@ -593,15 +599,17 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
}
#endif
template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> RectangularMatrix<cols, rows, T>::fromDiagonal(const Vector<DiagonalSize, T>& diagonal) {
RectangularMatrix<cols, rows, T> out;
for(std::size_t i = 0; i != DiagonalSize; ++i)
out[i][i] = diagonal[i];
return out;
namespace Implementation {
template<std::size_t rows, std::size_t i, class T, std::size_t ...sequence> inline constexpr Vector<rows, T> diagonalMatrixColumn2(Implementation::Sequence<sequence...>, const T& number) {
return {(sequence == i ? number : T(0))...};
}
template<std::size_t rows, std::size_t i, class T> inline constexpr Vector<rows, T> diagonalMatrixColumn(const T& number) {
return diagonalMatrixColumn2<rows, i, T>(typename Implementation::GenerateSequence<rows>::Type(), number);
}
}
template<std::size_t cols, std::size_t rows, class T> template<std::size_t ...sequence> inline constexpr RectangularMatrix<cols, rows, T>::RectangularMatrix(Implementation::Sequence<sequence...>, const Vector<DiagonalSize, T>& diagonal): _data{Implementation::diagonalMatrixColumn<rows, sequence>(sequence < DiagonalSize ? diagonal[sequence] : T{})...} {}
template<std::size_t cols, std::size_t rows, class T> inline Vector<cols, T> RectangularMatrix<cols, rows, T>::row(std::size_t row) const {
Vector<cols, T> out;
@ -641,13 +649,10 @@ template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<r
return out;
}
template<std::size_t cols, std::size_t rows, class T> auto RectangularMatrix<cols, rows, T>::diagonal() const -> Vector<DiagonalSize, T> {
Vector<DiagonalSize, T> out;
for(std::size_t i = 0; i != DiagonalSize; ++i)
out[i] = _data[i][i];
template<std::size_t cols, std::size_t rows, class T> inline constexpr auto RectangularMatrix<cols, rows, T>::diagonal() const -> Vector<DiagonalSize, T> { return diagonalInternal(typename Implementation::GenerateSequence<DiagonalSize>::Type()); }
return out;
template<std::size_t cols, std::size_t rows, class T> template<std::size_t ...sequence> inline constexpr auto RectangularMatrix<cols, rows, T>::diagonalInternal(Implementation::Sequence<sequence...>) const -> Vector<DiagonalSize, T> {
return {(*this)[sequence][sequence]...};
}
}}

6
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),

30
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() {

Loading…
Cancel
Save