#ifndef Magnum_Math_Dual_h #define Magnum_Math_Dual_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::Dual */ #include #include #include "Math/MathTypeTraits.h" namespace Magnum { namespace Math { /** @brief %Dual number */ template class Dual { template friend class Dual; public: /** * @brief Default constructor * * Both parts are default-constructed. */ inline constexpr /*implicit*/ Dual(): _real(), _dual() {} /** * @brief Construct dual number from real and dual part * * @f[ * \hat a = a_0 + \epsilon a_\epsilon * @f] */ inline constexpr /*implicit*/ Dual(const T& real, const T& dual = T()): _real(real), _dual(dual) {} /** @brief Equality comparison */ inline bool operator==(const Dual& other) const { return MathTypeTraits::equals(_real, other._real) && MathTypeTraits::equals(_dual, other._dual); } /** @brief Non-equality comparison */ inline bool operator!=(const Dual& other) const { return !operator==(other); } /** @brief Real part */ inline constexpr T real() const { return _real; } /** @brief %Dual part */ inline constexpr T dual() const { return _dual; } /** * @brief Add and assign dual number * * The computation is done in-place. @f[ * \hat a + \hat b = a_0 + b_0 + \epsilon (a_\epsilon + b_\epsilon) * @f] */ inline Dual& operator+=(const Dual& other) { _real += other._real; _dual += other._dual; return *this; } /** * @brief Add dual number * * @see operator+=() */ inline Dual operator+(const Dual& other) const { return Dual(*this)+=other; } /** * @brief Negated dual number * * @f[ * -\hat a = -a_0 - \epsilon a_\epsilon * @f] */ inline Dual operator-() const { return {-_real, -_dual}; } /** * @brief Subtract and assign dual number * * The computation is done in-place. @f[ * \hat a - \hat b = a_0 - b_0 + \epsilon (a_\epsilon - b_\epsilon) * @f] */ inline Dual& operator-=(const Dual& other) { _real -= other._real; _dual -= other._dual; return *this; } /** * @brief Subtract dual number * * @see operator-=() */ inline Dual operator-(const Dual& other) const { return Dual(*this)-=other; } /** * @brief Multiply by dual number * * @f[ * \hat a \hat b = a_0 b_0 + \epsilon (a_0 b_\epsilon + a_\epsilon b_0) * @f] */ template inline Dual operator*(const Dual& other) const { return {_real*other._real, _real*other._dual + _dual*other._real}; } /** * @brief Divide by dual number * * @f[ * \frac{\hat a}{\hat b} = \frac{a_0}{b_0} + \epsilon \frac{a_\epsilon b_0 - a_0 b_\epsilon}{b_0^2} * @f] */ template inline Dual operator/(const Dual& other) const { return {_real/other._real, (_dual*other._real - _real*other._dual)/(other._real*other._real)}; } /** * @brief Conjugated dual number * * @f[ * \overline{\hat a} = a_0 - \epsilon a_\epsilon * @f] */ inline Dual conjugated() const { return {_real, -_dual}; } private: T _real, _dual; }; #ifndef DOXYGEN_GENERATING_OUTPUT #define MAGNUM_DUAL_SUBCLASS_IMPLEMENTATION(Type, Underlying) \ inline Type operator-() const { \ return Dual>::operator-(); \ } \ inline Type& operator+=(const Dual>& other) { \ Dual>::operator+=(other); \ return *this; \ } \ inline Type operator+(const Dual>& other) const { \ return Dual>::operator+(other); \ } \ inline Type& operator-=(const Dual>& other) { \ Dual>::operator-=(other); \ return *this; \ } \ inline Type operator-(const Dual>& other) const { \ return Dual>::operator-(other); \ } \ template inline Type operator*(const Dual& other) const { \ return Dual>::operator*(other); \ } \ template inline Type operator/(const Dual& other) const { \ return Dual>::operator/(other); \ } #endif /** @debugoperator{Magnum::Math::Dual} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Dual& value) { debug << "Dual("; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); debug << value.real() << ", " << value.dual() << ")"; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true); return debug; } /** @relates Dual @brief Square root of dual number @f[ \sqrt{\hat a} = \sqrt{a_0} + \epsilon \frac{a_\epsilon}{2 \sqrt{a_0}} @f] @see Math::sqrt(const T&) */ template Dual sqrt(const Dual& dual) { T sqrt0 = std::sqrt(dual.real()); return {sqrt0, dual.dual()/(2*sqrt0)}; } }} #endif