Browse Source

Moved multiplication and division from Vector to RectangularMatrix.

vectorfields
Vladimír Vondruš 14 years ago
parent
commit
8911dbdffe
  1. 17
      src/Math/Matrix.h
  2. 110
      src/Math/RectangularMatrix.h
  3. 23
      src/Math/Test/RectangularMatrixTest.cpp
  4. 1
      src/Math/Test/RectangularMatrixTest.h
  5. 22
      src/Math/Test/VectorTest.cpp
  6. 1
      src/Math/Test/VectorTest.h
  7. 109
      src/Math/Vector.h

17
src/Math/Matrix.h

@ -145,6 +145,15 @@ template<size_t s, class T> class Matrix: public RectangularMatrix<s, s, T> {
MAGNUM_RECTANGULARMATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(size, size, Matrix<size, T>) MAGNUM_RECTANGULARMATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(size, size, Matrix<size, T>)
}; };
#ifndef DOXYGEN_GENERATING_OUTPUT
template<size_t size, class T, class U> inline Matrix<size, T> operator*(U number, const Matrix<size, T>& matrix) {
return number*RectangularMatrix<size, size, T>(matrix);
}
template<size_t size, class T, class U> inline Matrix<size, T> operator/(U number, const Matrix<size, T>& matrix) {
return number/RectangularMatrix<size, size, T>(matrix);
}
#endif
/** @debugoperator{Magnum::Math::Matrix} */ /** @debugoperator{Magnum::Math::Matrix} */
template<size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix<size, T>& value) { template<size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix<size, T>& value) {
return debug << static_cast<const Magnum::Math::RectangularMatrix<size, size, T>&>(value); return debug << static_cast<const Magnum::Math::RectangularMatrix<size, size, T>&>(value);
@ -191,6 +200,14 @@ template<size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utili
inline Type<T> transposed() const { return Matrix<size, T>::transposed(); } \ inline Type<T> transposed() const { return Matrix<size, T>::transposed(); } \
inline Type<T> inverted() const { return Matrix<size, T>::inverted(); } inline Type<T> inverted() const { return Matrix<size, T>::inverted(); }
#define MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Type, size) \
template<class T, class U> inline Type<T> operator*(U number, const Type<T>& matrix) { \
return number*Matrix<size, T>(matrix); \
} \
template<class T, class U> inline Type<T> operator/(U number, const Type<T>& matrix) { \
return number/Matrix<size, T>(matrix); \
}
namespace Implementation { namespace Implementation {
template<size_t size, class T> class MatrixDeterminant { template<size_t size, class T> class MatrixDeterminant {

110
src/Math/RectangularMatrix.h

@ -205,6 +205,66 @@ template<size_t c, size_t r, class T> class RectangularMatrix {
return *this; return *this;
} }
/**
* @brief Multiply matrix with number
*
* @see operator*=(U), operator*(U, const RectangularMatrix<cols, rows, T>&)
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator*(U number) const {
#else
template<class U> inline RectangularMatrix<cols, rows, T> operator*(U number) const {
#endif
return RectangularMatrix<cols, rows, T>(*this)*=number;
}
/**
* @brief Multiply matrix with number and assign
*
* More efficient than operator*(U), because it does the computation
* in-place.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>&>::type operator*=(U number) {
#else
template<class U> RectangularMatrix<cols, rows, T>& operator*=(U number) {
#endif
for(size_t i = 0; i != cols*rows; ++i)
_data[i] *= number;
return *this;
}
/**
* @brief Divide matrix with number
*
* @see operator/=(), operator/(U, const RectangularMatrix<cols, rows, T>&)
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator/(U number) const {
#else
template<class U> inline RectangularMatrix<cols, rows, T> operator/(U number) const {
#endif
return RectangularMatrix<cols, rows, T>(*this)/=number;
}
/**
* @brief Divide matrix with number and assign
*
* More efficient than operator/(), because it does the computation
* in-place.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>&>::type operator/=(U number) {
#else
template<class U> RectangularMatrix<cols, rows, T>& operator/=(U number) {
#endif
for(size_t i = 0; i != cols*rows; ++i)
_data[i] /= number;
return *this;
}
/** @brief Multiply matrix */ /** @brief Multiply matrix */
template<size_t size> RectangularMatrix<size, rows, T> operator*(const RectangularMatrix<size, cols, T>& other) const { template<size_t size> RectangularMatrix<size, rows, T> operator*(const RectangularMatrix<size, cols, T>& other) const {
RectangularMatrix<size, rows, T> out; RectangularMatrix<size, rows, T> out;
@ -249,6 +309,42 @@ template<size_t c, size_t r, class T> class RectangularMatrix {
T _data[rows*cols]; T _data[rows*cols];
}; };
/** @relates RectangularMatrix
@brief Multiply number with matrix
@see RectangularMatrix::operator*(U) const
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<size_t cols, size_t rows, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator*(U number, const RectangularMatrix<cols, rows, T>& matrix) {
#else
template<size_t cols, size_t rows, class T, class U> inline RectangularMatrix<cols, rows, T> operator*(U number, const RectangularMatrix<cols, rows, T>& matrix) {
#endif
return matrix*number;
}
/** @relates RectangularMatrix
@brief Divide matrix with number and invert
Example:
@code
RectangularMatrix<2, 3, float> mat(1.0f, 2.0f, -4.0f, 8.0f, -1.0f, 0.5f);
RectangularMatrix<2, 3, float> another = 1.0f/mat; // {1.0f, 0.5f, -0.25f, 0.128f, -1.0f, 2.0f}
@endcode
@see RectangularMatrix::operator/()
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<size_t cols, size_t rows, class T, class U> typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator/(U number, const RectangularMatrix<cols, rows, T>& matrix) {
#else
template<size_t cols, size_t rows, class T, class U> RectangularMatrix<cols, rows, T> operator/(U number, const RectangularMatrix<cols, rows, T>& matrix) {
#endif
RectangularMatrix<cols, rows, T> out;
for(size_t i = 0; i != cols*rows; ++i)
out.data()[i] = number/matrix.data()[i];
return out;
}
/** @debugoperator{Magnum::Math::RectangularMatrix} */ /** @debugoperator{Magnum::Math::RectangularMatrix} */
template<size_t cols, size_t rows, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::RectangularMatrix<cols, rows, T>& value) { template<size_t cols, size_t rows, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::RectangularMatrix<cols, rows, T>& value) {
debug << "Matrix("; debug << "Matrix(";
@ -296,6 +392,20 @@ template<size_t cols, size_t rows, class T> Corrade::Utility::Debug operator<<(C
inline __VA_ARGS__& operator-=(const RectangularMatrix<cols, rows, T>& other) { \ inline __VA_ARGS__& operator-=(const RectangularMatrix<cols, rows, T>& other) { \
RectangularMatrix<cols, rows, T>::operator-=(other); \ RectangularMatrix<cols, rows, T>::operator-=(other); \
return *this; \ return *this; \
} \
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__>::type operator*(U number) const { \
return RectangularMatrix<cols, rows, T>::operator*(number); \
} \
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__&>::type operator*=(U number) { \
RectangularMatrix<cols, rows, T>::operator*=(number); \
return *this; \
} \
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__>::type operator/(U number) const { \
return RectangularMatrix<cols, rows, T>::operator/(number); \
} \
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__&>::type operator/=(U number) { \
RectangularMatrix<cols, rows, T>::operator/=(number); \
return *this; \
} }
#endif #endif

23
src/Math/Test/RectangularMatrixTest.cpp

@ -28,6 +28,7 @@ namespace Magnum { namespace Math { namespace Test {
typedef RectangularMatrix<4, 3, float> Matrix4x3; typedef RectangularMatrix<4, 3, float> Matrix4x3;
typedef RectangularMatrix<3, 4, float> Matrix3x4; typedef RectangularMatrix<3, 4, float> Matrix3x4;
typedef RectangularMatrix<2, 2, float> Matrix2;
typedef Vector<4, float> Vector4; typedef Vector<4, float> Vector4;
RectangularMatrixTest::RectangularMatrixTest() { RectangularMatrixTest::RectangularMatrixTest() {
@ -37,6 +38,7 @@ RectangularMatrixTest::RectangularMatrixTest() {
&RectangularMatrixTest::data, &RectangularMatrixTest::data,
&RectangularMatrixTest::addSubtract, &RectangularMatrixTest::addSubtract,
&RectangularMatrixTest::multiplyDivide,
&RectangularMatrixTest::multiply, &RectangularMatrixTest::multiply,
&RectangularMatrixTest::transposed, &RectangularMatrixTest::transposed,
@ -127,6 +129,27 @@ void RectangularMatrixTest::addSubtract() {
CORRADE_COMPARE(e - b, a); CORRADE_COMPARE(e - b, a);
} }
void RectangularMatrixTest::multiplyDivide() {
Matrix2 vec(1.0f, 2.0f, 3.0f, 4.0f);
Matrix2 multiplied(-1.5f, -3.0f, -4.5f, -6.0f);
CORRADE_COMPARE(vec*-1.5f, multiplied);
CORRADE_COMPARE(-1.5f*vec, multiplied);
CORRADE_COMPARE(multiplied/-1.5f, vec);
Math::RectangularMatrix<1, 1, char> vecChar(32);
Math::RectangularMatrix<1, 1, char> multipliedChar(-48);
CORRADE_COMPARE(vecChar*-1.5f, multipliedChar);
CORRADE_COMPARE(multipliedChar/-1.5f, vecChar);
CORRADE_COMPARE(-1.5f*vecChar, multipliedChar);
/* Divide vector with number and inverse */
Matrix2 divisor(1.0f, 2.0f, -4.0f, 8.0f);
Matrix2 result(1.0f, 0.5f, -0.25f, 0.125f);
CORRADE_COMPARE(1.0f/divisor, result);
CORRADE_COMPARE(-1550.0f/multipliedChar, vecChar);
}
void RectangularMatrixTest::multiply() { void RectangularMatrixTest::multiply() {
RectangularMatrix<4, 6, int> left( RectangularMatrix<4, 6, int> left(
-5, 27, 10, 33, 0, -15, -5, 27, 10, 33, 0, -15,

1
src/Math/Test/RectangularMatrixTest.h

@ -29,6 +29,7 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester<RectangularMatrix
void data(); void data();
void addSubtract(); void addSubtract();
void multiplyDivide();
void multiply(); void multiply();
void transposed(); void transposed();

22
src/Math/Test/VectorTest.cpp

@ -35,7 +35,6 @@ VectorTest::VectorTest() {
addTests(&VectorTest::construct, addTests(&VectorTest::construct,
&VectorTest::constructFrom, &VectorTest::constructFrom,
&VectorTest::dot, &VectorTest::dot,
&VectorTest::multiplyDivide,
&VectorTest::multiplyDivideComponentWise, &VectorTest::multiplyDivideComponentWise,
&VectorTest::dotSelf, &VectorTest::dotSelf,
&VectorTest::length, &VectorTest::length,
@ -70,27 +69,6 @@ void VectorTest::dot() {
CORRADE_COMPARE(Vector4::dot({1.0f, 0.5f, 0.75f, 1.5f}, {2.0f, 4.0f, 1.0f, 7.0f}), 15.25f); CORRADE_COMPARE(Vector4::dot({1.0f, 0.5f, 0.75f, 1.5f}, {2.0f, 4.0f, 1.0f, 7.0f}), 15.25f);
} }
void VectorTest::multiplyDivide() {
Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f);
Vector4 multiplied(-1.5f, -3.0f, -4.5f, -6.0f);
CORRADE_COMPARE(vec*-1.5f, multiplied);
CORRADE_COMPARE(-1.5f*vec, multiplied);
CORRADE_COMPARE(multiplied/-1.5f, vec);
Math::Vector<1, char> vecChar(32);
Math::Vector<1, char> multipliedChar(-48);
CORRADE_COMPARE(vecChar*-1.5f, multipliedChar);
CORRADE_COMPARE(multipliedChar/-1.5f, vecChar);
CORRADE_COMPARE(-1.5f*vecChar, multipliedChar);
/* Divide vector with number and inverse */
Vector4 divisor(1.0f, 2.0f, -4.0f, 8.0f);
Vector4 result(1.0f, 0.5f, -0.25f, 0.125f);
CORRADE_COMPARE(1.0f/divisor, result);
CORRADE_COMPARE(-1550.0f/multipliedChar, vecChar);
}
void VectorTest::multiplyDivideComponentWise() { void VectorTest::multiplyDivideComponentWise() {
Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f); Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f);
Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f); Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f);

1
src/Math/Test/VectorTest.h

@ -26,7 +26,6 @@ class VectorTest: public Corrade::TestSuite::Tester<VectorTest> {
void construct(); void construct();
void constructFrom(); void constructFrom();
void dot(); void dot();
void multiplyDivide();
void multiplyDivideComponentWise(); void multiplyDivideComponentWise();
void dotSelf(); void dotSelf();
void length(); void length();

109
src/Math/Vector.h

@ -125,36 +125,6 @@ template<size_t s, class T> class Vector: public RectangularMatrix<1, s, T> {
inline T& operator[](size_t pos) { return RectangularMatrix<1, size, T>::_data[pos]; } inline T& operator[](size_t pos) { return RectangularMatrix<1, size, T>::_data[pos]; }
inline constexpr T operator[](size_t pos) const { return RectangularMatrix<1, size, T>::_data[pos]; } /**< @overload */ inline constexpr T operator[](size_t pos) const { return RectangularMatrix<1, size, T>::_data[pos]; } /**< @overload */
/**
* @brief Multiply vector
*
* @see operator*=(U), operator*(U, const Vector<size, T>&)
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>>::type operator*(U number) const {
#else
template<class U> inline Vector<size, T> operator*(U number) const {
#endif
return Vector<size, T>(*this)*=number;
}
/**
* @brief Multiply vector and assign
*
* More efficient than operator*(U) const, because it does the
* computation in-place.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>&>::type operator*=(U number) {
#else
template<class U> Vector<size, T>& operator*=(U number) {
#endif
for(size_t i = 0; i != size; ++i)
(*this)[i] *= number;
return *this;
}
/** /**
* @brief Multiply vector component-wise * @brief Multiply vector component-wise
* *
@ -177,36 +147,6 @@ template<size_t s, class T> class Vector: public RectangularMatrix<1, s, T> {
return *this; return *this;
} }
/**
* @brief Divide vector
*
* @see operator/=(U), operator/(U, const Vector<size, T>&)
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>>::type operator/(U number) const {
#else
template<class U> inline Vector<size, T> operator/(U number) const {
#endif
return Vector<size, T>(*this)/=number;
}
/**
* @brief Divide vector and assign
*
* More efficient than operator/(U) const, because it does the
* computation in-place.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>&>::type operator/=(U number) {
#else
template<class U> Vector<size, T>& operator/=(U number) {
#endif
for(size_t i = 0; i != size; ++i)
(*this)[i] /= number;
return *this;
}
/** /**
* @brief Divide vector component-wise * @brief Divide vector component-wise
* *
@ -318,41 +258,14 @@ template<size_t s, class T> class Vector: public RectangularMatrix<1, s, T> {
using RectangularMatrix<1, size, T>::operator(); using RectangularMatrix<1, size, T>::operator();
}; };
/** @relates Vector
@brief Multiply number with vector
@see Vector::operator*(U) const
*/
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
template<size_t size, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>>::type operator*(U number, const Vector<size, T>& vector) {
#else
template<size_t size, class T, class U> inline Vector<size, T> operator*(U number, const Vector<size, T>& vector) { template<size_t size, class T, class U> inline Vector<size, T> operator*(U number, const Vector<size, T>& vector) {
#endif return number*RectangularMatrix<1, size, T>(vector);
return vector*number;
} }
template<size_t size, class T, class U> inline Vector<size, T> operator/(U number, const Vector<size, T>& vector) {
/** @relates Vector return number/RectangularMatrix<1, size, T>(vector);
@brief Divide vector with number and invert
Example:
@code
Vector<4, float> vec(1.0f, 2.0f, -4.0f, 8.0f);
Vector<4, float> another = 1.0f/vec; // {1.0f, 0.5f, -0.25f, 0.128f}
@endcode
@see Vector::operator/(U) const
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<size_t size, class T, class U> typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>>::type operator/(U number, const Vector<size, T>& vector) {
#else
template<size_t size, class T, class U> Vector<size, T> operator/(U number, const Vector<size, T>& vector) {
#endif
Vector<size, T> out;
for(size_t i = 0; i != size; ++i)
out[i] = number/vector[i];
return out;
} }
#endif
/** @debugoperator{Magnum::Math::Vector} */ /** @debugoperator{Magnum::Math::Vector} */
template<size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector<size, T>& value) { template<size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector<size, T>& value) {
@ -384,13 +297,6 @@ template<size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utili
return *this; \ return *this; \
} \ } \
\ \
template<class U> inline Type<T> operator*(U number) const { \
return Vector<size, T>::operator*(number); \
} \
template<class U> inline Type<T>& operator*=(U number) { \
Vector<size, T>::operator*=(number); \
return *this; \
} \
inline Type<T> operator*(const Vector<size, T>& other) const { \ inline Type<T> operator*(const Vector<size, T>& other) const { \
return Vector<size, T>::operator*(other); \ return Vector<size, T>::operator*(other); \
} \ } \
@ -398,13 +304,6 @@ template<size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utili
Vector<size, T>::operator*=(other); \ Vector<size, T>::operator*=(other); \
return *this; \ return *this; \
} \ } \
template<class U> inline Type<T> operator/(U number) const { \
return Vector<size, T>::operator/(number); \
} \
template<class U> inline Type<T>& operator/=(U number) { \
Vector<size, T>::operator/=(number); \
return *this; \
} \
inline Type<T> operator/(const Vector<size, T>& other) const { \ inline Type<T> operator/(const Vector<size, T>& other) const { \
return Vector<size, T>::operator/(other); \ return Vector<size, T>::operator/(other); \
} \ } \

Loading…
Cancel
Save