From b4a33d15c3b17034a6111c3794a43594d8091638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 2 Sep 2013 17:09:29 +0200 Subject: [PATCH] Math: improve integer/float Vector multiplication and division. Operators that are part of Vector are operating only with the same type as Vector itself, operators for multiplying/dividing integral vectors with floating-point numbers and vectors are now out-of-class and enabled only for integer vectors. It allows better control (e.g. multiplying integer and floating-point vector will _always_ result in floating-point one). Thoroughly tested integer/FP operations and also reworked and tested operator and funciton reimplementations in subclasses, both for value correctness and result type correctness. --- src/Color.h | 8 +- src/Math/Test/VectorTest.cpp | 134 ++++++++++- src/Math/Vector.h | 333 ++++++++++++++++++++++----- src/Math/Vector2.h | 4 +- src/Math/Vector3.h | 4 +- src/Math/Vector4.h | 4 +- src/Text/DistanceFieldGlyphCache.cpp | 2 +- src/TextureTools/DistanceField.cpp | 4 +- 8 files changed, 416 insertions(+), 77 deletions(-) diff --git a/src/Color.h b/src/Color.h index 410990944..a204e058d 100644 --- a/src/Color.h +++ b/src/Color.h @@ -254,13 +254,13 @@ template class BasicColor3: public Math::Vector3 { return Implementation::value(*this); } - MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(BasicColor3, 3) + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(3, BasicColor3) }; /** @brief Three-component (RGB) float color */ typedef BasicColor3 Color3; -MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(BasicColor3, 3) +MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(3, BasicColor3) /** @brief Four-component (RGBA) color @@ -374,13 +374,13 @@ class BasicColor4: public Math::Vector4 { return Implementation::value(rgb()); } - MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(BasicColor4, 4) + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(4, BasicColor4) }; /** @brief Four-component (RGBA) float color */ typedef BasicColor4 Color4; -MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(BasicColor4, 4) +MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, BasicColor4) /** @debugoperator{Magnum::BasicColor3} */ template inline Debug operator<<(Debug debug, const BasicColor3& value) { diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index c6aa1474c..b6484e5e6 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -71,7 +71,9 @@ class VectorTest: public Corrade::TestSuite::Tester { void negative(); void addSubtract(); void multiplyDivide(); + void multiplyDivideIntegral(); void multiplyDivideComponentWise(); + void multiplyDivideComponentWiseIntegral(); void compare(); void compareComponentWise(); @@ -92,6 +94,9 @@ class VectorTest: public Corrade::TestSuite::Tester { void projectedOntoNormalized(); void angle(); + void subclassTypes(); + void subclass(); + void debug(); void configuration(); }; @@ -119,7 +124,9 @@ VectorTest::VectorTest() { &VectorTest::negative, &VectorTest::addSubtract, &VectorTest::multiplyDivide, + &VectorTest::multiplyDivideIntegral, &VectorTest::multiplyDivideComponentWise, + &VectorTest::multiplyDivideComponentWiseIntegral, &VectorTest::compare, &VectorTest::compareComponentWise, @@ -140,6 +147,9 @@ VectorTest::VectorTest() { &VectorTest::projectedOntoNormalized, &VectorTest::angle, + &VectorTest::subclassTypes, + &VectorTest::subclass, + &VectorTest::debug, &VectorTest::configuration}); } @@ -287,17 +297,21 @@ void VectorTest::multiplyDivide() { CORRADE_COMPARE(-1.5f*vector, multiplied); CORRADE_COMPARE(multiplied/-1.5f, vector); - Math::Vector<1, Byte> vectorChar(32); - Math::Vector<1, Byte> multipliedChar(-48); - CORRADE_COMPARE(vectorChar*-1.5f, multipliedChar); - CORRADE_COMPARE(multipliedChar/-1.5f, vectorChar); - CORRADE_COMPARE(-1.5f*vectorChar, multipliedChar); - - /* Divide vector with number and inverse */ + /* Divide vector with number and invert */ 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, vectorChar); +} + +void VectorTest::multiplyDivideIntegral() { + Vector4i vector(32, 10, -6, 2); + Vector4i multiplied(-48, -15, 9, -3); + + CORRADE_COMPARE(vector*-1.5f, multiplied); + CORRADE_COMPARE(-1.5f*vector, multiplied); + + CORRADE_COMPARE(multiplied/-1.5f, vector); + /* Using integer vector as divisor is not supported */ } void VectorTest::multiplyDivideComponentWise() { @@ -309,6 +323,18 @@ void VectorTest::multiplyDivideComponentWise() { CORRADE_COMPARE(multiplied/multiplier, vec); } +void VectorTest::multiplyDivideComponentWiseIntegral() { + Vector4i vec(7, 2, -16, -1); + Vector4 multiplier(2.0f, -1.5f, 0.5f, 10.0f); + Vector4i multiplied(14, -3, -8, -10); + + CORRADE_COMPARE(vec*multiplier, multiplied); + CORRADE_COMPARE(multiplier*vec, multiplied); + + CORRADE_COMPARE(multiplied/multiplier, vec); + /* Using integer vector as divisor is not supported */ +} + 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); } @@ -396,6 +422,98 @@ void VectorTest::angle() { Rad(1.162514f)); } +template class BasicVec2: public Math::Vector<2, T> { + public: + template BasicVec2(U&&... args): Math::Vector<2, T>{std::forward(args)...} {} + + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, BasicVec2) +}; + +MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(2, BasicVec2) + +typedef BasicVec2 Vec2; +typedef BasicVec2 Vec2i; + +void VectorTest::subclassTypes() { + Float* const data = nullptr; + const Float* const cdata = nullptr; + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + + /* Const operators */ + const Vec2 c; + const Vec2 c2; + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + + /* Assignment operators */ + Vec2 a; + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + + /* Integer multiplication/division */ + const Vec2i ci; + Vec2i i; + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + + /* Functions */ + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); +} + +void VectorTest::subclass() { + Float data[] = {1.0f, -2.0f}; + CORRADE_COMPARE(Vec2::from(data), Vec2(1.0f, -2.0f)); + + const Float cdata[] = {1.0f, -2.0f}; + CORRADE_COMPARE(Vec2::from(cdata), Vec2(1.0f, -2.0f)); + + CORRADE_COMPARE(Vec2(-2.0f, 5.0f) + Vec2(1.0f, -3.0f), Vec2(-1.0f, 2.0f)); + CORRADE_COMPARE(Vec2(-2.0f, 5.0f) - Vec2(1.0f, -3.0f), Vec2(-3.0f, 8.0f)); + + CORRADE_COMPARE(Vec2(-2.0f, 5.0f)*2.0f, Vec2(-4.0f, 10.0f)); + CORRADE_COMPARE(2.0f*Vec2(-2.0f, 5.0f), Vec2(-4.0f, 10.0f)); + CORRADE_COMPARE(Vec2(-2.0f, 5.0f)/0.5f, Vec2(-4.0f, 10.0f)); + CORRADE_COMPARE(2.0f/Vec2(-2.0f, 5.0f), Vec2(-1.0f, 0.4f)); + + CORRADE_COMPARE(Vec2(-2.0f, 5.0f)*Vec2(1.5f, -2.0f), Vec2(-3.0f, -10.0f)); + CORRADE_COMPARE(Vec2(-2.0f, 5.0f)/Vec2(2.0f/3.0f, -0.5f), Vec2(-3.0f, -10.0f)); + + /* Integral multiplication/division */ + CORRADE_COMPARE(Vec2i(2, 4)*1.5f, Vec2i(3, 6)); + CORRADE_COMPARE(1.5f*Vec2i(2, 4), Vec2i(3, 6)); + CORRADE_COMPARE(Vec2i(2, 4)/(2.0f/3.0f), Vec2i(3, 6)); + + CORRADE_COMPARE(Vec2i(2, 4)*Vec2(-1.5f, 0.5f), Vec2i(-3, 2)); + CORRADE_COMPARE(Vec2(-1.5f, 0.5f)*Vec2i(2, 4), Vec2i(-3, 2)); + CORRADE_COMPARE(Vec2i(2, 4)/Vec2(-2.0f/3.0f, 2.0f), Vec2i(-3, 2)); + + /* Functions */ + CORRADE_COMPARE(Vec2(3.0f, 0.0f).normalized(), Vec2(1.0f, 0.0f)); + CORRADE_COMPARE(Vec2(3.0f, 0.0f).resized(6.0f), Vec2(6.0f, 0.0f)); + CORRADE_COMPARE(Vec2(1.0f, 1.0f).projected({0.0f, 2.0f}), Vec2(0.0f, 1.0f)); + CORRADE_COMPARE(Vec2(1.0f, 1.0f).projectedOntoNormalized({0.0f, 1.0f}), Vec2(0.0f, 1.0f)); +} + void VectorTest::debug() { std::ostringstream o; Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index b90923b92..28dc4daf8 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -306,12 +306,10 @@ template class Vector { * The computation is done in-place. @f[ * \boldsymbol a_i = b \boldsymbol a_i * @f] + * @see operator*=(const Vector&), + * operator*=(Vector&, FloatingPoint) */ - #ifdef DOXYGEN_GENERATING_OUTPUT - template Vector& operator*=(U number) { - #else - template typename std::enable_if::value, Vector&>::type operator*=(U number) { - #endif + Vector& operator*=(T number) { for(std::size_t i = 0; i != size; ++i) _data[i] *= number; @@ -321,13 +319,11 @@ template class Vector { /** * @brief Multiply vector with number * - * @see operator*=(U), operator*(U, const Vector&) + * @see operator*(const Vector&) const, + * operator*=(T), operator*(T, const Vector&), + * operator*(const Vector&, FloatingPoint) */ - #ifdef DOXYGEN_GENERATING_OUTPUT - template Vector operator*(U number) const { - #else - template typename std::enable_if::value, Vector>::type operator*(U number) const { - #endif + Vector operator*(T number) const { return Vector(*this) *= number; } @@ -337,12 +333,10 @@ template class Vector { * The computation is done in-place. @f[ * \boldsymbol a_i = \frac{\boldsymbol a_i} b * @f] + * @see operator/=(const Vector&), + * operator/=(Vector&, FloatingPoint) */ - #ifdef DOXYGEN_GENERATING_OUTPUT - template Vector& operator/=(U number) { - #else - template typename std::enable_if::value, Vector&>::type operator/=(U number) { - #endif + Vector& operator/=(T number) { for(std::size_t i = 0; i != size; ++i) _data[i] /= number; @@ -352,13 +346,11 @@ template class Vector { /** * @brief Divide vector with number * - * @see operator/=(), operator/(U, const Vector&) + * @see operator/(const Vector&) const, + * operator/=(T), operator/(T, const Vector&), + * operator/(const Vector&, FloatingPoint) */ - #ifdef DOXYGEN_GENERATING_OUTPUT - template Vector operator/(U number) const { - #else - template typename std::enable_if::value, Vector>::type operator/(U number) const { - #endif + Vector operator/(T number) const { return Vector(*this) /= number; } @@ -368,8 +360,10 @@ template class Vector { * The computation is done in-place. @f[ * \boldsymbol a_i = \boldsymbol a_i \boldsymbol b_i * @f] + * @see operator*=(T), + * operator*=(Vector&, const Vector&) */ - template Vector& operator*=(const Vector& other) { + Vector& operator*=(const Vector& other) { for(std::size_t i = 0; i != size; ++i) _data[i] *= other._data[i]; @@ -379,9 +373,10 @@ template class Vector { /** * @brief Multiply vector component-wise * - * @see operator*=(const Vector&), product() + * @see operator*(T) const, operator*=(const Vector&), + * operator*(const Vector&, const Vector&) */ - template Vector operator*(const Vector& other) const { + Vector operator*(const Vector& other) const { return Vector(*this) *= other; } @@ -391,8 +386,10 @@ template class Vector { * The computation is done in-place. @f[ * \boldsymbol a_i = \frac{\boldsymbol a_i}{\boldsymbol b_i} * @f] + * @see operator/=(T), + * operator/=(Vector&, const Vector&) */ - template Vector& operator/=(const Vector& other) { + Vector& operator/=(const Vector& other) { for(std::size_t i = 0; i != size; ++i) _data[i] /= other._data[i]; @@ -402,9 +399,10 @@ template class Vector { /** * @brief Divide vector component-wise * - * @see operator/=(const Vector&) + * @see operator/(T) const, operator/=(const Vector&), + * operator/(const Vector&, const Vector&) */ - template Vector operator/(const Vector& other) const { + Vector operator/(const Vector& other) const { return Vector(*this) /= other; } @@ -415,7 +413,7 @@ template class Vector { * other values, because it doesn't compute the square root. @f[ * \boldsymbol a \cdot \boldsymbol a = \sum_{i=0}^{n-1} \boldsymbol a_i^2 * @f] - * @see dot(const Vector&, const Vector&), isNormalized() + * @see dot(const Vector&, const Vector&), isNormalized() */ T dot() const { return dot(*this, *this); } @@ -497,7 +495,7 @@ template class Vector { /** * @brief Product of values in the vector * - * @see operator*(const Vector&) + * @see operator*(const Vector&) const */ T product() const; @@ -528,13 +526,16 @@ template class Vector { /** @relates Vector @brief Multiply number with vector -Same as Vector::operator*(U) const. +Same as Vector::operator*(T) const. */ -#ifdef DOXYGEN_GENERATING_OUTPUT -template inline Vector operator*(U number, const Vector& vector) { -#else -template inline typename std::enable_if::value, Vector>::type operator*(U number, const Vector& vector) { -#endif +template inline Vector operator*( + #ifdef DOXYGEN_GENERATING_OUTPUT + T + #else + typename std::common_type::type + #endif + number, const Vector& vector) +{ return vector*number; } @@ -544,13 +545,16 @@ template inline typename std::enable_if inline Vector operator/(U number, const Vector& vector) { -#else -template inline typename std::enable_if::value, Vector>::type operator/(U number, const Vector& vector) { -#endif +template inline Vector operator/( + #ifdef DOXYGEN_GENERATING_OUTPUT + T + #else + typename std::common_type::type + #endif + number, const Vector& vector) +{ Vector out; for(std::size_t i = 0; i != size; ++i) @@ -559,6 +563,184 @@ template inline typename std::enable_if inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value && std::is_floating_point::value, Vector&>::type +#endif +operator*=(Vector& vector, FloatingPoint number) { + for(std::size_t i = 0; i != size; ++i) + vector[i] *= number; + + return vector; +} + +/** @relates Vector +@brief Multiply integral vector with floating-point number + +Similar to Vector::operator*(T) const, except that the multiplication is done +in floating-point. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value && std::is_floating_point::value, Vector>::type +#endif +operator*(const Vector& vector, FloatingPoint number) { + Vector copy(vector); + return copy *= number; +} + +/** @relates Vector +@brief Multiply floating-point number with integral vector + +Same as operator*(const Vector&, FloatingPoint). +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value && std::is_floating_point::value, Vector>::type +#endif +operator*(FloatingPoint number, const Vector& vector) { + return vector*number; +} + +/** @relates Vector +@brief Divide integral vector with floating-point number and assign + +Similar to Vector::operator/=(T), except that the division is done in +floating-point. The computation is done in-place. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value && std::is_floating_point::value, Vector&>::type +#endif +operator/=(Vector& vector, FloatingPoint number) { + for(std::size_t i = 0; i != size; ++i) + vector[i] /= number; + + return vector; +} + +/** @relates Vector +@brief Divide integral vector with floating-point number + +Similar to Vector::operator/(T) const, except that the division is done in +floating-point. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value && std::is_floating_point::value, Vector>::type +#endif +operator/(const Vector& vector, FloatingPoint number) { + Vector copy(vector); + return copy /= number; +} + +/** @relates Vector +@brief Multiply integral vector with floating-point vector component-wise and assign + +Similar to Vector::operator*=(const Vector&), except that the +multiplication is done in floating-point. The computation is done in-place. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value && std::is_floating_point::value, Vector&>::type +#endif +operator*=(Vector& a, const Vector& b) { + for(std::size_t i = 0; i != size; ++i) + a[i] *= b[i]; + + return a; +} + +/** @relates Vector +@brief Multiply integral vector with floating-point vector component-wise + +Similar to Vector::operator*(const Vector&) const, except that the +multiplication is done in floating-point. The result is always integral vector, +convert both arguments to the same floating-point type to have floating-point +result. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value && std::is_floating_point::value, Vector>::type +#endif +operator*(const Vector& a, const Vector& b) { + Vector copy(a); + return copy *= b; +} + +/** @relates Vector +@brief Multiply floating-point vector with integral vector component-wise + +Same as operator*(const Vector&, const Vector&). +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value && std::is_floating_point::value, Vector>::type +#endif +operator*(const Vector& a, const Vector& b) { + return b*a; +} + +/** @relates Vector +@brief Divide integral vector with floating-point vector component-wise and assign + +Similar to Vector::operator/=(const Vector&), except that the division +is done in floating-point. The computation is done in-place. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value && std::is_floating_point::value, Vector&>::type +#endif +operator/=(Vector& a, const Vector& b) { + for(std::size_t i = 0; i != size; ++i) + a[i] /= b[i]; + + return a; +} + +/** @relates Vector +@brief Divide integral vector with floating-point vector component-wise + +Similar to Vector::operator/(const Vector&) const, except that the +division is done in floating-point. The result is always integral vector, +convert both arguments to the same floating-point type to have floating-point +result. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value && std::is_floating_point::value, Vector>::type +#endif +operator/(const Vector& a, const Vector& b) { + Vector copy(a); + return copy /= b; +} + /** @debugoperator{Magnum::Math::Vector} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector& value) { debug << "Vector("; @@ -591,7 +773,7 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit #endif #ifndef DOXYGEN_GENERATING_OUTPUT -#define MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Type, size) \ +#define MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(size, Type) \ constexpr static Type& from(T* data) { \ return *reinterpret_cast*>(data); \ } \ @@ -621,32 +803,32 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit Type operator-(const Math::Vector& other) const { \ return Math::Vector::operator-(other); \ } \ - template typename std::enable_if::value, Type&>::type operator*=(U number) { \ + Type& operator*=(T number) { \ Math::Vector::operator*=(number); \ return *this; \ } \ - template typename std::enable_if::value, Type>::type operator*(U number) const { \ + Type operator*(T number) const { \ return Math::Vector::operator*(number); \ } \ - template typename std::enable_if::value, Type&>::type operator/=(U number) { \ + Type& operator/=(T number) { \ Math::Vector::operator/=(number); \ return *this; \ } \ - template typename std::enable_if::value, Type>::type operator/(U number) const { \ + Type operator/(T number) const { \ return Math::Vector::operator/(number); \ } \ - template Type& operator*=(const Math::Vector& other) { \ + Type& operator*=(const Math::Vector& other) { \ Math::Vector::operator*=(other); \ return *this; \ } \ - template Type operator*(const Math::Vector& other) const { \ + Type operator*(const Math::Vector& other) const { \ return Math::Vector::operator*(other); \ } \ - template Type& operator/=(const Math::Vector& other) { \ + Type& operator/=(const Math::Vector& other) { \ Math::Vector::operator/=(other); \ return *this; \ } \ - template Type operator/(const Math::Vector& other) const { \ + Type operator/(const Math::Vector& other) const { \ return Math::Vector::operator/(other); \ } \ \ @@ -658,14 +840,53 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit } \ Type projected(const Math::Vector& other) const { \ return Math::Vector::projected(other); \ + } \ + Type projectedOntoNormalized(const Math::Vector& other) const { \ + return Math::Vector::projectedOntoNormalized(other); \ } -#define MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Type, size) \ - template inline typename std::enable_if::value, Type>::type operator*(U number, const Type& vector) { \ - return number*Math::Vector(vector); \ +#define MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(size, Type) \ + template inline Type operator*(typename std::common_type::type number, const Type& vector) { \ + return number*static_cast&>(vector); \ + } \ + template inline Type operator/(typename std::common_type::type number, const Type& vector) { \ + return number/static_cast&>(vector); \ + } \ + \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator*=(Type& vector, FloatingPoint number) { \ + static_cast&>(vector) *= number; \ + return vector; \ + } \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Type& vector, FloatingPoint number) { \ + return static_cast&>(vector)*number; \ + } \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(FloatingPoint number, const Type& vector) { \ + return number*static_cast&>(vector); \ + } \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator/=(Type& vector, FloatingPoint number) { \ + static_cast&>(vector) /= number; \ + return vector; \ + } \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator/(const Type& vector, FloatingPoint number) { \ + return static_cast&>(vector)/number; \ + } \ + \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator*=(Type& a, const Math::Vector& b) { \ + static_cast&>(a) *= b; \ + return a; \ + } \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Type& a, const Math::Vector& b) { \ + return static_cast&>(a)*b; \ + } \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Math::Vector& a, const Type& b) { \ + return a*static_cast&>(b); \ + } \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator/=(Type& a, const Math::Vector& b) { \ + static_cast&>(a) /= b; \ + return a; \ } \ - template inline typename std::enable_if::value, Type>::type operator/(U number, const Type& vector) { \ - return number/Math::Vector(vector); \ + template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator/(const Type& a, const Math::Vector& b) { \ + return static_cast&>(a)/b; \ } #endif diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 3f1b5a9dc..f55483b7d 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -134,10 +134,10 @@ template class Vector2: public Vector<2, T> { */ Vector2 perpendicular() const { return {-y(), x()}; } - MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector2, 2) + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2) }; -MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector2, 2) +MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(2, Vector2) /** @debugoperator{Magnum::Math::Vector2} */ template inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector2& value) { diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index ad0beff03..99d0692f7 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -161,10 +161,10 @@ template class Vector3: public Vector<3, T> { Vector2& xy() { return Vector2::from(Vector<3, T>::data()); } constexpr const Vector2 xy() const { return {x(), y()}; } /**< @overload */ - MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector3, 3) + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(3, Vector3) }; -MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector3, 3) +MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(3, Vector3) /** @debugoperator{Magnum::Math::Vector3} */ template inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector3& value) { diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index 2af6e2da8..ecc6cfe20 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -102,10 +102,10 @@ template class Vector4: public Vector<4, T> { Vector2& xy() { return Vector2::from(Vector<4, T>::data()); } constexpr const Vector2 xy() const { return {x(), y()}; } /**< @overload */ - MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector4, 4) + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(4, Vector4) }; -MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector4, 4) +MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, Vector4) /** @debugoperator{Magnum::Math::Vector4} */ template inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector4& value) { diff --git a/src/Text/DistanceFieldGlyphCache.cpp b/src/Text/DistanceFieldGlyphCache.cpp index 476ee61b7..5b2eab84c 100644 --- a/src/Text/DistanceFieldGlyphCache.cpp +++ b/src/Text/DistanceFieldGlyphCache.cpp @@ -42,7 +42,7 @@ DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, c GlyphCache(Context::current()->isExtensionSupported() ? TextureFormat::Red : TextureFormat::RGB, originalSize, size, Vector2i(radius)), #endif - scale(Vector2(size)/originalSize), radius(radius) + scale(Vector2(size)/Vector2(originalSize)), radius(radius) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); diff --git a/src/TextureTools/DistanceField.cpp b/src/TextureTools/DistanceField.cpp index e2d185a8d..5165a3a51 100644 --- a/src/TextureTools/DistanceField.cpp +++ b/src/TextureTools/DistanceField.cpp @@ -158,7 +158,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Rectanglei& rectan DistanceFieldShader shader; shader.setRadius(radius) - .setScaling(Vector2(imageSize)/rectangle.size()) + .setScaling(Vector2(imageSize)/Vector2(rectangle.size())) .use(); input.bind(DistanceFieldShader::TextureLayer); @@ -169,7 +169,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Rectanglei& rectan if(!Context::current()->isVersionSupported(Version::GLES300)) #endif { - shader.setImageSizeInverted(Vector2(1)/imageSize); + shader.setImageSizeInverted(1.0f/Vector2(imageSize)); } Mesh mesh;