From bf58bb3cb1e717489961bea7353c7cec90b65245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 11 Apr 2013 15:34:58 +0200 Subject: [PATCH] Math: rework of component-wise matrix and vector functions. First, removed functions which can be done with Vector's member functions and functions from Functions.h. More flexibility and less redundant code which leads to easier SIMD implementation later. Vector4 a; Float b = a.maxAbs(); // before Float b = Math::abs(a).max(); // now Second, removed all functions from RectangularMatrix which are implemented in Vector and added conversion from RectangularMatrix to Vector and back. Also for more flexibility and less redundant code (i.e. reusing SIMD-optimized Vector::max() instead of writing it again). Matrix4x3 a; Float b = a.max(); // before Float b = a.toVector().max(); // now --- src/Math/Algorithms/Test/SvdTest.cpp | 4 +- src/Math/Functions.h | 4 +- src/Math/RectangularMatrix.h | 80 +++++++------------------ src/Math/Test/RectangularMatrixTest.cpp | 66 ++++---------------- src/Math/Test/VectorTest.cpp | 16 ----- src/Math/Vector.h | 48 +++++++-------- 6 files changed, 61 insertions(+), 157 deletions(-) diff --git a/src/Math/Algorithms/Test/SvdTest.cpp b/src/Math/Algorithms/Test/SvdTest.cpp index 3397f92f3..c46448fc4 100644 --- a/src/Math/Algorithms/Test/SvdTest.cpp +++ b/src/Math/Algorithms/Test/SvdTest.cpp @@ -107,14 +107,14 @@ void SvdTest::testFloat() { /* Test composition (single precision is not enough, test for similarity) */ Matrix8f u2(u[0], u[1], u[2], u[3], u[4], Vector8f(), Vector8f(), Vector8f()); Matrix5x8f w2 = Matrix5x8f::fromDiagonal(w); - CORRADE_VERIFY((u2*w2*v.transposed()-af).maxAbs() < 1.0e-5f); + CORRADE_VERIFY(Math::abs((u2*w2*v.transposed()-af).toVector()).max() < 1.0e-5f); /* Test that V is unitary */ CORRADE_COMPARE(v*v.transposed(), Matrix5f(Matrix5f::Identity)); CORRADE_COMPARE(v.transposed()*v, Matrix5f(Matrix5f::Identity)); /* Test W (single precision is not enough, test for similarity) */ - CORRADE_VERIFY((w-expectedf).maxAbs() < 1.0e-5f); + CORRADE_VERIFY(Math::abs(w-expectedf).max() < 1.0e-5f); } }}}} diff --git a/src/Math/Functions.h b/src/Math/Functions.h index f5af1e56a..fb4bafd1b 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -126,7 +126,7 @@ perform the operations component-wise. /** @brief Minimum -@see min(), clamp() +@see min(), clamp(), Vector::min() */ #ifdef DOXYGEN_GENERATING_OUTPUT template inline T min(T a, T b); @@ -145,7 +145,7 @@ template inline Vector min(const Vector inline T max(const T& a, const T& b); diff --git a/src/Math/RectangularMatrix.h b/src/Math/RectangularMatrix.h index fb869992d..48b86a3f8 100644 --- a/src/Math/RectangularMatrix.h +++ b/src/Math/RectangularMatrix.h @@ -96,6 +96,17 @@ template class RectangularMatrix { return out; } + /** + * @brief Construct matrix from vector + * + * Rolls the vector into matrix, i.e. first `rows` elements of the + * vector will make first column of resulting matrix. + * @see toVector() + */ + inline static RectangularMatrix fromVector(const Vector& vector) { + return *reinterpret_cast*>(vector.data()); + } + /** @brief Construct zero-filled matrix */ inline constexpr /*implicit*/ RectangularMatrix() {} @@ -381,64 +392,17 @@ template class RectangularMatrix { return out; } - /** @brief Sum of values in the matrix */ - T sum() const { - T out(_data[0].sum()); - - for(std::size_t i = 1; i != cols; ++i) - out += _data[i].sum(); - - return out; - } - - /** @brief Product of values in the matrix */ - T product() const { - T out(_data[0].product()); - - for(std::size_t i = 1; i != cols; ++i) - out *= _data[i].product(); - - return out; - } - - /** @brief Minimal value in the matrix */ - T min() const { - T out(_data[0].min()); - - for(std::size_t i = 1; i != cols; ++i) - out = std::min(out, _data[i].min()); - - return out; - } - - /** @brief Minimal absolute value in the matrix */ - T minAbs() const { - T out(_data[0].minAbs()); - - for(std::size_t i = 1; i != cols; ++i) - out = std::min(out, _data[i].minAbs()); - - return out; - } - - /** @brief Maximal value in the matrix */ - T max() const { - T out(_data[0].max()); - - for(std::size_t i = 1; i != cols; ++i) - out = std::max(out, _data[i].max()); - - return out; - } - - /** @brief Maximal absolute value in the matrix */ - T maxAbs() const { - T out(_data[0].maxAbs()); - - for(std::size_t i = 1; i != cols; ++i) - out = std::max(out, _data[i].maxAbs()); - - return out; + /** + * @brief Convert matrix to vector + * + * Returns the matrix unrolled into one large vector, i.e. first column + * of the matrix will make first `rows` elements of resulting vector. + * Useful for performing vector operations with the matrix (e.g. + * summing the elements etc.). + * @see fromVector() + */ + inline Vector toVector() const { + return *reinterpret_cast*>(data()); } private: diff --git a/src/Math/Test/RectangularMatrixTest.cpp b/src/Math/Test/RectangularMatrixTest.cpp index 9ce624889..ab25a608c 100644 --- a/src/Math/Test/RectangularMatrixTest.cpp +++ b/src/Math/Test/RectangularMatrixTest.cpp @@ -54,12 +54,7 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester { void transposed(); void diagonal(); - void sum(); - void product(); - void min(); - void minAbs(); - void max(); - void maxAbs(); + void vector(); void debug(); void configuration(); @@ -95,12 +90,7 @@ RectangularMatrixTest::RectangularMatrixTest() { &RectangularMatrixTest::transposed, &RectangularMatrixTest::diagonal, - &RectangularMatrixTest::sum, - &RectangularMatrixTest::product, - &RectangularMatrixTest::min, - &RectangularMatrixTest::minAbs, - &RectangularMatrixTest::max, - &RectangularMatrixTest::maxAbs, + &RectangularMatrixTest::vector, &RectangularMatrixTest::debug, &RectangularMatrixTest::configuration}); @@ -338,50 +328,20 @@ void RectangularMatrixTest::diagonal() { CORRADE_COMPARE(b.diagonal(), diagonal); } -void RectangularMatrixTest::sum() { - Matrix2 matrix(Vector2(1.0f, 2.0f), - Vector2(3.0f, 4.0f)); - CORRADE_COMPARE(matrix.sum(), 10.0f); -} - -void RectangularMatrixTest::product() { - Matrix2 matrix(Vector2(1.0f, 2.0f), - Vector2(3.0f, 4.0f)); - CORRADE_COMPARE(matrix.product(), 24.0f); -} - -void RectangularMatrixTest::min() { - /* Check also that initial value isn't initialized to 0 */ - Matrix2 matrix(Vector2(-2.0f, 1.0f), - Vector2(3.0f, 4.0f)); - CORRADE_COMPARE(matrix.min(), -2.0f); -} +void RectangularMatrixTest::vector() { + typedef Vector<3, Int> Vector3i; + typedef RectangularMatrix<4, 3, Int> Matrix4x3i; + typedef Vector<12, Int> Vector12i; -void RectangularMatrixTest::minAbs() { - /* Check that initial value is absolute and also all others */ - Matrix2 a(Vector2(-2.0f, 1.0f), - Vector2(3.0f, 4.0f)); - Matrix2 b(Vector2(3.0f, 4.0f), - Vector2(-2.0f, 1.0f)); - CORRADE_COMPARE(a.minAbs(), 1.0f); - CORRADE_COMPARE(a.minAbs(), 1.0f); -} + Matrix4x3i a(Vector3i(0, 1, 2), + Vector3i(3, 4, 5), + Vector3i(6, 7, 8), + Vector3i(9, 10, 11)); -void RectangularMatrixTest::max() { - /* Check also that initial value isn't initialized to 0 */ - Matrix2 matrix(Vector2(-2.0f, -1.0f), - Vector2(-3.0f, -4.0f)); - CORRADE_COMPARE(matrix.max(), -1.0f); -} + Vector12i b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); -void RectangularMatrixTest::maxAbs() { - /* Check that initial value is absolute and also all others */ - Matrix2 a(Vector2(2.0f, 1.0f), - Vector2(3.0f, -4.0f)); - Matrix2 b(Vector2(3.0f, -4.0f), - Vector2(2.0f, 1.0f)); - CORRADE_COMPARE(a.maxAbs(), 4.0f); - CORRADE_COMPARE(b.maxAbs(), 4.0f); + CORRADE_COMPARE(a.toVector(), b); + CORRADE_COMPARE(Matrix4x3i::fromVector(b), a); } void RectangularMatrixTest::debug() { diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index 7c93976b6..583df6b19 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -83,9 +83,7 @@ class VectorTest: public Corrade::TestSuite::Tester { void sum(); void product(); void min(); - void minAbs(); void max(); - void maxAbs(); void projected(); void projectedOntoNormalized(); @@ -130,9 +128,7 @@ VectorTest::VectorTest() { &VectorTest::sum, &VectorTest::product, &VectorTest::min, - &VectorTest::minAbs, &VectorTest::max, - &VectorTest::maxAbs, &VectorTest::projected, &VectorTest::projectedOntoNormalized, @@ -331,23 +327,11 @@ void VectorTest::min() { CORRADE_COMPARE(Vector3(1.0f, -2.0f, 3.0f).min(), -2.0f); } -void VectorTest::minAbs() { - /* Check that initial value is absolute and also all others */ - CORRADE_COMPARE(Vector3(-2.0f, 1.0f, 3.0f).minAbs(), 1.0f); - CORRADE_COMPARE(Vector3(1.0f, -2.0f, 3.0f).minAbs(), 1.0f); -} - void VectorTest::max() { /* Check also that initial value isn't initialized to 0 */ CORRADE_COMPARE(Vector3(-1.0f, -2.0f, -3.0f).max(), -1.0f); } -void VectorTest::maxAbs() { - /* Check that initial value is absolute and also all others */ - CORRADE_COMPARE(Vector3(-5.0f, 1.0f, 3.0f).maxAbs(), 5.0f); - CORRADE_COMPARE(Vector3(1.0f, -5.0f, 3.0f).maxAbs(), 5.0f); -} - void VectorTest::projected() { Vector3 line(1.0f, -1.0f, 0.5f); Vector3 projected = Vector3(1.0f, 2.0f, 3.0f).projected(line); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index e49f1700b..ad4ea4314 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -300,7 +300,7 @@ template class Vector { /** * @brief Add vector * - * @see operator+=() + * @see operator+=(), sum() */ inline Vector operator+(const Vector& other) const { return Vector(*this) += other; @@ -408,7 +408,7 @@ template class Vector { /** * @brief Multiply vector component-wise * - * @see operator*=(const Vector&) + * @see operator*=(const Vector&), product() */ template inline Vector operator*(const Vector& other) const { return Vector(*this) *= other; @@ -499,7 +499,11 @@ template class Vector { return line*dot(*this, line); } - /** @brief Sum of values in the vector */ + /** + * @brief Sum of values in the vector + * + * @see operator+() + */ T sum() const { T out(_data[0]); @@ -509,7 +513,11 @@ template class Vector { return out; } - /** @brief Product of values in the vector */ + /** + * @brief Product of values in the vector + * + * @see operator*(const Vector&) + */ T product() const { T out(_data[0]); @@ -519,7 +527,11 @@ template class Vector { return out; } - /** @brief Minimal value in the vector */ + /** + * @brief Minimal value in the vector + * + * @see Math::min() + */ T min() const { T out(_data[0]); @@ -529,17 +541,11 @@ template class Vector { return out; } - /** @brief Minimal absolute value in the vector */ - T minAbs() const { - T out(std::abs(_data[0])); - - for(std::size_t i = 1; i != size; ++i) - out = std::min(out, std::abs(_data[i])); - - return out; - } - - /** @brief Maximal value in the vector */ + /** + * @brief Maximal value in the vector + * + * @see Math::max() + */ T max() const { T out(_data[0]); @@ -549,16 +555,6 @@ template class Vector { return out; } - /** @brief Maximal absolute value in the vector */ - T maxAbs() const { - T out(std::abs(_data[0])); - - for(std::size_t i = 1; i != size; ++i) - out = std::max(out, std::abs(_data[i])); - - return out; - } - private: /* Implementation for Vector::Vector(const Vector&) */ template inline constexpr explicit Vector(Implementation::Sequence, const Vector& vector): _data{T(vector._data[sequence])...} {}