diff --git a/src/Magnum/Math/DualComplex.h b/src/Magnum/Math/DualComplex.h index 142d772d0..0b6c90b66 100644 --- a/src/Magnum/Math/DualComplex.h +++ b/src/Magnum/Math/DualComplex.h @@ -35,6 +35,10 @@ namespace Magnum { namespace Math { +namespace Implementation { + template struct DualComplexConverter; +} + /** @brief Dual complex number @tparam T Underlying data type @@ -127,9 +131,17 @@ template class DualComplex: public Dual> { constexpr explicit DualComplex(const Vector2& vector): Dual>({}, Complex(vector)) {} #endif + /** @brief Construct dual complex number from external representation */ + template::from(std::declval()))> constexpr explicit DualComplex(const U& other): DualComplex{Implementation::DualComplexConverter::from(other)} {} + /** @brief Copy constructor */ constexpr DualComplex(const Dual>& other): Dual>(other) {} + /** @brief Convert dual complex number to external representation */ + template::to(std::declval>()))> constexpr explicit operator U() const { + return Implementation::DualComplexConverter::to(*this); + } + /** * @brief Whether the dual complex number is normalized * diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index 0fe63828b..036205f7b 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -29,7 +29,27 @@ #include "Magnum/Math/DualComplex.h" #include "Magnum/Math/DualQuaternion.h" -namespace Magnum { namespace Math { namespace Test { +struct DualCmpl { + float re, im, x, y; +}; + +namespace Magnum { namespace Math { + +namespace Implementation { + +template<> struct DualComplexConverter { + constexpr static DualComplex from(const DualCmpl& other) { + return {{other.re, other.im}, {other.x, other.y}}; + } + + constexpr static DualCmpl to(const DualComplex& other) { + return {other.real().real(), other.real().imaginary(), other.dual().real(), other.dual().imaginary() }; + } +}; + +} + +namespace Test { struct DualComplexTest: Corrade::TestSuite::Tester { explicit DualComplexTest(); @@ -38,6 +58,7 @@ struct DualComplexTest: Corrade::TestSuite::Tester { void constructDefault(); void constructFromVector(); void constructCopy(); + void convert(); void isNormalized(); @@ -75,6 +96,7 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::constructDefault, &DualComplexTest::constructFromVector, &DualComplexTest::constructCopy, + &DualComplexTest::convert, &DualComplexTest::isNormalized, @@ -132,6 +154,24 @@ void DualComplexTest::constructCopy() { CORRADE_COMPARE(b, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); } +void DualComplexTest::convert() { + constexpr DualCmpl a{1.5f, -3.5f, 7.0f, -0.5f}; + constexpr DualComplex b{{1.5f, -3.5f}, {7.0f, -0.5f}}; + + constexpr DualComplex c{a}; + CORRADE_COMPARE(c, b); + + constexpr DualCmpl d(b); + CORRADE_COMPARE(d.re, a.re); + CORRADE_COMPARE(d.im, a.im); + CORRADE_COMPARE(d.x, a.x); + CORRADE_COMPARE(d.y, a.y); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void DualComplexTest::isNormalized() { CORRADE_VERIFY(!DualComplex({2.0f, 1.0f}, {}).isNormalized()); CORRADE_VERIFY((DualComplex::rotation(Deg(23.0f))*DualComplex::translation({6.0f, 3.0f})).isNormalized());