diff --git a/sprout/math/quaternion.hpp b/sprout/math/quaternion.hpp new file mode 100644 index 00000000..ff1d14ed --- /dev/null +++ b/sprout/math/quaternion.hpp @@ -0,0 +1,1506 @@ +/*============================================================================= + Copyright (c) 2011-2015 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_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 +} // namespace sprout + +#endif // #ifndef SPROUT_MATH_QUATERNION_HPP diff --git a/testspr/header_all.hpp b/testspr/header_all.hpp index eb5ac42b..1f57526a 100644 --- a/testspr/header_all.hpp +++ b/testspr/header_all.hpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include