Sprout/sprout/math/quaternion/quaternion.hpp

770 lines
29 KiB
C++
Raw Normal View History

2016-02-26 14:19:42 +00:00
/*=============================================================================
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 <sprout/config.hpp>
2016-02-26 16:21:46 +00:00
#include <sprout/workaround/std/cstddef.hpp>
2016-02-26 14:19:42 +00:00
#include <sprout/array/array.hpp>
#include <sprout/complex/complex.hpp>
2016-02-26 16:21:46 +00:00
#include <sprout/math/quaternion/detail/abs_max.hpp>
#include <sprout/math/quaternion/detail/sum.hpp>
#include <sprout/math/quaternion/detail/mul.hpp>
2016-02-26 14:19:42 +00:00
namespace sprout {
namespace math {
#define SPROUT_QUATERNION_ACCESSOR_GENERATOR(type) \
SPROUT_CONSTEXPR type real() const { \
return (elems_[0]); \
} \
SPROUT_CONSTEXPR quaternion<type> unreal() const { \
return (quaternion<type>(static_cast<type>(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<type> C_component_1() const { \
return sprout::complex<type>(elems_[0], elems_[1]); \
} \
SPROUT_CONSTEXPR sprout::complex<type> C_component_2() const { \
return sprout::complex<type>(elems_[2], elems_[3]); \
}
#define SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type) \
template<typename X> \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator=(quaternion<X> const& a_affecter) { \
elems_[0] = static_cast<type>(a_affecter.R_component_1()); \
elems_[1] = static_cast<type>(a_affecter.R_component_2()); \
elems_[2] = static_cast<type>(a_affecter.R_component_3()); \
elems_[3] = static_cast<type>(a_affecter.R_component_4()); \
return *this; \
} \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator=(quaternion<type> 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<type>& operator=(type const& a_affecter) { \
elems_[0] = a_affecter; \
elems_[1] = elems_[2] = elems_[3] = static_cast<type>(0); \
return *this; \
} \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator=(sprout::complex<type> const& a_affecter) { \
elems_[0] = a_affecter.real(); \
elems_[1] = a_affecter.imag(); \
elems_[2] = elems_[3] = static_cast<type>(0); \
return *this; \
}
//
// quaternion
//
template<typename T>
class quaternion {
private:
typedef sprout::array<T, 4> 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<T> const& z0,
sprout::complex<T> const& z1 = sprout::complex<T>()
)
: elems_{{z0.real(), z0.imag(), z1.real(), z1.imag()}}
{}
template<typename X>
explicit SPROUT_CONSTEXPR quaternion(quaternion<X> const& a_recopier)
: elems_{{
static_cast<T>(a_recopier.R_component_1()),
static_cast<T>(a_recopier.R_component_2()),
static_cast<T>(a_recopier.R_component_3()),
static_cast<T>(a_recopier.R_component_4())
}}
{}
SPROUT_QUATERNION_ACCESSOR_GENERATOR(T)
SPROUT_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T)
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator+=(T const& rhs) {
T at = elems_[0] + rhs;
elems_[0] = at;
return *this;
}
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator+=(sprout::complex<T> const& rhs) {
T at = elems_[0] + rhs.real();
T bt = elems_[1] + rhs.imag();
elems_[0] = at;
elems_[1] = bt;
return *this;
}
template<typename X>
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator+=(quaternion<X> const& rhs) {
T at = elems_[0] + static_cast<T>(rhs.R_component_1());
T bt = elems_[1] + static_cast<T>(rhs.R_component_2());
T ct = elems_[2] + static_cast<T>(rhs.R_component_3());
T dt = elems_[3] + static_cast<T>(rhs.R_component_4());
elems_[0] = at;
elems_[1] = bt;
elems_[2] = ct;
elems_[3] = dt;
return *this;
}
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator-=(T const& rhs) {
T at = elems_[0] - rhs;
elems_[0] = at;
return *this;
}
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator-=(sprout::complex<T> const& rhs) {
T at = elems_[0] - rhs.real();
T bt = elems_[1] - rhs.imag();
elems_[0] = at;
elems_[1] = bt;
return *this;
}
template<typename X>
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator-=(quaternion<X> const& rhs) {
T at = elems_[0] - static_cast<T>(rhs.R_component_1());
T bt = elems_[1] - static_cast<T>(rhs.R_component_2());
T ct = elems_[2] - static_cast<T>(rhs.R_component_3());
T dt = elems_[3] - static_cast<T>(rhs.R_component_4());
elems_[0] = at;
elems_[1] = bt;
elems_[2] = ct;
elems_[3] = dt;
return *this;
}
SPROUT_CXX14_CONSTEXPR quaternion<T>& 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<T>& operator*=(sprout::complex<T> 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<typename X>
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator*=(quaternion<X> const& rhs) {
T ar = static_cast<T>(rhs.R_component_1());
T br = static_cast<T>(rhs.R_component_2());
T cr = static_cast<T>(rhs.R_component_3());
T dr = static_cast<T>(rhs.R_component_4());
T at = +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<T>& 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<T>& operator/=(sprout::complex<T> 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<typename X>
SPROUT_CXX14_CONSTEXPR quaternion<T>& operator/=(quaternion<X> const& rhs) {
T ar = static_cast<T>(rhs.R_component_1());
T br = static_cast<T>(rhs.R_component_2());
T cr = static_cast<T>(rhs.R_component_3());
T dr = static_cast<T>(rhs.R_component_4());
T denominator = ar * ar + br * br + cr * cr + dr * dr;
T at =(+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<typename T>
SPROUT_CONSTEXPR_OR_CONST typename sprout::math::quaternion<T>::size_type sprout::math::quaternion<T>::static_size;
template<>
class quaternion<float>;
template<>
class quaternion<double>;
template<>
class quaternion<long double>;
#define SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(type) \
private: \
typedef sprout::array<type, 4> 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<type>(0), \
type const& requested_b = static_cast<type>(0), \
type const& requested_c = static_cast<type>(0), \
type const& requested_d = static_cast<type>(0) \
) \
: elems_{{requested_a, requested_a, requested_c, requested_d}} \
{} \
explicit SPROUT_CONSTEXPR quaternion( \
sprout::complex<type> const& z0, \
sprout::complex<type> const& z1 = sprout::complex<type>() \
) \
: elems_{{z0.real(), z0.imag(), z1.real(), z1.imag()}} \
{}
#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator+=(type const& rhs) { \
elems_[0] += rhs; \
return *this; \
}
#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator+=(sprout::complex<type> const& rhs) { \
elems_[0] += rhs.real(); \
elems_[1] += rhs.imag(); \
return *this; \
}
#define SPROUT_QUATERNION_MEMBER_ADD_GENERATOR_3(type) \
template<typename X> \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator+=(quaternion<X> const& rhs) { \
elems_[0] += static_cast<type>(rhs.R_component_1()); \
elems_[1] += static_cast<type>(rhs.R_component_2()); \
elems_[2] += static_cast<type>(rhs.R_component_3()); \
elems_[3] += static_cast<type>(rhs.R_component_4()); \
return *this; \
}
#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator-=(type const& rhs) { \
elems_[0] -= rhs; \
return *this; \
}
#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator-=(sprout::complex<type> const& rhs) { \
elems_[0] -= rhs.real(); \
elems_[1] -= rhs.imag(); \
return *this; \
}
#define SPROUT_QUATERNION_MEMBER_SUB_GENERATOR_3(type) \
template<typename X> \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator-=(quaternion<X> const& rhs) { \
elems_[0] -= static_cast<type>(rhs.R_component_1()); \
elems_[1] -= static_cast<type>(rhs.R_component_2()); \
elems_[2] -= static_cast<type>(rhs.R_component_3()); \
elems_[3] -= static_cast<type>(rhs.R_component_4()); \
return *this; \
}
#define SPROUT_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
SPROUT_CXX14_CONSTEXPR quaternion<type>& 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<type>& operator*=(sprout::complex<type> 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<typename X> \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator*=(quaternion<X> const& rhs) { \
type ar = static_cast<type>(rhs.R_component_1()); \
type br = static_cast<type>(rhs.R_component_2()); \
type cr = static_cast<type>(rhs.R_component_3()); \
type dr = static_cast<type>(rhs.R_component_4()); \
type at = +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<type>& 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<type>& operator/=(sprout::complex<type> const& rhs) { \
sprout::array<type, 2> tr{{ \
rhs.real(), \
rhs.imag() \
}}; \
type mixam = static_cast<type>(1) / sprout::math::detail::abs_max(tr); \
tr = sprout::math::detail::mul(tr, mixam); \
sprout::array<type, 4> 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<typename X> \
SPROUT_CXX14_CONSTEXPR quaternion<type>& operator/=(quaternion<X> const& rhs) { \
sprout::array<type, 4> tr{{ \
static_cast<type>(rhs.R_component_1()), \
static_cast<type>(rhs.R_component_2()), \
static_cast<type>(rhs.R_component_3()), \
static_cast<type>(rhs.R_component_4()) \
}}; \
type mixam = static_cast<type>(1) / sprout::math::detail::abs_max(tr); \
tr = sprout::math::detail::mul(tr, mixam); \
sprout::array<type, 4> 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<type>::size_type sprout::math::quaternion<type>::static_size;
template<>
class quaternion<float> {
public:
SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(float)
public:
SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(float)
explicit SPROUT_CONSTEXPR quaternion(quaternion<double> const& a_recopier);
explicit SPROUT_CONSTEXPR quaternion(quaternion<long double> 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<double> {
public:
SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(double)
public:
SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(double)
explicit SPROUT_CONSTEXPR quaternion(quaternion<float> const& a_recopier);
explicit SPROUT_CONSTEXPR quaternion(quaternion<long double> 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<long double> {
public:
SPROUT_QUATERNION_MEMBER_TYPE_DATA_GENERATOR(long double)
public:
SPROUT_QUATERNION_CONSTRUCTOR_GENERATOR(long double)
explicit SPROUT_CONSTEXPR quaternion(quaternion<float> const& a_recopier);
explicit SPROUT_CONSTEXPR quaternion(quaternion<double> 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<float>::quaternion(sprout::math::quaternion<double> const& a_recopier)
: elems_{{
static_cast<float>(a_recopier.R_component_1()),
static_cast<float>(a_recopier.R_component_2()),
static_cast<float>(a_recopier.R_component_3()),
static_cast<float>(a_recopier.R_component_4())
}}
{}
SPROUT_CONSTEXPR sprout::math::quaternion<float>::quaternion(sprout::math::quaternion<long double> const& a_recopier)
: elems_{{
static_cast<float>(a_recopier.R_component_1()),
static_cast<float>(a_recopier.R_component_2()),
static_cast<float>(a_recopier.R_component_3()),
static_cast<float>(a_recopier.R_component_4())
}}
{}
SPROUT_CONSTEXPR sprout::math::quaternion<double>::quaternion(sprout::math::quaternion<float> const& a_recopier)
: elems_{{
static_cast<double>(a_recopier.R_component_1()),
static_cast<double>(a_recopier.R_component_2()),
static_cast<double>(a_recopier.R_component_3()),
static_cast<double>(a_recopier.R_component_4())
}}
{}
SPROUT_CONSTEXPR sprout::math::quaternion<double>::quaternion(sprout::math::quaternion<long double> const& a_recopier)
: elems_{{
static_cast<double>(a_recopier.R_component_1()),
static_cast<double>(a_recopier.R_component_2()),
static_cast<double>(a_recopier.R_component_3()),
static_cast<double>(a_recopier.R_component_4())
}}
{}
SPROUT_CONSTEXPR sprout::math::quaternion<long double>::quaternion(sprout::math::quaternion<float> const& a_recopier)
: elems_{{
static_cast<long double>(a_recopier.R_component_1()),
static_cast<long double>(a_recopier.R_component_2()),
static_cast<long double>(a_recopier.R_component_3()),
static_cast<long double>(a_recopier.R_component_4())
}}
{}
SPROUT_CONSTEXPR sprout::math::quaternion<long double>::quaternion(sprout::math::quaternion<double> const& a_recopier)
: elems_{{
static_cast<long double>(a_recopier.R_component_1()),
static_cast<long double>(a_recopier.R_component_2()),
static_cast<long double>(a_recopier.R_component_3()),
static_cast<long double>(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