Browse Source

Math: added sincos() for Dual numbers.

Calculating sin of Dual number involves also calculating the cos value,
thus a helper function is in order.
pull/118/head
Vladimír Vondruš 11 years ago
parent
commit
609df779f5
  1. 27
      src/Magnum/Math/Dual.h
  2. 2
      src/Magnum/Math/Functions.h
  3. 29
      src/Magnum/Math/Test/DualTest.cpp

27
src/Magnum/Math/Dual.h

@ -32,6 +32,7 @@
#include <cmath>
#include <Corrade/Utility/Debug.h>
#include "Magnum/Math/Angle.h"
#include "Magnum/Math/Tags.h"
#include "Magnum/Math/TypeTraits.h"
@ -322,6 +323,32 @@ template<class T> Dual<T> sqrt(const Dual<T>& dual) {
return {sqrt0, dual.dual()/(2*sqrt0)};
}
/** @relatesalso Dual
@brief Sine and cosine of dual angle
@f[
\begin{array}{rcl}
sin(\hat a) & = & sin(a_0) + \epsilon a_\epsilon cos(a_0) \\
cos(\hat a) & = & cos(a_0) - \epsilon a_\epsilon sin(a_0)
\end{array}
@f]
@see @ref sincos(Rad<T>)
*/
/* The function accepts Unit instead of Rad to make it working with operator
products (e.g. 2*35.0_degf, which is of type Unit) */
template<class T> std::pair<Dual<T>, Dual<T>> sincos(const Dual<Rad<T>>& angle)
{
/* Not using Math::sincos(), because I don't want to include Functions.h */
const T sin = std::sin(T(angle.real()));
const T cos = std::cos(T(angle.real()));
return {{sin, T(angle.dual())*cos}, {cos, -T(angle.dual())*sin}};
}
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class T> std::pair<Dual<T>, Dual<T>> sincos(const Dual<Deg<T>>& angle) { return sincos(Dual<Rad<T>>(angle)); }
template<class T> std::pair<Dual<T>, Dual<T>> sincos(const Dual<Unit<Rad, T>>& angle) { return sincos(Dual<Rad<T>>(angle)); }
template<class T> std::pair<Dual<T>, Dual<T>> sincos(const Dual<Unit<Deg, T>>& angle) { return sincos(Dual<Rad<T>>(angle)); }
#endif
}}
#endif

2
src/Magnum/Math/Functions.h

@ -132,7 +132,7 @@ template<class T> inline T cos(Unit<Deg, T> angle) { return cos(Rad<T>(angle));
@brief Sine and cosine
On some architectures might be faster than doing both computations separately.
@see @ref sin(), @ref cos()
@see @ref sin(), @ref cos(), @ref sincos(const Dual<Rad<T>>&)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline std::pair<T, T> sincos(Rad<T> angle);

29
src/Magnum/Math/Test/DualTest.cpp

@ -51,6 +51,9 @@ struct DualTest: Corrade::TestSuite::Tester {
void conjugated();
void sqrt();
void sincos();
void sincosWithBase();
void subclassTypes();
void subclass();
@ -60,6 +63,9 @@ struct DualTest: Corrade::TestSuite::Tester {
typedef Math::Dual<Float> Dual;
typedef Math::Vector2<Float> Vector2;
typedef Math::Dual<Vector2> DualVector2;
typedef Math::Deg<Float> Deg;
typedef Math::Rad<Float> Rad;
typedef Math::Constants<Float> Constants;
DualTest::DualTest() {
addTests({&DualTest::construct,
@ -79,6 +85,9 @@ DualTest::DualTest() {
&DualTest::conjugated,
&DualTest::sqrt,
&DualTest::sincos,
&DualTest::sincosWithBase,
&DualTest::subclassTypes,
&DualTest::subclass,
@ -188,6 +197,26 @@ void DualTest::sqrt() {
CORRADE_COMPARE(Math::sqrt(Dual(16.0f, 2.0f)), Dual(4.0f, 0.25f));
}
void DualTest::sincos() {
const auto result = std::make_pair(
Dual(0.5f, 0.8660254037844386f*Constants::pi()/2),
Dual(0.8660254037844386f, -0.5f*Constants::pi()/2));
CORRADE_COMPARE(Math::sincos(Math::Dual<Deg>(30.0_degf, 90.0_degf)), result);
CORRADE_COMPARE(Math::sincos(Math::Dual<Rad>(Rad(Constants::pi()/6), Rad(Constants::pi()/2))), result);
}
void DualTest::sincosWithBase() {
/* Verify that the functions can be called with Dual<Unit<Deg, T>> and Dual<Unit<Rad, T>> */
CORRADE_VERIFY((std::is_same<decltype(2*Math::Dual<Deg>{15.0_degf}), Math::Dual<Unit<Math::Deg, Float>>>::value));
CORRADE_VERIFY((std::is_same<decltype(2*Math::Dual<Rad>{Rad{Constants::pi()/12}}), Math::Dual<Unit<Math::Rad, Float>>>::value));
const auto result = std::make_pair(
Dual(0.5f, 0.8660254037844386f*Constants::pi()/2),
Dual(0.8660254037844386f, -0.5f*Constants::pi()/2));
CORRADE_COMPARE(Math::sincos(2*Math::Dual<Deg>(15.0_degf, 45.0_degf)), result);
CORRADE_COMPARE(Math::sincos(2*Math::Dual<Rad>(Rad(Constants::pi()/12), Rad(Constants::pi()/4))), result);
}
namespace {
template<class T> class BasicDualVec2: public Math::Dual<Math::Vector2<T>> {

Loading…
Cancel
Save