summaryrefslogtreecommitdiff
path: root/boost/math/quaternion.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/math/quaternion.hpp')
-rw-r--r--boost/math/quaternion.hpp1459
1 files changed, 469 insertions, 990 deletions
diff --git a/boost/math/quaternion.hpp b/boost/math/quaternion.hpp
index d816a767cb..7b7a1aa17d 100644
--- a/boost/math/quaternion.hpp
+++ b/boost/math/quaternion.hpp
@@ -10,122 +10,70 @@
#ifndef BOOST_QUATERNION_HPP
#define BOOST_QUATERNION_HPP
-
-#include <complex>
-#include <iosfwd> // for the "<<" and ">>" operators
-#include <sstream> // for the "<<" operator
-
#include <boost/config.hpp> // for BOOST_NO_STD_LOCALE
#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/enable_if.hpp>
#ifndef BOOST_NO_STD_LOCALE
- #include <locale> // for the "<<" operator
+# include <locale> // for the "<<" operator
#endif /* BOOST_NO_STD_LOCALE */
-#include <valarray>
-
-
+#include <complex>
+#include <iosfwd> // for the "<<" and ">>" operators
+#include <sstream> // for the "<<" operator
#include <boost/math/special_functions/sinc.hpp> // for the Sinus cardinal
#include <boost/math/special_functions/sinhc.hpp> // for the Hyperbolic Sinus cardinal
+#if defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_SFINAE_EXPR)
+#include <boost/type_traits/is_pod.hpp>
+#endif
namespace boost
{
- namespace math
- {
+ namespace math
+ {
-#define BOOST_QUATERNION_ACCESSOR_GENERATOR(type) \
- type real() const \
- { \
- return(a); \
- } \
- \
- quaternion<type> unreal() const \
- { \
- return(quaternion<type>(static_cast<type>(0),b,c,d)); \
- } \
- \
- type R_component_1() const \
- { \
- return(a); \
- } \
- \
- type R_component_2() const \
- { \
- return(b); \
- } \
- \
- type R_component_3() const \
- { \
- return(c); \
- } \
- \
- type R_component_4() const \
- { \
- return(d); \
- } \
- \
- ::std::complex<type> C_component_1() const \
- { \
- return(::std::complex<type>(a,b)); \
- } \
- \
- ::std::complex<type> C_component_2() const \
- { \
- return(::std::complex<type>(c,d)); \
- }
-
-
-#define BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type) \
- template<typename X> \
- quaternion<type> & operator = (quaternion<X> const & a_affecter) \
- { \
- a = static_cast<type>(a_affecter.R_component_1()); \
- b = static_cast<type>(a_affecter.R_component_2()); \
- c = static_cast<type>(a_affecter.R_component_3()); \
- d = static_cast<type>(a_affecter.R_component_4()); \
- \
- return(*this); \
- } \
- \
- quaternion<type> & operator = (quaternion<type> const & a_affecter) \
- { \
- a = a_affecter.a; \
- b = a_affecter.b; \
- c = a_affecter.c; \
- d = a_affecter.d; \
- \
- return(*this); \
- } \
- \
- quaternion<type> & operator = (type const & a_affecter) \
- { \
- a = a_affecter; \
- \
- b = c = d = static_cast<type>(0); \
- \
- return(*this); \
- } \
- \
- quaternion<type> & operator = (::std::complex<type> const & a_affecter) \
- { \
- a = a_affecter.real(); \
- b = a_affecter.imag(); \
- \
- c = d = static_cast<type>(0); \
- \
- return(*this); \
- }
-
-
-#define BOOST_QUATERNION_MEMBER_DATA_GENERATOR(type) \
- type a; \
- type b; \
- type c; \
- type d;
-
-
- template<typename T>
+ namespace detail {
+
+#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_SFINAE_EXPR)
+
+ template <class T>
+ struct is_trivial_arithmetic_type_imp
+ {
+ typedef mpl::bool_<
+ noexcept(std::declval<T&>() += std::declval<T>())
+ && noexcept(std::declval<T&>() -= std::declval<T>())
+ && noexcept(std::declval<T&>() *= std::declval<T>())
+ && noexcept(std::declval<T&>() /= std::declval<T>())
+ > type;
+ };
+
+ template <class T>
+ struct is_trivial_arithmetic_type : public is_trivial_arithmetic_type_imp<T>::type {};
+#else
+
+ template <class T>
+ struct is_trivial_arithmetic_type : public boost::is_pod<T> {};
+
+#endif
+
+ }
+
+#ifndef BOOST_NO_CXX14_CONSTEXPR
+ namespace constexpr_detail
+ {
+ template <class T>
+ constexpr void swap(T& a, T& b)
+ {
+ T t(a);
+ a = b;
+ b = t;
+ }
+ }
+#endif
+
+ template<typename T>
class quaternion
{
public:
@@ -136,7 +84,7 @@ namespace boost
// constructor for H seen as R^4
// (also default constructor)
- explicit quaternion( T const & requested_a = T(),
+ BOOST_CONSTEXPR explicit quaternion( T const & requested_a = T(),
T const & requested_b = T(),
T const & requested_c = T(),
T const & requested_d = T())
@@ -151,7 +99,7 @@ namespace boost
// constructor for H seen as C^2
- explicit quaternion( ::std::complex<T> const & z0,
+ BOOST_CONSTEXPR explicit quaternion( ::std::complex<T> const & z0,
::std::complex<T> const & z1 = ::std::complex<T>())
: a(z0.real()),
b(z0.imag()),
@@ -163,13 +111,23 @@ namespace boost
// UNtemplated copy constructor
- // (this is taken care of by the compiler itself)
-
+ BOOST_CONSTEXPR quaternion(quaternion const & a_recopier)
+ : a(a_recopier.R_component_1()),
+ b(a_recopier.R_component_2()),
+ c(a_recopier.R_component_3()),
+ d(a_recopier.R_component_4()) {}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_CONSTEXPR quaternion(quaternion && a_recopier)
+ : a(std::move(a_recopier.R_component_1())),
+ b(std::move(a_recopier.R_component_2())),
+ c(std::move(a_recopier.R_component_3())),
+ d(std::move(a_recopier.R_component_4())) {}
+#endif
// templated copy constructor
template<typename X>
- explicit quaternion(quaternion<X> const & a_recopier)
+ BOOST_CONSTEXPR explicit quaternion(quaternion<X> const & a_recopier)
: a(static_cast<T>(a_recopier.R_component_1())),
b(static_cast<T>(a_recopier.R_component_2())),
c(static_cast<T>(a_recopier.R_component_3())),
@@ -192,857 +150,452 @@ namespace boost
// However, for practicallity, there are accessors for the other components
// (these are necessary for the templated copy constructor, for instance).
- BOOST_QUATERNION_ACCESSOR_GENERATOR(T)
-
- // assignment operators
-
- BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T)
-
- // other assignment-related operators
- //
- // NOTE: Quaternion multiplication is *NOT* commutative;
- // symbolically, "q *= rhs;" means "q = q * rhs;"
- // and "q /= rhs;" means "q = q * inverse_of(rhs);"
-
- quaternion<T> & operator += (T const & rhs)
+ BOOST_CONSTEXPR T real() const
{
- T at = a + rhs; // exception guard
-
- a = at;
-
- return(*this);
+ return(a);
}
-
-
- quaternion<T> & operator += (::std::complex<T> const & rhs)
+
+ BOOST_CONSTEXPR quaternion<T> unreal() const
{
- T at = a + rhs.real(); // exception guard
- T bt = b + rhs.imag(); // exception guard
-
- a = at;
- b = bt;
-
- return(*this);
+ return(quaternion<T>(static_cast<T>(0), b, c, d));
}
-
-
- template<typename X>
- quaternion<T> & operator += (quaternion<X> const & rhs)
+
+ BOOST_CONSTEXPR T R_component_1() const
{
- T at = a + static_cast<T>(rhs.R_component_1()); // exception guard
- T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard
- T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard
- T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ return(a);
}
-
-
-
- quaternion<T> & operator -= (T const & rhs)
+
+ BOOST_CONSTEXPR T R_component_2() const
{
- T at = a - rhs; // exception guard
-
- a = at;
-
- return(*this);
+ return(b);
}
-
-
- quaternion<T> & operator -= (::std::complex<T> const & rhs)
+
+ BOOST_CONSTEXPR T R_component_3() const
{
- T at = a - rhs.real(); // exception guard
- T bt = b - rhs.imag(); // exception guard
-
- a = at;
- b = bt;
-
- return(*this);
+ return(c);
}
-
-
- template<typename X>
- quaternion<T> & operator -= (quaternion<X> const & rhs)
+
+ BOOST_CONSTEXPR T R_component_4() const
{
- T at = a - static_cast<T>(rhs.R_component_1()); // exception guard
- T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard
- T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard
- T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ return(d);
}
-
-
- quaternion<T> & operator *= (T const & rhs)
+
+ BOOST_CONSTEXPR ::std::complex<T> C_component_1() const
{
- T at = a * rhs; // exception guard
- T bt = b * rhs; // exception guard
- T ct = c * rhs; // exception guard
- T dt = d * rhs; // exception guard
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ return(::std::complex<T>(a, b));
}
-
-
- quaternion<T> & operator *= (::std::complex<T> const & rhs)
+
+ BOOST_CONSTEXPR ::std::complex<T> C_component_2() const
{
- T ar = rhs.real();
- T br = rhs.imag();
-
- T at = +a*ar-b*br;
- T bt = +a*br+b*ar;
- T ct = +c*ar+d*br;
- T dt = -c*br+d*ar;
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ return(::std::complex<T>(c, d));
}
-
+
+ BOOST_CXX14_CONSTEXPR void swap(quaternion& o)
+ {
+#ifndef BOOST_NO_CXX14_CONSTEXPR
+ using constexpr_detail::swap;
+#else
+ using std::swap;
+#endif
+ swap(a, o.a);
+ swap(b, o.b);
+ swap(c, o.c);
+ swap(d, o.d);
+ }
+
+ // assignment operators
template<typename X>
- quaternion<T> & operator *= (quaternion<X> const & rhs)
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (quaternion<X> const & a_affecter)
{
- T ar = static_cast<T>(rhs.R_component_1());
- T br = static_cast<T>(rhs.R_component_2());
- T cr = static_cast<T>(rhs.R_component_3());
- T dr = static_cast<T>(rhs.R_component_4());
-
- T at = +a*ar-b*br-c*cr-d*dr;
- T bt = +a*br+b*ar+c*dr-d*cr; //(a*br+ar*b)+(c*dr-cr*d);
- T ct = +a*cr-b*dr+c*ar+d*br; //(a*cr+ar*c)+(d*br-dr*b);
- T dt = +a*dr+b*cr-c*br+d*ar; //(a*dr+ar*d)+(b*cr-br*c);
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ a = static_cast<T>(a_affecter.R_component_1());
+ b = static_cast<T>(a_affecter.R_component_2());
+ c = static_cast<T>(a_affecter.R_component_3());
+ d = static_cast<T>(a_affecter.R_component_4());
+
+ return(*this);
}
-
-
-
- quaternion<T> & operator /= (T const & rhs)
+
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (quaternion<T> const & a_affecter)
{
- T at = a / rhs; // exception guard
- T bt = b / rhs; // exception guard
- T ct = c / rhs; // exception guard
- T dt = d / rhs; // exception guard
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ a = a_affecter.a;
+ b = a_affecter.b;
+ c = a_affecter.c;
+ d = a_affecter.d;
+
+ return(*this);
}
-
-
- quaternion<T> & operator /= (::std::complex<T> const & rhs)
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (quaternion<T> && a_affecter)
{
- T ar = rhs.real();
- T br = rhs.imag();
-
- T denominator = ar*ar+br*br;
-
- T at = (+a*ar+b*br)/denominator; //(a*ar+b*br)/denominator;
- T bt = (-a*br+b*ar)/denominator; //(ar*b-a*br)/denominator;
- T ct = (+c*ar-d*br)/denominator; //(ar*c-d*br)/denominator;
- T dt = (+c*br+d*ar)/denominator; //(ar*d+br*c)/denominator;
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ a = std::move(a_affecter.a);
+ b = std::move(a_affecter.b);
+ c = std::move(a_affecter.c);
+ d = std::move(a_affecter.d);
+
+ return(*this);
}
-
-
- template<typename X>
- quaternion<T> & operator /= (quaternion<X> const & rhs)
+#endif
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (T const & a_affecter)
{
- T ar = static_cast<T>(rhs.R_component_1());
- T br = static_cast<T>(rhs.R_component_2());
- T cr = static_cast<T>(rhs.R_component_3());
- T dr = static_cast<T>(rhs.R_component_4());
-
- T denominator = ar*ar+br*br+cr*cr+dr*dr;
-
- T at = (+a*ar+b*br+c*cr+d*dr)/denominator; //(a*ar+b*br+c*cr+d*dr)/denominator;
- T bt = (-a*br+b*ar-c*dr+d*cr)/denominator; //((ar*b-a*br)+(cr*d-c*dr))/denominator;
- T ct = (-a*cr+b*dr+c*ar-d*br)/denominator; //((ar*c-a*cr)+(dr*b-d*br))/denominator;
- T dt = (-a*dr-b*cr+c*br+d*ar)/denominator; //((ar*d-a*dr)+(br*c-b*cr))/denominator;
-
- a = at;
- b = bt;
- c = ct;
- d = dt;
-
- return(*this);
+ a = a_affecter;
+
+ b = c = d = static_cast<T>(0);
+
+ return(*this);
}
-
-
- protected:
-
- BOOST_QUATERNION_MEMBER_DATA_GENERATOR(T)
-
-
- private:
-
- };
-
-
- // declaration of quaternion specialization
-
- template<> class quaternion<float>;
- template<> class quaternion<double>;
- template<> class quaternion<long double>;
-
-
- // helper templates for converting copy constructors (declaration)
-
- namespace detail
- {
-
- template< typename T,
- typename U
- >
- quaternion<T> quaternion_type_converter(quaternion<U> const & rhs);
- }
-
-
- // implementation of quaternion specialization
-
-
-#define BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(type) \
- explicit quaternion( type const & requested_a = static_cast<type>(0), \
- type const & requested_b = static_cast<type>(0), \
- type const & requested_c = static_cast<type>(0), \
- type const & requested_d = static_cast<type>(0)) \
- : a(requested_a), \
- b(requested_b), \
- c(requested_c), \
- d(requested_d) \
- { \
- } \
- \
- explicit quaternion( ::std::complex<type> const & z0, \
- ::std::complex<type> const & z1 = ::std::complex<type>()) \
- : a(z0.real()), \
- b(z0.imag()), \
- c(z1.real()), \
- d(z1.imag()) \
- { \
+
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (::std::complex<T> const & a_affecter)
+ {
+ a = a_affecter.real();
+ b = a_affecter.imag();
+
+ c = d = static_cast<T>(0);
+
+ return(*this);
}
-
-
-#define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
- quaternion<type> & operator += (type const & rhs) \
- { \
- a += rhs; \
- \
- return(*this); \
+
+ // other assignment-related operators
+ //
+ // NOTE: Quaternion multiplication is *NOT* commutative;
+ // symbolically, "q *= rhs;" means "q = q * rhs;"
+ // and "q /= rhs;" means "q = q * inverse_of(rhs);"
+ //
+ // Note2: Each operator comes in 2 forms - one for the simple case where
+ // type T throws no exceptions, and one exception-safe version
+ // for the case where it might.
+ private:
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(T const & rhs, const mpl::true_&)
+ {
+ a += rhs;
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
- quaternion<type> & operator += (::std::complex<type> const & rhs) \
- { \
- a += rhs.real(); \
- b += rhs.imag(); \
- \
- return(*this); \
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(T const & rhs, const mpl::false_&)
+ {
+ quaternion<T> result(a + rhs, b, c, d); // exception guard
+ swap(result);
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type) \
- template<typename X> \
- quaternion<type> & operator += (quaternion<X> const & rhs) \
- { \
- a += static_cast<type>(rhs.R_component_1()); \
- b += static_cast<type>(rhs.R_component_2()); \
- c += static_cast<type>(rhs.R_component_3()); \
- d += static_cast<type>(rhs.R_component_4()); \
- \
- return(*this); \
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(std::complex<T> const & rhs, const mpl::true_&)
+ {
+ a += std::real(rhs);
+ b += std::imag(rhs);
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
- quaternion<type> & operator -= (type const & rhs) \
- { \
- a -= rhs; \
- \
- return(*this); \
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(std::complex<T> const & rhs, const mpl::false_&)
+ {
+ quaternion<T> result(a + std::real(rhs), b + std::imag(rhs), c, d); // exception guard
+ swap(result);
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
- quaternion<type> & operator -= (::std::complex<type> const & rhs) \
- { \
- a -= rhs.real(); \
- b -= rhs.imag(); \
- \
- return(*this); \
+ template <class X>
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(quaternion<X> const & rhs, const mpl::true_&)
+ {
+ a += rhs.R_component_1();
+ b += rhs.R_component_2();
+ c += rhs.R_component_3();
+ d += rhs.R_component_4();
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type) \
- template<typename X> \
- quaternion<type> & operator -= (quaternion<X> const & rhs) \
- { \
- a -= static_cast<type>(rhs.R_component_1()); \
- b -= static_cast<type>(rhs.R_component_2()); \
- c -= static_cast<type>(rhs.R_component_3()); \
- d -= static_cast<type>(rhs.R_component_4()); \
- \
- return(*this); \
+ template <class X>
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(quaternion<X> const & rhs, const mpl::false_&)
+ {
+ quaternion<T> result(a + rhs.R_component_1(), b + rhs.R_component_2(), c + rhs.R_component_3(), d + rhs.R_component_4()); // exception guard
+ swap(result);
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
- quaternion<type> & operator *= (type const & rhs) \
- { \
- a *= rhs; \
- b *= rhs; \
- c *= rhs; \
- d *= rhs; \
- \
- return(*this); \
+
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(T const & rhs, const mpl::true_&)
+ {
+ a -= rhs;
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
- quaternion<type> & operator *= (::std::complex<type> const & rhs) \
- { \
- type ar = rhs.real(); \
- type br = rhs.imag(); \
- \
- type at = +a*ar-b*br; \
- type bt = +a*br+b*ar; \
- type ct = +c*ar+d*br; \
- type dt = -c*br+d*ar; \
- \
- a = at; \
- b = bt; \
- c = ct; \
- d = dt; \
- \
- return(*this); \
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(T const & rhs, const mpl::false_&)
+ {
+ quaternion<T> result(a - rhs, b, c, d); // exception guard
+ swap(result);
+ return *this;
}
-
-#define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type) \
- template<typename X> \
- quaternion<type> & operator *= (quaternion<X> const & rhs) \
- { \
- type ar = static_cast<type>(rhs.R_component_1()); \
- type br = static_cast<type>(rhs.R_component_2()); \
- type cr = static_cast<type>(rhs.R_component_3()); \
- type dr = static_cast<type>(rhs.R_component_4()); \
- \
- type at = +a*ar-b*br-c*cr-d*dr; \
- type bt = +a*br+b*ar+c*dr-d*cr; \
- type ct = +a*cr-b*dr+c*ar+d*br; \
- type dt = +a*dr+b*cr-c*br+d*ar; \
- \
- a = at; \
- b = bt; \
- c = ct; \
- d = dt; \
- \
- return(*this); \
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(std::complex<T> const & rhs, const mpl::true_&)
+ {
+ a -= std::real(rhs);
+ b -= std::imag(rhs);
+ return *this;
}
-
-// There is quite a lot of repetition in the code below. This is intentional.
-// The last conditional block is the normal form, and the others merely
-// consist of workarounds for various compiler deficiencies. Hopefuly, when
-// more compilers are conformant and we can retire support for those that are
-// not, we will be able to remove the clutter. This is makes the situation
-// (painfully) explicit.
-
-#define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
- quaternion<type> & operator /= (type const & rhs) \
- { \
- a /= rhs; \
- b /= rhs; \
- c /= rhs; \
- d /= rhs; \
- \
- return(*this); \
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(std::complex<T> const & rhs, const mpl::false_&)
+ {
+ quaternion<T> result(a - std::real(rhs), b - std::imag(rhs), c, d); // exception guard
+ swap(result);
+ return *this;
}
-
-#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
- #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
- quaternion<type> & operator /= (::std::complex<type> const & rhs) \
- { \
- using ::std::valarray; \
- using ::std::abs; \
- \
- valarray<type> tr(2); \
- \
- tr[0] = rhs.real(); \
- tr[1] = rhs.imag(); \
- \
- type mixam = static_cast<type>(1)/(abs(tr).max)(); \
- \
- tr *= mixam; \
- \
- valarray<type> tt(4); \
- \
- tt[0] = +a*tr[0]+b*tr[1]; \
- tt[1] = -a*tr[1]+b*tr[0]; \
- tt[2] = +c*tr[0]-d*tr[1]; \
- tt[3] = +c*tr[1]+d*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- \
- return(*this); \
+ template <class X>
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(quaternion<X> const & rhs, const mpl::true_&)
+ {
+ a -= rhs.R_component_1();
+ b -= rhs.R_component_2();
+ c -= rhs.R_component_3();
+ d -= rhs.R_component_4();
+ return *this;
}
-#else
- #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
- quaternion<type> & operator /= (::std::complex<type> const & rhs) \
- { \
- using ::std::valarray; \
- \
- valarray<type> tr(2); \
- \
- tr[0] = rhs.real(); \
- tr[1] = rhs.imag(); \
- \
- type mixam = static_cast<type>(1)/(abs(tr).max)(); \
- \
- tr *= mixam; \
- \
- valarray<type> tt(4); \
- \
- tt[0] = +a*tr[0]+b*tr[1]; \
- tt[1] = -a*tr[1]+b*tr[0]; \
- tt[2] = +c*tr[0]-d*tr[1]; \
- tt[3] = +c*tr[1]+d*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- \
- return(*this); \
+ template <class X>
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(quaternion<X> const & rhs, const mpl::false_&)
+ {
+ quaternion<T> result(a - rhs.R_component_1(), b - rhs.R_component_2(), c - rhs.R_component_3(), d - rhs.R_component_4()); // exception guard
+ swap(result);
+ return *this;
}
-#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-
-#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
- #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
- template<typename X> \
- quaternion<type> & operator /= (quaternion<X> const & rhs) \
- { \
- using ::std::valarray; \
- using ::std::abs; \
- \
- valarray<type> tr(4); \
- \
- tr[0] = static_cast<type>(rhs.R_component_1()); \
- tr[1] = static_cast<type>(rhs.R_component_2()); \
- tr[2] = static_cast<type>(rhs.R_component_3()); \
- tr[3] = static_cast<type>(rhs.R_component_4()); \
- \
- type mixam = static_cast<type>(1)/(abs(tr).max)(); \
- \
- tr *= mixam; \
- \
- valarray<type> tt(4); \
- \
- tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
- tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
- tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
- tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- \
- return(*this); \
+
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_multiply(T const & rhs, const mpl::true_&)
+ {
+ a *= rhs;
+ b *= rhs;
+ c *= rhs;
+ d *= rhs;
+ return *this;
}
-#else
- #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
- template<typename X> \
- quaternion<type> & operator /= (quaternion<X> const & rhs) \
- { \
- using ::std::valarray; \
- \
- valarray<type> tr(4); \
- \
- tr[0] = static_cast<type>(rhs.R_component_1()); \
- tr[1] = static_cast<type>(rhs.R_component_2()); \
- tr[2] = static_cast<type>(rhs.R_component_3()); \
- tr[3] = static_cast<type>(rhs.R_component_4()); \
- \
- type mixam = static_cast<type>(1)/(abs(tr).max)(); \
- \
- tr *= mixam; \
- \
- valarray<type> tt(4); \
- \
- tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
- tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
- tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
- tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
- \
- tr *= tr; \
- \
- tt *= (mixam/tr.sum()); \
- \
- a = tt[0]; \
- b = tt[1]; \
- c = tt[2]; \
- d = tt[3]; \
- \
- return(*this); \
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_multiply(T const & rhs, const mpl::false_&)
+ {
+ quaternion<T> result(a * rhs, b * rhs, c * rhs, d * rhs); // exception guard
+ swap(result);
+ return *this;
}
-#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-
-#define BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
- BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
- BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type)
-
-#define BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
- BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
- BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type)
-
-#define BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
- BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
- BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type)
-
-#define BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
- BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
- BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)
-
-#define BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
- BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type)
-
-
- template<>
- class quaternion<float>
- {
- public:
-
- typedef float value_type;
-
- BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(float)
-
- // UNtemplated copy constructor
- // (this is taken care of by the compiler itself)
-
- // explicit copy constructors (precision-loosing converters)
-
- explicit quaternion(quaternion<double> const & a_recopier)
+
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_divide(T const & rhs, const mpl::true_&)
{
- *this = detail::quaternion_type_converter<float, double>(a_recopier);
+ a /= rhs;
+ b /= rhs;
+ c /= rhs;
+ d /= rhs;
+ return *this;
}
-
- explicit quaternion(quaternion<long double> const & a_recopier)
+ BOOST_CXX14_CONSTEXPR quaternion<T> & do_divide(T const & rhs, const mpl::false_&)
{
- *this = detail::quaternion_type_converter<float, long double>(a_recopier);
+ quaternion<T> result(a / rhs, b / rhs, c / rhs, d / rhs); // exception guard
+ swap(result);
+ return *this;
}
+ public:
+
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator += (T const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type<T>()); }
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator += (::std::complex<T> const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type<T>()); }
+ template<typename X> BOOST_CXX14_CONSTEXPR quaternion<T> & operator += (quaternion<X> const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type<T>()); }
+
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator -= (T const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type<T>()); }
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator -= (::std::complex<T> const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type<T>()); }
+ template<typename X> BOOST_CXX14_CONSTEXPR quaternion<T> & operator -= (quaternion<X> const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type<T>()); }
- // destructor
- // (this is taken care of by the compiler itself)
-
- // accessors
- //
- // Note: Like complex number, quaternions do have a meaningful notion of "real part",
- // but unlike them there is no meaningful notion of "imaginary part".
- // Instead there is an "unreal part" which itself is a quaternion, and usually
- // nothing simpler (as opposed to the complex number case).
- // However, for practicallity, there are accessors for the other components
- // (these are necessary for the templated copy constructor, for instance).
-
- BOOST_QUATERNION_ACCESSOR_GENERATOR(float)
-
- // assignment operators
-
- BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(float)
-
- // other assignment-related operators
- //
- // NOTE: Quaternion multiplication is *NOT* commutative;
- // symbolically, "q *= rhs;" means "q = q * rhs;"
- // and "q /= rhs;" means "q = q * inverse_of(rhs);"
-
- BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(float)
-
-
- protected:
-
- BOOST_QUATERNION_MEMBER_DATA_GENERATOR(float)
-
-
- private:
-
- };
-
-
- template<>
- class quaternion<double>
- {
- public:
-
- typedef double value_type;
-
- BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(double)
-
- // UNtemplated copy constructor
- // (this is taken care of by the compiler itself)
-
- // converting copy constructor
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator *= (T const & rhs) { return do_multiply(rhs, detail::is_trivial_arithmetic_type<T>()); }
- explicit quaternion(quaternion<float> const & a_recopier)
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator *= (::std::complex<T> const & rhs)
{
- *this = detail::quaternion_type_converter<double, float>(a_recopier);
+ T ar = rhs.real();
+ T br = rhs.imag();
+ quaternion<T> result(a*ar - b*br, a*br + b*ar, c*ar + d*br, -c*br+d*ar);
+ swap(result);
+ return(*this);
}
- // explicit copy constructors (precision-loosing converters)
-
- explicit quaternion(quaternion<long double> const & a_recopier)
+ template<typename X>
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator *= (quaternion<X> const & rhs)
{
- *this = detail::quaternion_type_converter<double, long double>(a_recopier);
+ T ar = static_cast<T>(rhs.R_component_1());
+ T br = static_cast<T>(rhs.R_component_2());
+ T cr = static_cast<T>(rhs.R_component_3());
+ T dr = static_cast<T>(rhs.R_component_4());
+
+ quaternion<T> result(a*ar - b*br - c*cr - d*dr, a*br + b*ar + c*dr - d*cr, a*cr - b*dr + c*ar + d*br, a*dr + b*cr - c*br + d*ar);
+ swap(result);
+ return(*this);
}
- // destructor
- // (this is taken care of by the compiler itself)
-
- // accessors
- //
- // Note: Like complex number, quaternions do have a meaningful notion of "real part",
- // but unlike them there is no meaningful notion of "imaginary part".
- // Instead there is an "unreal part" which itself is a quaternion, and usually
- // nothing simpler (as opposed to the complex number case).
- // However, for practicallity, there are accessors for the other components
- // (these are necessary for the templated copy constructor, for instance).
-
- BOOST_QUATERNION_ACCESSOR_GENERATOR(double)
-
- // assignment operators
-
- BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(double)
-
- // other assignment-related operators
- //
- // NOTE: Quaternion multiplication is *NOT* commutative;
- // symbolically, "q *= rhs;" means "q = q * rhs;"
- // and "q /= rhs;" means "q = q * inverse_of(rhs);"
-
- BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(double)
-
-
- protected:
-
- BOOST_QUATERNION_MEMBER_DATA_GENERATOR(double)
-
-
- private:
-
- };
-
-
- template<>
- class quaternion<long double>
- {
- public:
-
- typedef long double value_type;
-
- BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(long double)
-
- // UNtemplated copy constructor
- // (this is taken care of by the compiler itself)
-
- // converting copy constructors
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator /= (T const & rhs) { return do_divide(rhs, detail::is_trivial_arithmetic_type<T>()); }
- explicit quaternion(quaternion<float> const & a_recopier)
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator /= (::std::complex<T> const & rhs)
{
- *this = detail::quaternion_type_converter<long double, float>(a_recopier);
+ T ar = rhs.real();
+ T br = rhs.imag();
+ T denominator = ar*ar+br*br;
+ quaternion<T> result((+a*ar + b*br) / denominator, (-a*br + b*ar) / denominator, (+c*ar - d*br) / denominator, (+c*br + d*ar) / denominator);
+ swap(result);
+ return(*this);
}
- explicit quaternion(quaternion<double> const & a_recopier)
+ template<typename X>
+ BOOST_CXX14_CONSTEXPR quaternion<T> & operator /= (quaternion<X> const & rhs)
{
- *this = detail::quaternion_type_converter<long double, double>(a_recopier);
+ T ar = static_cast<T>(rhs.R_component_1());
+ T br = static_cast<T>(rhs.R_component_2());
+ T cr = static_cast<T>(rhs.R_component_3());
+ T dr = static_cast<T>(rhs.R_component_4());
+
+ T denominator = ar*ar+br*br+cr*cr+dr*dr;
+ quaternion<T> result((+a*ar+b*br+c*cr+d*dr)/denominator, (-a*br+b*ar-c*dr+d*cr)/denominator, (-a*cr+b*dr+c*ar-d*br)/denominator, (-a*dr-b*cr+c*br+d*ar)/denominator);
+ swap(result);
+ return(*this);
}
-
- // destructor
- // (this is taken care of by the compiler itself)
-
- // accessors
- //
- // Note: Like complex number, quaternions do have a meaningful notion of "real part",
- // but unlike them there is no meaningful notion of "imaginary part".
- // Instead there is an "unreal part" which itself is a quaternion, and usually
- // nothing simpler (as opposed to the complex number case).
- // However, for practicallity, there are accessors for the other components
- // (these are necessary for the templated copy constructor, for instance).
-
- BOOST_QUATERNION_ACCESSOR_GENERATOR(long double)
-
- // assignment operators
-
- BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(long double)
-
- // other assignment-related operators
- //
- // NOTE: Quaternion multiplication is *NOT* commutative;
- // symbolically, "q *= rhs;" means "q = q * rhs;"
- // and "q /= rhs;" means "q = q * inverse_of(rhs);"
-
- BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(long double)
-
-
- protected:
-
- BOOST_QUATERNION_MEMBER_DATA_GENERATOR(long double)
-
-
private:
+ T a, b, c, d;
};
-
-
-#undef BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR
-#undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR
-#undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR
-#undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR
-#undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR
-#undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1
-#undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2
-#undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3
-#undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1
-#undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2
-#undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3
-#undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1
-#undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2
-#undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3
-#undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1
-#undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2
-#undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3
-
-#undef BOOST_QUATERNION_CONSTRUCTOR_GENERATOR
-
-
-#undef BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR
-
-#undef BOOST_QUATERNION_MEMBER_DATA_GENERATOR
-
-#undef BOOST_QUATERNION_ACCESSOR_GENERATOR
-
-
- // operators
-
-#define BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op) \
- { \
- quaternion<T> res(lhs); \
- res op##= rhs; \
- return(res); \
- }
-
-#define BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
- template<typename T> \
- inline quaternion<T> operator op (T const & lhs, quaternion<T> const & rhs) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
-
-#define BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
- template<typename T> \
- inline quaternion<T> operator op (quaternion<T> const & lhs, T const & rhs) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
-
-#define BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
- template<typename T> \
- inline quaternion<T> operator op (::std::complex<T> const & lhs, quaternion<T> const & rhs) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
-
-#define BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
- template<typename T> \
- inline quaternion<T> operator op (quaternion<T> const & lhs, ::std::complex<T> const & rhs) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
-
-#define BOOST_QUATERNION_OPERATOR_GENERATOR_3(op) \
- template<typename T> \
- inline quaternion<T> operator op (quaternion<T> const & lhs, quaternion<T> const & rhs) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
-
-#define BOOST_QUATERNION_OPERATOR_GENERATOR(op) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
- BOOST_QUATERNION_OPERATOR_GENERATOR_3(op)
-
-
- BOOST_QUATERNION_OPERATOR_GENERATOR(+)
- BOOST_QUATERNION_OPERATOR_GENERATOR(-)
- BOOST_QUATERNION_OPERATOR_GENERATOR(*)
- BOOST_QUATERNION_OPERATOR_GENERATOR(/)
+// swap:
+template <class T>
+BOOST_CXX14_CONSTEXPR void swap(quaternion<T>& a, quaternion<T>& b) { a.swap(b); }
+
+// operator+
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator + (const quaternion<T1>& a, const T2& b)
+{
+ return quaternion<T1>(static_cast<T1>(a.R_component_1() + b), a.R_component_2(), a.R_component_3(), a.R_component_4());
+}
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator + (const T1& a, const quaternion<T2>& b)
+{
+ return quaternion<T2>(static_cast<T2>(b.R_component_1() + a), b.R_component_2(), b.R_component_3(), b.R_component_4());
+}
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator + (const quaternion<T1>& a, const std::complex<T2>& b)
+{
+ return quaternion<T1>(a.R_component_1() + std::real(b), a.R_component_2() + std::imag(b), a.R_component_3(), a.R_component_4());
+}
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator + (const std::complex<T1>& a, const quaternion<T2>& b)
+{
+ return quaternion<T1>(b.R_component_1() + real(a), b.R_component_2() + imag(a), b.R_component_3(), b.R_component_4());
+}
+template <class T>
+inline BOOST_CONSTEXPR quaternion<T> operator + (const quaternion<T>& a, const quaternion<T>& b)
+{
+ return quaternion<T>(a.R_component_1() + b.R_component_1(), a.R_component_2() + b.R_component_2(), a.R_component_3() + b.R_component_3(), a.R_component_4() + b.R_component_4());
+}
+// operator-
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator - (const quaternion<T1>& a, const T2& b)
+{
+ return quaternion<T1>(static_cast<T1>(a.R_component_1() - b), a.R_component_2(), a.R_component_3(), a.R_component_4());
+}
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator - (const T1& a, const quaternion<T2>& b)
+{
+ return quaternion<T2>(static_cast<T2>(a - b.R_component_1()), -b.R_component_2(), -b.R_component_3(), -b.R_component_4());
+}
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator - (const quaternion<T1>& a, const std::complex<T2>& b)
+{
+ return quaternion<T1>(a.R_component_1() - std::real(b), a.R_component_2() - std::imag(b), a.R_component_3(), a.R_component_4());
+}
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator - (const std::complex<T1>& a, const quaternion<T2>& b)
+{
+ return quaternion<T1>(real(a) - b.R_component_1(), imag(a) - b.R_component_2(), -b.R_component_3(), -b.R_component_4());
+}
+template <class T>
+inline BOOST_CONSTEXPR quaternion<T> operator - (const quaternion<T>& a, const quaternion<T>& b)
+{
+ return quaternion<T>(a.R_component_1() - b.R_component_1(), a.R_component_2() - b.R_component_2(), a.R_component_3() - b.R_component_3(), a.R_component_4() - b.R_component_4());
+}
-#undef BOOST_QUATERNION_OPERATOR_GENERATOR
-
-#undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_L
-#undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_R
-#undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_L
-#undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_R
-#undef BOOST_QUATERNION_OPERATOR_GENERATOR_3
+// operator*
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator * (const quaternion<T1>& a, const T2& b)
+{
+ return quaternion<T1>(static_cast<T1>(a.R_component_1() * b), a.R_component_2() * b, a.R_component_3() * b, a.R_component_4() * b);
+}
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator * (const T1& a, const quaternion<T2>& b)
+{
+ return quaternion<T2>(static_cast<T2>(a * b.R_component_1()), a * b.R_component_2(), a * b.R_component_3(), a * b.R_component_4());
+}
+template <class T1, class T2>
+inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator * (const quaternion<T1>& a, const std::complex<T2>& b)
+{
+ quaternion<T1> result(a);
+ result *= b;
+ return result;
+}
+template <class T1, class T2>
+inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator * (const std::complex<T1>& a, const quaternion<T2>& b)
+{
+ quaternion<T1> result(a);
+ result *= b;
+ return result;
+}
+template <class T>
+inline BOOST_CXX14_CONSTEXPR quaternion<T> operator * (const quaternion<T>& a, const quaternion<T>& b)
+{
+ quaternion<T> result(a);
+ result *= b;
+ return result;
+}
-#undef BOOST_QUATERNION_OPERATOR_GENERATOR_BODY
+// operator/
+template <class T1, class T2>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator / (const quaternion<T1>& a, const T2& b)
+{
+ return quaternion<T1>(a.R_component_1() / b, a.R_component_2() / b, a.R_component_3() / b, a.R_component_4() / b);
+}
+template <class T1, class T2>
+inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator / (const T1& a, const quaternion<T2>& b)
+{
+ quaternion<T2> result(a);
+ result /= b;
+ return result;
+}
+template <class T1, class T2>
+inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T2, T1>::value, quaternion<T1> >::type
+operator / (const quaternion<T1>& a, const std::complex<T2>& b)
+{
+ quaternion<T1> result(a);
+ result /= b;
+ return result;
+}
+template <class T1, class T2>
+inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<T1, T2>::value, quaternion<T2> >::type
+operator / (const std::complex<T1>& a, const quaternion<T2>& b)
+{
+ quaternion<T2> result(a);
+ result /= b;
+ return result;
+}
+template <class T>
+inline BOOST_CXX14_CONSTEXPR quaternion<T> operator / (const quaternion<T>& a, const quaternion<T>& b)
+{
+ quaternion<T> result(a);
+ result /= b;
+ return result;
+}
template<typename T>
- inline quaternion<T> operator + (quaternion<T> const & q)
+ inline BOOST_CONSTEXPR const quaternion<T>& operator + (quaternion<T> const & q)
{
- return(q);
+ return q;
}
template<typename T>
- inline quaternion<T> operator - (quaternion<T> const & q)
+ inline BOOST_CONSTEXPR quaternion<T> operator - (quaternion<T> const & q)
{
return(quaternion<T>(-q.R_component_1(),-q.R_component_2(),-q.R_component_3(),-q.R_component_4()));
}
- template<typename T>
- inline bool operator == (T const & lhs, quaternion<T> const & rhs)
+ template<typename R, typename T>
+ inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<R, T>::value, bool>::type operator == (R const & lhs, quaternion<T> const & rhs)
{
return (
(rhs.R_component_1() == lhs)&&
@@ -1053,20 +606,15 @@ namespace boost
}
- template<typename T>
- inline bool operator == (quaternion<T> const & lhs, T const & rhs)
+ template<typename T, typename R>
+ inline BOOST_CONSTEXPR typename boost::enable_if_c<boost::is_convertible<R, T>::value, bool>::type operator == (quaternion<T> const & lhs, R const & rhs)
{
- return (
- (lhs.R_component_1() == rhs)&&
- (lhs.R_component_2() == static_cast<T>(0))&&
- (lhs.R_component_3() == static_cast<T>(0))&&
- (lhs.R_component_4() == static_cast<T>(0))
- );
+ return rhs == lhs;
}
template<typename T>
- inline bool operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs)
+ inline BOOST_CONSTEXPR bool operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs)
{
return (
(rhs.R_component_1() == lhs.real())&&
@@ -1078,19 +626,14 @@ namespace boost
template<typename T>
- inline bool operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
+ inline BOOST_CONSTEXPR bool operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
{
- return (
- (lhs.R_component_1() == rhs.real())&&
- (lhs.R_component_2() == rhs.imag())&&
- (lhs.R_component_3() == static_cast<T>(0))&&
- (lhs.R_component_4() == static_cast<T>(0))
- );
+ return rhs == lhs;
}
template<typename T>
- inline bool operator == (quaternion<T> const & lhs, quaternion<T> const & rhs)
+ inline BOOST_CONSTEXPR bool operator == (quaternion<T> const & lhs, quaternion<T> const & rhs)
{
return (
(rhs.R_component_1() == lhs.R_component_1())&&
@@ -1099,34 +642,12 @@ namespace boost
(rhs.R_component_4() == lhs.R_component_4())
);
}
-
-
-#define BOOST_QUATERNION_NOT_EQUAL_GENERATOR \
- { \
- return(!(lhs == rhs)); \
- }
-
- template<typename T>
- inline bool operator != (T const & lhs, quaternion<T> const & rhs)
- BOOST_QUATERNION_NOT_EQUAL_GENERATOR
-
- template<typename T>
- inline bool operator != (quaternion<T> const & lhs, T const & rhs)
- BOOST_QUATERNION_NOT_EQUAL_GENERATOR
-
- template<typename T>
- inline bool operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs)
- BOOST_QUATERNION_NOT_EQUAL_GENERATOR
-
- template<typename T>
- inline bool operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
- BOOST_QUATERNION_NOT_EQUAL_GENERATOR
-
- template<typename T>
- inline bool operator != (quaternion<T> const & lhs, quaternion<T> const & rhs)
- BOOST_QUATERNION_NOT_EQUAL_GENERATOR
-
-#undef BOOST_QUATERNION_NOT_EQUAL_GENERATOR
+
+ template<typename R, typename T> inline BOOST_CONSTEXPR bool operator != (R const & lhs, quaternion<T> const & rhs) { return !(lhs == rhs); }
+ template<typename T, typename R> inline BOOST_CONSTEXPR bool operator != (quaternion<T> const & lhs, R const & rhs) { return !(lhs == rhs); }
+ template<typename T> inline BOOST_CONSTEXPR bool operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs) { return !(lhs == rhs); }
+ template<typename T> inline BOOST_CONSTEXPR bool operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs) { return !(lhs == rhs); }
+ template<typename T> inline BOOST_CONSTEXPR bool operator != (quaternion<T> const & lhs, quaternion<T> const & rhs) { return !(lhs == rhs); }
// Note: we allow the following formats, whith a, b, c, and d reals
@@ -1421,68 +942,41 @@ namespace boost
// values
template<typename T>
- inline T real(quaternion<T> const & q)
+ inline BOOST_CONSTEXPR T real(quaternion<T> const & q)
{
return(q.real());
}
template<typename T>
- inline quaternion<T> unreal(quaternion<T> const & q)
+ inline BOOST_CONSTEXPR quaternion<T> unreal(quaternion<T> const & q)
{
return(q.unreal());
}
-
-
-#define BOOST_QUATERNION_VALARRAY_LOADER \
- using ::std::valarray; \
- \
- valarray<T> temp(4); \
- \
- temp[0] = q.R_component_1(); \
- temp[1] = q.R_component_2(); \
- temp[2] = q.R_component_3(); \
- temp[3] = q.R_component_4();
-
-
+
template<typename T>
- inline T sup(quaternion<T> const & q)
+ inline T sup(quaternion<T> const & q)
{
-#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
using ::std::abs;
-#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-
- BOOST_QUATERNION_VALARRAY_LOADER
-
- return((abs(temp).max)());
+ return (std::max)((std::max)(abs(q.R_component_1()), abs(q.R_component_2())), (std::max)(abs(q.R_component_3()), abs(q.R_component_4())));
}
template<typename T>
- inline T l1(quaternion<T> const & q)
+ inline T l1(quaternion<T> const & q)
{
-#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
- using ::std::abs;
-#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-
- BOOST_QUATERNION_VALARRAY_LOADER
-
- return(abs(temp).sum());
+ using ::std::abs;
+ return abs(q.R_component_1()) + abs(q.R_component_2()) + abs(q.R_component_3()) + abs(q.R_component_4());
}
template<typename T>
- inline T abs(quaternion<T> const & q)
+ inline T abs(quaternion<T> const & q)
{
-#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
using ::std::abs;
-#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
-
using ::std::sqrt;
- BOOST_QUATERNION_VALARRAY_LOADER
-
- T maxim = (abs(temp).max)(); // overflow protection
+ T maxim = sup(q); // overflow protection
if (maxim == static_cast<T>(0))
{
@@ -1492,31 +986,34 @@ namespace boost
{
T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions
- temp *= mixam;
-
- temp *= temp;
+ T a = q.R_component_1() * mixam;
+ T b = q.R_component_2() * mixam;
+ T c = q.R_component_3() * mixam;
+ T d = q.R_component_4() * mixam;
+
+ a *= a;
+ b *= b;
+ c *= c;
+ d *= d;
- return(maxim*sqrt(temp.sum()));
+ return(maxim * sqrt(a + b + c + d));
}
//return(sqrt(norm(q)));
}
-#undef BOOST_QUATERNION_VALARRAY_LOADER
-
-
// Note: This is the Cayley norm, not the Euclidian norm...
template<typename T>
- inline T norm(quaternion<T>const & q)
+ inline BOOST_CXX14_CONSTEXPR T norm(quaternion<T>const & q)
{
return(real(q*conj(q)));
}
template<typename T>
- inline quaternion<T> conj(quaternion<T> const & q)
+ inline BOOST_CONSTEXPR quaternion<T> conj(quaternion<T> const & q)
{
return(quaternion<T>( +q.R_component_1(),
-q.R_component_2(),
@@ -1749,24 +1246,6 @@ namespace boost
return(pow(quaternion<T>(static_cast<T>(1))/q,-n));
}
}
-
-
- // helper templates for converting copy constructors (definition)
-
- namespace detail
- {
-
- template< typename T,
- typename U
- >
- quaternion<T> quaternion_type_converter(quaternion<U> const & rhs)
- {
- return(quaternion<T>( static_cast<T>(rhs.R_component_1()),
- static_cast<T>(rhs.R_component_2()),
- static_cast<T>(rhs.R_component_3()),
- static_cast<T>(rhs.R_component_4())));
- }
- }
}
}