diff --git a/src/Math/Algorithms/Svd.h b/src/Math/Algorithms/Svd.h index 406a6d38b..3d4aef076 100644 --- a/src/Math/Algorithms/Svd.h +++ b/src/Math/Algorithms/Svd.h @@ -49,9 +49,9 @@ template T pythagoras(T a, T b) { } template constexpr T smallestDelta(); -template<> inline constexpr Float smallestDelta() { return 1.0e-32; } +template<> constexpr Float smallestDelta() { return 1.0e-32; } #ifndef MAGNUM_TARGET_GLES -template<> inline constexpr Double smallestDelta() { return 1.0e-64; } +template<> constexpr Double smallestDelta() { return 1.0e-64; } #endif } diff --git a/src/Math/Angle.h b/src/Math/Angle.h index 9b7b66000..9fa9a4617 100644 --- a/src/Math/Angle.h +++ b/src/Math/Angle.h @@ -124,16 +124,16 @@ std::sin(Float(Rad(angleInDegrees)); // required explicit conversion hint template class Deg: public Unit { public: /** @brief Default constructor */ - inline constexpr /*implicit*/ Deg() {} + constexpr /*implicit*/ Deg() {} /** @brief Explicit constructor from unitless type */ - inline constexpr explicit Deg(T value): Unit(value) {} + constexpr explicit Deg(T value): Unit(value) {} /** @brief Copy constructor */ - inline constexpr /*implicit*/ Deg(Unit value): Unit(value) {} + constexpr /*implicit*/ Deg(Unit value): Unit(value) {} /** @brief Construct from another underlying type */ - template inline constexpr explicit Deg(Unit value): Unit(value) {} + template constexpr explicit Deg(Unit value): Unit(value) {} /** * @brief Construct degrees from radians @@ -143,7 +143,7 @@ template class Deg: public Unit { * deg = 180 \frac {rad} \pi * @f] */ - inline constexpr /*implicit*/ Deg(Unit value); + constexpr /*implicit*/ Deg(Unit value); }; #ifndef CORRADE_GCC46_COMPATIBILITY @@ -160,7 +160,7 @@ Double cosine = Math::cos(1.047_rad); // cosine = 0.5 @note Not available on GCC < 4.7. Use Deg::Deg(T) instead. @requires_gl Only single-precision types are available in OpenGL ES. */ -inline constexpr Deg operator "" _deg(long double value) { return Deg(value); } +constexpr Deg operator "" _deg(long double value) { return Deg(value); } #endif /** @relates Deg @@ -175,7 +175,7 @@ Float tangent = Math::tan(1.047_radf); // tangent = 1.732f @note Not available on GCC < 4.7. Use Deg::Deg(T) instead. @requires_gl Only single-precision types are available in OpenGL ES. */ -inline constexpr Deg operator "" _degf(long double value) { return Deg(value); } +constexpr Deg operator "" _degf(long double value) { return Deg(value); } #endif /** @@ -187,16 +187,16 @@ See Deg for more information. template class Rad: public Unit { public: /** @brief Default constructor */ - inline constexpr /*implicit*/ Rad() {} + constexpr /*implicit*/ Rad() {} /** @brief Construct from unitless type */ - inline constexpr explicit Rad(T value): Unit(value) {} + constexpr explicit Rad(T value): Unit(value) {} /** @brief Copy constructor */ - inline constexpr /*implicit*/ Rad(Unit value): Unit(value) {} + constexpr /*implicit*/ Rad(Unit value): Unit(value) {} /** @brief Construct from another underlying type */ - template inline constexpr explicit Rad(Unit value): Unit(value) {} + template constexpr explicit Rad(Unit value): Unit(value) {} /** * @brief Construct radians from degrees @@ -206,7 +206,7 @@ template class Rad: public Unit { * rad = deg \frac \pi 180 * @f] */ - inline constexpr /*implicit*/ Rad(Unit value); + constexpr /*implicit*/ Rad(Unit value); }; #ifndef CORRADE_GCC46_COMPATIBILITY @@ -218,7 +218,7 @@ See operator""_rad() for more information. @see Magnum::operator""_rad(), operator""_radf(), operator""_deg() @note Not available on GCC < 4.7. Use Rad::Rad(T) instead. */ -inline constexpr Rad operator "" _rad(long double value) { return Rad(value); } +constexpr Rad operator "" _rad(long double value) { return Rad(value); } #endif /** @relates Rad @@ -228,11 +228,11 @@ See operator""_degf() for more information. @see Magnum::operator""_radf(), operator""_rad(), operator""_degf() @note Not available on GCC < 4.7. Use Rad::Rad(T) instead. */ -inline constexpr Rad operator "" _radf(long double value) { return Rad(value); } +constexpr Rad operator "" _radf(long double value) { return Rad(value); } #endif -template inline constexpr Deg::Deg(Unit value): Unit(T(180)*T(value)/Math::Constants::pi()) {} -template inline constexpr Rad::Rad(Unit value): Unit(T(value)*Math::Constants::pi()/T(180)) {} +template constexpr Deg::Deg(Unit value): Unit(T(180)*T(value)/Math::Constants::pi()) {} +template constexpr Rad::Rad(Unit value): Unit(T(value)*Math::Constants::pi()/T(180)) {} /** @debugoperator{Magnum::Math::Rad} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Unit& value) { diff --git a/src/Math/BoolVector.h b/src/Math/BoolVector.h index ce81ba946..9866ee114 100644 --- a/src/Math/BoolVector.h +++ b/src/Math/BoolVector.h @@ -49,7 +49,7 @@ namespace Implementation { }; #endif - template inline constexpr T repeat(T value, std::size_t) { return value; } + template constexpr T repeat(T value, std::size_t) { return value; } } /** @@ -69,7 +69,7 @@ template class BoolVector { static const std::size_t DataSize = (size-1)/8+1; /**< @brief %Vector storage size */ /** @brief Construct zero-filled boolean vector */ - inline constexpr BoolVector(): _data() {} + constexpr BoolVector(): _data() {} /** * @brief Construct boolean vector from segment values @@ -77,9 +77,9 @@ template class BoolVector { * @param next Values for next Bbit segments */ #ifdef DOXYGEN_GENERATING_OUTPUT - template inline constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next); + template constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next); #else - template::type> inline constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next): _data{first, UnsignedByte(next)...} {} + template::type> constexpr /*implicit*/ BoolVector(UnsignedByte first, T... next): _data{first, UnsignedByte(next)...} {} #endif /** @brief Construct boolean vector with one value for all fields */ @@ -87,19 +87,19 @@ template class BoolVector { inline explicit BoolVector(T value); #else #ifndef CORRADE_GCC46_COMPATIBILITY - template::value && size != 1, bool>::type> inline constexpr explicit BoolVector(T value): BoolVector(typename Implementation::GenerateSequence::Type(), value ? FullSegmentMask : 0) {} + template::value && size != 1, bool>::type> constexpr explicit BoolVector(T value): BoolVector(typename Implementation::GenerateSequence::Type(), value ? FullSegmentMask : 0) {} #else - template::value && size != 1, bool>::type> inline explicit BoolVector(T value) { + template::value && size != 1, bool>::type> explicit BoolVector(T value) { *this = BoolVector(typename Implementation::GenerateSequence::Type(), value ? FullSegmentMask : 0); } #endif #endif /** @brief Copy constructor */ - inline constexpr BoolVector(const BoolVector&) = default; + constexpr BoolVector(const BoolVector&) = default; /** @brief Copy assignment */ - inline BoolVector& operator=(const BoolVector&) = default; + BoolVector& operator=(const BoolVector&) = default; /** * @brief Raw data @@ -107,84 +107,46 @@ template class BoolVector { * * @see operator[](), set() */ - inline UnsignedByte* data() { return _data; } - inline constexpr const UnsignedByte* data() const { return _data; } /**< @overload */ + UnsignedByte* data() { return _data; } + constexpr const UnsignedByte* data() const { return _data; } /**< @overload */ /** @brief Bit at given position */ - inline constexpr bool operator[](std::size_t i) const { + constexpr bool operator[](std::size_t i) const { return (_data[i/8] >> i%8) & 0x01; } /** @brief Set bit at given position */ - inline BoolVector& set(std::size_t i, bool value) { + BoolVector& set(std::size_t i, bool value) { _data[i/8] |= ((value & 0x01) << i%8); return *this; } /** @brief Equality comparison */ - inline bool operator==(const BoolVector& other) const { - for(std::size_t i = 0; i != size/8; ++i) - if(_data[i] != other._data[i]) return false; - - /* Check last segment */ - if(size%8 && (_data[DataSize-1] & LastSegmentMask) != (other._data[DataSize-1] & LastSegmentMask)) - return false; - - return true; - } + bool operator==(const BoolVector& other) const; /** @brief Non-equality comparison */ - inline bool operator!=(const BoolVector& other) const { + bool operator!=(const BoolVector& other) const { return !operator==(other); } /** @brief Whether all bits are set */ - bool all() const { - /* Check all full segments */ - for(std::size_t i = 0; i != size/8; ++i) - if(_data[i] != FullSegmentMask) return false; - - /* Check last segment */ - if(size%8 && (_data[DataSize-1] & LastSegmentMask) != LastSegmentMask) - return false; - - return true; - } + bool all() const; /** @brief Whether no bits are set */ - bool none() const { - /* Check all full segments */ - for(std::size_t i = 0; i != size/8; ++i) - if(_data[i]) return false; - - /* Check last segment */ - if(size%8 && (_data[DataSize-1] & LastSegmentMask)) - return false; - - return true; - } + bool none() const; /** @brief Whether any bit is set */ - inline bool any() const { - return !none(); - } + bool any() const { return !none(); } /** @brief Bitwise inversion */ - inline BoolVector operator~() const { - BoolVector out; - - for(std::size_t i = 0; i != DataSize; ++i) - out._data[i] = ~_data[i]; - - return out; - } + BoolVector operator~() const; /** * @brief Bitwise AND and assign * * The computation is done in-place. */ - inline BoolVector& operator&=(const BoolVector& other) { + BoolVector& operator&=(const BoolVector& other) { for(std::size_t i = 0; i != DataSize; ++i) _data[i] &= other._data[i]; @@ -196,7 +158,7 @@ template class BoolVector { * * @see operator&=() */ - inline BoolVector operator&(const BoolVector& other) const { + BoolVector operator&(const BoolVector& other) const { return BoolVector(*this) &= other; } @@ -205,7 +167,7 @@ template class BoolVector { * * The computation is done in-place. */ - inline BoolVector& operator|=(const BoolVector& other) { + BoolVector& operator|=(const BoolVector& other) { for(std::size_t i = 0; i != DataSize; ++i) _data[i] |= other._data[i]; @@ -217,7 +179,7 @@ template class BoolVector { * * @see operator|=() */ - inline BoolVector operator|(const BoolVector& other) const { + BoolVector operator|(const BoolVector& other) const { return BoolVector(*this) |= other; } @@ -226,7 +188,7 @@ template class BoolVector { * * The computation is done in-place. */ - inline BoolVector& operator^=(const BoolVector& other) { + BoolVector& operator^=(const BoolVector& other) { for(std::size_t i = 0; i != DataSize; ++i) _data[i] ^= other._data[i]; @@ -238,7 +200,7 @@ template class BoolVector { * * @see operator^=() */ - inline BoolVector operator^(const BoolVector& other) const { + BoolVector operator^(const BoolVector& other) const { return BoolVector(*this) ^= other; } @@ -249,7 +211,7 @@ template class BoolVector { }; /* Implementation for Vector::Vector(U) */ - template inline constexpr explicit BoolVector(Implementation::Sequence, UnsignedByte value): _data{Implementation::repeat(value, sequence)...} {} + template constexpr explicit BoolVector(Implementation::Sequence, UnsignedByte value): _data{Implementation::repeat(value, sequence)...} {} UnsignedByte _data[(size-1)/8+1]; }; @@ -267,6 +229,50 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility:: return debug; } +template inline bool BoolVector::operator==(const BoolVector< size >& other) const { + for(std::size_t i = 0; i != size/8; ++i) + if(_data[i] != other._data[i]) return false; + + /* Check last segment */ + if(size%8 && (_data[DataSize-1] & LastSegmentMask) != (other._data[DataSize-1] & LastSegmentMask)) + return false; + + return true; +} + +template inline bool BoolVector::all() const { + /* Check all full segments */ + for(std::size_t i = 0; i != size/8; ++i) + if(_data[i] != FullSegmentMask) return false; + + /* Check last segment */ + if(size%8 && (_data[DataSize-1] & LastSegmentMask) != LastSegmentMask) + return false; + + return true; +} + +template inline bool BoolVector::none() const { + /* Check all full segments */ + for(std::size_t i = 0; i != size/8; ++i) + if(_data[i]) return false; + + /* Check last segment */ + if(size%8 && (_data[DataSize-1] & LastSegmentMask)) + return false; + + return true; +} + +template inline BoolVector BoolVector::operator~() const { + BoolVector out; + + for(std::size_t i = 0; i != DataSize; ++i) + out._data[i] = ~_data[i]; + + return out; +} + }} #endif diff --git a/src/Math/Complex.h b/src/Math/Complex.h index 8b102ea4b..8e54f03b7 100644 --- a/src/Math/Complex.h +++ b/src/Math/Complex.h @@ -40,7 +40,7 @@ namespace Magnum { namespace Math { namespace Implementation { /* No assertions fired, for internal use. Not private member because used from outside the class. */ - template inline static Complex complexFromMatrix(const Matrix<2, T>& matrix) { + template constexpr static Complex complexFromMatrix(const Matrix<2, T>& matrix) { return {matrix[0][0], matrix[0][1]}; } } @@ -64,7 +64,7 @@ template class Complex { * @f] * @see dot() const */ - inline static T dot(const Complex& a, const Complex& b) { + static T dot(const Complex& a, const Complex& b) { return a._real*b._real + a._imaginary*b._imaginary; } @@ -76,7 +76,7 @@ template class Complex { * @f] * @see isNormalized(), Quaternion::angle(), Vector::angle() */ - inline static Rad angle(const Complex& normalizedA, const Complex& normalizedB) { + static Rad angle(const Complex& normalizedA, const Complex& normalizedB) { CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), "Math::Complex::angle(): complex numbers must be normalized", Rad(std::numeric_limits::quiet_NaN())); return Rad(std::acos(normalizedA._real*normalizedB._real + normalizedA._imaginary*normalizedB._imaginary)); @@ -91,7 +91,7 @@ template class Complex { * @f] * @see angle(), Matrix3::rotation(), Quaternion::rotation() */ - inline static Complex rotation(Rad angle) { + static Complex rotation(Rad angle) { return {std::cos(T(angle)), std::sin(T(angle))}; } @@ -101,7 +101,7 @@ template class Complex { * Expects that the matrix is orthogonal (i.e. pure rotation). * @see toMatrix(), DualComplex::fromMatrix(), Matrix::isOrthogonal() */ - inline static Complex fromMatrix(const Matrix<2, T>& matrix) { + static Complex fromMatrix(const Matrix<2, T>& matrix) { CORRADE_ASSERT(matrix.isOrthogonal(), "Math::Complex::fromMatrix(): the matrix is not orthogonal", {}); return Implementation::complexFromMatrix(matrix); @@ -114,7 +114,7 @@ template class Complex { * c = 1 + i0 * @f] */ - inline constexpr /*implicit*/ Complex(): _real(T(1)), _imaginary(T(0)) {} + constexpr /*implicit*/ Complex(): _real(T(1)), _imaginary(T(0)) {} /** * @brief Construct complex number from real and imaginary part @@ -123,7 +123,7 @@ template class Complex { * c = a + ib * @f] */ - inline constexpr /*implicit*/ Complex(T real, T imaginary): _real(real), _imaginary(imaginary) {} + constexpr /*implicit*/ Complex(T real, T imaginary): _real(real), _imaginary(imaginary) {} /** * @brief Construct complex number from vector @@ -133,16 +133,16 @@ template class Complex { * @f] * @see operator Vector2(), transformVector() */ - inline constexpr explicit Complex(const Vector2& vector): _real(vector.x()), _imaginary(vector.y()) {} + constexpr explicit Complex(const Vector2& vector): _real(vector.x()), _imaginary(vector.y()) {} /** @brief Equality comparison */ - inline bool operator==(const Complex& other) const { + bool operator==(const Complex& other) const { return TypeTraits::equals(_real, other._real) && TypeTraits::equals(_imaginary, other._imaginary); } /** @brief Non-equality comparison */ - inline bool operator!=(const Complex& other) const { + bool operator!=(const Complex& other) const { return !operator==(other); } @@ -154,15 +154,15 @@ template class Complex { * @f] * @see dot(), normalized() */ - inline bool isNormalized() const { + bool isNormalized() const { return Implementation::isNormalizedSquared(dot()); } /** @brief Real part */ - inline constexpr T real() const { return _real; } + constexpr T real() const { return _real; } /** @brief Imaginary part */ - inline constexpr T imaginary() const { return _imaginary; } + constexpr T imaginary() const { return _imaginary; } /** * @brief Convert complex number to vector @@ -171,7 +171,7 @@ template class Complex { * \boldsymbol v = \begin{pmatrix} a \\ b \end{pmatrix} * @f] */ - inline constexpr explicit operator Vector2() const { + constexpr explicit operator Vector2() const { return {_real, _imaginary}; } @@ -183,7 +183,7 @@ template class Complex { * @f] * @see rotation() */ - inline Rad angle() const { + Rad angle() const { return Rad(std::atan2(_imaginary, _real)); } @@ -211,7 +211,7 @@ template class Complex { * c_0 + c_1 = (a_0 + a_1) + i(b_0 + b_1) * @f] */ - inline Complex& operator+=(const Complex& other) { + Complex& operator+=(const Complex& other) { _real += other._real; _imaginary += other._imaginary; return *this; @@ -222,7 +222,7 @@ template class Complex { * * @see operator+=() */ - inline Complex operator+(const Complex& other) const { + Complex operator+(const Complex& other) const { return Complex(*this) += other; } @@ -233,7 +233,7 @@ template class Complex { * -c = -a -ib * @f] */ - inline Complex operator-() const { + Complex operator-() const { return {-_real, -_imaginary}; } @@ -244,7 +244,7 @@ template class Complex { * c_0 - c_1 = (a_0 - a_1) + i(b_0 - b_1) * @f] */ - inline Complex& operator-=(const Complex& other) { + Complex& operator-=(const Complex& other) { _real -= other._real; _imaginary -= other._imaginary; return *this; @@ -255,7 +255,7 @@ template class Complex { * * @see operator-=() */ - inline Complex operator-(const Complex& other) const { + Complex operator-(const Complex& other) const { return Complex(*this) -= other; } @@ -266,7 +266,7 @@ template class Complex { * c \cdot t = ta + itb * @f] */ - inline Complex& operator*=(T scalar) { + Complex& operator*=(T scalar) { _real *= scalar; _imaginary *= scalar; return *this; @@ -277,7 +277,7 @@ template class Complex { * * @see operator*=(T) */ - inline Complex operator*(T scalar) const { + Complex operator*(T scalar) const { return Complex(*this) *= scalar; } @@ -288,7 +288,7 @@ template class Complex { * \frac c t = \frac a t + i \frac b t * @f] */ - inline Complex& operator/=(T scalar) { + Complex& operator/=(T scalar) { _real /= scalar; _imaginary /= scalar; return *this; @@ -299,7 +299,7 @@ template class Complex { * * @see operator/=(T) */ - inline Complex operator/(T scalar) const { + Complex operator/(T scalar) const { return Complex(*this) /= scalar; } @@ -310,7 +310,7 @@ template class Complex { * c_0 c_1 = (a_0 + ib_0)(a_1 + ib_1) = (a_0 a_1 - b_0 b_1) + i(a_1 b_0 + a_0 b_1) * @f] */ - inline Complex operator*(const Complex& other) const { + Complex operator*(const Complex& other) const { return {_real*other._real - _imaginary*other._imaginary, _imaginary*other._real + _real*other._imaginary}; } @@ -324,7 +324,7 @@ template class Complex { * @f] * @see dot(const Complex&, const Complex&), isNormalized() */ - inline T dot() const { + T dot() const { return dot(*this, *this); } @@ -337,7 +337,7 @@ template class Complex { * @f] * @see isNormalized() */ - inline T length() const { + T length() const { /** @todo Remove when NaCl's newlib has this fixed */ #ifndef CORRADE_TARGET_NACL_NEWLIB return std::hypot(_real, _imaginary); @@ -351,7 +351,7 @@ template class Complex { * * @see isNormalized() */ - inline Complex normalized() const { + Complex normalized() const { return (*this)/length(); } @@ -362,7 +362,7 @@ template class Complex { * c^* = a - ib * @f] */ - inline Complex conjugated() const { + Complex conjugated() const { return {_real, -_imaginary}; } @@ -374,7 +374,7 @@ template class Complex { * c^{-1} = \frac{c^*}{|c|^2} = \frac{c^*}{c \cdot c} * @f] */ - inline Complex inverted() const { + Complex inverted() const { return conjugated()/dot(); } @@ -387,7 +387,7 @@ template class Complex { * @f] * @see isNormalized(), inverted() */ - inline Complex invertedNormalized() const { + Complex invertedNormalized() const { CORRADE_ASSERT(isNormalized(), "Math::Complex::invertedNormalized(): complex number must be normalized", Complex(std::numeric_limits::quiet_NaN(), {})); @@ -402,7 +402,7 @@ template class Complex { * @f] * @see Complex(const Vector2&), operator Vector2(), Matrix3::transformVector() */ - inline Vector2 transformVector(const Vector2& vector) const { + Vector2 transformVector(const Vector2& vector) const { return Vector2((*this)*Complex(vector)); } diff --git a/src/Math/Constants.h b/src/Math/Constants.h index d4c232677..a2bc5a7b6 100644 --- a/src/Math/Constants.h +++ b/src/Math/Constants.h @@ -47,10 +47,10 @@ template struct Constants { * * @see Deg, Rad */ - static inline constexpr T pi(); + static constexpr T pi(); - static inline constexpr T sqrt2(); /**< @brief Square root of 2 */ - static inline constexpr T sqrt3(); /**< @brief Square root of 3 */ + static constexpr T sqrt2(); /**< @brief Square root of 2 */ + static constexpr T sqrt3(); /**< @brief Square root of 3 */ #endif }; @@ -59,17 +59,17 @@ template struct Constants { template<> struct Constants { Constants() = delete; - static inline constexpr Double pi() { return 3.141592653589793; } - static inline constexpr Double sqrt2() { return 1.414213562373095; } - static inline constexpr Double sqrt3() { return 1.732050807568877; } + static constexpr Double pi() { return 3.141592653589793; } + static constexpr Double sqrt2() { return 1.414213562373095; } + static constexpr Double sqrt3() { return 1.732050807568877; } }; #endif template<> struct Constants { Constants() = delete; - static inline constexpr Float pi() { return 3.141592654f; } - static inline constexpr Float sqrt2() { return 1.414213562f; } - static inline constexpr Float sqrt3() { return 1.732050808f; } + static constexpr Float pi() { return 3.141592654f; } + static constexpr Float sqrt2() { return 1.414213562f; } + static constexpr Float sqrt3() { return 1.732050808f; } }; #endif diff --git a/src/Math/Dual.h b/src/Math/Dual.h index 630a6f736..5d5e4948a 100644 --- a/src/Math/Dual.h +++ b/src/Math/Dual.h @@ -50,7 +50,7 @@ template class Dual { * * Both parts are default-constructed. */ - inline constexpr /*implicit*/ Dual(): _real(), _dual() {} + constexpr /*implicit*/ Dual(): _real(), _dual() {} /** * @brief Construct dual number from real and dual part @@ -59,24 +59,24 @@ template class Dual { * \hat a = a_0 + \epsilon a_\epsilon * @f] */ - inline constexpr /*implicit*/ Dual(const T& real, const T& dual = T()): _real(real), _dual(dual) {} + constexpr /*implicit*/ Dual(const T& real, const T& dual = T()): _real(real), _dual(dual) {} /** @brief Equality comparison */ - inline bool operator==(const Dual& other) const { + bool operator==(const Dual& other) const { return TypeTraits::equals(_real, other._real) && TypeTraits::equals(_dual, other._dual); } /** @brief Non-equality comparison */ - inline bool operator!=(const Dual& other) const { + bool operator!=(const Dual& other) const { return !operator==(other); } /** @brief Real part */ - inline constexpr T real() const { return _real; } + constexpr T real() const { return _real; } /** @brief %Dual part */ - inline constexpr T dual() const { return _dual; } + constexpr T dual() const { return _dual; } /** * @brief Add and assign dual number @@ -85,7 +85,7 @@ template class Dual { * \hat a + \hat b = a_0 + b_0 + \epsilon (a_\epsilon + b_\epsilon) * @f] */ - inline Dual& operator+=(const Dual& other) { + Dual& operator+=(const Dual& other) { _real += other._real; _dual += other._dual; return *this; @@ -96,7 +96,7 @@ template class Dual { * * @see operator+=() */ - inline Dual operator+(const Dual& other) const { + Dual operator+(const Dual& other) const { return Dual(*this)+=other; } @@ -107,7 +107,7 @@ template class Dual { * -\hat a = -a_0 - \epsilon a_\epsilon * @f] */ - inline Dual operator-() const { + Dual operator-() const { return {-_real, -_dual}; } @@ -118,7 +118,7 @@ template class Dual { * \hat a - \hat b = a_0 - b_0 + \epsilon (a_\epsilon - b_\epsilon) * @f] */ - inline Dual& operator-=(const Dual& other) { + Dual& operator-=(const Dual& other) { _real -= other._real; _dual -= other._dual; return *this; @@ -129,7 +129,7 @@ template class Dual { * * @see operator-=() */ - inline Dual operator-(const Dual& other) const { + Dual operator-(const Dual& other) const { return Dual(*this)-=other; } @@ -140,7 +140,7 @@ template class Dual { * \hat a \hat b = a_0 b_0 + \epsilon (a_0 b_\epsilon + a_\epsilon b_0) * @f] */ - template inline Dual operator*(const Dual& other) const { + template Dual operator*(const Dual& other) const { return {_real*other._real, _real*other._dual + _dual*other._real}; } @@ -151,7 +151,7 @@ template class Dual { * \frac{\hat a}{\hat b} = \frac{a_0}{b_0} + \epsilon \frac{a_\epsilon b_0 - a_0 b_\epsilon}{b_0^2} * @f] */ - template inline Dual operator/(const Dual& other) const { + template Dual operator/(const Dual& other) const { return {_real/other._real, (_dual*other._real - _real*other._dual)/(other._real*other._real)}; } @@ -162,7 +162,7 @@ template class Dual { * \overline{\hat a} = a_0 - \epsilon a_\epsilon * @f] */ - inline Dual conjugated() const { + Dual conjugated() const { return {_real, -_dual}; } @@ -172,27 +172,27 @@ template class Dual { #ifndef DOXYGEN_GENERATING_OUTPUT #define MAGNUM_DUAL_SUBCLASS_IMPLEMENTATION(Type, Underlying) \ - inline Type operator-() const { \ + Type operator-() const { \ return Dual>::operator-(); \ } \ - inline Type& operator+=(const Dual>& other) { \ + Type& operator+=(const Dual>& other) { \ Dual>::operator+=(other); \ return *this; \ } \ - inline Type operator+(const Dual>& other) const { \ + Type operator+(const Dual>& other) const { \ return Dual>::operator+(other); \ } \ - inline Type& operator-=(const Dual>& other) { \ + Type& operator-=(const Dual>& other) { \ Dual>::operator-=(other); \ return *this; \ } \ - inline Type operator-(const Dual>& other) const { \ + Type operator-(const Dual>& other) const { \ return Dual>::operator-(other); \ } \ - template inline Type operator*(const Dual& other) const { \ + template Type operator*(const Dual& other) const { \ return Dual>::operator*(other); \ } \ - template inline Type operator/(const Dual& other) const { \ + template Type operator/(const Dual& other) const { \ return Dual>::operator/(other); \ } #endif diff --git a/src/Math/DualComplex.h b/src/Math/DualComplex.h index 648f9f6bc..024563d2f 100644 --- a/src/Math/DualComplex.h +++ b/src/Math/DualComplex.h @@ -58,7 +58,7 @@ template class DualComplex: public Dual> { * @see angle(), Complex::rotation(), Matrix3::rotation(), * DualQuaternion::rotation() */ - inline static DualComplex rotation(Rad angle) { + static DualComplex rotation(Rad angle) { return {Complex::rotation(angle), {{}, {}}}; } @@ -72,7 +72,7 @@ template class DualComplex: public Dual> { * @see translation() const, Matrix3::translation(const Vector2&), * DualQuaternion::translation(), Vector2::xAxis(), Vector2::yAxis() */ - inline static DualComplex translation(const Vector2& vector) { + static DualComplex translation(const Vector2& vector) { return {{}, {vector.x(), vector.y()}}; } @@ -83,7 +83,7 @@ template class DualComplex: public Dual> { * @see toMatrix(), Complex::fromMatrix(), * Matrix3::isRigidTransformation() */ - inline static DualComplex fromMatrix(const Matrix3& matrix) { + static DualComplex fromMatrix(const Matrix3& matrix) { CORRADE_ASSERT(matrix.isRigidTransformation(), "Math::DualComplex::fromMatrix(): the matrix doesn't represent rigid transformation", {}); return {Implementation::complexFromMatrix(matrix.rotationScaling()), Complex(matrix.translation())}; @@ -98,9 +98,9 @@ template class DualComplex: public Dual> { * @todoc Remove workaround when Doxygen is predictable */ #ifdef DOXYGEN_GENERATING_OUTPUT - inline constexpr /*implicit*/ DualComplex(); + constexpr /*implicit*/ DualComplex(); #else - inline constexpr /*implicit*/ DualComplex(): Dual>({}, {T(0), T(0)}) {} + constexpr /*implicit*/ DualComplex(): Dual>({}, {T(0), T(0)}) {} #endif /** @@ -110,7 +110,7 @@ template class DualComplex: public Dual> { * \hat c = c_0 + \epsilon c_\epsilon * @f] */ - inline constexpr /*implicit*/ DualComplex(const Complex& real, const Complex& dual = Complex(T(0), T(0))): Dual>(real, dual) {} + constexpr /*implicit*/ DualComplex(const Complex& real, const Complex& dual = Complex(T(0), T(0))): Dual>(real, dual) {} /** * @brief Construct dual complex number from vector @@ -121,9 +121,9 @@ template class DualComplex: public Dual> { * @todoc Remove workaround when Doxygen is predictable */ #ifdef DOXYGEN_GENERATING_OUTPUT - inline constexpr explicit DualComplex(const Vector2& vector); + constexpr explicit DualComplex(const Vector2& vector); #else - inline constexpr explicit DualComplex(const Vector2& vector): Dual>({}, Complex(vector)) {} + constexpr explicit DualComplex(const Vector2& vector): Dual>({}, Complex(vector)) {} #endif /** @@ -134,7 +134,7 @@ template class DualComplex: public Dual> { * @f] * @see Complex::dot(), normalized() */ - inline bool isNormalized() const { + bool isNormalized() const { return Implementation::isNormalizedSquared(lengthSquared()); } @@ -143,7 +143,7 @@ template class DualComplex: public Dual> { * * @see Complex::angle() */ - inline constexpr Complex rotation() const { + constexpr Complex rotation() const { return this->real(); } @@ -155,7 +155,7 @@ template class DualComplex: public Dual> { * @f] * @see translation(const Vector2&) */ - inline Vector2 translation() const { + Vector2 translation() const { return Vector2(this->dual()); } @@ -164,7 +164,7 @@ template class DualComplex: public Dual> { * * @see fromMatrix(), Complex::toMatrix() */ - inline Matrix3 toMatrix() const { + Matrix3 toMatrix() const { return Matrix3::from(this->real().toMatrix(), translation()); } @@ -176,7 +176,7 @@ template class DualComplex: public Dual> { * @f] * @todo can this be done similarly to dual quaternions? */ - inline DualComplex operator*(const DualComplex& other) const { + DualComplex operator*(const DualComplex& other) const { return {this->real()*other.real(), this->real()*other.dual() + this->dual()}; } @@ -188,7 +188,7 @@ template class DualComplex: public Dual> { * @f] * @see dualConjugated(), conjugated(), Complex::conjugated() */ - inline DualComplex complexConjugated() const { + DualComplex complexConjugated() const { return {this->real().conjugated(), this->dual().conjugated()}; } @@ -200,7 +200,7 @@ template class DualComplex: public Dual> { * @f] * @see complexConjugated(), conjugated(), Dual::conjugated() */ - inline DualComplex dualConjugated() const { + DualComplex dualConjugated() const { return Dual>::conjugated(); } @@ -213,7 +213,7 @@ template class DualComplex: public Dual> { * @see complexConjugated(), dualConjugated(), Complex::conjugated(), * Dual::conjugated() */ - inline DualComplex conjugated() const { + DualComplex conjugated() const { return {this->real().conjugated(), {-this->dual().real(), this->dual().imaginary()}}; } @@ -226,7 +226,7 @@ template class DualComplex: public Dual> { * @f] * @todo Can this be done similarly to dual quaternins? */ - inline T lengthSquared() const { + T lengthSquared() const { return this->real().dot(); } @@ -239,7 +239,7 @@ template class DualComplex: public Dual> { * @f] * @todo can this be done similarly to dual quaternions? */ - inline T length() const { + T length() const { return this->real().length(); } @@ -252,7 +252,7 @@ template class DualComplex: public Dual> { * @see isNormalized() * @todo can this be done similarly to dual quaternions? */ - inline DualComplex normalized() const { + DualComplex normalized() const { return {this->real()/length(), this->dual()}; } @@ -265,7 +265,7 @@ template class DualComplex: public Dual> { * @f] * @todo can this be done similarly to dual quaternions? */ - inline DualComplex inverted() const { + DualComplex inverted() const { return DualComplex(this->real().inverted(), {{}, {}})*DualComplex({}, -this->dual()); } @@ -278,7 +278,7 @@ template class DualComplex: public Dual> { * @see isNormalized(), inverted() * @todo can this be done similarly to dual quaternions? */ - inline DualComplex invertedNormalized() const { + DualComplex invertedNormalized() const { return DualComplex(this->real().invertedNormalized(), {{}, {}})*DualComplex({}, -this->dual()); } @@ -292,35 +292,35 @@ template class DualComplex: public Dual> { * @see DualComplex(const Vector2&), dual(), Matrix3::transformPoint(), * Complex::transformVector(), DualQuaternion::transformPoint() */ - inline Vector2 transformPoint(const Vector2& vector) const { + Vector2 transformPoint(const Vector2& vector) const { return Vector2(((*this)*DualComplex(vector)).dual()); } /* Verbatim copy of DUAL_SUBCLASS_IMPLEMENTATION(), as we need to hide Dual's operator*() and operator/() */ #ifndef DOXYGEN_GENERATING_OUTPUT - inline DualComplex operator-() const { + DualComplex operator-() const { return Dual>::operator-(); } - inline DualComplex& operator+=(const Dual>& other) { + DualComplex& operator+=(const Dual>& other) { Dual>::operator+=(other); return *this; } - inline DualComplex operator+(const Dual>& other) const { + DualComplex operator+(const Dual>& other) const { return Dual>::operator+(other); } - inline DualComplex& operator-=(const Dual>& other) { + DualComplex& operator-=(const Dual>& other) { Dual>::operator-=(other); return *this; } - inline DualComplex operator-(const Dual>& other) const { + DualComplex operator-(const Dual>& other) const { return Dual>::operator-(other); } #endif private: /* Used by Dual operators and dualConjugated() */ - inline constexpr DualComplex(const Dual>& other): Dual>(other) {} + constexpr DualComplex(const Dual>& other): Dual>(other) {} /* Just to be sure nobody uses this, as it wouldn't probably work with our operator*() */ diff --git a/src/Math/DualQuaternion.h b/src/Math/DualQuaternion.h index 8d4837aac..6411c9fa7 100644 --- a/src/Math/DualQuaternion.h +++ b/src/Math/DualQuaternion.h @@ -58,7 +58,7 @@ template class DualQuaternion: public Dual> { * DualComplex::rotation(), Vector3::xAxis(), Vector3::yAxis(), * Vector3::zAxis(), Vector::isNormalized() */ - inline static DualQuaternion rotation(Rad angle, const Vector3& normalizedAxis) { + static DualQuaternion rotation(Rad angle, const Vector3& normalizedAxis) { return {Quaternion::rotation(angle, normalizedAxis), {{}, T(0)}}; } @@ -75,7 +75,7 @@ template class DualQuaternion: public Dual> { * DualComplex::translation(), Vector3::xAxis(), Vector3::yAxis(), * Vector3::zAxis() */ - inline static DualQuaternion translation(const Vector3& vector) { + static DualQuaternion translation(const Vector3& vector) { return {{}, {vector/T(2), T(0)}}; } @@ -86,7 +86,7 @@ template class DualQuaternion: public Dual> { * @see toMatrix(), Quaternion::fromMatrix(), * Matrix4::isRigidTransformation() */ - inline static DualQuaternion fromMatrix(const Matrix4& matrix) { + static DualQuaternion fromMatrix(const Matrix4& matrix) { CORRADE_ASSERT(matrix.isRigidTransformation(), "Math::DualQuaternion::fromMatrix(): the matrix doesn't represent rigid transformation", {}); @@ -103,9 +103,9 @@ template class DualQuaternion: public Dual> { * @todoc Remove workaround when Doxygen is predictable */ #ifdef DOXYGEN_GENERATING_OUTPUT - inline constexpr /*implicit*/ DualQuaternion(); + constexpr /*implicit*/ DualQuaternion(); #else - inline constexpr /*implicit*/ DualQuaternion(): Dual>({}, {{}, T(0)}) {} + constexpr /*implicit*/ DualQuaternion(): Dual>({}, {{}, T(0)}) {} #endif /** @@ -115,7 +115,7 @@ template class DualQuaternion: public Dual> { * \hat q = q_0 + \epsilon q_\epsilon * @f] */ - inline constexpr /*implicit*/ DualQuaternion(const Quaternion& real, const Quaternion& dual = Quaternion({}, T(0))): Dual>(real, dual) {} + constexpr /*implicit*/ DualQuaternion(const Quaternion& real, const Quaternion& dual = Quaternion({}, T(0))): Dual>(real, dual) {} /** * @brief Construct dual quaternion from vector @@ -127,9 +127,9 @@ template class DualQuaternion: public Dual> { * @todoc Remove workaround when Doxygen is predictable */ #ifdef DOXYGEN_GENERATING_OUTPUT - inline constexpr explicit DualQuaternion(const Vector3& vector); + constexpr explicit DualQuaternion(const Vector3& vector); #else - inline constexpr explicit DualQuaternion(const Vector3& vector): Dual>({}, {vector, T(0)}) {} + constexpr explicit DualQuaternion(const Vector3& vector): Dual>({}, {vector, T(0)}) {} #endif /** @@ -140,7 +140,7 @@ template class DualQuaternion: public Dual> { * @f] * @see lengthSquared(), normalized() */ - inline bool isNormalized() const { + bool isNormalized() const { /* Comparing dual part classically, as comparing sqrt() of it would lead to overly strict precision */ Dual a = lengthSquared(); @@ -153,7 +153,7 @@ template class DualQuaternion: public Dual> { * * @see Quaternion::angle(), Quaternion::axis() */ - inline constexpr Quaternion rotation() const { + constexpr Quaternion rotation() const { return this->real(); } @@ -165,7 +165,7 @@ template class DualQuaternion: public Dual> { * @f] * @see translation(const Vector3&) */ - inline Vector3 translation() const { + Vector3 translation() const { return (this->dual()*this->real().conjugated()).vector()*T(2); } @@ -186,7 +186,7 @@ template class DualQuaternion: public Dual> { * @f] * @see dualConjugated(), conjugated(), Quaternion::conjugated() */ - inline DualQuaternion quaternionConjugated() const { + DualQuaternion quaternionConjugated() const { return {this->real().conjugated(), this->dual().conjugated()}; } @@ -198,7 +198,7 @@ template class DualQuaternion: public Dual> { * @f] * @see quaternionConjugated(), conjugated(), Dual::conjugated() */ - inline DualQuaternion dualConjugated() const { + DualQuaternion dualConjugated() const { return Dual>::conjugated(); } @@ -211,7 +211,7 @@ template class DualQuaternion: public Dual> { * @see quaternionConjugated(), dualConjugated(), Quaternion::conjugated(), * Dual::conjugated() */ - inline DualQuaternion conjugated() const { + DualQuaternion conjugated() const { return {this->real().conjugated(), {this->dual().vector(), -this->dual().scalar()}}; } @@ -223,7 +223,7 @@ template class DualQuaternion: public Dual> { * |\hat q|^2 = \sqrt{\hat q^* \hat q}^2 = q_0 \cdot q_0 + \epsilon 2 (q_0 \cdot q_\epsilon) * @f] */ - inline Dual lengthSquared() const { + Dual lengthSquared() const { return {this->real().dot(), T(2)*Quaternion::dot(this->real(), this->dual())}; } @@ -235,7 +235,7 @@ template class DualQuaternion: public Dual> { * |\hat q| = \sqrt{\hat q^* \hat q} = |q_0| + \epsilon \frac{q_0 \cdot q_\epsilon}{|q_0|} * @f] */ - inline Dual length() const { + Dual length() const { return Math::sqrt(lengthSquared()); } @@ -244,7 +244,7 @@ template class DualQuaternion: public Dual> { * * @see isNormalized() */ - inline DualQuaternion normalized() const { + DualQuaternion normalized() const { return (*this)/length(); } @@ -256,7 +256,7 @@ template class DualQuaternion: public Dual> { * \hat q^{-1} = \frac{\hat q^*}{|\hat q|^2} * @f] */ - inline DualQuaternion inverted() const { + DualQuaternion inverted() const { return quaternionConjugated()/lengthSquared(); } @@ -269,7 +269,7 @@ template class DualQuaternion: public Dual> { * @f] * @see isNormalized(), inverted() */ - inline DualQuaternion invertedNormalized() const { + DualQuaternion invertedNormalized() const { CORRADE_ASSERT(isNormalized(), "Math::DualQuaternion::invertedNormalized(): dual quaternion must be normalized", {}); return quaternionConjugated(); @@ -285,7 +285,7 @@ template class DualQuaternion: public Dual> { * @see DualQuaternion(const Vector3&), dual(), Matrix4::transformPoint(), * Quaternion::transformVector(), DualComplex::transformPoint() */ - inline Vector3 transformPoint(const Vector3& vector) const { + Vector3 transformPoint(const Vector3& vector) const { return ((*this)*DualQuaternion(vector)*inverted().dualConjugated()).dual().vector(); } @@ -300,7 +300,7 @@ template class DualQuaternion: public Dual> { * Matrix4::transformPoint(), Quaternion::transformVectorNormalized(), * DualComplex::transformPointNormalized() */ - inline Vector3 transformPointNormalized(const Vector3& vector) const { + Vector3 transformPointNormalized(const Vector3& vector) const { CORRADE_ASSERT(isNormalized(), "Math::DualQuaternion::transformPointNormalized(): dual quaternion must be normalized", Vector3(std::numeric_limits::quiet_NaN())); @@ -311,7 +311,7 @@ template class DualQuaternion: public Dual> { private: /* Used by Dual operators and dualConjugated() */ - inline constexpr DualQuaternion(const Dual>& other): Dual>(other) {} + constexpr DualQuaternion(const Dual>& other): Dual>(other) {} }; /** @debugoperator{Magnum::Math::DualQuaternion} */ diff --git a/src/Math/Functions.h b/src/Math/Functions.h index ed944ca58..bb1947d38 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -42,14 +42,14 @@ namespace Implementation { template struct Pow { Pow() = delete; - template inline constexpr static T pow(T base) { + template constexpr static T pow(T base) { return base*Pow::pow(base); } }; template<> struct Pow<0> { Pow() = delete; - template inline constexpr static T pow(T) { return 1; } + template constexpr static T pow(T) { return 1; } }; } @@ -58,7 +58,7 @@ namespace Implementation { * * Returns integral power of base to the exponent. */ -template inline constexpr T pow(T base) { +template constexpr T pow(T base) { return Implementation::Pow::pow(base); } diff --git a/src/Math/Geometry/Distance.h b/src/Math/Geometry/Distance.h index 6816df743..c6e20b57a 100644 --- a/src/Math/Geometry/Distance.h +++ b/src/Math/Geometry/Distance.h @@ -51,7 +51,7 @@ class Distance { * Source: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html * @see linePointSquared(const Vector2&, const Vector2&, const Vector2&) */ - template inline static T linePoint(const Vector2& a, const Vector2& b, const Vector2& point) { + template static T linePoint(const Vector2& a, const Vector2& b, const Vector2& point) { const Vector2 bMinusA = b - a; return std::abs(Vector2::cross(bMinusA, a - point))/bMinusA.length(); } @@ -66,7 +66,7 @@ class Distance { * for comparing distance with other values, because it doesn't * compute the square root. */ - template inline static T linePointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { + template static T linePointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { const Vector2 bMinusA = b - a; return Math::pow<2>(Vector2::cross(bMinusA, a - point))/bMinusA.dot(); } @@ -85,7 +85,7 @@ class Distance { * Source: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html * @see linePointSquared(const Vector3&, const Vector3&, const Vector3&) */ - template inline static T linePoint(const Vector3& a, const Vector3& b, const Vector3& point) { + template static T linePoint(const Vector3& a, const Vector3& b, const Vector3& point) { return std::sqrt(linePointSquared(a, b, point)); } @@ -126,25 +126,7 @@ class Distance { * * @see lineSegmentPointSquared() */ - template inline static T lineSegmentPoint(const Vector2& a, const Vector2& b, const Vector2& point) { - const Vector2 pointMinusA = point - a; - const Vector2 pointMinusB = point - b; - const Vector2 bMinusA = b - a; - const T pointDistanceA = pointMinusA.dot(); - const T pointDistanceB = pointMinusB.dot(); - const T bDistanceA = bMinusA.dot(); - - /* Point is before A */ - if(pointDistanceB > bDistanceA + pointDistanceA) - return std::sqrt(pointDistanceA); - - /* Point is after B */ - if(pointDistanceA > bDistanceA + pointDistanceB) - return std::sqrt(pointDistanceB); - - /* Between A and B */ - return std::abs(Vector2::cross(bMinusA, -pointMinusA))/std::sqrt(bDistanceA); - } + template static T lineSegmentPoint(const Vector2& a, const Vector2& b, const Vector2& point); /** * @brief %Distance of point from line segment in 2D, squared @@ -152,25 +134,7 @@ class Distance { * More efficient than lineSegmentPoint() for comparing distance with * other values, because it doesn't compute the square root. */ - template static T lineSegmentPointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { - const Vector2 pointMinusA = point - a; - const Vector2 pointMinusB = point - b; - const Vector2 bMinusA = b - a; - const T pointDistanceA = pointMinusA.dot(); - const T pointDistanceB = pointMinusB.dot(); - const T bDistanceA = bMinusA.dot(); - - /* Point is before A */ - if(pointDistanceB > bDistanceA + pointDistanceA) - return pointDistanceA; - - /* Point is after B */ - if(pointDistanceA > bDistanceA + pointDistanceB) - return pointDistanceB; - - /* Between A and B */ - return Math::pow<2>(Vector2::cross(bMinusA, -pointMinusA))/bDistanceA; - } + template static T lineSegmentPointSquared(const Vector2& a, const Vector2& b, const Vector2& point); /** * @brief %Dístance of point from line segment in 3D @@ -183,7 +147,7 @@ class Distance { * * @see lineSegmentPointSquared(const Vector3&, const Vector3&, const Vector3&) */ - template inline static T lineSegmentPoint(const Vector3& a, const Vector3& b, const Vector3& point) { + template static T lineSegmentPoint(const Vector3& a, const Vector3& b, const Vector3& point) { return std::sqrt(lineSegmentPointSquared(a, b, point)); } @@ -193,26 +157,68 @@ class Distance { * More efficient than lineSegmentPoint(const Vector3&, const Vector3&, const Vector3&) for comparing distance with * other values, because it doesn't compute the square root. */ - template static T lineSegmentPointSquared(const Vector3& a, const Vector3& b, const Vector3& point) { - const Vector3 pointMinusA = point - a; - const Vector3 pointMinusB = point - b; - const T pointDistanceA = pointMinusA.dot(); - const T pointDistanceB = pointMinusB.dot(); - const T bDistanceA = (b - a).dot(); - - /* Point is before A */ - if(pointDistanceB > bDistanceA + pointDistanceA) - return pointDistanceA; - - /* Point is after B */ - if(pointDistanceA > bDistanceA + pointDistanceB) - return pointDistanceB; - - /* Between A and B */ - return Vector3::cross(pointMinusA, pointMinusB).dot()/bDistanceA; - } + template static T lineSegmentPointSquared(const Vector3& a, const Vector3& b, const Vector3& point); }; +template T Distance::lineSegmentPoint(const Vector2& a, const Vector2& b, const Vector2& point) { + const Vector2 pointMinusA = point - a; + const Vector2 pointMinusB = point - b; + const Vector2 bMinusA = b - a; + const T pointDistanceA = pointMinusA.dot(); + const T pointDistanceB = pointMinusB.dot(); + const T bDistanceA = bMinusA.dot(); + + /* Point is before A */ + if(pointDistanceB > bDistanceA + pointDistanceA) + return std::sqrt(pointDistanceA); + + /* Point is after B */ + if(pointDistanceA > bDistanceA + pointDistanceB) + return std::sqrt(pointDistanceB); + + /* Between A and B */ + return std::abs(Vector2::cross(bMinusA, -pointMinusA))/std::sqrt(bDistanceA); +} + +template T Distance::lineSegmentPointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { + const Vector2 pointMinusA = point - a; + const Vector2 pointMinusB = point - b; + const Vector2 bMinusA = b - a; + const T pointDistanceA = pointMinusA.dot(); + const T pointDistanceB = pointMinusB.dot(); + const T bDistanceA = bMinusA.dot(); + + /* Point is before A */ + if(pointDistanceB > bDistanceA + pointDistanceA) + return pointDistanceA; + + /* Point is after B */ + if(pointDistanceA > bDistanceA + pointDistanceB) + return pointDistanceB; + + /* Between A and B */ + return Math::pow<2>(Vector2::cross(bMinusA, -pointMinusA))/bDistanceA; +} + +template T Distance::lineSegmentPointSquared(const Vector3& a, const Vector3& b, const Vector3& point) { + const Vector3 pointMinusA = point - a; + const Vector3 pointMinusB = point - b; + const T pointDistanceA = pointMinusA.dot(); + const T pointDistanceB = pointMinusB.dot(); + const T bDistanceA = (b - a).dot(); + + /* Point is before A */ + if(pointDistanceB > bDistanceA + pointDistanceA) + return pointDistanceA; + + /* Point is after B */ + if(pointDistanceA > bDistanceA + pointDistanceB) + return pointDistanceB; + + /* Between A and B */ + return Vector3::cross(pointMinusA, pointMinusB).dot()/bDistanceA; +} + }}} #endif diff --git a/src/Math/Geometry/Rectangle.h b/src/Math/Geometry/Rectangle.h index 6211bd8b7..ad8ef7b20 100644 --- a/src/Math/Geometry/Rectangle.h +++ b/src/Math/Geometry/Rectangle.h @@ -51,7 +51,7 @@ template class Rectangle { * @param bottomLeft Bottom left rectangle corner * @param size %Rectangle size */ - inline static Rectangle fromSize(const Vector2& bottomLeft, const Vector2& size) { + static Rectangle fromSize(const Vector2& bottomLeft, const Vector2& size) { return {bottomLeft, bottomLeft+size}; } @@ -60,10 +60,10 @@ template class Rectangle { * * Construct zero-area rectangle positioned at origin. */ - inline constexpr Rectangle() {} + constexpr Rectangle() {} /** @brief Construct rectangle from two corners */ - inline constexpr Rectangle(const Vector2& bottomLeft, const Vector2& topRight): _bottomLeft(bottomLeft), _topRight(topRight) {} + constexpr Rectangle(const Vector2& bottomLeft, const Vector2& topRight): _bottomLeft(bottomLeft), _topRight(topRight) {} /** * @brief Construct rectangle from another of different type @@ -75,64 +75,62 @@ template class Rectangle { * Rectangle integral(floatingPoint); // {{1, 2}, {-15, 7}} * @endcode */ - template inline constexpr explicit Rectangle(const Rectangle& other): _bottomLeft(other._bottomLeft), _topRight(other._topRight) {} + template constexpr explicit Rectangle(const Rectangle& other): _bottomLeft(other._bottomLeft), _topRight(other._topRight) {} /** @brief Copy constructor */ - inline constexpr Rectangle(const Rectangle&) = default; + constexpr Rectangle(const Rectangle&) = default; /** @brief Assignment operator */ - inline Rectangle& operator=(const Rectangle&) = default; + Rectangle& operator=(const Rectangle&) = default; /** @brief Equality operator */ - inline constexpr bool operator==(const Rectangle& other) const { + constexpr bool operator==(const Rectangle& other) const { return _bottomLeft == other._bottomLeft && _topRight == other._topRight; } /** @brief Non-equality operator */ - inline constexpr bool operator!=(const Rectangle& other) const { + constexpr bool operator!=(const Rectangle& other) const { return !operator==(other); } /** @brief Bottom left corner */ - inline Vector2& bottomLeft() { return _bottomLeft; } - inline constexpr Vector2 bottomLeft() const { return _bottomLeft; } /**< @overload */ + Vector2& bottomLeft() { return _bottomLeft; } + constexpr Vector2 bottomLeft() const { return _bottomLeft; } /**< @overload */ /** @brief Bottom right corner */ - inline constexpr Vector2 bottomRight() const { return {_topRight.x(), _bottomLeft.y()}; } /**< @overload */ + constexpr Vector2 bottomRight() const { return {_topRight.x(), _bottomLeft.y()}; } /**< @overload */ /** @brief Top left corner */ - inline constexpr Vector2 topLeft() const { return {_bottomLeft.x(), _topRight.y()}; } /**< @overload */ + constexpr Vector2 topLeft() const { return {_bottomLeft.x(), _topRight.y()}; } /**< @overload */ /** @brief Top right corner */ - inline Vector2& topRight() { return _topRight; } - inline constexpr Vector2 topRight() const { return _topRight; } /**< @overload */ + Vector2& topRight() { return _topRight; } + constexpr Vector2 topRight() const { return _topRight; } /**< @overload */ /** @brief Bottom edge */ - inline T& bottom() { return _bottomLeft.y(); } - inline constexpr T bottom() const { return _bottomLeft.y(); } /**< @overload */ + T& bottom() { return _bottomLeft.y(); } + constexpr T bottom() const { return _bottomLeft.y(); } /**< @overload */ /** @brief Top edge */ - inline T& top() { return _topRight.y(); } - inline constexpr T top() const { return _topRight.y(); } /**< @overload */ + T& top() { return _topRight.y(); } + constexpr T top() const { return _topRight.y(); } /**< @overload */ /** @brief Left edge */ - inline T& left() { return _bottomLeft.x(); } - inline constexpr T left() const { return _bottomLeft.x(); } /**< @overload */ + T& left() { return _bottomLeft.x(); } + constexpr T left() const { return _bottomLeft.x(); } /**< @overload */ /** @brief Right edge */ - inline T& right() { return _topRight.x(); } - inline constexpr T right() const { return _topRight.x(); } /**< @overload */ + T& right() { return _topRight.x(); } + constexpr T right() const { return _topRight.x(); } /**< @overload */ /** @brief %Rectangle size */ - inline constexpr Vector2 size() const { - return _topRight-_bottomLeft; - } + constexpr Vector2 size() const { return _topRight-_bottomLeft; } /** @brief %Rectangle width */ - inline constexpr T width() const { return _topRight.x() - _bottomLeft.x(); } + constexpr T width() const { return _topRight.x() - _bottomLeft.x(); } /** @brief %Rectangle height */ - inline constexpr T height() const { return _topRight.y() - _bottomLeft.y(); } + constexpr T height() const { return _topRight.y() - _bottomLeft.y(); } private: Vector2 _bottomLeft; diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index adcbba862..e5db427ea 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -58,7 +58,7 @@ template class Matrix: public RectangularMatrix class Matrix: public RectangularMatrix class Matrix: public RectangularMatrix inline constexpr /*implicit*/ Matrix(const Vector& first, const U&... next): RectangularMatrix(first, next...) {} + template constexpr /*implicit*/ Matrix(const Vector& first, const U&... next): RectangularMatrix(first, next...) {} /** * @brief Construct matrix from another of different type @@ -95,13 +95,13 @@ template class Matrix: public RectangularMatrix inline constexpr explicit Matrix(const RectangularMatrix& other): RectangularMatrix(other) {} + template constexpr explicit Matrix(const RectangularMatrix& other): RectangularMatrix(other) {} /** @brief Construct matrix from external representation */ - template::from(std::declval()))> inline constexpr explicit Matrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} + template::from(std::declval()))> constexpr explicit Matrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} /** @brief Copy constructor */ - inline constexpr Matrix(const RectangularMatrix& other): RectangularMatrix(other) {} + constexpr Matrix(const RectangularMatrix& other): RectangularMatrix(other) {} /** * @brief Whether the matrix is orthogonal @@ -112,19 +112,7 @@ template class Matrix: public RectangularMatrix::dot((*this)[i], (*this)[j]) > TypeTraits::epsilon()) - return false; - - return true; - } + bool isOrthogonal() const; /** * @brief Trace of the matrix @@ -133,21 +121,10 @@ template class Matrix: public RectangularMatrixdiagonal().sum(); - } + T trace() const { return this->diagonal().sum(); } /** @brief %Matrix without given column and row */ - Matrix ij(std::size_t skipCol, std::size_t skipRow) const { - Matrix out(Matrix::Zero); - - for(std::size_t col = 0; col != size-1; ++col) - for(std::size_t row = 0; row != size-1; ++row) - out[col][row] = (*this)[col + (col >= skipCol)] - [row + (row >= skipRow)]; - - return out; - } + Matrix ij(std::size_t skipCol, std::size_t skipRow) const; /** * @brief Determinant @@ -160,7 +137,7 @@ template class Matrix: public RectangularMatrix()(*this); } + T determinant() const { return Implementation::MatrixDeterminant()(*this); } /** * @brief Inverted matrix @@ -171,17 +148,7 @@ template class Matrix: public RectangularMatrix inverted() const { - Matrix out(Zero); - - T _determinant = determinant(); - - for(std::size_t col = 0; col != size; ++col) - for(std::size_t row = 0; row != size; ++row) - out[col][row] = (((row+col) & 1) ? -1 : 1)*ij(row, col).determinant()/_determinant; - - return out; - } + Matrix inverted() const; /** * @brief Inverted orthogonal matrix @@ -192,7 +159,7 @@ template class Matrix: public RectangularMatrix invertedOrthogonal() const { + Matrix invertedOrthogonal() const { CORRADE_ASSERT(isOrthogonal(), "Math::Matrix::invertedOrthogonal(): the matrix is not orthogonal", {}); return this->transposed(); @@ -200,13 +167,13 @@ template class Matrix: public RectangularMatrix operator*(const Matrix& other) const { + Matrix operator*(const Matrix& other) const { return RectangularMatrix::operator*(other); } - template inline RectangularMatrix operator*(const RectangularMatrix& other) const { + template RectangularMatrix operator*(const RectangularMatrix& other) const { return RectangularMatrix::operator*(other); } - inline Vector operator*(const Vector& other) const { + Vector operator*(const Vector& other) const { return RectangularMatrix::operator*(other); } MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(size, size, Matrix) @@ -232,29 +199,29 @@ template inline Corrade::Utility::Debug operator<<(Co #ifndef DOXYGEN_GENERATING_OUTPUT #define MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Type, VectorType, size) \ - inline VectorType& operator[](std::size_t col) { \ + VectorType& operator[](std::size_t col) { \ return static_cast&>(Matrix::operator[](col)); \ } \ - inline constexpr const VectorType operator[](std::size_t col) const { \ + constexpr const VectorType operator[](std::size_t col) const { \ return VectorType(Matrix::operator[](col)); \ } \ - inline VectorType row(std::size_t row) const { \ + VectorType row(std::size_t row) const { \ return VectorType(Matrix::row(row)); \ } \ \ - inline Type operator*(const Matrix& other) const { \ + Type operator*(const Matrix& other) const { \ return Matrix::operator*(other); \ } \ - template inline RectangularMatrix operator*(const RectangularMatrix& other) const { \ + template RectangularMatrix operator*(const RectangularMatrix& other) const { \ return Matrix::operator*(other); \ } \ - inline VectorType operator*(const Vector& other) const { \ + VectorType operator*(const Vector& other) const { \ return Matrix::operator*(other); \ } \ \ - inline Type transposed() const { return Matrix::transposed(); } \ - inline Type inverted() const { return Matrix::inverted(); } \ - inline Type invertedOrthogonal() const { \ + Type transposed() const { return Matrix::transposed(); } \ + Type inverted() const { return Matrix::inverted(); } \ + Type invertedOrthogonal() const { \ return Matrix::invertedOrthogonal(); \ } @@ -273,26 +240,28 @@ namespace Implementation { template class MatrixDeterminant { public: - T operator()(const Matrix& m) { - T out(0); + T operator()(const Matrix& m); +}; - for(std::size_t col = 0; col != size; ++col) - out += ((col & 1) ? -1 : 1)*m[col][0]*m.ij(col, 0).determinant(); +template T MatrixDeterminant::operator()(const Matrix& m) { + T out(0); - return out; - } -}; + for(std::size_t col = 0; col != size; ++col) + out += ((col & 1) ? -1 : 1)*m[col][0]*m.ij(col, 0).determinant(); + + return out; +} template class MatrixDeterminant<2, T> { public: - inline constexpr T operator()(const Matrix<2, T>& m) { + constexpr T operator()(const Matrix<2, T>& m) { return m[0][0]*m[1][1] - m[1][0]*m[0][1]; } }; template class MatrixDeterminant<1, T> { public: - inline constexpr T operator()(const Matrix<1, T>& m) { + constexpr T operator()(const Matrix<1, T>& m) { return m[0][0]; } }; @@ -300,6 +269,43 @@ template class MatrixDeterminant<1, T> { } #endif +template bool Matrix::isOrthogonal() const { + /* Normality */ + for(std::size_t i = 0; i != size; ++i) + if(!(*this)[i].isNormalized()) return false; + + /* Orthogonality */ + for(std::size_t i = 0; i != size-1; ++i) + for(std::size_t j = i+1; j != size; ++j) + if(Vector::dot((*this)[i], (*this)[j]) > TypeTraits::epsilon()) + return false; + + return true; +} + +template Matrix Matrix::ij(const std::size_t skipCol, const std::size_t skipRow) const { + Matrix out(Matrix::Zero); + + for(std::size_t col = 0; col != size-1; ++col) + for(std::size_t row = 0; row != size-1; ++row) + out[col][row] = (*this)[col + (col >= skipCol)] + [row + (row >= skipRow)]; + + return out; +} + +template Matrix Matrix::inverted() const { + Matrix out(Zero); + + const T _determinant = determinant(); + + for(std::size_t col = 0; col != size; ++col) + for(std::size_t row = 0; row != size; ++row) + out[col][row] = (((row+col) & 1) ? -1 : 1)*ij(row, col).determinant()/_determinant; + + return out; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 1a4c0c6c0..39413b874 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -53,11 +53,7 @@ template class Matrix3: public Matrix<3, T> { * Matrix4::translation(const Vector3&), Vector2::xAxis(), * Vector2::yAxis() */ - inline constexpr static Matrix3 translation(const Vector2& vector) { - return {{ T(1), T(0), T(0)}, - { T(0), T(1), T(0)}, - {vector.x(), vector.y(), T(1)}}; - } + constexpr static Matrix3 translation(const Vector2& vector); /** * @brief 2D scaling matrix @@ -66,11 +62,7 @@ template class Matrix3: public Matrix<3, T> { * @see rotationScaling() const, Matrix4::scaling(const Vector3&), * Vector2::xScale(), Vector2::yScale() */ - inline constexpr static Matrix3 scaling(const Vector2& vector) { - return {{vector.x(), T(0), T(0)}, - { T(0), vector.y(), T(0)}, - { T(0), T(0), T(1)}}; - } + constexpr static Matrix3 scaling(const Vector2& vector); /** * @brief 2D rotation matrix @@ -79,14 +71,7 @@ template class Matrix3: public Matrix<3, T> { * @see rotation() const, Complex::rotation(), DualComplex::rotation(), * Matrix4::rotation(Rad, const Vector3&) */ - static Matrix3 rotation(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); - - return {{ cosine, sine, T(0)}, - { -sine, cosine, T(0)}, - { T(0), T(0), T(1)}}; - } + static Matrix3 rotation(Rad angle); /** * @brief 2D reflection matrix @@ -120,14 +105,14 @@ template class Matrix3: public Matrix<3, T> { * * @see rotationScaling() const, translation() const */ - inline constexpr static Matrix3 from(const Matrix<2, T>& rotationScaling, const Vector2& translation) { + constexpr static Matrix3 from(const Matrix<2, T>& rotationScaling, const Vector2& translation) { return {{rotationScaling[0], T(0)}, {rotationScaling[1], T(0)}, { translation, T(1)}}; } /** @copydoc Matrix::Matrix(ZeroType) */ - inline constexpr explicit Matrix3(typename Matrix<3, T>::ZeroType): Matrix<3, T>(Matrix<3, T>::Zero) {} + constexpr explicit Matrix3(typename Matrix<3, T>::ZeroType): Matrix<3, T>(Matrix<3, T>::Zero) {} /** * @brief Default constructor @@ -137,23 +122,19 @@ template class Matrix3: public Matrix<3, T> { * @p value allows you to specify value on diagonal. * @todo Use constexpr implementation in Matrix, when done */ - inline constexpr /*implicit*/ Matrix3(typename Matrix<3, T>::IdentityType = (Matrix<3, T>::Identity), T value = T(1)): Matrix<3, T>( - Vector<3, T>(value, T(0), T(0)), - Vector<3, T>( T(0), value, T(0)), - Vector<3, T>( T(0), T(0), value) - ) {} + constexpr /*implicit*/ Matrix3(typename Matrix<3, T>::IdentityType = (Matrix<3, T>::Identity), T value = T(1)); /** @brief %Matrix from column vectors */ - inline constexpr /*implicit*/ Matrix3(const Vector3& first, const Vector3& second, const Vector3& third): Matrix<3, T>(first, second, third) {} + constexpr /*implicit*/ Matrix3(const Vector3& first, const Vector3& second, const Vector3& third): Matrix<3, T>(first, second, third) {} /** @copydoc Matrix::Matrix(const RectangularMatrix&) */ - template inline constexpr explicit Matrix3(const RectangularMatrix<3, 3, U>& other): Matrix<3, T>(other) {} + template constexpr explicit Matrix3(const RectangularMatrix<3, 3, U>& other): Matrix<3, T>(other) {} /** @brief Construct matrix from external representation */ - template::from(std::declval()))> inline constexpr explicit Matrix3(const U& other): Matrix<3, T>(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {} + template::from(std::declval()))> constexpr explicit Matrix3(const U& other): Matrix<3, T>(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {} /** @brief Copy constructor */ - inline constexpr Matrix3(const RectangularMatrix<3, 3, T>& other): Matrix<3, T>(other) {} + constexpr Matrix3(const RectangularMatrix<3, 3, T>& other): Matrix<3, T>(other) {} /** * @brief Check whether the matrix represents rigid transformation @@ -162,7 +143,7 @@ template class Matrix3: public Matrix<3, T> { * no scaling or projection). * @see isOrthogonal() */ - inline bool isRigidTransformation() const { + bool isRigidTransformation() const { return rotationScaling().isOrthogonal() && row(2) == Vector3(T(0), T(0), T(1)); } @@ -174,7 +155,7 @@ template class Matrix3: public Matrix<3, T> { * rotation(T), Matrix4::rotationScaling() const * @todo extract rotation with assert for no scaling */ - inline constexpr Matrix<2, T> rotationScaling() const { + constexpr Matrix<2, T> rotationScaling() const { return {(*this)[0].xy(), (*this)[1].xy()}; } @@ -186,7 +167,7 @@ template class Matrix3: public Matrix<3, T> { * @see rotationScaling() const, rotation(T), Matrix4::rotation() const * @todo assert uniform scaling (otherwise this would be garbage) */ - inline Matrix<2, T> rotation() const { + Matrix<2, T> rotation() const { return {(*this)[0].xy().normalized(), (*this)[1].xy().normalized()}; } @@ -199,8 +180,8 @@ template class Matrix3: public Matrix<3, T> { * First two elements of first column. * @see up(), Vector2::xAxis(), Matrix4::right() */ - inline Vector2& right() { return (*this)[0].xy(); } - inline constexpr Vector2 right() const { return (*this)[0].xy(); } /**< @overload */ + Vector2& right() { return (*this)[0].xy(); } + constexpr Vector2 right() const { return (*this)[0].xy(); } /**< @overload */ /** * @brief Up-pointing 2D vector @@ -208,8 +189,8 @@ template class Matrix3: public Matrix<3, T> { * First two elements of second column. * @see right(), Vector2::yAxis(), Matrix4::up() */ - inline Vector2& up() { return (*this)[1].xy(); } - inline constexpr Vector2 up() const { return (*this)[1].xy(); } /**< @overload */ + Vector2& up() { return (*this)[1].xy(); } + constexpr Vector2 up() const { return (*this)[1].xy(); } /**< @overload */ /** * @brief 2D translation part of the matrix @@ -218,8 +199,8 @@ template class Matrix3: public Matrix<3, T> { * @see from(const Matrix<2, T>&, const Vector2&), * translation(const Vector2&), Matrix4::translation() */ - inline Vector2& translation() { return (*this)[2].xy(); } - inline constexpr Vector2 translation() const { return (*this)[2].xy(); } /**< @overload */ + Vector2& translation() { return (*this)[2].xy(); } + constexpr Vector2 translation() const { return (*this)[2].xy(); } /**< @overload */ /** * @brief Inverted rigid transformation matrix @@ -229,13 +210,7 @@ template class Matrix3: public Matrix<3, T> { * @see isRigidTransformation(), invertedOrthogonal(), * rotationScaling() const, translation() const */ - inline Matrix3 invertedRigid() const { - CORRADE_ASSERT(isRigidTransformation(), - "Math::Matrix3::invertedRigid(): the matrix doesn't represent rigid transformation", {}); - - Matrix<2, T> inverseRotation = rotationScaling().transposed(); - return from(inverseRotation, inverseRotation*-translation()); - } + Matrix3 invertedRigid() const; /** * @brief Transform 2D vector with the matrix @@ -247,7 +222,7 @@ template class Matrix3: public Matrix<3, T> { * @see Complex::transformVector(), Matrix4::transformVector() * @todo extract 2x2 matrix and multiply directly? (benchmark that) */ - inline Vector2 transformVector(const Vector2& vector) const { + Vector2 transformVector(const Vector2& vector) const { return ((*this)*Vector3(vector, T(0))).xy(); } @@ -260,7 +235,7 @@ template class Matrix3: public Matrix<3, T> { * @f] * @see DualComplex::transformPoint(), Matrix4::transformPoint() */ - inline Vector2 transformPoint(const Vector2& vector) const { + Vector2 transformPoint(const Vector2& vector) const { return ((*this)*Vector3(vector, T(1))).xy(); } @@ -275,6 +250,41 @@ template inline Corrade::Utility::Debug operator<<(Corrade::Utility::De return debug << static_cast&>(value); } +template constexpr Matrix3::Matrix3(typename Matrix<3, T>::IdentityType, const T value): Matrix<3, T>( + Vector<3, T>(value, T(0), T(0)), + Vector<3, T>( T(0), value, T(0)), + Vector<3, T>( T(0), T(0), value) +) {} + +template constexpr Matrix3 Matrix3::translation(const Vector2& vector) { + return {{ T(1), T(0), T(0)}, + { T(0), T(1), T(0)}, + {vector.x(), vector.y(), T(1)}}; +} + +template constexpr Matrix3 Matrix3::scaling(const Vector2< T >& vector) { + return {{vector.x(), T(0), T(0)}, + { T(0), vector.y(), T(0)}, + { T(0), T(0), T(1)}}; +} + +template Matrix3 Matrix3::rotation(const Rad angle) { + const T sine = std::sin(T(angle)); + const T cosine = std::cos(T(angle)); + + return {{ cosine, sine, T(0)}, + { -sine, cosine, T(0)}, + { T(0), T(0), T(1)}}; +} + +template inline Matrix3 Matrix3::invertedRigid() const { + CORRADE_ASSERT(isRigidTransformation(), + "Math::Matrix3::invertedRigid(): the matrix doesn't represent rigid transformation", {}); + + Matrix<2, T> inverseRotation = rotationScaling().transposed(); + return from(inverseRotation, inverseRotation*-translation()); +} + }} namespace Corrade { namespace Utility { diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index ebd5582fa..f1f366bf9 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -58,12 +58,7 @@ template class Matrix4: public Matrix<4, T> { * Matrix3::translation(const Vector2&), Vector3::xAxis(), * Vector3::yAxis(), Vector3::zAxis() */ - inline constexpr static Matrix4 translation(const Vector3& vector) { - return {{ T(1), T(0), T(0), T(0)}, - { T(0), T(1), T(0), T(0)}, - { T(0), T(0), T(1), T(0)}, - {vector.x(), vector.y(), vector.z(), T(1)}}; - } + constexpr static Matrix4 translation(const Vector3& vector); /** * @brief 3D scaling @@ -72,12 +67,7 @@ template class Matrix4: public Matrix<4, T> { * @see rotationScaling() const, Matrix3::scaling(const Vector2&), * Vector3::xScale(), Vector3::yScale(), Vector3::zScale() */ - inline constexpr static Matrix4 scaling(const Vector3& vector) { - return {{vector.x(), T(0), T(0), T(0)}, - { T(0), vector.y(), T(0), T(0)}, - { T(0), T(0), vector.z(), T(0)}, - { T(0), T(0), T(0), T(1)}}; - } + constexpr static Matrix4 scaling(const Vector3& vector); /** * @brief 3D rotation around arbitrary axis @@ -90,37 +80,7 @@ template class Matrix4: public Matrix<4, T> { * Matrix3::rotation(Rad), Vector3::xAxis(), Vector3::yAxis(), * Vector3::zAxis(), Vector::isNormalized() */ - static Matrix4 rotation(Rad angle, const Vector3& normalizedAxis) { - CORRADE_ASSERT(normalizedAxis.isNormalized(), - "Math::Matrix4::rotation(): axis must be normalized", {}); - - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); - T oneMinusCosine = T(1) - cosine; - - T xx = normalizedAxis.x()*normalizedAxis.x(); - T xy = normalizedAxis.x()*normalizedAxis.y(); - T xz = normalizedAxis.x()*normalizedAxis.z(); - T yy = normalizedAxis.y()*normalizedAxis.y(); - T yz = normalizedAxis.y()*normalizedAxis.z(); - T zz = normalizedAxis.z()*normalizedAxis.z(); - - return { - {cosine + xx*oneMinusCosine, - xy*oneMinusCosine + normalizedAxis.z()*sine, - xz*oneMinusCosine - normalizedAxis.y()*sine, - T(0)}, - {xy*oneMinusCosine - normalizedAxis.z()*sine, - cosine + yy*oneMinusCosine, - yz*oneMinusCosine + normalizedAxis.x()*sine, - T(0)}, - {xz*oneMinusCosine + normalizedAxis.y()*sine, - yz*oneMinusCosine - normalizedAxis.x()*sine, - cosine + zz*oneMinusCosine, - T(0)}, - {T(0), T(0), T(0), T(1)} - }; - } + static Matrix4 rotation(Rad angle, const Vector3& normalizedAxis); /** * @brief 3D rotation around X axis @@ -130,15 +90,7 @@ template class Matrix4: public Matrix<4, T> { * @see rotation(Rad, const Vector3&), rotationY(), rotationZ(), * rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) */ - static Matrix4 rotationX(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); - - return {{T(1), T(0), T(0), T(0)}, - {T(0), cosine, sine, T(0)}, - {T(0), -sine, cosine, T(0)}, - {T(0), T(0), T(0), T(1)}}; - } + static Matrix4 rotationX(Rad angle); /** * @brief 3D rotation around Y axis @@ -148,15 +100,7 @@ template class Matrix4: public Matrix<4, T> { * @see rotation(Rad, const Vector3&), rotationX(), rotationZ(), * rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) */ - static Matrix4 rotationY(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); - - return {{cosine, T(0), -sine, T(0)}, - { T(0), T(1), T(0), T(0)}, - { sine, T(0), cosine, T(0)}, - { T(0), T(0), T(0), T(1)}}; - } + static Matrix4 rotationY(Rad angle); /** * @brief 3D rotation matrix around Z axis @@ -166,15 +110,7 @@ template class Matrix4: public Matrix<4, T> { * @see rotation(Rad, const Vector3&), rotationX(), rotationY(), * rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) */ - static Matrix4 rotationZ(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); - - return {{cosine, sine, T(0), T(0)}, - { -sine, cosine, T(0), T(0)}, - { T(0), T(0), T(1), T(0)}, - { T(0), T(0), T(0), T(1)}}; - } + static Matrix4 rotationZ(Rad angle); /** * @brief 3D reflection matrix @@ -183,11 +119,7 @@ template class Matrix4: public Matrix<4, T> { * Expects that the normal is normalized. * @see Matrix3::reflection(), Vector::isNormalized() */ - static Matrix4 reflection(const Vector3& normal) { - CORRADE_ASSERT(normal.isNormalized(), - "Math::Matrix4::reflection(): normal must be normalized", {}); - return from(Matrix<3, T>() - T(2)*normal*RectangularMatrix<1, 3, T>(normal).transposed(), {}); - } + static Matrix4 reflection(const Vector3& normal); /** * @brief 3D orthographic projection matrix @@ -197,15 +129,7 @@ template class Matrix4: public Matrix<4, T> { * * @see perspectiveProjection(), Matrix3::projection() */ - static Matrix4 orthographicProjection(const Vector2& size, T near, T far) { - Vector2 xyScale = T(2.0)/size; - T zScale = T(2.0)/(near-far); - - return {{xyScale.x(), T(0), T(0), T(0)}, - { T(0), xyScale.y(), T(0), T(0)}, - { T(0), T(0), zScale, T(0)}, - { T(0), T(0), near*zScale-T(1), T(1)}}; - } + static Matrix4 orthographicProjection(const Vector2& size, T near, T far); /** * @brief 3D perspective projection matrix @@ -215,15 +139,7 @@ template class Matrix4: public Matrix<4, T> { * * @see orthographicProjection(), Matrix3::projection() */ - static Matrix4 perspectiveProjection(const Vector2& size, T near, T far) { - Vector2 xyScale = 2*near/size; - T zScale = T(1.0)/(near-far); - - return {{xyScale.x(), T(0), T(0), T(0)}, - { T(0), xyScale.y(), T(0), T(0)}, - { T(0), T(0), (far+near)*zScale, T(-1)}, - { T(0), T(0), T(2)*far*near*zScale, T(0)}}; - } + static Matrix4 perspectiveProjection(const Vector2& size, T near, T far); /** * @brief 3D perspective projection matrix @@ -235,8 +151,7 @@ template class Matrix4: public Matrix<4, T> { * @see orthographicProjection(), Matrix3::projection() */ static Matrix4 perspectiveProjection(Rad fov, T aspectRatio, T near, T far) { - T xyScale = 2*std::tan(T(fov)/2)*near; - + const T xyScale = 2*std::tan(T(fov)/2)*near; return perspectiveProjection(Vector2(xyScale, xyScale/aspectRatio), near, far); } @@ -249,15 +164,10 @@ template class Matrix4: public Matrix<4, T> { * * @see rotationScaling() const, translation() const */ - inline constexpr static Matrix4 from(const Matrix<3, T>& rotationScaling, const Vector3& translation) { - return {{rotationScaling[0], T(0)}, - {rotationScaling[1], T(0)}, - {rotationScaling[2], T(0)}, - { translation, T(1)}}; - } + constexpr static Matrix4 from(const Matrix<3, T>& rotationScaling, const Vector3& translation); /** @copydoc Matrix::Matrix(ZeroType) */ - inline constexpr explicit Matrix4(typename Matrix<4, T>::ZeroType): Matrix<4, T>(Matrix<4, T>::Zero) {} + constexpr explicit Matrix4(typename Matrix<4, T>::ZeroType): Matrix<4, T>(Matrix<4, T>::Zero) {} /** * @brief Default constructor @@ -267,24 +177,19 @@ template class Matrix4: public Matrix<4, T> { * @p value allows you to specify value on diagonal. * @todo Use constexpr implementation in Matrix, when done */ - inline constexpr /*implicit*/ Matrix4(typename Matrix<4, T>::IdentityType = (Matrix<4, T>::Identity), T value = T(1)): Matrix<4, T>( - Vector<4, T>(value, T(0), T(0), T(0)), - Vector<4, T>( T(0), value, T(0), T(0)), - Vector<4, T>( T(0), T(0), value, T(0)), - Vector<4, T>( T(0), T(0), T(0), value) - ) {} + constexpr /*implicit*/ Matrix4(typename Matrix<4, T>::IdentityType = (Matrix<4, T>::Identity), T value = T(1)); /** @brief %Matrix from column vectors */ - inline constexpr /*implicit*/ Matrix4(const Vector4& first, const Vector4& second, const Vector4& third, const Vector4& fourth): Matrix<4, T>(first, second, third, fourth) {} + constexpr /*implicit*/ Matrix4(const Vector4& first, const Vector4& second, const Vector4& third, const Vector4& fourth): Matrix<4, T>(first, second, third, fourth) {} /** @copydoc Matrix::Matrix(const RectangularMatrix&) */ - template inline constexpr explicit Matrix4(const RectangularMatrix<4, 4, U>& other): Matrix<4, T>(other) {} + template constexpr explicit Matrix4(const RectangularMatrix<4, 4, U>& other): Matrix<4, T>(other) {} /** @brief Construct matrix from external representation */ - template::from(std::declval()))> inline constexpr explicit Matrix4(const U& other): Matrix<4, T>(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {} + template::from(std::declval()))> constexpr explicit Matrix4(const U& other): Matrix<4, T>(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {} /** @brief Copy constructor */ - inline constexpr Matrix4(const RectangularMatrix<4, 4, T>& other): Matrix<4, T>(other) {} + constexpr Matrix4(const RectangularMatrix<4, 4, T>& other): Matrix<4, T>(other) {} /** * @brief Check whether the matrix represents rigid transformation @@ -293,7 +198,7 @@ template class Matrix4: public Matrix<4, T> { * no scaling or projection). * @see isOrthogonal() */ - inline bool isRigidTransformation() const { + bool isRigidTransformation() const { return rotationScaling().isOrthogonal() && row(3) == Vector4(T(0), T(0), T(0), T(1)); } @@ -305,12 +210,8 @@ template class Matrix4: public Matrix<4, T> { * rotation(T, const Vector3&), Matrix3::rotationScaling() const * @todo extract rotation with assert for no scaling */ - inline constexpr Matrix<3, T> rotationScaling() const { - /* Not Matrix3, because it is for affine 2D transformations */ - return {(*this)[0].xyz(), - (*this)[1].xyz(), - (*this)[2].xyz()}; - } + /* Not Matrix3, because it is for affine 2D transformations */ + constexpr Matrix<3, T> rotationScaling() const; /** * @brief 3D rotation part of the matrix @@ -320,12 +221,8 @@ template class Matrix4: public Matrix<4, T> { * Matrix3::rotation() const * @todo assert uniform scaling (otherwise this would be garbage) */ - inline Matrix<3, T> rotation() const { - /* Not Matrix3, because it is for affine 2D transformations */ - return {(*this)[0].xyz().normalized(), - (*this)[1].xyz().normalized(), - (*this)[2].xyz().normalized()}; - } + /* Not Matrix3, because it is for affine 2D transformations */ + Matrix<3, T> rotation() const; /** @todo uniform scaling extraction */ @@ -335,8 +232,8 @@ template class Matrix4: public Matrix<4, T> { * First three elements of first column. * @see up(), backward(), Vector3::xAxis(), Matrix3::right() */ - inline Vector3& right() { return (*this)[0].xyz(); } - inline constexpr Vector3 right() const { return (*this)[0].xyz(); } /**< @overload */ + Vector3& right() { return (*this)[0].xyz(); } + constexpr Vector3 right() const { return (*this)[0].xyz(); } /**< @overload */ /** * @brief Up-pointing 3D vector @@ -344,8 +241,8 @@ template class Matrix4: public Matrix<4, T> { * First three elements of second column. * @see right(), backward(), Vector3::yAxis(), Matrix3::up() */ - inline Vector3& up() { return (*this)[1].xyz(); } - inline constexpr Vector3 up() const { return (*this)[1].xyz(); } /**< @overload */ + Vector3& up() { return (*this)[1].xyz(); } + constexpr Vector3 up() const { return (*this)[1].xyz(); } /**< @overload */ /** * @brief Backward-pointing 3D vector @@ -353,8 +250,8 @@ template class Matrix4: public Matrix<4, T> { * First three elements of third column. * @see right(), up(), Vector3::yAxis() */ - inline Vector3& backward() { return (*this)[2].xyz(); } - inline constexpr Vector3 backward() const { return (*this)[2].xyz(); } /**< @overload */ + Vector3& backward() { return (*this)[2].xyz(); } + constexpr Vector3 backward() const { return (*this)[2].xyz(); } /**< @overload */ /** * @brief 3D translation part of the matrix @@ -363,8 +260,8 @@ template class Matrix4: public Matrix<4, T> { * @see from(const Matrix<3, T>&, const Vector3&), * translation(const Vector3&), Matrix3::translation() */ - inline Vector3& translation() { return (*this)[3].xyz(); } - inline constexpr Vector3 translation() const { return (*this)[3].xyz(); } /**< @overload */ + Vector3& translation() { return (*this)[3].xyz(); } + constexpr Vector3 translation() const { return (*this)[3].xyz(); } /**< @overload */ /** * @brief Inverted rigid transformation matrix @@ -374,13 +271,7 @@ template class Matrix4: public Matrix<4, T> { * @see isRigidTransformation(), invertedOrthogonal(), * rotationScaling() const, translation() const */ - inline Matrix4 invertedRigid() const { - CORRADE_ASSERT(isRigidTransformation(), - "Math::Matrix4::invertedRigid(): the matrix doesn't represent rigid transformation", {}); - - Matrix<3, T> inverseRotation = rotationScaling().transposed(); - return from(inverseRotation, inverseRotation*-translation()); - } + Matrix4 invertedRigid() const; /** * @brief Transform 3D vector with the matrix @@ -392,7 +283,7 @@ template class Matrix4: public Matrix<4, T> { * @see Quaternion::transformVector(), Matrix3::transformVector() * @todo extract 3x3 matrix and multiply directly? (benchmark that) */ - inline Vector3 transformVector(const Vector3& vector) const { + Vector3 transformVector(const Vector3& vector) const { return ((*this)*Vector4(vector, T(0))).xyz(); } @@ -405,7 +296,7 @@ template class Matrix4: public Matrix<4, T> { * @f] * @see DualQuaternion::transformPoint(), Matrix3::transformPoint() */ - inline Vector3 transformPoint(const Vector3& vector) const { + Vector3 transformPoint(const Vector3& vector) const { return ((*this)*Vector4(vector, T(1))).xyz(); } @@ -420,6 +311,142 @@ template inline Corrade::Utility::Debug operator<<(Corrade::Utility::De return debug << static_cast&>(value); } +template constexpr Matrix4 Matrix4::translation(const Vector3& vector) { + return {{ T(1), T(0), T(0), T(0)}, + { T(0), T(1), T(0), T(0)}, + { T(0), T(0), T(1), T(0)}, + {vector.x(), vector.y(), vector.z(), T(1)}}; +} + +template constexpr Matrix4 Matrix4::scaling(const Vector3& vector) { + return {{vector.x(), T(0), T(0), T(0)}, + { T(0), vector.y(), T(0), T(0)}, + { T(0), T(0), vector.z(), T(0)}, + { T(0), T(0), T(0), T(1)}}; +} + +template Matrix4 Matrix4::rotation(const Rad angle, const Vector3& normalizedAxis) { + CORRADE_ASSERT(normalizedAxis.isNormalized(), + "Math::Matrix4::rotation(): axis must be normalized", {}); + + const T sine = std::sin(T(angle)); + const T cosine = std::cos(T(angle)); + const T oneMinusCosine = T(1) - cosine; + + const T xx = normalizedAxis.x()*normalizedAxis.x(); + const T xy = normalizedAxis.x()*normalizedAxis.y(); + const T xz = normalizedAxis.x()*normalizedAxis.z(); + const T yy = normalizedAxis.y()*normalizedAxis.y(); + const T yz = normalizedAxis.y()*normalizedAxis.z(); + const T zz = normalizedAxis.z()*normalizedAxis.z(); + + return { + {cosine + xx*oneMinusCosine, + xy*oneMinusCosine + normalizedAxis.z()*sine, + xz*oneMinusCosine - normalizedAxis.y()*sine, + T(0)}, + {xy*oneMinusCosine - normalizedAxis.z()*sine, + cosine + yy*oneMinusCosine, + yz*oneMinusCosine + normalizedAxis.x()*sine, + T(0)}, + {xz*oneMinusCosine + normalizedAxis.y()*sine, + yz*oneMinusCosine - normalizedAxis.x()*sine, + cosine + zz*oneMinusCosine, + T(0)}, + {T(0), T(0), T(0), T(1)} + }; +} + +template Matrix4 Matrix4::rotationX(const Rad angle) { + const T sine = std::sin(T(angle)); + const T cosine = std::cos(T(angle)); + + return {{T(1), T(0), T(0), T(0)}, + {T(0), cosine, sine, T(0)}, + {T(0), -sine, cosine, T(0)}, + {T(0), T(0), T(0), T(1)}}; +} + +template Matrix4 Matrix4::rotationY(const Rad angle) { + const T sine = std::sin(T(angle)); + const T cosine = std::cos(T(angle)); + + return {{cosine, T(0), -sine, T(0)}, + { T(0), T(1), T(0), T(0)}, + { sine, T(0), cosine, T(0)}, + { T(0), T(0), T(0), T(1)}}; +} + +template Matrix4 Matrix4::rotationZ(const Rad angle) { + const T sine = std::sin(T(angle)); + const T cosine = std::cos(T(angle)); + + return {{cosine, sine, T(0), T(0)}, + { -sine, cosine, T(0), T(0)}, + { T(0), T(0), T(1), T(0)}, + { T(0), T(0), T(0), T(1)}}; +} + +template Matrix4 Matrix4::reflection(const Vector3& normal) { + CORRADE_ASSERT(normal.isNormalized(), + "Math::Matrix4::reflection(): normal must be normalized", {}); + return from(Matrix<3, T>() - T(2)*normal*RectangularMatrix<1, 3, T>(normal).transposed(), {}); +} + +template Matrix4 Matrix4::orthographicProjection(const Vector2& size, const T near, const T far) { + const Vector2 xyScale = T(2.0)/size; + const T zScale = T(2.0)/(near-far); + + return {{xyScale.x(), T(0), T(0), T(0)}, + { T(0), xyScale.y(), T(0), T(0)}, + { T(0), T(0), zScale, T(0)}, + { T(0), T(0), near*zScale-T(1), T(1)}}; +} + +template Matrix4 Matrix4::perspectiveProjection(const Vector2& size, const T near, const T far) { + Vector2 xyScale = 2*near/size; + T zScale = T(1.0)/(near-far); + + return {{xyScale.x(), T(0), T(0), T(0)}, + { T(0), xyScale.y(), T(0), T(0)}, + { T(0), T(0), (far+near)*zScale, T(-1)}, + { T(0), T(0), T(2)*far*near*zScale, T(0)}}; +} + +template constexpr Matrix4 Matrix4::from(const Matrix<3, T>& rotationScaling, const Vector3& translation) { + return {{rotationScaling[0], T(0)}, + {rotationScaling[1], T(0)}, + {rotationScaling[2], T(0)}, + { translation, T(1)}}; +} + +template constexpr Matrix4::Matrix4(typename Matrix<4, T>::IdentityType, const T value): Matrix<4, T>( + Vector<4, T>(value, T(0), T(0), T(0)), + Vector<4, T>( T(0), value, T(0), T(0)), + Vector<4, T>( T(0), T(0), value, T(0)), + Vector<4, T>( T(0), T(0), T(0), value) +) {} + +template constexpr Matrix<3, T> Matrix4::rotationScaling() const { + return {(*this)[0].xyz(), + (*this)[1].xyz(), + (*this)[2].xyz()}; +} + +template inline Matrix<3, T> Matrix4::rotation() const { + return {(*this)[0].xyz().normalized(), + (*this)[1].xyz().normalized(), + (*this)[2].xyz().normalized()}; +} + +template Matrix4 Matrix4::invertedRigid() const { + CORRADE_ASSERT(isRigidTransformation(), + "Math::Matrix4::invertedRigid(): the matrix doesn't represent rigid transformation", {}); + + Matrix<3, T> inverseRotation = rotationScaling().transposed(); + return from(inverseRotation, inverseRotation*-translation()); +} + }} namespace Corrade { namespace Utility { diff --git a/src/Math/Quaternion.h b/src/Math/Quaternion.h index 3cd832fbf..d17c3e627 100644 --- a/src/Math/Quaternion.h +++ b/src/Math/Quaternion.h @@ -38,44 +38,6 @@ namespace Magnum { namespace Math { -namespace Implementation { - -/* No assertions fired, for internal use. Not private member because used from - outside the class. */ -template inline Quaternion quaternionFromMatrix(const Matrix<3, T>& m) { - const Vector<3, T> diagonal = m.diagonal(); - const T trace = diagonal.sum(); - - /* Diagonal is positive */ - if(trace > T(0)) { - const T s = std::sqrt(trace + T(1)); - const T t = T(0.5)/s; - return {Vector3(m[1][2] - m[2][1], - m[2][0] - m[0][2], - m[0][1] - m[1][0])*t, s*T(0.5)}; - } - - /* Diagonal is negative */ - std::size_t i = 0; - if(diagonal[1] > diagonal[0]) i = 1; - if(diagonal[2] > diagonal[i]) i = 2; - - const std::size_t j = (i + 1) % 3; - const std::size_t k = (i + 2) % 3; - - const T s = std::sqrt(diagonal[i] - diagonal[j] - diagonal[k] + T(1)); - const T t = (s == T(0) ? T(0) : T(0.5)/s); - - Vector3 vec; - vec[i] = s*T(0.5); - vec[j] = (m[i][j] + m[j][i])*t; - vec[k] = (m[i][k] + m[k][i])*t; - - return {vec, (m[j][k] - m[k][j])*t}; -} - -} - /** @brief %Quaternion @tparam T Underlying data type @@ -95,7 +57,7 @@ template class Quaternion { * @f] * @see dot() const */ - inline static T dot(const Quaternion& a, const Quaternion& b) { + static T dot(const Quaternion& a, const Quaternion& b) { /** @todo Use four-component SIMD implementation when available */ return Vector3::dot(a.vector(), b.vector()) + a.scalar()*b.scalar(); } @@ -108,11 +70,7 @@ template class Quaternion { * @f] * @see isNormalized(), Complex::angle(), Vector::angle() */ - inline static Rad angle(const Quaternion& normalizedA, const Quaternion& normalizedB) { - CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), - "Math::Quaternion::angle(): quaternions must be normalized", Rad(std::numeric_limits::quiet_NaN())); - return Rad(angleInternal(normalizedA, normalizedB)); - } + static Rad angle(const Quaternion& normalizedA, const Quaternion& normalizedB); /** * @brief Linear interpolation of two quaternions @@ -125,12 +83,7 @@ template class Quaternion { * @f] * @see isNormalized(), slerp(), Math::lerp() */ - inline static Quaternion lerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t) { - CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), - "Math::Quaternion::lerp(): quaternions must be normalized", - Quaternion({}, std::numeric_limits::quiet_NaN())); - return ((T(1) - t)*normalizedA + t*normalizedB).normalized(); - } + static Quaternion lerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t); /** * @brief Spherical linear interpolation of two quaternions @@ -145,13 +98,7 @@ template class Quaternion { * @f] * @see isNormalized(), lerp() */ - inline static Quaternion slerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t) { - CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), - "Math::Quaternion::slerp(): quaternions must be normalized", - Quaternion({}, std::numeric_limits::quiet_NaN())); - T a = angleInternal(normalizedA, normalizedB); - return (std::sin((T(1) - t)*a)*normalizedA + std::sin(t*a)*normalizedB)/std::sin(a); - } + static Quaternion slerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t); /** * @brief Rotation quaternion @@ -165,12 +112,7 @@ template class Quaternion { * Matrix4::rotation(), Complex::rotation(), Vector3::xAxis(), * Vector3::yAxis(), Vector3::zAxis(), Vector::isNormalized() */ - inline static Quaternion rotation(Rad angle, const Vector3& normalizedAxis) { - CORRADE_ASSERT(normalizedAxis.isNormalized(), - "Math::Quaternion::rotation(): axis must be normalized", {}); - - return {normalizedAxis*std::sin(T(angle)/2), std::cos(T(angle)/2)}; - } + static Quaternion rotation(Rad angle, const Vector3& normalizedAxis); /** * @brief Create quaternion from rotation matrix @@ -178,11 +120,7 @@ template class Quaternion { * Expects that the matrix is orthogonal (i.e. pure rotation). * @see toMatrix(), DualComplex::fromMatrix(), Matrix::isOrthogonal() */ - inline static Quaternion fromMatrix(const Matrix<3, T>& matrix) { - CORRADE_ASSERT(matrix.isOrthogonal(), - "Math::Quaternion::fromMatrix(): the matrix is not orthogonal", {}); - return Implementation::quaternionFromMatrix(matrix); - } + static Quaternion fromMatrix(const Matrix<3, T>& matrix); /** * @brief Default constructor @@ -191,7 +129,7 @@ template class Quaternion { * q = [\boldsymbol 0, 1] * @f] */ - inline constexpr /*implicit*/ Quaternion(): _scalar(T(1)) {} + constexpr /*implicit*/ Quaternion(): _scalar(T(1)) {} /** * @brief Construct quaternion from vector and scalar @@ -200,7 +138,7 @@ template class Quaternion { * q = [\boldsymbol v, s] * @f] */ - inline constexpr /*implicit*/ Quaternion(const Vector3& vector, T scalar): _vector(vector), _scalar(scalar) {} + constexpr /*implicit*/ Quaternion(const Vector3& vector, T scalar): _vector(vector), _scalar(scalar) {} /** * @brief Construct quaternion from vector @@ -210,15 +148,15 @@ template class Quaternion { * @f] * @see transformVector(), transformVectorNormalized() */ - inline constexpr explicit Quaternion(const Vector3& vector): _vector(vector), _scalar(T(0)) {} + constexpr explicit Quaternion(const Vector3& vector): _vector(vector), _scalar(T(0)) {} /** @brief Equality comparison */ - inline bool operator==(const Quaternion& other) const { + bool operator==(const Quaternion& other) const { return _vector == other._vector && TypeTraits::equals(_scalar, other._scalar); } /** @brief Non-equality comparison */ - inline bool operator!=(const Quaternion& other) const { + bool operator!=(const Quaternion& other) const { return !operator==(other); } @@ -230,15 +168,15 @@ template class Quaternion { * @f] * @see dot(), normalized() */ - inline bool isNormalized() const { + bool isNormalized() const { return Implementation::isNormalizedSquared(dot()); } /** @brief %Vector part */ - inline constexpr Vector3 vector() const { return _vector; } + constexpr Vector3 vector() const { return _vector; } /** @brief %Scalar part */ - inline constexpr T scalar() const { return _scalar; } + constexpr T scalar() const { return _scalar; } /** * @brief Rotation angle of unit quaternion @@ -248,12 +186,7 @@ template class Quaternion { * @f] * @see isNormalized(), axis(), rotation() */ - inline Rad angle() const { - CORRADE_ASSERT(isNormalized(), - "Math::Quaternion::angle(): quaternion must be normalized", - Rad(std::numeric_limits::quiet_NaN())); - return Rad(T(2)*std::acos(_scalar)); - } + Rad angle() const; /** * @brief Rotation axis of unit quaternion @@ -265,12 +198,7 @@ template class Quaternion { * @f] * @see isNormalized(), angle(), rotation() */ - inline Vector3 axis() const { - CORRADE_ASSERT(isNormalized(), - "Math::Quaternion::axis(): quaternion must be normalized", - {}); - return _vector/std::sqrt(1-pow2(_scalar)); - } + Vector3 axis() const; /** * @brief Convert quaternion to rotation matrix @@ -278,19 +206,7 @@ template class Quaternion { * @see fromMatrix(), DualQuaternion::toMatrix(), * Matrix4::from(const Matrix<3, T>&, const Vector3&) */ - Matrix<3, T> toMatrix() const { - return { - Vector<3, T>(T(1) - 2*pow2(_vector.y()) - 2*pow2(_vector.z()), - 2*_vector.x()*_vector.y() + 2*_vector.z()*_scalar, - 2*_vector.x()*_vector.z() - 2*_vector.y()*_scalar), - Vector<3, T>(2*_vector.x()*_vector.y() - 2*_vector.z()*_scalar, - T(1) - 2*pow2(_vector.x()) - 2*pow2(_vector.z()), - 2*_vector.y()*_vector.z() + 2*_vector.x()*_scalar), - Vector<3, T>(2*_vector.x()*_vector.z() + 2*_vector.y()*_scalar, - 2*_vector.y()*_vector.z() - 2*_vector.x()*_scalar, - T(1) - 2*pow2(_vector.x()) - 2*pow2(_vector.y())) - }; - } + Matrix<3, T> toMatrix() const; /** * @brief Add and assign quaternion @@ -299,7 +215,7 @@ template class Quaternion { * p + q = [\boldsymbol p_V + \boldsymbol q_V, p_S + q_S] * @f] */ - inline Quaternion& operator+=(const Quaternion& other) { + Quaternion& operator+=(const Quaternion& other) { _vector += other._vector; _scalar += other._scalar; return *this; @@ -310,7 +226,7 @@ template class Quaternion { * * @see operator+=() */ - inline Quaternion operator+(const Quaternion& other) const { + Quaternion operator+(const Quaternion& other) const { return Quaternion(*this) += other; } @@ -321,9 +237,7 @@ template class Quaternion { * -q = [-\boldsymbol q_V, -q_S] * @f] */ - inline Quaternion operator-() const { - return {-_vector, -_scalar}; - } + Quaternion operator-() const { return {-_vector, -_scalar}; } /** * @brief Subtract and assign quaternion @@ -332,7 +246,7 @@ template class Quaternion { * p - q = [\boldsymbol p_V - \boldsymbol q_V, p_S - q_S] * @f] */ - inline Quaternion& operator-=(const Quaternion& other) { + Quaternion& operator-=(const Quaternion& other) { _vector -= other._vector; _scalar -= other._scalar; return *this; @@ -343,7 +257,7 @@ template class Quaternion { * * @see operator-=() */ - inline Quaternion operator-(const Quaternion& other) const { + Quaternion operator-(const Quaternion& other) const { return Quaternion(*this) -= other; } @@ -354,7 +268,7 @@ template class Quaternion { * q \cdot a = [\boldsymbol q_V \cdot a, q_S \cdot a] * @f] */ - inline Quaternion& operator*=(T scalar) { + Quaternion& operator*=(T scalar) { _vector *= scalar; _scalar *= scalar; return *this; @@ -365,7 +279,7 @@ template class Quaternion { * * @see operator*=(T) */ - inline Quaternion operator*(T scalar) const { + Quaternion operator*(T scalar) const { return Quaternion(*this) *= scalar; } @@ -376,7 +290,7 @@ template class Quaternion { * \frac q a = [\frac {\boldsymbol q_V} a, \frac {q_S} a] * @f] */ - inline Quaternion& operator/=(T scalar) { + Quaternion& operator/=(T scalar) { _vector /= scalar; _scalar /= scalar; return *this; @@ -387,7 +301,7 @@ template class Quaternion { * * @see operator/=(T) */ - inline Quaternion operator/(T scalar) const { + Quaternion operator/(T scalar) const { return Quaternion(*this) /= scalar; } @@ -399,10 +313,7 @@ template class Quaternion { * p_S q_S - \boldsymbol p_V \cdot \boldsymbol q_V] * @f] */ - inline Quaternion operator*(const Quaternion& other) const { - return {_scalar*other._vector + other._scalar*_vector + Vector3::cross(_vector, other._vector), - _scalar*other._scalar - Vector3::dot(_vector, other._vector)}; - } + Quaternion operator*(const Quaternion& other) const; /** * @brief Dot product of the quaternion @@ -413,9 +324,7 @@ template class Quaternion { * @f] * @see isNormalized(), dot(const Quaternion&, const Quaternion&) */ - inline T dot() const { - return dot(*this, *this); - } + T dot() const { return dot(*this, *this); } /** * @brief %Quaternion length @@ -426,18 +335,14 @@ template class Quaternion { * @f] * @see isNormalized() */ - inline T length() const { - return std::sqrt(dot()); - } + T length() const { return std::sqrt(dot()); } /** * @brief Normalized quaternion (of unit length) * * @see isNormalized() */ - inline Quaternion normalized() const { - return (*this)/length(); - } + Quaternion normalized() const { return (*this)/length(); } /** * @brief Conjugated quaternion @@ -446,9 +351,7 @@ template class Quaternion { * q^* = [-\boldsymbol q_V, q_S] * @f] */ - inline Quaternion conjugated() const { - return {-_vector, _scalar}; - } + Quaternion conjugated() const { return {-_vector, _scalar}; } /** * @brief Inverted quaternion @@ -458,9 +361,7 @@ template class Quaternion { * q^{-1} = \frac{q^*}{|q|^2} = \frac{q^*}{q \cdot q} * @f] */ - inline Quaternion inverted() const { - return conjugated()/dot(); - } + Quaternion inverted() const { return conjugated()/dot(); } /** * @brief Inverted normalized quaternion @@ -471,12 +372,7 @@ template class Quaternion { * @f] * @see isNormalized(), inverted() */ - inline Quaternion invertedNormalized() const { - CORRADE_ASSERT(isNormalized(), - "Math::Quaternion::invertedNormalized(): quaternion must be normalized", - Quaternion({}, std::numeric_limits::quiet_NaN())); - return conjugated(); - } + Quaternion invertedNormalized() const; /** * @brief Rotate vector with quaternion @@ -488,7 +384,7 @@ template class Quaternion { * @see Quaternion(const Vector3&), vector(), Matrix4::transformVector(), * DualQuaternion::transformPoint(), Complex::transformVector() */ - inline Vector3 transformVector(const Vector3& vector) const { + Vector3 transformVector(const Vector3& vector) const { return ((*this)*Quaternion(vector)*inverted()).vector(); } @@ -502,21 +398,16 @@ template class Quaternion { * @see isNormalized(), Quaternion(const Vector3&), vector(), Matrix4::transformVector(), * DualQuaternion::transformPointNormalized(), Complex::transformVector() */ - inline Vector3 transformVectorNormalized(const Vector3& vector) const { - CORRADE_ASSERT(isNormalized(), - "Math::Quaternion::transformVectorNormalized(): quaternion must be normalized", - Vector3(std::numeric_limits::quiet_NaN())); - return ((*this)*Quaternion(vector)*conjugated()).vector(); - } + Vector3 transformVectorNormalized(const Vector3& vector) const; private: /* Used to avoid including Functions.h */ - inline constexpr static T pow2(T value) { + constexpr static T pow2(T value) { return value*value; } /* Used in angle() and slerp() (no assertions) */ - inline static T angleInternal(const Quaternion& normalizedA, const Quaternion& normalizedB) { + static T angleInternal(const Quaternion& normalizedA, const Quaternion& normalizedB) { return std::acos(dot(normalizedA, normalizedB)); } @@ -562,6 +453,116 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit #endif #endif +namespace Implementation { + +/* No assertions fired, for internal use. Not private member because used from + outside the class. */ +template Quaternion quaternionFromMatrix(const Matrix<3, T>& m) { + const Vector<3, T> diagonal = m.diagonal(); + const T trace = diagonal.sum(); + + /* Diagonal is positive */ + if(trace > T(0)) { + const T s = std::sqrt(trace + T(1)); + const T t = T(0.5)/s; + return {Vector3(m[1][2] - m[2][1], + m[2][0] - m[0][2], + m[0][1] - m[1][0])*t, s*T(0.5)}; + } + + /* Diagonal is negative */ + std::size_t i = 0; + if(diagonal[1] > diagonal[0]) i = 1; + if(diagonal[2] > diagonal[i]) i = 2; + + const std::size_t j = (i + 1) % 3; + const std::size_t k = (i + 2) % 3; + + const T s = std::sqrt(diagonal[i] - diagonal[j] - diagonal[k] + T(1)); + const T t = (s == T(0) ? T(0) : T(0.5)/s); + + Vector3 vec; + vec[i] = s*T(0.5); + vec[j] = (m[i][j] + m[j][i])*t; + vec[k] = (m[i][k] + m[k][i])*t; + + return {vec, (m[j][k] - m[k][j])*t}; +} + +} + +template inline Rad Quaternion::angle(const Quaternion& normalizedA, const Quaternion& normalizedB) { + CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), + "Math::Quaternion::angle(): quaternions must be normalized", Rad(std::numeric_limits::quiet_NaN())); + return Rad(angleInternal(normalizedA, normalizedB)); +} + +template inline Quaternion Quaternion::lerp(const Quaternion& normalizedA, const Quaternion& normalizedB, const T t) { + CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), + "Math::Quaternion::lerp(): quaternions must be normalized", Quaternion({}, std::numeric_limits::quiet_NaN())); + return ((T(1) - t)*normalizedA + t*normalizedB).normalized(); +} + +template inline Quaternion Quaternion::slerp(const Quaternion& normalizedA, const Quaternion& normalizedB, const T t) { + CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), + "Math::Quaternion::slerp(): quaternions must be normalized", Quaternion({}, std::numeric_limits::quiet_NaN())); + const T a = angleInternal(normalizedA, normalizedB); + return (std::sin((T(1) - t)*a)*normalizedA + std::sin(t*a)*normalizedB)/std::sin(a); +} + +template inline Quaternion Quaternion::rotation(const Rad angle, const Vector3& normalizedAxis) { + CORRADE_ASSERT(normalizedAxis.isNormalized(), + "Math::Quaternion::rotation(): axis must be normalized", {}); + return {normalizedAxis*std::sin(T(angle)/2), std::cos(T(angle)/2)}; +} + +template inline Quaternion Quaternion::fromMatrix(const Matrix<3, T>& matrix) { + CORRADE_ASSERT(matrix.isOrthogonal(), "Math::Quaternion::fromMatrix(): the matrix is not orthogonal", {}); + return Implementation::quaternionFromMatrix(matrix); +} + +template inline Rad Quaternion::angle() const { + CORRADE_ASSERT(isNormalized(), "Math::Quaternion::angle(): quaternion must be normalized", + Rad(std::numeric_limits::quiet_NaN())); + return Rad(T(2)*std::acos(_scalar)); +} + +template inline Vector3 Quaternion::axis() const { + CORRADE_ASSERT(isNormalized(), "Math::Quaternion::axis(): quaternion must be normalized", {}); + return _vector/std::sqrt(1-pow2(_scalar)); +} + +template Matrix<3, T> Quaternion::toMatrix() const { + return { + Vector<3, T>(T(1) - 2*pow2(_vector.y()) - 2*pow2(_vector.z()), + 2*_vector.x()*_vector.y() + 2*_vector.z()*_scalar, + 2*_vector.x()*_vector.z() - 2*_vector.y()*_scalar), + Vector<3, T>(2*_vector.x()*_vector.y() - 2*_vector.z()*_scalar, + T(1) - 2*pow2(_vector.x()) - 2*pow2(_vector.z()), + 2*_vector.y()*_vector.z() + 2*_vector.x()*_scalar), + Vector<3, T>(2*_vector.x()*_vector.z() + 2*_vector.y()*_scalar, + 2*_vector.y()*_vector.z() - 2*_vector.x()*_scalar, + T(1) - 2*pow2(_vector.x()) - 2*pow2(_vector.y())) + }; +} + +template inline Quaternion Quaternion::operator*(const Quaternion& other) const { + return {_scalar*other._vector + other._scalar*_vector + Vector3::cross(_vector, other._vector), + _scalar*other._scalar - Vector3::dot(_vector, other._vector)}; +} + +template inline Quaternion Quaternion::invertedNormalized() const { + CORRADE_ASSERT(isNormalized(), "Math::Quaternion::invertedNormalized(): quaternion must be normalized", + Quaternion({}, std::numeric_limits::quiet_NaN())); + return conjugated(); +} + +template inline Vector3 Quaternion::transformVectorNormalized(const Vector3< T >& vector) const { + CORRADE_ASSERT(isNormalized(), "Math::Quaternion::transformVectorNormalized(): quaternion must be normalized", + Vector3(std::numeric_limits::quiet_NaN())); + return ((*this)*Quaternion(vector)*conjugated()).vector(); +} + }} #endif diff --git a/src/Math/RectangularMatrix.h b/src/Math/RectangularMatrix.h index 3702a4aaf..ffa9b0224 100644 --- a/src/Math/RectangularMatrix.h +++ b/src/Math/RectangularMatrix.h @@ -77,11 +77,11 @@ template class RectangularMatrix { * @attention Use with caution, the function doesn't check whether the * array is long enough. */ - inline constexpr static RectangularMatrix& from(T* data) { + constexpr static RectangularMatrix& from(T* data) { return *reinterpret_cast*>(data); } /** @overload */ - inline constexpr static const RectangularMatrix& from(const T* data) { + constexpr static const RectangularMatrix& from(const T* data) { return *reinterpret_cast*>(data); } @@ -91,14 +91,7 @@ template class RectangularMatrix { * @see diagonal() * @todo make this constexpr */ - inline static RectangularMatrix fromDiagonal(const Vector& diagonal) { - RectangularMatrix out; - - for(std::size_t i = 0; i != DiagonalSize; ++i) - out[i][i] = diagonal[i]; - - return out; - } + static RectangularMatrix fromDiagonal(const Vector& diagonal); /** * @brief Construct matrix from vector @@ -107,12 +100,12 @@ template class RectangularMatrix { * vector will make first column of resulting matrix. * @see toVector() */ - inline static RectangularMatrix fromVector(const Vector& vector) { + static RectangularMatrix fromVector(const Vector& vector) { return *reinterpret_cast*>(vector.data()); } /** @brief Construct zero-filled matrix */ - inline constexpr /*implicit*/ RectangularMatrix() {} + constexpr /*implicit*/ RectangularMatrix() {} /** * @brief Construct matrix from column vectors @@ -121,7 +114,7 @@ template class RectangularMatrix { * * @todo Creating matrix from arbitrary combination of matrices with n rows */ - template inline constexpr /*implicit*/ RectangularMatrix(const Vector& first, const U&... next): _data{first, next...} { + template constexpr /*implicit*/ RectangularMatrix(const Vector& first, const U&... next): _data{first, next...} { static_assert(sizeof...(next)+1 == cols, "Improper number of arguments passed to RectangularMatrix constructor"); } @@ -137,30 +130,30 @@ template class RectangularMatrix { * @endcode */ #ifndef CORRADE_GCC46_COMPATIBILITY - template inline constexpr explicit RectangularMatrix(const RectangularMatrix& other): RectangularMatrix(typename Implementation::GenerateSequence::Type(), other) {} + template constexpr explicit RectangularMatrix(const RectangularMatrix& other): RectangularMatrix(typename Implementation::GenerateSequence::Type(), other) {} #else - template inline explicit RectangularMatrix(const RectangularMatrix& other) { + template explicit RectangularMatrix(const RectangularMatrix& other) { *this = RectangularMatrix(typename Implementation::GenerateSequence::Type(), other); } #endif /** @brief Construct matrix from external representation */ #ifndef CORRADE_GCC46_COMPATIBILITY - template::from(std::declval()))> inline constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} + template::from(std::declval()))> constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} #else - template::from(std::declval()))> inline explicit RectangularMatrix(const U& other) { + template::from(std::declval()))> explicit RectangularMatrix(const U& other) { *this = Implementation::RectangularMatrixConverter::from(other); } #endif /** @brief Copy constructor */ - inline constexpr RectangularMatrix(const RectangularMatrix&) = default; + constexpr RectangularMatrix(const RectangularMatrix&) = default; /** @brief Assignment operator */ - inline RectangularMatrix& operator=(const RectangularMatrix&) = default; + RectangularMatrix& operator=(const RectangularMatrix&) = default; /** @brief Convert matrix to external representation */ - template::to(std::declval>()))> inline constexpr explicit operator U() const { + template::to(std::declval>()))> constexpr explicit operator U() const { /** @bug Why this is not constexpr under GCC 4.6? */ return Implementation::RectangularMatrixConverter::to(*this); } @@ -172,8 +165,8 @@ template class RectangularMatrix { * * @see operator[] */ - inline T* data() { return _data[0].data(); } - inline constexpr const T* data() const { return _data[0].data(); } /**< @overload */ + T* data() { return _data[0].data(); } + constexpr const T* data() const { return _data[0].data(); } /**< @overload */ /** * @brief %Matrix column @@ -186,13 +179,8 @@ template class RectangularMatrix { * * @see row(), data() */ - inline Vector& operator[](std::size_t col) { - return _data[col]; - } - /** @overload */ - inline constexpr const Vector& operator[](std::size_t col) const { - return _data[col]; - } + Vector& operator[](std::size_t col) { return _data[col]; } + constexpr const Vector& operator[](std::size_t col) const { return _data[col]; } /** @overload */ /** * @brief %Matrix row @@ -201,17 +189,10 @@ template class RectangularMatrix { * is slower than accessing columns due to the way the matrix is stored. * @see operator[]() */ - inline Vector row(std::size_t row) const { - Vector out; - - for(std::size_t i = 0; i != cols; ++i) - out[i] = _data[i][row]; - - return out; - } + Vector row(std::size_t row) const; /** @brief Equality comparison */ - inline bool operator==(const RectangularMatrix& other) const { + bool operator==(const RectangularMatrix& other) const { for(std::size_t i = 0; i != cols; ++i) if(_data[i] != other._data[i]) return false; @@ -224,10 +205,19 @@ template class RectangularMatrix { * @see Vector::operator<(), Vector::operator<=(), Vector::operator>=(), * Vector::operator>() */ - inline bool operator!=(const RectangularMatrix& other) const { + bool operator!=(const RectangularMatrix& other) const { return !operator==(other); } + /** + * @brief Negated matrix + * + * The computation is done column-wise. @f[ + * \boldsymbol B_j = -\boldsymbol A_j + * @f] + */ + RectangularMatrix operator-() const; + /** * @brief Add and assign matrix * @@ -247,26 +237,10 @@ template class RectangularMatrix { * * @see operator+=() */ - inline RectangularMatrix operator+(const RectangularMatrix& other) const { + RectangularMatrix operator+(const RectangularMatrix& other) const { return RectangularMatrix(*this)+=other; } - /** - * @brief Negated matrix - * - * The computation is done column-wise in-place. @f[ - * \boldsymbol A_j = -\boldsymbol A_j - * @f] - */ - RectangularMatrix operator-() const { - RectangularMatrix out; - - for(std::size_t i = 0; i != cols; ++i) - out._data[i] = -_data[i]; - - return out; - } - /** * @brief Subtract and assign matrix * @@ -286,7 +260,7 @@ template class RectangularMatrix { * * @see operator-=() */ - inline RectangularMatrix operator-(const RectangularMatrix& other) const { + RectangularMatrix operator-(const RectangularMatrix& other) const { return RectangularMatrix(*this)-=other; } @@ -316,7 +290,7 @@ template class RectangularMatrix { #ifndef DOXYGEN_GENERATING_OUTPUT template inline typename std::enable_if::value, RectangularMatrix>::type operator*(U number) const { #else - template inline RectangularMatrix operator*(U number) const { + template RectangularMatrix operator*(U number) const { #endif return RectangularMatrix(*this)*=number; } @@ -347,7 +321,7 @@ template class RectangularMatrix { #ifndef DOXYGEN_GENERATING_OUTPUT template inline typename std::enable_if::value, RectangularMatrix>::type operator/(U number) const { #else - template inline RectangularMatrix operator/(U number) const { + template RectangularMatrix operator/(U number) const { #endif return RectangularMatrix(*this)/=number; } @@ -359,16 +333,7 @@ template class RectangularMatrix { * (\boldsymbol {AB})_{ji} = \sum_{k=0}^{m-1} \boldsymbol A_{ki} \boldsymbol B_{jk} * @f] */ - template RectangularMatrix operator*(const RectangularMatrix& other) const { - RectangularMatrix out; - - for(std::size_t col = 0; col != size; ++col) - for(std::size_t row = 0; row != rows; ++row) - for(std::size_t pos = 0; pos != cols; ++pos) - out[col][row] += _data[pos][row]*other._data[col][pos]; - - return out; - } + template RectangularMatrix operator*(const RectangularMatrix& other) const; /** * @brief Multiply vector @@ -387,29 +352,15 @@ template class RectangularMatrix { * * @see row() */ - RectangularMatrix transposed() const { - RectangularMatrix out; - - for(std::size_t col = 0; col != cols; ++col) - for(std::size_t row = 0; row != rows; ++row) - out[row][col] = _data[col][row]; - - return out; - } + RectangularMatrix transposed() const; /** * @brief Values on diagonal * * @see fromDiagonal() + * @todo constexpr */ - Vector diagonal() const { - Vector out; - - for(std::size_t i = 0; i != DiagonalSize; ++i) - out[i] = _data[i][i]; - - return out; - } + Vector diagonal() const; /** * @brief Convert matrix to vector @@ -420,13 +371,13 @@ template class RectangularMatrix { * summing the elements etc.). * @see fromVector() */ - inline Vector toVector() const { + Vector toVector() const { return *reinterpret_cast*>(data()); } private: /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ - template inline constexpr explicit RectangularMatrix(Implementation::Sequence, const RectangularMatrix& matrix): _data{Vector(matrix[sequence])...} {} + template constexpr explicit RectangularMatrix(Implementation::Sequence, const RectangularMatrix& matrix): _data{Vector(matrix[sequence])...} {} Vector _data[cols]; }; @@ -453,9 +404,9 @@ The computation is done column-wise. @f[ @see RectangularMatrix::operator/(U) const */ #ifdef DOXYGEN_GENERATING_OUTPUT -template RectangularMatrix operator/(U number, const RectangularMatrix& matrix) { +template inline RectangularMatrix operator/(U number, const RectangularMatrix& matrix) { #else -template typename std::enable_if::value, RectangularMatrix>::type operator/(U number, const RectangularMatrix& matrix) { +template inline typename std::enable_if::value, RectangularMatrix>::type operator/(U number, const RectangularMatrix& matrix) { #endif RectangularMatrix out; @@ -522,51 +473,108 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit #endif #define MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(cols, rows, ...) \ - inline constexpr static __VA_ARGS__& from(T* data) { \ + constexpr static __VA_ARGS__& from(T* data) { \ return *reinterpret_cast<__VA_ARGS__*>(data); \ } \ - inline constexpr static const __VA_ARGS__& from(const T* data) { \ + constexpr static const __VA_ARGS__& from(const T* data) { \ return *reinterpret_cast(data); \ } \ \ - inline __VA_ARGS__& operator=(const Math::RectangularMatrix& other) { \ + __VA_ARGS__& operator=(const Math::RectangularMatrix& other) { \ Math::RectangularMatrix::operator=(other); \ return *this; \ } \ \ - inline __VA_ARGS__ operator-() const { \ + __VA_ARGS__ operator-() const { \ return Math::RectangularMatrix::operator-(); \ } \ - inline __VA_ARGS__& operator+=(const Math::RectangularMatrix& other) { \ + __VA_ARGS__& operator+=(const Math::RectangularMatrix& other) { \ Math::RectangularMatrix::operator+=(other); \ return *this; \ } \ - inline __VA_ARGS__ operator+(const Math::RectangularMatrix& other) const { \ + __VA_ARGS__ operator+(const Math::RectangularMatrix& other) const { \ return Math::RectangularMatrix::operator+(other); \ } \ - inline __VA_ARGS__& operator-=(const Math::RectangularMatrix& other) { \ + __VA_ARGS__& operator-=(const Math::RectangularMatrix& other) { \ Math::RectangularMatrix::operator-=(other); \ return *this; \ } \ - inline __VA_ARGS__ operator-(const Math::RectangularMatrix& other) const { \ + __VA_ARGS__ operator-(const Math::RectangularMatrix& other) const { \ return Math::RectangularMatrix::operator-(other); \ } \ - template inline typename std::enable_if::value, __VA_ARGS__&>::type operator*=(U number) { \ + template typename std::enable_if::value, __VA_ARGS__&>::type operator*=(U number) { \ Math::RectangularMatrix::operator*=(number); \ return *this; \ } \ - template inline typename std::enable_if::value, __VA_ARGS__>::type operator*(U number) const { \ + template typename std::enable_if::value, __VA_ARGS__>::type operator*(U number) const { \ return Math::RectangularMatrix::operator*(number); \ } \ - template inline typename std::enable_if::value, __VA_ARGS__&>::type operator/=(U number) { \ + template typename std::enable_if::value, __VA_ARGS__&>::type operator/=(U number) { \ Math::RectangularMatrix::operator/=(number); \ return *this; \ } \ - template inline typename std::enable_if::value, __VA_ARGS__>::type operator/(U number) const { \ + template typename std::enable_if::value, __VA_ARGS__>::type operator/(U number) const { \ return Math::RectangularMatrix::operator/(number); \ } #endif +template inline RectangularMatrix RectangularMatrix::fromDiagonal(const Vector& diagonal) { + RectangularMatrix out; + + for(std::size_t i = 0; i != DiagonalSize; ++i) + out[i][i] = diagonal[i]; + + return out; +} + +template inline Vector RectangularMatrix::row(std::size_t row) const { + Vector out; + + for(std::size_t i = 0; i != cols; ++i) + out[i] = _data[i][row]; + + return out; +} + +template inline RectangularMatrix RectangularMatrix::operator-() const { + RectangularMatrix out; + + for(std::size_t i = 0; i != cols; ++i) + out._data[i] = -_data[i]; + + return out; +} + +template template inline RectangularMatrix RectangularMatrix::operator*(const RectangularMatrix& other) const { + RectangularMatrix out; + + for(std::size_t col = 0; col != size; ++col) + for(std::size_t row = 0; row != rows; ++row) + for(std::size_t pos = 0; pos != cols; ++pos) + out[col][row] += _data[pos][row]*other._data[col][pos]; + + return out; +} + +template inline RectangularMatrix RectangularMatrix::transposed() const { + RectangularMatrix out; + + for(std::size_t col = 0; col != cols; ++col) + for(std::size_t row = 0; row != rows; ++row) + out[row][col] = _data[col][row]; + + return out; +} + +template auto RectangularMatrix::diagonal() const -> Vector { + Vector out; + + for(std::size_t i = 0; i != DiagonalSize; ++i) + out[i] = _data[i][i]; + + return out; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Math/Swizzle.h b/src/Math/Swizzle.h index 064023a28..1ac9746b3 100644 --- a/src/Math/Swizzle.h +++ b/src/Math/Swizzle.h @@ -36,7 +36,7 @@ namespace Implementation { template struct ComponentAtPosition { static_assert(size > position, "Swizzle parameter out of range of base vector"); - template inline constexpr static T value(const Math::Vector& vector) { return vector[position]; } + template constexpr static T value(const Math::Vector& vector) { return vector[position]; } }; template struct Component {}; @@ -45,10 +45,10 @@ namespace Implementation { template struct Component: public ComponentAtPosition {}; template struct Component: public ComponentAtPosition {}; template struct Component { - template inline constexpr static T value(const Math::Vector&) { return T(0); } + template constexpr static T value(const Math::Vector&) { return T(0); } }; template struct Component { - template inline constexpr static T value(const Math::Vector&) { return T(1); } + template constexpr static T value(const Math::Vector&) { return T(1); } }; } @@ -72,7 +72,7 @@ present in this lightweight implementation for Math namespace. @see @ref matrix-vector-component-access, Vector4::xyz(), Vector4::xy(), Vector3::xy() */ -template inline constexpr Vector swizzle(const Vector& vector) { +template constexpr Vector swizzle(const Vector& vector) { return {Implementation::Component::value(vector)...}; } diff --git a/src/Math/Test/Matrix3Test.cpp b/src/Math/Test/Matrix3Test.cpp index 6a5c91fb8..7546434ca 100644 --- a/src/Math/Test/Matrix3Test.cpp +++ b/src/Math/Test/Matrix3Test.cpp @@ -37,14 +37,14 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct RectangularMatrixConverter<3, 3, float, Mat3> { - inline constexpr static RectangularMatrix<3, 3, Float> from(const Mat3& other) { + constexpr static RectangularMatrix<3, 3, Float> from(const Mat3& other) { return RectangularMatrix<3, 3, Float>( Vector<3, Float>(other.a[0], other.a[1], other.a[2]), Vector<3, Float>(other.a[3], other.a[4], other.a[5]), Vector<3, Float>(other.a[6], other.a[7], other.a[8])); } - inline constexpr static Mat3 to(const RectangularMatrix<3, 3, Float>& other) { + constexpr static Mat3 to(const RectangularMatrix<3, 3, Float>& other) { return Mat3{{other[0][0], other[0][1], other[0][2], other[1][0], other[1][1], other[1][2], other[2][0], other[2][1], other[2][2]}}; diff --git a/src/Math/Test/Matrix4Test.cpp b/src/Math/Test/Matrix4Test.cpp index 2a18a20b0..d5bbfa70b 100644 --- a/src/Math/Test/Matrix4Test.cpp +++ b/src/Math/Test/Matrix4Test.cpp @@ -37,7 +37,7 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct RectangularMatrixConverter<4, 4, float, Mat4> { - inline constexpr static RectangularMatrix<4, 4, Float> from(const Mat4& other) { + constexpr static RectangularMatrix<4, 4, Float> from(const Mat4& other) { return RectangularMatrix<4, 4, Float>( Vector<4, Float>(other.a[0], other.a[1], other.a[2], other.a[3]), Vector<4, Float>(other.a[4], other.a[5], other.a[6], other.a[7]), @@ -45,7 +45,7 @@ template<> struct RectangularMatrixConverter<4, 4, float, Mat4> { Vector<4, Float>(other.a[12], other.a[13], other.a[14], other.a[15])); } - inline constexpr static Mat4 to(const RectangularMatrix<4, 4, Float>& other) { + constexpr static Mat4 to(const RectangularMatrix<4, 4, Float>& other) { return Mat4{{other[0][0], other[0][1], other[0][2], other[0][3], other[1][0], other[1][1], other[1][2], other[1][3], other[2][0], other[2][1], other[2][2], other[2][3], diff --git a/src/Math/Test/MatrixTest.cpp b/src/Math/Test/MatrixTest.cpp index efc2282cc..9dfa54457 100644 --- a/src/Math/Test/MatrixTest.cpp +++ b/src/Math/Test/MatrixTest.cpp @@ -37,14 +37,14 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct RectangularMatrixConverter<3, 3, float, Mat3> { - inline constexpr static RectangularMatrix<3, 3, Float> from(const Mat3& other) { + constexpr static RectangularMatrix<3, 3, Float> from(const Mat3& other) { return RectangularMatrix<3, 3, Float>( Vector<3, Float>(other.a[0], other.a[1], other.a[2]), Vector<3, Float>(other.a[3], other.a[4], other.a[5]), Vector<3, Float>(other.a[6], other.a[7], other.a[8])); } - inline constexpr static Mat3 to(const RectangularMatrix<3, 3, Float>& other) { + constexpr static Mat3 to(const RectangularMatrix<3, 3, Float>& other) { return Mat3{{other[0][0], other[0][1], other[0][2], other[1][0], other[1][1], other[1][2], other[2][0], other[2][1], other[2][2]}}; diff --git a/src/Math/Test/RectangularMatrixTest.cpp b/src/Math/Test/RectangularMatrixTest.cpp index e05e2e036..1062015b9 100644 --- a/src/Math/Test/RectangularMatrixTest.cpp +++ b/src/Math/Test/RectangularMatrixTest.cpp @@ -37,13 +37,13 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct RectangularMatrixConverter<2, 3, float, Mat2x3> { - inline constexpr static RectangularMatrix<2, 3, Float> from(const Mat2x3& other) { + constexpr static RectangularMatrix<2, 3, Float> from(const Mat2x3& other) { return RectangularMatrix<2, 3, Float>( Vector<3, Float>(other.a[0], other.a[1], other.a[2]), Vector<3, Float>(other.a[3], other.a[4], other.a[5])); } - inline constexpr static Mat2x3 to(const RectangularMatrix<2, 3, Float>& other) { + constexpr static Mat2x3 to(const RectangularMatrix<2, 3, Float>& other) { return Mat2x3{{other[0][0], other[0][1], other[0][2], other[1][0], other[1][1], other[1][2]}}; } diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index 0d8aa7691..3daa43ef4 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -37,11 +37,11 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct VectorConverter<2, float, Vec2> { - inline constexpr static Vector<2, float> from(const Vec2& other) { + constexpr static Vector<2, float> from(const Vec2& other) { return {other.x, other.y}; } - inline constexpr static Vec2 to(const Vector<2, float>& other) { + constexpr static Vec2 to(const Vector<2, float>& other) { return {other[0], other[1]}; } }; diff --git a/src/Math/Test/Vector3Test.cpp b/src/Math/Test/Vector3Test.cpp index 586bc4e9a..dcbde0ae2 100644 --- a/src/Math/Test/Vector3Test.cpp +++ b/src/Math/Test/Vector3Test.cpp @@ -37,11 +37,11 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct VectorConverter<3, float, Vec3> { - inline constexpr static Vector<3, Float> from(const Vec3& other) { + constexpr static Vector<3, Float> from(const Vec3& other) { return {other.x, other.y, other.z}; } - inline constexpr static Vec3 to(const Vector<3, Float>& other) { + constexpr static Vec3 to(const Vector<3, Float>& other) { return {other[0], other[1], other[2]}; } }; diff --git a/src/Math/Test/Vector4Test.cpp b/src/Math/Test/Vector4Test.cpp index 447215890..1913b3fdb 100644 --- a/src/Math/Test/Vector4Test.cpp +++ b/src/Math/Test/Vector4Test.cpp @@ -37,11 +37,11 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct VectorConverter<4, float, Vec4> { - inline constexpr static Vector<4, Float> from(const Vec4& other) { + constexpr static Vector<4, Float> from(const Vec4& other) { return {other.x, other.y, other.z, other.w}; } - inline constexpr static Vec4 to(const Vector<4, Float>& other) { + constexpr static Vec4 to(const Vector<4, Float>& other) { return {other[0], other[1], other[2], other[3]}; } }; diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index 1cfb76ffb..71e98edb2 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -37,11 +37,11 @@ namespace Magnum { namespace Math { namespace Implementation { template<> struct VectorConverter<3, float, Vec3> { - inline constexpr static Vector<3, Float> from(const Vec3& other) { + constexpr static Vector<3, Float> from(const Vec3& other) { return {other.x, other.y, other.z}; } - inline constexpr static Vec3 to(const Vector<3, Float>& other) { + constexpr static Vec3 to(const Vector<3, Float>& other) { return {other[0], other[1], other[2]}; } }; diff --git a/src/Math/TypeTraits.h b/src/Math/TypeTraits.h index 136083681..217e2275d 100644 --- a/src/Math/TypeTraits.h +++ b/src/Math/TypeTraits.h @@ -56,7 +56,7 @@ namespace Implementation { template struct TypeTraitsDefault { TypeTraitsDefault() = delete; - inline constexpr static bool equals(T a, T b) { + constexpr static bool equals(T a, T b) { return a == b; } }; @@ -93,7 +93,7 @@ template struct TypeTraits: Implementation::TypeTraitsDefault { * inequal. Returns 1 for integer types and reasonably small value for * floating-point types. Not implemented for arbitrary types. */ - inline constexpr static T epsilon(); + constexpr static T epsilon(); /** * @brief Fuzzy compare @@ -116,7 +116,7 @@ template struct TypeTraits: Implementation::TypeTraitsDefault { /* Integral scalar types */ namespace Implementation { template struct TypeTraitsIntegral: TypeTraitsDefault { - inline constexpr static T epsilon() { return T(1); } + constexpr static T epsilon() { return T(1); } }; } @@ -159,7 +159,7 @@ namespace Implementation { template struct TypeTraitsFloatingPoint { TypeTraitsFloatingPoint() = delete; - inline static bool equals(T a, T b) { + static bool equals(T a, T b) { return std::abs(a - b) < TypeTraits::epsilon(); } }; @@ -168,19 +168,19 @@ namespace Implementation { template<> struct TypeTraits: Implementation::TypeTraitsFloatingPoint { typedef Float FloatingPointType; - inline constexpr static Float epsilon() { return FLOAT_EQUALITY_PRECISION; } + constexpr static Float epsilon() { return FLOAT_EQUALITY_PRECISION; } }; #ifndef MAGNUM_TARGET_GLES template<> struct TypeTraits: Implementation::TypeTraitsFloatingPoint { typedef Double FloatingPointType; - inline constexpr static Double epsilon() { return DOUBLE_EQUALITY_PRECISION; } + constexpr static Double epsilon() { return DOUBLE_EQUALITY_PRECISION; } }; #endif template<> struct TypeTraits: Implementation::TypeTraitsFloatingPoint { typedef long double FloatingPointType; - inline constexpr static long double epsilon() { return LONG_DOUBLE_EQUALITY_PRECISION; } + constexpr static long double epsilon() { return LONG_DOUBLE_EQUALITY_PRECISION; } }; /* Comparing squared length to 1 is not sufficient to compare within range diff --git a/src/Math/Unit.h b/src/Math/Unit.h index 7a586ec6e..6f4cecb4b 100644 --- a/src/Math/Unit.h +++ b/src/Math/Unit.h @@ -45,98 +45,98 @@ template class Derived, class T> class Unit { typedef T Type; /**< @brief Underlying data type */ /** @brief Default constructor */ - inline constexpr /*implicit*/ Unit(): value(T(0)) {} + constexpr /*implicit*/ Unit(): value(T(0)) {} /** @brief Explicit conversion from unitless type */ - inline constexpr explicit Unit(T value): value(value) {} + constexpr explicit Unit(T value): value(value) {} /** @brief Construct from another underlying type */ - template inline constexpr explicit Unit(Unit value): value(value.value) {} + template constexpr explicit Unit(Unit value): value(value.value) {} /** @brief Explicit conversion to underlying type */ - inline constexpr explicit operator T() const { return value; } + constexpr explicit operator T() const { return value; } /** @brief Equality comparison */ - inline constexpr bool operator==(Unit other) const { + constexpr bool operator==(Unit other) const { return TypeTraits::equals(value, other.value); } /** @brief Non-equality comparison */ - inline constexpr bool operator!=(Unit other) const { + constexpr bool operator!=(Unit other) const { return !operator==(other); } /** @brief Less than comparison */ - inline constexpr bool operator<(Unit other) const { + constexpr bool operator<(Unit other) const { return value < other.value; } /** @brief Greater than comparison */ - inline constexpr bool operator>(Unit other) const { + constexpr bool operator>(Unit other) const { return value > other.value; } /** @brief Less than or equal comparison */ - inline constexpr bool operator<=(Unit other) const { + constexpr bool operator<=(Unit other) const { return !operator>(other); } /** @brief Greater than or equal comparison */ - inline constexpr bool operator>=(Unit other) const { + constexpr bool operator>=(Unit other) const { return !operator<(other); } /** @brief Negated value */ - inline constexpr Unit operator-() const { + constexpr Unit operator-() const { return Unit(-value); } /** @brief Add and assign value */ - inline Unit& operator+=(Unit other) { + Unit& operator+=(Unit other) { value += other.value; return *this; } /** @brief Add value */ - inline constexpr Unit operator+(Unit other) const { + constexpr Unit operator+(Unit other) const { return Unit(value + other.value); } /** @brief Subtract and assign value */ - inline Unit& operator-=(Unit other) { + Unit& operator-=(Unit other) { value -= other.value; return *this; } /** @brief Subtract value */ - inline constexpr Unit operator-(Unit other) const { + constexpr Unit operator-(Unit other) const { return Unit(value - other.value); } /** @brief Multiply with number and assign */ - inline Unit& operator*=(T number) { + Unit& operator*=(T number) { value *= number; return *this; } /** @brief Multiply with number */ - inline constexpr Unit operator*(T number) const { + constexpr Unit operator*(T number) const { return Unit(value*number); } /** @brief Divide with number and assign */ - inline Unit& operator/=(T number) { + Unit& operator/=(T number) { value /= number; return *this; } /** @brief Divide with number */ - inline constexpr Unit operator/(T number) const { + constexpr Unit operator/(T number) const { return Unit(value/number); } /** @brief Ratio of two values */ - inline constexpr T operator/(Unit other) const { + constexpr T operator/(Unit other) const { return value/other.value; } @@ -147,7 +147,7 @@ template class Derived, class T> class Unit { /** @relates Unit @brief Multiply number with value */ -template class Derived, class T> inline constexpr Unit operator*(typename std::common_type::type number, const Unit& value) { +template class Derived, class T> constexpr Unit operator*(typename std::common_type::type number, const Unit& value) { return value*number; } diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 6e6a55c40..353986936 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -71,11 +71,11 @@ template class Vector { * @attention Use with caution, the function doesn't check whether the * array is long enough. */ - inline constexpr static Vector& from(T* data) { + constexpr static Vector& from(T* data) { return *reinterpret_cast*>(data); } /** @overload */ - inline constexpr static const Vector& from(const T* data) { + constexpr static const Vector& from(const T* data) { return *reinterpret_cast*>(data); } @@ -89,7 +89,7 @@ template class Vector { * @f] * @see dot() const, operator-(), Vector2::perpendicular() */ - inline static T dot(const Vector& a, const Vector& b) { + static T dot(const Vector& a, const Vector& b) { return (a*b).sum(); } @@ -101,11 +101,7 @@ template class Vector { * @f] * @see isNormalized(), Quaternion::angle(), Complex::angle() */ - inline static Rad angle(const Vector& normalizedA, const Vector& normalizedB) { - CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), - "Math::Vector::angle(): vectors must be normalized", Rad(std::numeric_limits::quiet_NaN())); - return Rad(std::acos(dot(normalizedA, normalizedB))); - } + static Rad angle(const Vector& normalizedA, const Vector& normalizedB); /** * @brief Default constructor @@ -114,7 +110,7 @@ template class Vector { * \boldsymbol v = \boldsymbol 0 * @f] */ - inline constexpr /*implicit*/ Vector(): _data() {} + constexpr /*implicit*/ Vector(): _data() {} /** @todo Creating Vector from combination of vector and scalar types */ @@ -124,19 +120,19 @@ template class Vector { * @param next Next values */ #ifdef DOXYGEN_GENERATING_OUTPUT - template inline constexpr /*implicit*/ Vector(T first, U... next); + template constexpr /*implicit*/ Vector(T first, U... next); #else - template::type> inline constexpr /*implicit*/ Vector(T first, U... next): _data{first, next...} {} + template::type> constexpr /*implicit*/ Vector(T first, U... next): _data{first, next...} {} #endif /** @brief Construct vector with one value for all fields */ #ifdef DOXYGEN_GENERATING_OUTPUT - inline explicit Vector(T value); + constexpr explicit Vector(T value); #else #ifndef CORRADE_GCC46_COMPATIBILITY - template::value && size != 1, T>::type> inline constexpr explicit Vector(U value): Vector(typename Implementation::GenerateSequence::Type(), value) {} + template::value && size != 1, T>::type> constexpr explicit Vector(U value): Vector(typename Implementation::GenerateSequence::Type(), value) {} #else - template::value && size != 1, T>::type> inline explicit Vector(U value) { + template::value && size != 1, T>::type> explicit Vector(U value) { *this = Vector(typename Implementation::GenerateSequence::Type(), value); } #endif @@ -154,30 +150,30 @@ template class Vector { * @endcode */ #ifndef CORRADE_GCC46_COMPATIBILITY - template inline constexpr explicit Vector(const Vector& other): Vector(typename Implementation::GenerateSequence::Type(), other) {} + template constexpr explicit Vector(const Vector& other): Vector(typename Implementation::GenerateSequence::Type(), other) {} #else - template inline explicit Vector(const Vector& other) { + template explicit Vector(const Vector& other) { *this = Vector(typename Implementation::GenerateSequence::Type(), other); } #endif /** @brief Construct vector from external representation */ #ifndef CORRADE_GCC46_COMPATIBILITY - template::from(std::declval()))> inline constexpr explicit Vector(const U& other): Vector(Implementation::VectorConverter::from(other)) {} + template::from(std::declval()))> constexpr explicit Vector(const U& other): Vector(Implementation::VectorConverter::from(other)) {} #else - template::from(std::declval()))> inline explicit Vector(const U& other) { + template::from(std::declval()))> explicit Vector(const U& other) { *this = Implementation::VectorConverter::from(other); } #endif /** @brief Copy constructor */ - inline constexpr Vector(const Vector&) = default; + constexpr Vector(const Vector&) = default; /** @brief Assignment operator */ - inline Vector& operator=(const Vector&) = default; + Vector& operator=(const Vector&) = default; /** @brief Convert vector to external representation */ - template::to(std::declval>()))> inline constexpr explicit operator U() const { + template::to(std::declval>()))> constexpr explicit operator U() const { /** @bug Why this is not constexpr under GCC 4.6? */ return Implementation::VectorConverter::to(*this); } @@ -188,19 +184,19 @@ template class Vector { * * @see operator[]() */ - inline T* data() { return _data; } - inline constexpr const T* data() const { return _data; } /**< @overload */ + T* data() { return _data; } + constexpr const T* data() const { return _data; } /**< @overload */ /** * @brief Value at given position * * @see data() */ - inline T& operator[](std::size_t pos) { return _data[pos]; } - inline constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */ + T& operator[](std::size_t pos) { return _data[pos]; } + constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */ /** @brief Equality comparison */ - inline bool operator==(const Vector& other) const { + bool operator==(const Vector& other) const { for(std::size_t i = 0; i != size; ++i) if(!TypeTraits::equals(_data[i], other._data[i])) return false; @@ -208,49 +204,21 @@ template class Vector { } /** @brief Non-equality comparison */ - inline bool operator!=(const Vector& other) const { + bool operator!=(const Vector& other) const { return !operator==(other); } /** @brief Component-wise less than */ - inline BoolVector operator<(const Vector& other) const { - BoolVector out; - - for(std::size_t i = 0; i != size; ++i) - out.set(i, _data[i] < other._data[i]); - - return out; - } + BoolVector operator<(const Vector& other) const; /** @brief Component-wise less than or equal */ - inline BoolVector operator<=(const Vector& other) const { - BoolVector out; - - for(std::size_t i = 0; i != size; ++i) - out.set(i, _data[i] <= other._data[i]); - - return out; - } + BoolVector operator<=(const Vector& other) const; /** @brief Component-wise greater than or equal */ - inline BoolVector operator>=(const Vector& other) const { - BoolVector out; - - for(std::size_t i = 0; i != size; ++i) - out.set(i, _data[i] >= other._data[i]); - - return out; - } + BoolVector operator>=(const Vector& other) const; /** @brief Component-wise greater than */ - inline BoolVector operator>(const Vector& other) const { - BoolVector out; - - for(std::size_t i = 0; i != size; ++i) - out.set(i, _data[i] > other._data[i]); - - return out; - } + BoolVector operator>(const Vector& other) const; /** * @brief Whether the vector is normalized @@ -260,26 +228,19 @@ template class Vector { * @f] * @see dot(), normalized() */ - inline bool isNormalized() const { + bool isNormalized() const { return Implementation::isNormalizedSquared(dot()); } /** * @brief Negated vector * - * The computation is done in-place. @f[ - * \boldsymbol a_i = -\boldsymbol a_i + * @f[ + * \boldsymbol b_i = -\boldsymbol a_i * @f] * @see Vector2::perpendicular() */ - Vector operator-() const { - Vector out; - - for(std::size_t i = 0; i != size; ++i) - out._data[i] = -_data[i]; - - return out; - } + Vector operator-() const; /** * @brief Add and assign vector @@ -300,7 +261,7 @@ template class Vector { * * @see operator+=(), sum() */ - inline Vector operator+(const Vector& other) const { + Vector operator+(const Vector& other) const { return Vector(*this) += other; } @@ -323,7 +284,7 @@ template class Vector { * * @see operator-=() */ - inline Vector operator-(const Vector& other) const { + Vector operator-(const Vector& other) const { return Vector(*this) -= other; } @@ -337,7 +298,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT template Vector& operator*=(U number) { #else - template inline typename std::enable_if::value, Vector&>::type operator*=(U number) { + template typename std::enable_if::value, Vector&>::type operator*=(U number) { #endif for(std::size_t i = 0; i != size; ++i) _data[i] *= number; @@ -351,9 +312,9 @@ template class Vector { * @see operator*=(U), operator*(U, const Vector&) */ #ifdef DOXYGEN_GENERATING_OUTPUT - template inline Vector operator*(U number) const { + template Vector operator*(U number) const { #else - template inline typename std::enable_if::value, Vector>::type operator*(U number) const { + template typename std::enable_if::value, Vector>::type operator*(U number) const { #endif return Vector(*this) *= number; } @@ -368,7 +329,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT template Vector& operator/=(U number) { #else - template inline typename std::enable_if::value, Vector&>::type operator/=(U number) { + template typename std::enable_if::value, Vector&>::type operator/=(U number) { #endif for(std::size_t i = 0; i != size; ++i) _data[i] /= number; @@ -382,9 +343,9 @@ template class Vector { * @see operator/=(), operator/(U, const Vector&) */ #ifdef DOXYGEN_GENERATING_OUTPUT - template inline Vector operator/(U number) const { + template Vector operator/(U number) const { #else - template inline typename std::enable_if::value, Vector>::type operator/(U number) const { + template typename std::enable_if::value, Vector>::type operator/(U number) const { #endif return Vector(*this) /= number; } @@ -408,7 +369,7 @@ template class Vector { * * @see operator*=(const Vector&), product() */ - template inline Vector operator*(const Vector& other) const { + template Vector operator*(const Vector& other) const { return Vector(*this) *= other; } @@ -431,7 +392,7 @@ template class Vector { * * @see operator/=(const Vector&) */ - template inline Vector operator/(const Vector& other) const { + template Vector operator/(const Vector& other) const { return Vector(*this) /= other; } @@ -444,9 +405,7 @@ template class Vector { * @f] * @see dot(const Vector&, const Vector&), isNormalized() */ - inline T dot() const { - return dot(*this, *this); - } + T dot() const { return dot(*this, *this); } /** * @brief %Vector length @@ -458,9 +417,7 @@ template class Vector { * @see lengthInverted(), Math::sqrt(), normalized(), resized() * @todo something like std::hypot() for possibly better precision? */ - inline T length() const { - return std::sqrt(dot()); - } + T length() const { return std::sqrt(dot()); } /** * @brief Inverse vector length @@ -470,18 +427,14 @@ template class Vector { * @f] * @see length(), Math::sqrtInverted(), normalized(), resized() */ - inline T lengthInverted() const { - return T(1)/length(); - } + T lengthInverted() const { return T(1)/length(); } /** * @brief Normalized vector (of unit length) * * @see isNormalized(), lengthInverted(), resized() */ - inline Vector normalized() const { - return *this*lengthInverted(); - } + Vector normalized() const { return *this*lengthInverted(); } /** * @brief Resized vector @@ -494,7 +447,7 @@ template class Vector { * @endcode * @see normalized() */ - inline Vector resized(T length) const { + Vector resized(T length) const { return *this*(lengthInverted()*length); } @@ -506,7 +459,7 @@ template class Vector { * @f] * @see dot(), projectedOntoNormalized() */ - inline Vector projected(const Vector& line) const { + Vector projected(const Vector& line) const { return line*dot(*this, line)/line.dot(); } @@ -520,73 +473,42 @@ template class Vector { * @f] * @see dot() */ - inline Vector projectedOntoNormalized(const Vector& line) const { - CORRADE_ASSERT(line.isNormalized(), "Math::Vector::projectedOntoNormalized(): line must be normalized", (Vector(std::numeric_limits::quiet_NaN()))); - return line*dot(*this, line); - } + Vector projectedOntoNormalized(const Vector& line) const; /** * @brief Sum of values in the vector * * @see operator+() */ - T sum() const { - T out(_data[0]); - - for(std::size_t i = 1; i != size; ++i) - out += _data[i]; - - return out; - } + T sum() const; /** * @brief Product of values in the vector * * @see operator*(const Vector&) */ - T product() const { - T out(_data[0]); - - for(std::size_t i = 1; i != size; ++i) - out *= _data[i]; - - return out; - } + T product() const; /** * @brief Minimal value in the vector * * @see Math::min() */ - T min() const { - T out(_data[0]); - - for(std::size_t i = 1; i != size; ++i) - out = std::min(out, _data[i]); - - return out; - } + T min() const; /** * @brief Maximal value in the vector * * @see Math::max() */ - T max() const { - T out(_data[0]); - - for(std::size_t i = 1; i != size; ++i) - out = std::max(out, _data[i]); - - return out; - } + T max() const; private: /* Implementation for Vector::Vector(const Vector&) */ - template inline constexpr explicit Vector(Implementation::Sequence, const Vector& vector): _data{T(vector._data[sequence])...} {} + template constexpr explicit Vector(Implementation::Sequence, const Vector& vector): _data{T(vector._data[sequence])...} {} /* Implementation for Vector::Vector(U) */ - template inline constexpr explicit Vector(Implementation::Sequence, T value): _data{Implementation::repeat(value, sequence)...} {} + template constexpr explicit Vector(Implementation::Sequence, T value): _data{Implementation::repeat(value, sequence)...} {} T _data[size]; }; @@ -658,71 +580,71 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit #ifndef DOXYGEN_GENERATING_OUTPUT #define MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Type, size) \ - inline constexpr static Type& from(T* data) { \ + constexpr static Type& from(T* data) { \ return *reinterpret_cast*>(data); \ } \ - inline constexpr static const Type& from(const T* data) { \ + constexpr static const Type& from(const T* data) { \ return *reinterpret_cast*>(data); \ } \ \ - inline Type& operator=(const Type& other) { \ + Type& operator=(const Type& other) { \ Math::Vector::operator=(other); \ return *this; \ } \ \ - inline Type operator-() const { \ + Type operator-() const { \ return Math::Vector::operator-(); \ } \ - inline Type& operator+=(const Math::Vector& other) { \ + Type& operator+=(const Math::Vector& other) { \ Math::Vector::operator+=(other); \ return *this; \ } \ - inline Type operator+(const Math::Vector& other) const { \ + Type operator+(const Math::Vector& other) const { \ return Math::Vector::operator+(other); \ } \ - inline Type& operator-=(const Math::Vector& other) { \ + Type& operator-=(const Math::Vector& other) { \ Math::Vector::operator-=(other); \ return *this; \ } \ - inline Type operator-(const Math::Vector& other) const { \ + Type operator-(const Math::Vector& other) const { \ return Math::Vector::operator-(other); \ } \ - template inline typename std::enable_if::value, Type&>::type operator*=(U number) { \ + template typename std::enable_if::value, Type&>::type operator*=(U number) { \ Math::Vector::operator*=(number); \ return *this; \ } \ - template inline typename std::enable_if::value, Type>::type operator*(U number) const { \ + template typename std::enable_if::value, Type>::type operator*(U number) const { \ return Math::Vector::operator*(number); \ } \ - template inline typename std::enable_if::value, Type&>::type operator/=(U number) { \ + template typename std::enable_if::value, Type&>::type operator/=(U number) { \ Math::Vector::operator/=(number); \ return *this; \ } \ - template inline typename std::enable_if::value, Type>::type operator/(U number) const { \ + template typename std::enable_if::value, Type>::type operator/(U number) const { \ return Math::Vector::operator/(number); \ } \ - template inline Type& operator*=(const Math::Vector& other) { \ + template Type& operator*=(const Math::Vector& other) { \ Math::Vector::operator*=(other); \ return *this; \ } \ - template inline Type operator*(const Math::Vector& other) const { \ + template Type operator*(const Math::Vector& other) const { \ return Math::Vector::operator*(other); \ } \ - template inline Type& operator/=(const Math::Vector& other) { \ + template Type& operator/=(const Math::Vector& other) { \ Math::Vector::operator/=(other); \ return *this; \ } \ - template inline Type operator/(const Math::Vector& other) const { \ + template Type operator/(const Math::Vector& other) const { \ return Math::Vector::operator/(other); \ } \ \ - inline Type normalized() const { \ + Type normalized() const { \ return Math::Vector::normalized(); \ } \ - inline Type resized(T length) const { \ + Type resized(T length) const { \ return Math::Vector::resized(length); \ } \ - inline Type projected(const Math::Vector& other) const { \ + Type projected(const Math::Vector& other) const { \ return Math::Vector::projected(other); \ } @@ -735,6 +657,99 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit } #endif +template inline Rad Vector::angle(const Vector& normalizedA, const Vector& normalizedB) { + CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), + "Math::Vector::angle(): vectors must be normalized", Rad(std::numeric_limits::quiet_NaN())); + return Rad(std::acos(dot(normalizedA, normalizedB))); +} + +template inline BoolVector Vector::operator<(const Vector& other) const { + BoolVector out; + + for(std::size_t i = 0; i != size; ++i) + out.set(i, _data[i] < other._data[i]); + + return out; +} + +template inline BoolVector Vector::operator<=(const Vector& other) const { + BoolVector out; + + for(std::size_t i = 0; i != size; ++i) + out.set(i, _data[i] <= other._data[i]); + + return out; +} + +template inline BoolVector Vector::operator>=(const Vector& other) const { + BoolVector out; + + for(std::size_t i = 0; i != size; ++i) + out.set(i, _data[i] >= other._data[i]); + + return out; +} + +template inline BoolVector Vector::operator>(const Vector& other) const { + BoolVector out; + + for(std::size_t i = 0; i != size; ++i) + out.set(i, _data[i] > other._data[i]); + + return out; +} + +template inline Vector Vector::operator-() const { + Vector out; + + for(std::size_t i = 0; i != size; ++i) + out._data[i] = -_data[i]; + + return out; +} + +template inline Vector Vector::projectedOntoNormalized(const Vector& line) const { + CORRADE_ASSERT(line.isNormalized(), "Math::Vector::projectedOntoNormalized(): line must be normalized", + (Vector(std::numeric_limits::quiet_NaN()))); + return line*dot(*this, line); +} + +template inline T Vector::sum() const { + T out(_data[0]); + + for(std::size_t i = 1; i != size; ++i) + out += _data[i]; + + return out; +} + +template inline T Vector::product() const { + T out(_data[0]); + + for(std::size_t i = 1; i != size; ++i) + out *= _data[i]; + + return out; +} + +template inline T Vector::min() const { + T out(_data[0]); + + for(std::size_t i = 1; i != size; ++i) + out = std::min(out, _data[i]); + + return out; +} + +template inline T Vector::max() const { + T out(_data[0]); + + for(std::size_t i = 1; i != size; ++i) + out = std::max(out, _data[i]); + + return out; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 655fbd235..3f1b5a9dc 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -51,7 +51,7 @@ template class Vector2: public Vector<2, T> { * @endcode * @see yAxis(), xScale(), Matrix3::right() */ - inline constexpr static Vector2 xAxis(T length = T(1)) { return Vector2(length, T()); } + constexpr static Vector2 xAxis(T length = T(1)) { return Vector2(length, T()); } /** * @brief %Vector in direction of Y axis (up) @@ -59,7 +59,7 @@ template class Vector2: public Vector<2, T> { * See xAxis() for more information. * @see yScale(), Matrix3::up() */ - inline constexpr static Vector2 yAxis(T length = T(1)) { return Vector2(T(), length); } + constexpr static Vector2 yAxis(T length = T(1)) { return Vector2(T(), length); } /** * @brief Scaling vector in direction of X axis (width) @@ -70,7 +70,7 @@ template class Vector2: public Vector<2, T> { * @endcode * @see yScale(), xAxis() */ - inline constexpr static Vector2 xScale(T scale) { return Vector2(scale, T(1)); } + constexpr static Vector2 xScale(T scale) { return Vector2(scale, T(1)); } /** * @brief Scaling vector in direction of Y axis (height) @@ -78,7 +78,7 @@ template class Vector2: public Vector<2, T> { * See xScale() for more information. * @see yAxis() */ - inline constexpr static Vector2 yScale(T scale) { return Vector2(T(1), scale); } + constexpr static Vector2 yScale(T scale) { return Vector2(T(1), scale); } /** * @brief 2D cross product @@ -91,15 +91,15 @@ template class Vector2: public Vector<2, T> { * @f] * @see perpendicular(), dot(const Vector&, const Vector&) */ - inline static T cross(const Vector2& a, const Vector2& b) { + static T cross(const Vector2& a, const Vector2& b) { return Vector<2, T>::dot(a.perpendicular(), b); } /** @copydoc Vector::Vector() */ - inline constexpr /*implicit*/ Vector2() {} + constexpr /*implicit*/ Vector2() {} /** @copydoc Vector::Vector(T) */ - inline constexpr explicit Vector2(T value): Vector<2, T>(value) {} + constexpr explicit Vector2(T value): Vector<2, T>(value) {} /** * @brief Constructor @@ -108,21 +108,21 @@ template class Vector2: public Vector<2, T> { * \boldsymbol v = \begin{pmatrix} x \\ y \end{pmatrix} * @f] */ - inline constexpr /*implicit*/ Vector2(T x, T y): Vector<2, T>(x, y) {} + constexpr /*implicit*/ Vector2(T x, T y): Vector<2, T>(x, y) {} /** @copydoc Vector::Vector(const Vector&) */ - template inline constexpr explicit Vector2(const Vector<2, U>& other): Vector<2, T>(other) {} + template constexpr explicit Vector2(const Vector<2, U>& other): Vector<2, T>(other) {} /** @brief Construct vector from external representation */ - template::from(std::declval()))> inline constexpr explicit Vector2(const U& other): Vector<2, T>(Implementation::VectorConverter<2, T, U>::from(other)) {} + template::from(std::declval()))> constexpr explicit Vector2(const U& other): Vector<2, T>(Implementation::VectorConverter<2, T, U>::from(other)) {} /** @brief Copy constructor */ - inline constexpr Vector2(const Vector<2, T>& other): Vector<2, T>(other) {} + constexpr Vector2(const Vector<2, T>& other): Vector<2, T>(other) {} - inline T& x() { return (*this)[0]; } /**< @brief X component */ - inline constexpr T x() const { return (*this)[0]; } /**< @overload */ - inline T& y() { return (*this)[1]; } /**< @brief Y component */ - inline constexpr T y() const { return (*this)[1]; } /**< @overload */ + T& x() { return (*this)[0]; } /**< @brief X component */ + constexpr T x() const { return (*this)[0]; } /**< @overload */ + T& y() { return (*this)[1]; } /**< @brief Y component */ + constexpr T y() const { return (*this)[1]; } /**< @overload */ /** * @brief Perpendicular vector @@ -132,7 +132,7 @@ template class Vector2: public Vector<2, T> { * @f] * @see cross(), dot(const Vector&, const Vector&), operator-() const */ - inline Vector2 perpendicular() const { return {-y(), x()}; } + Vector2 perpendicular() const { return {-y(), x()}; } MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector2, 2) }; diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 933d11591..ad0beff03 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -53,7 +53,7 @@ template class Vector3: public Vector<3, T> { * @endcode * @see yAxis(), zAxis(), xScale(), Matrix4::right() */ - inline constexpr static Vector3 xAxis(T length = T(1)) { return Vector3(length, T(), T()); } + constexpr static Vector3 xAxis(T length = T(1)) { return Vector3(length, T(), T()); } /** * @brief %Vector in direction of Y axis (up) @@ -61,7 +61,7 @@ template class Vector3: public Vector<3, T> { * See xAxis() for more information. * @see yScale(), Matrix4::up() */ - inline constexpr static Vector3 yAxis(T length = T(1)) { return Vector3(T(), length, T()); } + constexpr static Vector3 yAxis(T length = T(1)) { return Vector3(T(), length, T()); } /** * @brief %Vector in direction of Z axis (backward) @@ -69,7 +69,7 @@ template class Vector3: public Vector<3, T> { * See xAxis() for more information. * @see zScale(), Matrix4::backward() */ - inline constexpr static Vector3 zAxis(T length = T(1)) { return Vector3(T(), T(), length); } + constexpr static Vector3 zAxis(T length = T(1)) { return Vector3(T(), T(), length); } /** * @brief Scaling vector in direction of X axis (width) @@ -80,7 +80,7 @@ template class Vector3: public Vector<3, T> { * @endcode * @see yScale(), zScale(), xAxis() */ - inline constexpr static Vector3 xScale(T scale) { return Vector3(scale, T(1), T(1)); } + constexpr static Vector3 xScale(T scale) { return Vector3(scale, T(1), T(1)); } /** * @brief Scaling vector in direction of Y axis (height) @@ -88,7 +88,7 @@ template class Vector3: public Vector<3, T> { * See xScale() for more information. * @see yAxis() */ - inline constexpr static Vector3 yScale(T scale) { return Vector3(T(1), scale, T(1)); } + constexpr static Vector3 yScale(T scale) { return Vector3(T(1), scale, T(1)); } /** * @brief Scaling vector in direction of Z axis (depth) @@ -96,7 +96,7 @@ template class Vector3: public Vector<3, T> { * See xScale() for more information. * @see zAxis() */ - inline constexpr static Vector3 zScale(T scale) { return Vector3(T(1), T(1), scale); } + constexpr static Vector3 zScale(T scale) { return Vector3(T(1), T(1), scale); } /** * @brief Cross product @@ -107,16 +107,16 @@ template class Vector3: public Vector<3, T> { * @f] * @see Vector2::cross() */ - inline static Vector3 cross(const Vector3& a, const Vector3& b) { + static Vector3 cross(const Vector3& a, const Vector3& b) { return swizzle<'y', 'z', 'x'>(a)*swizzle<'z', 'x', 'y'>(b) - swizzle<'z', 'x', 'y'>(a)*swizzle<'y', 'z', 'x'>(b); } /** @copydoc Vector::Vector() */ - inline constexpr /*implicit*/ Vector3() {} + constexpr /*implicit*/ Vector3() {} /** @copydoc Vector::Vector(T) */ - inline constexpr explicit Vector3(T value): Vector<3, T>(value) {} + constexpr explicit Vector3(T value): Vector<3, T>(value) {} /** * @brief Constructor @@ -125,7 +125,7 @@ template class Vector3: public Vector<3, T> { * \boldsymbol v = \begin{pmatrix} x \\ y \\ z \end{pmatrix} * @f] */ - inline constexpr /*implicit*/ Vector3(T x, T y, T z): Vector<3, T>(x, y, z) {} + constexpr /*implicit*/ Vector3(T x, T y, T z): Vector<3, T>(x, y, z) {} /** * @brief Constructor @@ -134,23 +134,23 @@ template class Vector3: public Vector<3, T> { * \boldsymbol v = \begin{pmatrix} v_x \\ v_y \\ z \end{pmatrix} * @f] */ - inline constexpr /*implicit*/ Vector3(const Vector2& xy, T z): Vector<3, T>(xy[0], xy[1], z) {} + constexpr /*implicit*/ Vector3(const Vector2& xy, T z): Vector<3, T>(xy[0], xy[1], z) {} /** @copydoc Vector::Vector(const Vector&) */ - template inline constexpr explicit Vector3(const Vector<3, U>& other): Vector<3, T>(other) {} + template constexpr explicit Vector3(const Vector<3, U>& other): Vector<3, T>(other) {} /** @brief Construct vector from external representation */ - template::from(std::declval()))> inline constexpr explicit Vector3(const U& other): Vector<3, T>(Implementation::VectorConverter<3, T, U>::from(other)) {} + template::from(std::declval()))> constexpr explicit Vector3(const U& other): Vector<3, T>(Implementation::VectorConverter<3, T, U>::from(other)) {} /** @brief Copy constructor */ - inline constexpr Vector3(const Vector<3, T>& other): Vector<3, T>(other) {} + constexpr Vector3(const Vector<3, T>& other): Vector<3, T>(other) {} - inline T& x() { return (*this)[0]; } /**< @brief X component */ - inline constexpr T x() const { return (*this)[0]; } /**< @overload */ - inline T& y() { return (*this)[1]; } /**< @brief Y component */ - inline constexpr T y() const { return (*this)[1]; } /**< @overload */ - inline T& z() { return (*this)[2]; } /**< @brief Z component */ - inline constexpr T z() const { return (*this)[2]; } /**< @overload */ + T& x() { return (*this)[0]; } /**< @brief X component */ + constexpr T x() const { return (*this)[0]; } /**< @overload */ + T& y() { return (*this)[1]; } /**< @brief Y component */ + constexpr T y() const { return (*this)[1]; } /**< @overload */ + T& z() { return (*this)[2]; } /**< @brief Z component */ + constexpr T z() const { return (*this)[2]; } /**< @overload */ /** * @brief XY part of the vector @@ -158,8 +158,8 @@ template class Vector3: public Vector<3, T> { * * @see swizzle() */ - inline Vector2& xy() { return Vector2::from(Vector<3, T>::data()); } - inline constexpr const Vector2 xy() const { return {x(), y()}; } /**< @overload */ + Vector2& xy() { return Vector2::from(Vector<3, T>::data()); } + constexpr const Vector2 xy() const { return {x(), y()}; } /**< @overload */ MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector3, 3) }; diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index 6e40b12be..2af6e2da8 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -43,10 +43,10 @@ See @ref matrix-vector for brief introduction. template class Vector4: public Vector<4, T> { public: /** @copydoc Vector::Vector() */ - inline constexpr /*implicit*/ Vector4() {} + constexpr /*implicit*/ Vector4() {} /** @copydoc Vector::Vector(T) */ - inline constexpr explicit Vector4(T value): Vector<4, T>(value) {} + constexpr explicit Vector4(T value): Vector<4, T>(value) {} /** * @brief Constructor @@ -55,7 +55,7 @@ template class Vector4: public Vector<4, T> { * \boldsymbol v = \begin{pmatrix} x \\ y \\ z \\ w \end{pmatrix} * @f] */ - inline constexpr /*implicit*/ Vector4(T x, T y, T z, T w): Vector<4, T>(x, y, z, w) {} + constexpr /*implicit*/ Vector4(T x, T y, T z, T w): Vector<4, T>(x, y, z, w) {} /** * @brief Constructor @@ -64,25 +64,25 @@ template class Vector4: public Vector<4, T> { * \boldsymbol v = \begin{pmatrix} v_x \\ v_y \\ v_z \\ w \end{pmatrix} * @f] */ - inline constexpr /*implicit*/ Vector4(const Vector3& xyz, T w): Vector<4, T>(xyz[0], xyz[1], xyz[2], w) {} + constexpr /*implicit*/ Vector4(const Vector3& xyz, T w): Vector<4, T>(xyz[0], xyz[1], xyz[2], w) {} /** @copydoc Vector::Vector(const Vector&) */ - template inline constexpr explicit Vector4(const Vector<4, U>& other): Vector<4, T>(other) {} + template constexpr explicit Vector4(const Vector<4, U>& other): Vector<4, T>(other) {} /** @brief Construct vector from external representation */ - template::from(std::declval()))> inline constexpr explicit Vector4(const U& other): Vector<4, T>(Implementation::VectorConverter<4, T, U>::from(other)) {} + template::from(std::declval()))> constexpr explicit Vector4(const U& other): Vector<4, T>(Implementation::VectorConverter<4, T, U>::from(other)) {} /** @brief Copy constructor */ - inline constexpr Vector4(const Vector<4, T>& other): Vector<4, T>(other) {} + constexpr Vector4(const Vector<4, T>& other): Vector<4, T>(other) {} - inline T& x() { return (*this)[0]; } /**< @brief X component */ - inline constexpr T x() const { return (*this)[0]; } /**< @overload */ - inline T& y() { return (*this)[1]; } /**< @brief Y component */ - inline constexpr T y() const { return (*this)[1]; } /**< @overload */ - inline T& z() { return (*this)[2]; } /**< @brief Z component */ - inline constexpr T z() const { return (*this)[2]; } /**< @overload */ - inline T& w() { return (*this)[3]; } /**< @brief W component */ - inline constexpr T w() const { return (*this)[3]; } /**< @overload */ + T& x() { return (*this)[0]; } /**< @brief X component */ + constexpr T x() const { return (*this)[0]; } /**< @overload */ + T& y() { return (*this)[1]; } /**< @brief Y component */ + constexpr T y() const { return (*this)[1]; } /**< @overload */ + T& z() { return (*this)[2]; } /**< @brief Z component */ + constexpr T z() const { return (*this)[2]; } /**< @overload */ + T& w() { return (*this)[3]; } /**< @brief W component */ + constexpr T w() const { return (*this)[3]; } /**< @overload */ /** * @brief XYZ part of the vector @@ -90,8 +90,8 @@ template class Vector4: public Vector<4, T> { * * @see swizzle() */ - inline Vector3& xyz() { return Vector3::from(Vector<4, T>::data()); } - inline constexpr const Vector3 xyz() const { return {x(), y(), z()}; } /**< @overload */ + Vector3& xyz() { return Vector3::from(Vector<4, T>::data()); } + constexpr const Vector3 xyz() const { return {x(), y(), z()}; } /**< @overload */ /** * @brief XY part of the vector @@ -99,8 +99,8 @@ template class Vector4: public Vector<4, T> { * * @see swizzle() */ - inline Vector2& xy() { return Vector2::from(Vector<4, T>::data()); } - inline constexpr const Vector2 xy() const { return {x(), y()}; } /**< @overload */ + Vector2& xy() { return Vector2::from(Vector<4, T>::data()); } + constexpr const Vector2 xy() const { return {x(), y()}; } /**< @overload */ MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector4, 4) };