Edit: /usr/include/boost/math/quaternion.hpp (49132B)
// boost quaternion.hpp header file
// (C) Copyright Hubert Holin 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_QUATERNION_HPP
#define BOOST_QUATERNION_HPP
#include
// for BOOST_NO_STD_LOCALE
#include
#include
#include
#include
#ifndef BOOST_NO_STD_LOCALE
# include // for the "<<" operator
#endif /* BOOST_NO_STD_LOCALE */
#include
#include // for the "<<" and ">>" operators
#include // for the "<<" operator
#include // for the Sinus cardinal
#include // for the Hyperbolic Sinus cardinal
#include
#if defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_SFINAE_EXPR)
#include
#endif
namespace boost
{
namespace math
{
namespace detail {
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_SFINAE_EXPR)
template
struct is_trivial_arithmetic_type_imp
{
typedef boost::integral_constant() += std::declval())
&& noexcept(std::declval() -= std::declval())
&& noexcept(std::declval() *= std::declval())
&& noexcept(std::declval() /= std::declval())
> type;
};
template
struct is_trivial_arithmetic_type : public is_trivial_arithmetic_type_imp::type {};
#else
template
struct is_trivial_arithmetic_type : public boost::is_pod {};
#endif
}
#ifndef BOOST_NO_CXX14_CONSTEXPR
namespace constexpr_detail
{
template
constexpr void swap(T& a, T& b)
{
T t(a);
a = b;
b = t;
}
}
#endif
template
class quaternion
{
public:
typedef T value_type;
// constructor for H seen as R^4
// (also default constructor)
BOOST_CONSTEXPR explicit quaternion( T const & requested_a = T(),
T const & requested_b = T(),
T const & requested_c = T(),
T const & requested_d = T())
: a(requested_a),
b(requested_b),
c(requested_c),
d(requested_d)
{
// nothing to do!
}
// constructor for H seen as C^2
BOOST_CONSTEXPR explicit quaternion( ::std::complex const & z0,
::std::complex const & z1 = ::std::complex())
: a(z0.real()),
b(z0.imag()),
c(z1.real()),
d(z1.imag())
{
// nothing to do!
}
// UNtemplated copy constructor
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
BOOST_CONSTEXPR explicit quaternion(quaternion const & a_recopier)
: a(static_cast(a_recopier.R_component_1())),
b(static_cast(a_recopier.R_component_2())),
c(static_cast(a_recopier.R_component_3())),
d(static_cast(a_recopier.R_component_4()))
{
// nothing to do!
}
// 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 practicality, there are accessors for the other components
// (these are necessary for the templated copy constructor, for instance).
BOOST_CONSTEXPR T real() const
{
return(a);
}
BOOST_CONSTEXPR quaternion unreal() const
{
return(quaternion(static_cast(0), b, c, d));
}
BOOST_CONSTEXPR T R_component_1() const
{
return(a);
}
BOOST_CONSTEXPR T R_component_2() const
{
return(b);
}
BOOST_CONSTEXPR T R_component_3() const
{
return(c);
}
BOOST_CONSTEXPR T R_component_4() const
{
return(d);
}
BOOST_CONSTEXPR ::std::complex C_component_1() const
{
return(::std::complex(a, b));
}
BOOST_CONSTEXPR ::std::complex C_component_2() const
{
return(::std::complex(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
BOOST_CXX14_CONSTEXPR quaternion & operator = (quaternion const & a_affecter)
{
a = static_cast(a_affecter.R_component_1());
b = static_cast(a_affecter.R_component_2());
c = static_cast(a_affecter.R_component_3());
d = static_cast(a_affecter.R_component_4());
return(*this);
}
BOOST_CXX14_CONSTEXPR quaternion & operator = (quaternion const & a_affecter)
{
a = a_affecter.a;
b = a_affecter.b;
c = a_affecter.c;
d = a_affecter.d;
return(*this);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_CXX14_CONSTEXPR quaternion & operator = (quaternion && a_affecter)
{
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);
}
#endif
BOOST_CXX14_CONSTEXPR quaternion & operator = (T const & a_affecter)
{
a = a_affecter;
b = c = d = static_cast(0);
return(*this);
}
BOOST_CXX14_CONSTEXPR quaternion & operator = (::std::complex const & a_affecter)
{
a = a_affecter.real();
b = a_affecter.imag();
c = d = static_cast(0);
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 & do_add(T const & rhs, const boost::true_type&)
{
a += rhs;
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_add(T const & rhs, const boost::false_type&)
{
quaternion result(a + rhs, b, c, d); // exception guard
swap(result);
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_add(std::complex const & rhs, const boost::true_type&)
{
a += std::real(rhs);
b += std::imag(rhs);
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_add(std::complex const & rhs, const boost::false_type&)
{
quaternion result(a + std::real(rhs), b + std::imag(rhs), c, d); // exception guard
swap(result);
return *this;
}
template
BOOST_CXX14_CONSTEXPR quaternion & do_add(quaternion const & rhs, const boost::true_type&)
{
a += rhs.R_component_1();
b += rhs.R_component_2();
c += rhs.R_component_3();
d += rhs.R_component_4();
return *this;
}
template
BOOST_CXX14_CONSTEXPR quaternion & do_add(quaternion const & rhs, const boost::false_type&)
{
quaternion 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;
}
BOOST_CXX14_CONSTEXPR quaternion & do_subtract(T const & rhs, const boost::true_type&)
{
a -= rhs;
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_subtract(T const & rhs, const boost::false_type&)
{
quaternion result(a - rhs, b, c, d); // exception guard
swap(result);
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_subtract(std::complex const & rhs, const boost::true_type&)
{
a -= std::real(rhs);
b -= std::imag(rhs);
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_subtract(std::complex const & rhs, const boost::false_type&)
{
quaternion result(a - std::real(rhs), b - std::imag(rhs), c, d); // exception guard
swap(result);
return *this;
}
template
BOOST_CXX14_CONSTEXPR quaternion & do_subtract(quaternion const & rhs, const boost::true_type&)
{
a -= rhs.R_component_1();
b -= rhs.R_component_2();
c -= rhs.R_component_3();
d -= rhs.R_component_4();
return *this;
}
template
BOOST_CXX14_CONSTEXPR quaternion & do_subtract(quaternion const & rhs, const boost::false_type&)
{
quaternion 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;
}
BOOST_CXX14_CONSTEXPR quaternion & do_multiply(T const & rhs, const boost::true_type&)
{
a *= rhs;
b *= rhs;
c *= rhs;
d *= rhs;
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_multiply(T const & rhs, const boost::false_type&)
{
quaternion result(a * rhs, b * rhs, c * rhs, d * rhs); // exception guard
swap(result);
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_divide(T const & rhs, const boost::true_type&)
{
a /= rhs;
b /= rhs;
c /= rhs;
d /= rhs;
return *this;
}
BOOST_CXX14_CONSTEXPR quaternion & do_divide(T const & rhs, const boost::false_type&)
{
quaternion result(a / rhs, b / rhs, c / rhs, d / rhs); // exception guard
swap(result);
return *this;
}
public:
BOOST_CXX14_CONSTEXPR quaternion & operator += (T const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type()); }
BOOST_CXX14_CONSTEXPR quaternion & operator += (::std::complex const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type()); }
template BOOST_CXX14_CONSTEXPR quaternion & operator += (quaternion const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type()); }
BOOST_CXX14_CONSTEXPR quaternion & operator -= (T const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type()); }
BOOST_CXX14_CONSTEXPR quaternion & operator -= (::std::complex const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type()); }
template BOOST_CXX14_CONSTEXPR quaternion & operator -= (quaternion const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type()); }
BOOST_CXX14_CONSTEXPR quaternion & operator *= (T const & rhs) { return do_multiply(rhs, detail::is_trivial_arithmetic_type()); }
BOOST_CXX14_CONSTEXPR quaternion & operator *= (::std::complex const & rhs)
{
T ar = rhs.real();
T br = rhs.imag();
quaternion result(a*ar - b*br, a*br + b*ar, c*ar + d*br, -c*br+d*ar);
swap(result);
return(*this);
}
template
BOOST_CXX14_CONSTEXPR quaternion & operator *= (quaternion const & rhs)
{
T ar = static_cast(rhs.R_component_1());
T br = static_cast(rhs.R_component_2());
T cr = static_cast(rhs.R_component_3());
T dr = static_cast(rhs.R_component_4());
quaternion 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);
}
BOOST_CXX14_CONSTEXPR quaternion & operator /= (T const & rhs) { return do_divide(rhs, detail::is_trivial_arithmetic_type()); }
BOOST_CXX14_CONSTEXPR quaternion & operator /= (::std::complex const & rhs)
{
T ar = rhs.real();
T br = rhs.imag();
T denominator = ar*ar+br*br;
quaternion 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);
}
template
BOOST_CXX14_CONSTEXPR quaternion & operator /= (quaternion const & rhs)
{
T ar = static_cast(rhs.R_component_1());
T br = static_cast(rhs.R_component_2());
T cr = static_cast(rhs.R_component_3());
T dr = static_cast(rhs.R_component_4());
T denominator = ar*ar+br*br+cr*cr+dr*dr;
quaternion 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);
}
private:
T a, b, c, d;
};
// swap:
template
BOOST_CXX14_CONSTEXPR void swap(quaternion& a, quaternion& b) { a.swap(b); }
// operator+
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator + (const quaternion& a, const T2& b)
{
return quaternion(static_cast(a.R_component_1() + b), a.R_component_2(), a.R_component_3(), a.R_component_4());
}
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator + (const T1& a, const quaternion& b)
{
return quaternion(static_cast(b.R_component_1() + a), b.R_component_2(), b.R_component_3(), b.R_component_4());
}
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator + (const quaternion& a, const std::complex& b)
{
return quaternion(a.R_component_1() + std::real(b), a.R_component_2() + std::imag(b), a.R_component_3(), a.R_component_4());
}
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator + (const std::complex& a, const quaternion& b)
{
return quaternion(b.R_component_1() + real(a), b.R_component_2() + imag(a), b.R_component_3(), b.R_component_4());
}
template
inline BOOST_CONSTEXPR quaternion operator + (const quaternion& a, const quaternion& b)
{
return quaternion(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
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator - (const quaternion& a, const T2& b)
{
return quaternion(static_cast(a.R_component_1() - b), a.R_component_2(), a.R_component_3(), a.R_component_4());
}
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator - (const T1& a, const quaternion& b)
{
return quaternion(static_cast(a - b.R_component_1()), -b.R_component_2(), -b.R_component_3(), -b.R_component_4());
}
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator - (const quaternion& a, const std::complex& b)
{
return quaternion(a.R_component_1() - std::real(b), a.R_component_2() - std::imag(b), a.R_component_3(), a.R_component_4());
}
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator - (const std::complex& a, const quaternion& b)
{
return quaternion(real(a) - b.R_component_1(), imag(a) - b.R_component_2(), -b.R_component_3(), -b.R_component_4());
}
template
inline BOOST_CONSTEXPR quaternion operator - (const quaternion& a, const quaternion& b)
{
return quaternion(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
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator * (const quaternion& a, const T2& b)
{
return quaternion(static_cast(a.R_component_1() * b), a.R_component_2() * b, a.R_component_3() * b, a.R_component_4() * b);
}
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator * (const T1& a, const quaternion& b)
{
return quaternion(static_cast(a * b.R_component_1()), a * b.R_component_2(), a * b.R_component_3(), a * b.R_component_4());
}
template
inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator * (const quaternion& a, const std::complex& b)
{
quaternion result(a);
result *= b;
return result;
}
template
inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator * (const std::complex& a, const quaternion& b)
{
quaternion result(a);
result *= b;
return result;
}
template
inline BOOST_CXX14_CONSTEXPR quaternion operator * (const quaternion& a, const quaternion& b)
{
quaternion result(a);
result *= b;
return result;
}
// operator/
template
inline BOOST_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator / (const quaternion& a, const T2& b)
{
return quaternion(a.R_component_1() / b, a.R_component_2() / b, a.R_component_3() / b, a.R_component_4() / b);
}
template
inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator / (const T1& a, const quaternion& b)
{
quaternion result(a);
result /= b;
return result;
}
template
inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator / (const quaternion& a, const std::complex& b)
{
quaternion result(a);
result /= b;
return result;
}
template
inline BOOST_CXX14_CONSTEXPR typename boost::enable_if_c::value, quaternion >::type
operator / (const std::complex& a, const quaternion& b)
{
quaternion result(a);
result /= b;
return result;
}
template
inline BOOST_CXX14_CONSTEXPR quaternion