From f6d1a158f8c75e90bf1b0abd8685ba6e9374a0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 24 Feb 2013 14:25:40 +0100 Subject: [PATCH] Math: initial implementation of dual complex numbers. --- src/CMakeLists.txt | 1 + src/Math/CMakeLists.txt | 1 + src/Math/DualComplex.cpp | 27 +++++++ src/Math/DualComplex.h | 125 ++++++++++++++++++++++++++++++ src/Math/Math.h | 1 + src/Math/Test/CMakeLists.txt | 1 + src/Math/Test/DualComplexTest.cpp | 106 +++++++++++++++++++++++++ 7 files changed, 262 insertions(+) create mode 100644 src/Math/DualComplex.cpp create mode 100644 src/Math/DualComplex.h create mode 100644 src/Math/Test/DualComplexTest.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed0ce0c4a..56b94d28d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,6 +100,7 @@ add_library(MagnumObjects OBJECT ${Magnum_SRCS}) set(MagnumMath_SRCS Math/Angle.cpp Math/Complex.cpp + Math/DualComplex.cpp Math/DualQuaternion.cpp Math/Functions.cpp Math/Quaternion.cpp diff --git a/src/Math/CMakeLists.txt b/src/Math/CMakeLists.txt index 287d96427..e8c9997fb 100644 --- a/src/Math/CMakeLists.txt +++ b/src/Math/CMakeLists.txt @@ -4,6 +4,7 @@ set(MagnumMath_HEADERS Complex.h Constants.h Dual.h + DualComplex.h DualQuaternion.h Functions.h Math.h diff --git a/src/Math/DualComplex.cpp b/src/Math/DualComplex.cpp new file mode 100644 index 000000000..128f2f767 --- /dev/null +++ b/src/Math/DualComplex.cpp @@ -0,0 +1,27 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "DualComplex.h" + +namespace Magnum { namespace Math { + +#ifndef DOXYGEN_GENERATING_OUTPUT +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const DualComplex&); +#ifndef MAGNUM_TARGET_GLES +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const DualComplex&); +#endif +#endif + +}} diff --git a/src/Math/DualComplex.h b/src/Math/DualComplex.h new file mode 100644 index 000000000..26c51879a --- /dev/null +++ b/src/Math/DualComplex.h @@ -0,0 +1,125 @@ +#ifndef Magnum_Math_DualComplex_h +#define Magnum_Math_DualComplex_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Math::DualComplex + */ + +#include "Math/Dual.h" +#include "Math/Complex.h" + +namespace Magnum { namespace Math { + +/** +@brief %Dual complex number +@tparam T Underlying data type + +Represents 2D rotation and translation. +@see Dual, Complex, Matrix3 +*/ +template class DualComplex: public Dual> { + public: + typedef T Type; /**< @brief Underlying data type */ + + /** + * @brief Default constructor + * + * Creates unit dual complex number. @f[ + * \hat c = (0 + i1) + \epsilon (0 + i0) + * @f] + * @todoc Remove workaround when Doxygen is predictable + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + inline constexpr /*implicit*/ DualComplex(); + #else + inline constexpr /*implicit*/ DualComplex(): Dual>({}, {T(0), T(0)}) {} + #endif + + /** + * @brief Construct dual complex number from real and dual part + * + * @f[ + * \hat c = c_0 + \epsilon c_\epsilon + * @f] + */ + inline constexpr /*implicit*/ DualComplex(const Complex& real, const Complex& dual): Dual>(real, dual) {} + + /** + * @brief Complex-conjugated dual complex number + * + * @f[ + * \hat c^* = c^*_0 + c^*_\epsilon + * @f] + * @see dualConjugated(), conjugated(), Complex::conjugated() + */ + inline DualComplex complexConjugated() const { + return {this->real().conjugated(), this->dual().conjugated()}; + } + + /** + * @brief Dual-conjugated dual complex number + * + * @f[ + * \overline{\hat c} = c_0 - \epsilon c_\epsilon + * @f] + * @see complexConjugated(), conjugated(), Dual::conjugated() + */ + inline DualComplex dualConjugated() const { + return Dual>::conjugated(); + } + + /** + * @brief Conjugated dual complex number + * + * Both complex and dual conjugation. @f[ + * \overline{\hat c^*} = c^*_0 - \epsilon c^*_\epsilon = c^*_0 + \epsilon(-a_\epsilon + ib_\epsilon) + * @f] + * @see complexConjugated(), dualConjugated(), Complex::conjugated(), + * Dual::conjugated() + */ + inline DualComplex conjugated() const { + return {this->real().conjugated(), {-this->dual().real(), this->dual().imaginary()}}; + } + + MAGNUM_DUAL_SUBCLASS_IMPLEMENTATION(DualComplex, Complex) + + private: + /* Used by Dual operators and dualConjugated() */ + inline constexpr DualComplex(const Dual>& other): Dual>(other) {} +}; + +/** @debugoperator{Magnum::Math::DualQuaternion} */ +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const DualComplex& value) { + debug << "DualComplex({"; + debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); + debug << value.real().real() << ", " << value.real().imaginary() << "}, {" + << value.dual().real() << ", " << value.dual().imaginary() << "})"; + debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true); + return debug; +} + +/* Explicit instantiation for commonly used types */ +#ifndef DOXYGEN_GENERATING_OUTPUT +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const DualComplex&); +#ifndef MAGNUM_TARGET_GLES +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const DualComplex&); +#endif +#endif + +}} + +#endif diff --git a/src/Math/Math.h b/src/Math/Math.h index a05da0a1c..11915afd7 100644 --- a/src/Math/Math.h +++ b/src/Math/Math.h @@ -29,6 +29,7 @@ namespace Magnum { namespace Math { template class Complex; template class Dual; +template class DualComplex; template class DualQuaternion; template class Matrix; diff --git a/src/Math/Test/CMakeLists.txt b/src/Math/Test/CMakeLists.txt index e0e8b22be..6a88a4676 100644 --- a/src/Math/Test/CMakeLists.txt +++ b/src/Math/Test/CMakeLists.txt @@ -19,6 +19,7 @@ corrade_add_test(MathAngleTest AngleTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathDualTest DualTest.cpp) corrade_add_test(MathComplexTest ComplexTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathDualComplexTest DualComplexTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathQuaternionTest QuaternionTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathDualQuaternionTest DualQuaternionTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Math/Test/DualComplexTest.cpp b/src/Math/Test/DualComplexTest.cpp new file mode 100644 index 000000000..5548f71cf --- /dev/null +++ b/src/Math/Test/DualComplexTest.cpp @@ -0,0 +1,106 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include +#include + +#include "Math/DualComplex.h" + +namespace Magnum { namespace Math { namespace Test { + +class DualComplexTest: public Corrade::TestSuite::Tester { + public: + explicit DualComplexTest(); + + void construct(); + void constructDefault(); + + void constExpressions(); + + void complexConjugated(); + void dualConjugated(); + void conjugated(); + + void debug(); +}; + +typedef Math::Complex Complex; +typedef Math::DualComplex DualComplex; + +DualComplexTest::DualComplexTest() { + addTests(&DualComplexTest::construct, + &DualComplexTest::constructDefault, + + &DualComplexTest::constExpressions, + + &DualComplexTest::complexConjugated, + &DualComplexTest::dualConjugated, + &DualComplexTest::conjugated, + + &DualComplexTest::debug); +} + +void DualComplexTest::construct() { + DualComplex a({-1.0f, 2.5f}, {3.0f, -7.5f}); + CORRADE_COMPARE(a.real(), Complex(-1.0f, 2.5f)); + CORRADE_COMPARE(a.dual(), Complex(3.0f, -7.5f)); +} + +void DualComplexTest::constructDefault() { + CORRADE_COMPARE(DualComplex(), DualComplex({1.0f, 0.0f}, {0.0f, 0.0f})); +} + +void DualComplexTest::constExpressions() { + /* Default constructor */ + constexpr DualComplex a; + CORRADE_COMPARE(a, DualComplex({1.0f, 0.0f}, {0.0f, 0.0f})); + + /* Value constructor */ + constexpr DualComplex b({-1.0f, 2.5f}, {3.0f, -7.5f}); + CORRADE_COMPARE(b, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); + + /* Copy constructor */ + constexpr DualComplex d(b); + CORRADE_COMPARE(d, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); +} + +void DualComplexTest::complexConjugated() { + DualComplex a({-1.0f, 2.5f}, {3.0f, -7.5f}); + DualComplex b({-1.0f, -2.5f}, {3.0f, 7.5f}); + CORRADE_COMPARE(a.complexConjugated(), b); +} + +void DualComplexTest::dualConjugated() { + DualComplex a({-1.0f, 2.5f}, { 3.0f, -7.5f}); + DualComplex b({-1.0f, 2.5f}, {-3.0f, 7.5f}); + CORRADE_COMPARE(a.dualConjugated(), b); +} + +void DualComplexTest::conjugated() { + DualComplex a({-1.0f, 2.5f}, { 3.0f, -7.5f}); + DualComplex b({-1.0f, -2.5f}, {-3.0f, -7.5f}); + CORRADE_COMPARE(a.conjugated(), b); +} + +void DualComplexTest::debug() { + std::ostringstream o; + + Debug(&o) << DualComplex({-1.0f, -2.5f}, {-3.0f, -7.5f}); + CORRADE_COMPARE(o.str(), "DualComplex({-1, -2.5}, {-3, -7.5})\n"); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Math::Test::DualComplexTest)