From 35bd69d5d3f6c7073c798363922f7b02fc466125 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Fri, 26 Feb 2016 23:19:42 +0900 Subject: [PATCH] add quaternion container interface --- sprout/complex/complex.hpp | 4 +- sprout/math/quaternion.hpp | 1517 +-------------------- sprout/math/quaternion/container.hpp | 43 + sprout/math/quaternion/quaternion.hpp | 1734 +++++++++++++++++++++++++ 4 files changed, 1781 insertions(+), 1517 deletions(-) create mode 100644 sprout/math/quaternion/container.hpp create mode 100644 sprout/math/quaternion/quaternion.hpp diff --git a/sprout/complex/complex.hpp b/sprout/complex/complex.hpp index 231b2b31..0df9718e 100644 --- a/sprout/complex/complex.hpp +++ b/sprout/complex/complex.hpp @@ -40,8 +40,8 @@ namespace sprout { typedef typename array_type::size_type size_type; typedef typename array_type::pointer pointer; typedef typename array_type::const_pointer const_pointer; - typedef typename array_type::pointer reverse_iterator; - typedef typename array_type::pointer const_reverse_iterator; + typedef typename array_type::reverse_iterator reverse_iterator; + typedef typename array_type::const_reverse_iterator const_reverse_iterator; public: SPROUT_STATIC_CONSTEXPR size_type static_size = array_type::static_size; private: diff --git a/sprout/math/quaternion.hpp b/sprout/math/quaternion.hpp index e9d38952..b4b682c5 100644 --- a/sprout/math/quaternion.hpp +++ b/sprout/math/quaternion.hpp @@ -8,1521 +8,8 @@ #ifndef SPROUT_MATH_QUATERNION_HPP #define SPROUT_MATH_QUATERNION_HPP -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -//#include -//#include -#include -#include -#include - -namespace sprout { - namespace math { - namespace detail { - template - class abs_less { - public: - SPROUT_CONSTEXPR T - operator()(T const& lhs, T const& rhs) const { - return sprout::math::abs(lhs) < sprout::math::abs(rhs); - } - }; - template - class abs_plus { - public: - SPROUT_CONSTEXPR T - operator()(T const& lhs, T const& rhs) const { - return sprout::math::abs(lhs) + sprout::math::abs(rhs); - } - }; - template - SPROUT_CONSTEXPR T - abs_max(sprout::array const& c) { - return sprout::math::abs(*sprout::range::max_element(c, sprout::math::detail::abs_less())); - } - template - SPROUT_CONSTEXPR T - sum(sprout::array const& c) { - return sprout::range::accumulate(c, static_cast(0)); - } - template - SPROUT_CONSTEXPR T - abs_sum(sprout::array const& c) { - return sprout::range::accumulate(c, static_cast(0), sprout::math::detail::abs_plus()); - } - template - SPROUT_CONSTEXPR sprout::array - mul(sprout::array const& l, T const& r) { - return sprout::array{{ - l[0] * r, - l[1] * r, - }}; - } - template - SPROUT_CONSTEXPR sprout::array - mul(sprout::array const& l, sprout::array const& r) { - return sprout::array{{ - l[0] * r[0], - l[1] * r[1], - }}; - } - template - SPROUT_CONSTEXPR sprout::array - mul(sprout::array const& l, T const& r) { - return sprout::array{{ - l[0] * r, - l[1] * r, - l[2] * r, - l[3] * r - }}; - } - template - SPROUT_CONSTEXPR sprout::array - mul(sprout::array const& l, sprout::array const& r) { - return sprout::array{{ - l[0] * r[0], - l[1] * r[1], - l[2] * r[2], - l[3] * r[3] - }}; - } - } // namespace detail - -#define SPROUT_QUATERNION_ACCESSOR_GENERATOR(type) \ - SPROUT_CONSTEXPR type real() const { \ - return (a); \ - } \ - SPROUT_CONSTEXPR quaternion unreal() const { \ - return (quaternion(static_cast(0), b, c, d)); \ - } \ - SPROUT_CONSTEXPR type R_component_1() const { \ - return (a); \ - } \ - SPROUT_CONSTEXPR type R_component_2() const { \ - return (b); \ - } \ - SPROUT_CONSTEXPR type R_component_3() const { \ - return (c); \ - } \ - SPROUT_CONSTEXPR type R_component_4() const { \ - return (d); \ - } \ - SPROUT_CONSTEXPR sprout::complex C_component_1() const { \ - return sprout::complex(a, b); \ - } \ - SPROUT_CONSTEXPR sprout::complex C_component_2() const { \ - return sprout::complex(c, d); \ - } - -#define SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type) \ - template \ - SPROUT_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; \ - } \ - SPROUT_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; \ - } \ - SPROUT_CXX14_CONSTEXPR quaternion& operator=(type const& a_affecter) { \ - a = a_affecter; \ - b = c = d = static_cast(0); \ - return *this; \ - } \ - SPROUT_CXX14_CONSTEXPR quaternion& operator=(sprout::complex const& a_affecter) { \ - a = a_affecter.real(); \ - b = a_affecter.imag(); \ - c = d = static_cast(0); \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_DATA_GENERATOR(type) \ - type a; \ - type b; \ - type c; \ - type d; - - // - // quaternion - // - template - class quaternion { - public: - typedef T value_type; - protected: - SPROUT_QUATERNION_MEMBER_DATA_GENERATOR(T) - public: - explicit SPROUT_CONSTEXPR 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) - {} - explicit SPROUT_CONSTEXPR quaternion( - sprout::complex const& z0, - sprout::complex const& z1 = sprout::complex() - ) - : a(z0.real()) - , b(z0.imag()) - , c(z1.real()) - , d(z1.imag()) - {} - template - explicit SPROUT_CONSTEXPR 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())) - {} - SPROUT_QUATERNION_ACCESSOR_GENERATOR(T) - SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T) - SPROUT_CXX14_CONSTEXPR quaternion& operator+=(T const& rhs) { - T at = a + rhs; - a = at; - return *this; - } - SPROUT_CXX14_CONSTEXPR quaternion& operator+=(sprout::complex const& rhs) { - T at = a + rhs.real(); - T bt = b + rhs.imag(); - a = at; - b = bt; - return *this; - } - template - SPROUT_CXX14_CONSTEXPR quaternion& operator+=(quaternion const& rhs) { - T at = a + static_cast(rhs.R_component_1()); - T bt = b + static_cast(rhs.R_component_2()); - T ct = c + static_cast(rhs.R_component_3()); - T dt = d + static_cast(rhs.R_component_4()); - a = at; - b = bt; - c = ct; - d = dt; - return *this; - } - SPROUT_CXX14_CONSTEXPR quaternion& operator-=(T const& rhs) { - T at = a - rhs; - a = at; - return *this; - } - SPROUT_CXX14_CONSTEXPR quaternion& operator-=(sprout::complex const& rhs) { - T at = a - rhs.real(); - T bt = b - rhs.imag(); - a = at; - b = bt; - return *this; - } - template - SPROUT_CXX14_CONSTEXPR quaternion& operator-=(quaternion const& rhs) { - T at = a - static_cast(rhs.R_component_1()); - T bt = b - static_cast(rhs.R_component_2()); - T ct = c - static_cast(rhs.R_component_3()); - T dt = d - static_cast(rhs.R_component_4()); - a = at; - b = bt; - c = ct; - d = dt; - return *this; - } - SPROUT_CXX14_CONSTEXPR quaternion& operator*=(T const& rhs) { - T at = a * rhs; - T bt = b * rhs; - T ct = c * rhs; - T dt = d * rhs; - a = at; - b = bt; - c = ct; - d = dt; - return *this; - } - SPROUT_CXX14_CONSTEXPR quaternion& operator*=(sprout::complex const& rhs) { - 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; - } - template - SPROUT_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 at = +a * ar - b * br - c * cr - d * dr; - T bt = +a * br + b * ar + c * dr - d * cr; - T ct = +a * cr - b * dr + c * ar + d * br; - T dt = +a * dr + b * cr - c * br + d * ar; - a = at; - b = bt; - c = ct; - d = dt; - return *this; - } - SPROUT_CXX14_CONSTEXPR quaternion& operator/=(T const& rhs) { - T at = a / rhs; - T bt = b / rhs; - T ct = c / rhs; - T dt = d / rhs; - a = at; - b = bt; - c = ct; - d = dt; - return *this; - } - SPROUT_CXX14_CONSTEXPR quaternion& operator/=(sprout::complex const& rhs) { - T ar = rhs.real(); - T br = rhs.imag(); - T denominator = ar * ar + br * br; - T at =(+a * ar + b * br) / denominator; - T bt =(-a * br + b * ar) / denominator; - T ct =(+c * ar - d * br) / denominator; - T dt =(+c * br + d * ar) / denominator; - a = at; - b = bt; - c = ct; - d = dt; - return *this; - } - template - SPROUT_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; - T at =(+a * ar + b * br + c * cr + d * dr) / denominator; - T bt =(-a * br + b * ar - c * dr + d * cr) / denominator; - T ct =(-a * cr + b * dr + c * ar - d * br) / denominator; - T dt =(-a * dr - b * cr + c * br + d * ar) / denominator; - a = at; - b = bt; - c = ct; - d = dt; - return *this; - } - }; - - template<> - class quaternion; - template<> - class quaternion; - template<> - class quaternion; - -#define SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(type) \ - explicit SPROUT_CONSTEXPR quaternion( \ - type const& requested_a = static_cast(0), \ - type const& requested_b = static_cast(0), \ - type const& requested_c = static_cast(0), \ - type const& requested_d = static_cast(0) \ - ) \ - : a(requested_a) \ - , b(requested_b) \ - , c(requested_c) \ - , d(requested_d) \ - {} \ - explicit SPROUT_CONSTEXPR quaternion( \ - sprout::complex const& z0, \ - sprout::complex const& z1 = sprout::complex() \ - ) \ - : a(z0.real()) \ - , b(z0.imag()) \ - , c(z1.real()) \ - , d(z1.imag()) \ - {} - -#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator+=(type const& rhs) { \ - a += rhs; \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator+=(sprout::complex const& rhs) { \ - a += rhs.real(); \ - b += rhs.imag(); \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_3(type) \ - template \ - SPROUT_CXX14_CONSTEXPR quaternion& operator+=(quaternion const& rhs) { \ - a += static_cast(rhs.R_component_1()); \ - b += static_cast(rhs.R_component_2()); \ - c += static_cast(rhs.R_component_3()); \ - d += static_cast(rhs.R_component_4()); \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator-=(type const& rhs) { \ - a -= rhs; \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator-=(sprout::complex const& rhs) { \ - a -= rhs.real(); \ - b -= rhs.imag(); \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_3(type) \ - template \ - SPROUT_CXX14_CONSTEXPR quaternion& operator-=(quaternion const& rhs) { \ - a -= static_cast(rhs.R_component_1()); \ - b -= static_cast(rhs.R_component_2()); \ - c -= static_cast(rhs.R_component_3()); \ - d -= static_cast(rhs.R_component_4()); \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator*=(type const& rhs) { \ - a *= rhs; \ - b *= rhs; \ - c *= rhs; \ - d *= rhs; \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator*=(sprout::complex 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; \ - } - -#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_3(type) \ - template \ - SPROUT_CXX14_CONSTEXPR quaternion& operator*=(quaternion const& rhs) { \ - type ar = static_cast(rhs.R_component_1()); \ - type br = static_cast(rhs.R_component_2()); \ - type cr = static_cast(rhs.R_component_3()); \ - type dr = static_cast(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; \ - } - -#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator/=(type const& rhs) { \ - a /= rhs; \ - b /= rhs; \ - c /= rhs; \ - d /= rhs; \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \ - SPROUT_CXX14_CONSTEXPR quaternion& operator/=(sprout::complex const& rhs) { \ - sprout::array tr{{ \ - rhs.real(), \ - rhs.imag() \ - }}; \ - type mixam = static_cast(1) / sprout::math::detail::abs_max(tr); \ - tr = sprout::math::detail::mul(tr, mixam); \ - sprout::array tt{{ \ - +a * tr[0] + b * tr[1], \ - -a * tr[1] + b * tr[0], \ - +c * tr[0] - d * tr[1], \ - +c * tr[1] + d * tr[0] \ - }}; \ - tr = sprout::math::detail::mul(tr, tr); \ - tt = sprout::math::detail::mul(tt, mixam / sprout::math::detail::sum(tr)); \ - a = tt[0]; \ - b = tt[1]; \ - c = tt[2]; \ - d = tt[3]; \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \ - template \ - SPROUT_CXX14_CONSTEXPR quaternion& operator/=(quaternion const& rhs) { \ - sprout::array tr{{ \ - static_cast(rhs.R_component_1()), \ - static_cast(rhs.R_component_2()), \ - static_cast(rhs.R_component_3()), \ - static_cast(rhs.R_component_4()) \ - }}; \ - type mixam = static_cast(1) / sprout::math::detail::abs_max(tr); \ - tr = sprout::math::detail::mul(tr, mixam); \ - sprout::array tt{{ \ - +a * tr[0] + b * tr[1] + c * tr[2] + d * tr[3], \ - -a * tr[1] + b * tr[0] - c * tr[3] + d * tr[2], \ - -a * tr[2] + b * tr[3] + c * tr[0] - d * tr[1], \ - -a * tr[3] - b * tr[2] + c * tr[1] + d * tr[0] \ - }}; \ - tr = sprout::math::detail::mul(tr, tr); \ - tt = sprout::math::detail::mul(tt, mixam / sprout::math::detail::sum(tr)); \ - a = tt[0]; \ - b = tt[1]; \ - c = tt[2]; \ - d = tt[3]; \ - return *this; \ - } - -#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \ - SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \ - SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_3(type) - -#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \ - SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \ - SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_3(type) - -#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \ - SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \ - SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_3(type) - -#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \ - SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \ - SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_3(type) - -#define SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_ADD_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_SUB_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_MUL_GENERATOR(type) \ - SPROUT_QUATERNION_MEMBER_DIV_GENERATOR(type) - - template<> - class quaternion { - public: - typedef float value_type; - protected: - SPROUT_QUATERNION_MEMBER_DATA_GENERATOR(float) - public: - SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(float) - explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); - explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); - SPROUT_QUATERNION_ACCESSOR_GENERATOR(float) - SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(float) - SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(float) - }; - - template<> - class quaternion { - public: - typedef double value_type; - protected: - SPROUT_QUATERNION_MEMBER_DATA_GENERATOR(double) - public: - SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(double) - explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); - explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); - SPROUT_QUATERNION_ACCESSOR_GENERATOR(double) - SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(double) - SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(double) - }; - - template<> - class quaternion { - public: - typedef double value_type; - protected: - SPROUT_QUATERNION_MEMBER_DATA_GENERATOR(long double) - public: - SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(long double) - explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); - explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); - SPROUT_QUATERNION_ACCESSOR_GENERATOR(long double) - SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(long double) - SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(long double) - }; - - SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::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())) - {} - SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::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())) - {} - - SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::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())) - {} - SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::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())) - {} - - SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::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())) - {} - SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::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())) - {} - -#undef SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR -#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR -#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR -#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR -#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR -#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_1 -#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_2 -#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_3 -#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_1 -#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_2 -#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_3 -#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_1 -#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_2 -#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_3 -#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_1 -#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_2 -#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_3 -#undef SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR -#undef SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR -#undef SPROUT_QUATERNION_MEMBER_DATA_GENERATOR -#undef SPROUT_QUATERNION_ACCESSOR_GENERATOR - - // - // operator+ - // - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator+(T const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs + rhs.R_component_1(), - rhs.R_component_2(), - rhs.R_component_3(), - rhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator+(sprout::math::quaternion const& lhs, T const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() + rhs, - lhs.R_component_2(), - lhs.R_component_3(), - lhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator+(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs.real() + rhs.R_component_1(), - lhs.imag() + rhs.R_component_2(), - rhs.R_component_3(), - rhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator+(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() + rhs.real(), - lhs.R_component_2() + rhs.imag(), - lhs.R_component_3(), - lhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator+(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() + rhs.R_component_1(), - lhs.R_component_2() + rhs.R_component_2(), - lhs.R_component_3() + rhs.R_component_3(), - lhs.R_component_4() + rhs.R_component_4() - ); - } - // - // operator- - // - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator-(T const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs - rhs.R_component_1(), - rhs.R_component_2(), - rhs.R_component_3(), - rhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator-(sprout::math::quaternion const& lhs, T const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() - rhs, - lhs.R_component_2(), - lhs.R_component_3(), - lhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator-(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs.real() - rhs.R_component_1(), - lhs.imag() - rhs.R_component_2(), - rhs.R_component_3(), - rhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator-(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() - rhs.real(), - lhs.R_component_2() - rhs.imag(), - lhs.R_component_3(), - lhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator-(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() - rhs.R_component_1(), - lhs.R_component_2() - rhs.R_component_2(), - lhs.R_component_3() - rhs.R_component_3(), - lhs.R_component_4() - rhs.R_component_4() - ); - } - // - // operator* - // - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator*(T const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs * rhs.R_component_1(), - lhs * rhs.R_component_2(), - lhs * rhs.R_component_3(), - lhs * rhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator*(sprout::math::quaternion const& lhs, T const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() * rhs, - lhs.R_component_2() * rhs, - lhs.R_component_3() * rhs, - lhs.R_component_4() * rhs - ); - } - namespace detail { - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - mul_qc_impl(T const& a, T const& b, T const& c, T const& d, T const& ar, T const& br) { - return sprout::math::quaternion( - +a * ar - b * br, - +a * br + b * ar, - +c * ar + d * br, - -c * br + d * ar - ); - } - } // namespace detail - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator*(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::detail::mul_qc_impl( - lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), - rhs.real(), rhs.imag() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator*(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { - return sprout::math::detail::mul_qc_impl( - rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4(), - lhs.real(), lhs.imag() - ); - } - namespace detail { - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - mul_qq_impl(T const& a, T const& b, T const& c, T const& d, T const& ar, T const& br, T const& cr, T const& dr) { - return sprout::math::quaternion( - +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 - ); - } - } // namespace detail - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator*(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::detail::mul_qq_impl( - lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), - rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4() - ); - } - // - // operator/ - // - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator/(T const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::quaternion( - lhs / rhs.R_component_1(), - lhs / rhs.R_component_2(), - lhs / rhs.R_component_3(), - lhs / rhs.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator/(sprout::math::quaternion const& lhs, T const& rhs) { - return sprout::math::quaternion( - lhs.R_component_1() / rhs, - lhs.R_component_2() / rhs, - lhs.R_component_3() / rhs, - lhs.R_component_4() / rhs - ); - } - namespace detail { - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - div_qq_impl_4(sprout::array const& tt) { - return sprout::math::quaternion( - tt[0], tt[1], tt[2], tt[3] - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - div_qq_impl_3(sprout::array const& tr, T const& mixam, sprout::array const& tt) { - return sprout::math::detail::div_qq_impl_3( - sprout::math::detail::mul(tt, mixam / sprout::math::detail::sum(tr)) - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - div_qq_impl_2(T const& a, T const& b, T const& c, T const& d, sprout::array const& tr, T const& mixam) { - return sprout::math::detail::div_qq_impl_3( - sprout::math::detail::mul(tr, tr), mixam, - sprout::array{{ - +a * tr[0] + b * tr[1] + c * tr[2] + d * tr[3], - -a * tr[1] + b * tr[0] - c * tr[3] + d * tr[2], - -a * tr[2] + b * tr[3] + c * tr[0] - d * tr[1], - -a * tr[3] - b * tr[2] + c * tr[1] + d * tr[0] - }} - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - div_qq_impl_1(T const& a, T const& b, T const& c, T const& d, sprout::array const& tr, T const& mixam) { - return sprout::math::detail::div_qq_impl_2( - a, b, c, d, sprout::math::detail::mul(tr, mixam), mixam - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - div_qq_impl(T const& a, T const& b, T const& c, T const& d, sprout::array const& tr) { - return sprout::math::detail::div_qq_impl_1( - a, b, c, d, tr, - static_cast(1) / sprout::math::detail::abs_max(tr) - ); - } - } // namespace detail - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator/(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::detail::div_qq_impl( - lhs.real(), lhs.imag(), static_cast(0), static_cast(0), - sprout::array{{rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4()}} - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator/(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { - return sprout::math::detail::div_qq_impl( - lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), - sprout::array{{rhs.real(), rhs.imag(), static_cast(0), static_cast(0)}} - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator/(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { - return sprout::math::detail::div_qq_impl( - lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), - sprout::array{{rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4()}} - ); - } - - // - // operator+ - // operator- - // - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator+(sprout::math::quaternion const& q) { - return q; - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - operator-(sprout::math::quaternion const& q) { - return sprout::math::quaternion(-q.R_component_1(), -q.R_component_2(), -q.R_component_3(), -q.R_component_4()); - } - - // - // operator== - // operator!= - // - template - inline SPROUT_CONSTEXPR bool - operator==(T const& lhs, sprout::math::quaternion const& rhs) { - return rhs.R_component_1() == lhs - && rhs.R_component_2() == static_cast(0) - && rhs.R_component_3() == static_cast(0) - && rhs.R_component_4() == static_cast(0) - ; - } - template - inline SPROUT_CONSTEXPR bool - operator==(sprout::math::quaternion const& lhs, T const& rhs) { - return lhs.R_component_1() == rhs - && lhs.R_component_2() == static_cast(0) - && lhs.R_component_3() == static_cast(0) - && lhs.R_component_4() == static_cast(0) - ; - } - template - inline SPROUT_CONSTEXPR bool - operator==(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { - return rhs.R_component_1() == lhs.real() - && rhs.R_component_2() == lhs.imag() - && rhs.R_component_3() == static_cast(0) - && rhs.R_component_4() == static_cast(0) - ; - } - template - inline SPROUT_CONSTEXPR bool - operator==(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { - return lhs.R_component_1() == rhs.real() - && lhs.R_component_2() == rhs.imag() - && lhs.R_component_3() == static_cast(0) - && lhs.R_component_4() == static_cast(0) - ; - } - template - inline SPROUT_CONSTEXPR bool - operator==(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { - return rhs.R_component_1() == lhs.R_component_1() - && rhs.R_component_2() == lhs.R_component_2() - && rhs.R_component_3() == lhs.R_component_3() - && rhs.R_component_4() == lhs.R_component_4() - ; - } - -#define SPROUT_QUATERNION_NOT_EQUAL_GENERATOR \ - { \ - return !(lhs == rhs); \ - } - - template - inline SPROUT_CONSTEXPR bool - operator!=(T const& lhs, sprout::math::quaternion const& rhs) - SPROUT_QUATERNION_NOT_EQUAL_GENERATOR - template - inline SPROUT_CONSTEXPR bool - operator!=(sprout::math::quaternion const& lhs, T const& rhs) - SPROUT_QUATERNION_NOT_EQUAL_GENERATOR - template - inline SPROUT_CONSTEXPR bool - operator!=(sprout::complex const& lhs, sprout::math::quaternion const& rhs) - SPROUT_QUATERNION_NOT_EQUAL_GENERATOR - template - inline SPROUT_CONSTEXPR bool - operator!=(sprout::math::quaternion const& lhs, sprout::complex const& rhs) - SPROUT_QUATERNION_NOT_EQUAL_GENERATOR - template - inline SPROUT_CONSTEXPR bool - operator!=(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) - SPROUT_QUATERNION_NOT_EQUAL_GENERATOR - -#undef SPROUT_QUATERNION_NOT_EQUAL_GENERATOR - - // - // operator<< - // operator>> - // - template - inline SPROUT_NON_CONSTEXPR std::basic_ostream& - operator<<( std::basic_ostream& lhs, sprout::math::quaternion const& rhs) { - std::basic_ostringstream s; - s.flags(lhs.flags()); - s.imbue(lhs.getloc()); - s.precision(lhs.precision()); - s - << '(' - << rhs.R_component_1() << ',' - << rhs.R_component_2() << ',' - << rhs.R_component_3() << ',' - << rhs.R_component_4() - << ')' - ; - return lhs << s.str(); - } - template - inline SPROUT_NON_CONSTEXPR std::basic_istream& - operator>>(std::basic_istream& lhs, sprout::math::quaternion& rhs) { - std::ctype const& ct = std::use_facet >(lhs.getloc()); - T a = T(); - T b = T(); - T c = T(); - T d = T(); - sprout::complex u = sprout::complex(); - sprout::complex v = sprout::complex(); - Elem ch = Elem(); - char cc; - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == '(') { - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == '(') { - lhs.putback(ch); - lhs >> u; - a = u.real(); - b = u.imag(); - if (!lhs.good()) { - goto finish; - } - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == ')') { - rhs = sprout::math::quaternion(a, b); - } else if (cc == ',') { - lhs >> v; - c = v.real(); - d = v.imag(); - if (!lhs.good()) { - goto finish; - } - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == ')') { - rhs = sprout::math::quaternion(a, b, c, d); - } else { - lhs.setstate(std::ios_base::failbit); - } - } else { - lhs.setstate(std::ios_base::failbit); - } - } else { - lhs.putback(ch); - lhs >> a; - if (!lhs.good()) { - goto finish; - } - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == ')') { - rhs = sprout::math::quaternion(a); - } else if (cc == ',') { - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == '(') { - lhs.putback(ch); - lhs >> v; - c = v.real(); - d = v.imag(); - if (!lhs.good()) { - goto finish; - } - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == ')') { - rhs = sprout::math::quaternion(a, b, c, d); - } else { - lhs.setstate(std::ios_base::failbit); - } - } else { - lhs.putback(ch); - lhs >> b; - if (!lhs.good()) { - goto finish; - } - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == ')') { - rhs = sprout::math::quaternion(a, b); - } else if (cc == ',') { - lhs >> c; - if (!lhs.good()) { - goto finish; - } - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == ')') { - rhs = sprout::math::quaternion(a, b, c); - } else if (cc == ',') { - lhs >> d; - if (!lhs.good()) { - goto finish; - } - lhs >> ch; - if (!lhs.good()) { - goto finish; - } - cc = ct.narrow(ch, char()); - if (cc == ')') { - rhs = sprout::math::quaternion(a, b, c, d); - } else { - lhs.setstate(std::ios_base::failbit); - } - } else { - lhs.setstate(std::ios_base::failbit); - } - } else { - lhs.setstate(std::ios_base::failbit); - } - } - } else { - lhs.setstate(std::ios_base::failbit); - } - } - } else { - lhs.putback(ch); - lhs >> a; - if (!lhs.good()) { - goto finish; - } - rhs = sprout::math::quaternion(a); - } - finish: - return lhs; - } - - // - // real - // unreal - // - template - inline SPROUT_CONSTEXPR T - real(sprout::math::quaternion const& q) { - return q.real(); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - unreal(sprout::math::quaternion const& q) { - return q.unreal(); - } - - // - // sup - // l1 - // - template - inline SPROUT_CONSTEXPR T - sup(sprout::math::quaternion const& q) { - return sprout::math::detail::abs_max( - sprout::array{{ - q.R_component_1(), - q.R_component_2(), - q.R_component_3(), - q.R_component_4() - }} - ); - } - template - inline SPROUT_CONSTEXPR T - l1(sprout::math::quaternion const& q) { - return sprout::math::detail::abs_sum( - sprout::array{{ - q.R_component_1(), - q.R_component_2(), - q.R_component_3(), - q.R_component_4() - }} - ); - } - - // - // abs - // - namespace detail { - template - inline SPROUT_CONSTEXPR T - abs_q_impl_3(sprout::array const& temp, T const& maxim) { - return maxim * sprout::math::sqrt(sprout::math::detail::sum(sprout::math::detail::mul(temp, temp))); - } - template - inline SPROUT_CONSTEXPR T - abs_q_impl_2(sprout::array const& temp, T const& maxim) { - return sprout::math::detail::abs_q_impl_3( - sprout::math::detail::mul(temp, maxim), maxim - ); - } - template - inline SPROUT_CONSTEXPR T - abs_q_impl_1(sprout::array const& temp, T const& maxim) { - return maxim == static_cast(0) ? sprout::math::quaternion(maxim) - : sprout::math::detail::abs_q_impl_2( - temp, static_cast(1) / maxim - ) - ; - } - template - inline SPROUT_CONSTEXPR T - abs_q_impl(sprout::array const& temp) { - return sprout::math::detail::abs_q_impl_1( - temp, sprout::math::detail::abs_max(temp) - ); - } - } // namespace detail - template - inline SPROUT_CONSTEXPR T - abs(sprout::math::quaternion const& q) { - return sprout::math::detail::abs_q_impl( - sprout::array{{ - q.R_component_1(), - q.R_component_2(), - q.R_component_3(), - q.R_component_4() - }} - ); - } - -#undef SPROUT_QUATERNION_ARRAY_LOADER - - // - // conj - // norm - // - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - conj(sprout::math::quaternion const& q) { - return sprout::math::quaternion( - +q.R_component_1(), - -q.R_component_2(), - -q.R_component_3(), - -q.R_component_4() - ); - } - template - inline SPROUT_CONSTEXPR T - norm(sprout::math::quaternion const& q) { - return sprout::math::real(q * sprout::math::conj(q)); - } - - // - // spherical - // semipolar - // multipolar - // cylindrospherical - // cylindrical - // - namespace detail { - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - spherical_impl(T const& rho, T const& theta, T const& phi1, T const& phi2, T const& p1, T const& p2) { - return rho * sprout::math::quaternion( - sprout::math::cos(theta) * (p2 * p1), - sprout::math::sin(theta) * (p2 * p1), - sprout::math::sin(phi1) * p2, - sprout::math::sin(phi2) - ); - } - } // namespace detail - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - spherical(T const& rho, T const& theta, T const& phi1, T const& phi2) { - return sprout::math::detail::spherical_impl( - rho, theta, phi1, phi2, - sprout::math::cos(phi1), sprout::math::cos(phi2) - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - semipolar(T const& rho, T const& alpha, T const& theta1, T const& theta2) { - return rho * sprout::math::quaternion( - sprout::math::cos(alpha) * sprout::math::cos(theta1), - sprout::math::cos(alpha) * sprout::math::sin(theta1), - sprout::math::sin(alpha) * sprout::math::cos(theta2), - sprout::math::sin(alpha) * sprout::math::sin(theta2) - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - multipolar(T const& rho1, T const& theta1, T const& rho2, T const& theta2) { - return sprout::math::quaternion( - rho1 * sprout::math::cos(theta1), - rho1 * sprout::math::sin(theta1), - rho2 * sprout::math::cos(theta2), - rho2 * sprout::math::sin(theta2) - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - cylindrospherical(T const& t, T const& radius, T const& longitude, T const& latitude) { - return sprout::math::quaternion( - t, - radius * sprout::math::cos(longitude) * sprout::math::cos(latitude), - radius * sprout::math::sin(longitude) * sprout::math::cos(latitude), - radius * sprout::math::sin(latitude) - ); - } - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - cylindrical(T const& r, T const& angle, T const& h1, T const& h2) { - return sprout::math::quaternion( - r * sprout::math::cos(angle), - r * sprout::math::sin(angle), - h1, - h2 - ); - } - - // - // exp - // - // !!! -// namespace detail { -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// exp_impl_1(sprout::math::quaternion const& q, T const& z, T const& w) { -// return sprout::math::exp(sprout::math::real(q)) * sprout::math::quaternion( -// sprout::math::cos(z), -// w * q.R_component_2(), -// w * q.R_component_3(), -// w * q.R_component_4() -// ); -// } -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// exp_impl(sprout::math::quaternion const& q, T const& z) { -// return sprout::math::detail::exp_impl_1( -// q, z, -// sprout::math::sinc_pi(z) -// ); -// } -// } // namespace detail -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// exp(sprout::math::quaternion const& q) { -// return sprout::math::detail::exp_impl( -// q, -// sprout::math::abs(sprout::math::unreal(q)) -// ); -// } - - // - // cos - // sin - // tan - // - // !!! -// namespace detail { -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// cos_impl_1(sprout::math::quaternion const& q, T const& z, T const& w) { -// return sprout::math::quaternion( -// sprout::math::cos(q.real()) * sprout::math::cosh(z), -// w * q.R_component_2(), -// w * q.R_component_3(), -// w * q.R_component_4() -// ); -// } -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// cos_impl(sprout::math::quaternion const& q, T const& z) { -// return sprout::math::detail::cos_impl_1( -// q, z, -// -sprout::math::sin(q.real()) * sprout::math::sinhc_pi(z) -// ); -// } -// } // namespace detail -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// cos(sprout::math::quaternion const& q) { -// return sprout::math::detail::cos_impl( -// q, -// sprout::math::abs(sprout::math::unreal(q)) -// ); -// } -// namespace detail { -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// sin_impl_1(sprout::math::quaternion const& q, T const& z, T const& w) { -// return sprout::math::quaternion( -// sprout::math::sin(q.real()) * sprout::math::cosh(z), -// w * q.R_component_2(), -// w * q.R_component_3(), -// w * q.R_component_4() -// ); -// } -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// sin_impl(sprout::math::quaternion const& q, T const& z) { -// return sprout::math::detail::sin_impl_1( -// q, z, -// +sprout::math::cos(q.real()) * sprout::math::sinhc_pi(z) -// ); -// } -// } // namespace detail -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// sin(sprout::math::quaternion const& q) { -// return sprout::math::detail::sin_impl( -// q, -// sprout::math::abs(sprout::math::unreal(q)) -// ); -// } -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// tan(sprout::math::quaternion const& q) { -// return sprout::math::sin(q) / sprout::math::cos(q); -// } - - // - // cosh - // sinh - // tanh - // - // !!! -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// cosh(sprout::math::quaternion const& q) { -// return (sprout::math::exp(+q) + sprout::math::exp(-q)) / static_cast(2); -// } -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// sinh(sprout::math::quaternion const& q) { -// return (sprout::math::exp(+q) - sprout::math::exp(-q)) / static_cast(2); -// } -// template -// inline SPROUT_CONSTEXPR sprout::math::quaternion -// tanh(sprout::math::quaternion const& q) { -// return sprout::math::sinh(q) / sprout::math::cosh(q); -// } - - // - // pow - // - namespace detail { - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - pow_q_impl(sprout::math::quaternion const& q, int n, int m, sprout::math::quaternion const& result) { - return n != m << 1 ? result * result * q - : result * result - ; - } - } // namespace detail - template - inline SPROUT_CONSTEXPR sprout::math::quaternion - pow(sprout::math::quaternion const& q, int n) { - return n > 1 ? sprout::math::detail::pow_q_impl( - q, n, n >> 1, sprout::math::pow(q, n >> 1) - ) - : n == 1 ? q - : n == 0 ? sprout::math::quaternion(static_cast(1)) - : sprout::math::pow(sprout::math::quaternion(static_cast(1)) / q, -n) - ; - } - } // namespace math - - using sprout::math::quaternion; - using sprout::math::real; - using sprout::math::unreal; - using sprout::math::sup; - using sprout::math::l1; - using sprout::math::abs; - using sprout::math::conj; - using sprout::math::norm; - using sprout::math::spherical; - using sprout::math::semipolar; - using sprout::math::multipolar; - using sprout::math::cylindrospherical; - using sprout::math::cylindrical; -// using sprout::math::exp; -// using sprout::math::cos; -// using sprout::math::sin; -// using sprout::math::tan; -// using sprout::math::cosh; -// using sprout::math::sinh; -// using sprout::math::tanh; - using sprout::math::pow; -} // namespace sprout +#include +#include #endif // #ifndef SPROUT_MATH_QUATERNION_HPP diff --git a/sprout/math/quaternion/container.hpp b/sprout/math/quaternion/container.hpp new file mode 100644 index 00000000..9f66d093 --- /dev/null +++ b/sprout/math/quaternion/container.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + 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) +=============================================================================*/ +#ifndef SPROUT_QUATERNION_CONTAINER_HPP +#define SPROUT_QUATERNION_CONTAINER_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // container_construct_traits + // + template + struct container_construct_traits > { + public: + typedef sprout::math::quaternion copied_type; + public: + template + static SPROUT_CONSTEXPR copied_type + deep_copy(Cont&& cont) { + return SPROUT_FORWARD(Cont, cont); + } + template + static SPROUT_CONSTEXPR copied_type + make(Args&&... args) { + return copied_type(SPROUT_FORWARD(Args, args)...); + } + template + static SPROUT_CONSTEXPR copied_type + remake(Cont&&, typename sprout::container_traits >::difference_type, Args&&... args) { + return copied_type(SPROUT_FORWARD(Args, args)...); + } + }; +} // namespace sprout + +#endif // #ifndef SPROUT_QUATERNION_CONTAINER_HPP diff --git a/sprout/math/quaternion/quaternion.hpp b/sprout/math/quaternion/quaternion.hpp new file mode 100644 index 00000000..6cd10073 --- /dev/null +++ b/sprout/math/quaternion/quaternion.hpp @@ -0,0 +1,1734 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the sprout Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.sprout.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_MATH_QUATERNION_QUATERNION_HPP +#define SPROUT_MATH_QUATERNION_QUATERNION_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include + +namespace sprout { + namespace math { + namespace detail { + template + class abs_less { + public: + SPROUT_CONSTEXPR T + operator()(T const& lhs, T const& rhs) const { + return sprout::math::abs(lhs) < sprout::math::abs(rhs); + } + }; + template + class abs_plus { + public: + SPROUT_CONSTEXPR T + operator()(T const& lhs, T const& rhs) const { + return sprout::math::abs(lhs) + sprout::math::abs(rhs); + } + }; + template + SPROUT_CONSTEXPR T + abs_max(sprout::array const& c) { + return sprout::math::abs(*sprout::range::max_element(c, sprout::math::detail::abs_less())); + } + template + SPROUT_CONSTEXPR T + sum(sprout::array const& c) { + return sprout::range::accumulate(c, static_cast(0)); + } + template + SPROUT_CONSTEXPR T + abs_sum(sprout::array const& c) { + return sprout::range::accumulate(c, static_cast(0), sprout::math::detail::abs_plus()); + } + template + SPROUT_CONSTEXPR sprout::array + mul(sprout::array const& l, T const& r) { + return sprout::array{{ + l[0] * r, + l[1] * r, + }}; + } + template + SPROUT_CONSTEXPR sprout::array + mul(sprout::array const& l, sprout::array const& r) { + return sprout::array{{ + l[0] * r[0], + l[1] * r[1], + }}; + } + template + SPROUT_CONSTEXPR sprout::array + mul(sprout::array const& l, T const& r) { + return sprout::array{{ + l[0] * r, + l[1] * r, + l[2] * r, + l[3] * r + }}; + } + template + SPROUT_CONSTEXPR sprout::array + mul(sprout::array const& l, sprout::array const& r) { + return sprout::array{{ + l[0] * r[0], + l[1] * r[1], + l[2] * r[2], + l[3] * r[3] + }}; + } + } // namespace detail + +#define SPROUT_QUATERNION_ACCESSOR_GENERATOR(type) \ + SPROUT_CONSTEXPR type real() const { \ + return (elems_[0]); \ + } \ + SPROUT_CONSTEXPR quaternion unreal() const { \ + return (quaternion(static_cast(0), elems_[1], elems_[2], elems_[3])); \ + } \ + SPROUT_CONSTEXPR type R_component_1() const { \ + return (elems_[0]); \ + } \ + SPROUT_CONSTEXPR type R_component_2() const { \ + return (elems_[1]); \ + } \ + SPROUT_CONSTEXPR type R_component_3() const { \ + return (elems_[2]); \ + } \ + SPROUT_CONSTEXPR type R_component_4() const { \ + return (elems_[3]); \ + } \ + SPROUT_CONSTEXPR sprout::complex C_component_1() const { \ + return sprout::complex(elems_[0], elems_[1]); \ + } \ + SPROUT_CONSTEXPR sprout::complex C_component_2() const { \ + return sprout::complex(elems_[2], elems_[3]); \ + } + +#define SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type) \ + template \ + SPROUT_CXX14_CONSTEXPR quaternion& operator=(quaternion const& a_affecter) { \ + elems_[0] = static_cast(a_affecter.R_component_1()); \ + elems_[1] = static_cast(a_affecter.R_component_2()); \ + elems_[2] = static_cast(a_affecter.R_component_3()); \ + elems_[3] = static_cast(a_affecter.R_component_4()); \ + return *this; \ + } \ + SPROUT_CXX14_CONSTEXPR quaternion& operator=(quaternion const& a_affecter) { \ + elems_[0] = a_affecter.elems_[0]; \ + elems_[1] = a_affecter.elems_[1]; \ + elems_[2] = a_affecter.elems_[2]; \ + elems_[3] = a_affecter.elems_[3]; \ + return *this; \ + } \ + SPROUT_CXX14_CONSTEXPR quaternion& operator=(type const& a_affecter) { \ + elems_[0] = a_affecter; \ + elems_[1] = elems_[2] = elems_[3] = static_cast(0); \ + return *this; \ + } \ + SPROUT_CXX14_CONSTEXPR quaternion& operator=(sprout::complex const& a_affecter) { \ + elems_[0] = a_affecter.real(); \ + elems_[1] = a_affecter.imag(); \ + elems_[2] = elems_[3] = static_cast(0); \ + return *this; \ + } + + // + // quaternion + // + template + class quaternion { + private: + typedef sprout::array array_type; + public: + typedef T value_type; + typedef typename array_type::iterator iterator; + typedef typename array_type::const_iterator const_iterator; + typedef typename array_type::reference reference; + typedef typename array_type::const_reference const_reference; + typedef typename array_type::size_type size_type; + typedef typename array_type::pointer pointer; + typedef typename array_type::const_pointer const_pointer; + typedef typename array_type::reverse_iterator reverse_iterator; + typedef typename array_type::const_reverse_iterator const_reverse_iterator; + public: + SPROUT_STATIC_CONSTEXPR size_type static_size = array_type::static_size; + private: + array_type elems_; + public: + explicit SPROUT_CONSTEXPR quaternion( + T const& requested_a = T(), + T const& requested_b = T(), + T const& requested_c = T(), + T const& requested_d = T() + ) + : elems_{{requested_a, requested_b, requested_c, requested_d}} + {} + explicit SPROUT_CONSTEXPR quaternion( + sprout::complex const& z0, + sprout::complex const& z1 = sprout::complex() + ) + : elems_{{z0.real(), z0.imag(), z1.real(), z1.imag()}} + {} + template + explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier) + : elems_{{ + static_cast(a_recopier.R_component_1()), + static_cast(a_recopier.R_component_2()), + static_cast(a_recopier.R_component_3()), + static_cast(a_recopier.R_component_4()) + }} + {} + SPROUT_QUATERNION_ACCESSOR_GENERATOR(T) + SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T) + SPROUT_CXX14_CONSTEXPR quaternion& operator+=(T const& rhs) { + T at = elems_[0] + rhs; + elems_[0] = at; + return *this; + } + SPROUT_CXX14_CONSTEXPR quaternion& operator+=(sprout::complex const& rhs) { + T at = elems_[0] + rhs.real(); + T bt = elems_[1] + rhs.imag(); + elems_[0] = at; + elems_[1] = bt; + return *this; + } + template + SPROUT_CXX14_CONSTEXPR quaternion& operator+=(quaternion const& rhs) { + T at = elems_[0] + static_cast(rhs.R_component_1()); + T bt = elems_[1] + static_cast(rhs.R_component_2()); + T ct = elems_[2] + static_cast(rhs.R_component_3()); + T dt = elems_[3] + static_cast(rhs.R_component_4()); + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + SPROUT_CXX14_CONSTEXPR quaternion& operator-=(T const& rhs) { + T at = elems_[0] - rhs; + elems_[0] = at; + return *this; + } + SPROUT_CXX14_CONSTEXPR quaternion& operator-=(sprout::complex const& rhs) { + T at = elems_[0] - rhs.real(); + T bt = elems_[1] - rhs.imag(); + elems_[0] = at; + elems_[1] = bt; + return *this; + } + template + SPROUT_CXX14_CONSTEXPR quaternion& operator-=(quaternion const& rhs) { + T at = elems_[0] - static_cast(rhs.R_component_1()); + T bt = elems_[1] - static_cast(rhs.R_component_2()); + T ct = elems_[2] - static_cast(rhs.R_component_3()); + T dt = elems_[3] - static_cast(rhs.R_component_4()); + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + SPROUT_CXX14_CONSTEXPR quaternion& operator*=(T const& rhs) { + T at = elems_[0] * rhs; + T bt = elems_[1] * rhs; + T ct = elems_[2] * rhs; + T dt = elems_[3] * rhs; + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + SPROUT_CXX14_CONSTEXPR quaternion& operator*=(sprout::complex const& rhs) { + T ar = rhs.real(); + T br = rhs.imag(); + T at = +elems_[0] * ar - elems_[1] * br; + T bt = +elems_[0] * br + elems_[1] * ar; + T ct = +elems_[2] * ar + elems_[3] * br; + T dt = -elems_[2] * br + elems_[3] * ar; + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + template + SPROUT_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 at = +elems_[0] * ar - elems_[1] * br - elems_[2] * cr - elems_[3] * dr; + T bt = +elems_[0] * br + elems_[1] * ar + elems_[2] * dr - elems_[3] * cr; + T ct = +elems_[0] * cr - elems_[1] * dr + elems_[2] * ar + elems_[3] * br; + T dt = +elems_[0] * dr + elems_[1] * cr - elems_[2] * br + elems_[3] * ar; + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + SPROUT_CXX14_CONSTEXPR quaternion& operator/=(T const& rhs) { + T at = elems_[0] / rhs; + T bt = elems_[1] / rhs; + T ct = elems_[2] / rhs; + T dt = elems_[3] / rhs; + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + SPROUT_CXX14_CONSTEXPR quaternion& operator/=(sprout::complex const& rhs) { + T ar = rhs.real(); + T br = rhs.imag(); + T denominator = ar * ar + br * br; + T at =(+elems_[0] * ar + elems_[1] * br) / denominator; + T bt =(-elems_[0] * br + elems_[1] * ar) / denominator; + T ct =(+elems_[2] * ar - elems_[3] * br) / denominator; + T dt =(+elems_[2] * br + elems_[3] * ar) / denominator; + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + template + SPROUT_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; + T at =(+elems_[0] * ar + elems_[1] * br + elems_[2] * cr + elems_[3] * dr) / denominator; + T bt =(-elems_[0] * br + elems_[1] * ar - elems_[2] * dr + elems_[3] * cr) / denominator; + T ct =(-elems_[0] * cr + elems_[1] * dr + elems_[2] * ar - elems_[3] * br) / denominator; + T dt =(-elems_[0] * dr - elems_[1] * cr + elems_[2] * br + elems_[3] * ar) / denominator; + elems_[0] = at; + elems_[1] = bt; + elems_[2] = ct; + elems_[3] = dt; + return *this; + } + // iterators: + SPROUT_CXX14_CONSTEXPR iterator begin() SPROUT_NOEXCEPT { + return elems_.begin(); + } + SPROUT_CONSTEXPR const_iterator begin() const SPROUT_NOEXCEPT { + return elems_.begin(); + } + SPROUT_CXX14_CONSTEXPR iterator end() SPROUT_NOEXCEPT { + return elems_.end(); + } + SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT { + return elems_.end(); + } + SPROUT_CXX14_CONSTEXPR reverse_iterator rbegin() SPROUT_NOEXCEPT { + return elems_.rbegin(); + } + SPROUT_CONSTEXPR const_reverse_iterator rbegin() const SPROUT_NOEXCEPT { + return elems_.rbegin(); + } + SPROUT_CXX14_CONSTEXPR reverse_iterator rend() SPROUT_NOEXCEPT { + return elems_.rend(); + } + SPROUT_CONSTEXPR const_reverse_iterator rend() const SPROUT_NOEXCEPT { + return elems_.rend(); + } + SPROUT_CONSTEXPR const_iterator cbegin() const SPROUT_NOEXCEPT { + return elems_.cbegin(); + } + SPROUT_CONSTEXPR const_iterator cend() const SPROUT_NOEXCEPT { + return elems_.cbegin(); + } + SPROUT_CONSTEXPR const_reverse_iterator crbegin() const SPROUT_NOEXCEPT { + return elems_.crbegin(); + } + SPROUT_CONSTEXPR const_reverse_iterator crend() const SPROUT_NOEXCEPT { + return elems_.crend(); + } + // capacity: + SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { + return elems_.size(); + } + SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { + return elems_.max_size(); + } + SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { + return elems_.empty(); + } + // element access: + SPROUT_CXX14_CONSTEXPR reference operator[](size_type i) { + return elems_[i]; + } + SPROUT_CONSTEXPR const_reference operator[](size_type i) const { + return elems_[i]; + } + SPROUT_CXX14_CONSTEXPR reference at(size_type i) { + return elems_.at(i); + } + SPROUT_CONSTEXPR const_reference at(size_type i) const { + return elems_.at(i); + } + SPROUT_CXX14_CONSTEXPR reference front() { + return elems_.front(); + } + SPROUT_CONSTEXPR const_reference front() const { + return elems_.front(); + } + SPROUT_CXX14_CONSTEXPR reference back() { + return elems_.back(); + } + SPROUT_CONSTEXPR const_reference back() const { + return elems_.back(); + } + + SPROUT_CXX14_CONSTEXPR pointer data() SPROUT_NOEXCEPT { + return elems_.data(); + } + SPROUT_CONSTEXPR const_pointer data() const SPROUT_NOEXCEPT { + return elems_.data(); + } + SPROUT_CXX14_CONSTEXPR pointer c_array() SPROUT_NOEXCEPT { + return elems_.c_array(); + } + SPROUT_CONSTEXPR const_pointer c_array() const SPROUT_NOEXCEPT { + return elems_.c_array(); + } + }; + template + SPROUT_CONSTEXPR_OR_CONST typename sprout::math::quaternion::size_type sprout::math::quaternion::static_size; + + template<> + class quaternion; + template<> + class quaternion; + template<> + class quaternion; + +#define SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(type) \ + private: \ + typedef sprout::array array_type; \ + public: \ + typedef type value_type; \ + typedef typename array_type::iterator iterator; \ + typedef typename array_type::const_iterator const_iterator; \ + typedef typename array_type::reference reference; \ + typedef typename array_type::const_reference const_reference; \ + typedef typename array_type::size_type size_type; \ + typedef typename array_type::pointer pointer; \ + typedef typename array_type::const_pointer const_pointer; \ + typedef typename array_type::reverse_iterator reverse_iterator; \ + typedef typename array_type::const_reverse_iterator const_reverse_iterator; \ + public: \ + SPROUT_STATIC_CONSTEXPR size_type static_size = array_type::static_size; \ + private: \ + array_type elems_; + +#define SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(type) \ + explicit SPROUT_CONSTEXPR quaternion( \ + type const& requested_a = static_cast(0), \ + type const& requested_b = static_cast(0), \ + type const& requested_c = static_cast(0), \ + type const& requested_d = static_cast(0) \ + ) \ + : elems_{{requested_a, requested_a, requested_c, requested_d}} \ + {} \ + explicit SPROUT_CONSTEXPR quaternion( \ + sprout::complex const& z0, \ + sprout::complex const& z1 = sprout::complex() \ + ) \ + : elems_{{z0.real(), z0.imag(), z1.real(), z1.imag()}} \ + {} + +#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator+=(type const& rhs) { \ + elems_[0] += rhs; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator+=(sprout::complex const& rhs) { \ + elems_[0] += rhs.real(); \ + elems_[1] += rhs.imag(); \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_3(type) \ + template \ + SPROUT_CXX14_CONSTEXPR quaternion& operator+=(quaternion const& rhs) { \ + elems_[0] += static_cast(rhs.R_component_1()); \ + elems_[1] += static_cast(rhs.R_component_2()); \ + elems_[2] += static_cast(rhs.R_component_3()); \ + elems_[3] += static_cast(rhs.R_component_4()); \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator-=(type const& rhs) { \ + elems_[0] -= rhs; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator-=(sprout::complex const& rhs) { \ + elems_[0] -= rhs.real(); \ + elems_[1] -= rhs.imag(); \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_3(type) \ + template \ + SPROUT_CXX14_CONSTEXPR quaternion& operator-=(quaternion const& rhs) { \ + elems_[0] -= static_cast(rhs.R_component_1()); \ + elems_[1] -= static_cast(rhs.R_component_2()); \ + elems_[2] -= static_cast(rhs.R_component_3()); \ + elems_[3] -= static_cast(rhs.R_component_4()); \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator*=(type const& rhs) { \ + elems_[0] *= rhs; \ + elems_[1] *= rhs; \ + elems_[2] *= rhs; \ + elems_[3] *= rhs; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator*=(sprout::complex const& rhs) { \ + type ar = rhs.real(); \ + type br = rhs.imag(); \ + type at = +elems_[0] * ar - elems_[1] * br; \ + type bt = +elems_[0] * br + elems_[1] * ar; \ + type ct = +elems_[2] * ar + elems_[3] * br; \ + type dt = -elems_[2] * br + elems_[3] * ar; \ + elems_[0] = at; \ + elems_[1] = bt; \ + elems_[2] = ct; \ + elems_[3] = dt; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_3(type) \ + template \ + SPROUT_CXX14_CONSTEXPR quaternion& operator*=(quaternion const& rhs) { \ + type ar = static_cast(rhs.R_component_1()); \ + type br = static_cast(rhs.R_component_2()); \ + type cr = static_cast(rhs.R_component_3()); \ + type dr = static_cast(rhs.R_component_4()); \ + type at = +elems_[0] * ar - elems_[1] * br - elems_[2] * cr - elems_[3] * dr; \ + type bt = +elems_[0] * br + elems_[1] * ar + elems_[2] * dr - elems_[3] * cr; \ + type ct = +elems_[0] * cr - elems_[1] * dr + elems_[2] * ar + elems_[3] * br; \ + type dt = +elems_[0] * dr + elems_[1] * cr - elems_[2] * br + elems_[3] * ar; \ + elems_[0] = at; \ + elems_[1] = bt; \ + elems_[2] = ct; \ + elems_[3] = dt; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator/=(type const& rhs) { \ + elems_[0] /= rhs; \ + elems_[1] /= rhs; \ + elems_[2] /= rhs; \ + elems_[3] /= rhs; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \ + SPROUT_CXX14_CONSTEXPR quaternion& operator/=(sprout::complex const& rhs) { \ + sprout::array tr{{ \ + rhs.real(), \ + rhs.imag() \ + }}; \ + type mixam = static_cast(1) / sprout::math::detail::abs_max(tr); \ + tr = sprout::math::detail::mul(tr, mixam); \ + sprout::array tt{{ \ + +elems_[0] * tr[0] + elems_[1] * tr[1], \ + -elems_[0] * tr[1] + elems_[1] * tr[0], \ + +elems_[2] * tr[0] - elems_[3] * tr[1], \ + +elems_[2] * tr[1] + elems_[3] * tr[0] \ + }}; \ + tr = sprout::math::detail::mul(tr, tr); \ + tt = sprout::math::detail::mul(tt, mixam / sprout::math::detail::sum(tr)); \ + elems_[0] = tt[0]; \ + elems_[1] = tt[1]; \ + elems_[2] = tt[2]; \ + elems_[3] = tt[3]; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \ + template \ + SPROUT_CXX14_CONSTEXPR quaternion& operator/=(quaternion const& rhs) { \ + sprout::array tr{{ \ + static_cast(rhs.R_component_1()), \ + static_cast(rhs.R_component_2()), \ + static_cast(rhs.R_component_3()), \ + static_cast(rhs.R_component_4()) \ + }}; \ + type mixam = static_cast(1) / sprout::math::detail::abs_max(tr); \ + tr = sprout::math::detail::mul(tr, mixam); \ + sprout::array tt{{ \ + +elems_[0] * tr[0] + elems_[1] * tr[1] + elems_[2] * tr[2] + elems_[3] * tr[3], \ + -elems_[0] * tr[1] + elems_[1] * tr[0] - elems_[2] * tr[3] + elems_[3] * tr[2], \ + -elems_[0] * tr[2] + elems_[1] * tr[3] + elems_[2] * tr[0] - elems_[3] * tr[1], \ + -elems_[0] * tr[3] - elems_[1] * tr[2] + elems_[2] * tr[1] + elems_[3] * tr[0] \ + }}; \ + tr = sprout::math::detail::mul(tr, tr); \ + tt = sprout::math::detail::mul(tt, mixam / sprout::math::detail::sum(tr)); \ + elems_[0] = tt[0]; \ + elems_[1] = tt[1]; \ + elems_[2] = tt[2]; \ + elems_[3] = tt[3]; \ + return *this; \ + } + +#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \ + SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \ + SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_3(type) + +#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \ + SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \ + SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_3(type) + +#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \ + SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \ + SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_3(type) + +#define SPROUT_QUATERNION_MEMBER_DIV_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \ + SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \ + SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_3(type) + +#define SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_ADD_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_SUB_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_MUL_GENERATOR(type) \ + SPROUT_QUATERNION_MEMBER_DIV_GENERATOR(type) + +#define SPROUT_QUATERNION_MEMBER_CONTAINER_GENERATOR(type) \ + SPROUT_CXX14_CONSTEXPR iterator begin() SPROUT_NOEXCEPT { \ + return elems_.begin(); \ + } \ + SPROUT_CONSTEXPR const_iterator begin() const SPROUT_NOEXCEPT { \ + return elems_.begin(); \ + } \ + SPROUT_CXX14_CONSTEXPR iterator end() SPROUT_NOEXCEPT { \ + return elems_.end(); \ + } \ + SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT { \ + return elems_.end(); \ + } \ + SPROUT_CXX14_CONSTEXPR reverse_iterator rbegin() SPROUT_NOEXCEPT { \ + return elems_.rbegin(); \ + } \ + SPROUT_CONSTEXPR const_reverse_iterator rbegin() const SPROUT_NOEXCEPT { \ + return elems_.rbegin(); \ + } \ + SPROUT_CXX14_CONSTEXPR reverse_iterator rend() SPROUT_NOEXCEPT { \ + return elems_.rend(); \ + } \ + SPROUT_CONSTEXPR const_reverse_iterator rend() const SPROUT_NOEXCEPT { \ + return elems_.rend(); \ + } \ + SPROUT_CONSTEXPR const_iterator cbegin() const SPROUT_NOEXCEPT { \ + return elems_.cbegin(); \ + } \ + SPROUT_CONSTEXPR const_iterator cend() const SPROUT_NOEXCEPT { \ + return elems_.cbegin(); \ + } \ + SPROUT_CONSTEXPR const_reverse_iterator crbegin() const SPROUT_NOEXCEPT { \ + return elems_.crbegin(); \ + } \ + SPROUT_CONSTEXPR const_reverse_iterator crend() const SPROUT_NOEXCEPT { \ + return elems_.crend(); \ + } \ + \ + SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { \ + return elems_.size(); \ + } \ + SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { \ + return elems_.max_size(); \ + } \ + SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { \ + return elems_.empty(); \ + } \ + \ + SPROUT_CXX14_CONSTEXPR reference operator[](size_type i) { \ + return elems_[i]; \ + } \ + SPROUT_CONSTEXPR const_reference operator[](size_type i) const { \ + return elems_[i]; \ + } \ + SPROUT_CXX14_CONSTEXPR reference at(size_type i) { \ + return elems_.at(i); \ + } \ + SPROUT_CONSTEXPR const_reference at(size_type i) const { \ + return elems_.at(i); \ + } \ + SPROUT_CXX14_CONSTEXPR reference front() { \ + return elems_.front(); \ + } \ + SPROUT_CONSTEXPR const_reference front() const { \ + return elems_.front(); \ + } \ + SPROUT_CXX14_CONSTEXPR reference back() { \ + return elems_.back(); \ + } \ + SPROUT_CONSTEXPR const_reference back() const { \ + return elems_.back(); \ + } \ + \ + SPROUT_CXX14_CONSTEXPR pointer data() SPROUT_NOEXCEPT { \ + return elems_.data(); \ + } \ + SPROUT_CONSTEXPR const_pointer data() const SPROUT_NOEXCEPT { \ + return elems_.data(); \ + } \ + SPROUT_CXX14_CONSTEXPR pointer c_array() SPROUT_NOEXCEPT { \ + return elems_.c_array(); \ + } \ + SPROUT_CONSTEXPR const_pointer c_array() const SPROUT_NOEXCEPT { \ + return elems_.c_array(); \ + } + +#define SPROUT_QUATERNION_MEMBER_STATIC_SIZE_SPECIALIZATION_GENERATOR(type) \ + SPROUT_CONSTEXPR_OR_CONST typename sprout::math::quaternion::size_type sprout::math::quaternion::static_size; + + template<> + class quaternion { + public: + SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(float) + public: + SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(float) + explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); + explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); + SPROUT_QUATERNION_ACCESSOR_GENERATOR(float) + SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(float) + SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(float) + SPROUT_QUATERNION_MEMBER_CONTAINER_GENERATOR(float) + }; + SPROUT_QUATERNION_MEMBER_STATIC_SIZE_SPECIALIZATION_GENERATOR(float) + + template<> + class quaternion { + public: + SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(double) + public: + SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(double) + explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); + explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); + SPROUT_QUATERNION_ACCESSOR_GENERATOR(double) + SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(double) + SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(double) + SPROUT_QUATERNION_MEMBER_CONTAINER_GENERATOR(double) + }; + SPROUT_QUATERNION_MEMBER_STATIC_SIZE_SPECIALIZATION_GENERATOR(double) + + template<> + class quaternion { + public: + SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(long double) + public: + SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(long double) + explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); + explicit SPROUT_CONSTEXPR quaternion(quaternion const& a_recopier); + SPROUT_QUATERNION_ACCESSOR_GENERATOR(long double) + SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(long double) + SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(long double) + SPROUT_QUATERNION_MEMBER_CONTAINER_GENERATOR(long double) + }; + SPROUT_QUATERNION_MEMBER_STATIC_SIZE_SPECIALIZATION_GENERATOR(long double) + + SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::quaternion const& a_recopier) + : elems_{{ + static_cast(a_recopier.R_component_1()), + static_cast(a_recopier.R_component_2()), + static_cast(a_recopier.R_component_3()), + static_cast(a_recopier.R_component_4()) + }} + {} + SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::quaternion const& a_recopier) + : elems_{{ + static_cast(a_recopier.R_component_1()), + static_cast(a_recopier.R_component_2()), + static_cast(a_recopier.R_component_3()), + static_cast(a_recopier.R_component_4()) + }} + {} + + SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::quaternion const& a_recopier) + : elems_{{ + static_cast(a_recopier.R_component_1()), + static_cast(a_recopier.R_component_2()), + static_cast(a_recopier.R_component_3()), + static_cast(a_recopier.R_component_4()) + }} + {} + SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::quaternion const& a_recopier) + : elems_{{ + static_cast(a_recopier.R_component_1()), + static_cast(a_recopier.R_component_2()), + static_cast(a_recopier.R_component_3()), + static_cast(a_recopier.R_component_4()) + }} + {} + + SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::quaternion const& a_recopier) + : elems_{{ + static_cast(a_recopier.R_component_1()), + static_cast(a_recopier.R_component_2()), + static_cast(a_recopier.R_component_3()), + static_cast(a_recopier.R_component_4()) + }} + {} + SPROUT_CONSTEXPR sprout::math::quaternion::quaternion(sprout::math::quaternion const& a_recopier) + : elems_{{ + static_cast(a_recopier.R_component_1()), + static_cast(a_recopier.R_component_2()), + static_cast(a_recopier.R_component_3()), + static_cast(a_recopier.R_component_4()) + }} + {} + +#undef SPROUT_QUATERNION_MEMBER_CONTAINER_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_1 +#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_2 +#undef SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_3 +#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_1 +#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_2 +#undef SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_3 +#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_1 +#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_2 +#undef SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_3 +#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_1 +#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_2 +#undef SPROUT_QUATERNION_MEMBER_DIV_GENERATOR_3 +#undef SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR +#undef SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR +#undef SPROUT_QUATERNION_ACCESSOR_GENERATOR + + // + // operator+ + // + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator+(T const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs + rhs.R_component_1(), + rhs.R_component_2(), + rhs.R_component_3(), + rhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator+(sprout::math::quaternion const& lhs, T const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() + rhs, + lhs.R_component_2(), + lhs.R_component_3(), + lhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator+(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs.real() + rhs.R_component_1(), + lhs.imag() + rhs.R_component_2(), + rhs.R_component_3(), + rhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator+(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() + rhs.real(), + lhs.R_component_2() + rhs.imag(), + lhs.R_component_3(), + lhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator+(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() + rhs.R_component_1(), + lhs.R_component_2() + rhs.R_component_2(), + lhs.R_component_3() + rhs.R_component_3(), + lhs.R_component_4() + rhs.R_component_4() + ); + } + // + // operator- + // + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator-(T const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs - rhs.R_component_1(), + rhs.R_component_2(), + rhs.R_component_3(), + rhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator-(sprout::math::quaternion const& lhs, T const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() - rhs, + lhs.R_component_2(), + lhs.R_component_3(), + lhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator-(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs.real() - rhs.R_component_1(), + lhs.imag() - rhs.R_component_2(), + rhs.R_component_3(), + rhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator-(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() - rhs.real(), + lhs.R_component_2() - rhs.imag(), + lhs.R_component_3(), + lhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator-(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() - rhs.R_component_1(), + lhs.R_component_2() - rhs.R_component_2(), + lhs.R_component_3() - rhs.R_component_3(), + lhs.R_component_4() - rhs.R_component_4() + ); + } + // + // operator* + // + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator*(T const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs * rhs.R_component_1(), + lhs * rhs.R_component_2(), + lhs * rhs.R_component_3(), + lhs * rhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator*(sprout::math::quaternion const& lhs, T const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() * rhs, + lhs.R_component_2() * rhs, + lhs.R_component_3() * rhs, + lhs.R_component_4() * rhs + ); + } + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + mul_qc_impl(T const& a, T const& b, T const& c, T const& d, T const& ar, T const& br) { + return sprout::math::quaternion( + +a * ar - b * br, + +a * br + b * ar, + +c * ar + d * br, + -c * br + d * ar + ); + } + } // namespace detail + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator*(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::detail::mul_qc_impl( + lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), + rhs.real(), rhs.imag() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator*(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { + return sprout::math::detail::mul_qc_impl( + rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4(), + lhs.real(), lhs.imag() + ); + } + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + mul_qq_impl(T const& a, T const& b, T const& c, T const& d, T const& ar, T const& br, T const& cr, T const& dr) { + return sprout::math::quaternion( + +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 + ); + } + } // namespace detail + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator*(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::detail::mul_qq_impl( + lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), + rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4() + ); + } + // + // operator/ + // + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator/(T const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::quaternion( + lhs / rhs.R_component_1(), + lhs / rhs.R_component_2(), + lhs / rhs.R_component_3(), + lhs / rhs.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator/(sprout::math::quaternion const& lhs, T const& rhs) { + return sprout::math::quaternion( + lhs.R_component_1() / rhs, + lhs.R_component_2() / rhs, + lhs.R_component_3() / rhs, + lhs.R_component_4() / rhs + ); + } + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + div_qq_impl_4(sprout::array const& tt) { + return sprout::math::quaternion( + tt[0], tt[1], tt[2], tt[3] + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + div_qq_impl_3(sprout::array const& tr, T const& mixam, sprout::array const& tt) { + return sprout::math::detail::div_qq_impl_3( + sprout::math::detail::mul(tt, mixam / sprout::math::detail::sum(tr)) + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + div_qq_impl_2(T const& a, T const& b, T const& c, T const& d, sprout::array const& tr, T const& mixam) { + return sprout::math::detail::div_qq_impl_3( + sprout::math::detail::mul(tr, tr), mixam, + sprout::array{{ + +a * tr[0] + b * tr[1] + c * tr[2] + d * tr[3], + -a * tr[1] + b * tr[0] - c * tr[3] + d * tr[2], + -a * tr[2] + b * tr[3] + c * tr[0] - d * tr[1], + -a * tr[3] - b * tr[2] + c * tr[1] + d * tr[0] + }} + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + div_qq_impl_1(T const& a, T const& b, T const& c, T const& d, sprout::array const& tr, T const& mixam) { + return sprout::math::detail::div_qq_impl_2( + a, b, c, d, sprout::math::detail::mul(tr, mixam), mixam + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + div_qq_impl(T const& a, T const& b, T const& c, T const& d, sprout::array const& tr) { + return sprout::math::detail::div_qq_impl_1( + a, b, c, d, tr, + static_cast(1) / sprout::math::detail::abs_max(tr) + ); + } + } // namespace detail + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator/(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::detail::div_qq_impl( + lhs.real(), lhs.imag(), static_cast(0), static_cast(0), + sprout::array{{rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4()}} + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator/(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { + return sprout::math::detail::div_qq_impl( + lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), + sprout::array{{rhs.real(), rhs.imag(), static_cast(0), static_cast(0)}} + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator/(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { + return sprout::math::detail::div_qq_impl( + lhs.R_component_1(), lhs.R_component_2(), lhs.R_component_3(), lhs.R_component_4(), + sprout::array{{rhs.R_component_1(), rhs.R_component_2(), rhs.R_component_3(), rhs.R_component_4()}} + ); + } + + // + // operator+ + // operator- + // + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator+(sprout::math::quaternion const& q) { + return q; + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + operator-(sprout::math::quaternion const& q) { + return sprout::math::quaternion(-q.R_component_1(), -q.R_component_2(), -q.R_component_3(), -q.R_component_4()); + } + + // + // operator== + // operator!= + // + template + inline SPROUT_CONSTEXPR bool + operator==(T const& lhs, sprout::math::quaternion const& rhs) { + return rhs.R_component_1() == lhs + && rhs.R_component_2() == static_cast(0) + && rhs.R_component_3() == static_cast(0) + && rhs.R_component_4() == static_cast(0) + ; + } + template + inline SPROUT_CONSTEXPR bool + operator==(sprout::math::quaternion const& lhs, T const& rhs) { + return lhs.R_component_1() == rhs + && lhs.R_component_2() == static_cast(0) + && lhs.R_component_3() == static_cast(0) + && lhs.R_component_4() == static_cast(0) + ; + } + template + inline SPROUT_CONSTEXPR bool + operator==(sprout::complex const& lhs, sprout::math::quaternion const& rhs) { + return rhs.R_component_1() == lhs.real() + && rhs.R_component_2() == lhs.imag() + && rhs.R_component_3() == static_cast(0) + && rhs.R_component_4() == static_cast(0) + ; + } + template + inline SPROUT_CONSTEXPR bool + operator==(sprout::math::quaternion const& lhs, sprout::complex const& rhs) { + return lhs.R_component_1() == rhs.real() + && lhs.R_component_2() == rhs.imag() + && lhs.R_component_3() == static_cast(0) + && lhs.R_component_4() == static_cast(0) + ; + } + template + inline SPROUT_CONSTEXPR bool + operator==(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) { + return rhs.R_component_1() == lhs.R_component_1() + && rhs.R_component_2() == lhs.R_component_2() + && rhs.R_component_3() == lhs.R_component_3() + && rhs.R_component_4() == lhs.R_component_4() + ; + } + +#define SPROUT_QUATERNION_NOT_EQUAL_GENERATOR \ + { \ + return !(lhs == rhs); \ + } + + template + inline SPROUT_CONSTEXPR bool + operator!=(T const& lhs, sprout::math::quaternion const& rhs) + SPROUT_QUATERNION_NOT_EQUAL_GENERATOR + template + inline SPROUT_CONSTEXPR bool + operator!=(sprout::math::quaternion const& lhs, T const& rhs) + SPROUT_QUATERNION_NOT_EQUAL_GENERATOR + template + inline SPROUT_CONSTEXPR bool + operator!=(sprout::complex const& lhs, sprout::math::quaternion const& rhs) + SPROUT_QUATERNION_NOT_EQUAL_GENERATOR + template + inline SPROUT_CONSTEXPR bool + operator!=(sprout::math::quaternion const& lhs, sprout::complex const& rhs) + SPROUT_QUATERNION_NOT_EQUAL_GENERATOR + template + inline SPROUT_CONSTEXPR bool + operator!=(sprout::math::quaternion const& lhs, sprout::math::quaternion const& rhs) + SPROUT_QUATERNION_NOT_EQUAL_GENERATOR + +#undef SPROUT_QUATERNION_NOT_EQUAL_GENERATOR + + // + // operator<< + // operator>> + // + template + inline SPROUT_NON_CONSTEXPR std::basic_ostream& + operator<<( std::basic_ostream& lhs, sprout::math::quaternion const& rhs) { + std::basic_ostringstream s; + s.flags(lhs.flags()); + s.imbue(lhs.getloc()); + s.precision(lhs.precision()); + s + << '(' + << rhs.R_component_1() << ',' + << rhs.R_component_2() << ',' + << rhs.R_component_3() << ',' + << rhs.R_component_4() + << ')' + ; + return lhs << s.str(); + } + template + inline SPROUT_NON_CONSTEXPR std::basic_istream& + operator>>(std::basic_istream& lhs, sprout::math::quaternion& rhs) { + std::ctype const& ct = std::use_facet >(lhs.getloc()); + T a = T(); + T b = T(); + T c = T(); + T d = T(); + sprout::complex u = sprout::complex(); + sprout::complex v = sprout::complex(); + Elem ch = Elem(); + char cc; + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == '(') { + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == '(') { + lhs.putback(ch); + lhs >> u; + a = u.real(); + b = u.imag(); + if (!lhs.good()) { + goto finish; + } + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == ')') { + rhs = sprout::math::quaternion(a, b); + } else if (cc == ',') { + lhs >> v; + c = v.real(); + d = v.imag(); + if (!lhs.good()) { + goto finish; + } + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == ')') { + rhs = sprout::math::quaternion(a, b, c, d); + } else { + lhs.setstate(std::ios_base::failbit); + } + } else { + lhs.setstate(std::ios_base::failbit); + } + } else { + lhs.putback(ch); + lhs >> a; + if (!lhs.good()) { + goto finish; + } + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == ')') { + rhs = sprout::math::quaternion(a); + } else if (cc == ',') { + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == '(') { + lhs.putback(ch); + lhs >> v; + c = v.real(); + d = v.imag(); + if (!lhs.good()) { + goto finish; + } + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == ')') { + rhs = sprout::math::quaternion(a, b, c, d); + } else { + lhs.setstate(std::ios_base::failbit); + } + } else { + lhs.putback(ch); + lhs >> b; + if (!lhs.good()) { + goto finish; + } + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == ')') { + rhs = sprout::math::quaternion(a, b); + } else if (cc == ',') { + lhs >> c; + if (!lhs.good()) { + goto finish; + } + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == ')') { + rhs = sprout::math::quaternion(a, b, c); + } else if (cc == ',') { + lhs >> d; + if (!lhs.good()) { + goto finish; + } + lhs >> ch; + if (!lhs.good()) { + goto finish; + } + cc = ct.narrow(ch, char()); + if (cc == ')') { + rhs = sprout::math::quaternion(a, b, c, d); + } else { + lhs.setstate(std::ios_base::failbit); + } + } else { + lhs.setstate(std::ios_base::failbit); + } + } else { + lhs.setstate(std::ios_base::failbit); + } + } + } else { + lhs.setstate(std::ios_base::failbit); + } + } + } else { + lhs.putback(ch); + lhs >> a; + if (!lhs.good()) { + goto finish; + } + rhs = sprout::math::quaternion(a); + } + finish: + return lhs; + } + + // + // real + // unreal + // + template + inline SPROUT_CONSTEXPR T + real(sprout::math::quaternion const& q) { + return q.real(); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + unreal(sprout::math::quaternion const& q) { + return q.unreal(); + } + + // + // sup + // l1 + // + template + inline SPROUT_CONSTEXPR T + sup(sprout::math::quaternion const& q) { + return sprout::math::detail::abs_max( + sprout::array{{ + q.R_component_1(), + q.R_component_2(), + q.R_component_3(), + q.R_component_4() + }} + ); + } + template + inline SPROUT_CONSTEXPR T + l1(sprout::math::quaternion const& q) { + return sprout::math::detail::abs_sum( + sprout::array{{ + q.R_component_1(), + q.R_component_2(), + q.R_component_3(), + q.R_component_4() + }} + ); + } + + // + // abs + // + namespace detail { + template + inline SPROUT_CONSTEXPR T + abs_q_impl_3(sprout::array const& temp, T const& maxim) { + return maxim * sprout::math::sqrt(sprout::math::detail::sum(sprout::math::detail::mul(temp, temp))); + } + template + inline SPROUT_CONSTEXPR T + abs_q_impl_2(sprout::array const& temp, T const& maxim) { + return sprout::math::detail::abs_q_impl_3( + sprout::math::detail::mul(temp, maxim), maxim + ); + } + template + inline SPROUT_CONSTEXPR T + abs_q_impl_1(sprout::array const& temp, T const& maxim) { + return maxim == static_cast(0) ? sprout::math::quaternion(maxim) + : sprout::math::detail::abs_q_impl_2( + temp, static_cast(1) / maxim + ) + ; + } + template + inline SPROUT_CONSTEXPR T + abs_q_impl(sprout::array const& temp) { + return sprout::math::detail::abs_q_impl_1( + temp, sprout::math::detail::abs_max(temp) + ); + } + } // namespace detail + template + inline SPROUT_CONSTEXPR T + abs(sprout::math::quaternion const& q) { + return sprout::math::detail::abs_q_impl( + sprout::array{{ + q.R_component_1(), + q.R_component_2(), + q.R_component_3(), + q.R_component_4() + }} + ); + } + +#undef SPROUT_QUATERNION_ARRAY_LOADER + + // + // conj + // norm + // + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + conj(sprout::math::quaternion const& q) { + return sprout::math::quaternion( + +q.R_component_1(), + -q.R_component_2(), + -q.R_component_3(), + -q.R_component_4() + ); + } + template + inline SPROUT_CONSTEXPR T + norm(sprout::math::quaternion const& q) { + return sprout::math::real(q * sprout::math::conj(q)); + } + + // + // spherical + // semipolar + // multipolar + // cylindrospherical + // cylindrical + // + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + spherical_impl(T const& rho, T const& theta, T const& phi1, T const& phi2, T const& p1, T const& p2) { + return rho * sprout::math::quaternion( + sprout::math::cos(theta) * (p2 * p1), + sprout::math::sin(theta) * (p2 * p1), + sprout::math::sin(phi1) * p2, + sprout::math::sin(phi2) + ); + } + } // namespace detail + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + spherical(T const& rho, T const& theta, T const& phi1, T const& phi2) { + return sprout::math::detail::spherical_impl( + rho, theta, phi1, phi2, + sprout::math::cos(phi1), sprout::math::cos(phi2) + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + semipolar(T const& rho, T const& alpha, T const& theta1, T const& theta2) { + return rho * sprout::math::quaternion( + sprout::math::cos(alpha) * sprout::math::cos(theta1), + sprout::math::cos(alpha) * sprout::math::sin(theta1), + sprout::math::sin(alpha) * sprout::math::cos(theta2), + sprout::math::sin(alpha) * sprout::math::sin(theta2) + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + multipolar(T const& rho1, T const& theta1, T const& rho2, T const& theta2) { + return sprout::math::quaternion( + rho1 * sprout::math::cos(theta1), + rho1 * sprout::math::sin(theta1), + rho2 * sprout::math::cos(theta2), + rho2 * sprout::math::sin(theta2) + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + cylindrospherical(T const& t, T const& radius, T const& longitude, T const& latitude) { + return sprout::math::quaternion( + t, + radius * sprout::math::cos(longitude) * sprout::math::cos(latitude), + radius * sprout::math::sin(longitude) * sprout::math::cos(latitude), + radius * sprout::math::sin(latitude) + ); + } + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + cylindrical(T const& r, T const& angle, T const& h1, T const& h2) { + return sprout::math::quaternion( + r * sprout::math::cos(angle), + r * sprout::math::sin(angle), + h1, + h2 + ); + } + + // + // exp + // + // !!! +// namespace detail { +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// exp_impl_1(sprout::math::quaternion const& q, T const& z, T const& w) { +// return sprout::math::exp(sprout::math::real(q)) * sprout::math::quaternion( +// sprout::math::cos(z), +// w * q.R_component_2(), +// w * q.R_component_3(), +// w * q.R_component_4() +// ); +// } +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// exp_impl(sprout::math::quaternion const& q, T const& z) { +// return sprout::math::detail::exp_impl_1( +// q, z, +// sprout::math::sinc_pi(z) +// ); +// } +// } // namespace detail +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// exp(sprout::math::quaternion const& q) { +// return sprout::math::detail::exp_impl( +// q, +// sprout::math::abs(sprout::math::unreal(q)) +// ); +// } + + // + // cos + // sin + // tan + // + // !!! +// namespace detail { +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// cos_impl_1(sprout::math::quaternion const& q, T const& z, T const& w) { +// return sprout::math::quaternion( +// sprout::math::cos(q.real()) * sprout::math::cosh(z), +// w * q.R_component_2(), +// w * q.R_component_3(), +// w * q.R_component_4() +// ); +// } +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// cos_impl(sprout::math::quaternion const& q, T const& z) { +// return sprout::math::detail::cos_impl_1( +// q, z, +// -sprout::math::sin(q.real()) * sprout::math::sinhc_pi(z) +// ); +// } +// } // namespace detail +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// cos(sprout::math::quaternion const& q) { +// return sprout::math::detail::cos_impl( +// q, +// sprout::math::abs(sprout::math::unreal(q)) +// ); +// } +// namespace detail { +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// sin_impl_1(sprout::math::quaternion const& q, T const& z, T const& w) { +// return sprout::math::quaternion( +// sprout::math::sin(q.real()) * sprout::math::cosh(z), +// w * q.R_component_2(), +// w * q.R_component_3(), +// w * q.R_component_4() +// ); +// } +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// sin_impl(sprout::math::quaternion const& q, T const& z) { +// return sprout::math::detail::sin_impl_1( +// q, z, +// +sprout::math::cos(q.real()) * sprout::math::sinhc_pi(z) +// ); +// } +// } // namespace detail +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// sin(sprout::math::quaternion const& q) { +// return sprout::math::detail::sin_impl( +// q, +// sprout::math::abs(sprout::math::unreal(q)) +// ); +// } +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// tan(sprout::math::quaternion const& q) { +// return sprout::math::sin(q) / sprout::math::cos(q); +// } + + // + // cosh + // sinh + // tanh + // + // !!! +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// cosh(sprout::math::quaternion const& q) { +// return (sprout::math::exp(+q) + sprout::math::exp(-q)) / static_cast(2); +// } +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// sinh(sprout::math::quaternion const& q) { +// return (sprout::math::exp(+q) - sprout::math::exp(-q)) / static_cast(2); +// } +// template +// inline SPROUT_CONSTEXPR sprout::math::quaternion +// tanh(sprout::math::quaternion const& q) { +// return sprout::math::sinh(q) / sprout::math::cosh(q); +// } + + // + // pow + // + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + pow_q_impl(sprout::math::quaternion const& q, int n, int m, sprout::math::quaternion const& result) { + return n != m << 1 ? result * result * q + : result * result + ; + } + } // namespace detail + template + inline SPROUT_CONSTEXPR sprout::math::quaternion + pow(sprout::math::quaternion const& q, int n) { + return n > 1 ? sprout::math::detail::pow_q_impl( + q, n, n >> 1, sprout::math::pow(q, n >> 1) + ) + : n == 1 ? q + : n == 0 ? sprout::math::quaternion(static_cast(1)) + : sprout::math::pow(sprout::math::quaternion(static_cast(1)) / q, -n) + ; + } + } // namespace math + + using sprout::math::quaternion; + using sprout::math::real; + using sprout::math::unreal; + using sprout::math::sup; + using sprout::math::l1; + using sprout::math::abs; + using sprout::math::conj; + using sprout::math::norm; + using sprout::math::spherical; + using sprout::math::semipolar; + using sprout::math::multipolar; + using sprout::math::cylindrospherical; + using sprout::math::cylindrical; +// using sprout::math::exp; +// using sprout::math::cos; +// using sprout::math::sin; +// using sprout::math::tan; +// using sprout::math::cosh; +// using sprout::math::sinh; +// using sprout::math::tanh; + using sprout::math::pow; +} // namespace sprout + +#endif // #ifndef SPROUT_MATH_QUATERNION_QUATERNION_HPP