/*============================================================================= 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 namespace sprout { namespace math { #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 } // namespace math using sprout::math::quaternion; } // namespace sprout #endif // #ifndef SPROUT_MATH_QUATERNION_QUATERNION_HPP