fix doc example typo
[boost.git] / boost / math / quaternion.hpp
blobbbccce1b67c35026f94b9702ee29ec6aac3ca87b
1 // boost quaternion.hpp header file
3 // (C) Copyright Hubert Holin 2001.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // See http://www.boost.org for updates, documentation, and revision history.
10 #ifndef BOOST_QUATERNION_HPP
11 #define BOOST_QUATERNION_HPP
14 #include <complex>
15 #include <iosfwd> // for the "<<" and ">>" operators
16 #include <sstream> // for the "<<" operator
18 #include <boost/config.hpp> // for BOOST_NO_STD_LOCALE
19 #include <boost/detail/workaround.hpp>
20 #ifndef BOOST_NO_STD_LOCALE
21 #include <locale> // for the "<<" operator
22 #endif /* BOOST_NO_STD_LOCALE */
24 #include <valarray>
28 #include <boost/math/special_functions/sinc.hpp> // for the Sinus cardinal
29 #include <boost/math/special_functions/sinhc.hpp> // for the Hyperbolic Sinus cardinal
32 namespace boost
34 namespace math
36 #if BOOST_WORKAROUND(__GNUC__, < 3)
37 // gcc 2.95.x uses expression templates for valarray calculations, but
38 // the result is not conforming. We need BOOST_GET_VALARRAY to get an
39 // actual valarray result when we need to call a member function
40 #define BOOST_GET_VALARRAY(T,x) ::std::valarray<T>(x)
41 // gcc 2.95.x has an "std::ios" class that is similar to
42 // "std::ios_base", so we just use a #define
43 #define BOOST_IOS_BASE ::std::ios
44 // gcc 2.x ignores function scope using declarations,
45 // put them in the scope of the enclosing namespace instead:
46 using ::std::valarray;
47 using ::std::sqrt;
48 using ::std::cos;
49 using ::std::sin;
50 using ::std::exp;
51 using ::std::cosh;
52 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
54 #define BOOST_QUATERNION_ACCESSOR_GENERATOR(type) \
55 type real() const \
56 { \
57 return(a); \
58 } \
60 quaternion<type> unreal() const \
61 { \
62 return(quaternion<type>(static_cast<type>(0),b,c,d)); \
63 } \
65 type R_component_1() const \
66 { \
67 return(a); \
68 } \
70 type R_component_2() const \
71 { \
72 return(b); \
73 } \
75 type R_component_3() const \
76 { \
77 return(c); \
78 } \
80 type R_component_4() const \
81 { \
82 return(d); \
83 } \
85 ::std::complex<type> C_component_1() const \
86 { \
87 return(::std::complex<type>(a,b)); \
88 } \
90 ::std::complex<type> C_component_2() const \
91 { \
92 return(::std::complex<type>(c,d)); \
96 #define BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type) \
97 template<typename X> \
98 quaternion<type> & operator = (quaternion<X> const & a_affecter) \
99 { \
100 a = static_cast<type>(a_affecter.R_component_1()); \
101 b = static_cast<type>(a_affecter.R_component_2()); \
102 c = static_cast<type>(a_affecter.R_component_3()); \
103 d = static_cast<type>(a_affecter.R_component_4()); \
105 return(*this); \
108 quaternion<type> & operator = (quaternion<type> const & a_affecter) \
110 a = a_affecter.a; \
111 b = a_affecter.b; \
112 c = a_affecter.c; \
113 d = a_affecter.d; \
115 return(*this); \
118 quaternion<type> & operator = (type const & a_affecter) \
120 a = a_affecter; \
122 b = c = d = static_cast<type>(0); \
124 return(*this); \
127 quaternion<type> & operator = (::std::complex<type> const & a_affecter) \
129 a = a_affecter.real(); \
130 b = a_affecter.imag(); \
132 c = d = static_cast<type>(0); \
134 return(*this); \
138 #define BOOST_QUATERNION_MEMBER_DATA_GENERATOR(type) \
139 type a; \
140 type b; \
141 type c; \
142 type d;
145 template<typename T>
146 class quaternion
148 public:
150 typedef T value_type;
153 // constructor for H seen as R^4
154 // (also default constructor)
156 explicit quaternion( T const & requested_a = T(),
157 T const & requested_b = T(),
158 T const & requested_c = T(),
159 T const & requested_d = T())
160 : a(requested_a),
161 b(requested_b),
162 c(requested_c),
163 d(requested_d)
165 // nothing to do!
169 // constructor for H seen as C^2
171 explicit quaternion( ::std::complex<T> const & z0,
172 ::std::complex<T> const & z1 = ::std::complex<T>())
173 : a(z0.real()),
174 b(z0.imag()),
175 c(z1.real()),
176 d(z1.imag())
178 // nothing to do!
182 // UNtemplated copy constructor
183 // (this is taken care of by the compiler itself)
186 // templated copy constructor
188 template<typename X>
189 explicit quaternion(quaternion<X> const & a_recopier)
190 : a(static_cast<T>(a_recopier.R_component_1())),
191 b(static_cast<T>(a_recopier.R_component_2())),
192 c(static_cast<T>(a_recopier.R_component_3())),
193 d(static_cast<T>(a_recopier.R_component_4()))
195 // nothing to do!
199 // destructor
200 // (this is taken care of by the compiler itself)
203 // accessors
205 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
206 // but unlike them there is no meaningful notion of "imaginary part".
207 // Instead there is an "unreal part" which itself is a quaternion, and usually
208 // nothing simpler (as opposed to the complex number case).
209 // However, for practicallity, there are accessors for the other components
210 // (these are necessary for the templated copy constructor, for instance).
212 BOOST_QUATERNION_ACCESSOR_GENERATOR(T)
214 // assignment operators
216 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T)
218 // other assignment-related operators
220 // NOTE: Quaternion multiplication is *NOT* commutative;
221 // symbolically, "q *= rhs;" means "q = q * rhs;"
222 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
224 quaternion<T> & operator += (T const & rhs)
226 T at = a + rhs; // exception guard
228 a = at;
230 return(*this);
234 quaternion<T> & operator += (::std::complex<T> const & rhs)
236 T at = a + rhs.real(); // exception guard
237 T bt = b + rhs.imag(); // exception guard
239 a = at;
240 b = bt;
242 return(*this);
246 template<typename X>
247 quaternion<T> & operator += (quaternion<X> const & rhs)
249 T at = a + static_cast<T>(rhs.R_component_1()); // exception guard
250 T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard
251 T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard
252 T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard
254 a = at;
255 b = bt;
256 c = ct;
257 d = dt;
259 return(*this);
264 quaternion<T> & operator -= (T const & rhs)
266 T at = a - rhs; // exception guard
268 a = at;
270 return(*this);
274 quaternion<T> & operator -= (::std::complex<T> const & rhs)
276 T at = a - rhs.real(); // exception guard
277 T bt = b - rhs.imag(); // exception guard
279 a = at;
280 b = bt;
282 return(*this);
286 template<typename X>
287 quaternion<T> & operator -= (quaternion<X> const & rhs)
289 T at = a - static_cast<T>(rhs.R_component_1()); // exception guard
290 T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard
291 T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard
292 T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard
294 a = at;
295 b = bt;
296 c = ct;
297 d = dt;
299 return(*this);
303 quaternion<T> & operator *= (T const & rhs)
305 T at = a * rhs; // exception guard
306 T bt = b * rhs; // exception guard
307 T ct = c * rhs; // exception guard
308 T dt = d * rhs; // exception guard
310 a = at;
311 b = bt;
312 c = ct;
313 d = dt;
315 return(*this);
319 quaternion<T> & operator *= (::std::complex<T> const & rhs)
321 T ar = rhs.real();
322 T br = rhs.imag();
324 T at = +a*ar-b*br;
325 T bt = +a*br+b*ar;
326 T ct = +c*ar+d*br;
327 T dt = -c*br+d*ar;
329 a = at;
330 b = bt;
331 c = ct;
332 d = dt;
334 return(*this);
338 template<typename X>
339 quaternion<T> & operator *= (quaternion<X> const & rhs)
341 T ar = static_cast<T>(rhs.R_component_1());
342 T br = static_cast<T>(rhs.R_component_2());
343 T cr = static_cast<T>(rhs.R_component_3());
344 T dr = static_cast<T>(rhs.R_component_4());
346 T at = +a*ar-b*br-c*cr-d*dr;
347 T bt = +a*br+b*ar+c*dr-d*cr; //(a*br+ar*b)+(c*dr-cr*d);
348 T ct = +a*cr-b*dr+c*ar+d*br; //(a*cr+ar*c)+(d*br-dr*b);
349 T dt = +a*dr+b*cr-c*br+d*ar; //(a*dr+ar*d)+(b*cr-br*c);
351 a = at;
352 b = bt;
353 c = ct;
354 d = dt;
356 return(*this);
361 quaternion<T> & operator /= (T const & rhs)
363 T at = a / rhs; // exception guard
364 T bt = b / rhs; // exception guard
365 T ct = c / rhs; // exception guard
366 T dt = d / rhs; // exception guard
368 a = at;
369 b = bt;
370 c = ct;
371 d = dt;
373 return(*this);
377 quaternion<T> & operator /= (::std::complex<T> const & rhs)
379 T ar = rhs.real();
380 T br = rhs.imag();
382 T denominator = ar*ar+br*br;
384 T at = (+a*ar+b*br)/denominator; //(a*ar+b*br)/denominator;
385 T bt = (-a*br+b*ar)/denominator; //(ar*b-a*br)/denominator;
386 T ct = (+c*ar-d*br)/denominator; //(ar*c-d*br)/denominator;
387 T dt = (+c*br+d*ar)/denominator; //(ar*d+br*c)/denominator;
389 a = at;
390 b = bt;
391 c = ct;
392 d = dt;
394 return(*this);
398 template<typename X>
399 quaternion<T> & operator /= (quaternion<X> const & rhs)
401 T ar = static_cast<T>(rhs.R_component_1());
402 T br = static_cast<T>(rhs.R_component_2());
403 T cr = static_cast<T>(rhs.R_component_3());
404 T dr = static_cast<T>(rhs.R_component_4());
406 T denominator = ar*ar+br*br+cr*cr+dr*dr;
408 T at = (+a*ar+b*br+c*cr+d*dr)/denominator; //(a*ar+b*br+c*cr+d*dr)/denominator;
409 T bt = (-a*br+b*ar-c*dr+d*cr)/denominator; //((ar*b-a*br)+(cr*d-c*dr))/denominator;
410 T ct = (-a*cr+b*dr+c*ar-d*br)/denominator; //((ar*c-a*cr)+(dr*b-d*br))/denominator;
411 T dt = (-a*dr-b*cr+c*br+d*ar)/denominator; //((ar*d-a*dr)+(br*c-b*cr))/denominator;
413 a = at;
414 b = bt;
415 c = ct;
416 d = dt;
418 return(*this);
422 protected:
424 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(T)
427 private:
432 // declaration of quaternion specialization
434 template<> class quaternion<float>;
435 template<> class quaternion<double>;
436 template<> class quaternion<long double>;
439 // helper templates for converting copy constructors (declaration)
441 namespace detail
444 template< typename T,
445 typename U
447 quaternion<T> quaternion_type_converter(quaternion<U> const & rhs);
451 // implementation of quaternion specialization
454 #define BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(type) \
455 explicit quaternion( type const & requested_a = static_cast<type>(0), \
456 type const & requested_b = static_cast<type>(0), \
457 type const & requested_c = static_cast<type>(0), \
458 type const & requested_d = static_cast<type>(0)) \
459 : a(requested_a), \
460 b(requested_b), \
461 c(requested_c), \
462 d(requested_d) \
466 explicit quaternion( ::std::complex<type> const & z0, \
467 ::std::complex<type> const & z1 = ::std::complex<type>()) \
468 : a(z0.real()), \
469 b(z0.imag()), \
470 c(z1.real()), \
471 d(z1.imag()) \
476 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
477 quaternion<type> & operator += (type const & rhs) \
479 a += rhs; \
481 return(*this); \
484 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
485 quaternion<type> & operator += (::std::complex<type> const & rhs) \
487 a += rhs.real(); \
488 b += rhs.imag(); \
490 return(*this); \
493 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type) \
494 template<typename X> \
495 quaternion<type> & operator += (quaternion<X> const & rhs) \
497 a += static_cast<type>(rhs.R_component_1()); \
498 b += static_cast<type>(rhs.R_component_2()); \
499 c += static_cast<type>(rhs.R_component_3()); \
500 d += static_cast<type>(rhs.R_component_4()); \
502 return(*this); \
505 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
506 quaternion<type> & operator -= (type const & rhs) \
508 a -= rhs; \
510 return(*this); \
513 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
514 quaternion<type> & operator -= (::std::complex<type> const & rhs) \
516 a -= rhs.real(); \
517 b -= rhs.imag(); \
519 return(*this); \
522 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type) \
523 template<typename X> \
524 quaternion<type> & operator -= (quaternion<X> const & rhs) \
526 a -= static_cast<type>(rhs.R_component_1()); \
527 b -= static_cast<type>(rhs.R_component_2()); \
528 c -= static_cast<type>(rhs.R_component_3()); \
529 d -= static_cast<type>(rhs.R_component_4()); \
531 return(*this); \
534 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
535 quaternion<type> & operator *= (type const & rhs) \
537 a *= rhs; \
538 b *= rhs; \
539 c *= rhs; \
540 d *= rhs; \
542 return(*this); \
545 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
546 quaternion<type> & operator *= (::std::complex<type> const & rhs) \
548 type ar = rhs.real(); \
549 type br = rhs.imag(); \
551 type at = +a*ar-b*br; \
552 type bt = +a*br+b*ar; \
553 type ct = +c*ar+d*br; \
554 type dt = -c*br+d*ar; \
556 a = at; \
557 b = bt; \
558 c = ct; \
559 d = dt; \
561 return(*this); \
564 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type) \
565 template<typename X> \
566 quaternion<type> & operator *= (quaternion<X> const & rhs) \
568 type ar = static_cast<type>(rhs.R_component_1()); \
569 type br = static_cast<type>(rhs.R_component_2()); \
570 type cr = static_cast<type>(rhs.R_component_3()); \
571 type dr = static_cast<type>(rhs.R_component_4()); \
573 type at = +a*ar-b*br-c*cr-d*dr; \
574 type bt = +a*br+b*ar+c*dr-d*cr; \
575 type ct = +a*cr-b*dr+c*ar+d*br; \
576 type dt = +a*dr+b*cr-c*br+d*ar; \
578 a = at; \
579 b = bt; \
580 c = ct; \
581 d = dt; \
583 return(*this); \
586 // There is quite a lot of repetition in the code below. This is intentional.
587 // The last conditional block is the normal form, and the others merely
588 // consist of workarounds for various compiler deficiencies. Hopefuly, when
589 // more compilers are conformant and we can retire support for those that are
590 // not, we will be able to remove the clutter. This is makes the situation
591 // (painfully) explicit.
593 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
594 quaternion<type> & operator /= (type const & rhs) \
596 a /= rhs; \
597 b /= rhs; \
598 c /= rhs; \
599 d /= rhs; \
601 return(*this); \
604 #if defined(__GNUC__) && (__GNUC__ < 3)
605 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
606 quaternion<type> & operator /= (::std::complex<type> const & rhs) \
608 using ::std::valarray; \
610 valarray<type> tr(2); \
612 tr[0] = rhs.real(); \
613 tr[1] = rhs.imag(); \
615 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
617 tr *= mixam; \
619 valarray<type> tt(4); \
621 tt[0] = +a*tr[0]+b*tr[1]; \
622 tt[1] = -a*tr[1]+b*tr[0]; \
623 tt[2] = +c*tr[0]-d*tr[1]; \
624 tt[3] = +c*tr[1]+d*tr[0]; \
626 tr *= tr; \
628 tt *= (mixam/tr.sum()); \
630 a = tt[0]; \
631 b = tt[1]; \
632 c = tt[2]; \
633 d = tt[3]; \
635 return(*this); \
637 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
638 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
639 quaternion<type> & operator /= (::std::complex<type> const & rhs) \
641 using ::std::valarray; \
642 using ::std::abs; \
644 valarray<type> tr(2); \
646 tr[0] = rhs.real(); \
647 tr[1] = rhs.imag(); \
649 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
651 tr *= mixam; \
653 valarray<type> tt(4); \
655 tt[0] = +a*tr[0]+b*tr[1]; \
656 tt[1] = -a*tr[1]+b*tr[0]; \
657 tt[2] = +c*tr[0]-d*tr[1]; \
658 tt[3] = +c*tr[1]+d*tr[0]; \
660 tr *= tr; \
662 tt *= (mixam/tr.sum()); \
664 a = tt[0]; \
665 b = tt[1]; \
666 c = tt[2]; \
667 d = tt[3]; \
669 return(*this); \
671 #else
672 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
673 quaternion<type> & operator /= (::std::complex<type> const & rhs) \
675 using ::std::valarray; \
677 valarray<type> tr(2); \
679 tr[0] = rhs.real(); \
680 tr[1] = rhs.imag(); \
682 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
684 tr *= mixam; \
686 valarray<type> tt(4); \
688 tt[0] = +a*tr[0]+b*tr[1]; \
689 tt[1] = -a*tr[1]+b*tr[0]; \
690 tt[2] = +c*tr[0]-d*tr[1]; \
691 tt[3] = +c*tr[1]+d*tr[0]; \
693 tr *= tr; \
695 tt *= (mixam/tr.sum()); \
697 a = tt[0]; \
698 b = tt[1]; \
699 c = tt[2]; \
700 d = tt[3]; \
702 return(*this); \
704 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
706 #if defined(__GNUC__) && (__GNUC__ < 3)
707 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
708 template<typename X> \
709 quaternion<type> & operator /= (quaternion<X> const & rhs) \
711 using ::std::valarray; \
713 valarray<type> tr(4); \
715 tr[0] = static_cast<type>(rhs.R_component_1()); \
716 tr[1] = static_cast<type>(rhs.R_component_2()); \
717 tr[2] = static_cast<type>(rhs.R_component_3()); \
718 tr[3] = static_cast<type>(rhs.R_component_4()); \
720 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
722 tr *= mixam; \
724 valarray<type> tt(4); \
726 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
727 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
728 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
729 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
731 tr *= tr; \
733 tt *= (mixam/tr.sum()); \
735 a = tt[0]; \
736 b = tt[1]; \
737 c = tt[2]; \
738 d = tt[3]; \
740 return(*this); \
742 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
743 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
744 template<typename X> \
745 quaternion<type> & operator /= (quaternion<X> const & rhs) \
747 using ::std::valarray; \
748 using ::std::abs; \
750 valarray<type> tr(4); \
752 tr[0] = static_cast<type>(rhs.R_component_1()); \
753 tr[1] = static_cast<type>(rhs.R_component_2()); \
754 tr[2] = static_cast<type>(rhs.R_component_3()); \
755 tr[3] = static_cast<type>(rhs.R_component_4()); \
757 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
759 tr *= mixam; \
761 valarray<type> tt(4); \
763 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
764 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
765 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
766 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
768 tr *= tr; \
770 tt *= (mixam/tr.sum()); \
772 a = tt[0]; \
773 b = tt[1]; \
774 c = tt[2]; \
775 d = tt[3]; \
777 return(*this); \
779 #else
780 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
781 template<typename X> \
782 quaternion<type> & operator /= (quaternion<X> const & rhs) \
784 using ::std::valarray; \
786 valarray<type> tr(4); \
788 tr[0] = static_cast<type>(rhs.R_component_1()); \
789 tr[1] = static_cast<type>(rhs.R_component_2()); \
790 tr[2] = static_cast<type>(rhs.R_component_3()); \
791 tr[3] = static_cast<type>(rhs.R_component_4()); \
793 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
795 tr *= mixam; \
797 valarray<type> tt(4); \
799 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
800 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
801 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
802 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
804 tr *= tr; \
806 tt *= (mixam/tr.sum()); \
808 a = tt[0]; \
809 b = tt[1]; \
810 c = tt[2]; \
811 d = tt[3]; \
813 return(*this); \
815 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
817 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
818 BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
819 BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
820 BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type)
822 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
823 BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
824 BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
825 BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type)
827 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
828 BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
829 BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
830 BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type)
832 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type) \
833 BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
834 BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
835 BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)
837 #define BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(type) \
838 BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
839 BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
840 BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
841 BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type)
844 template<>
845 class quaternion<float>
847 public:
849 typedef float value_type;
851 BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(float)
853 // UNtemplated copy constructor
854 // (this is taken care of by the compiler itself)
856 // explicit copy constructors (precision-loosing converters)
858 explicit quaternion(quaternion<double> const & a_recopier)
860 *this = detail::quaternion_type_converter<float, double>(a_recopier);
863 explicit quaternion(quaternion<long double> const & a_recopier)
865 *this = detail::quaternion_type_converter<float, long double>(a_recopier);
868 // destructor
869 // (this is taken care of by the compiler itself)
871 // accessors
873 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
874 // but unlike them there is no meaningful notion of "imaginary part".
875 // Instead there is an "unreal part" which itself is a quaternion, and usually
876 // nothing simpler (as opposed to the complex number case).
877 // However, for practicallity, there are accessors for the other components
878 // (these are necessary for the templated copy constructor, for instance).
880 BOOST_QUATERNION_ACCESSOR_GENERATOR(float)
882 // assignment operators
884 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(float)
886 // other assignment-related operators
888 // NOTE: Quaternion multiplication is *NOT* commutative;
889 // symbolically, "q *= rhs;" means "q = q * rhs;"
890 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
892 BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(float)
895 protected:
897 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(float)
900 private:
905 template<>
906 class quaternion<double>
908 public:
910 typedef double value_type;
912 BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(double)
914 // UNtemplated copy constructor
915 // (this is taken care of by the compiler itself)
917 // converting copy constructor
919 explicit quaternion(quaternion<float> const & a_recopier)
921 *this = detail::quaternion_type_converter<double, float>(a_recopier);
924 // explicit copy constructors (precision-loosing converters)
926 explicit quaternion(quaternion<long double> const & a_recopier)
928 *this = detail::quaternion_type_converter<double, long double>(a_recopier);
931 // destructor
932 // (this is taken care of by the compiler itself)
934 // accessors
936 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
937 // but unlike them there is no meaningful notion of "imaginary part".
938 // Instead there is an "unreal part" which itself is a quaternion, and usually
939 // nothing simpler (as opposed to the complex number case).
940 // However, for practicallity, there are accessors for the other components
941 // (these are necessary for the templated copy constructor, for instance).
943 BOOST_QUATERNION_ACCESSOR_GENERATOR(double)
945 // assignment operators
947 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(double)
949 // other assignment-related operators
951 // NOTE: Quaternion multiplication is *NOT* commutative;
952 // symbolically, "q *= rhs;" means "q = q * rhs;"
953 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
955 BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(double)
958 protected:
960 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(double)
963 private:
968 template<>
969 class quaternion<long double>
971 public:
973 typedef long double value_type;
975 BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(long double)
977 // UNtemplated copy constructor
978 // (this is taken care of by the compiler itself)
980 // converting copy constructors
982 explicit quaternion(quaternion<float> const & a_recopier)
984 *this = detail::quaternion_type_converter<long double, float>(a_recopier);
987 explicit quaternion(quaternion<double> const & a_recopier)
989 *this = detail::quaternion_type_converter<long double, double>(a_recopier);
992 // destructor
993 // (this is taken care of by the compiler itself)
995 // accessors
997 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
998 // but unlike them there is no meaningful notion of "imaginary part".
999 // Instead there is an "unreal part" which itself is a quaternion, and usually
1000 // nothing simpler (as opposed to the complex number case).
1001 // However, for practicallity, there are accessors for the other components
1002 // (these are necessary for the templated copy constructor, for instance).
1004 BOOST_QUATERNION_ACCESSOR_GENERATOR(long double)
1006 // assignment operators
1008 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(long double)
1010 // other assignment-related operators
1012 // NOTE: Quaternion multiplication is *NOT* commutative;
1013 // symbolically, "q *= rhs;" means "q = q * rhs;"
1014 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
1016 BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(long double)
1019 protected:
1021 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(long double)
1024 private:
1029 #undef BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR
1030 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR
1031 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR
1032 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR
1033 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR
1034 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1
1035 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2
1036 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3
1037 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1
1038 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2
1039 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3
1040 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1
1041 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2
1042 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3
1043 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1
1044 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2
1045 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3
1047 #undef BOOST_QUATERNION_CONSTRUCTOR_GENERATOR
1050 #undef BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR
1052 #undef BOOST_QUATERNION_MEMBER_DATA_GENERATOR
1054 #undef BOOST_QUATERNION_ACCESSOR_GENERATOR
1057 // operators
1059 #define BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op) \
1061 quaternion<T> res(lhs); \
1062 res op##= rhs; \
1063 return(res); \
1066 #define BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
1067 template<typename T> \
1068 inline quaternion<T> operator op (T const & lhs, quaternion<T> const & rhs) \
1069 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
1071 #define BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
1072 template<typename T> \
1073 inline quaternion<T> operator op (quaternion<T> const & lhs, T const & rhs) \
1074 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
1076 #define BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
1077 template<typename T> \
1078 inline quaternion<T> operator op (::std::complex<T> const & lhs, quaternion<T> const & rhs) \
1079 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
1081 #define BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
1082 template<typename T> \
1083 inline quaternion<T> operator op (quaternion<T> const & lhs, ::std::complex<T> const & rhs) \
1084 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
1086 #define BOOST_QUATERNION_OPERATOR_GENERATOR_3(op) \
1087 template<typename T> \
1088 inline quaternion<T> operator op (quaternion<T> const & lhs, quaternion<T> const & rhs) \
1089 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
1091 #define BOOST_QUATERNION_OPERATOR_GENERATOR(op) \
1092 BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
1093 BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
1094 BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
1095 BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
1096 BOOST_QUATERNION_OPERATOR_GENERATOR_3(op)
1099 BOOST_QUATERNION_OPERATOR_GENERATOR(+)
1100 BOOST_QUATERNION_OPERATOR_GENERATOR(-)
1101 BOOST_QUATERNION_OPERATOR_GENERATOR(*)
1102 BOOST_QUATERNION_OPERATOR_GENERATOR(/)
1105 #undef BOOST_QUATERNION_OPERATOR_GENERATOR
1107 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_L
1108 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_R
1109 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_L
1110 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_R
1111 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_3
1113 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_BODY
1116 template<typename T>
1117 inline quaternion<T> operator + (quaternion<T> const & q)
1119 return(q);
1123 template<typename T>
1124 inline quaternion<T> operator - (quaternion<T> const & q)
1126 return(quaternion<T>(-q.R_component_1(),-q.R_component_2(),-q.R_component_3(),-q.R_component_4()));
1130 template<typename T>
1131 inline bool operator == (T const & lhs, quaternion<T> const & rhs)
1133 return (
1134 (rhs.R_component_1() == lhs)&&
1135 (rhs.R_component_2() == static_cast<T>(0))&&
1136 (rhs.R_component_3() == static_cast<T>(0))&&
1137 (rhs.R_component_4() == static_cast<T>(0))
1142 template<typename T>
1143 inline bool operator == (quaternion<T> const & lhs, T const & rhs)
1145 return (
1146 (lhs.R_component_1() == rhs)&&
1147 (lhs.R_component_2() == static_cast<T>(0))&&
1148 (lhs.R_component_3() == static_cast<T>(0))&&
1149 (lhs.R_component_4() == static_cast<T>(0))
1154 template<typename T>
1155 inline bool operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs)
1157 return (
1158 (rhs.R_component_1() == lhs.real())&&
1159 (rhs.R_component_2() == lhs.imag())&&
1160 (rhs.R_component_3() == static_cast<T>(0))&&
1161 (rhs.R_component_4() == static_cast<T>(0))
1166 template<typename T>
1167 inline bool operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
1169 return (
1170 (lhs.R_component_1() == rhs.real())&&
1171 (lhs.R_component_2() == rhs.imag())&&
1172 (lhs.R_component_3() == static_cast<T>(0))&&
1173 (lhs.R_component_4() == static_cast<T>(0))
1178 template<typename T>
1179 inline bool operator == (quaternion<T> const & lhs, quaternion<T> const & rhs)
1181 return (
1182 (rhs.R_component_1() == lhs.R_component_1())&&
1183 (rhs.R_component_2() == lhs.R_component_2())&&
1184 (rhs.R_component_3() == lhs.R_component_3())&&
1185 (rhs.R_component_4() == lhs.R_component_4())
1190 #define BOOST_QUATERNION_NOT_EQUAL_GENERATOR \
1192 return(!(lhs == rhs)); \
1195 template<typename T>
1196 inline bool operator != (T const & lhs, quaternion<T> const & rhs)
1197 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
1199 template<typename T>
1200 inline bool operator != (quaternion<T> const & lhs, T const & rhs)
1201 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
1203 template<typename T>
1204 inline bool operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs)
1205 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
1207 template<typename T>
1208 inline bool operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
1209 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
1211 template<typename T>
1212 inline bool operator != (quaternion<T> const & lhs, quaternion<T> const & rhs)
1213 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
1215 #undef BOOST_QUATERNION_NOT_EQUAL_GENERATOR
1218 // Note: we allow the following formats, whith a, b, c, and d reals
1219 // a
1220 // (a), (a,b), (a,b,c), (a,b,c,d)
1221 // (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))
1222 #if BOOST_WORKAROUND(__GNUC__, < 3)
1223 template<typename T>
1224 std::istream & operator >> ( ::std::istream & is,
1225 quaternion<T> & q)
1226 #else
1227 template<typename T, typename charT, class traits>
1228 ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
1229 quaternion<T> & q)
1230 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1232 #if BOOST_WORKAROUND(__GNUC__, < 3)
1233 typedef char charT;
1234 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1236 #ifdef BOOST_NO_STD_LOCALE
1237 #else
1238 const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
1239 #endif /* BOOST_NO_STD_LOCALE */
1241 T a = T();
1242 T b = T();
1243 T c = T();
1244 T d = T();
1246 ::std::complex<T> u = ::std::complex<T>();
1247 ::std::complex<T> v = ::std::complex<T>();
1249 charT ch = charT();
1250 char cc;
1252 is >> ch; // get the first lexeme
1254 if (!is.good()) goto finish;
1256 #ifdef BOOST_NO_STD_LOCALE
1257 cc = ch;
1258 #else
1259 cc = ct.narrow(ch, char());
1260 #endif /* BOOST_NO_STD_LOCALE */
1262 if (cc == '(') // read "(", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
1264 is >> ch; // get the second lexeme
1266 if (!is.good()) goto finish;
1268 #ifdef BOOST_NO_STD_LOCALE
1269 cc = ch;
1270 #else
1271 cc = ct.narrow(ch, char());
1272 #endif /* BOOST_NO_STD_LOCALE */
1274 if (cc == '(') // read "((", possible: ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
1276 is.putback(ch);
1278 is >> u; // we extract the first and second components
1279 a = u.real();
1280 b = u.imag();
1282 if (!is.good()) goto finish;
1284 is >> ch; // get the next lexeme
1286 if (!is.good()) goto finish;
1288 #ifdef BOOST_NO_STD_LOCALE
1289 cc = ch;
1290 #else
1291 cc = ct.narrow(ch, char());
1292 #endif /* BOOST_NO_STD_LOCALE */
1294 if (cc == ')') // format: ((a)) or ((a,b))
1296 q = quaternion<T>(a,b);
1298 else if (cc == ',') // read "((a)," or "((a,b),", possible: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
1300 is >> v; // we extract the third and fourth components
1301 c = v.real();
1302 d = v.imag();
1304 if (!is.good()) goto finish;
1306 is >> ch; // get the last lexeme
1308 if (!is.good()) goto finish;
1310 #ifdef BOOST_NO_STD_LOCALE
1311 cc = ch;
1312 #else
1313 cc = ct.narrow(ch, char());
1314 #endif /* BOOST_NO_STD_LOCALE */
1316 if (cc == ')') // format: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)) or ((a,b,),(c,d,))
1318 q = quaternion<T>(a,b,c,d);
1320 else // error
1322 #if BOOST_WORKAROUND(__GNUC__, < 3)
1323 is.setstate(::std::ios::failbit);
1324 #else
1325 is.setstate(::std::ios_base::failbit);
1326 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1329 else // error
1331 #if BOOST_WORKAROUND(__GNUC__, < 3)
1332 is.setstate(::std::ios::failbit);
1333 #else
1334 is.setstate(::std::ios_base::failbit);
1335 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1338 else // read "(a", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
1340 is.putback(ch);
1342 is >> a; // we extract the first component
1344 if (!is.good()) goto finish;
1346 is >> ch; // get the third lexeme
1348 if (!is.good()) goto finish;
1350 #ifdef BOOST_NO_STD_LOCALE
1351 cc = ch;
1352 #else
1353 cc = ct.narrow(ch, char());
1354 #endif /* BOOST_NO_STD_LOCALE */
1356 if (cc == ')') // format: (a)
1358 q = quaternion<T>(a);
1360 else if (cc == ',') // read "(a,", possible: (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
1362 is >> ch; // get the fourth lexeme
1364 if (!is.good()) goto finish;
1366 #ifdef BOOST_NO_STD_LOCALE
1367 cc = ch;
1368 #else
1369 cc = ct.narrow(ch, char());
1370 #endif /* BOOST_NO_STD_LOCALE */
1372 if (cc == '(') // read "(a,(", possible: (a,(c)), (a,(c,d))
1374 is.putback(ch);
1376 is >> v; // we extract the third and fourth component
1378 c = v.real();
1379 d = v.imag();
1381 if (!is.good()) goto finish;
1383 is >> ch; // get the ninth lexeme
1385 if (!is.good()) goto finish;
1387 #ifdef BOOST_NO_STD_LOCALE
1388 cc = ch;
1389 #else
1390 cc = ct.narrow(ch, char());
1391 #endif /* BOOST_NO_STD_LOCALE */
1393 if (cc == ')') // format: (a,(c)) or (a,(c,d))
1395 q = quaternion<T>(a,b,c,d);
1397 else // error
1399 #if BOOST_WORKAROUND(__GNUC__, < 3)
1400 is.setstate(::std::ios::failbit);
1401 #else
1402 is.setstate(::std::ios_base::failbit);
1403 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1406 else // read "(a,b", possible: (a,b), (a,b,c), (a,b,c,d)
1408 is.putback(ch);
1410 is >> b; // we extract the second component
1412 if (!is.good()) goto finish;
1414 is >> ch; // get the fifth lexeme
1416 if (!is.good()) goto finish;
1418 #ifdef BOOST_NO_STD_LOCALE
1419 cc = ch;
1420 #else
1421 cc = ct.narrow(ch, char());
1422 #endif /* BOOST_NO_STD_LOCALE */
1424 if (cc == ')') // format: (a,b)
1426 q = quaternion<T>(a,b);
1428 else if (cc == ',') // read "(a,b,", possible: (a,b,c), (a,b,c,d)
1430 is >> c; // we extract the third component
1432 if (!is.good()) goto finish;
1434 is >> ch; // get the seventh lexeme
1436 if (!is.good()) goto finish;
1438 #ifdef BOOST_NO_STD_LOCALE
1439 cc = ch;
1440 #else
1441 cc = ct.narrow(ch, char());
1442 #endif /* BOOST_NO_STD_LOCALE */
1444 if (cc == ')') // format: (a,b,c)
1446 q = quaternion<T>(a,b,c);
1448 else if (cc == ',') // read "(a,b,c,", possible: (a,b,c,d)
1450 is >> d; // we extract the fourth component
1452 if (!is.good()) goto finish;
1454 is >> ch; // get the ninth lexeme
1456 if (!is.good()) goto finish;
1458 #ifdef BOOST_NO_STD_LOCALE
1459 cc = ch;
1460 #else
1461 cc = ct.narrow(ch, char());
1462 #endif /* BOOST_NO_STD_LOCALE */
1464 if (cc == ')') // format: (a,b,c,d)
1466 q = quaternion<T>(a,b,c,d);
1468 else // error
1470 #if BOOST_WORKAROUND(__GNUC__, < 3)
1471 is.setstate(::std::ios::failbit);
1472 #else
1473 is.setstate(::std::ios_base::failbit);
1474 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1477 else // error
1479 #if BOOST_WORKAROUND(__GNUC__, < 3)
1480 is.setstate(::std::ios::failbit);
1481 #else
1482 is.setstate(::std::ios_base::failbit);
1483 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1486 else // error
1488 #if BOOST_WORKAROUND(__GNUC__, < 3)
1489 is.setstate(::std::ios::failbit);
1490 #else
1491 is.setstate(::std::ios_base::failbit);
1492 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1496 else // error
1498 #if BOOST_WORKAROUND(__GNUC__, < 3)
1499 is.setstate(::std::ios::failbit);
1500 #else
1501 is.setstate(::std::ios_base::failbit);
1502 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1506 else // format: a
1508 is.putback(ch);
1510 is >> a; // we extract the first component
1512 if (!is.good()) goto finish;
1514 q = quaternion<T>(a);
1517 finish:
1518 return(is);
1522 #if BOOST_WORKAROUND(__GNUC__, < 3)
1523 template<typename T>
1524 ::std::ostream & operator << ( ::std::ostream & os,
1525 quaternion<T> const & q)
1526 #else
1527 template<typename T, typename charT, class traits>
1528 ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
1529 quaternion<T> const & q)
1530 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1532 #if BOOST_WORKAROUND(__GNUC__, < 3)
1533 ::std::ostringstream s;
1534 #else
1535 ::std::basic_ostringstream<charT,traits> s;
1536 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1538 s.flags(os.flags());
1539 #ifdef BOOST_NO_STD_LOCALE
1540 #else
1541 s.imbue(os.getloc());
1542 #endif /* BOOST_NO_STD_LOCALE */
1543 s.precision(os.precision());
1545 s << '(' << q.R_component_1() << ','
1546 << q.R_component_2() << ','
1547 << q.R_component_3() << ','
1548 << q.R_component_4() << ')';
1550 return os << s.str();
1554 // values
1556 template<typename T>
1557 inline T real(quaternion<T> const & q)
1559 return(q.real());
1563 template<typename T>
1564 inline quaternion<T> unreal(quaternion<T> const & q)
1566 return(q.unreal());
1570 #define BOOST_QUATERNION_VALARRAY_LOADER \
1571 using ::std::valarray; \
1573 valarray<T> temp(4); \
1575 temp[0] = q.R_component_1(); \
1576 temp[1] = q.R_component_2(); \
1577 temp[2] = q.R_component_3(); \
1578 temp[3] = q.R_component_4();
1581 template<typename T>
1582 inline T sup(quaternion<T> const & q)
1584 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
1585 using ::std::abs;
1586 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1588 BOOST_QUATERNION_VALARRAY_LOADER
1590 #if BOOST_WORKAROUND(__GNUC__, < 3)
1591 return((BOOST_GET_VALARRAY(T, abs(temp)).max)());
1592 #else
1593 return((abs(temp).max)());
1594 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1598 template<typename T>
1599 inline T l1(quaternion<T> const & q)
1601 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
1602 using ::std::abs;
1603 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1605 BOOST_QUATERNION_VALARRAY_LOADER
1607 #if BOOST_WORKAROUND(__GNUC__, < 3)
1608 return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
1609 #else
1610 return(abs(temp).sum());
1611 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1615 template<typename T>
1616 inline T abs(quaternion<T> const & q)
1618 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
1619 using ::std::abs;
1620 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1622 using ::std::sqrt;
1624 BOOST_QUATERNION_VALARRAY_LOADER
1626 #if BOOST_WORKAROUND(__GNUC__, < 3)
1627 T maxim = (BOOST_GET_VALARRAY(T, abs(temp)).max)(); // overflow protection
1628 #else
1629 T maxim = (abs(temp).max)(); // overflow protection
1630 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1632 if (maxim == static_cast<T>(0))
1634 return(maxim);
1636 else
1638 T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions
1640 temp *= mixam;
1642 temp *= temp;
1644 return(maxim*sqrt(temp.sum()));
1647 //return(sqrt(norm(q)));
1651 #undef BOOST_QUATERNION_VALARRAY_LOADER
1654 // Note: This is the Cayley norm, not the Euclidian norm...
1656 template<typename T>
1657 inline T norm(quaternion<T>const & q)
1659 return(real(q*conj(q)));
1663 template<typename T>
1664 inline quaternion<T> conj(quaternion<T> const & q)
1666 return(quaternion<T>( +q.R_component_1(),
1667 -q.R_component_2(),
1668 -q.R_component_3(),
1669 -q.R_component_4()));
1673 template<typename T>
1674 inline quaternion<T> spherical( T const & rho,
1675 T const & theta,
1676 T const & phi1,
1677 T const & phi2)
1679 using ::std::cos;
1680 using ::std::sin;
1682 //T a = cos(theta)*cos(phi1)*cos(phi2);
1683 //T b = sin(theta)*cos(phi1)*cos(phi2);
1684 //T c = sin(phi1)*cos(phi2);
1685 //T d = sin(phi2);
1687 T courrant = static_cast<T>(1);
1689 T d = sin(phi2);
1691 courrant *= cos(phi2);
1693 T c = sin(phi1)*courrant;
1695 courrant *= cos(phi1);
1697 T b = sin(theta)*courrant;
1698 T a = cos(theta)*courrant;
1700 return(rho*quaternion<T>(a,b,c,d));
1704 template<typename T>
1705 inline quaternion<T> semipolar( T const & rho,
1706 T const & alpha,
1707 T const & theta1,
1708 T const & theta2)
1710 using ::std::cos;
1711 using ::std::sin;
1713 T a = cos(alpha)*cos(theta1);
1714 T b = cos(alpha)*sin(theta1);
1715 T c = sin(alpha)*cos(theta2);
1716 T d = sin(alpha)*sin(theta2);
1718 return(rho*quaternion<T>(a,b,c,d));
1722 template<typename T>
1723 inline quaternion<T> multipolar( T const & rho1,
1724 T const & theta1,
1725 T const & rho2,
1726 T const & theta2)
1728 using ::std::cos;
1729 using ::std::sin;
1731 T a = rho1*cos(theta1);
1732 T b = rho1*sin(theta1);
1733 T c = rho2*cos(theta2);
1734 T d = rho2*sin(theta2);
1736 return(quaternion<T>(a,b,c,d));
1740 template<typename T>
1741 inline quaternion<T> cylindrospherical( T const & t,
1742 T const & radius,
1743 T const & longitude,
1744 T const & latitude)
1746 using ::std::cos;
1747 using ::std::sin;
1751 T b = radius*cos(longitude)*cos(latitude);
1752 T c = radius*sin(longitude)*cos(latitude);
1753 T d = radius*sin(latitude);
1755 return(quaternion<T>(t,b,c,d));
1759 template<typename T>
1760 inline quaternion<T> cylindrical(T const & r,
1761 T const & angle,
1762 T const & h1,
1763 T const & h2)
1765 using ::std::cos;
1766 using ::std::sin;
1768 T a = r*cos(angle);
1769 T b = r*sin(angle);
1771 return(quaternion<T>(a,b,h1,h2));
1775 // transcendentals
1776 // (please see the documentation)
1779 template<typename T>
1780 inline quaternion<T> exp(quaternion<T> const & q)
1782 using ::std::exp;
1783 using ::std::cos;
1785 using ::boost::math::sinc_pi;
1787 T u = exp(real(q));
1789 T z = abs(unreal(q));
1791 T w = sinc_pi(z);
1793 return(u*quaternion<T>(cos(z),
1794 w*q.R_component_2(), w*q.R_component_3(),
1795 w*q.R_component_4()));
1799 template<typename T>
1800 inline quaternion<T> cos(quaternion<T> const & q)
1802 using ::std::sin;
1803 using ::std::cos;
1804 using ::std::cosh;
1806 using ::boost::math::sinhc_pi;
1808 T z = abs(unreal(q));
1810 T w = -sin(q.real())*sinhc_pi(z);
1812 return(quaternion<T>(cos(q.real())*cosh(z),
1813 w*q.R_component_2(), w*q.R_component_3(),
1814 w*q.R_component_4()));
1818 template<typename T>
1819 inline quaternion<T> sin(quaternion<T> const & q)
1821 using ::std::sin;
1822 using ::std::cos;
1823 using ::std::cosh;
1825 using ::boost::math::sinhc_pi;
1827 T z = abs(unreal(q));
1829 T w = +cos(q.real())*sinhc_pi(z);
1831 return(quaternion<T>(sin(q.real())*cosh(z),
1832 w*q.R_component_2(), w*q.R_component_3(),
1833 w*q.R_component_4()));
1837 template<typename T>
1838 inline quaternion<T> tan(quaternion<T> const & q)
1840 return(sin(q)/cos(q));
1844 template<typename T>
1845 inline quaternion<T> cosh(quaternion<T> const & q)
1847 return((exp(+q)+exp(-q))/static_cast<T>(2));
1851 template<typename T>
1852 inline quaternion<T> sinh(quaternion<T> const & q)
1854 return((exp(+q)-exp(-q))/static_cast<T>(2));
1858 template<typename T>
1859 inline quaternion<T> tanh(quaternion<T> const & q)
1861 return(sinh(q)/cosh(q));
1865 template<typename T>
1866 quaternion<T> pow(quaternion<T> const & q,
1867 int n)
1869 if (n > 1)
1871 int m = n>>1;
1873 quaternion<T> result = pow(q, m);
1875 result *= result;
1877 if (n != (m<<1))
1879 result *= q; // n odd
1882 return(result);
1884 else if (n == 1)
1886 return(q);
1888 else if (n == 0)
1890 return(quaternion<T>(1));
1892 else /* n < 0 */
1894 return(pow(quaternion<T>(1)/q,-n));
1899 // helper templates for converting copy constructors (definition)
1901 namespace detail
1904 template< typename T,
1905 typename U
1907 quaternion<T> quaternion_type_converter(quaternion<U> const & rhs)
1909 return(quaternion<T>( static_cast<T>(rhs.R_component_1()),
1910 static_cast<T>(rhs.R_component_2()),
1911 static_cast<T>(rhs.R_component_3()),
1912 static_cast<T>(rhs.R_component_4())));
1919 #if BOOST_WORKAROUND(__GNUC__, < 3)
1920 #undef BOOST_GET_VALARRAY
1921 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1924 #endif /* BOOST_QUATERNION_HPP */