File indexing completed on 2025-01-18 09:40:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_QUATERNION_HPP
0011 #define BOOST_QUATERNION_HPP
0012
0013 #include <boost/math_fwd.hpp>
0014 #include <boost/math/tools/config.hpp>
0015 #include <locale> // for the "<<" operator
0016
0017 #include <complex>
0018 #include <iosfwd> // for the "<<" and ">>" operators
0019 #include <sstream> // for the "<<" operator
0020
0021 #include <boost/math/special_functions/sinc.hpp> // for the Sinus cardinal
0022 #include <boost/math/special_functions/sinhc.hpp> // for the Hyperbolic Sinus cardinal
0023 #include <boost/math/tools/cxx03_warn.hpp>
0024
0025 #include <type_traits>
0026
0027 namespace boost
0028 {
0029 namespace math
0030 {
0031
0032 namespace detail {
0033
0034 template <class T>
0035 struct is_trivial_arithmetic_type_imp
0036 {
0037 typedef std::integral_constant<bool,
0038 noexcept(std::declval<T&>() += std::declval<T>())
0039 && noexcept(std::declval<T&>() -= std::declval<T>())
0040 && noexcept(std::declval<T&>() *= std::declval<T>())
0041 && noexcept(std::declval<T&>() /= std::declval<T>())
0042 > type;
0043 };
0044
0045 template <class T>
0046 struct is_trivial_arithmetic_type : public is_trivial_arithmetic_type_imp<T>::type {};
0047 }
0048
0049 #ifndef BOOST_NO_CXX14_CONSTEXPR
0050 namespace constexpr_detail
0051 {
0052 template <class T>
0053 constexpr void swap(T& a, T& b)
0054 {
0055 T t(a);
0056 a = b;
0057 b = t;
0058 }
0059 }
0060 #endif
0061
0062 template<typename T>
0063 class quaternion
0064 {
0065 public:
0066
0067 typedef T value_type;
0068
0069
0070
0071
0072
0073 constexpr explicit quaternion( T const & requested_a = T(),
0074 T const & requested_b = T(),
0075 T const & requested_c = T(),
0076 T const & requested_d = T())
0077 : a(requested_a),
0078 b(requested_b),
0079 c(requested_c),
0080 d(requested_d)
0081 {
0082
0083 }
0084
0085
0086
0087
0088 constexpr explicit quaternion( ::std::complex<T> const & z0,
0089 ::std::complex<T> const & z1 = ::std::complex<T>())
0090 : a(z0.real()),
0091 b(z0.imag()),
0092 c(z1.real()),
0093 d(z1.imag())
0094 {
0095
0096 }
0097
0098
0099
0100 constexpr quaternion(quaternion const & a_recopier)
0101 : a(a_recopier.R_component_1()),
0102 b(a_recopier.R_component_2()),
0103 c(a_recopier.R_component_3()),
0104 d(a_recopier.R_component_4()) {}
0105
0106 constexpr quaternion(quaternion && a_recopier)
0107 : a(std::move(a_recopier.R_component_1())),
0108 b(std::move(a_recopier.R_component_2())),
0109 c(std::move(a_recopier.R_component_3())),
0110 d(std::move(a_recopier.R_component_4())) {}
0111
0112
0113
0114 template<typename X>
0115 constexpr explicit quaternion(quaternion<X> const & a_recopier)
0116 : a(static_cast<T>(a_recopier.R_component_1())),
0117 b(static_cast<T>(a_recopier.R_component_2())),
0118 c(static_cast<T>(a_recopier.R_component_3())),
0119 d(static_cast<T>(a_recopier.R_component_4()))
0120 {
0121
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 constexpr T real() const
0139 {
0140 return(a);
0141 }
0142
0143 constexpr quaternion<T> unreal() const
0144 {
0145 return(quaternion<T>(static_cast<T>(0), b, c, d));
0146 }
0147
0148 constexpr T R_component_1() const
0149 {
0150 return(a);
0151 }
0152
0153 constexpr T R_component_2() const
0154 {
0155 return(b);
0156 }
0157
0158 constexpr T R_component_3() const
0159 {
0160 return(c);
0161 }
0162
0163 constexpr T R_component_4() const
0164 {
0165 return(d);
0166 }
0167
0168 constexpr ::std::complex<T> C_component_1() const
0169 {
0170 return(::std::complex<T>(a, b));
0171 }
0172
0173 constexpr ::std::complex<T> C_component_2() const
0174 {
0175 return(::std::complex<T>(c, d));
0176 }
0177
0178 BOOST_CXX14_CONSTEXPR void swap(quaternion& o)
0179 {
0180 #ifndef BOOST_NO_CXX14_CONSTEXPR
0181 using constexpr_detail::swap;
0182 #else
0183 using std::swap;
0184 #endif
0185 swap(a, o.a);
0186 swap(b, o.b);
0187 swap(c, o.c);
0188 swap(d, o.d);
0189 }
0190
0191
0192
0193 template<typename X>
0194 BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (quaternion<X> const & a_affecter)
0195 {
0196 a = static_cast<T>(a_affecter.R_component_1());
0197 b = static_cast<T>(a_affecter.R_component_2());
0198 c = static_cast<T>(a_affecter.R_component_3());
0199 d = static_cast<T>(a_affecter.R_component_4());
0200
0201 return(*this);
0202 }
0203
0204 BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (quaternion<T> const & a_affecter)
0205 {
0206 a = a_affecter.a;
0207 b = a_affecter.b;
0208 c = a_affecter.c;
0209 d = a_affecter.d;
0210
0211 return(*this);
0212 }
0213
0214 BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (quaternion<T> && a_affecter)
0215 {
0216 a = std::move(a_affecter.a);
0217 b = std::move(a_affecter.b);
0218 c = std::move(a_affecter.c);
0219 d = std::move(a_affecter.d);
0220
0221 return(*this);
0222 }
0223
0224 BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (T const & a_affecter)
0225 {
0226 a = a_affecter;
0227
0228 b = c = d = static_cast<T>(0);
0229
0230 return(*this);
0231 }
0232
0233 BOOST_CXX14_CONSTEXPR quaternion<T> & operator = (::std::complex<T> const & a_affecter)
0234 {
0235 a = a_affecter.real();
0236 b = a_affecter.imag();
0237
0238 c = d = static_cast<T>(0);
0239
0240 return(*this);
0241 }
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 private:
0253 BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(T const & rhs, const std::true_type&)
0254 {
0255 a += rhs;
0256 return *this;
0257 }
0258 BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(T const & rhs, const std::false_type&)
0259 {
0260 quaternion<T> result(a + rhs, b, c, d);
0261 swap(result);
0262 return *this;
0263 }
0264 BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(std::complex<T> const & rhs, const std::true_type&)
0265 {
0266 a += std::real(rhs);
0267 b += std::imag(rhs);
0268 return *this;
0269 }
0270 BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(std::complex<T> const & rhs, const std::false_type&)
0271 {
0272 quaternion<T> result(a + std::real(rhs), b + std::imag(rhs), c, d);
0273 swap(result);
0274 return *this;
0275 }
0276 template <class X>
0277 BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(quaternion<X> const & rhs, const std::true_type&)
0278 {
0279 a += rhs.R_component_1();
0280 b += rhs.R_component_2();
0281 c += rhs.R_component_3();
0282 d += rhs.R_component_4();
0283 return *this;
0284 }
0285 template <class X>
0286 BOOST_CXX14_CONSTEXPR quaternion<T> & do_add(quaternion<X> const & rhs, const std::false_type&)
0287 {
0288 quaternion<T> result(a + rhs.R_component_1(), b + rhs.R_component_2(), c + rhs.R_component_3(), d + rhs.R_component_4());
0289 swap(result);
0290 return *this;
0291 }
0292
0293 BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(T const & rhs, const std::true_type&)
0294 {
0295 a -= rhs;
0296 return *this;
0297 }
0298 BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(T const & rhs, const std::false_type&)
0299 {
0300 quaternion<T> result(a - rhs, b, c, d);
0301 swap(result);
0302 return *this;
0303 }
0304 BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(std::complex<T> const & rhs, const std::true_type&)
0305 {
0306 a -= std::real(rhs);
0307 b -= std::imag(rhs);
0308 return *this;
0309 }
0310 BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(std::complex<T> const & rhs, const std::false_type&)
0311 {
0312 quaternion<T> result(a - std::real(rhs), b - std::imag(rhs), c, d);
0313 swap(result);
0314 return *this;
0315 }
0316 template <class X>
0317 BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(quaternion<X> const & rhs, const std::true_type&)
0318 {
0319 a -= rhs.R_component_1();
0320 b -= rhs.R_component_2();
0321 c -= rhs.R_component_3();
0322 d -= rhs.R_component_4();
0323 return *this;
0324 }
0325 template <class X>
0326 BOOST_CXX14_CONSTEXPR quaternion<T> & do_subtract(quaternion<X> const & rhs, const std::false_type&)
0327 {
0328 quaternion<T> result(a - rhs.R_component_1(), b - rhs.R_component_2(), c - rhs.R_component_3(), d - rhs.R_component_4());
0329 swap(result);
0330 return *this;
0331 }
0332
0333 BOOST_CXX14_CONSTEXPR quaternion<T> & do_multiply(T const & rhs, const std::true_type&)
0334 {
0335 a *= rhs;
0336 b *= rhs;
0337 c *= rhs;
0338 d *= rhs;
0339 return *this;
0340 }
0341 BOOST_CXX14_CONSTEXPR quaternion<T> & do_multiply(T const & rhs, const std::false_type&)
0342 {
0343 quaternion<T> result(a * rhs, b * rhs, c * rhs, d * rhs);
0344 swap(result);
0345 return *this;
0346 }
0347
0348 BOOST_CXX14_CONSTEXPR quaternion<T> & do_divide(T const & rhs, const std::true_type&)
0349 {
0350 a /= rhs;
0351 b /= rhs;
0352 c /= rhs;
0353 d /= rhs;
0354 return *this;
0355 }
0356 BOOST_CXX14_CONSTEXPR quaternion<T> & do_divide(T const & rhs, const std::false_type&)
0357 {
0358 quaternion<T> result(a / rhs, b / rhs, c / rhs, d / rhs);
0359 swap(result);
0360 return *this;
0361 }
0362 public:
0363
0364 BOOST_CXX14_CONSTEXPR quaternion<T> & operator += (T const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type<T>()); }
0365 BOOST_CXX14_CONSTEXPR quaternion<T> & operator += (::std::complex<T> const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type<T>()); }
0366 template<typename X> BOOST_CXX14_CONSTEXPR quaternion<T> & operator += (quaternion<X> const & rhs) { return do_add(rhs, detail::is_trivial_arithmetic_type<T>()); }
0367
0368 BOOST_CXX14_CONSTEXPR quaternion<T> & operator -= (T const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type<T>()); }
0369 BOOST_CXX14_CONSTEXPR quaternion<T> & operator -= (::std::complex<T> const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type<T>()); }
0370 template<typename X> BOOST_CXX14_CONSTEXPR quaternion<T> & operator -= (quaternion<X> const & rhs) { return do_subtract(rhs, detail::is_trivial_arithmetic_type<T>()); }
0371
0372 BOOST_CXX14_CONSTEXPR quaternion<T> & operator *= (T const & rhs) { return do_multiply(rhs, detail::is_trivial_arithmetic_type<T>()); }
0373
0374 BOOST_CXX14_CONSTEXPR quaternion<T> & operator *= (::std::complex<T> const & rhs)
0375 {
0376 T ar = rhs.real();
0377 T br = rhs.imag();
0378 quaternion<T> result(a*ar - b*br, a*br + b*ar, c*ar + d*br, -c*br+d*ar);
0379 swap(result);
0380 return(*this);
0381 }
0382
0383 template<typename X>
0384 BOOST_CXX14_CONSTEXPR quaternion<T> & operator *= (quaternion<X> const & rhs)
0385 {
0386 T ar = static_cast<T>(rhs.R_component_1());
0387 T br = static_cast<T>(rhs.R_component_2());
0388 T cr = static_cast<T>(rhs.R_component_3());
0389 T dr = static_cast<T>(rhs.R_component_4());
0390
0391 quaternion<T> result(a*ar - b*br - c*cr - d*dr, a*br + b*ar + c*dr - d*cr, a*cr - b*dr + c*ar + d*br, a*dr + b*cr - c*br + d*ar);
0392 swap(result);
0393 return(*this);
0394 }
0395
0396 BOOST_CXX14_CONSTEXPR quaternion<T> & operator /= (T const & rhs) { return do_divide(rhs, detail::is_trivial_arithmetic_type<T>()); }
0397
0398 BOOST_CXX14_CONSTEXPR quaternion<T> & operator /= (::std::complex<T> const & rhs)
0399 {
0400 T ar = rhs.real();
0401 T br = rhs.imag();
0402 T denominator = ar*ar+br*br;
0403 quaternion<T> result((+a*ar + b*br) / denominator, (-a*br + b*ar) / denominator, (+c*ar - d*br) / denominator, (+c*br + d*ar) / denominator);
0404 swap(result);
0405 return(*this);
0406 }
0407
0408 template<typename X>
0409 BOOST_CXX14_CONSTEXPR quaternion<T> & operator /= (quaternion<X> const & rhs)
0410 {
0411 T ar = static_cast<T>(rhs.R_component_1());
0412 T br = static_cast<T>(rhs.R_component_2());
0413 T cr = static_cast<T>(rhs.R_component_3());
0414 T dr = static_cast<T>(rhs.R_component_4());
0415
0416 T denominator = ar*ar+br*br+cr*cr+dr*dr;
0417 quaternion<T> result((+a*ar+b*br+c*cr+d*dr)/denominator, (-a*br+b*ar-c*dr+d*cr)/denominator, (-a*cr+b*dr+c*ar-d*br)/denominator, (-a*dr-b*cr+c*br+d*ar)/denominator);
0418 swap(result);
0419 return(*this);
0420 }
0421 private:
0422 T a, b, c, d;
0423
0424 };
0425
0426
0427 template <class T>
0428 BOOST_CXX14_CONSTEXPR void swap(quaternion<T>& a, quaternion<T>& b) { a.swap(b); }
0429
0430
0431 template <class T1, class T2>
0432 inline constexpr typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0433 operator + (const quaternion<T1>& a, const T2& b)
0434 {
0435 return quaternion<T1>(static_cast<T1>(a.R_component_1() + b), a.R_component_2(), a.R_component_3(), a.R_component_4());
0436 }
0437 template <class T1, class T2>
0438 inline constexpr typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0439 operator + (const T1& a, const quaternion<T2>& b)
0440 {
0441 return quaternion<T2>(static_cast<T2>(b.R_component_1() + a), b.R_component_2(), b.R_component_3(), b.R_component_4());
0442 }
0443 template <class T1, class T2>
0444 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0445 operator + (const quaternion<T1>& a, const std::complex<T2>& b)
0446 {
0447 return quaternion<T1>(a.R_component_1() + std::real(b), a.R_component_2() + std::imag(b), a.R_component_3(), a.R_component_4());
0448 }
0449 template <class T1, class T2>
0450 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0451 operator + (const std::complex<T1>& a, const quaternion<T2>& b)
0452 {
0453 return quaternion<T1>(b.R_component_1() + std::real(a), b.R_component_2() + std::imag(a), b.R_component_3(), b.R_component_4());
0454 }
0455 template <class T>
0456 inline constexpr quaternion<T> operator + (const quaternion<T>& a, const quaternion<T>& b)
0457 {
0458 return quaternion<T>(a.R_component_1() + b.R_component_1(), a.R_component_2() + b.R_component_2(), a.R_component_3() + b.R_component_3(), a.R_component_4() + b.R_component_4());
0459 }
0460
0461 template <class T1, class T2>
0462 inline constexpr typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0463 operator - (const quaternion<T1>& a, const T2& b)
0464 {
0465 return quaternion<T1>(static_cast<T1>(a.R_component_1() - b), a.R_component_2(), a.R_component_3(), a.R_component_4());
0466 }
0467 template <class T1, class T2>
0468 inline constexpr typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0469 operator - (const T1& a, const quaternion<T2>& b)
0470 {
0471 return quaternion<T2>(static_cast<T2>(a - b.R_component_1()), -b.R_component_2(), -b.R_component_3(), -b.R_component_4());
0472 }
0473 template <class T1, class T2>
0474 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0475 operator - (const quaternion<T1>& a, const std::complex<T2>& b)
0476 {
0477 return quaternion<T1>(a.R_component_1() - std::real(b), a.R_component_2() - std::imag(b), a.R_component_3(), a.R_component_4());
0478 }
0479 template <class T1, class T2>
0480 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0481 operator - (const std::complex<T1>& a, const quaternion<T2>& b)
0482 {
0483 return quaternion<T1>(std::real(a) - b.R_component_1(), std::imag(a) - b.R_component_2(), -b.R_component_3(), -b.R_component_4());
0484 }
0485 template <class T>
0486 inline constexpr quaternion<T> operator - (const quaternion<T>& a, const quaternion<T>& b)
0487 {
0488 return quaternion<T>(a.R_component_1() - b.R_component_1(), a.R_component_2() - b.R_component_2(), a.R_component_3() - b.R_component_3(), a.R_component_4() - b.R_component_4());
0489 }
0490
0491
0492 template <class T1, class T2>
0493 inline constexpr typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0494 operator * (const quaternion<T1>& a, const T2& b)
0495 {
0496 return quaternion<T1>(static_cast<T1>(a.R_component_1() * b), a.R_component_2() * b, a.R_component_3() * b, a.R_component_4() * b);
0497 }
0498 template <class T1, class T2>
0499 inline constexpr typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0500 operator * (const T1& a, const quaternion<T2>& b)
0501 {
0502 return quaternion<T2>(static_cast<T2>(a * b.R_component_1()), a * b.R_component_2(), a * b.R_component_3(), a * b.R_component_4());
0503 }
0504 template <class T1, class T2>
0505 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0506 operator * (const quaternion<T1>& a, const std::complex<T2>& b)
0507 {
0508 quaternion<T1> result(a);
0509 result *= b;
0510 return result;
0511 }
0512 template <class T1, class T2>
0513 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0514 operator * (const std::complex<T1>& a, const quaternion<T2>& b)
0515 {
0516 quaternion<T1> result(a);
0517 result *= b;
0518 return result;
0519 }
0520 template <class T>
0521 inline BOOST_CXX14_CONSTEXPR quaternion<T> operator * (const quaternion<T>& a, const quaternion<T>& b)
0522 {
0523 quaternion<T> result(a);
0524 result *= b;
0525 return result;
0526 }
0527
0528
0529 template <class T1, class T2>
0530 inline constexpr typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0531 operator / (const quaternion<T1>& a, const T2& b)
0532 {
0533 return quaternion<T1>(a.R_component_1() / b, a.R_component_2() / b, a.R_component_3() / b, a.R_component_4() / b);
0534 }
0535 template <class T1, class T2>
0536 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0537 operator / (const T1& a, const quaternion<T2>& b)
0538 {
0539 quaternion<T2> result(a);
0540 result /= b;
0541 return result;
0542 }
0543 template <class T1, class T2>
0544 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T2, T1>::value, quaternion<T1> >::type
0545 operator / (const quaternion<T1>& a, const std::complex<T2>& b)
0546 {
0547 quaternion<T1> result(a);
0548 result /= b;
0549 return result;
0550 }
0551 template <class T1, class T2>
0552 inline BOOST_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T1, T2>::value, quaternion<T2> >::type
0553 operator / (const std::complex<T1>& a, const quaternion<T2>& b)
0554 {
0555 quaternion<T2> result(a);
0556 result /= b;
0557 return result;
0558 }
0559 template <class T>
0560 inline BOOST_CXX14_CONSTEXPR quaternion<T> operator / (const quaternion<T>& a, const quaternion<T>& b)
0561 {
0562 quaternion<T> result(a);
0563 result /= b;
0564 return result;
0565 }
0566
0567
0568 template<typename T>
0569 inline constexpr const quaternion<T>& operator + (quaternion<T> const & q)
0570 {
0571 return q;
0572 }
0573
0574
0575 template<typename T>
0576 inline constexpr quaternion<T> operator - (quaternion<T> const & q)
0577 {
0578 return(quaternion<T>(-q.R_component_1(),-q.R_component_2(),-q.R_component_3(),-q.R_component_4()));
0579 }
0580
0581
0582 template<typename R, typename T>
0583 inline constexpr typename std::enable_if<std::is_convertible<R, T>::value, bool>::type operator == (R const & lhs, quaternion<T> const & rhs)
0584 {
0585 return (
0586 (rhs.R_component_1() == lhs)&&
0587 (rhs.R_component_2() == static_cast<T>(0))&&
0588 (rhs.R_component_3() == static_cast<T>(0))&&
0589 (rhs.R_component_4() == static_cast<T>(0))
0590 );
0591 }
0592
0593
0594 template<typename T, typename R>
0595 inline constexpr typename std::enable_if<std::is_convertible<R, T>::value, bool>::type operator == (quaternion<T> const & lhs, R const & rhs)
0596 {
0597 return rhs == lhs;
0598 }
0599
0600
0601 template<typename T>
0602 inline constexpr bool operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs)
0603 {
0604 return (
0605 (rhs.R_component_1() == lhs.real())&&
0606 (rhs.R_component_2() == lhs.imag())&&
0607 (rhs.R_component_3() == static_cast<T>(0))&&
0608 (rhs.R_component_4() == static_cast<T>(0))
0609 );
0610 }
0611
0612
0613 template<typename T>
0614 inline constexpr bool operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
0615 {
0616 return rhs == lhs;
0617 }
0618
0619
0620 template<typename T>
0621 inline constexpr bool operator == (quaternion<T> const & lhs, quaternion<T> const & rhs)
0622 {
0623 return (
0624 (rhs.R_component_1() == lhs.R_component_1())&&
0625 (rhs.R_component_2() == lhs.R_component_2())&&
0626 (rhs.R_component_3() == lhs.R_component_3())&&
0627 (rhs.R_component_4() == lhs.R_component_4())
0628 );
0629 }
0630
0631 template<typename R, typename T> inline constexpr bool operator != (R const & lhs, quaternion<T> const & rhs) { return !(lhs == rhs); }
0632 template<typename T, typename R> inline constexpr bool operator != (quaternion<T> const & lhs, R const & rhs) { return !(lhs == rhs); }
0633 template<typename T> inline constexpr bool operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs) { return !(lhs == rhs); }
0634 template<typename T> inline constexpr bool operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs) { return !(lhs == rhs); }
0635 template<typename T> inline constexpr bool operator != (quaternion<T> const & lhs, quaternion<T> const & rhs) { return !(lhs == rhs); }
0636
0637
0638
0639
0640
0641
0642 template<typename T, typename charT, class traits>
0643 ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
0644 quaternion<T> & q)
0645 {
0646 const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
0647
0648 T a = T();
0649 T b = T();
0650 T c = T();
0651 T d = T();
0652
0653 ::std::complex<T> u = ::std::complex<T>();
0654 ::std::complex<T> v = ::std::complex<T>();
0655
0656 charT ch = charT();
0657 char cc;
0658
0659 is >> ch;
0660
0661 if (!is.good()) goto finish;
0662
0663 cc = ct.narrow(ch, char());
0664
0665 if (cc == '(')
0666 {
0667 is >> ch;
0668
0669 if (!is.good()) goto finish;
0670
0671 cc = ct.narrow(ch, char());
0672
0673 if (cc == '(')
0674 {
0675 is.putback(ch);
0676
0677 is >> u;
0678 a = u.real();
0679 b = u.imag();
0680
0681 if (!is.good()) goto finish;
0682
0683 is >> ch;
0684
0685 if (!is.good()) goto finish;
0686
0687 cc = ct.narrow(ch, char());
0688
0689 if (cc == ')')
0690 {
0691 q = quaternion<T>(a,b);
0692 }
0693 else if (cc == ',')
0694 {
0695 is >> v;
0696 c = v.real();
0697 d = v.imag();
0698
0699 if (!is.good()) goto finish;
0700
0701 is >> ch;
0702
0703 if (!is.good()) goto finish;
0704
0705 cc = ct.narrow(ch, char());
0706
0707 if (cc == ')')
0708 {
0709 q = quaternion<T>(a,b,c,d);
0710 }
0711 else
0712 {
0713 is.setstate(::std::ios_base::failbit);
0714 }
0715 }
0716 else
0717 {
0718 is.setstate(::std::ios_base::failbit);
0719 }
0720 }
0721 else
0722 {
0723 is.putback(ch);
0724
0725 is >> a;
0726
0727 if (!is.good()) goto finish;
0728
0729 is >> ch;
0730
0731 if (!is.good()) goto finish;
0732
0733 cc = ct.narrow(ch, char());
0734
0735 if (cc == ')')
0736 {
0737 q = quaternion<T>(a);
0738 }
0739 else if (cc == ',')
0740 {
0741 is >> ch;
0742
0743 if (!is.good()) goto finish;
0744
0745 cc = ct.narrow(ch, char());
0746
0747 if (cc == '(')
0748 {
0749 is.putback(ch);
0750
0751 is >> v;
0752
0753 c = v.real();
0754 d = v.imag();
0755
0756 if (!is.good()) goto finish;
0757
0758 is >> ch;
0759
0760 if (!is.good()) goto finish;
0761
0762 cc = ct.narrow(ch, char());
0763
0764 if (cc == ')')
0765 {
0766 q = quaternion<T>(a,b,c,d);
0767 }
0768 else
0769 {
0770 is.setstate(::std::ios_base::failbit);
0771 }
0772 }
0773 else
0774 {
0775 is.putback(ch);
0776
0777 is >> b;
0778
0779 if (!is.good()) goto finish;
0780
0781 is >> ch;
0782
0783 if (!is.good()) goto finish;
0784
0785 cc = ct.narrow(ch, char());
0786
0787 if (cc == ')')
0788 {
0789 q = quaternion<T>(a,b);
0790 }
0791 else if (cc == ',')
0792 {
0793 is >> c;
0794
0795 if (!is.good()) goto finish;
0796
0797 is >> ch;
0798
0799 if (!is.good()) goto finish;
0800
0801 cc = ct.narrow(ch, char());
0802
0803 if (cc == ')')
0804 {
0805 q = quaternion<T>(a,b,c);
0806 }
0807 else if (cc == ',')
0808 {
0809 is >> d;
0810
0811 if (!is.good()) goto finish;
0812
0813 is >> ch;
0814
0815 if (!is.good()) goto finish;
0816
0817 cc = ct.narrow(ch, char());
0818
0819 if (cc == ')')
0820 {
0821 q = quaternion<T>(a,b,c,d);
0822 }
0823 else
0824 {
0825 is.setstate(::std::ios_base::failbit);
0826 }
0827 }
0828 else
0829 {
0830 is.setstate(::std::ios_base::failbit);
0831 }
0832 }
0833 else
0834 {
0835 is.setstate(::std::ios_base::failbit);
0836 }
0837 }
0838 }
0839 else
0840 {
0841 is.setstate(::std::ios_base::failbit);
0842 }
0843 }
0844 }
0845 else
0846 {
0847 is.putback(ch);
0848
0849 is >> a;
0850
0851 if (!is.good()) goto finish;
0852
0853 q = quaternion<T>(a);
0854 }
0855
0856 finish:
0857 return(is);
0858 }
0859
0860
0861 template<typename T, typename charT, class traits>
0862 ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
0863 quaternion<T> const & q)
0864 {
0865 ::std::basic_ostringstream<charT,traits> s;
0866
0867 s.flags(os.flags());
0868 s.imbue(os.getloc());
0869 s.precision(os.precision());
0870
0871 s << '(' << q.R_component_1() << ','
0872 << q.R_component_2() << ','
0873 << q.R_component_3() << ','
0874 << q.R_component_4() << ')';
0875
0876 return os << s.str();
0877 }
0878
0879
0880
0881
0882 template<typename T>
0883 inline constexpr T real(quaternion<T> const & q)
0884 {
0885 return(q.real());
0886 }
0887
0888
0889 template<typename T>
0890 inline constexpr quaternion<T> unreal(quaternion<T> const & q)
0891 {
0892 return(q.unreal());
0893 }
0894
0895 template<typename T>
0896 inline T sup(quaternion<T> const & q)
0897 {
0898 using ::std::abs;
0899 return (std::max)((std::max)(abs(q.R_component_1()), abs(q.R_component_2())), (std::max)(abs(q.R_component_3()), abs(q.R_component_4())));
0900 }
0901
0902
0903 template<typename T>
0904 inline T l1(quaternion<T> const & q)
0905 {
0906 using ::std::abs;
0907 return abs(q.R_component_1()) + abs(q.R_component_2()) + abs(q.R_component_3()) + abs(q.R_component_4());
0908 }
0909
0910
0911 template<typename T>
0912 inline T abs(quaternion<T> const & q)
0913 {
0914 using ::std::abs;
0915 using ::std::sqrt;
0916
0917 T maxim = sup(q);
0918
0919 if (maxim == static_cast<T>(0))
0920 {
0921 return(maxim);
0922 }
0923 else
0924 {
0925 T mixam = static_cast<T>(1)/maxim;
0926
0927 T a = q.R_component_1() * mixam;
0928 T b = q.R_component_2() * mixam;
0929 T c = q.R_component_3() * mixam;
0930 T d = q.R_component_4() * mixam;
0931
0932 a *= a;
0933 b *= b;
0934 c *= c;
0935 d *= d;
0936
0937 return(maxim * sqrt(a + b + c + d));
0938 }
0939
0940
0941 }
0942
0943
0944
0945
0946 template<typename T>
0947 inline BOOST_CXX14_CONSTEXPR T norm(quaternion<T>const & q)
0948 {
0949 return(real(q*conj(q)));
0950 }
0951
0952
0953 template<typename T>
0954 inline constexpr quaternion<T> conj(quaternion<T> const & q)
0955 {
0956 return(quaternion<T>( +q.R_component_1(),
0957 -q.R_component_2(),
0958 -q.R_component_3(),
0959 -q.R_component_4()));
0960 }
0961
0962
0963 template<typename T>
0964 inline quaternion<T> spherical( T const & rho,
0965 T const & theta,
0966 T const & phi1,
0967 T const & phi2)
0968 {
0969 using ::std::cos;
0970 using ::std::sin;
0971
0972
0973
0974
0975
0976
0977 T courrant = static_cast<T>(1);
0978
0979 T d = sin(phi2);
0980
0981 courrant *= cos(phi2);
0982
0983 T c = sin(phi1)*courrant;
0984
0985 courrant *= cos(phi1);
0986
0987 T b = sin(theta)*courrant;
0988 T a = cos(theta)*courrant;
0989
0990 return(rho*quaternion<T>(a,b,c,d));
0991 }
0992
0993
0994 template<typename T>
0995 inline quaternion<T> semipolar( T const & rho,
0996 T const & alpha,
0997 T const & theta1,
0998 T const & theta2)
0999 {
1000 using ::std::cos;
1001 using ::std::sin;
1002
1003 T a = cos(alpha)*cos(theta1);
1004 T b = cos(alpha)*sin(theta1);
1005 T c = sin(alpha)*cos(theta2);
1006 T d = sin(alpha)*sin(theta2);
1007
1008 return(rho*quaternion<T>(a,b,c,d));
1009 }
1010
1011
1012 template<typename T>
1013 inline quaternion<T> multipolar( T const & rho1,
1014 T const & theta1,
1015 T const & rho2,
1016 T const & theta2)
1017 {
1018 using ::std::cos;
1019 using ::std::sin;
1020
1021 T a = rho1*cos(theta1);
1022 T b = rho1*sin(theta1);
1023 T c = rho2*cos(theta2);
1024 T d = rho2*sin(theta2);
1025
1026 return(quaternion<T>(a,b,c,d));
1027 }
1028
1029
1030 template<typename T>
1031 inline quaternion<T> cylindrospherical( T const & t,
1032 T const & radius,
1033 T const & longitude,
1034 T const & latitude)
1035 {
1036 using ::std::cos;
1037 using ::std::sin;
1038
1039
1040
1041 T b = radius*cos(longitude)*cos(latitude);
1042 T c = radius*sin(longitude)*cos(latitude);
1043 T d = radius*sin(latitude);
1044
1045 return(quaternion<T>(t,b,c,d));
1046 }
1047
1048
1049 template<typename T>
1050 inline quaternion<T> cylindrical(T const & r,
1051 T const & angle,
1052 T const & h1,
1053 T const & h2)
1054 {
1055 using ::std::cos;
1056 using ::std::sin;
1057
1058 T a = r*cos(angle);
1059 T b = r*sin(angle);
1060
1061 return(quaternion<T>(a,b,h1,h2));
1062 }
1063
1064
1065
1066
1067
1068
1069 template<typename T>
1070 inline quaternion<T> exp(quaternion<T> const & q)
1071 {
1072 using ::std::exp;
1073 using ::std::cos;
1074
1075 using ::boost::math::sinc_pi;
1076
1077 T u = exp(real(q));
1078
1079 T z = abs(unreal(q));
1080
1081 T w = sinc_pi(z);
1082
1083 return(u*quaternion<T>(cos(z),
1084 w*q.R_component_2(), w*q.R_component_3(),
1085 w*q.R_component_4()));
1086 }
1087
1088
1089 template<typename T>
1090 inline quaternion<T> cos(quaternion<T> const & q)
1091 {
1092 using ::std::sin;
1093 using ::std::cos;
1094 using ::std::cosh;
1095
1096 using ::boost::math::sinhc_pi;
1097
1098 T z = abs(unreal(q));
1099
1100 T w = -sin(q.real())*sinhc_pi(z);
1101
1102 return(quaternion<T>(cos(q.real())*cosh(z),
1103 w*q.R_component_2(), w*q.R_component_3(),
1104 w*q.R_component_4()));
1105 }
1106
1107
1108 template<typename T>
1109 inline quaternion<T> sin(quaternion<T> const & q)
1110 {
1111 using ::std::sin;
1112 using ::std::cos;
1113 using ::std::cosh;
1114
1115 using ::boost::math::sinhc_pi;
1116
1117 T z = abs(unreal(q));
1118
1119 T w = +cos(q.real())*sinhc_pi(z);
1120
1121 return(quaternion<T>(sin(q.real())*cosh(z),
1122 w*q.R_component_2(), w*q.R_component_3(),
1123 w*q.R_component_4()));
1124 }
1125
1126
1127 template<typename T>
1128 inline quaternion<T> tan(quaternion<T> const & q)
1129 {
1130 return(sin(q)/cos(q));
1131 }
1132
1133
1134 template<typename T>
1135 inline quaternion<T> cosh(quaternion<T> const & q)
1136 {
1137 return((exp(+q)+exp(-q))/static_cast<T>(2));
1138 }
1139
1140
1141 template<typename T>
1142 inline quaternion<T> sinh(quaternion<T> const & q)
1143 {
1144 return((exp(+q)-exp(-q))/static_cast<T>(2));
1145 }
1146
1147
1148 template<typename T>
1149 inline quaternion<T> tanh(quaternion<T> const & q)
1150 {
1151 return(sinh(q)/cosh(q));
1152 }
1153
1154
1155 template<typename T>
1156 quaternion<T> pow(quaternion<T> const & q,
1157 int n)
1158 {
1159 if (n > 1)
1160 {
1161 int m = n>>1;
1162
1163 quaternion<T> result = pow(q, m);
1164
1165 result *= result;
1166
1167 if (n != (m<<1))
1168 {
1169 result *= q;
1170 }
1171
1172 return(result);
1173 }
1174 else if (n == 1)
1175 {
1176 return(q);
1177 }
1178 else if (n == 0)
1179 {
1180 return(quaternion<T>(static_cast<T>(1)));
1181 }
1182 else
1183 {
1184 return(pow(quaternion<T>(static_cast<T>(1))/q,-n));
1185 }
1186 }
1187 }
1188 }
1189
1190 #endif