Browse Source

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.
pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
b4a33d15c3
  1. 8
      src/Color.h
  2. 134
      src/Math/Test/VectorTest.cpp
  3. 333
      src/Math/Vector.h
  4. 4
      src/Math/Vector2.h
  5. 4
      src/Math/Vector3.h
  6. 4
      src/Math/Vector4.h
  7. 2
      src/Text/DistanceFieldGlyphCache.cpp
  8. 4
      src/TextureTools/DistanceField.cpp

8
src/Color.h

@ -254,13 +254,13 @@ template<class T> class BasicColor3: public Math::Vector3<T> {
return Implementation::value<T>(*this);
}
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(BasicColor3, 3)
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(3, BasicColor3)
};
/** @brief Three-component (RGB) float color */
typedef BasicColor3<Float> 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<T> {
return Implementation::value<T>(rgb());
}
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(BasicColor4, 4)
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(4, BasicColor4)
};
/** @brief Four-component (RGBA) float color */
typedef BasicColor4<Float> Color4;
MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(BasicColor4, 4)
MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, BasicColor4)
/** @debugoperator{Magnum::BasicColor3} */
template<class T> inline Debug operator<<(Debug debug, const BasicColor3<T>& value) {

134
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 T> class BasicVec2: public Math::Vector<2, T> {
public:
template<class ...U> BasicVec2(U&&... args): Math::Vector<2, T>{std::forward<U>(args)...} {}
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, BasicVec2)
};
MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(2, BasicVec2)
typedef BasicVec2<Float> Vec2;
typedef BasicVec2<Int> Vec2i;
void VectorTest::subclassTypes() {
Float* const data = nullptr;
const Float* const cdata = nullptr;
CORRADE_VERIFY((std::is_same<decltype(Vec2::from(data)), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(Vec2::from(cdata)), const Vec2&>::value));
/* Const operators */
const Vec2 c;
const Vec2 c2;
CORRADE_VERIFY((std::is_same<decltype(-c), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c + c), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c*1.0f), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f*c), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c/1.0f), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f/c), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c*c2), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c/c2), Vec2>::value));
/* Assignment operators */
Vec2 a;
CORRADE_VERIFY((std::is_same<decltype(a = c), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a += c), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a -= c), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a *= 1.0f), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a /= 1.0f), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a *= c), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a /= c), Vec2&>::value));
/* Integer multiplication/division */
const Vec2i ci;
Vec2i i;
CORRADE_VERIFY((std::is_same<decltype(ci*1.0f), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f*ci), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(c*ci), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(ci*c), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(ci/c), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(i *= c), Vec2i&>::value));
CORRADE_VERIFY((std::is_same<decltype(i /= c), Vec2i&>::value));
/* Functions */
CORRADE_VERIFY((std::is_same<decltype(c.normalized()), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c.resized(1.0f)), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c.projected(c2)), Vec2>::value));
CORRADE_VERIFY((std::is_same<decltype(c.projectedOntoNormalized(c2)), Vec2>::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);

333
src/Math/Vector.h

@ -306,12 +306,10 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[
* \boldsymbol a_i = b \boldsymbol a_i
* @f]
* @see operator*=(const Vector<size, T>&),
* operator*=(Vector<size, Integral>&, FloatingPoint)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class U> Vector<size, T>& operator*=(U number) {
#else
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>&>::type operator*=(U number) {
#endif
Vector<size, T>& operator*=(T number) {
for(std::size_t i = 0; i != size; ++i)
_data[i] *= number;
@ -321,13 +319,11 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Multiply vector with number
*
* @see operator*=(U), operator*(U, const Vector<size, T>&)
* @see operator*(const Vector<size, T>&) const,
* operator*=(T), operator*(T, const Vector<size, T>&),
* operator*(const Vector<size, Integral>&, FloatingPoint)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class U> Vector<size, T> operator*(U number) const {
#else
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>>::type operator*(U number) const {
#endif
Vector<size, T> operator*(T number) const {
return Vector<size, T>(*this) *= number;
}
@ -337,12 +333,10 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[
* \boldsymbol a_i = \frac{\boldsymbol a_i} b
* @f]
* @see operator/=(const Vector<size, T>&),
* operator/=(Vector<size, Integral>&, FloatingPoint)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class U> Vector<size, T>& operator/=(U number) {
#else
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>&>::type operator/=(U number) {
#endif
Vector<size, T>& operator/=(T number) {
for(std::size_t i = 0; i != size; ++i)
_data[i] /= number;
@ -352,13 +346,11 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Divide vector with number
*
* @see operator/=(), operator/(U, const Vector<size, T>&)
* @see operator/(const Vector<size, T>&) const,
* operator/=(T), operator/(T, const Vector<size, T>&),
* operator/(const Vector<size, Integral>&, FloatingPoint)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class U> Vector<size, T> operator/(U number) const {
#else
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Vector<size, T>>::type operator/(U number) const {
#endif
Vector<size, T> operator/(T number) const {
return Vector<size, T>(*this) /= number;
}
@ -368,8 +360,10 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[
* \boldsymbol a_i = \boldsymbol a_i \boldsymbol b_i
* @f]
* @see operator*=(T),
* operator*=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/
template<class U> Vector<size, T>& operator*=(const Vector<size, U>& other) {
Vector<size, T>& operator*=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] *= other._data[i];
@ -379,9 +373,10 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Multiply vector component-wise
*
* @see operator*=(const Vector<size, U>&), product()
* @see operator*(T) const, operator*=(const Vector<size, T>&),
* operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/
template<class U> Vector<size, T> operator*(const Vector<size, U>& other) const {
Vector<size, T> operator*(const Vector<size, T>& other) const {
return Vector<size, T>(*this) *= other;
}
@ -391,8 +386,10 @@ template<std::size_t size, class T> 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<size, Integral>&, const Vector<size, FloatingPoint>&)
*/
template<class U> Vector<size, T>& operator/=(const Vector<size, U>& other) {
Vector<size, T>& operator/=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] /= other._data[i];
@ -402,9 +399,10 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Divide vector component-wise
*
* @see operator/=(const Vector<size, U>&)
* @see operator/(T) const, operator/=(const Vector<size, T>&),
* operator/(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/
template<class U> Vector<size, T> operator/(const Vector<size, U>& other) const {
Vector<size, T> operator/(const Vector<size, T>& other) const {
return Vector<size, T>(*this) /= other;
}
@ -415,7 +413,7 @@ template<std::size_t size, class T> 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<size, T>&, const Vector<size, T>&), isNormalized()
*/
T dot() const { return dot(*this, *this); }
@ -497,7 +495,7 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Product of values in the vector
*
* @see operator*(const Vector&)
* @see operator*(const Vector<size, T>&) const
*/
T product() const;
@ -528,13 +526,16 @@ template<std::size_t size, class T> 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<std::size_t size, class T, class U> inline Vector<size, T> operator*(U number, const Vector<size, T>& vector) {
#else
template<std::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) {
#endif
template<std::size_t size, class T> inline Vector<size, T> operator*(
#ifdef DOXYGEN_GENERATING_OUTPUT
T
#else
typename std::common_type<T>::type
#endif
number, const Vector<size, T>& vector)
{
return vector*number;
}
@ -544,13 +545,16 @@ template<std::size_t size, class T, class U> inline typename std::enable_if<std:
@f[
\boldsymbol c_i = \frac b {\boldsymbol a_i}
@f]
@see Vector::operator/()
@see Vector::operator/(T) const
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<std::size_t size, class T, class U> inline Vector<size, T> operator/(U number, const Vector<size, T>& vector) {
#else
template<std::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) {
#endif
template<std::size_t size, class T> inline Vector<size, T> operator/(
#ifdef DOXYGEN_GENERATING_OUTPUT
T
#else
typename std::common_type<T>::type
#endif
number, const Vector<size, T>& vector)
{
Vector<size, T> out;
for(std::size_t i = 0; i != size; ++i)
@ -559,6 +563,184 @@ template<std::size_t size, class T, class U> inline typename std::enable_if<std:
return out;
}
/** @relates Vector
@brief Multiply integral vector with floating-point number and assign
Similar to Vector::operator*=(T), except that the multiplication is done in
floating-point. The computation is done in-place.
*/
template<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>&>::type
#endif
operator*=(Vector<size, Integral>& 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<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type
#endif
operator*(const Vector<size, Integral>& vector, FloatingPoint number) {
Vector<size, Integral> copy(vector);
return copy *= number;
}
/** @relates Vector
@brief Multiply floating-point number with integral vector
Same as operator*(const Vector<size, Integral>&, FloatingPoint).
*/
template<std::size_t size, class FloatingPoint, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type
#endif
operator*(FloatingPoint number, const Vector<size, Integral>& 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<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>&>::type
#endif
operator/=(Vector<size, Integral>& 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<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type
#endif
operator/(const Vector<size, Integral>& vector, FloatingPoint number) {
Vector<size, Integral> 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<size, T>&), except that the
multiplication is done in floating-point. The computation is done in-place.
*/
template<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>&>::type
#endif
operator*=(Vector<size, Integral>& a, const Vector<size, FloatingPoint>& 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<size, T>&) 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<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type
#endif
operator*(const Vector<size, Integral>& a, const Vector<size, FloatingPoint>& b) {
Vector<size, Integral> copy(a);
return copy *= b;
}
/** @relates Vector
@brief Multiply floating-point vector with integral vector component-wise
Same as operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&).
*/
template<std::size_t size, class FloatingPoint, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type
#endif
operator*(const Vector<size, FloatingPoint>& a, const Vector<size, Integral>& b) {
return b*a;
}
/** @relates Vector
@brief Divide integral vector with floating-point vector component-wise and assign
Similar to Vector::operator/=(const Vector<size, T>&), except that the division
is done in floating-point. The computation is done in-place.
*/
template<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>&>::type
#endif
operator/=(Vector<size, Integral>& a, const Vector<size, FloatingPoint>& 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<size, T>&) 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<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type
#endif
operator/(const Vector<size, Integral>& a, const Vector<size, FloatingPoint>& b) {
Vector<size, Integral> copy(a);
return copy /= b;
}
/** @debugoperator{Magnum::Math::Vector} */
template<std::size_t size, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector<size, T>& 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<T>& from(T* data) { \
return *reinterpret_cast<Type<T>*>(data); \
} \
@ -621,32 +803,32 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
Type<T> operator-(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::operator-(other); \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Type<T>&>::type operator*=(U number) { \
Type<T>& operator*=(T number) { \
Math::Vector<size, T>::operator*=(number); \
return *this; \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Type<T>>::type operator*(U number) const { \
Type<T> operator*(T number) const { \
return Math::Vector<size, T>::operator*(number); \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Type<T>&>::type operator/=(U number) { \
Type<T>& operator/=(T number) { \
Math::Vector<size, T>::operator/=(number); \
return *this; \
} \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, Type<T>>::type operator/(U number) const { \
Type<T> operator/(T number) const { \
return Math::Vector<size, T>::operator/(number); \
} \
template<class U> Type<T>& operator*=(const Math::Vector<size, U>& other) { \
Type<T>& operator*=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator*=(other); \
return *this; \
} \
template<class U> Type<T> operator*(const Math::Vector<size, U>& other) const { \
Type<T> operator*(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::operator*(other); \
} \
template<class U> Type<T>& operator/=(const Math::Vector<size, U>& other) { \
Type<T>& operator/=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator/=(other); \
return *this; \
} \
template<class U> Type<T> operator/(const Math::Vector<size, U>& other) const { \
Type<T> operator/(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::operator/(other); \
} \
\
@ -658,14 +840,53 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
} \
Type<T> projected(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::projected(other); \
} \
Type<T> projectedOntoNormalized(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::projectedOntoNormalized(other); \
}
#define MAGNUM_VECTOR_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>& vector) { \
return number*Math::Vector<size, T>(vector); \
#define MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(size, Type) \
template<class T> inline Type<T> operator*(typename std::common_type<T>::type number, const Type<T>& vector) { \
return number*static_cast<const Math::Vector<size, T>&>(vector); \
} \
template<class T> inline Type<T> operator/(typename std::common_type<T>::type number, const Type<T>& vector) { \
return number/static_cast<const Math::Vector<size, T>&>(vector); \
} \
\
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>&>::type operator*=(Type<Integral>& vector, FloatingPoint number) { \
static_cast<Math::Vector<size, Integral>&>(vector) *= number; \
return vector; \
} \
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator*(const Type<Integral>& vector, FloatingPoint number) { \
return static_cast<const Math::Vector<size, Integral>&>(vector)*number; \
} \
template<class FloatingPoint, class Integral> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator*(FloatingPoint number, const Type<Integral>& vector) { \
return number*static_cast<const Math::Vector<size, Integral>&>(vector); \
} \
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>&>::type operator/=(Type<Integral>& vector, FloatingPoint number) { \
static_cast<Math::Vector<size, Integral>&>(vector) /= number; \
return vector; \
} \
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator/(const Type<Integral>& vector, FloatingPoint number) { \
return static_cast<const Math::Vector<size, Integral>&>(vector)/number; \
} \
\
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>&>::type operator*=(Type<Integral>& a, const Math::Vector<size, FloatingPoint>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) *= b; \
return a; \
} \
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator*(const Type<Integral>& a, const Math::Vector<size, FloatingPoint>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a)*b; \
} \
template<class FloatingPoint, class Integral> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator*(const Math::Vector<size, FloatingPoint>& a, const Type<Integral>& b) { \
return a*static_cast<const Math::Vector<size, Integral>&>(b); \
} \
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>&>::type operator/=(Type<Integral>& a, const Math::Vector<size, FloatingPoint>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) /= b; \
return a; \
} \
template<class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Type<T>>::type operator/(U number, const Type<T>& vector) { \
return number/Math::Vector<size, T>(vector); \
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator/(const Type<Integral>& a, const Math::Vector<size, FloatingPoint>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a)/b; \
}
#endif

4
src/Math/Vector2.h

@ -134,10 +134,10 @@ template<class T> class Vector2: public Vector<2, T> {
*/
Vector2<T> 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<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector2<T>& value) {

4
src/Math/Vector3.h

@ -161,10 +161,10 @@ template<class T> class Vector3: public Vector<3, T> {
Vector2<T>& xy() { return Vector2<T>::from(Vector<3, T>::data()); }
constexpr const Vector2<T> 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<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector3<T>& value) {

4
src/Math/Vector4.h

@ -102,10 +102,10 @@ template<class T> class Vector4: public Vector<4, T> {
Vector2<T>& xy() { return Vector2<T>::from(Vector<4, T>::data()); }
constexpr const Vector2<T> 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<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Vector4<T>& value) {

2
src/Text/DistanceFieldGlyphCache.cpp

@ -42,7 +42,7 @@ DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, c
GlyphCache(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>() ?
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);

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

Loading…
Cancel
Save