Browse Source

Math: C++14 constexpr in Vector.

pull/276/head
Vladimír Vondruš 12 years ago
parent
commit
7f662f2c3e
  1. 226
      src/Magnum/Math/Test/VectorTest.cpp
  2. 212
      src/Magnum/Math/Vector.h

226
src/Magnum/Math/Test/VectorTest.cpp

@ -245,8 +245,8 @@ void VectorTest::data() {
/* Pointer chasings, i.e. *(b.data()[3]), are not possible */ /* Pointer chasings, i.e. *(b.data()[3]), are not possible */
constexpr Vector4 a(1.0f, 2.0f, -3.0f, 4.5f); constexpr Vector4 a(1.0f, 2.0f, -3.0f, 4.5f);
constexpr Float f = a[3]; constexpr auto f = a[3];
constexpr Float g = *a.data(); constexpr auto g = *a.data();
CORRADE_COMPARE(f, 4.5f); CORRADE_COMPARE(f, 4.5f);
CORRADE_COMPARE(g, 1.0f); CORRADE_COMPARE(g, 1.0f);
} }
@ -261,101 +261,145 @@ void VectorTest::compare() {
void VectorTest::compareComponentWise() { void VectorTest::compareComponentWise() {
typedef BoolVector<3> BoolVector3; typedef BoolVector<3> BoolVector3;
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) < Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x1));
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) <= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x3)); constexpr auto a = Vector3(1.0f, -1.0f, 5.0f) < Vector3(1.1f, -1.0f, 3.0f);
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) >= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x6)); constexpr auto b = Vector3(1.0f, -1.0f, 5.0f) <= Vector3(1.1f, -1.0f, 3.0f);
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) > Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x4)); constexpr auto c = Vector3(1.0f, -1.0f, 5.0f) >= Vector3(1.1f, -1.0f, 3.0f);
constexpr auto d = Vector3(1.0f, -1.0f, 5.0f) > Vector3(1.1f, -1.0f, 3.0f);
CORRADE_COMPARE(a, BoolVector3(0x1));
CORRADE_COMPARE(b, BoolVector3(0x3));
CORRADE_COMPARE(c, BoolVector3(0x6));
CORRADE_COMPARE(d, BoolVector3(0x4));
} }
void VectorTest::negative() { void VectorTest::negative() {
CORRADE_COMPARE(-Vector4(1.0f, -3.0f, 5.0f, -10.0f), Vector4(-1.0f, 3.0f, -5.0f, 10.0f)); constexpr auto a = -Vector4(1.0f, -3.0f, 5.0f, -10.0f);
CORRADE_COMPARE(a, Vector4(-1.0f, 3.0f, -5.0f, 10.0f));
} }
void VectorTest::addSubtract() { void VectorTest::addSubtract() {
Vector4 a(1.0f, -3.0f, 5.0f, -10.0f); constexpr Vector4 a(1.0f, -3.0f, 5.0f, -10.0f);
Vector4 b(7.5f, 33.0f, -15.0f, 0.0f); constexpr Vector4 b(7.5f, 33.0f, -15.0f, 0.0f);
Vector4 c(8.5f, 30.0f, -10.0f, -10.0f); constexpr Vector4 c(8.5f, 30.0f, -10.0f, -10.0f);
constexpr auto d = a + b;
constexpr auto e = c - b;
CORRADE_COMPARE(a + b, c); CORRADE_COMPARE(d, c);
CORRADE_COMPARE(c - b, a); CORRADE_COMPARE(e, a);
} }
void VectorTest::multiplyDivide() { void VectorTest::multiplyDivide() {
Vector4 vector(1.0f, 2.0f, 3.0f, 4.0f); constexpr Vector4 vector(1.0f, 2.0f, 3.0f, 4.0f);
Vector4 multiplied(-1.5f, -3.0f, -4.5f, -6.0f); constexpr Vector4 multiplied(-1.5f, -3.0f, -4.5f, -6.0f);
CORRADE_COMPARE(vector*-1.5f, multiplied); constexpr auto a = vector*-1.5f;
CORRADE_COMPARE(-1.5f*vector, multiplied); constexpr auto b = -1.5f*vector;
CORRADE_COMPARE(multiplied/-1.5f, vector); constexpr auto c = multiplied/-1.5f;
CORRADE_COMPARE(a, multiplied);
CORRADE_COMPARE(b, multiplied);
CORRADE_COMPARE(c, vector);
/* Divide vector with number and invert */ /* Divide vector with number and invert */
Vector4 divisor(1.0f, 2.0f, -4.0f, 8.0f); constexpr Vector4 divisor(1.0f, 2.0f, -4.0f, 8.0f);
Vector4 result(1.0f, 0.5f, -0.25f, 0.125f); constexpr auto d = 1.0f/divisor;
CORRADE_COMPARE(1.0f/divisor, result);
CORRADE_COMPARE(d, Vector4(1.0f, 0.5f, -0.25f, 0.125f));
} }
void VectorTest::multiplyDivideIntegral() { void VectorTest::multiplyDivideIntegral() {
Vector4i vector(32, 10, -6, 2); constexpr Vector4i vector(32, 10, -6, 2);
Vector4i multiplied(-48, -15, 9, -3); constexpr Vector4i multiplied(-48, -15, 9, -3);
CORRADE_COMPARE(vector*-1.5f, multiplied); constexpr auto a = vector*-1.5f;
CORRADE_COMPARE(-1.5f*vector, multiplied); constexpr auto b = -1.5f*vector;
CORRADE_COMPARE(multiplied/-1.5f, vector); CORRADE_COMPARE(a, multiplied);
CORRADE_COMPARE(b, multiplied);
constexpr auto c = multiplied/-1.5f;
CORRADE_COMPARE(c, vector);
/* Using integer vector as divisor is not supported */ /* Using integer vector as divisor is not supported */
} }
void VectorTest::multiplyDivideComponentWise() { void VectorTest::multiplyDivideComponentWise() {
Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f); constexpr Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f);
Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f); constexpr Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f);
Vector4 multiplied(7.0f, -8.0f, -4.5f, 4.0f); constexpr Vector4 multiplied(7.0f, -8.0f, -4.5f, 4.0f);
constexpr auto a = vec*multiplier;
constexpr auto b = multiplied/multiplier;
CORRADE_COMPARE(vec*multiplier, multiplied); CORRADE_COMPARE(a, multiplied);
CORRADE_COMPARE(multiplied/multiplier, vec); CORRADE_COMPARE(b, vec);
} }
void VectorTest::multiplyDivideComponentWiseIntegral() { void VectorTest::multiplyDivideComponentWiseIntegral() {
Vector4i vec(7, 2, -16, -1); constexpr Vector4i vec(7, 2, -16, -1);
Vector4 multiplier(2.0f, -1.5f, 0.5f, 10.0f); constexpr Vector4 multiplier(2.0f, -1.5f, 0.5f, 10.0f);
Vector4i multiplied(14, -3, -8, -10); constexpr Vector4i multiplied(14, -3, -8, -10);
constexpr auto a = vec*multiplier;
constexpr auto b = multiplier*vec;
CORRADE_COMPARE(a, multiplied);
CORRADE_COMPARE(b, multiplied);
CORRADE_COMPARE(vec*multiplier, multiplied); constexpr auto c = multiplied/multiplier;
CORRADE_COMPARE(multiplier*vec, multiplied);
CORRADE_COMPARE(multiplied/multiplier, vec); CORRADE_COMPARE(c, vec);
/* Using integer vector as divisor is not supported */ /* Using integer vector as divisor is not supported */
} }
void VectorTest::modulo() { void VectorTest::modulo() {
typedef Math::Vector<2, Int> Vector2i; typedef Math::Vector<2, Int> Vector2i;
const Vector2i a(4, 13); constexpr Vector2i a(4, 13);
const Vector2i b(2, 5); constexpr Vector2i b(2, 5);
CORRADE_COMPARE(a % 2, Vector2i(0, 1));
CORRADE_COMPARE(a % b, Vector2i(0, 3)); constexpr auto c = a % 2;
constexpr auto d = a % b;
CORRADE_COMPARE(c, Vector2i(0, 1));
CORRADE_COMPARE(d, Vector2i(0, 3));
} }
void VectorTest::bitwise() { void VectorTest::bitwise() {
typedef Math::Vector<2, Int> Vector2i; typedef Math::Vector<2, Int> Vector2i;
const Vector2i a(85, 240); constexpr Vector2i a(85, 240);
const Vector2i b(170, 85); constexpr Vector2i b(170, 85);
CORRADE_COMPARE(~a, Vector2i(-86, -241));
CORRADE_COMPARE(a & b, Vector2i(0, 80)); constexpr auto c = ~a;
CORRADE_COMPARE(a | b, Vector2i(255, 245)); constexpr auto d = a & b;
CORRADE_COMPARE(a ^ b, Vector2i(255, 165)); constexpr auto e = a | b;
constexpr auto f = a ^ b;
CORRADE_COMPARE(c, Vector2i(-86, -241));
CORRADE_COMPARE(d, Vector2i(0, 80));
CORRADE_COMPARE(e, Vector2i(255, 245));
CORRADE_COMPARE(f, Vector2i(255, 165));
constexpr Vector2i g(7, 32);
const Vector2i c(7, 32); constexpr auto h = g << 2;
CORRADE_COMPARE(c << 2, Vector2i(28, 128)); constexpr auto i = g >> 2;
CORRADE_COMPARE(c >> 2, Vector2i(1, 8));
CORRADE_COMPARE(h, Vector2i(28, 128));
CORRADE_COMPARE(i, Vector2i(1, 8));
} }
void VectorTest::dot() { 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); constexpr auto a = Vector4::dot({1.0f, 0.5f, 0.75f, 1.5f}, {2.0f, 4.0f, 1.0f, 7.0f});
CORRADE_COMPARE(a, 15.25f);
} }
void VectorTest::dotSelf() { void VectorTest::dotSelf() {
CORRADE_COMPARE(Vector4(1.0f, 2.0f, 3.0f, 4.0f).dot(), 30.0f); constexpr auto a = Vector4(1.0f, 2.0f, 3.0f, 4.0f).dot();
CORRADE_COMPARE(a, 30.0f);
} }
void VectorTest::length() { void VectorTest::length() {
@ -379,11 +423,13 @@ void VectorTest::resized() {
} }
void VectorTest::sum() { void VectorTest::sum() {
CORRADE_COMPARE(Vector3(1.0f, 2.0f, 4.0f).sum(), 7.0f); constexpr auto a = Vector3(1.0f, 2.0f, 4.0f).sum();
CORRADE_COMPARE(a, 7.0f);
} }
void VectorTest::product() { void VectorTest::product() {
CORRADE_COMPARE(Vector3(1.0f, 2.0f, 3.0f).product(), 6.0f); constexpr auto a = Vector3(1.0f, 2.0f, 3.0f).product();
CORRADE_COMPARE(a, 6.0f);
} }
void VectorTest::min() { void VectorTest::min() {
@ -522,38 +568,60 @@ void VectorTest::subclass() {
const Float cdata[] = {1.0f, -2.0f}; const Float cdata[] = {1.0f, -2.0f};
CORRADE_COMPARE(Vec2::from(cdata), Vec2(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)); constexpr auto a = Vec2(-2.0f, 5.0f) + Vec2(1.0f, -3.0f);
CORRADE_COMPARE(Vec2(-2.0f, 5.0f) - Vec2(1.0f, -3.0f), Vec2(-3.0f, 8.0f)); constexpr auto b = Vec2(-2.0f, 5.0f) - Vec2(1.0f, -3.0f);
CORRADE_COMPARE(a, Vec2(-1.0f, 2.0f));
CORRADE_COMPARE(Vec2(-2.0f, 5.0f)*2.0f, Vec2(-4.0f, 10.0f)); CORRADE_COMPARE(b, Vec2(-3.0f, 8.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)); constexpr auto c = Vec2(-2.0f, 5.0f)*2.0f;
CORRADE_COMPARE(2.0f/Vec2(-2.0f, 5.0f), Vec2(-1.0f, 0.4f)); constexpr auto d = 2.0f*Vec2(-2.0f, 5.0f);
constexpr auto e = Vec2(-2.0f, 5.0f)/0.5f;
CORRADE_COMPARE(Vec2(-2.0f, 5.0f)*Vec2(1.5f, -2.0f), Vec2(-3.0f, -10.0f)); constexpr auto f = 2.0f/Vec2(-2.0f, 5.0f);
CORRADE_COMPARE(Vec2(-2.0f, 5.0f)/Vec2(2.0f/3.0f, -0.5f), Vec2(-3.0f, -10.0f)); CORRADE_COMPARE(c, Vec2(-4.0f, 10.0f));
CORRADE_COMPARE(d, Vec2(-4.0f, 10.0f));
CORRADE_COMPARE(e, Vec2(-4.0f, 10.0f));
CORRADE_COMPARE(f, Vec2(-1.0f, 0.4f));
constexpr auto g = Vec2(-2.0f, 5.0f)*Vec2(1.5f, -2.0f);
constexpr auto h = Vec2(-2.0f, 5.0f)/Vec2(2.0f/3.0f, -0.5f);
CORRADE_COMPARE(g, Vec2(-3.0f, -10.0f));
CORRADE_COMPARE(h, Vec2(-3.0f, -10.0f));
/* Modulo operations */ /* Modulo operations */
CORRADE_COMPARE(Vec2i(4, 13) % 2, Vec2i(0, 1)); constexpr auto i = Vec2i(4, 13) % 2;
CORRADE_COMPARE(Vec2i(4, 13) % Vec2i(2, 5), Vec2i(0, 3)); constexpr auto j = Vec2i(4, 13) % Vec2i(2, 5);
CORRADE_COMPARE(i, Vec2i(0, 1));
CORRADE_COMPARE(j, Vec2i(0, 3));
/* Bitwise operations */ /* Bitwise operations */
CORRADE_COMPARE(~Vec2i(85, 240), Vec2i(-86, -241)); constexpr auto k = ~Vec2i(85, 240);
CORRADE_COMPARE(Vec2i(85, 240) & Vec2i(170, 85), Vec2i(0, 80)); constexpr auto l = Vec2i(85, 240) & Vec2i(170, 85);
CORRADE_COMPARE(Vec2i(85, 240) | Vec2i(170, 85), Vec2i(255, 245)); constexpr auto m = Vec2i(85, 240) | Vec2i(170, 85);
CORRADE_COMPARE(Vec2i(85, 240) ^ Vec2i(170, 85), Vec2i(255, 165)); constexpr auto n = Vec2i(85, 240) ^ Vec2i(170, 85);
CORRADE_COMPARE(k, Vec2i(-86, -241));
CORRADE_COMPARE(Vec2i(7, 32) << 2, Vec2i(28, 128)); CORRADE_COMPARE(l, Vec2i(0, 80));
CORRADE_COMPARE(Vec2i(7, 32) >> 2, Vec2i(1, 8)); CORRADE_COMPARE(m, Vec2i(255, 245));
CORRADE_COMPARE(n, Vec2i(255, 165));
constexpr auto o = Vec2i(7, 32) << 2;
constexpr auto p = Vec2i(7, 32) >> 2;
CORRADE_COMPARE(o, Vec2i(28, 128));
CORRADE_COMPARE(p, Vec2i(1, 8));
/* Integral multiplication/division */ /* Integral multiplication/division */
CORRADE_COMPARE(Vec2i(2, 4)*1.5f, Vec2i(3, 6)); constexpr auto q = Vec2i(2, 4)*1.5f;
CORRADE_COMPARE(1.5f*Vec2i(2, 4), Vec2i(3, 6)); constexpr auto r = 1.5f*Vec2i(2, 4);
CORRADE_COMPARE(Vec2i(2, 4)/(2.0f/3.0f), Vec2i(3, 6)); constexpr auto s = Vec2i(2, 4)/(2.0f/3.0f);
CORRADE_COMPARE(q, Vec2i(3, 6));
CORRADE_COMPARE(Vec2i(2, 4)*Vec2(-1.5f, 0.5f), Vec2i(-3, 2)); CORRADE_COMPARE(r, Vec2i(3, 6));
CORRADE_COMPARE(Vec2(-1.5f, 0.5f)*Vec2i(2, 4), Vec2i(-3, 2)); CORRADE_COMPARE(s, Vec2i(3, 6));
CORRADE_COMPARE(Vec2i(2, 4)/Vec2(-2.0f/3.0f, 2.0f), Vec2i(-3, 2));
constexpr auto t = Vec2i(2, 4)*Vec2(-1.5f, 0.5f);
constexpr auto u = Vec2(-1.5f, 0.5f)*Vec2i(2, 4);
constexpr auto v = Vec2i(2, 4)/Vec2(-2.0f/3.0f, 2.0f);
CORRADE_COMPARE(t, Vec2i(-3, 2));
CORRADE_COMPARE(u, Vec2i(-3, 2));
CORRADE_COMPARE(v, Vec2i(-3, 2));
/* Functions */ /* Functions */
CORRADE_COMPARE(Vec2(3.0f, 0.0f).normalized(), Vec2(1.0f, 0.0f)); CORRADE_COMPARE(Vec2(3.0f, 0.0f).normalized(), Vec2(1.0f, 0.0f));

212
src/Magnum/Math/Vector.h

@ -91,7 +91,7 @@ template<std::size_t size, class T> class Vector {
* @ref Vector2::perpendicular() * @ref Vector2::perpendicular()
* @todoc Explicit reference when Doxygen can handle const * @todoc Explicit reference when Doxygen can handle const
*/ */
static T dot(const Vector<size, T>& a, const Vector<size, T>& b) { constexpr static T dot(const Vector<size, T>& a, const Vector<size, T>& b) {
return (a*b).sum(); return (a*b).sum();
} }
@ -155,7 +155,7 @@ template<std::size_t size, class T> class Vector {
constexpr Vector(const Vector<size, T>&) = default; constexpr Vector(const Vector<size, T>&) = default;
/** @brief Assignment operator */ /** @brief Assignment operator */
Vector<size, T>& operator=(const Vector<size, T>&) = default; constexpr Vector<size, T>& operator=(const Vector<size, T>&) = default;
/** @brief Convert vector to external representation */ /** @brief Convert vector to external representation */
template<class U, class V = decltype(Implementation::VectorConverter<size, T, U>::to(std::declval<Vector<size, T>>()))> constexpr explicit operator U() const { template<class U, class V = decltype(Implementation::VectorConverter<size, T, U>::to(std::declval<Vector<size, T>>()))> constexpr explicit operator U() const {
@ -168,7 +168,7 @@ template<std::size_t size, class T> class Vector {
* *
* @see @ref operator[]() * @see @ref operator[]()
*/ */
T* data() { return _data; } constexpr T* data() { return _data; }
constexpr const T* data() const { return _data; } /**< @overload */ constexpr const T* data() const { return _data; } /**< @overload */
/** /**
@ -176,7 +176,7 @@ template<std::size_t size, class T> class Vector {
* *
* @see @ref data() * @see @ref data()
*/ */
T& operator[](std::size_t pos) { return _data[pos]; } constexpr T& operator[](std::size_t pos) { return _data[pos]; }
constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */ constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */
/** @brief Equality comparison */ /** @brief Equality comparison */
@ -193,16 +193,16 @@ template<std::size_t size, class T> class Vector {
} }
/** @brief Component-wise less than */ /** @brief Component-wise less than */
BoolVector<size> operator<(const Vector<size, T>& other) const; constexpr BoolVector<size> operator<(const Vector<size, T>& other) const;
/** @brief Component-wise less than or equal */ /** @brief Component-wise less than or equal */
BoolVector<size> operator<=(const Vector<size, T>& other) const; constexpr BoolVector<size> operator<=(const Vector<size, T>& other) const;
/** @brief Component-wise greater than or equal */ /** @brief Component-wise greater than or equal */
BoolVector<size> operator>=(const Vector<size, T>& other) const; constexpr BoolVector<size> operator>=(const Vector<size, T>& other) const;
/** @brief Component-wise greater than */ /** @brief Component-wise greater than */
BoolVector<size> operator>(const Vector<size, T>& other) const; constexpr BoolVector<size> operator>(const Vector<size, T>& other) const;
/** /**
* @brief Whether the vector is zero * @brief Whether the vector is zero
@ -236,7 +236,7 @@ template<std::size_t size, class T> class Vector {
* @f] * @f]
* @see @ref Vector2::perpendicular() * @see @ref Vector2::perpendicular()
*/ */
Vector<size, T> operator-() const; constexpr Vector<size, T> operator-() const;
/** /**
* @brief Add and assign vector * @brief Add and assign vector
@ -245,7 +245,7 @@ template<std::size_t size, class T> class Vector {
* \boldsymbol a_i = \boldsymbol a_i + \boldsymbol b_i * \boldsymbol a_i = \boldsymbol a_i + \boldsymbol b_i
* @f] * @f]
*/ */
Vector<size, T>& operator+=(const Vector<size, T>& other) { constexpr Vector<size, T>& operator+=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
_data[i] += other._data[i]; _data[i] += other._data[i];
@ -257,7 +257,7 @@ template<std::size_t size, class T> class Vector {
* *
* @see @ref operator+=(), @ref sum() * @see @ref operator+=(), @ref sum()
*/ */
Vector<size, T> operator+(const Vector<size, T>& other) const { constexpr Vector<size, T> operator+(const Vector<size, T>& other) const {
return Vector<size, T>(*this) += other; return Vector<size, T>(*this) += other;
} }
@ -268,7 +268,7 @@ template<std::size_t size, class T> class Vector {
* \boldsymbol a_i = \boldsymbol a_i - \boldsymbol b_i * \boldsymbol a_i = \boldsymbol a_i - \boldsymbol b_i
* @f] * @f]
*/ */
Vector<size, T>& operator-=(const Vector<size, T>& other) { constexpr Vector<size, T>& operator-=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
_data[i] -= other._data[i]; _data[i] -= other._data[i];
@ -280,7 +280,7 @@ template<std::size_t size, class T> class Vector {
* *
* @see @ref operator-=() * @see @ref operator-=()
*/ */
Vector<size, T> operator-(const Vector<size, T>& other) const { constexpr Vector<size, T> operator-(const Vector<size, T>& other) const {
return Vector<size, T>(*this) -= other; return Vector<size, T>(*this) -= other;
} }
@ -293,7 +293,7 @@ template<std::size_t size, class T> class Vector {
* @see @ref operator*=(const Vector<size, T>&), * @see @ref operator*=(const Vector<size, T>&),
* @ref operator*=(Vector<size, Integral>&, FloatingPoint) * @ref operator*=(Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T>& operator*=(T number) { constexpr Vector<size, T>& operator*=(T number) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
_data[i] *= number; _data[i] *= number;
@ -307,7 +307,7 @@ template<std::size_t size, class T> class Vector {
* @ref operator*=(T), operator*(T, const Vector<size, T>&), * @ref operator*=(T), operator*(T, const Vector<size, T>&),
* @ref operator*(const Vector<size, Integral>&, FloatingPoint) * @ref operator*(const Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T> operator*(T number) const { constexpr Vector<size, T> operator*(T number) const {
return Vector<size, T>(*this) *= number; return Vector<size, T>(*this) *= number;
} }
@ -320,7 +320,7 @@ template<std::size_t size, class T> class Vector {
* @see @ref operator/=(const Vector<size, T>&), * @see @ref operator/=(const Vector<size, T>&),
* @ref operator/=(Vector<size, Integral>&, FloatingPoint) * @ref operator/=(Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T>& operator/=(T number) { constexpr Vector<size, T>& operator/=(T number) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
_data[i] /= number; _data[i] /= number;
@ -334,7 +334,7 @@ template<std::size_t size, class T> class Vector {
* @ref operator/=(T), operator/(T, const Vector<size, T>&), * @ref operator/=(T), operator/(T, const Vector<size, T>&),
* @ref operator/(const Vector<size, Integral>&, FloatingPoint) * @ref operator/(const Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T> operator/(T number) const { constexpr Vector<size, T> operator/(T number) const {
return Vector<size, T>(*this) /= number; return Vector<size, T>(*this) /= number;
} }
@ -347,7 +347,7 @@ template<std::size_t size, class T> class Vector {
* @see @ref operator*=(T), * @see @ref operator*=(T),
* @ref operator*=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&) * @ref operator*=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/ */
Vector<size, T>& operator*=(const Vector<size, T>& other) { constexpr Vector<size, T>& operator*=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
_data[i] *= other._data[i]; _data[i] *= other._data[i];
@ -361,7 +361,7 @@ template<std::size_t size, class T> class Vector {
* @ref operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&), * @ref operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&),
* @ref product() * @ref product()
*/ */
Vector<size, T> operator*(const Vector<size, T>& other) const { constexpr Vector<size, T> operator*(const Vector<size, T>& other) const {
return Vector<size, T>(*this) *= other; return Vector<size, T>(*this) *= other;
} }
@ -374,7 +374,7 @@ template<std::size_t size, class T> class Vector {
* @see @ref operator/=(T), * @see @ref operator/=(T),
* @ref operator/=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&) * @ref operator/=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/ */
Vector<size, T>& operator/=(const Vector<size, T>& other) { constexpr Vector<size, T>& operator/=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
_data[i] /= other._data[i]; _data[i] /= other._data[i];
@ -387,7 +387,7 @@ template<std::size_t size, class T> class Vector {
* @see @ref operator/(T) const, @ref operator/=(const Vector<size, T>&), * @see @ref operator/(T) const, @ref operator/=(const Vector<size, T>&),
* @ref operator/(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&) * @ref operator/(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/ */
Vector<size, T> operator/(const Vector<size, T>& other) const { constexpr Vector<size, T> operator/(const Vector<size, T>& other) const {
return Vector<size, T>(*this) /= other; return Vector<size, T>(*this) /= other;
} }
@ -401,7 +401,7 @@ template<std::size_t size, class T> class Vector {
* @see @ref dot(const Vector<size, T>&, const Vector<size, T>&), * @see @ref dot(const Vector<size, T>&, const Vector<size, T>&),
* @ref isNormalized() * @ref isNormalized()
*/ */
T dot() const { return dot(*this, *this); } constexpr T dot() const { return dot(*this, *this); }
/** /**
* @brief %Vector length * @brief %Vector length
@ -479,14 +479,14 @@ template<std::size_t size, class T> class Vector {
* *
* @see @ref operator+() * @see @ref operator+()
*/ */
T sum() const; constexpr T sum() const;
/** /**
* @brief Product of values in the vector * @brief Product of values in the vector
* *
* @see @ref operator*(const Vector<size, T>&) const * @see @ref operator*(const Vector<size, T>&) const
*/ */
T product() const; constexpr T product() const;
/** /**
* @brief Minimal value in the vector * @brief Minimal value in the vector
@ -517,7 +517,7 @@ template<std::size_t size, class T> class Vector {
Same as @ref Vector::operator*(T) const. Same as @ref Vector::operator*(T) const.
*/ */
template<std::size_t size, class T> inline Vector<size, T> operator*( template<std::size_t size, class T> inline constexpr Vector<size, T> operator*(
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
T T
#else #else
@ -536,7 +536,7 @@ template<std::size_t size, class T> inline Vector<size, T> operator*(
@f] @f]
@see @ref Vector::operator/(T) const @see @ref Vector::operator/(T) const
*/ */
template<std::size_t size, class T> inline Vector<size, T> operator/( template<std::size_t size, class T> inline constexpr Vector<size, T> operator/(
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
T T
#else #else
@ -544,7 +544,7 @@ template<std::size_t size, class T> inline Vector<size, T> operator/(
#endif #endif
number, const Vector<size, T>& vector) number, const Vector<size, T>& vector)
{ {
Vector<size, T> out; Vector<size, T> out{};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out[i] = number/vector[i]; out[i] = number/vector[i];
@ -557,7 +557,7 @@ template<std::size_t size, class T> inline Vector<size, T> operator/(
The computation is done in-place. The computation is done in-place.
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -573,7 +573,7 @@ operator%=(Vector<size, Integral>& a, Integral b) {
/** @relates Vector /** @relates Vector
@brief Modulo of integral vector @brief Modulo of integral vector
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -589,7 +589,7 @@ operator%(const Vector<size, Integral>& a, Integral b) {
The computation is done in-place. The computation is done in-place.
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -605,7 +605,7 @@ operator%=(Vector<size, Integral>& a, const Vector<size, Integral>& b) {
/** @relates Vector /** @relates Vector
@brief Modulo of two integral vectors @brief Modulo of two integral vectors
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -619,14 +619,14 @@ operator%(const Vector<size, Integral>& a, const Vector<size, Integral>& b) {
/** @relates Vector /** @relates Vector
@brief Bitwise NOT of integral vector @brief Bitwise NOT of integral vector
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type
#endif #endif
operator~(const Vector<size, Integral>& vector) { operator~(const Vector<size, Integral>& vector) {
Vector<size, Integral> out; Vector<size, Integral> out{};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out[i] = ~vector[i]; out[i] = ~vector[i];
@ -639,7 +639,7 @@ operator~(const Vector<size, Integral>& vector) {
The computation is done in-place. The computation is done in-place.
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -655,7 +655,7 @@ operator&=(Vector<size, Integral>& a, const Vector<size, Integral>& b) {
/** @relates Vector /** @relates Vector
@brief Bitwise AND of two integral vectors @brief Bitwise AND of two integral vectors
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -671,7 +671,7 @@ operator&(const Vector<size, Integral>& a, const Vector<size, Integral>& b) {
The computation is done in-place. The computation is done in-place.
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -687,7 +687,7 @@ operator|=(Vector<size, Integral>& a, const Vector<size, Integral>& b) {
/** @relates Vector /** @relates Vector
@brief Bitwise OR of two integral vectors @brief Bitwise OR of two integral vectors
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -703,7 +703,7 @@ operator|(const Vector<size, Integral>& a, const Vector<size, Integral>& b) {
The computation is done in-place. The computation is done in-place.
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -719,7 +719,7 @@ operator^=(Vector<size, Integral>& a, const Vector<size, Integral>& b) {
/** @relates Vector /** @relates Vector
@brief Bitwise XOR of two integral vectors @brief Bitwise XOR of two integral vectors
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -735,7 +735,7 @@ operator^(const Vector<size, Integral>& a, const Vector<size, Integral>& b) {
The computation is done in-place. The computation is done in-place.
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -758,7 +758,7 @@ operator<<=(Vector<size, Integral>& vector,
/** @relates Vector /** @relates Vector
@brief Bitwise left shift of integral vector @brief Bitwise left shift of integral vector
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -781,7 +781,7 @@ operator<<(const Vector<size, Integral>& vector,
The computation is done in-place. The computation is done in-place.
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -803,7 +803,7 @@ operator>>=(Vector<size, Integral>& vector,
/** @relates Vector /** @relates Vector
@brief Bitwise left shift of integral vector @brief Bitwise left shift of integral vector
*/ */
template<std::size_t size, class Integral> inline template<std::size_t size, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -826,7 +826,7 @@ operator>>(const Vector<size, Integral>& vector,
Similar to @ref Vector::operator*=(T), except that the multiplication is done Similar to @ref Vector::operator*=(T), except that the multiplication is done
in floating-point. The computation is done in-place. in floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -845,7 +845,7 @@ operator*=(Vector<size, Integral>& vector, FloatingPoint number) {
Similar to @ref Vector::operator*(T) const, except that the multiplication is Similar to @ref Vector::operator*(T) const, except that the multiplication is
done in floating-point. done in floating-point.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -861,7 +861,7 @@ operator*(const Vector<size, Integral>& vector, FloatingPoint number) {
Same as @ref operator*(const Vector<size, Integral>&, FloatingPoint). Same as @ref operator*(const Vector<size, Integral>&, FloatingPoint).
*/ */
template<std::size_t size, class FloatingPoint, class Integral> inline template<std::size_t size, class FloatingPoint, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -877,7 +877,7 @@ operator*(FloatingPoint number, const Vector<size, Integral>& vector) {
Similar to @ref Vector::operator/=(T), except that the division is done in Similar to @ref Vector::operator/=(T), except that the division is done in
floating-point. The computation is done in-place. floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -896,7 +896,7 @@ operator/=(Vector<size, Integral>& vector, FloatingPoint number) {
Similar to @ref Vector::operator/(T) const, except that the division is done in Similar to @ref Vector::operator/(T) const, except that the division is done in
floating-point. floating-point.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -913,7 +913,7 @@ operator/(const Vector<size, Integral>& vector, FloatingPoint number) {
Similar to @ref Vector::operator*=(const Vector<size, T>&), except that the Similar to @ref Vector::operator*=(const Vector<size, T>&), except that the
multiplication is done in floating-point. The computation is done in-place. multiplication is done in floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -934,7 +934,7 @@ the multiplication is done in floating-point. The result is always integral
vector, convert both arguments to the same floating-point type to have vector, convert both arguments to the same floating-point type to have
floating-point result. floating-point result.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -950,7 +950,7 @@ operator*(const Vector<size, Integral>& a, const Vector<size, FloatingPoint>& b)
Same as @ref operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&). Same as @ref operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&).
*/ */
template<std::size_t size, class FloatingPoint, class Integral> inline template<std::size_t size, class FloatingPoint, class Integral> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -966,7 +966,7 @@ operator*(const Vector<size, FloatingPoint>& a, const Vector<size, Integral>& b)
Similar to @ref Vector::operator/=(const Vector<size, T>&), except that the Similar to @ref Vector::operator/=(const Vector<size, T>&), except that the
division is done in floating-point. The computation is done in-place. division is done in floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>& Vector<size, Integral>&
#else #else
@ -987,7 +987,7 @@ 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 convert both arguments to the same floating-point type to have floating-point
result. result.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline constexpr
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral> Vector<size, Integral>
#else #else
@ -1038,54 +1038,54 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
return *reinterpret_cast<const Type<T>*>(data); \ return *reinterpret_cast<const Type<T>*>(data); \
} \ } \
\ \
Type<T>& operator=(const Type<T>& other) { \ constexpr Type<T>& operator=(const Type<T>& other) { \
Math::Vector<size, T>::operator=(other); \ Math::Vector<size, T>::operator=(other); \
return *this; \ return *this; \
} \ } \
\ \
Type<T> operator-() const { \ constexpr Type<T> operator-() const { \
return Math::Vector<size, T>::operator-(); \ return Math::Vector<size, T>::operator-(); \
} \ } \
Type<T>& operator+=(const Math::Vector<size, T>& other) { \ constexpr Type<T>& operator+=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator+=(other); \ Math::Vector<size, T>::operator+=(other); \
return *this; \ return *this; \
} \ } \
Type<T> operator+(const Math::Vector<size, T>& other) const { \ constexpr Type<T> operator+(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::operator+(other); \ return Math::Vector<size, T>::operator+(other); \
} \ } \
Type<T>& operator-=(const Math::Vector<size, T>& other) { \ constexpr Type<T>& operator-=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator-=(other); \ Math::Vector<size, T>::operator-=(other); \
return *this; \ return *this; \
} \ } \
Type<T> operator-(const Math::Vector<size, T>& other) const { \ constexpr Type<T> operator-(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::operator-(other); \ return Math::Vector<size, T>::operator-(other); \
} \ } \
Type<T>& operator*=(T number) { \ constexpr Type<T>& operator*=(T number) { \
Math::Vector<size, T>::operator*=(number); \ Math::Vector<size, T>::operator*=(number); \
return *this; \ return *this; \
} \ } \
Type<T> operator*(T number) const { \ constexpr Type<T> operator*(T number) const { \
return Math::Vector<size, T>::operator*(number); \ return Math::Vector<size, T>::operator*(number); \
} \ } \
Type<T>& operator/=(T number) { \ constexpr Type<T>& operator/=(T number) { \
Math::Vector<size, T>::operator/=(number); \ Math::Vector<size, T>::operator/=(number); \
return *this; \ return *this; \
} \ } \
Type<T> operator/(T number) const { \ constexpr Type<T> operator/(T number) const { \
return Math::Vector<size, T>::operator/(number); \ return Math::Vector<size, T>::operator/(number); \
} \ } \
Type<T>& operator*=(const Math::Vector<size, T>& other) { \ constexpr Type<T>& operator*=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator*=(other); \ Math::Vector<size, T>::operator*=(other); \
return *this; \ return *this; \
} \ } \
Type<T> operator*(const Math::Vector<size, T>& other) const { \ constexpr Type<T> operator*(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::operator*(other); \ return Math::Vector<size, T>::operator*(other); \
} \ } \
Type<T>& operator/=(const Math::Vector<size, T>& other) { \ constexpr Type<T>& operator/=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator/=(other); \ Math::Vector<size, T>::operator/=(other); \
return *this; \ return *this; \
} \ } \
Type<T> operator/(const Math::Vector<size, T>& other) const { \ constexpr Type<T> operator/(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::operator/(other); \ return Math::Vector<size, T>::operator/(other); \
} \ } \
\ \
@ -1103,99 +1103,99 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
} }
#define MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(size, Type) \ #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) { \ template<class T> inline constexpr Type<T> operator*(typename std::common_type<T>::type number, const Type<T>& vector) { \
return number*static_cast<const Math::Vector<size, 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) { \ template<class T> inline constexpr Type<T> operator/(typename std::common_type<T>::type number, const Type<T>& vector) { \
return number/static_cast<const Math::Vector<size, T>&>(vector); \ return number/static_cast<const Math::Vector<size, T>&>(vector); \
} \ } \
\ \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator%=(Type<Integral>& a, Integral b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator%=(Type<Integral>& a, Integral b) { \
static_cast<Math::Vector<size, Integral>&>(a) %= b; \ static_cast<Math::Vector<size, Integral>&>(a) %= b; \
return a; \ return a; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator%(const Type<Integral>& a, Integral b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator%(const Type<Integral>& a, Integral b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) % b; \ return static_cast<const Math::Vector<size, Integral>&>(a) % b; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator%=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator%=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) %= b; \ static_cast<Math::Vector<size, Integral>&>(a) %= b; \
return a; \ return a; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator%(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator%(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) % b; \ return static_cast<const Math::Vector<size, Integral>&>(a) % b; \
} \ } \
\ \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator~(const Type<Integral>& vector) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator~(const Type<Integral>& vector) { \
return ~static_cast<const Math::Vector<size, Integral>&>(vector); \ return ~static_cast<const Math::Vector<size, Integral>&>(vector); \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator&=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator&=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) &= b; \ static_cast<Math::Vector<size, Integral>&>(a) &= b; \
return a; \ return a; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator&(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator&(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) & b; \ return static_cast<const Math::Vector<size, Integral>&>(a) & b; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator|=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator|=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) |= b; \ static_cast<Math::Vector<size, Integral>&>(a) |= b; \
return a; \ return a; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator|(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator|(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) | b; \ return static_cast<const Math::Vector<size, Integral>&>(a) | b; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator^=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator^=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) ^= b; \ static_cast<Math::Vector<size, Integral>&>(a) ^= b; \
return a; \ return a; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator^(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator^(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) ^ b; \ return static_cast<const Math::Vector<size, Integral>&>(a) ^ b; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator<<=(Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator<<=(Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
static_cast<Math::Vector<size, Integral>&>(vector) <<= shift; \ static_cast<Math::Vector<size, Integral>&>(vector) <<= shift; \
return vector; \ return vector; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator<<(const Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator<<(const Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
return static_cast<const Math::Vector<size, Integral>&>(vector) << shift; \ return static_cast<const Math::Vector<size, Integral>&>(vector) << shift; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator>>=(Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator>>=(Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
static_cast<Math::Vector<size, Integral>&>(vector) >>= shift; \ static_cast<Math::Vector<size, Integral>&>(vector) >>= shift; \
return vector; \ return vector; \
} \ } \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator>>(const Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \ template<class Integral> inline constexpr typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator>>(const Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
return static_cast<const Math::Vector<size, Integral>&>(vector) >> shift; \ return static_cast<const Math::Vector<size, Integral>&>(vector) >> shift; \
} \ } \
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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ static_cast<Math::Vector<size, Integral>&>(vector) *= number; \
return vector; \ 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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ 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) { \ template<class FloatingPoint, class Integral> inline constexpr 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); \ 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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ static_cast<Math::Vector<size, Integral>&>(vector) /= number; \
return vector; \ 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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ 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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ static_cast<Math::Vector<size, Integral>&>(a) *= b; \
return a; \ 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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ 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) { \ template<class FloatingPoint, class Integral> inline constexpr 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); \ 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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ static_cast<Math::Vector<size, Integral>&>(a) /= b; \
return a; \ 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) { \ template<class Integral, class FloatingPoint> inline constexpr 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; \ return static_cast<const Math::Vector<size, Integral>&>(a)/b; \
} }
#endif #endif
@ -1206,8 +1206,8 @@ template<std::size_t size, class T> inline Rad<T> Vector<size, T>::angle(const V
return Rad<T>(std::acos(dot(normalizedA, normalizedB))); return Rad<T>(std::acos(dot(normalizedA, normalizedB)));
} }
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator<(const Vector<size, T>& other) const { template<std::size_t size, class T> inline constexpr BoolVector<size> Vector<size, T>::operator<(const Vector<size, T>& other) const {
BoolVector<size> out; BoolVector<size> out{};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] < other._data[i]); out.set(i, _data[i] < other._data[i]);
@ -1215,8 +1215,8 @@ template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::ope
return out; return out;
} }
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator<=(const Vector<size, T>& other) const { template<std::size_t size, class T> inline constexpr BoolVector<size> Vector<size, T>::operator<=(const Vector<size, T>& other) const {
BoolVector<size> out; BoolVector<size> out{};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] <= other._data[i]); out.set(i, _data[i] <= other._data[i]);
@ -1224,8 +1224,8 @@ template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::ope
return out; return out;
} }
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator>=(const Vector<size, T>& other) const { template<std::size_t size, class T> inline constexpr BoolVector<size> Vector<size, T>::operator>=(const Vector<size, T>& other) const {
BoolVector<size> out; BoolVector<size> out{};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] >= other._data[i]); out.set(i, _data[i] >= other._data[i]);
@ -1233,8 +1233,8 @@ template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::ope
return out; return out;
} }
template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::operator>(const Vector<size, T>& other) const { template<std::size_t size, class T> inline constexpr BoolVector<size> Vector<size, T>::operator>(const Vector<size, T>& other) const {
BoolVector<size> out; BoolVector<size> out{};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out.set(i, _data[i] > other._data[i]); out.set(i, _data[i] > other._data[i]);
@ -1242,8 +1242,8 @@ template<std::size_t size, class T> inline BoolVector<size> Vector<size, T>::ope
return out; return out;
} }
template<std::size_t size, class T> inline Vector<size, T> Vector<size, T>::operator-() const { template<std::size_t size, class T> inline constexpr Vector<size, T> Vector<size, T>::operator-() const {
Vector<size, T> out; Vector<size, T> out{};
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
out._data[i] = -_data[i]; out._data[i] = -_data[i];
@ -1257,7 +1257,7 @@ template<std::size_t size, class T> inline Vector<size, T> Vector<size, T>::proj
return line*dot(*this, line); return line*dot(*this, line);
} }
template<std::size_t size, class T> inline T Vector<size, T>::sum() const { template<std::size_t size, class T> inline constexpr T Vector<size, T>::sum() const {
T out(_data[0]); T out(_data[0]);
for(std::size_t i = 1; i != size; ++i) for(std::size_t i = 1; i != size; ++i)
@ -1266,7 +1266,7 @@ template<std::size_t size, class T> inline T Vector<size, T>::sum() const {
return out; return out;
} }
template<std::size_t size, class T> inline T Vector<size, T>::product() const { template<std::size_t size, class T> inline constexpr T Vector<size, T>::product() const {
T out(_data[0]); T out(_data[0]);
for(std::size_t i = 1; i != size; ++i) for(std::size_t i = 1; i != size; ++i)

Loading…
Cancel
Save