Browse Source

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
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
bf58bb3cb1
  1. 4
      src/Math/Algorithms/Test/SvdTest.cpp
  2. 4
      src/Math/Functions.h
  3. 80
      src/Math/RectangularMatrix.h
  4. 66
      src/Math/Test/RectangularMatrixTest.cpp
  5. 16
      src/Math/Test/VectorTest.cpp
  6. 48
      src/Math/Vector.h

4
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);
}
}}}}

4
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<class T> inline T min(T a, T b);
@ -145,7 +145,7 @@ template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size
/**
@brief Maximum
@see max(), clamp()
@see max(), clamp(), Vector::max()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T max(const T& a, const T& b);

80
src/Math/RectangularMatrix.h

@ -96,6 +96,17 @@ template<std::size_t cols, std::size_t rows, class T> 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<cols, rows, T> fromVector(const Vector<cols*rows, T>& vector) {
return *reinterpret_cast<const RectangularMatrix<cols, rows, T>*>(vector.data());
}
/** @brief Construct zero-filled matrix */
inline constexpr /*implicit*/ RectangularMatrix() {}
@ -381,64 +392,17 @@ template<std::size_t cols, std::size_t rows, class T> 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<rows*cols, T> toVector() const {
return *reinterpret_cast<const Vector<rows*cols, T>*>(data());
}
private:

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

16
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);

48
src/Math/Vector.h

@ -300,7 +300,7 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Add vector
*
* @see operator+=()
* @see operator+=(), sum()
*/
inline Vector<size, T> operator+(const Vector<size, T>& other) const {
return Vector<size, T>(*this) += other;
@ -408,7 +408,7 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Multiply vector component-wise
*
* @see operator*=(const Vector<size, U>&)
* @see operator*=(const Vector<size, U>&), product()
*/
template<class U> inline Vector<size, T> operator*(const Vector<size, U>& other) const {
return Vector<size, T>(*this) *= other;
@ -499,7 +499,11 @@ template<std::size_t size, class T> 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<std::size_t size, class T> 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<std::size_t size, class T> 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<std::size_t size, class T> 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<std::size_t size, class T> 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<size, T>::Vector(const Vector<size, U>&) */
template<class U, std::size_t ...sequence> inline constexpr explicit Vector(Implementation::Sequence<sequence...>, const Vector<sizeof...(sequence), U>& vector): _data{T(vector._data[sequence])...} {}

Loading…
Cancel
Save