diff --git a/src/Magnum/Math/BitVector.h b/src/Magnum/Math/BitVector.h index 5f3e467705..ee1e0c3c36 100644 --- a/src/Magnum/Math/BitVector.h +++ b/src/Magnum/Math/BitVector.h @@ -35,6 +35,7 @@ #ifndef CORRADE_NO_DEBUG #include #endif +#include #include "Magnum/Types.h" #include "Magnum/Math/Math.h" @@ -174,14 +175,14 @@ template class BitVector { * Equivalent to @ref all(). * @see @ref any(), @ref none() */ - explicit operator bool() const { return all(); } + explicit MAGNUM_CONSTEXPR14 operator bool() const { return all(); } /** * @brief Whether all bits are set * * @see @ref none(), @ref any(), @ref operator bool() */ - bool all() const; + MAGNUM_CONSTEXPR14 bool all() const; /** * @brief Whether no bits are set @@ -361,7 +362,7 @@ template inline bool BitVector::operator==(const BitVect return true; } -template inline bool BitVector::all() const { +template MAGNUM_CONSTEXPR14 inline bool BitVector::all() const { /* Check all full segments */ for(std::size_t i = 0; i != size/8; ++i) if(_data[i] != FullSegmentMask) return false; diff --git a/src/Magnum/Math/Math.h b/src/Magnum/Math/Math.h index be95511dc7..870be6371d 100644 --- a/src/Magnum/Math/Math.h +++ b/src/Magnum/Math/Math.h @@ -116,4 +116,17 @@ namespace Implementation { }} +// TODO remove this once corrade#152 gets merged +#if defined __cpp_constexpr && __cpp_constexpr >= 201304 || \ + defined CORRADE_TARGET_MSVC && _MSC_VER >= 1910 && CORRADE_CXX_STANDARD >= 201402L +#define MAGNUM_CONSTEXPR14 constexpr +#else +#define MAGNUM_CONSTEXPR14 +#endif +#if defined(__clang__) && __clang_major__ >= 9 || defined(__GNUG__) && __GNUG__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1931 +#define MAGNUM_CONSTEVAL (__builtin_is_constant_evaluated()) +#elif CORRADE_CXX_STANDARD >= 202002L +#define MAGNUM_CONSTEVAL (std::is_constant_evaluated()) +#endif + #endif diff --git a/src/Magnum/Math/Test/CMakeLists.txt b/src/Magnum/Math/Test/CMakeLists.txt index 9251da3964..a3813af3d7 100644 --- a/src/Magnum/Math/Test/CMakeLists.txt +++ b/src/Magnum/Math/Test/CMakeLists.txt @@ -41,6 +41,13 @@ corrade_add_test(MathVectorTest VectorTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathVector2Test Vector2Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathVector3Test Vector3Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathVector4Test Vector4Test.cpp LIBRARIES MagnumMathTestLib) + +foreach(_test VectorTest Vector2Test Vector3Test Vector4Test) + corrade_add_test(Cpp14Math${_test} ${_test}.cpp LIBRARIES MagnumMathTestLib) + set_target_properties(Cpp14Math${_test} PROPERTIES CORRADE_CXX_STANDARD 14) + target_compile_definitions(Cpp14Math${_test} PRIVATE TESTING_CONSTEXPR CORRADE_GRACEFUL_ASSERT) +endforeach() + corrade_add_test(MathColorTest ColorTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathRectangularMatrixTest RectangularMatrixTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Magnum/Math/Test/Cpp14VectorTest.h b/src/Magnum/Math/Test/Cpp14VectorTest.h new file mode 100644 index 0000000000..961ecf60fb --- /dev/null +++ b/src/Magnum/Math/Test/Cpp14VectorTest.h @@ -0,0 +1,14 @@ +#ifndef Magnum_Math_Test_Cpp14Vector +#define Magnum_Math_Test_Cpp14Vector + +#define CE +#ifdef TESTING_CONSTEXPR +#if __cpp_constexpr >= 201304 +#undef CE +#define CE constexpr +#else +#define SKIP_TESTING +#endif +#endif + +#endif diff --git a/src/Magnum/Math/Test/Vector2Test.cpp b/src/Magnum/Math/Test/Vector2Test.cpp index f6215c3348..0f43ba1b87 100644 --- a/src/Magnum/Math/Test/Vector2Test.cpp +++ b/src/Magnum/Math/Test/Vector2Test.cpp @@ -32,6 +32,8 @@ #include "Magnum/Math/StrictWeakOrdering.h" #include "Magnum/Math/Swizzle.h" +#include "Cpp14VectorTest.h" + struct Vec2 { float x, y; }; @@ -57,6 +59,7 @@ namespace Test { namespace { struct Vector2Test: Corrade::TestSuite::Tester { explicit Vector2Test(); +#ifndef SKIP_TESTING void construct(); void constructDefault(); void constructNoInit(); @@ -76,6 +79,9 @@ struct Vector2Test: Corrade::TestSuite::Tester { void swizzleType(); void debug(); +#else + void skipTesting(); +#endif }; typedef Math::Vector3 Vector3i; @@ -83,7 +89,14 @@ typedef Math::Vector2 Vector2; typedef Math::Vector2 Vector2i; Vector2Test::Vector2Test() { - addTests({&Vector2Test::construct, +#ifndef TESTING_CONSTEXPR + setTestName("MathVector2Test"); +#else + setTestName("Cpp14MathVector2Test"); +#endif + addTests({ +#ifndef SKIP_TESTING + &Vector2Test::construct, &Vector2Test::constructDefault, &Vector2Test::constructNoInit, &Vector2Test::constructOneValue, @@ -101,9 +114,15 @@ Vector2Test::Vector2Test() { &Vector2Test::strictWeakOrdering, &Vector2Test::swizzleType, - &Vector2Test::debug}); + &Vector2Test::debug +#else + &Vector2Test::skipTesting +#endif + }); } +#ifndef SKIP_TESTING + void Vector2Test::construct() { constexpr Vector2 a = {1.5f, 2.5f}; CORRADE_COMPARE(a, (Vector<2, Float>(1.5f, 2.5f))); @@ -197,7 +216,7 @@ void Vector2Test::convert() { } void Vector2Test::access() { - Vector2 vec(1.0f, -2.0f); + CE Vector2 vec(1.0f, -2.0f); CORRADE_COMPARE(vec.x(), 1.0f); CORRADE_COMPARE(vec.y(), -2.0f); @@ -209,8 +228,8 @@ void Vector2Test::access() { } void Vector2Test::cross() { - Vector2i a(1, -1); - Vector2i b(4, 3); + CE Vector2i a(1, -1); + CE Vector2i b(4, 3); CORRADE_COMPARE(Math::cross(a, b), 7); CORRADE_COMPARE(Math::cross({a, 0}, {b, 0}), Vector3i(0, 0, Math::cross(a, b))); @@ -268,6 +287,11 @@ void Vector2Test::debug() { Debug(&o) << Vector2(0.5f, 15.0f); CORRADE_COMPARE(o.str(), "Vector(0.5, 15)\n"); } +#else +void Vector2Test::skipTesting() { + CORRADE_SKIP("Relaxed constexpr not supported by the compiler."); +} +#endif }}}} diff --git a/src/Magnum/Math/Test/Vector3Test.cpp b/src/Magnum/Math/Test/Vector3Test.cpp index 11f1326290..c69f9a6470 100644 --- a/src/Magnum/Math/Test/Vector3Test.cpp +++ b/src/Magnum/Math/Test/Vector3Test.cpp @@ -23,6 +23,8 @@ DEALINGS IN THE SOFTWARE. */ +#include "Cpp14VectorTest.h" + #include #include #include @@ -57,6 +59,7 @@ namespace Test { namespace { struct Vector3Test: Corrade::TestSuite::Tester { explicit Vector3Test(); +#ifndef SKIP_TESTING void construct(); void constructDefault(); void constructNoInit(); @@ -76,6 +79,9 @@ struct Vector3Test: Corrade::TestSuite::Tester { void swizzleType(); void debug(); +#else + void skipTesting(); +#endif }; typedef Math::Vector3 Vector3; @@ -83,7 +89,14 @@ typedef Math::Vector3 Vector3i; typedef Math::Vector2 Vector2; Vector3Test::Vector3Test() { - addTests({&Vector3Test::construct, +#ifndef TESTING_CONSTEXPR + setTestName("MathVector3Test"); +#else + setTestName("Cpp14MathVector3Test"); +#endif + addTests({ +#ifndef SKIP_TESTING + &Vector3Test::construct, &Vector3Test::constructDefault, &Vector3Test::constructNoInit, &Vector3Test::constructOneValue, @@ -101,9 +114,13 @@ Vector3Test::Vector3Test() { &Vector3Test::strictWeakOrdering, &Vector3Test::swizzleType, - &Vector3Test::debug}); + &Vector3Test::debug +#else + &Vector3Test::skipTesting +#endif + }); } - +#ifndef SKIP_TESTING void Vector3Test::construct() { constexpr Vector3 a = {1.0f, 2.5f, -3.0f}; CORRADE_COMPARE(a, (Vector<3, Float>(1.0f, 2.5f, -3.0f))); @@ -206,7 +223,7 @@ void Vector3Test::convert() { } void Vector3Test::access() { - Vector3 vec(1.0f, -2.0f, 5.0f); + CE Vector3 vec(1.0f, -2.0f, 5.0f); CORRADE_COMPARE(vec.x(), 1.0f); CORRADE_COMPARE(vec.r(), 1.0f); CORRADE_COMPARE(vec.y(), -2.0f); @@ -230,8 +247,8 @@ void Vector3Test::access() { } void Vector3Test::cross() { - Vector3i a(1, -1, 1); - Vector3i b(4, 3, 7); + CE Vector3i a(1, -1, 1); + CE Vector3i b(4, 3, 7); CORRADE_COMPARE(Math::cross(a, b), Vector3i(-10, -3, 7)); } @@ -255,7 +272,7 @@ void Vector3Test::scales() { } void Vector3Test::twoComponent() { - Vector3 a(1.0f, 2.0f, 3.0f); + CE Vector3 a(1.0f, 2.0f, 3.0f); CORRADE_COMPARE(a.xy(), Vector2(1.0f, 2.0f)); constexpr Vector3 b(1.0f, 2.0f, 3.0f); @@ -292,7 +309,11 @@ void Vector3Test::debug() { Debug(&o) << Vector3(0.5f, 15.0f, 1.0f); CORRADE_COMPARE(o.str(), "Vector(0.5, 15, 1)\n"); } - +#else +void Vector3Test::skipTesting() { + CORRADE_SKIP("Relaxed constexpr not supported by the compiler."); +} +#endif }}}} CORRADE_TEST_MAIN(Magnum::Math::Test::Vector3Test) diff --git a/src/Magnum/Math/Test/Vector4Test.cpp b/src/Magnum/Math/Test/Vector4Test.cpp index c4c0d7c79a..1a1adb0226 100644 --- a/src/Magnum/Math/Test/Vector4Test.cpp +++ b/src/Magnum/Math/Test/Vector4Test.cpp @@ -32,6 +32,8 @@ #include "Magnum/Math/StrictWeakOrdering.h" #include "Magnum/Math/Swizzle.h" +#include "Cpp14VectorTest.h" + struct Vec4 { float x, y, z, w; }; @@ -57,6 +59,7 @@ namespace Test { namespace { struct Vector4Test: Corrade::TestSuite::Tester { explicit Vector4Test(); +#ifndef SKIP_TESTING void construct(); void constructPad(); void constructDefault(); @@ -78,6 +81,9 @@ struct Vector4Test: Corrade::TestSuite::Tester { void swizzleType(); void debug(); +#else + void skipTesting(); +#endif }; typedef Math::Vector4 Vector4; @@ -86,7 +92,14 @@ typedef Math::Vector3 Vector3; typedef Math::Vector2 Vector2; Vector4Test::Vector4Test() { - addTests({&Vector4Test::construct, +#ifndef TESTING_CONSTEXPR + setTestName("MathVector4Test"); +#else + setTestName("Cpp14MathVector4Test"); +#endif + addTests({ +#ifndef SKIP_TESTING + &Vector4Test::construct, &Vector4Test::constructPad, &Vector4Test::constructDefault, &Vector4Test::constructNoInit, @@ -106,9 +119,14 @@ Vector4Test::Vector4Test() { &Vector4Test::strictWeakOrdering, &Vector4Test::swizzleType, - &Vector4Test::debug}); + &Vector4Test::debug +#else + &Vector4Test::skipTesting +#endif + }); } +#ifndef SKIP_TESTING void Vector4Test::construct() { constexpr Vector4 a = {1.0f, -2.5f, 3.0f, 4.1f}; CORRADE_COMPARE(a, (Vector<4, Float>(1.0f, -2.5f, 3.0f, 4.1f))); @@ -228,7 +246,7 @@ void Vector4Test::convert() { } void Vector4Test::access() { - Vector4 vec(1.0f, -2.0f, 5.0f, 0.5f); + CE Vector4 vec(1.0f, -2.0f, 5.0f, 0.5f); CORRADE_COMPARE(vec.x(), 1.0f); CORRADE_COMPARE(vec.r(), 1.0f); CORRADE_COMPARE(vec.y(), -2.0f); @@ -258,7 +276,7 @@ void Vector4Test::access() { } void Vector4Test::threeComponent() { - Vector4 a(1.0f, 2.0f, 3.0f, 4.0f); + CE Vector4 a(1.0f, 2.0f, 3.0f, 4.0f); CORRADE_COMPARE(a.xyz(), Vector3(1.0f, 2.0f, 3.0f)); CORRADE_COMPARE(a.rgb(), Vector3(1.0f, 2.0f, 3.0f)); @@ -270,7 +288,7 @@ void Vector4Test::threeComponent() { } void Vector4Test::twoComponent() { - Vector4 a(1.0f, 2.0f, 3.0f, 4.0f); + CE Vector4 a(1.0f, 2.0f, 3.0f, 4.0f); CORRADE_COMPARE(a.xy(), Vector2(1.0f, 2.0f)); constexpr Vector4 b(1.0f, 2.0f, 3.0f, 4.0f); @@ -281,9 +299,9 @@ void Vector4Test::twoComponent() { } void Vector4Test::planeEquationThreePoints() { - const Vector3 a{1.0f, 0.5f, 3.0f}; - const Vector3 b{1.5f, 1.5f, 2.5f}; - const Vector3 c{2.0f, 1.5f, 1.0f}; + CE const Vector3 a{1.0f, 0.5f, 3.0f}; + CE const Vector3 b{1.5f, 1.5f, 2.5f}; + CE const Vector3 c{2.0f, 1.5f, 1.0f}; const Vector4 eq = Math::planeEquation(a, b, c); CORRADE_COMPARE(Math::dot(a, eq.xyz()) + eq.w(), 0.0f); @@ -296,12 +314,12 @@ void Vector4Test::planeEquationThreePoints() { } void Vector4Test::planeEquationNormalPoint() { - const Vector3 a{1.0f, 0.5f, 3.0f}; - const Vector3 normal{-0.9045340f, 0.3015113f, -0.3015113f}; - const Vector4 eq = Math::planeEquation(normal, a); + CE const Vector3 a{1.0f, 0.5f, 3.0f}; + CE const Vector3 normal{-0.9045340f, 0.3015113f, -0.3015113f}; + CE const Vector4 eq = Math::planeEquation(normal, a); - const Vector3 b{1.5f, 1.5f, 2.5f}; - const Vector3 c{2.0f, 1.5f, 1.0f}; + CE const Vector3 b{1.5f, 1.5f, 2.5f}; + CE const Vector3 c{2.0f, 1.5f, 1.0f}; CORRADE_COMPARE(Math::dot(a, eq.xyz()) + eq.w(), 0.0f); CORRADE_COMPARE(Math::dot(b, eq.xyz()) + eq.w(), 0.0f); CORRADE_COMPARE(Math::dot(c, eq.xyz()) + eq.w(), 0.0f); @@ -310,9 +328,9 @@ void Vector4Test::planeEquationNormalPoint() { void Vector4Test::strictWeakOrdering() { StrictWeakOrdering o; - const Vector4 v4a{1.0f, 2.0f, 3.0f, 4.0f}; - const Vector4 v4b{2.0f, 3.0f, 4.0f, 5.0f}; - const Vector4 v4c{1.0f, 2.0f, 3.0f, 5.0f}; + CE const Vector4 v4a{1.0f, 2.0f, 3.0f, 4.0f}; + CE const Vector4 v4b{2.0f, 3.0f, 4.0f, 5.0f}; + CE const Vector4 v4c{1.0f, 2.0f, 3.0f, 5.0f}; CORRADE_VERIFY( o(v4a, v4b)); CORRADE_VERIFY(!o(v4b, v4a)); @@ -335,6 +353,11 @@ void Vector4Test::debug() { Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f); CORRADE_COMPARE(o.str(), "Vector(0.5, 15, 1, 1)\n"); } +#else +void Vector4Test::skipTesting() { + CORRADE_SKIP("Relaxed constexpr not supported by the compiler."); +} +#endif }}}} diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index 64ea4db734..3e9fef6c17 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -33,6 +33,8 @@ #include "Magnum/Math/Vector.h" #include "Magnum/Math/StrictWeakOrdering.h" +#include "Cpp14VectorTest.h" + struct Vec3 { float x, y, z; }; @@ -58,6 +60,7 @@ namespace Test { namespace { struct VectorTest: Corrade::TestSuite::Tester { explicit VectorTest(); +#ifndef SKIP_TESTING void construct(); void constructFromData(); void constructPad(); @@ -119,6 +122,9 @@ struct VectorTest: Corrade::TestSuite::Tester { void debug(); void debugPacked(); +#else + void skipTesting(); +#endif }; typedef Math::Constants Constants; @@ -133,7 +139,14 @@ typedef Vector<4, Int> Vector4i; using namespace Literals; VectorTest::VectorTest() { - addTests({&VectorTest::construct, +#ifndef TESTING_CONSTEXPR + setTestName("MathVectorTest"); +#else + setTestName("Cpp14MathVectorTest"); +#endif + addTests({ +#ifndef SKIP_TESTING + &VectorTest::construct, &VectorTest::constructFromData, &VectorTest::constructPad, &VectorTest::constructPadDefaultHalf, @@ -193,9 +206,14 @@ VectorTest::VectorTest() { &VectorTest::strictWeakOrdering, &VectorTest::debug, - &VectorTest::debugPacked}); + &VectorTest::debugPacked +#else + &VectorTest::skipTesting +#endif + }); } +#ifndef SKIP_TESTING void VectorTest::construct() { constexpr Vector4 a = {1.0f, 2.0f, -3.0f, 4.5f}; CORRADE_COMPARE(a, Vector4(1.0f, 2.0f, -3.0f, 4.5f)); @@ -378,9 +396,9 @@ void VectorTest::compareComponentWise() { typedef BitVector<3> BitVector3; typedef BitVector<4> BitVector4; - Vector4 a{1.0f, -3.5f, 5.0f, -10.0f}; - Vector4 b{1.0f + TypeTraits::epsilon()/2, -3.5f, 5.0f - TypeTraits::epsilon()*2, -10.0f}; - Vector4 c{1.0f + TypeTraits::epsilon()*2, -3.5f, 5.0f - TypeTraits::epsilon()*10, -10.0f}; + CE Vector4 a{1.0f, -3.5f, 5.0f, -10.0f}; + CE Vector4 b{1.0f + TypeTraits::epsilon()/2, -3.5f, 5.0f - TypeTraits::epsilon()*2, -10.0f}; + CE Vector4 c{1.0f + TypeTraits::epsilon()*2, -3.5f, 5.0f - TypeTraits::epsilon()*10, -10.0f}; CORRADE_COMPARE(equal(a, b), BitVector4{0xf}); CORRADE_COMPARE(equal(a, c), BitVector4{0xa}); CORRADE_COMPARE(notEqual(a, b), BitVector4{0x0}); @@ -400,31 +418,31 @@ void VectorTest::promotedNegated() { } void VectorTest::addSubtract() { - Vector4 a(1.0f, -3.0f, 5.0f, -10.0f); - Vector4 b(7.5f, 33.0f, -15.0f, 0.0f); - Vector4 c(8.5f, 30.0f, -10.0f, -10.0f); + CE Vector4 a(1.0f, -3.0f, 5.0f, -10.0f); + CE Vector4 b(7.5f, 33.0f, -15.0f, 0.0f); + CE Vector4 c(8.5f, 30.0f, -10.0f, -10.0f); CORRADE_COMPARE(a + b, c); CORRADE_COMPARE(c - b, a); } void VectorTest::multiplyDivide() { - Vector4 vector(1.0f, 2.0f, 3.0f, 4.0f); - Vector4 multiplied(-1.5f, -3.0f, -4.5f, -6.0f); + CE Vector4 vector(1.0f, 2.0f, 3.0f, 4.0f); + CE Vector4 multiplied(-1.5f, -3.0f, -4.5f, -6.0f); CORRADE_COMPARE(vector*-1.5f, multiplied); CORRADE_COMPARE(-1.5f*vector, multiplied); CORRADE_COMPARE(multiplied/-1.5f, vector); /* Divide vector with number and invert */ - Vector4 divisor(1.0f, 2.0f, -4.0f, 8.0f); - Vector4 result(1.0f, 0.5f, -0.25f, 0.125f); + CE Vector4 divisor(1.0f, 2.0f, -4.0f, 8.0f); + CE Vector4 result(1.0f, 0.5f, -0.25f, 0.125f); CORRADE_COMPARE(1.0f/divisor, result); } void VectorTest::multiplyDivideIntegral() { - Vector4i vector(32, 10, -6, 2); - Vector4i multiplied(-48, -15, 9, -3); + CE Vector4i vector(32, 10, -6, 2); + CE Vector4i multiplied(-48, -15, 9, -3); CORRADE_COMPARE(vector*-1.5f, multiplied); CORRADE_COMPARE(-1.5f*vector, multiplied); @@ -434,18 +452,18 @@ void VectorTest::multiplyDivideIntegral() { } void VectorTest::multiplyDivideComponentWise() { - Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f); - Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f); - Vector4 multiplied(7.0f, -8.0f, -4.5f, 4.0f); + CE Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f); + CE Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f); + CE Vector4 multiplied(7.0f, -8.0f, -4.5f, 4.0f); CORRADE_COMPARE(vec*multiplier, multiplied); CORRADE_COMPARE(multiplied/multiplier, vec); } void VectorTest::multiplyDivideComponentWiseIntegral() { - Vector4i vec(7, 2, -16, -1); - Vector4 multiplier(2.0f, -1.5f, 0.5f, 10.0f); - Vector4i multiplied(14, -3, -8, -10); + CE Vector4i vec(7, 2, -16, -1); + CE Vector4 multiplier(2.0f, -1.5f, 0.5f, 10.0f); + CE Vector4i multiplied(14, -3, -8, -10); CORRADE_COMPARE(vec*multiplier, multiplied); CORRADE_COMPARE(multiplier*vec, multiplied); @@ -457,8 +475,8 @@ void VectorTest::multiplyDivideComponentWiseIntegral() { void VectorTest::modulo() { typedef Math::Vector<2, Int> Vector2i; - const Vector2i a(4, 13); - const Vector2i b(2, 5); + CE const Vector2i a(4, 13); + CE const Vector2i b(2, 5); CORRADE_COMPARE(a % 2, Vector2i(0, 1)); CORRADE_COMPARE(a % b, Vector2i(0, 3)); } @@ -466,14 +484,14 @@ void VectorTest::modulo() { void VectorTest::bitwise() { typedef Math::Vector<2, Int> Vector2i; - const Vector2i a(85, 240); - const Vector2i b(170, 85); + CE const Vector2i a(85, 240); + CE const Vector2i b(170, 85); CORRADE_COMPARE(~a, Vector2i(-86, -241)); CORRADE_COMPARE(a & b, Vector2i(0, 80)); CORRADE_COMPARE(a | b, Vector2i(255, 245)); CORRADE_COMPARE(a ^ b, Vector2i(255, 165)); - const Vector2i c(7, 32); + CE const Vector2i c(7, 32); CORRADE_COMPARE(c << 2, Vector2i(28, 128)); CORRADE_COMPARE(c >> 2, Vector2i(1, 8)); } @@ -487,11 +505,13 @@ void VectorTest::dotSelf() { } void VectorTest::length() { - CORRADE_COMPARE(Vector4(1.0f, 2.0f, 3.0f, 4.0f).length(), 5.4772256f); + CE const Vector4 a(1.0f, 2.0f, 3.0f, 4.0f); + CORRADE_COMPARE(a.length(), 5.4772256f); } void VectorTest::lengthInverted() { - CORRADE_COMPARE(Vector4(1.0f, 2.0f, 3.0f, 4.0f).lengthInverted(), 0.182574f); + CE const Vector4 a(1.0f, 2.0f, 3.0f, 4.0f); + CORRADE_COMPARE(a.lengthInverted(), 0.182574f); } void VectorTest::normalized() { @@ -525,7 +545,7 @@ void VectorTest::max() { } void VectorTest::minmax() { - const auto expected = std::make_pair(-3.0f, 2.0f); + CE const auto expected = std::make_pair(-3.0f, 2.0f); CORRADE_COMPARE((Vector3{-1.0f, 2.0f, -3.0f}.minmax()), expected); CORRADE_COMPARE((Vector3{-1.0f, -3.0f, 2.0f}.minmax()), expected); CORRADE_COMPARE((Vector3{2.0f, -1.0f, -3.0f}.minmax()), expected); @@ -535,9 +555,9 @@ void VectorTest::minmax() { } void VectorTest::nanIgnoring() { - Vector3 oneNan{1.0f, Constants::nan(), -3.0f}; - Vector3 firstNan{Constants::nan(), 1.0f, -3.0f}; - Vector3 allNan{Constants::nan(), Constants::nan(), Constants::nan()}; + CE Vector3 oneNan{1.0f, Constants::nan(), -3.0f}; + CE Vector3 firstNan{Constants::nan(), 1.0f, -3.0f}; + CE Vector3 allNan{Constants::nan(), Constants::nan(), Constants::nan()}; CORRADE_COMPARE(oneNan.min(), -3.0f); CORRADE_COMPARE(firstNan.min(), -3.0f); @@ -555,16 +575,16 @@ void VectorTest::nanIgnoring() { } void VectorTest::projected() { - Vector3 line(1.0f, -1.0f, 0.5f); - Vector3 projected = Vector3(1.0f, 2.0f, 3.0f).projected(line); + CE Vector3 line(1.0f, -1.0f, 0.5f); + CE Vector3 projected = Vector3(1.0f, 2.0f, 3.0f).projected(line); CORRADE_COMPARE(projected, Vector3(0.222222f, -0.222222f, 0.111111f)); CORRADE_COMPARE(projected.normalized(), line.normalized()); } void VectorTest::projectedOntoNormalized() { - Vector3 vector(1.0f, 2.0f, 3.0f); - Vector3 line(1.0f, -1.0f, 0.5f); + CE Vector3 vector(1.0f, 2.0f, 3.0f); + CE Vector3 line(1.0f, -1.0f, 0.5f); Vector3 projected = vector.projectedOntoNormalized(line.normalized()); CORRADE_COMPARE(projected, Vector3(0.222222f, -0.222222f, 0.111111f)); @@ -610,7 +630,7 @@ void VectorTest::angleNormalizedButOver1() { /* This vector *is* normalized, but its length is larger than 1, which would cause acos() to return a NaN. Ensure it's clamped to correct range before passing it there. */ - Vector3 a{1.0f + Math::TypeTraits::epsilon()/2, 0.0f, 0.0f}; + CE Vector3 a{1.0f + Math::TypeTraits::epsilon()/2, 0.0f, 0.0f}; CORRADE_VERIFY(a.isNormalized()); CORRADE_COMPARE(Math::angle(a, a), 0.0_radf); @@ -648,12 +668,12 @@ void VectorTest::subclassTypes() { CORRADE_VERIFY(std::is_same::value); CORRADE_VERIFY(std::is_same::value); - Vector<1, Float> one; + CE Vector<1, Float> one; CORRADE_VERIFY(std::is_same::value); /* Const operators */ - const Vec2 c; - const Vec2 c2; + CE const Vec2 c; + CE const Vec2 c2; CORRADE_VERIFY(std::is_same::value); CORRADE_VERIFY(std::is_same::value); CORRADE_VERIFY(std::is_same::value); @@ -859,6 +879,11 @@ void VectorTest::debugPacked() { Debug{&out} << Debug::packed << Vector4(0.5f, 15.0f, 1.0f, 1.0f) << Vector4(); CORRADE_COMPARE(out.str(), "{0.5, 15, 1, 1} Vector(0, 0, 0, 0)\n"); } +#else +void VectorTest::skipTesting() { + CORRADE_SKIP("Relaxed constexpr not supported by the compiler."); +} +#endif }}}} diff --git a/src/Magnum/Math/TypeTraits.h b/src/Magnum/Math/TypeTraits.h index 3dda3fb046..6daddc1a88 100644 --- a/src/Magnum/Math/TypeTraits.h +++ b/src/Magnum/Math/TypeTraits.h @@ -392,7 +392,7 @@ Calls @ref TypeTraits::equals() --- using fuzzy compare for floating-point types and doing equality comparison on integral types. Scalar complement to @ref equal(const Vector& a, const Vector&). */ -template inline typename std::enable_if::value, bool>::type equal(T a, T b) { +template constexpr inline typename std::enable_if::value, bool>::type equal(T a, T b) { return TypeTraits::equals(a, b); } @@ -404,7 +404,7 @@ Calls @ref TypeTraits::equals() --- using fuzzy compare for floating-point types and doing equality comparison on integral types. Scalar complement to @ref notEqual(const Vector& a, const Vector&). */ -template inline typename std::enable_if::value, bool>::type notEqual(T a, T b) { +template constexpr inline typename std::enable_if::value, bool>::type notEqual(T a, T b) { return !TypeTraits::equals(a, b); } @@ -467,17 +467,18 @@ namespace Implementation { template struct TypeTraitsFloatingPoint: TypeTraitsName { TypeTraitsFloatingPoint() = delete; - static bool equals(T a, T b); - static bool equalsZero(T a, T epsilon); + static constexpr inline T abs(T x) { return x < 0 ? -x : x; } + static MAGNUM_CONSTEXPR14 bool equals(T a, T b); + static MAGNUM_CONSTEXPR14 bool equalsZero(T a, T epsilon); }; -template bool TypeTraitsFloatingPoint::equals(const T a, const T b) { +template MAGNUM_CONSTEXPR14 bool TypeTraitsFloatingPoint::equals(const T a, const T b) { /* Shortcut for binary equality (also infinites) */ if(a == b) return true; - const T absA = std::abs(a); - const T absB = std::abs(b); - const T difference = std::abs(a - b); + const T absA = abs(a); + const T absB = abs(b); + const T difference = abs(a - b); /* One of the numbers is zero or both are extremely close to it, relative error is meaningless */ @@ -488,11 +489,11 @@ template bool TypeTraitsFloatingPoint::equals(const T a, const T b) return difference/(absA + absB) < TypeTraits::epsilon(); } -template bool TypeTraitsFloatingPoint::equalsZero(const T a, const T magnitude) { +template MAGNUM_CONSTEXPR14 bool TypeTraitsFloatingPoint::equalsZero(const T a, const T magnitude) { /* Shortcut for binary equality */ if(a == T(0.0)) return true; - const T absA = std::abs(a); + const T absA = abs(a); /* The value is extremely close to zero, relative error is meaningless */ if(absA < TypeTraits::epsilon()) @@ -538,8 +539,8 @@ namespace Implementation { [1 - epsilon, 1 + epsilon] or dot() in range [1 - 2*epsilon + epsilon^2, 1 + 2*epsilon + epsilon^2]. Because epsilon^2 is way off machine precision, it's omitted. */ -template inline bool isNormalizedSquared(T lengthSquared) { - return std::abs(lengthSquared - T(1)) < T(2)*TypeTraits::epsilon(); +template constexpr inline bool isNormalizedSquared(T lengthSquared) { + return TypeTraitsFloatingPoint::abs(lengthSquared - T(1)) < T(2)*TypeTraits::epsilon(); } } diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index f6752ad519..d41dff3122 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -64,20 +64,21 @@ template constexpr typename std::enable_if::value, T>::type namespace Implementation { template struct VectorConverter; /* Needed by DualQuaternion and Functions.h (to avoid dependency between them) */ - template T lerp(const T& a, const T& b, U t) { + template constexpr T lerp(const T& a, const T& b, U t) { return T((U(1) - t)*a + t*b); } template struct IsZero; template<> struct IsZero { - template bool operator()(const Vector& vec) const { + template static constexpr T abs(T x) { return x < 0 ? -x : x; } + template constexpr bool operator()(const Vector& vec) const { /* Proper comparison should be with epsilon^2, but the value is not representable in given precision. Comparing to epsilon instead. */ - return std::abs(vec.dot()) < TypeTraits::epsilon(); + return abs(vec.dot()) < TypeTraits::epsilon(); } }; template<> struct IsZero { - template bool operator()(const Vector& vec) const { + template constexpr bool operator()(const Vector& vec) const { return vec == Vector{}; } }; @@ -101,7 +102,7 @@ the same general direction, `1` when two *normalized* vectors are parallel, @f] @see @ref Vector::dot() const, @ref Vector::operator-(), @ref Vector2::perpendicular() */ -template inline T dot(const Vector& a, const Vector& b) { +template MAGNUM_CONSTEXPR14 inline T dot(const Vector& a, const Vector& b) { T out{}; for(std::size_t i = 0; i != size; ++i) out += a._data[i]*b._data[i]; @@ -245,7 +246,7 @@ template class Vector { T* data(); constexpr const T* data() const; /**< @overload */ #else - auto data() -> T(&)[size] { return _data; } + MAGNUM_CONSTEXPR14 auto data() -> T(&)[size] { return _data; } constexpr auto data() const -> const T(&)[size] { return _data; } #endif @@ -254,7 +255,7 @@ template class Vector { * * @see @ref data() */ - T& operator[](std::size_t pos) { return _data[pos]; } + MAGNUM_CONSTEXPR14 T& operator[](std::size_t pos) { return _data[pos]; } constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */ /** @@ -262,7 +263,7 @@ template class Vector { * * @see @ref Math::equal() */ - bool operator==(const Vector& other) const { + MAGNUM_CONSTEXPR14 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; @@ -336,7 +337,7 @@ template class Vector { * * Returns the value as-is. */ - Vector operator+() const { return *this; } + MAGNUM_CONSTEXPR14 Vector operator+() const { return *this; } /** * @brief Negated vector @@ -349,7 +350,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else - template typename std::enable_if::value, Vector>::type + template MAGNUM_CONSTEXPR14 typename std::enable_if::value, Vector>::type #endif operator-() const; @@ -360,7 +361,7 @@ template class Vector { * \boldsymbol a_i = \boldsymbol a_i + \boldsymbol b_i * @f] */ - Vector& operator+=(const Vector& other) { + MAGNUM_CONSTEXPR14 Vector& operator+=(const Vector& other) { for(std::size_t i = 0; i != size; ++i) _data[i] += other._data[i]; @@ -372,7 +373,7 @@ template class Vector { * * @see @ref operator+=(), @ref sum() */ - Vector operator+(const Vector& other) const { + MAGNUM_CONSTEXPR14 Vector operator+(const Vector& other) const { return Vector(*this) += other; } @@ -383,7 +384,7 @@ template class Vector { * \boldsymbol a_i = \boldsymbol a_i - \boldsymbol b_i * @f] */ - Vector& operator-=(const Vector& other) { + MAGNUM_CONSTEXPR14 Vector& operator-=(const Vector& other) { for(std::size_t i = 0; i != size; ++i) _data[i] -= other._data[i]; @@ -395,7 +396,7 @@ template class Vector { * * @see @ref operator-=() */ - Vector operator-(const Vector& other) const { + MAGNUM_CONSTEXPR14 Vector operator-(const Vector& other) const { return Vector(*this) -= other; } @@ -408,7 +409,7 @@ template class Vector { * @see @ref operator*=(const Vector&), * @ref operator*=(Vector&, FloatingPoint) */ - Vector& operator*=(T scalar) { + MAGNUM_CONSTEXPR14 Vector& operator*=(T scalar) { for(std::size_t i = 0; i != size; ++i) _data[i] *= scalar; @@ -422,7 +423,7 @@ template class Vector { * @ref operator*=(T), @ref operator*(T, const Vector&), * @ref operator*(const Vector&, FloatingPoint) */ - Vector operator*(T scalar) const { + MAGNUM_CONSTEXPR14 Vector operator*(T scalar) const { return Vector(*this) *= scalar; } @@ -435,7 +436,7 @@ template class Vector { * @see @ref operator/=(const Vector&), * @ref operator/=(Vector&, FloatingPoint) */ - Vector& operator/=(T scalar) { + MAGNUM_CONSTEXPR14 Vector& operator/=(T scalar) { for(std::size_t i = 0; i != size; ++i) _data[i] /= scalar; @@ -449,7 +450,7 @@ template class Vector { * @ref operator/=(T), @ref operator/(T, const Vector&), * @ref operator/(const Vector&, FloatingPoint) */ - Vector operator/(T scalar) const { + MAGNUM_CONSTEXPR14 Vector operator/(T scalar) const { return Vector(*this) /= scalar; } @@ -462,7 +463,7 @@ template class Vector { * @see @ref operator*=(T), * @ref operator*=(Vector&, const Vector&) */ - Vector& operator*=(const Vector& other) { + MAGNUM_CONSTEXPR14 Vector& operator*=(const Vector& other) { for(std::size_t i = 0; i != size; ++i) _data[i] *= other._data[i]; @@ -476,7 +477,7 @@ template class Vector { * @ref operator*(const Vector&, const Vector&), * @ref product() */ - Vector operator*(const Vector& other) const { + MAGNUM_CONSTEXPR14 Vector operator*(const Vector& other) const { return Vector(*this) *= other; } @@ -489,7 +490,7 @@ template class Vector { * @see @ref operator/=(T), * @ref operator/=(Vector&, const Vector&) */ - Vector& operator/=(const Vector& other) { + MAGNUM_CONSTEXPR14 Vector& operator/=(const Vector& other) { for(std::size_t i = 0; i != size; ++i) _data[i] /= other._data[i]; @@ -502,7 +503,7 @@ template class Vector { * @see @ref operator/(T) const, @ref operator/=(const Vector&), * @ref operator/(const Vector&, const Vector&) */ - Vector operator/(const Vector& other) const { + MAGNUM_CONSTEXPR14 Vector operator/(const Vector& other) const { return Vector(*this) /= other; } @@ -517,7 +518,7 @@ template class Vector { * @ref isNormalized(), @ref Distance::pointPointSquared(), * @ref Intersection::pointSphere() */ - T dot() const { return Math::dot(*this, *this); } + MAGNUM_CONSTEXPR14 T dot() const { return Math::dot(*this, *this); } /** * @brief Vector length @@ -544,7 +545,7 @@ template class Vector { * @ref Intersection::pointSphere() * @todo something like std::hypot() for possibly better precision? */ - T length() const { return T(std::sqrt(dot())); } + MAGNUM_CONSTEXPR14 T length() const { return T(std::sqrt(dot())); } /** * @brief Inverse vector length @@ -558,7 +559,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT T #else - template typename std::enable_if::value, T>::type + template MAGNUM_CONSTEXPR14 typename std::enable_if::value, T>::type #endif lengthInverted() const { return T(1)/length(); } @@ -572,7 +573,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else - template typename std::enable_if::value, Vector>::type + template MAGNUM_CONSTEXPR14 typename std::enable_if::value, Vector>::type #endif normalized() const { return *this*lengthInverted(); } @@ -590,7 +591,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else - template typename std::enable_if::value, Vector>::type + template MAGNUM_CONSTEXPR14 typename std::enable_if::value, Vector>::type #endif resized(T length) const { return *this*(lengthInverted()*length); @@ -608,7 +609,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else - template typename std::enable_if::value, Vector>::type + template MAGNUM_CONSTEXPR14 typename std::enable_if::value, Vector>::type #endif projected(const Vector& line) const { return line*Math::dot(*this, line)/line.dot(); @@ -627,7 +628,7 @@ template class Vector { #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else - template typename std::enable_if::value, Vector>::type + template MAGNUM_CONSTEXPR14 typename std::enable_if::value, Vector>::type #endif projectedOntoNormalized(const Vector& line) const; @@ -647,14 +648,14 @@ template class Vector { * * @see @ref operator+(), @ref length() */ - T sum() const; + MAGNUM_CONSTEXPR14 T sum() const; /** * @brief Product of values in the vector * * @see @ref operator*(const Vector&) const */ - T product() const; + MAGNUM_CONSTEXPR14 T product() const; /** * @brief Minimal value in the vector @@ -662,7 +663,7 @@ template class Vector { * NaNs are ignored, unless the vector is all NaNs. * @see @ref Math::min(), @ref minmax(), @ref Math::isNan() */ - T min() const; + MAGNUM_CONSTEXPR14 T min() const; /** * @brief Maximal value in the vector @@ -670,7 +671,7 @@ template class Vector { * NaNs are ignored, unless the vector is all NaNs. * @see @ref Math::max(), @ref minmax(), @ref Math::isNan() */ - T max() const; + MAGNUM_CONSTEXPR14 T max() const; /** * @brief Minimal and maximal value in the vector @@ -678,7 +679,7 @@ template class Vector { * NaNs are ignored, unless the vector is all NaNs. * @see @ref min(), @ref max(), @ref Math::minmax(), @ref Math::isNan() */ - std::pair minmax() const; + MAGNUM_CONSTEXPR14 std::pair minmax() const; #ifndef DOXYGEN_GENERATING_OUTPUT protected: @@ -710,7 +711,7 @@ template class Vector { template friend BitVector equal(const Vector&, const Vector&); template friend BitVector notEqual(const Vector&, const Vector&); - template friend U dot(const Vector&, const Vector&); + template friend MAGNUM_CONSTEXPR14 U dot(const Vector&, const Vector&); /* Implementation for Vector::Vector(const Vector&) */ template constexpr explicit Vector(Corrade::Containers::Implementation::Sequence, const Vector& vector) noexcept: _data{T(vector._data[sequence])...} {} @@ -764,7 +765,7 @@ template inline BitVector notEqual(const Vector Same as @ref Vector::operator*(T) const. */ -template inline Vector operator*( +template inline Vector MAGNUM_CONSTEXPR14 operator*( #ifdef DOXYGEN_GENERATING_OUTPUT T #else @@ -783,7 +784,7 @@ template inline Vector operator*( @f] @see @ref Vector::operator/(T) const */ -template inline Vector operator/( +template inline Vector MAGNUM_CONSTEXPR14 operator/( #ifdef DOXYGEN_GENERATING_OUTPUT T #else @@ -804,7 +805,7 @@ template inline Vector operator/( The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -820,7 +821,7 @@ operator%=(Vector& a, Integral b) { /** @relates Vector @brief Modulo of an integral vector */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -836,7 +837,7 @@ operator%(const Vector& a, Integral b) { The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -852,7 +853,7 @@ operator%=(Vector& a, const Vector& b) { /** @relates Vector @brief Modulo of two integral vectors */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -866,7 +867,7 @@ operator%(const Vector& a, const Vector& b) { /** @relates Vector @brief Bitwise NOT of an integral vector */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -886,7 +887,7 @@ operator~(const Vector& vector) { The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -902,7 +903,7 @@ operator&=(Vector& a, const Vector& b) { /** @relates Vector @brief Bitwise AND of two integral vectors */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -918,7 +919,7 @@ operator&(const Vector& a, const Vector& b) { The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -934,7 +935,7 @@ operator|=(Vector& a, const Vector& b) { /** @relates Vector @brief Bitwise OR of two integral vectors */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -950,7 +951,7 @@ operator|(const Vector& a, const Vector& b) { The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -966,7 +967,7 @@ operator^=(Vector& a, const Vector& b) { /** @relates Vector @brief Bitwise XOR of two integral vectors */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -982,7 +983,7 @@ operator^(const Vector& a, const Vector& b) { The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -1005,7 +1006,7 @@ operator<<=(Vector& vector, /** @relates Vector @brief Bitwise left shift of an integral vector */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1028,7 +1029,7 @@ operator<<(const Vector& vector, The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -1050,7 +1051,7 @@ operator>>=(Vector& vector, /** @relates Vector @brief Bitwise left shift of an integral vector */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1073,7 +1074,7 @@ operator>>(const Vector& vector, Similar to @ref Vector::operator*=(T), except that the multiplication is done in floating-point. The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -1092,7 +1093,7 @@ operator*=(Vector& vector, FloatingPoint scalar) { Similar to @ref Vector::operator*(T) const, except that the multiplication is done in floating-point. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1108,7 +1109,7 @@ operator*(const Vector& vector, FloatingPoint scalar) { Same as @ref operator*(const Vector&, FloatingPoint). */ -template inline +template constexpr inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1124,7 +1125,7 @@ operator*(FloatingPoint scalar, const Vector& vector) { Similar to @ref Vector::operator/=(T), except that the division is done in floating-point. The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -1143,7 +1144,7 @@ operator/=(Vector& vector, FloatingPoint scalar) { Similar to @ref Vector::operator/(T) const, except that the division is done in floating-point. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1160,7 +1161,7 @@ operator/(const Vector& vector, FloatingPoint scalar) { Similar to @ref Vector::operator*=(const Vector&), except that the multiplication is done in floating-point. The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -1181,7 +1182,7 @@ the multiplication is done in floating-point. The result is always integral vector, convert both arguments to the same floating-point type to have floating-point result. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1197,7 +1198,7 @@ operator*(const Vector& a, const Vector& b) Same as @ref operator*(const Vector&, const Vector&). */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1213,7 +1214,7 @@ operator*(const Vector& a, const Vector& b) Similar to @ref Vector::operator/=(const Vector&), except that the division is done in floating-point. The computation is done in-place. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector& #else @@ -1234,7 +1235,7 @@ the division is done in floating-point. The result is always integral vector, convert both arguments to the same floating-point type to have floating-point result. */ -template inline +template MAGNUM_CONSTEXPR14 inline #ifdef DOXYGEN_GENERATING_OUTPUT Vector #else @@ -1288,66 +1289,66 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili return Math::Vector::pad(a, value); \ } \ \ - Type operator+() const { \ + constexpr Type operator+() const { \ return Math::Vector::operator+(); \ } \ - template typename std::enable_if::value, Type>::type \ - operator-() const { \ + template typename std::enable_if::value, Type>::type \ + constexpr operator-() const { \ return Math::Vector::operator-(); \ } \ - Type& operator+=(const Math::Vector& other) { \ + MAGNUM_CONSTEXPR14 Type& operator+=(const Math::Vector& other) { \ Math::Vector::operator+=(other); \ return *this; \ } \ - Type operator+(const Math::Vector& other) const { \ + constexpr Type operator+(const Math::Vector& other) const { \ return Math::Vector::operator+(other); \ } \ - Type& operator-=(const Math::Vector& other) { \ + MAGNUM_CONSTEXPR14 Type& operator-=(const Math::Vector& other) { \ Math::Vector::operator-=(other); \ return *this; \ } \ - Type operator-(const Math::Vector& other) const { \ + MAGNUM_CONSTEXPR14 Type operator-(const Math::Vector& other) const { \ return Math::Vector::operator-(other); \ } \ - Type& operator*=(T number) { \ + MAGNUM_CONSTEXPR14 Type& operator*=(T number) { \ Math::Vector::operator*=(number); \ return *this; \ } \ - Type operator*(T number) const { \ + constexpr Type operator*(T number) const { \ return Math::Vector::operator*(number); \ } \ - Type& operator/=(T number) { \ + MAGNUM_CONSTEXPR14 Type& operator/=(T number) { \ Math::Vector::operator/=(number); \ return *this; \ } \ - Type operator/(T number) const { \ + constexpr Type operator/(T number) const { \ return Math::Vector::operator/(number); \ } \ - Type& operator*=(const Math::Vector& other) { \ + MAGNUM_CONSTEXPR14 Type& operator*=(const Math::Vector& other) { \ Math::Vector::operator*=(other); \ return *this; \ } \ - Type operator*(const Math::Vector& other) const { \ + MAGNUM_CONSTEXPR14 Type operator*(const Math::Vector& other) const { \ return Math::Vector::operator*(other); \ } \ - Type& operator/=(const Math::Vector& other) { \ + MAGNUM_CONSTEXPR14 Type& operator/=(const Math::Vector& other) { \ Math::Vector::operator/=(other); \ return *this; \ } \ - Type operator/(const Math::Vector& other) const { \ + constexpr Type operator/(const Math::Vector& other) const { \ return Math::Vector::operator/(other); \ } \ \ - template typename std::enable_if::value, Type>::type normalized() const { \ + template constexpr typename std::enable_if::value, Type>::type normalized() const { \ return Math::Vector::normalized(); \ } \ - template typename std::enable_if::value, Type>::type resized(T length) const { \ + template constexpr typename std::enable_if::value, Type>::type resized(T length) const { \ return Math::Vector::resized(length); \ } \ - template typename std::enable_if::value, Type>::type projected(const Math::Vector& other) const { \ + template constexpr typename std::enable_if::value, Type>::type projected(const Math::Vector& other) const { \ return Math::Vector::projected(other); \ } \ - template typename std::enable_if::value, Type>::type projectedOntoNormalized(const Math::Vector& other) const { \ + template constexpr typename std::enable_if::value, Type>::type projectedOntoNormalized(const Math::Vector& other) const { \ return Math::Vector::projectedOntoNormalized(other); \ } \ constexpr Type flipped() const { \ @@ -1355,99 +1356,99 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili } #define MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(size, Type) \ - template inline Type operator*(typename std::common_type::type number, const Type& vector) { \ + template constexpr inline Type operator*(typename std::common_type::type number, const Type& vector) { \ return number*static_cast&>(vector); \ } \ - template inline Type operator/(typename std::common_type::type number, const Type& vector) { \ + template constexpr inline Type operator/(typename std::common_type::type number, const Type& vector) { \ return number/static_cast&>(vector); \ } \ \ - template inline typename std::enable_if::value, Type&>::type operator%=(Type& a, Integral b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type&>::type operator%=(Type& a, Integral b) { \ static_cast&>(a) %= b; \ return a; \ } \ - template inline typename std::enable_if::value, Type>::type operator%(const Type& a, Integral b) { \ + template constexpr inline typename std::enable_if::value, Type>::type operator%(const Type& a, Integral b) { \ return static_cast&>(a) % b; \ } \ - template inline typename std::enable_if::value, Type&>::type operator%=(Type& a, const Math::Vector& b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type&>::type operator%=(Type& a, const Math::Vector& b) { \ static_cast&>(a) %= b; \ return a; \ } \ - template inline typename std::enable_if::value, Type>::type operator%(const Type& a, const Math::Vector& b) { \ + template constexpr inline typename std::enable_if::value, Type>::type operator%(const Type& a, const Math::Vector& b) { \ return static_cast&>(a) % b; \ } \ \ - template inline typename std::enable_if::value, Type>::type operator~(const Type& vector) { \ + template constexpr inline typename std::enable_if::value, Type>::type operator~(const Type& vector) { \ return ~static_cast&>(vector); \ } \ - template inline typename std::enable_if::value, Type&>::type operator&=(Type& a, const Math::Vector& b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type&>::type operator&=(Type& a, const Math::Vector& b) { \ static_cast&>(a) &= b; \ return a; \ } \ - template inline typename std::enable_if::value, Type>::type operator&(const Type& a, const Math::Vector& b) { \ + template constexpr inline typename std::enable_if::value, Type>::type operator&(const Type& a, const Math::Vector& b) { \ return static_cast&>(a) & b; \ } \ - template inline typename std::enable_if::value, Type&>::type operator|=(Type& a, const Math::Vector& b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type&>::type operator|=(Type& a, const Math::Vector& b) { \ static_cast&>(a) |= b; \ return a; \ } \ - template inline typename std::enable_if::value, Type>::type operator|(const Type& a, const Math::Vector& b) { \ + template constexpr inline typename std::enable_if::value, Type>::type operator|(const Type& a, const Math::Vector& b) { \ return static_cast&>(a) | b; \ } \ - template inline typename std::enable_if::value, Type&>::type operator^=(Type& a, const Math::Vector& b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type&>::type operator^=(Type& a, const Math::Vector& b) { \ static_cast&>(a) ^= b; \ return a; \ } \ - template inline typename std::enable_if::value, Type>::type operator^(const Type& a, const Math::Vector& b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type>::type operator^(const Type& a, const Math::Vector& b) { \ return static_cast&>(a) ^ b; \ } \ - template inline typename std::enable_if::value, Type&>::type operator<<=(Type& vector, typename std::common_type::type shift) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type&>::type operator<<=(Type& vector, typename std::common_type::type shift) { \ static_cast&>(vector) <<= shift; \ return vector; \ } \ - template inline typename std::enable_if::value, Type>::type operator<<(const Type& vector, typename std::common_type::type shift) { \ + template constexpr inline typename std::enable_if::value, Type>::type operator<<(const Type& vector, typename std::common_type::type shift) { \ return static_cast&>(vector) << shift; \ } \ - template inline typename std::enable_if::value, Type&>::type operator>>=(Type& vector, typename std::common_type::type shift) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type&>::type operator>>=(Type& vector, typename std::common_type::type shift) { \ static_cast&>(vector) >>= shift; \ return vector; \ } \ - template inline typename std::enable_if::value, Type>::type operator>>(const Type& vector, typename std::common_type::type shift) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Type>::type operator>>(const Type& vector, typename std::common_type::type shift) { \ return static_cast&>(vector) >> shift; \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator*=(Type& vector, FloatingPoint number) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator*=(Type& vector, FloatingPoint number) { \ static_cast&>(vector) *= number; \ return vector; \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Type& vector, FloatingPoint number) { \ + template constexpr inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Type& vector, FloatingPoint number) { \ return static_cast&>(vector)*number; \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(FloatingPoint number, const Type& vector) { \ + template constexpr inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(FloatingPoint number, const Type& vector) { \ return number*static_cast&>(vector); \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator/=(Type& vector, FloatingPoint number) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator/=(Type& vector, FloatingPoint number) { \ static_cast&>(vector) /= number; \ return vector; \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator/(const Type& vector, FloatingPoint number) { \ + template constexpr inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator/(const Type& vector, FloatingPoint number) { \ return static_cast&>(vector)/number; \ } \ \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator*=(Type& a, const Math::Vector& b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator*=(Type& a, const Math::Vector& b) { \ static_cast&>(a) *= b; \ return a; \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Type& a, const Math::Vector& b) { \ + template constexpr inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Type& a, const Math::Vector& b) { \ return static_cast&>(a)*b; \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Math::Vector& a, const Type& b) { \ + template constexpr inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator*(const Math::Vector& a, const Type& b) { \ return a*static_cast&>(b); \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator/=(Type& a, const Math::Vector& b) { \ + template inline MAGNUM_CONSTEXPR14 typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator/=(Type& a, const Math::Vector& b) { \ static_cast&>(a) /= b; \ return a; \ } \ - template inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator/(const Type& a, const Math::Vector& b) { \ + template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value && std::is_floating_point::value, Type>::type operator/(const Type& a, const Math::Vector& b) { \ return static_cast&>(a)/b; \ } #endif @@ -1494,7 +1495,7 @@ inline Vector #else template inline typename std::enable_if::value, Vector>::type #endif -Vector::operator-() const { +MAGNUM_CONSTEXPR14 Vector::operator-() const { Vector out; for(std::size_t i = 0; i != size; ++i) @@ -1507,7 +1508,7 @@ template #ifdef DOXYGEN_GENERATING_OUTPUT inline Vector #else -template inline typename std::enable_if::value, Vector>::type +template MAGNUM_CONSTEXPR14 inline typename std::enable_if::value, Vector>::type #endif Vector::projectedOntoNormalized(const Vector& line) const { CORRADE_ASSERT(line.isNormalized(), @@ -1515,7 +1516,7 @@ Vector::projectedOntoNormalized(const Vector& line) const { return line*Math::dot(*this, line); } -template inline T Vector::sum() const { +template MAGNUM_CONSTEXPR14 inline T Vector::sum() const { T out(_data[0]); for(std::size_t i = 1; i != size; ++i) @@ -1524,7 +1525,7 @@ template inline T Vector::sum() const { return out; } -template inline T Vector::product() const { +template MAGNUM_CONSTEXPR14 inline T Vector::product() const { T out(_data[0]); for(std::size_t i = 1; i != size; ++i) @@ -1549,7 +1550,7 @@ namespace Implementation { } } -template inline T Vector::min() const { +template MAGNUM_CONSTEXPR14 inline T Vector::min() const { std::size_t i = Implementation::firstNonNan(_data, IsFloatingPoint{}); T out(_data[i]); @@ -1559,7 +1560,7 @@ template inline T Vector::min() const { return out; } -template inline T Vector::max() const { +template MAGNUM_CONSTEXPR14 inline T Vector::max() const { std::size_t i = Implementation::firstNonNan(_data, IsFloatingPoint{}); T out(_data[i]); @@ -1569,7 +1570,7 @@ template inline T Vector::max() const { return out; } -template inline std::pair Vector::minmax() const { +template MAGNUM_CONSTEXPR14 inline std::pair Vector::minmax() const { std::size_t i = Implementation::firstNonNan(_data, IsFloatingPoint{}); T min{_data[i]}, max{_data[i]}; diff --git a/src/Magnum/Math/Vector2.h b/src/Magnum/Math/Vector2.h index 2b44be4d15..c99bf9e8cb 100644 --- a/src/Magnum/Math/Vector2.h +++ b/src/Magnum/Math/Vector2.h @@ -51,7 +51,7 @@ for more information. @see @ref Vector2::perpendicular(), @ref dot(const Vector&, const Vector&) */ -template inline T cross(const Vector2& a, const Vector2& b) { +template constexpr inline T cross(const Vector2& a, const Vector2& b) { return a._data[0]*b._data[1] - a._data[1]*b._data[0]; } @@ -146,9 +146,9 @@ template class Vector2: public Vector<2, T> { /** @brief Copy constructor */ constexpr /*implicit*/ Vector2(const Vector<2, T>& other) noexcept: Vector<2, T>(other) {} - T& x() { return Vector<2, T>::_data[0]; } /**< @brief X component */ + MAGNUM_CONSTEXPR14 T& x() { return Vector<2, T>::_data[0]; } /**< @brief X component */ constexpr T x() const { return Vector<2, T>::_data[0]; } /**< @overload */ - T& y() { return Vector<2, T>::_data[1]; } /**< @brief Y component */ + MAGNUM_CONSTEXPR14 T& y() { return Vector<2, T>::_data[1]; } /**< @brief Y component */ constexpr T y() const { return Vector<2, T>::_data[1]; } /**< @overload */ /** @@ -166,7 +166,7 @@ template class Vector2: public Vector<2, T> { #ifdef DOXYGEN_GENERATING_OUTPUT Vector2 #else - template typename std::enable_if::value, Vector2>::type + template constexpr typename std::enable_if::value, Vector2>::type #endif perpendicular() const { return {-y(), x()}; } @@ -181,14 +181,14 @@ template class Vector2: public Vector<2, T> { #ifdef DOXYGEN_GENERATING_OUTPUT T #else - template typename std::enable_if::value, T>::type + template constexpr typename std::enable_if::value, T>::type #endif aspectRatio() const { return x()/y(); } MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2) private: - template friend U cross(const Vector2&, const Vector2&); + template friend constexpr U cross(const Vector2&, const Vector2&); }; #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/Math/Vector3.h b/src/Magnum/Math/Vector3.h index 25bab92638..f3a1778929 100644 --- a/src/Magnum/Math/Vector3.h +++ b/src/Magnum/Math/Vector3.h @@ -50,7 +50,7 @@ distance of a point and a line, see @ref Distance::linePoint(const Vector3&, for more information. @see @ref cross(const Vector2&, const Vector2&), @ref planeEquation() */ -template inline Vector3 cross(const Vector3& a, const Vector3& b) { +template constexpr inline Vector3 cross(const Vector3& a, const Vector3& b) { return { a._data[1]*b._data[2] - b._data[1]*a._data[2], a._data[2]*b._data[0] - b._data[2]*a._data[0], @@ -180,7 +180,7 @@ template class Vector3: public Vector<3, T> { * * @see @ref r() */ - T& x() { return Vector<3, T>::_data[0]; } + MAGNUM_CONSTEXPR14 T& x() { return Vector<3, T>::_data[0]; } constexpr T x() const { return Vector<3, T>::_data[0]; } /**< @overload */ /** @@ -188,7 +188,7 @@ template class Vector3: public Vector<3, T> { * * @see @ref g() */ - T& y() { return Vector<3, T>::_data[1]; } + MAGNUM_CONSTEXPR14 T& y() { return Vector<3, T>::_data[1]; } constexpr T y() const { return Vector<3, T>::_data[1]; } /**< @overload */ /** @@ -196,7 +196,7 @@ template class Vector3: public Vector<3, T> { * * @see @ref b() */ - T& z() { return Vector<3, T>::_data[2]; } + MAGNUM_CONSTEXPR14 T& z() { return Vector<3, T>::_data[2]; } constexpr T z() const { return Vector<3, T>::_data[2]; } /**< @overload */ /** @@ -204,7 +204,7 @@ template class Vector3: public Vector<3, T> { * * Equivalent to @ref x(). */ - T& r() { return Vector<3, T>::_data[0]; } + MAGNUM_CONSTEXPR14 T& r() { return Vector<3, T>::_data[0]; } constexpr T r() const { return Vector<3, T>::_data[0]; } /**< @overload */ /** @@ -212,7 +212,7 @@ template class Vector3: public Vector<3, T> { * * Equivalent to @ref y(). */ - T& g() { return Vector<3, T>::_data[1]; } + MAGNUM_CONSTEXPR14 T& g() { return Vector<3, T>::_data[1]; } constexpr T g() const { return Vector<3, T>::_data[1]; } /**< @overload */ /** @@ -220,7 +220,7 @@ template class Vector3: public Vector<3, T> { * * Equivalent to @ref z(). */ - T& b() { return Vector<3, T>::_data[2]; } + MAGNUM_CONSTEXPR14 T& b() { return Vector<3, T>::_data[2]; } constexpr T b() const { return Vector<3, T>::_data[2]; } /**< @overload */ /** @@ -229,7 +229,7 @@ template class Vector3: public Vector<3, T> { * * @see @ref gather(), @ref scatter() */ - Vector2& xy() { return Vector2::from(Vector<3, T>::data()); } + MAGNUM_CONSTEXPR14 Vector2& xy() { return Vector2::from(Vector<3, T>::data()); } constexpr const Vector2 xy() const { return {Vector<3, T>::_data[0], Vector<3, T>::_data[1]}; } /**< @overload */ @@ -237,7 +237,7 @@ template class Vector3: public Vector<3, T> { MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(3, Vector3) private: - template friend Vector3 cross(const Vector3&, const Vector3&); + template friend constexpr Vector3 cross(const Vector3&, const Vector3&); }; #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/Math/Vector4.h b/src/Magnum/Math/Vector4.h index c2254ec50d..3c50858a88 100644 --- a/src/Magnum/Math/Vector4.h +++ b/src/Magnum/Math/Vector4.h @@ -120,7 +120,7 @@ template class Vector4: public Vector<4, T> { * * @see @ref r() */ - T& x() { return Vector<4, T>::_data[0]; } + MAGNUM_CONSTEXPR14 T& x() { return Vector<4, T>::_data[0]; } constexpr T x() const { return Vector<4, T>::_data[0]; } /**< @overload */ /** @@ -128,7 +128,7 @@ template class Vector4: public Vector<4, T> { * * @see @ref g() */ - T& y() { return Vector<4, T>::_data[1]; } + MAGNUM_CONSTEXPR14 T& y() { return Vector<4, T>::_data[1]; } constexpr T y() const { return Vector<4, T>::_data[1]; } /**< @overload */ /** @@ -136,7 +136,7 @@ template class Vector4: public Vector<4, T> { * * @see @ref b() */ - T& z() { return Vector<4, T>::_data[2]; } + MAGNUM_CONSTEXPR14 T& z() { return Vector<4, T>::_data[2]; } constexpr T z() const { return Vector<4, T>::_data[2]; } /**< @overload */ /** @@ -144,7 +144,7 @@ template class Vector4: public Vector<4, T> { * * @see @ref a() */ - T& w() { return Vector<4, T>::_data[3]; } + MAGNUM_CONSTEXPR14 T& w() { return Vector<4, T>::_data[3]; } constexpr T w() const { return Vector<4, T>::_data[3]; } /**< @overload */ /** @@ -152,7 +152,7 @@ template class Vector4: public Vector<4, T> { * * Equivalent to @ref x(). */ - T& r() { return Vector<4, T>::_data[0]; } + MAGNUM_CONSTEXPR14 T& r() { return Vector<4, T>::_data[0]; } constexpr T r() const { return Vector<4, T>::_data[0]; } /**< @overload */ /** @@ -160,7 +160,7 @@ template class Vector4: public Vector<4, T> { * * Equivalent to @ref y(). */ - T& g() { return Vector<4, T>::_data[1]; } + MAGNUM_CONSTEXPR14 T& g() { return Vector<4, T>::_data[1]; } constexpr T g() const { return Vector<4, T>::_data[1]; } /**< @overload */ /** @@ -168,7 +168,7 @@ template class Vector4: public Vector<4, T> { * * Equivalent to @ref z(). */ - T& b() { return Vector<4, T>::_data[2]; } + MAGNUM_CONSTEXPR14 T& b() { return Vector<4, T>::_data[2]; } constexpr T b() const { return Vector<4, T>::_data[2]; } /**< @overload */ /** @@ -176,7 +176,7 @@ template class Vector4: public Vector<4, T> { * * Equivalent to @ref w(). */ - T& a() { return Vector<4, T>::_data[3]; } + MAGNUM_CONSTEXPR14 T& a() { return Vector<4, T>::_data[3]; } constexpr T a() const { return Vector<4, T>::_data[3]; } /**< @overload */ /** @@ -185,7 +185,7 @@ template class Vector4: public Vector<4, T> { * * @see @ref rgb(), @ref gather(), @ref scatter() */ - Vector3& xyz() { return Vector3::from(Vector<4, T>::data()); } + MAGNUM_CONSTEXPR14 Vector3& xyz() { return Vector3::from(Vector<4, T>::data()); } constexpr const Vector3 xyz() const { return {Vector<4, T>::_data[0], Vector<4, T>::_data[1], Vector<4, T>::_data[2]}; } /**< @overload */ @@ -197,7 +197,7 @@ template class Vector4: public Vector<4, T> { * Equivalent to @ref xyz(). * @see @ref gather(), @ref scatter() */ - Vector3& rgb() { return Vector3::from(Vector<4, T>::data()); } + MAGNUM_CONSTEXPR14 Vector3& rgb() { return Vector3::from(Vector<4, T>::data()); } constexpr const Vector3 rgb() const { return {Vector<4, T>::_data[0], Vector<4, T>::_data[1], Vector<4, T>::_data[2]}; } /**< @overload */ @@ -208,7 +208,7 @@ template class Vector4: public Vector<4, T> { * * @see @ref gather(), @ref scatter() */ - Vector2& xy() { return Vector2::from(Vector<4, T>::data()); } + MAGNUM_CONSTEXPR14 Vector2& xy() { return Vector2::from(Vector<4, T>::data()); } constexpr const Vector2 xy() const { return {Vector<4, T>::_data[0], Vector<4, T>::_data[1]}; } /**< @overload */ @@ -237,7 +237,7 @@ when assigning @f$ \boldsymbol{p_i} @f$ to @f$ x @f$, @f$ y @f$, @f$ z @f$. @f[ @see @ref planeEquation(const Vector3&, const Vector3&), @ref cross(), @ref dot() */ -template Vector4 planeEquation(const Vector3& p0, const Vector3& p1, const Vector3& p2) { +template MAGNUM_CONSTEXPR14 Vector4 planeEquation(const Vector3& p0, const Vector3& p1, const Vector3& p2) { const Vector3 normal = Math::cross(p1 - p0, p2 - p0).normalized(); return {normal, -Math::dot(normal, p0)}; } @@ -260,7 +260,7 @@ using a dot product with the normal @f$ \boldsymbol{n} @f$ using the point @see @ref planeEquation(const Vector3&, const Vector3&, const Vector3&), @ref dot(), @ref Frustum */ -template Vector4 planeEquation(const Vector3& normal, const Vector3& point) { +template MAGNUM_CONSTEXPR14 Vector4 planeEquation(const Vector3& normal, const Vector3& point) { return {normal, -Math::dot(normal, point)}; }