Browse Source

Math: removed integer/float RectangularMatrix multiplication and division.

We would need to duplicate all the functionality found in Vector, which
I don't think is needed at all. If anyone needs to do this, it is
possible to "linearize" the matrix into long vector and do the
operations on it.

Also updated subclass operator implementation, added tests for it, both
for proper returned value and proper result type.
pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
78417dfefa
  1. 25
      src/Math/Matrix.h
  2. 4
      src/Math/Matrix3.h
  3. 4
      src/Math/Matrix4.h
  4. 93
      src/Math/RectangularMatrix.h
  5. 117
      src/Math/Test/RectangularMatrixTest.cpp

25
src/Math/Matrix.h

@ -180,17 +180,7 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
#endif
};
#ifndef DOXYGEN_GENERATING_OUTPUT
template<std::size_t size, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Matrix<size, T>>::type operator*(U number, const Matrix<size, T>& matrix) {
return number*RectangularMatrix<size, size, T>(matrix);
}
template<std::size_t size, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Matrix<size, T>>::type operator/(U number, const Matrix<size, T>& matrix) {
return number/RectangularMatrix<size, size, T>(matrix);
}
template<std::size_t size, class T> inline Matrix<size, T> operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) {
return RectangularMatrix<1, size, T>(vector)*matrix;
}
#endif
MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(Matrix<size, T>)
/** @debugoperator{Magnum::Math::Matrix} */
template<std::size_t size, class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix<size, T>& value) {
@ -198,7 +188,7 @@ template<std::size_t size, class T> inline Corrade::Utility::Debug operator<<(Co
}
#ifndef DOXYGEN_GENERATING_OUTPUT
#define MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Type, VectorType, size) \
#define MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(size, Type, VectorType) \
VectorType<T>& operator[](std::size_t col) { \
return static_cast<VectorType<T>&>(Matrix<size, T>::operator[](col)); \
} \
@ -225,17 +215,6 @@ template<std::size_t size, class T> inline Corrade::Utility::Debug operator<<(Co
return Matrix<size, T>::invertedOrthogonal(); \
}
#define MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Type, size) \
template<class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Type<T>>::type operator*(U number, const Type<T>& matrix) { \
return number*Matrix<size, T>(matrix); \
} \
template<class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Type<T>>::type operator/(U number, const Type<T>& matrix) { \
return number/Matrix<size, T>(matrix); \
} \
template<class T> inline Type<T> operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) { \
return RectangularMatrix<1, size, T>(vector)*matrix; \
}
namespace Implementation {
template<std::size_t size, class T> class MatrixDeterminant {

4
src/Math/Matrix3.h

@ -299,10 +299,10 @@ template<class T> class Matrix3: public Matrix<3, T> {
}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(3, 3, Matrix3<T>)
MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix3, Vector3, 3)
MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(3, Matrix3, Vector3)
};
MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Matrix3, 3)
MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(3, Matrix3)
/** @debugoperator{Magnum::Math::Matrix3} */
template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix3<T>& value) {

4
src/Math/Matrix4.h

@ -367,10 +367,10 @@ template<class T> class Matrix4: public Matrix<4, T> {
}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(4, 4, Matrix4<T>)
MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix4, Vector4, 4)
MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(4, Matrix4, Vector4)
};
MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Matrix4, 4)
MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(4, Matrix4)
/** @debugoperator{Magnum::Math::Matrix4} */
template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix4<T>& value) {

93
src/Math/RectangularMatrix.h

@ -271,11 +271,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* \boldsymbol A_j = a \boldsymbol A_j
* @f]
*/
#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
RectangularMatrix<cols, rows, T>& operator*=(T number) {
for(std::size_t i = 0; i != cols; ++i)
_data[i] *= number;
@ -285,14 +281,10 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/**
* @brief Multiply matrix with number
*
* @see operator*=(U), operator*(U, const RectangularMatrix<cols, rows, T>&)
* @see operator*=(T), operator*(T, 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> RectangularMatrix<cols, rows, T> operator*(U number) const {
#endif
return RectangularMatrix<cols, rows, T>(*this)*=number;
RectangularMatrix<cols, rows, T> operator*(T number) const {
return RectangularMatrix<cols, rows, T>(*this) *= number;
}
/**
@ -302,11 +294,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* \boldsymbol A_j = \frac{\boldsymbol A_j} a
* @f]
*/
#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
RectangularMatrix<cols, rows, T>& operator/=(T number) {
for(std::size_t i = 0; i != cols; ++i)
_data[i] /= number;
@ -316,14 +304,11 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/**
* @brief Divide matrix with number
*
* @see operator/=(), operator/(U, const RectangularMatrix<cols, rows, T>&)
* @see operator/=(T),
* operator/(T, 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> RectangularMatrix<cols, rows, T> operator/(U number) const {
#endif
return RectangularMatrix<cols, rows, T>(*this)/=number;
RectangularMatrix<cols, rows, T> operator/(T number) const {
return RectangularMatrix<cols, rows, T>(*this) /= number;
}
/**
@ -385,13 +370,16 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** @relates RectangularMatrix
@brief Multiply number with matrix
Same as RectangularMatrix::operator*(U) const.
Same as RectangularMatrix::operator*(T) const.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<std::size_t cols, std::size_t rows, class T, class U> inline RectangularMatrix<cols, rows, T> operator*(U number, const RectangularMatrix<cols, rows, T>& matrix) {
#else
template<std::size_t cols, std::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) {
#endif
template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator*(
#ifdef DOXYGEN_GENERATING_OUTPUT
T
#else
typename std::common_type<T>::type
#endif
number, const RectangularMatrix<cols, rows, T>& matrix)
{
return matrix*number;
}
@ -401,13 +389,16 @@ template<std::size_t cols, std::size_t rows, class T, class U> inline typename s
The computation is done column-wise. @f[
\boldsymbol B_j = \frac a {\boldsymbol A_j}
@f]
@see RectangularMatrix::operator/(U) const
@see RectangularMatrix::operator/(T) const
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<std::size_t cols, std::size_t rows, class T, class U> inline RectangularMatrix<cols, rows, T> operator/(U number, const RectangularMatrix<cols, rows, T>& matrix) {
#else
template<std::size_t cols, std::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) {
#endif
template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator/(
#ifdef DOXYGEN_GENERATING_OUTPUT
T
#else
typename std::common_type<T>::type
#endif
number, const RectangularMatrix<cols, rows, T>& matrix)
{
RectangularMatrix<cols, rows, T> out;
for(std::size_t i = 0; i != cols; ++i)
@ -502,20 +493,42 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
__VA_ARGS__ operator-(const Math::RectangularMatrix<cols, rows, T>& other) const { \
return Math::RectangularMatrix<cols, rows, T>::operator-(other); \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__&>::type operator*=(U number) { \
__VA_ARGS__& operator*=(T number) { \
Math::RectangularMatrix<cols, rows, T>::operator*=(number); \
return *this; \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__>::type operator*(U number) const { \
__VA_ARGS__ operator*(T number) const { \
return Math::RectangularMatrix<cols, rows, T>::operator*(number); \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__&>::type operator/=(U number) { \
__VA_ARGS__& operator/=(T number) { \
Math::RectangularMatrix<cols, rows, T>::operator/=(number); \
return *this; \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__>::type operator/(U number) const { \
__VA_ARGS__ operator/(T number) const { \
return Math::RectangularMatrix<cols, rows, T>::operator/(number); \
}
#define MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(...) \
template<std::size_t size, class T> inline __VA_ARGS__ operator*(typename std::common_type<T>::type number, const __VA_ARGS__& matrix) { \
return number*static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<std::size_t size, class T> inline __VA_ARGS__ operator/(typename std::common_type<T>::type number, const __VA_ARGS__& matrix) { \
return number/static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<std::size_t size, class T> inline __VA_ARGS__ operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) { \
return Math::RectangularMatrix<1, size, T>(vector)*matrix; \
}
#define MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(size, Type) \
template<class T> inline Type<T> operator*(typename std::common_type<T>::type number, const Type<T>& matrix) { \
return number*static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<class T> inline Type<T> operator/(typename std::common_type<T>::type number, const Type<T>& matrix) { \
return number/static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<class T> inline Type<T> operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) { \
return Math::RectangularMatrix<1, size, T>(vector)*matrix; \
}
#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) {

117
src/Math/Test/RectangularMatrixTest.cpp

@ -80,6 +80,9 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester {
void vector();
void subclassTypes();
void subclass();
void debug();
void configuration();
};
@ -117,6 +120,9 @@ RectangularMatrixTest::RectangularMatrixTest() {
&RectangularMatrixTest::vector,
&RectangularMatrixTest::subclassTypes,
&RectangularMatrixTest::subclass,
&RectangularMatrixTest::debug,
&RectangularMatrixTest::configuration});
}
@ -308,19 +314,12 @@ void RectangularMatrixTest::multiplyDivide() {
CORRADE_COMPARE(-1.5f*matrix, multiplied);
CORRADE_COMPARE(multiplied/-1.5f, matrix);
Math::RectangularMatrix<1, 1, Byte> matrixChar(32);
Math::RectangularMatrix<1, 1, Byte> multipliedChar(-48);
CORRADE_COMPARE(matrixChar*-1.5f, multipliedChar);
CORRADE_COMPARE(multipliedChar/-1.5f, matrixChar);
CORRADE_COMPARE(-1.5f*matrixChar, multipliedChar);
/* Divide vector with number and inverse */
Matrix2 divisor(Vector2( 1.0f, 2.0f),
Vector2(-4.0f, 8.0f));
Matrix2 result(Vector2( 1.0f, 0.5f),
Vector2(-0.25f, 0.125f));
CORRADE_COMPARE(1.0f/divisor, result);
CORRADE_COMPARE(-1550.0f/multipliedChar, matrixChar);
}
void RectangularMatrixTest::multiply() {
@ -394,6 +393,110 @@ void RectangularMatrixTest::vector() {
CORRADE_COMPARE(Matrix4x3i::fromVector(b), a);
}
template<std::size_t size, class T> class BasicMat: public Math::RectangularMatrix<size, size, T> {
public:
template<class ...U> BasicMat(U&&... args): Math::RectangularMatrix<size, size, T>{std::forward<U>(args)...} {}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(size, size, BasicMat<size, T>)
};
MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(BasicMat<size, T>)
template<class T> class BasicMat2x2: public BasicMat<2, T> {
public:
template<class ...U> BasicMat2x2(U&&... args): BasicMat<2, T>{std::forward<U>(args)...} {}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(2, 2, BasicMat2x2<T>)
};
MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(2, BasicMat2x2)
typedef BasicMat2x2<Float> Mat2x2;
void RectangularMatrixTest::subclassTypes() {
Float* const data = nullptr;
const Float* const cdata = nullptr;
CORRADE_VERIFY((std::is_same<decltype(Mat2x2::from(data)), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(Mat2x2::from(cdata)), const Mat2x2&>::value));
/* Const operators */
const Mat2x2 c;
CORRADE_VERIFY((std::is_same<decltype(-c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(c + c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(c*1.0f), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f*c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(c/1.0f), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f/c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(Vector2()*Math::RectangularMatrix<2, 1, Float>()), Mat2x2>::value));
/* Assignment operators */
Mat2x2 a;
CORRADE_VERIFY((std::is_same<decltype(a = c), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a += c), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a -= c), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a *= 1.0f), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a /= 1.0f), Mat2x2&>::value));
/* Operators on variable-sized matrix */
const BasicMat<3, Float> c2;
CORRADE_VERIFY((std::is_same<decltype(1.0f*c2), BasicMat<3, Float>>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f/c2), BasicMat<3, Float>>::value));
CORRADE_VERIFY((std::is_same<decltype(Vector3()*Math::RectangularMatrix<3, 1, Float>()), BasicMat<3, Float>>::value));
}
void RectangularMatrixTest::subclass() {
Float data[] = {1.0f, -2.0f, 3.0f, -4.5f};
CORRADE_COMPARE(Mat2x2::from(data), Mat2x2(Vector2(1.0f, -2.0f),
Vector2(3.0f, -4.5f)));
const Float cdata[] = {1.0f, -2.0f, 3.0f, -4.5f};
CORRADE_COMPARE(Mat2x2::from(cdata), Mat2x2(Vector2(1.0f, -2.0f),
Vector2(3.0f, -4.5f)));
const Mat2x2 a(Vector2(1.0f, -3.0f),
Vector2(-3.0f, 1.0f));
CORRADE_COMPARE(-a, Mat2x2(Vector2(-1.0f, 3.0f),
Vector2(3.0f, -1.0f)));
Mat2x2 b(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
const Mat2x2 bExpected(Vector2(-1.0f, 2.0f),
Vector2(2.0f, -1.0f));
CORRADE_COMPARE(b + a, bExpected);
Mat2x2 c(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
const Mat2x2 cExpected(Vector2(-3.0f, 8.0f),
Vector2(8.0f, -3.0f));
CORRADE_COMPARE(c - a, cExpected);
Mat2x2 d(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
const Mat2x2 dExpected(Vector2(-4.0f, 10.0f),
Vector2(10.0f, -4.0f));
CORRADE_COMPARE(d*2.0f, dExpected);
CORRADE_COMPARE(2.0f*d, dExpected);
Mat2x2 e(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
CORRADE_COMPARE(e/0.5f, dExpected);
CORRADE_COMPARE(2.0f/e, Mat2x2(Vector2(-1.0f, 0.4f),
Vector2(0.4f, -1.0f)));
const Vector2 f(2.0f, 5.0f);
const Math::RectangularMatrix<2, 1, Float> g(3.0f, -1.0f);
CORRADE_COMPARE(f*g, Mat2x2(Vector2(6.0f, 15.0f),
Vector2(-2.0f, -5.0f)));
/* Operators on variable-sized matrix */
const BasicMat<1, Float> h(-2.0f);
CORRADE_COMPARE(2.0f*h, (BasicMat<1, Float>(-4.0f)));
CORRADE_COMPARE(2.0f/h, (BasicMat<1, Float>(-1.0f)));
const Math::Vector<1, Float> i(2.0f);
const Math::RectangularMatrix<1, 1, Float> j(3.0f);
CORRADE_COMPARE(i*j, (BasicMat<1, Float>(6.0f)));
}
void RectangularMatrixTest::debug() {
Matrix3x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),

Loading…
Cancel
Save