diff --git a/src/Math/Complex.h b/src/Math/Complex.h index a0c640d53..923d39c72 100644 --- a/src/Math/Complex.h +++ b/src/Math/Complex.h @@ -19,6 +19,8 @@ * @brief Class Magnum::Math::Complex */ +#include +#include #include #include "Math/MathTypeTraits.h" @@ -225,6 +227,45 @@ template class Complex { return (*this)/length(); } + /** + * @brief Conjugated complex number + * + * @f[ + * \overline c = a - ib + * @f] + */ + inline Complex conjugated() const { + return {_real, -_imaginary}; + } + + /** + * @brief Inverted complex number + * + * See invertedNormalized() which is faster for normalized + * complex numbers. @f[ + * c^{-1} = \frac{\overline c}{c \overline c} = \frac{\overline c}{a^2 + b^2} + * @f] + */ + inline Complex inverted() const { + return conjugated()/dot(); + } + + /** + * @brief Inverted normalized complex number + * + * Equivalent to conjugated(). Expects that the complex number is + * normalized. @f[ + * c^{-1} = \frac{\overline c}{c \overline c} = \frac{\overline c}{a^2 + b^2} = \overline c + * @f] + * @see inverted() + */ + inline Complex invertedNormalized() const { + CORRADE_ASSERT(MathTypeTraits::equals(dot(), T(1)), + "Math::Complex::invertedNormalized(): complex number must be normalized", + Complex(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN())); + return conjugated(); + } + private: T _real, _imaginary; }; diff --git a/src/Math/DualQuaternion.h b/src/Math/DualQuaternion.h index bd68b8d36..35d67565c 100644 --- a/src/Math/DualQuaternion.h +++ b/src/Math/DualQuaternion.h @@ -236,6 +236,7 @@ template class DualQuaternion: public Dual> { * normalized. @f[ * \hat q^{-1} = \frac{\hat q^*}{||\hat q||^2} = \hat q^* * @f] + * @see inverted() */ inline DualQuaternion invertedNormalized() const { CORRADE_ASSERT(MathTypeTraits::equals(lengthSquared(), T(1)), diff --git a/src/Math/Quaternion.h b/src/Math/Quaternion.h index 1c11fea04..0c284a8ac 100644 --- a/src/Math/Quaternion.h +++ b/src/Math/Quaternion.h @@ -391,6 +391,7 @@ template class Quaternion { * normalized. @f[ * q^{-1} = \frac{q^*}{|q|^2} = q^* * @f] + * @see inverted() */ inline Quaternion invertedNormalized() const { CORRADE_ASSERT(MathTypeTraits::equals(dot(), T(1)), diff --git a/src/Math/Test/CMakeLists.txt b/src/Math/Test/CMakeLists.txt index d5e0f63f0..76d7980dc 100644 --- a/src/Math/Test/CMakeLists.txt +++ b/src/Math/Test/CMakeLists.txt @@ -26,6 +26,7 @@ set_target_properties( MathVectorTest MathMatrix3Test MathMatrix4Test + MathComplexTest MathDualQuaternionTest MathQuaternionTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) diff --git a/src/Math/Test/ComplexTest.cpp b/src/Math/Test/ComplexTest.cpp index d8ffeb85d..8b0f1ec7a 100644 --- a/src/Math/Test/ComplexTest.cpp +++ b/src/Math/Test/ComplexTest.cpp @@ -40,6 +40,10 @@ class ComplexTest: public Corrade::TestSuite::Tester { void length(); void normalized(); + void conjugated(); + void inverted(); + void invertedNormalized(); + void debug(); }; @@ -60,6 +64,10 @@ ComplexTest::ComplexTest() { &ComplexTest::length, &ComplexTest::normalized, + &ComplexTest::conjugated, + &ComplexTest::inverted, + &ComplexTest::invertedNormalized, + &ComplexTest::debug); } @@ -162,6 +170,37 @@ void ComplexTest::normalized() { CORRADE_COMPARE(a.normalized().length(), 1.0f); } +void ComplexTest::conjugated() { + CORRADE_COMPARE(Complex(-3.0f, 4.5f).conjugated(), Complex(-3.0f, -4.5f)); +} + +void ComplexTest::inverted() { + Complex a(-3.0f, 4.0f); + Complex b(-0.12f, -0.16f); + + Complex inverted = a.inverted(); + CORRADE_COMPARE(a*inverted, Complex()); + CORRADE_COMPARE(inverted*a, Complex()); + CORRADE_COMPARE(inverted, b); +} + +void ComplexTest::invertedNormalized() { + std::ostringstream o; + Error::setOutput(&o); + + Complex a(-0.6f, 0.8f); + Complex b(-0.6f, -0.8f); + + Complex notInverted = (a*2).invertedNormalized(); + CORRADE_VERIFY(notInverted != notInverted); + CORRADE_COMPARE(o.str(), "Math::Complex::invertedNormalized(): complex number must be normalized\n"); + + Complex inverted = a.invertedNormalized(); + CORRADE_COMPARE(a*inverted, Complex()); + CORRADE_COMPARE(inverted*a, Complex()); + CORRADE_COMPARE(inverted, b); +} + void ComplexTest::debug() { std::ostringstream o;