diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index e551f868c..16beaf05c 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -145,6 +145,15 @@ template class Matrix: public RectangularMatrix { MAGNUM_RECTANGULARMATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(size, size, Matrix) }; +#ifndef DOXYGEN_GENERATING_OUTPUT +template inline Matrix operator*(U number, const Matrix& matrix) { + return number*RectangularMatrix(matrix); +} +template inline Matrix operator/(U number, const Matrix& matrix) { + return number/RectangularMatrix(matrix); +} +#endif + /** @debugoperator{Magnum::Math::Matrix} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix& value) { return debug << static_cast&>(value); @@ -191,6 +200,14 @@ template Corrade::Utility::Debug operator<<(Corrade::Utili inline Type transposed() const { return Matrix::transposed(); } \ inline Type inverted() const { return Matrix::inverted(); } +#define MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Type, size) \ + template inline Type operator*(U number, const Type& matrix) { \ + return number*Matrix(matrix); \ + } \ + template inline Type operator/(U number, const Type& matrix) { \ + return number/Matrix(matrix); \ + } + namespace Implementation { template class MatrixDeterminant { diff --git a/src/Math/RectangularMatrix.h b/src/Math/RectangularMatrix.h index 2ae79fea2..7d4d2c508 100644 --- a/src/Math/RectangularMatrix.h +++ b/src/Math/RectangularMatrix.h @@ -205,6 +205,66 @@ template class RectangularMatrix { return *this; } + /** + * @brief Multiply matrix with number + * + * @see operator*=(U), operator*(U, const RectangularMatrix&) + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template inline typename std::enable_if::value, RectangularMatrix>::type operator*(U number) const { + #else + template inline RectangularMatrix operator*(U number) const { + #endif + return RectangularMatrix(*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 inline typename std::enable_if::value, RectangularMatrix&>::type operator*=(U number) { + #else + template RectangularMatrix& 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&) + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template inline typename std::enable_if::value, RectangularMatrix>::type operator/(U number) const { + #else + template inline RectangularMatrix operator/(U number) const { + #endif + return RectangularMatrix(*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 inline typename std::enable_if::value, RectangularMatrix&>::type operator/=(U number) { + #else + template RectangularMatrix& operator/=(U number) { + #endif + for(size_t i = 0; i != cols*rows; ++i) + _data[i] /= number; + + return *this; + } + /** @brief Multiply matrix */ template RectangularMatrix operator*(const RectangularMatrix& other) const { RectangularMatrix out; @@ -249,6 +309,42 @@ template class RectangularMatrix { T _data[rows*cols]; }; +/** @relates RectangularMatrix +@brief Multiply number with matrix + +@see RectangularMatrix::operator*(U) const +*/ +#ifndef DOXYGEN_GENERATING_OUTPUT +template inline typename std::enable_if::value, RectangularMatrix>::type operator*(U number, const RectangularMatrix& matrix) { +#else +template inline RectangularMatrix operator*(U number, const RectangularMatrix& 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 typename std::enable_if::value, RectangularMatrix>::type operator/(U number, const RectangularMatrix& matrix) { +#else +template RectangularMatrix operator/(U number, const RectangularMatrix& matrix) { +#endif + RectangularMatrix out; + + for(size_t i = 0; i != cols*rows; ++i) + out.data()[i] = number/matrix.data()[i]; + + return out; +} + /** @debugoperator{Magnum::Math::RectangularMatrix} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::RectangularMatrix& value) { debug << "Matrix("; @@ -296,6 +392,20 @@ template Corrade::Utility::Debug operator<<(C inline __VA_ARGS__& operator-=(const RectangularMatrix& other) { \ RectangularMatrix::operator-=(other); \ return *this; \ + } \ + template inline typename std::enable_if::value, __VA_ARGS__>::type operator*(U number) const { \ + return RectangularMatrix::operator*(number); \ + } \ + template inline typename std::enable_if::value, __VA_ARGS__&>::type operator*=(U number) { \ + RectangularMatrix::operator*=(number); \ + return *this; \ + } \ + template inline typename std::enable_if::value, __VA_ARGS__>::type operator/(U number) const { \ + return RectangularMatrix::operator/(number); \ + } \ + template inline typename std::enable_if::value, __VA_ARGS__&>::type operator/=(U number) { \ + RectangularMatrix::operator/=(number); \ + return *this; \ } #endif diff --git a/src/Math/Test/RectangularMatrixTest.cpp b/src/Math/Test/RectangularMatrixTest.cpp index 925ed8bd2..51cfed605 100644 --- a/src/Math/Test/RectangularMatrixTest.cpp +++ b/src/Math/Test/RectangularMatrixTest.cpp @@ -28,6 +28,7 @@ namespace Magnum { namespace Math { namespace Test { typedef RectangularMatrix<4, 3, float> Matrix4x3; typedef RectangularMatrix<3, 4, float> Matrix3x4; +typedef RectangularMatrix<2, 2, float> Matrix2; typedef Vector<4, float> Vector4; RectangularMatrixTest::RectangularMatrixTest() { @@ -37,6 +38,7 @@ RectangularMatrixTest::RectangularMatrixTest() { &RectangularMatrixTest::data, &RectangularMatrixTest::addSubtract, + &RectangularMatrixTest::multiplyDivide, &RectangularMatrixTest::multiply, &RectangularMatrixTest::transposed, @@ -127,6 +129,27 @@ void RectangularMatrixTest::addSubtract() { 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() { RectangularMatrix<4, 6, int> left( -5, 27, 10, 33, 0, -15, diff --git a/src/Math/Test/RectangularMatrixTest.h b/src/Math/Test/RectangularMatrixTest.h index f2fcfed0f..211d767bd 100644 --- a/src/Math/Test/RectangularMatrixTest.h +++ b/src/Math/Test/RectangularMatrixTest.h @@ -29,6 +29,7 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester 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() { Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f); Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f); diff --git a/src/Math/Test/VectorTest.h b/src/Math/Test/VectorTest.h index 4504db2da..70fe2f878 100644 --- a/src/Math/Test/VectorTest.h +++ b/src/Math/Test/VectorTest.h @@ -26,7 +26,6 @@ class VectorTest: public Corrade::TestSuite::Tester { void construct(); void constructFrom(); void dot(); - void multiplyDivide(); void multiplyDivideComponentWise(); void dotSelf(); void length(); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 4b4bbfd2a..8ed2949c1 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -125,36 +125,6 @@ template class Vector: public RectangularMatrix<1, s, T> { 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 */ - /** - * @brief Multiply vector - * - * @see operator*=(U), operator*(U, const Vector&) - */ - #ifndef DOXYGEN_GENERATING_OUTPUT - template inline typename std::enable_if::value, Vector>::type operator*(U number) const { - #else - template inline Vector operator*(U number) const { - #endif - return Vector(*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 typename std::enable_if::value, Vector&>::type operator*=(U number) { - #else - template Vector& operator*=(U number) { - #endif - for(size_t i = 0; i != size; ++i) - (*this)[i] *= number; - - return *this; - } - /** * @brief Multiply vector component-wise * @@ -177,36 +147,6 @@ template class Vector: public RectangularMatrix<1, s, T> { return *this; } - /** - * @brief Divide vector - * - * @see operator/=(U), operator/(U, const Vector&) - */ - #ifndef DOXYGEN_GENERATING_OUTPUT - template inline typename std::enable_if::value, Vector>::type operator/(U number) const { - #else - template inline Vector operator/(U number) const { - #endif - return Vector(*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 typename std::enable_if::value, Vector&>::type operator/=(U number) { - #else - template Vector& operator/=(U number) { - #endif - for(size_t i = 0; i != size; ++i) - (*this)[i] /= number; - - return *this; - } - /** * @brief Divide vector component-wise * @@ -318,41 +258,14 @@ template class Vector: public RectangularMatrix<1, s, T> { using RectangularMatrix<1, size, T>::operator(); }; -/** @relates Vector -@brief Multiply number with vector - -@see Vector::operator*(U) const -*/ #ifndef DOXYGEN_GENERATING_OUTPUT -template inline typename std::enable_if::value, Vector>::type operator*(U number, const Vector& vector) { -#else template inline Vector operator*(U number, const Vector& vector) { -#endif - return vector*number; + return number*RectangularMatrix<1, size, T>(vector); } - -/** @relates 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 typename std::enable_if::value, Vector>::type operator/(U number, const Vector& vector) { -#else -template Vector operator/(U number, const Vector& vector) { -#endif - Vector out; - - for(size_t i = 0; i != size; ++i) - out[i] = number/vector[i]; - - return out; +template inline Vector operator/(U number, const Vector& vector) { + return number/RectangularMatrix<1, size, T>(vector); } +#endif /** @debugoperator{Magnum::Math::Vector} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector& value) { @@ -384,13 +297,6 @@ template Corrade::Utility::Debug operator<<(Corrade::Utili return *this; \ } \ \ - template inline Type operator*(U number) const { \ - return Vector::operator*(number); \ - } \ - template inline Type& operator*=(U number) { \ - Vector::operator*=(number); \ - return *this; \ - } \ inline Type operator*(const Vector& other) const { \ return Vector::operator*(other); \ } \ @@ -398,13 +304,6 @@ template Corrade::Utility::Debug operator<<(Corrade::Utili Vector::operator*=(other); \ return *this; \ } \ - template inline Type operator/(U number) const { \ - return Vector::operator/(number); \ - } \ - template inline Type& operator/=(U number) { \ - Vector::operator/=(number); \ - return *this; \ - } \ inline Type operator/(const Vector& other) const { \ return Vector::operator/(other); \ } \