From 7c857ccb165366ce1f47deaab300a32d974536c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 3 Apr 2012 22:32:33 +0200 Subject: [PATCH] Better implementation for Matrix::determinant() using external functor. Removes lots of unmaintained and duplicated code from Matrix template specialization. --- doc/namespaces.dox | 4 +++ src/Math/Matrix.h | 62 +++++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 4a7054097..8e0adb2ca 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -15,3 +15,7 @@ Basic primitives for testing purposes. Collection of shaders for testing purposes. */ + +/** @namespace Magnum::Math::Implementation +@brief Internal math implementation +*/ diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index 1a8acc2c8..930508014 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -23,6 +23,10 @@ namespace Magnum { namespace Math { +namespace Implementation { + template class MatrixDeterminant; +} + /** * @brief %Matrix * @@ -187,14 +191,7 @@ template class Matrix { * matrix, where the determinant is computed directly. Complexity is * O(n!), the same as when computing the determinant directly. */ - T determinant() const { - T out(0); - - for(size_t col = 0; col != size; ++col) - out += ((col & 1) ? -1 : 1)*at(0, col)*ij(0, col).determinant(); - - return out; - } + inline T determinant() const { return Implementation::MatrixDeterminant()(*this); } /** * @brief Inverse matrix @@ -216,32 +213,41 @@ template class Matrix { T _data[size*size]; }; -#ifndef DOXYGEN_GENERATING_OUTPUT -/* Barebone template specialization for 2x2 matrix (only for determinant computation) */ -template class Matrix { +namespace Implementation { + +/** @brief Matrix determinant implementation for >2x2 matrices */ +template class MatrixDeterminant { public: - inline Matrix(bool identity = true): _data() { - if(identity) { - set(0, 0, T(1)); - set(1, 1, T(1)); - } - } - inline Matrix& operator=(const Matrix& other) { - if(&other != this) setData(other.data()); - return *this; + /** @brief Functor */ + T operator()(const Matrix& m) { + T out(0); + + for(size_t col = 0; col != size; ++col) + out += ((col & 1) ? -1 : 1)*m.at(0, col)*m.ij(0, col).determinant(); + + return out; } - inline void setData(const T* data) { memcpy(_data, data, 4*sizeof(T)); } - inline T at(size_t row, size_t col) const { return _data[col*2+row]; } - inline void set(size_t row, size_t col, T value) { _data[col*2+row] = value; } +}; - T determinant() const { - return at(0, 0)*at(1, 1) - at(0, 1)*at(1, 0); +/** @brief Matrix determinant implementation for 2x2 matrix */ +template class MatrixDeterminant { + public: + /** @brief Functor */ + inline constexpr T operator()(const Matrix& m) { + return m.at(0, 0)*m.at(1, 1) - m.at(0, 1)*m.at(1, 0); } +}; - private: - T _data[4]; +/** @brief Matrix determinant implementation for 1x1 matrix */ +template class MatrixDeterminant { + public: + /** @brief Functor */ + inline constexpr T operator()(const Matrix& m) { + return m.at(0, 0); + } }; -#endif + +} #ifndef DOXYGEN_GENERATING_OUTPUT template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix& value) {