diff --git a/src/Math/DualComplex.h b/src/Math/DualComplex.h index 26c51879a..417d17a1f 100644 --- a/src/Math/DualComplex.h +++ b/src/Math/DualComplex.h @@ -95,6 +95,35 @@ template class DualComplex: public Dual> { return {this->real().conjugated(), {-this->dual().real(), this->dual().imaginary()}}; } + /** + * @brief %Complex number length squared + * + * Should be used instead of length() for comparing complex number + * length with other values, because it doesn't compute the square root. @f[ + * |\hat c|^2 = \sqrt{\hat c^* \hat c}^2 = c_0 \cdot c_0 + \epsilon 2 (c_0 \cdot c_\epsilon) + * @f] + */ + inline Dual lengthSquared() const { + return {this->real().dot(), T(2)*Complex::dot(this->real(), this->dual())}; + } + + /** + * @brief %Dual quaternion length + * + * See lengthSquared() which is faster for comparing length with other + * values. @f[ + * |\hat c| = \sqrt{\hat{c^*} \hat c} = |c_0| + \epsilon \frac{c_0 \cdot c_\epsilon}{|c_0|} + * @f] + */ + inline Dual length() const { + return Math::sqrt(lengthSquared()); + } + + /** @brief Normalized dual complex number (of unit length) */ + inline DualComplex normalized() const { + return (*this)/length(); + } + MAGNUM_DUAL_SUBCLASS_IMPLEMENTATION(DualComplex, Complex) private: diff --git a/src/Math/Test/DualComplexTest.cpp b/src/Math/Test/DualComplexTest.cpp index 5548f71cf..c82f310e5 100644 --- a/src/Math/Test/DualComplexTest.cpp +++ b/src/Math/Test/DualComplexTest.cpp @@ -29,6 +29,10 @@ class DualComplexTest: public Corrade::TestSuite::Tester { void constExpressions(); + void lengthSquared(); + void length(); + void normalized(); + void complexConjugated(); void dualConjugated(); void conjugated(); @@ -37,6 +41,7 @@ class DualComplexTest: public Corrade::TestSuite::Tester { }; typedef Math::Complex Complex; +typedef Math::Dual Dual; typedef Math::DualComplex DualComplex; DualComplexTest::DualComplexTest() { @@ -45,6 +50,10 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::constExpressions, + &DualComplexTest::lengthSquared, + &DualComplexTest::length, + &DualComplexTest::normalized, + &DualComplexTest::complexConjugated, &DualComplexTest::dualConjugated, &DualComplexTest::conjugated, @@ -60,6 +69,7 @@ void DualComplexTest::construct() { void DualComplexTest::constructDefault() { CORRADE_COMPARE(DualComplex(), DualComplex({1.0f, 0.0f}, {0.0f, 0.0f})); + CORRADE_COMPARE(DualComplex().length(), 1.0f); } void DualComplexTest::constExpressions() { @@ -76,6 +86,23 @@ void DualComplexTest::constExpressions() { CORRADE_COMPARE(d, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); } +void DualComplexTest::lengthSquared() { + DualComplex a({-1.0f, 3.0f}, {0.5f, -2.0f}); + CORRADE_COMPARE(a.lengthSquared(), Dual(10.0f, -13.0f)); +} + +void DualComplexTest::length() { + DualComplex a({-1.0f, 3.0f}, {0.5f, -2.0f}); + CORRADE_COMPARE(a.length(), Dual(3.162278f, -2.05548f)); +} + +void DualComplexTest::normalized() { + DualComplex a({-1.0f, 3.0f}, {0.5f, -2.0f}); + DualComplex b({-0.316228f, 0.948683f}, {-0.0474342f, -0.0158114f}); + CORRADE_COMPARE(a.normalized().length(), 1.0f); + CORRADE_COMPARE(a.normalized(), b); +} + void DualComplexTest::complexConjugated() { DualComplex a({-1.0f, 2.5f}, {3.0f, -7.5f}); DualComplex b({-1.0f, -2.5f}, {3.0f, 7.5f});