From 34df5a0aaae521b9046645747811a441c0168381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 24 Oct 2015 22:41:02 +0200 Subject: [PATCH] Math: explicit conversion constructors for Dual, Complex and Quaternion. Similarly to what's already in all Vector and Matrix classes. Not sure why this wasn't there already. --- src/Magnum/Math/Complex.h | 10 ++++++++++ src/Magnum/Math/Dual.h | 13 +++++++++++++ src/Magnum/Math/DualComplex.h | 12 ++++++++++++ src/Magnum/Math/DualQuaternion.h | 8 ++++++++ src/Magnum/Math/Quaternion.h | 10 ++++++++++ src/Magnum/Math/Test/ComplexTest.cpp | 14 ++++++++++++++ src/Magnum/Math/Test/DualComplexTest.cpp | 14 ++++++++++++++ src/Magnum/Math/Test/DualQuaternionTest.cpp | 14 ++++++++++++++ src/Magnum/Math/Test/DualTest.cpp | 14 ++++++++++++++ src/Magnum/Math/Test/QuaternionTest.cpp | 14 ++++++++++++++ 10 files changed, 123 insertions(+) diff --git a/src/Magnum/Math/Complex.h b/src/Magnum/Math/Complex.h index b50c2afac..0100b4682 100644 --- a/src/Magnum/Math/Complex.h +++ b/src/Magnum/Math/Complex.h @@ -83,6 +83,8 @@ Represents 2D rotation. See @ref transformations for brief introduction. @see @ref Magnum::Complex, @ref Magnum::Complexd, @ref Matrix3 */ template class Complex { + template friend class Complex; + public: typedef T Type; /**< @brief Underlying data type */ @@ -167,6 +169,14 @@ template class Complex { */ constexpr explicit Complex(const Vector2& vector): _real(vector.x()), _imaginary(vector.y()) {} + /** + * @brief Construct complex number from another of different type + * + * Performs only default casting on the values, no rounding or anything + * else. + */ + template constexpr explicit Complex(const Complex& other): _real{T(other._real)}, _imaginary{T(other._imaginary)} {} + /** @brief Construct complex number from external representation */ template::from(std::declval()))> #ifndef CORRADE_MSVC2015_COMPATIBILITY diff --git a/src/Magnum/Math/Dual.h b/src/Magnum/Math/Dual.h index 67e9f29ff..39536e0e5 100644 --- a/src/Magnum/Math/Dual.h +++ b/src/Magnum/Math/Dual.h @@ -72,6 +72,19 @@ template class Dual { */ constexpr /*implicit*/ Dual(const T& real, const T& dual = T()): _real(real), _dual(dual) {} + /** + * @brief Construct dual number from another of different type + * + * Performs only default casting on the values, no rounding or anything + * else. Example usage: + * @code + * Dual floatingPoint(1.3f, 2.7f); + * Dual integral(floatingPoint); + * // integral == {1, 2} + * @endcode + */ + template constexpr explicit Dual(const Dual& other): _real{T(other._real)}, _dual{T(other._dual)} {} + /** @brief Equality comparison */ bool operator==(const Dual& other) const { return TypeTraits::equals(_real, other._real) && diff --git a/src/Magnum/Math/DualComplex.h b/src/Magnum/Math/DualComplex.h index ae2ef17b4..e53714725 100644 --- a/src/Magnum/Math/DualComplex.h +++ b/src/Magnum/Math/DualComplex.h @@ -149,6 +149,18 @@ template class DualComplex: public Dual> { constexpr explicit DualComplex(const Vector2& vector): Dual>({}, Complex(vector)) {} #endif + /** + * @brief Construct dual complex number from another of different type + * + * Performs only default casting on the values, no rounding or anything + * else. + */ + template constexpr explicit DualComplex(const DualComplex& other) + #ifndef DOXYGEN_GENERATING_OUTPUT + : Dual>{other} + #endif + {} + /** @brief Construct dual complex number from external representation */ template::from(std::declval()))> #ifndef CORRADE_MSVC2015_COMPATIBILITY diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index 621450662..37c05514b 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -215,6 +215,14 @@ template class DualQuaternion: public Dual> { constexpr explicit DualQuaternion(const Vector3& vector): Dual>({}, {vector, T(0)}) {} #endif + /** + * @brief Construct dual quaternion from another of different type + * + * Performs only default casting on the values, no rounding or anything + * else. + */ + template constexpr explicit DualQuaternion(const DualQuaternion& other): Dual>(other) {} + /** @brief Construct dual quaternion from external representation */ template::from(std::declval()))> #ifndef CORRADE_MSVC2015_COMPATIBILITY diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index c05e0993e..119b55877 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -125,6 +125,8 @@ Represents 3D rotation. See @ref transformations for brief introduction. @ref Matrix4 */ template class Quaternion { + template friend class Quaternion; + public: typedef T Type; /**< @brief Underlying data type */ @@ -224,6 +226,14 @@ template class Quaternion { */ constexpr explicit Quaternion(const Vector3& vector): _vector(vector), _scalar(T(0)) {} + /** + * @brief Construct dual complex number from another of different type + * + * Performs only default casting on the values, no rounding or anything + * else. + */ + template constexpr explicit Quaternion(const Quaternion& other): _vector{other._vector}, _scalar{T(other._scalar)} {} + /** @brief Construct quaternion from external representation */ template::from(std::declval()))> #ifndef CORRADE_MSVC2015_COMPATIBILITY diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index 53653f8d9..c869fb391 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -62,6 +62,7 @@ struct ComplexTest: Corrade::TestSuite::Tester { void constructZero(); void constructNoInit(); void constructFromVector(); + void constructConversion(); void constructCopy(); void convert(); @@ -96,6 +97,7 @@ ComplexTest::ComplexTest() { &ComplexTest::constructZero, &ComplexTest::constructNoInit, &ComplexTest::constructFromVector, + &ComplexTest::constructConversion, &ComplexTest::constructCopy, &ComplexTest::convert, @@ -175,6 +177,18 @@ void ComplexTest::constructFromVector() { CORRADE_VERIFY(!(std::is_convertible::value)); } +void ComplexTest::constructConversion() { + typedef Math::Complex Complexi; + + constexpr Complex a{1.3f, 2.7f}; + constexpr Complexi b{a}; + + CORRADE_COMPARE(b, (Complexi{1, 2})); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void ComplexTest::constructCopy() { constexpr Complex a(2.5f, -5.0f); constexpr Complex b(a); diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index d7cb899fb..9e0a7096a 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -62,6 +62,7 @@ struct DualComplexTest: Corrade::TestSuite::Tester { void constructZero(); void constructNoInit(); void constructFromVector(); + void constructConversion(); void constructCopy(); void convert(); @@ -102,6 +103,7 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::constructZero, &DualComplexTest::constructNoInit, &DualComplexTest::constructFromVector, + &DualComplexTest::constructConversion, &DualComplexTest::constructCopy, &DualComplexTest::convert, @@ -169,6 +171,18 @@ void DualComplexTest::constructFromVector() { CORRADE_VERIFY(!(std::is_convertible::value)); } +void DualComplexTest::constructConversion() { + typedef Math::DualComplex DualComplexi; + + constexpr DualComplex a{{1.3f, 2.7f}, {-15.0f, 7.0f}}; + constexpr DualComplexi b{a}; + + CORRADE_COMPARE(b, (DualComplexi{{1, 2}, {-15, 7}})); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void DualComplexTest::constructCopy() { constexpr Math::Dual a({-1.0f, 2.5f}, {3.0f, -7.5f}); #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why can't be copy constexpr? */ diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 856ca6e53..e1e149c62 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -64,6 +64,7 @@ struct DualQuaternionTest: Corrade::TestSuite::Tester { void constructZero(); void constructNoInit(); void constructFromVector(); + void constructConversion(); void constructCopy(); void convert(); @@ -105,6 +106,7 @@ DualQuaternionTest::DualQuaternionTest() { &DualQuaternionTest::constructZero, &DualQuaternionTest::constructNoInit, &DualQuaternionTest::constructFromVector, + &DualQuaternionTest::constructConversion, &DualQuaternionTest::constructCopy, &DualQuaternionTest::convert, @@ -174,6 +176,18 @@ void DualQuaternionTest::constructFromVector() { CORRADE_VERIFY(!(std::is_convertible::value)); } +void DualQuaternionTest::constructConversion() { + typedef Math::DualQuaternion DualQuaternioni; + + constexpr DualQuaternion a{{{1.3f, 2.7f, -15.0f}, 7.0f}, {{1.0f, -2.0f, 3.0f}, 0.0f}}; + constexpr DualQuaternioni b{a}; + + CORRADE_COMPARE(b, (DualQuaternioni{{{1, 2, -15}, 7}, {{1, -2, 3}, 0}})); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void DualQuaternionTest::constructCopy() { constexpr Math::Dual a({{1.0f, 2.0f, -3.0f}, -3.5f}, {{4.5f, -7.0f, 2.0f}, 1.0f}); #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why can't be copy constexpr? */ diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index 2880f6dc3..90ee2b9da 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -37,6 +37,7 @@ struct DualTest: Corrade::TestSuite::Tester { void construct(); void constructDefault(); void constructNoInit(); + void constructConversion(); void constructCopy(); void compare(); @@ -63,6 +64,7 @@ DualTest::DualTest() { addTests({&DualTest::construct, &DualTest::constructDefault, &DualTest::constructNoInit, + &DualTest::constructConversion, &DualTest::constructCopy, &DualTest::compare, @@ -104,6 +106,18 @@ void DualTest::constructNoInit() { CORRADE_COMPARE(a, Dual(2.0f, -7.5f)); } +void DualTest::constructConversion() { + typedef Math::Dual Duali; + + constexpr Dual a{1.3f, 2.7f}; + constexpr Duali b{a}; + + CORRADE_COMPARE(b, (Duali{1, 2})); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void DualTest::constructCopy() { constexpr Dual a(2.0f, 3.0f); constexpr Dual b(a); diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index fefb37ac3..c7aabe50d 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -62,6 +62,7 @@ struct QuaternionTest: Corrade::TestSuite::Tester { void constructZero(); void constructNoInit(); void constructFromVector(); + void constructConversion(); void constructCopy(); void convert(); @@ -107,6 +108,7 @@ QuaternionTest::QuaternionTest() { &QuaternionTest::constructZero, &QuaternionTest::constructNoInit, &QuaternionTest::constructFromVector, + &QuaternionTest::constructConversion, &QuaternionTest::constructCopy, &QuaternionTest::convert, @@ -176,6 +178,18 @@ void QuaternionTest::constructFromVector() { CORRADE_VERIFY(!(std::is_convertible::value)); } +void QuaternionTest::constructConversion() { + typedef Math::Quaternion Quaternioni; + + constexpr Quaternion a{{1.3f, 2.7f, -15.0f}, 7.0f}; + constexpr Quaternioni b{a}; + + CORRADE_COMPARE(b, (Quaternioni{{1, 2, -15}, 7})); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void QuaternionTest::constructCopy() { constexpr Quaternion a({1.0f, -3.0f, 7.0f}, 2.5f); constexpr Quaternion b(a);