1 // boost octonion.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.
11 #ifndef BOOST_OCTONION_HPP
12 #define BOOST_OCTONION_HPP
14 #include <boost/math/quaternion.hpp>
23 #define BOOST_OCTONION_ACCESSOR_GENERATOR(type) \
29 octonion<type> unreal() const \
31 return( octonion<type>(static_cast<type>(0),b,c,d,e,f,g,h)); \
34 type R_component_1() const \
39 type R_component_2() const \
44 type R_component_3() const \
49 type R_component_4() const \
54 type R_component_5() const \
59 type R_component_6() const \
64 type R_component_7() const \
69 type R_component_8() const \
74 ::std::complex<type> C_component_1() const \
76 return(::std::complex<type>(a,b)); \
79 ::std::complex<type> C_component_2() const \
81 return(::std::complex<type>(c,d)); \
84 ::std::complex<type> C_component_3() const \
86 return(::std::complex<type>(e,f)); \
89 ::std::complex<type> C_component_4() const \
91 return(::std::complex<type>(g,h)); \
94 ::boost::math::quaternion<type> H_component_1() const \
96 return(::boost::math::quaternion<type>(a,b,c,d)); \
99 ::boost::math::quaternion<type> H_component_2() const \
101 return(::boost::math::quaternion<type>(e,f,g,h)); \
105 #define BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(type) \
106 template<typename X> \
107 octonion<type> & operator = (octonion<X> const & a_affecter) \
109 a = static_cast<type>(a_affecter.R_component_1()); \
110 b = static_cast<type>(a_affecter.R_component_2()); \
111 c = static_cast<type>(a_affecter.R_component_3()); \
112 d = static_cast<type>(a_affecter.R_component_4()); \
113 e = static_cast<type>(a_affecter.R_component_5()); \
114 f = static_cast<type>(a_affecter.R_component_6()); \
115 g = static_cast<type>(a_affecter.R_component_7()); \
116 h = static_cast<type>(a_affecter.R_component_8()); \
121 octonion<type> & operator = (octonion<type> const & a_affecter) \
135 octonion<type> & operator = (type const & a_affecter) \
139 b = c = d = e = f= g = h = static_cast<type>(0); \
144 octonion<type> & operator = (::std::complex<type> const & a_affecter) \
146 a = a_affecter.real(); \
147 b = a_affecter.imag(); \
149 c = d = e = f = g = h = static_cast<type>(0); \
154 octonion<type> & operator = (::boost::math::quaternion<type> const & a_affecter) \
156 a = a_affecter.R_component_1(); \
157 b = a_affecter.R_component_2(); \
158 c = a_affecter.R_component_3(); \
159 d = a_affecter.R_component_4(); \
161 e = f = g = h = static_cast<type>(0); \
167 #define BOOST_OCTONION_MEMBER_DATA_GENERATOR(type) \
183 typedef T value_type;
185 // constructor for O seen as R^8
186 // (also default constructor)
188 explicit octonion( T const & requested_a = T(),
189 T const & requested_b = T(),
190 T const & requested_c = T(),
191 T const & requested_d = T(),
192 T const & requested_e = T(),
193 T const & requested_f = T(),
194 T const & requested_g = T(),
195 T const & requested_h = T())
209 // constructor for H seen as C^4
211 explicit octonion( ::std::complex<T> const & z0,
212 ::std::complex<T> const & z1 = ::std::complex<T>(),
213 ::std::complex<T> const & z2 = ::std::complex<T>(),
214 ::std::complex<T> const & z3 = ::std::complex<T>())
228 // constructor for O seen as H^2
230 explicit octonion( ::boost::math::quaternion<T> const & q0,
231 ::boost::math::quaternion<T> const & q1 = ::boost::math::quaternion<T>())
232 : a(q0.R_component_1()),
233 b(q0.R_component_2()),
234 c(q0.R_component_3()),
235 d(q0.R_component_4()),
236 e(q1.R_component_1()),
237 f(q1.R_component_2()),
238 g(q1.R_component_3()),
239 h(q1.R_component_4())
245 // UNtemplated copy constructor
246 // (this is taken care of by the compiler itself)
249 // templated copy constructor
252 explicit octonion(octonion<X> const & a_recopier)
253 : a(static_cast<T>(a_recopier.R_component_1())),
254 b(static_cast<T>(a_recopier.R_component_2())),
255 c(static_cast<T>(a_recopier.R_component_3())),
256 d(static_cast<T>(a_recopier.R_component_4())),
257 e(static_cast<T>(a_recopier.R_component_5())),
258 f(static_cast<T>(a_recopier.R_component_6())),
259 g(static_cast<T>(a_recopier.R_component_7())),
260 h(static_cast<T>(a_recopier.R_component_8()))
267 // (this is taken care of by the compiler itself)
272 // Note: Like complex number, octonions do have a meaningful notion of "real part",
273 // but unlike them there is no meaningful notion of "imaginary part".
274 // Instead there is an "unreal part" which itself is an octonion, and usually
275 // nothing simpler (as opposed to the complex number case).
276 // However, for practicallity, there are accessors for the other components
277 // (these are necessary for the templated copy constructor, for instance).
279 BOOST_OCTONION_ACCESSOR_GENERATOR(T)
281 // assignment operators
283 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(T)
285 // other assignment-related operators
287 // NOTE: Octonion multiplication is *NOT* commutative;
288 // symbolically, "q *= rhs;" means "q = q * rhs;"
289 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
290 // octonion multiplication is also *NOT* associative
292 octonion<T> & operator += (T const & rhs)
294 T at = a + rhs; // exception guard
302 octonion<T> & operator += (::std::complex<T> const & rhs)
304 T at = a + rhs.real(); // exception guard
305 T bt = b + rhs.imag(); // exception guard
314 octonion<T> & operator += (::boost::math::quaternion<T> const & rhs)
316 T at = a + rhs.R_component_1(); // exception guard
317 T bt = b + rhs.R_component_2(); // exception guard
318 T ct = c + rhs.R_component_3(); // exception guard
319 T dt = d + rhs.R_component_4(); // exception guard
331 octonion<T> & operator += (octonion<X> const & rhs)
333 T at = a + static_cast<T>(rhs.R_component_1()); // exception guard
334 T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard
335 T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard
336 T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard
337 T et = e + static_cast<T>(rhs.R_component_5()); // exception guard
338 T ft = f + static_cast<T>(rhs.R_component_6()); // exception guard
339 T gt = g + static_cast<T>(rhs.R_component_7()); // exception guard
340 T ht = h + static_cast<T>(rhs.R_component_8()); // exception guard
356 octonion<T> & operator -= (T const & rhs)
358 T at = a - rhs; // exception guard
366 octonion<T> & operator -= (::std::complex<T> const & rhs)
368 T at = a - rhs.real(); // exception guard
369 T bt = b - rhs.imag(); // exception guard
378 octonion<T> & operator -= (::boost::math::quaternion<T> const & rhs)
380 T at = a - rhs.R_component_1(); // exception guard
381 T bt = b - rhs.R_component_2(); // exception guard
382 T ct = c - rhs.R_component_3(); // exception guard
383 T dt = d - rhs.R_component_4(); // exception guard
395 octonion<T> & operator -= (octonion<X> const & rhs)
397 T at = a - static_cast<T>(rhs.R_component_1()); // exception guard
398 T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard
399 T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard
400 T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard
401 T et = e - static_cast<T>(rhs.R_component_5()); // exception guard
402 T ft = f - static_cast<T>(rhs.R_component_6()); // exception guard
403 T gt = g - static_cast<T>(rhs.R_component_7()); // exception guard
404 T ht = h - static_cast<T>(rhs.R_component_8()); // exception guard
419 octonion<T> & operator *= (T const & rhs)
421 T at = a * rhs; // exception guard
422 T bt = b * rhs; // exception guard
423 T ct = c * rhs; // exception guard
424 T dt = d * rhs; // exception guard
425 T et = e * rhs; // exception guard
426 T ft = f * rhs; // exception guard
427 T gt = g * rhs; // exception guard
428 T ht = h * rhs; // exception guard
443 octonion<T> & operator *= (::std::complex<T> const & rhs)
470 octonion<T> & operator *= (::boost::math::quaternion<T> const & rhs)
472 T ar = rhs.R_component_1();
473 T br = rhs.R_component_2();
474 T cr = rhs.R_component_2();
475 T dr = rhs.R_component_2();
477 T at = +a*ar-b*br-c*cr-d*dr;
478 T bt = +a*br+b*ar+c*dr-d*cr;
479 T ct = +a*cr-b*dr+c*ar+d*br;
480 T dt = +a*dr+b*cr-c*br+d*ar;
481 T et = +e*ar+f*br+g*cr+h*dr;
482 T ft = -e*br+f*ar-g*dr+h*cr;
483 T gt = -e*cr+f*dr+g*ar-h*br;
484 T ht = -e*dr-f*cr+g*br+h*ar;
500 octonion<T> & operator *= (octonion<X> const & rhs)
502 T ar = static_cast<T>(rhs.R_component_1());
503 T br = static_cast<T>(rhs.R_component_2());
504 T cr = static_cast<T>(rhs.R_component_3());
505 T dr = static_cast<T>(rhs.R_component_4());
506 T er = static_cast<T>(rhs.R_component_5());
507 T fr = static_cast<T>(rhs.R_component_6());
508 T gr = static_cast<T>(rhs.R_component_7());
509 T hr = static_cast<T>(rhs.R_component_8());
511 T at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr;
512 T bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr;
513 T ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr;
514 T dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er;
515 T et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr;
516 T ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr;
517 T gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br;
518 T ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar;
533 octonion<T> & operator /= (T const & rhs)
535 T at = a / rhs; // exception guard
536 T bt = b / rhs; // exception guard
537 T ct = c / rhs; // exception guard
538 T dt = d / rhs; // exception guard
539 T et = e / rhs; // exception guard
540 T ft = f / rhs; // exception guard
541 T gt = g / rhs; // exception guard
542 T ht = h / rhs; // exception guard
557 octonion<T> & operator /= (::std::complex<T> const & rhs)
562 T denominator = ar*ar+br*br;
564 T at = (+a*ar-b*br)/denominator;
565 T bt = (-a*br+b*ar)/denominator;
566 T ct = (+c*ar-d*br)/denominator;
567 T dt = (+c*br+d*ar)/denominator;
568 T et = (+e*ar-f*br)/denominator;
569 T ft = (+e*br+f*ar)/denominator;
570 T gt = (+g*ar+h*br)/denominator;
571 T ht = (+g*br+h*ar)/denominator;
586 octonion<T> & operator /= (::boost::math::quaternion<T> const & rhs)
588 T ar = rhs.R_component_1();
589 T br = rhs.R_component_2();
590 T cr = rhs.R_component_2();
591 T dr = rhs.R_component_2();
593 T denominator = ar*ar+br*br+cr*cr+dr*dr;
595 T at = (+a*ar+b*br+c*cr+d*dr)/denominator;
596 T bt = (-a*br+b*ar-c*dr+d*cr)/denominator;
597 T ct = (-a*cr+b*dr+c*ar-d*br)/denominator;
598 T dt = (-a*dr-b*cr+c*br+d*ar)/denominator;
599 T et = (+e*ar-f*br-g*cr-h*dr)/denominator;
600 T ft = (+e*br+f*ar+g*dr-h*cr)/denominator;
601 T gt = (+e*cr-f*dr+g*ar+h*br)/denominator;
602 T ht = (+e*dr+f*cr-g*br+h*ar)/denominator;
618 octonion<T> & operator /= (octonion<X> const & rhs)
620 T ar = static_cast<T>(rhs.R_component_1());
621 T br = static_cast<T>(rhs.R_component_2());
622 T cr = static_cast<T>(rhs.R_component_3());
623 T dr = static_cast<T>(rhs.R_component_4());
624 T er = static_cast<T>(rhs.R_component_5());
625 T fr = static_cast<T>(rhs.R_component_6());
626 T gr = static_cast<T>(rhs.R_component_7());
627 T hr = static_cast<T>(rhs.R_component_8());
629 T denominator = ar*ar+br*br+cr*cr+dr*dr+er*er+fr*fr+gr*gr+hr*hr;
631 T at = (+a*ar+b*br+c*cr+d*dr+e*er+f*fr+g*gr+h*hr)/denominator;
632 T bt = (-a*br+b*ar-c*dr+d*cr-e*fr+f*er+g*hr-h*gr)/denominator;
633 T ct = (-a*cr+b*dr+c*ar-d*br-e*gr-f*hr+g*er+h*fr)/denominator;
634 T dt = (-a*dr-b*cr+c*br+d*ar-e*hr+f*gr-g*fr+h*er)/denominator;
635 T et = (-a*er+b*fr+c*gr+d*hr+e*ar-f*br-g*cr-h*dr)/denominator;
636 T ft = (-a*fr-b*er+c*hr-d*gr+e*br+f*ar+g*dr-h*cr)/denominator;
637 T gt = (-a*gr-b*hr-c*er+d*fr+e*cr-f*dr+g*ar+h*br)/denominator;
638 T ht = (-a*hr+b*gr-c*fr-d*er+e*dr+f*cr-g*br+h*ar)/denominator;
655 BOOST_OCTONION_MEMBER_DATA_GENERATOR(T)
663 // declaration of octonion specialization
665 template<> class octonion<float>;
666 template<> class octonion<double>;
667 template<> class octonion<long double>;
670 // helper templates for converting copy constructors (declaration)
675 template< typename T,
678 octonion<T> octonion_type_converter(octonion<U> const & rhs);
682 // implementation of octonion specialization
685 #define BOOST_OCTONION_CONSTRUCTOR_GENERATOR(type) \
686 explicit octonion( type const & requested_a = static_cast<type>(0), \
687 type const & requested_b = static_cast<type>(0), \
688 type const & requested_c = static_cast<type>(0), \
689 type const & requested_d = static_cast<type>(0), \
690 type const & requested_e = static_cast<type>(0), \
691 type const & requested_f = static_cast<type>(0), \
692 type const & requested_g = static_cast<type>(0), \
693 type const & requested_h = static_cast<type>(0)) \
705 explicit octonion( ::std::complex<type> const & z0, \
706 ::std::complex<type> const & z1 = ::std::complex<type>(), \
707 ::std::complex<type> const & z2 = ::std::complex<type>(), \
708 ::std::complex<type> const & z3 = ::std::complex<type>()) \
720 explicit octonion( ::boost::math::quaternion<type> const & q0, \
721 ::boost::math::quaternion<type> const & q1 = ::boost::math::quaternion<type>()) \
722 : a(q0.R_component_1()), \
723 b(q0.R_component_2()), \
724 c(q0.R_component_3()), \
725 d(q0.R_component_4()), \
726 e(q1.R_component_1()), \
727 f(q1.R_component_2()), \
728 g(q1.R_component_3()), \
729 h(q1.R_component_4()) \
734 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \
735 octonion<type> & operator += (type const & rhs) \
742 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \
743 octonion<type> & operator += (::std::complex<type> const & rhs) \
751 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \
752 octonion<type> & operator += (::boost::math::quaternion<type> const & rhs) \
754 a += rhs.R_component_1(); \
755 b += rhs.R_component_2(); \
756 c += rhs.R_component_3(); \
757 d += rhs.R_component_4(); \
762 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type) \
763 template<typename X> \
764 octonion<type> & operator += (octonion<X> const & rhs) \
766 a += static_cast<type>(rhs.R_component_1()); \
767 b += static_cast<type>(rhs.R_component_2()); \
768 c += static_cast<type>(rhs.R_component_3()); \
769 d += static_cast<type>(rhs.R_component_4()); \
770 e += static_cast<type>(rhs.R_component_5()); \
771 f += static_cast<type>(rhs.R_component_6()); \
772 g += static_cast<type>(rhs.R_component_7()); \
773 h += static_cast<type>(rhs.R_component_8()); \
778 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \
779 octonion<type> & operator -= (type const & rhs) \
786 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \
787 octonion<type> & operator -= (::std::complex<type> const & rhs) \
795 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \
796 octonion<type> & operator -= (::boost::math::quaternion<type> const & rhs) \
798 a -= rhs.R_component_1(); \
799 b -= rhs.R_component_2(); \
800 c -= rhs.R_component_3(); \
801 d -= rhs.R_component_4(); \
806 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type) \
807 template<typename X> \
808 octonion<type> & operator -= (octonion<X> const & rhs) \
810 a -= static_cast<type>(rhs.R_component_1()); \
811 b -= static_cast<type>(rhs.R_component_2()); \
812 c -= static_cast<type>(rhs.R_component_3()); \
813 d -= static_cast<type>(rhs.R_component_4()); \
814 e -= static_cast<type>(rhs.R_component_5()); \
815 f -= static_cast<type>(rhs.R_component_6()); \
816 g -= static_cast<type>(rhs.R_component_7()); \
817 h -= static_cast<type>(rhs.R_component_8()); \
822 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \
823 octonion<type> & operator *= (type const & rhs) \
837 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \
838 octonion<type> & operator *= (::std::complex<type> const & rhs) \
840 type ar = rhs.real(); \
841 type br = rhs.imag(); \
843 type at = +a*ar-b*br; \
844 type bt = +a*br+b*ar; \
845 type ct = +c*ar+d*br; \
846 type dt = -c*br+d*ar; \
847 type et = +e*ar+f*br; \
848 type ft = -e*br+f*ar; \
849 type gt = +g*ar-h*br; \
850 type ht = +g*br+h*ar; \
864 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \
865 octonion<type> & operator *= (::boost::math::quaternion<type> const & rhs) \
867 type ar = rhs.R_component_1(); \
868 type br = rhs.R_component_2(); \
869 type cr = rhs.R_component_2(); \
870 type dr = rhs.R_component_2(); \
872 type at = +a*ar-b*br-c*cr-d*dr; \
873 type bt = +a*br+b*ar+c*dr-d*cr; \
874 type ct = +a*cr-b*dr+c*ar+d*br; \
875 type dt = +a*dr+b*cr-c*br+d*ar; \
876 type et = +e*ar+f*br+g*cr+h*dr; \
877 type ft = -e*br+f*ar-g*dr+h*cr; \
878 type gt = -e*cr+f*dr+g*ar-h*br; \
879 type ht = -e*dr-f*cr+g*br+h*ar; \
893 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type) \
894 template<typename X> \
895 octonion<type> & operator *= (octonion<X> const & rhs) \
897 type ar = static_cast<type>(rhs.R_component_1()); \
898 type br = static_cast<type>(rhs.R_component_2()); \
899 type cr = static_cast<type>(rhs.R_component_3()); \
900 type dr = static_cast<type>(rhs.R_component_4()); \
901 type er = static_cast<type>(rhs.R_component_5()); \
902 type fr = static_cast<type>(rhs.R_component_6()); \
903 type gr = static_cast<type>(rhs.R_component_7()); \
904 type hr = static_cast<type>(rhs.R_component_8()); \
906 type at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr; \
907 type bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr; \
908 type ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr; \
909 type dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er; \
910 type et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr; \
911 type ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr; \
912 type gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br; \
913 type ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar; \
927 // There is quite a lot of repetition in the code below. This is intentional.
928 // The last conditional block is the normal form, and the others merely
929 // consist of workarounds for various compiler deficiencies. Hopefuly, when
930 // more compilers are conformant and we can retire support for those that are
931 // not, we will be able to remove the clutter. This is makes the situation
932 // (painfully) explicit.
934 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \
935 octonion<type> & operator /= (type const & rhs) \
945 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
946 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
947 octonion<type> & operator /= (::std::complex<type> const & rhs) \
949 using ::std::valarray; \
952 valarray<type> tr(2); \
954 tr[0] = rhs.real(); \
955 tr[1] = rhs.imag(); \
957 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
961 valarray<type> tt(8); \
963 tt[0] = +a*tr[0]-b*tr[1]; \
964 tt[1] = -a*tr[1]+b*tr[0]; \
965 tt[2] = +c*tr[0]-d*tr[1]; \
966 tt[3] = +c*tr[1]+d*tr[0]; \
967 tt[4] = +e*tr[0]-f*tr[1]; \
968 tt[5] = +e*tr[1]+f*tr[0]; \
969 tt[6] = +g*tr[0]+h*tr[1]; \
970 tt[7] = +g*tr[1]+h*tr[0]; \
974 tt *= (mixam/tr.sum()); \
988 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
989 octonion<type> & operator /= (::std::complex<type> const & rhs) \
991 using ::std::valarray; \
993 valarray<type> tr(2); \
995 tr[0] = rhs.real(); \
996 tr[1] = rhs.imag(); \
998 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1002 valarray<type> tt(8); \
1004 tt[0] = +a*tr[0]-b*tr[1]; \
1005 tt[1] = -a*tr[1]+b*tr[0]; \
1006 tt[2] = +c*tr[0]-d*tr[1]; \
1007 tt[3] = +c*tr[1]+d*tr[0]; \
1008 tt[4] = +e*tr[0]-f*tr[1]; \
1009 tt[5] = +e*tr[1]+f*tr[0]; \
1010 tt[6] = +g*tr[0]+h*tr[1]; \
1011 tt[7] = +g*tr[1]+h*tr[0]; \
1015 tt *= (mixam/tr.sum()); \
1028 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1030 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1031 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
1032 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \
1034 using ::std::valarray; \
1037 valarray<type> tr(4); \
1039 tr[0] = static_cast<type>(rhs.R_component_1()); \
1040 tr[1] = static_cast<type>(rhs.R_component_2()); \
1041 tr[2] = static_cast<type>(rhs.R_component_3()); \
1042 tr[3] = static_cast<type>(rhs.R_component_4()); \
1044 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1048 valarray<type> tt(8); \
1050 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
1051 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
1052 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
1053 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
1054 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
1055 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
1056 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
1057 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
1061 tt *= (mixam/tr.sum()); \
1075 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
1076 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \
1078 using ::std::valarray; \
1080 valarray<type> tr(4); \
1082 tr[0] = static_cast<type>(rhs.R_component_1()); \
1083 tr[1] = static_cast<type>(rhs.R_component_2()); \
1084 tr[2] = static_cast<type>(rhs.R_component_3()); \
1085 tr[3] = static_cast<type>(rhs.R_component_4()); \
1087 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1091 valarray<type> tt(8); \
1093 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
1094 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
1095 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
1096 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
1097 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
1098 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
1099 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
1100 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
1104 tt *= (mixam/tr.sum()); \
1117 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1119 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1120 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \
1121 template<typename X> \
1122 octonion<type> & operator /= (octonion<X> const & rhs) \
1124 using ::std::valarray; \
1127 valarray<type> tr(8); \
1129 tr[0] = static_cast<type>(rhs.R_component_1()); \
1130 tr[1] = static_cast<type>(rhs.R_component_2()); \
1131 tr[2] = static_cast<type>(rhs.R_component_3()); \
1132 tr[3] = static_cast<type>(rhs.R_component_4()); \
1133 tr[4] = static_cast<type>(rhs.R_component_5()); \
1134 tr[5] = static_cast<type>(rhs.R_component_6()); \
1135 tr[6] = static_cast<type>(rhs.R_component_7()); \
1136 tr[7] = static_cast<type>(rhs.R_component_8()); \
1138 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1142 valarray<type> tt(8); \
1144 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]+e*tr[4]+f*tr[5]+g*tr[6]+h*tr[7]; \
1145 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]-e*tr[5]+f*tr[4]+g*tr[7]-h*tr[6]; \
1146 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]-e*tr[6]-f*tr[7]+g*tr[4]+h*tr[5]; \
1147 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]-e*tr[7]+f*tr[6]-g*tr[5]+h*tr[4]; \
1148 tt[4] = -a*tr[4]+b*tr[5]+c*tr[6]+d*tr[7]+e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
1149 tt[5] = -a*tr[5]-b*tr[4]+c*tr[7]-d*tr[6]+e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
1150 tt[6] = -a*tr[6]-b*tr[7]-c*tr[4]+d*tr[5]+e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
1151 tt[7] = -a*tr[7]+b*tr[6]-c*tr[5]-d*tr[4]+e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
1155 tt *= (mixam/tr.sum()); \
1169 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \
1170 template<typename X> \
1171 octonion<type> & operator /= (octonion<X> const & rhs) \
1173 using ::std::valarray; \
1175 valarray<type> tr(8); \
1177 tr[0] = static_cast<type>(rhs.R_component_1()); \
1178 tr[1] = static_cast<type>(rhs.R_component_2()); \
1179 tr[2] = static_cast<type>(rhs.R_component_3()); \
1180 tr[3] = static_cast<type>(rhs.R_component_4()); \
1181 tr[4] = static_cast<type>(rhs.R_component_5()); \
1182 tr[5] = static_cast<type>(rhs.R_component_6()); \
1183 tr[6] = static_cast<type>(rhs.R_component_7()); \
1184 tr[7] = static_cast<type>(rhs.R_component_8()); \
1186 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1190 valarray<type> tt(8); \
1192 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]+e*tr[4]+f*tr[5]+g*tr[6]+h*tr[7]; \
1193 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]-e*tr[5]+f*tr[4]+g*tr[7]-h*tr[6]; \
1194 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]-e*tr[6]-f*tr[7]+g*tr[4]+h*tr[5]; \
1195 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]-e*tr[7]+f*tr[6]-g*tr[5]+h*tr[4]; \
1196 tt[4] = -a*tr[4]+b*tr[5]+c*tr[6]+d*tr[7]+e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
1197 tt[5] = -a*tr[5]-b*tr[4]+c*tr[7]-d*tr[6]+e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
1198 tt[6] = -a*tr[6]-b*tr[7]-c*tr[4]+d*tr[5]+e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
1199 tt[7] = -a*tr[7]+b*tr[6]-c*tr[5]-d*tr[4]+e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
1203 tt *= (mixam/tr.sum()); \
1216 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1219 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \
1220 BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \
1221 BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \
1222 BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \
1223 BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type)
1225 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \
1226 BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \
1227 BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \
1228 BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \
1229 BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type)
1231 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \
1232 BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \
1233 BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \
1234 BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \
1235 BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type)
1237 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR(type) \
1238 BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \
1239 BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
1240 BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
1241 BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type)
1243 #define BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(type) \
1244 BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \
1245 BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \
1246 BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \
1247 BOOST_OCTONION_MEMBER_DIV_GENERATOR(type)
1251 class octonion<float>
1255 typedef float value_type;
1257 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(float)
1259 // UNtemplated copy constructor
1260 // (this is taken care of by the compiler itself)
1262 // explicit copy constructors (precision-loosing converters)
1264 explicit octonion(octonion<double> const & a_recopier)
1266 *this = detail::octonion_type_converter<float, double>(a_recopier);
1269 explicit octonion(octonion<long double> const & a_recopier)
1271 *this = detail::octonion_type_converter<float, long double>(a_recopier);
1275 // (this is taken care of by the compiler itself)
1279 // Note: Like complex number, octonions do have a meaningful notion of "real part",
1280 // but unlike them there is no meaningful notion of "imaginary part".
1281 // Instead there is an "unreal part" which itself is an octonion, and usually
1282 // nothing simpler (as opposed to the complex number case).
1283 // However, for practicallity, there are accessors for the other components
1284 // (these are necessary for the templated copy constructor, for instance).
1286 BOOST_OCTONION_ACCESSOR_GENERATOR(float)
1288 // assignment operators
1290 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(float)
1292 // other assignment-related operators
1294 // NOTE: Octonion multiplication is *NOT* commutative;
1295 // symbolically, "q *= rhs;" means "q = q * rhs;"
1296 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
1297 // octonion multiplication is also *NOT* associative
1299 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(float)
1304 BOOST_OCTONION_MEMBER_DATA_GENERATOR(float)
1313 class octonion<double>
1317 typedef double value_type;
1319 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(double)
1321 // UNtemplated copy constructor
1322 // (this is taken care of by the compiler itself)
1324 // converting copy constructor
1326 explicit octonion(octonion<float> const & a_recopier)
1328 *this = detail::octonion_type_converter<double, float>(a_recopier);
1331 // explicit copy constructors (precision-loosing converters)
1333 explicit octonion(octonion<long double> const & a_recopier)
1335 *this = detail::octonion_type_converter<double, long double>(a_recopier);
1339 // (this is taken care of by the compiler itself)
1343 // Note: Like complex number, octonions do have a meaningful notion of "real part",
1344 // but unlike them there is no meaningful notion of "imaginary part".
1345 // Instead there is an "unreal part" which itself is an octonion, and usually
1346 // nothing simpler (as opposed to the complex number case).
1347 // However, for practicallity, there are accessors for the other components
1348 // (these are necessary for the templated copy constructor, for instance).
1350 BOOST_OCTONION_ACCESSOR_GENERATOR(double)
1352 // assignment operators
1354 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(double)
1356 // other assignment-related operators
1358 // NOTE: Octonion multiplication is *NOT* commutative;
1359 // symbolically, "q *= rhs;" means "q = q * rhs;"
1360 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
1361 // octonion multiplication is also *NOT* associative
1363 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(double)
1368 BOOST_OCTONION_MEMBER_DATA_GENERATOR(double)
1377 class octonion<long double>
1381 typedef long double value_type;
1383 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(long double)
1385 // UNtemplated copy constructor
1386 // (this is taken care of by the compiler itself)
1388 // converting copy constructor
1390 explicit octonion(octonion<float> const & a_recopier)
1392 *this = detail::octonion_type_converter<long double, float>(a_recopier);
1396 explicit octonion(octonion<double> const & a_recopier)
1398 *this = detail::octonion_type_converter<long double, double>(a_recopier);
1403 // (this is taken care of by the compiler itself)
1407 // Note: Like complex number, octonions do have a meaningful notion of "real part",
1408 // but unlike them there is no meaningful notion of "imaginary part".
1409 // Instead there is an "unreal part" which itself is an octonion, and usually
1410 // nothing simpler (as opposed to the complex number case).
1411 // However, for practicallity, there are accessors for the other components
1412 // (these are necessary for the templated copy constructor, for instance).
1414 BOOST_OCTONION_ACCESSOR_GENERATOR(long double)
1416 // assignment operators
1418 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(long double)
1420 // other assignment-related operators
1422 // NOTE: Octonion multiplication is *NOT* commutative;
1423 // symbolically, "q *= rhs;" means "q = q * rhs;"
1424 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
1425 // octonion multiplication is also *NOT* associative
1427 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(long double)
1432 BOOST_OCTONION_MEMBER_DATA_GENERATOR(long double)
1440 #undef BOOST_OCTONION_CONSTRUCTOR_GENERATOR
1442 #undef BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR
1444 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR
1445 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR
1446 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR
1447 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR
1449 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_1
1450 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_2
1451 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_3
1452 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_4
1453 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_1
1454 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_2
1455 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_3
1456 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_4
1457 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_1
1458 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_2
1459 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_3
1460 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_4
1461 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_1
1462 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_2
1463 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_3
1464 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_4
1467 #undef BOOST_OCTONION_MEMBER_DATA_GENERATOR
1469 #undef BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR
1471 #undef BOOST_OCTONION_ACCESSOR_GENERATOR
1476 #define BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) \
1478 octonion<T> res(lhs); \
1483 #define BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \
1484 template<typename T> \
1485 inline octonion<T> operator op (T const & lhs, octonion<T> const & rhs) \
1486 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1488 #define BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \
1489 template<typename T> \
1490 inline octonion<T> operator op (octonion<T> const & lhs, T const & rhs) \
1491 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1493 #define BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \
1494 template<typename T> \
1495 inline octonion<T> operator op (::std::complex<T> const & lhs, octonion<T> const & rhs) \
1496 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1498 #define BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \
1499 template<typename T> \
1500 inline octonion<T> operator op (octonion<T> const & lhs, ::std::complex<T> const & rhs) \
1501 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1503 #define BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \
1504 template<typename T> \
1505 inline octonion<T> operator op (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs) \
1506 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1508 #define BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \
1509 template<typename T> \
1510 inline octonion<T> operator op (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs) \
1511 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1513 #define BOOST_OCTONION_OPERATOR_GENERATOR_4(op) \
1514 template<typename T> \
1515 inline octonion<T> operator op (octonion<T> const & lhs, octonion<T> const & rhs) \
1516 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1518 #define BOOST_OCTONION_OPERATOR_GENERATOR(op) \
1519 BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \
1520 BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \
1521 BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \
1522 BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \
1523 BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \
1524 BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \
1525 BOOST_OCTONION_OPERATOR_GENERATOR_4(op)
1528 BOOST_OCTONION_OPERATOR_GENERATOR(+)
1529 BOOST_OCTONION_OPERATOR_GENERATOR(-)
1530 BOOST_OCTONION_OPERATOR_GENERATOR(*)
1531 BOOST_OCTONION_OPERATOR_GENERATOR(/)
1534 #undef BOOST_OCTONION_OPERATOR_GENERATOR
1536 #undef BOOST_OCTONION_OPERATOR_GENERATOR_1_L
1537 #undef BOOST_OCTONION_OPERATOR_GENERATOR_1_R
1538 #undef BOOST_OCTONION_OPERATOR_GENERATOR_2_L
1539 #undef BOOST_OCTONION_OPERATOR_GENERATOR_2_R
1540 #undef BOOST_OCTONION_OPERATOR_GENERATOR_3_L
1541 #undef BOOST_OCTONION_OPERATOR_GENERATOR_3_R
1542 #undef BOOST_OCTONION_OPERATOR_GENERATOR_4
1544 #undef BOOST_OCTONION_OPERATOR_GENERATOR_BODY
1547 template<typename T>
1548 inline octonion<T> operator + (octonion<T> const & o)
1554 template<typename T>
1555 inline octonion<T> operator - (octonion<T> const & o)
1557 return(octonion<T>(-o.R_component_1(),-o.R_component_2(),-o.R_component_3(),-o.R_component_4(),-o.R_component_5(),-o.R_component_6(),-o.R_component_7(),-o.R_component_8()));
1561 template<typename T>
1562 inline bool operator == (T const & lhs, octonion<T> const & rhs)
1565 (rhs.R_component_1() == lhs)&&
1566 (rhs.R_component_2() == static_cast<T>(0))&&
1567 (rhs.R_component_3() == static_cast<T>(0))&&
1568 (rhs.R_component_4() == static_cast<T>(0))&&
1569 (rhs.R_component_5() == static_cast<T>(0))&&
1570 (rhs.R_component_6() == static_cast<T>(0))&&
1571 (rhs.R_component_7() == static_cast<T>(0))&&
1572 (rhs.R_component_8() == static_cast<T>(0))
1577 template<typename T>
1578 inline bool operator == (octonion<T> const & lhs, T const & rhs)
1581 (lhs.R_component_1() == rhs)&&
1582 (lhs.R_component_2() == static_cast<T>(0))&&
1583 (lhs.R_component_3() == static_cast<T>(0))&&
1584 (lhs.R_component_4() == static_cast<T>(0))&&
1585 (lhs.R_component_5() == static_cast<T>(0))&&
1586 (lhs.R_component_6() == static_cast<T>(0))&&
1587 (lhs.R_component_7() == static_cast<T>(0))&&
1588 (lhs.R_component_8() == static_cast<T>(0))
1593 template<typename T>
1594 inline bool operator == (::std::complex<T> const & lhs, octonion<T> const & rhs)
1597 (rhs.R_component_1() == lhs.real())&&
1598 (rhs.R_component_2() == lhs.imag())&&
1599 (rhs.R_component_3() == static_cast<T>(0))&&
1600 (rhs.R_component_4() == static_cast<T>(0))&&
1601 (rhs.R_component_5() == static_cast<T>(0))&&
1602 (rhs.R_component_6() == static_cast<T>(0))&&
1603 (rhs.R_component_7() == static_cast<T>(0))&&
1604 (rhs.R_component_8() == static_cast<T>(0))
1609 template<typename T>
1610 inline bool operator == (octonion<T> const & lhs, ::std::complex<T> const & rhs)
1613 (lhs.R_component_1() == rhs.real())&&
1614 (lhs.R_component_2() == rhs.imag())&&
1615 (lhs.R_component_3() == static_cast<T>(0))&&
1616 (lhs.R_component_4() == static_cast<T>(0))&&
1617 (lhs.R_component_5() == static_cast<T>(0))&&
1618 (lhs.R_component_6() == static_cast<T>(0))&&
1619 (lhs.R_component_7() == static_cast<T>(0))&&
1620 (lhs.R_component_8() == static_cast<T>(0))
1625 template<typename T>
1626 inline bool operator == (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)
1629 (rhs.R_component_1() == lhs.R_component_1())&&
1630 (rhs.R_component_2() == lhs.R_component_2())&&
1631 (rhs.R_component_3() == lhs.R_component_3())&&
1632 (rhs.R_component_4() == lhs.R_component_4())&&
1633 (rhs.R_component_5() == static_cast<T>(0))&&
1634 (rhs.R_component_6() == static_cast<T>(0))&&
1635 (rhs.R_component_7() == static_cast<T>(0))&&
1636 (rhs.R_component_8() == static_cast<T>(0))
1641 template<typename T>
1642 inline bool operator == (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)
1645 (lhs.R_component_1() == rhs.R_component_1())&&
1646 (lhs.R_component_2() == rhs.R_component_2())&&
1647 (lhs.R_component_3() == rhs.R_component_3())&&
1648 (lhs.R_component_4() == rhs.R_component_4())&&
1649 (lhs.R_component_5() == static_cast<T>(0))&&
1650 (lhs.R_component_6() == static_cast<T>(0))&&
1651 (lhs.R_component_7() == static_cast<T>(0))&&
1652 (lhs.R_component_8() == static_cast<T>(0))
1657 template<typename T>
1658 inline bool operator == (octonion<T> const & lhs, octonion<T> const & rhs)
1661 (rhs.R_component_1() == lhs.R_component_1())&&
1662 (rhs.R_component_2() == lhs.R_component_2())&&
1663 (rhs.R_component_3() == lhs.R_component_3())&&
1664 (rhs.R_component_4() == lhs.R_component_4())&&
1665 (rhs.R_component_5() == lhs.R_component_5())&&
1666 (rhs.R_component_6() == lhs.R_component_6())&&
1667 (rhs.R_component_7() == lhs.R_component_7())&&
1668 (rhs.R_component_8() == lhs.R_component_8())
1673 #define BOOST_OCTONION_NOT_EQUAL_GENERATOR \
1675 return(!(lhs == rhs)); \
1678 template<typename T>
1679 inline bool operator != (T const & lhs, octonion<T> const & rhs)
1680 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1682 template<typename T>
1683 inline bool operator != (octonion<T> const & lhs, T const & rhs)
1684 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1686 template<typename T>
1687 inline bool operator != (::std::complex<T> const & lhs, octonion<T> const & rhs)
1688 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1690 template<typename T>
1691 inline bool operator != (octonion<T> const & lhs, ::std::complex<T> const & rhs)
1692 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1694 template<typename T>
1695 inline bool operator != (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)
1696 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1698 template<typename T>
1699 inline bool operator != (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)
1700 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1702 template<typename T>
1703 inline bool operator != (octonion<T> const & lhs, octonion<T> const & rhs)
1704 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1706 #undef BOOST_OCTONION_NOT_EQUAL_GENERATOR
1709 // Note: the default values in the constructors of the complex and quaternions make for
1710 // a very complex and ambiguous situation; we have made choices to disambiguate.
1711 template<typename T, typename charT, class traits>
1712 ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
1715 #ifdef BOOST_NO_STD_LOCALE
1717 const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
1718 #endif /* BOOST_NO_STD_LOCALE */
1729 ::std::complex<T> u = ::std::complex<T>();
1730 ::std::complex<T> v = ::std::complex<T>();
1731 ::std::complex<T> x = ::std::complex<T>();
1732 ::std::complex<T> y = ::std::complex<T>();
1734 ::boost::math::quaternion<T> p = ::boost::math::quaternion<T>();
1735 ::boost::math::quaternion<T> q = ::boost::math::quaternion<T>();
1740 is >> ch; // get the first lexeme
1742 if (!is.good()) goto finish;
1744 #ifdef BOOST_NO_STD_LOCALE
1747 cc = ct.narrow(ch, char());
1748 #endif /* BOOST_NO_STD_LOCALE */
1750 if (cc == '(') // read "("
1752 is >> ch; // get the second lexeme
1754 if (!is.good()) goto finish;
1756 #ifdef BOOST_NO_STD_LOCALE
1759 cc = ct.narrow(ch, char());
1760 #endif /* BOOST_NO_STD_LOCALE */
1762 if (cc == '(') // read "(("
1764 is >> ch; // get the third lexeme
1766 if (!is.good()) goto finish;
1768 #ifdef BOOST_NO_STD_LOCALE
1771 cc = ct.narrow(ch, char());
1772 #endif /* BOOST_NO_STD_LOCALE */
1774 if (cc == '(') // read "((("
1778 is >> u; // read "((u"
1780 if (!is.good()) goto finish;
1782 is >> ch; // get the next lexeme
1784 if (!is.good()) goto finish;
1786 #ifdef BOOST_NO_STD_LOCALE
1789 cc = ct.narrow(ch, char());
1790 #endif /* BOOST_NO_STD_LOCALE */
1792 if (cc == ')') // read "((u)"
1794 is >> ch; // get the next lexeme
1796 if (!is.good()) goto finish;
1798 #ifdef BOOST_NO_STD_LOCALE
1801 cc = ct.narrow(ch, char());
1802 #endif /* BOOST_NO_STD_LOCALE */
1804 if (cc == ')') // format: (((a))), (((a,b)))
1808 else if (cc == ',') // read "((u),"
1810 p = ::boost::math::quaternion<T>(u);
1812 is >> q; // read "((u),q"
1814 if (!is.good()) goto finish;
1816 is >> ch; // get the next lexeme
1818 if (!is.good()) goto finish;
1820 #ifdef BOOST_NO_STD_LOCALE
1823 cc = ct.narrow(ch, char());
1824 #endif /* BOOST_NO_STD_LOCALE */
1826 if (cc == ')') // format: (((a)),q), (((a,b)),q)
1828 o = octonion<T>(p,q);
1832 is.setstate(::std::ios_base::failbit);
1837 is.setstate(::std::ios_base::failbit);
1840 else if (cc ==',') // read "((u,"
1842 is >> v; // read "((u,v"
1844 if (!is.good()) goto finish;
1846 is >> ch; // get the next lexeme
1848 if (!is.good()) goto finish;
1850 #ifdef BOOST_NO_STD_LOCALE
1853 cc = ct.narrow(ch, char());
1854 #endif /* BOOST_NO_STD_LOCALE */
1856 if (cc == ')') // read "((u,v)"
1858 p = ::boost::math::quaternion<T>(u,v);
1860 is >> ch; // get the next lexeme
1862 if (!is.good()) goto finish;
1864 #ifdef BOOST_NO_STD_LOCALE
1867 cc = ct.narrow(ch, char());
1868 #endif /* BOOST_NO_STD_LOCALE */
1870 if (cc == ')') // format: (((a),v)), (((a,b),v))
1874 else if (cc == ',') // read "((u,v),"
1876 is >> q; // read "(p,q"
1878 if (!is.good()) goto finish;
1880 is >> ch; // get the next lexeme
1882 if (!is.good()) goto finish;
1884 #ifdef BOOST_NO_STD_LOCALE
1887 cc = ct.narrow(ch, char());
1888 #endif /* BOOST_NO_STD_LOCALE */
1890 if (cc == ')') // format: (((a),v),q), (((a,b),v),q)
1892 o = octonion<T>(p,q);
1896 is.setstate(::std::ios_base::failbit);
1901 is.setstate(::std::ios_base::failbit);
1906 is.setstate(::std::ios_base::failbit);
1911 is.setstate(::std::ios_base::failbit);
1918 is >> a; // we extract the first component
1920 if (!is.good()) goto finish;
1922 is >> ch; // get the next lexeme
1924 if (!is.good()) goto finish;
1926 #ifdef BOOST_NO_STD_LOCALE
1929 cc = ct.narrow(ch, char());
1930 #endif /* BOOST_NO_STD_LOCALE */
1932 if (cc == ')') // read "((a)"
1934 is >> ch; // get the next lexeme
1936 if (!is.good()) goto finish;
1938 #ifdef BOOST_NO_STD_LOCALE
1941 cc = ct.narrow(ch, char());
1942 #endif /* BOOST_NO_STD_LOCALE */
1944 if (cc == ')') // read "((a))"
1948 else if (cc == ',') // read "((a),"
1950 is >> ch; // get the next lexeme
1952 if (!is.good()) goto finish;
1954 #ifdef BOOST_NO_STD_LOCALE
1957 cc = ct.narrow(ch, char());
1958 #endif /* BOOST_NO_STD_LOCALE */
1960 if (cc == '(') // read "((a),("
1962 is >> ch; // get the next lexeme
1964 if (!is.good()) goto finish;
1966 #ifdef BOOST_NO_STD_LOCALE
1969 cc = ct.narrow(ch, char());
1970 #endif /* BOOST_NO_STD_LOCALE */
1972 if (cc == '(') // read "((a),(("
1976 is.putback(ch); // we backtrack twice, with the same value!
1978 is >> q; // read "((a),q"
1980 if (!is.good()) goto finish;
1982 is >> ch; // get the next lexeme
1984 if (!is.good()) goto finish;
1986 #ifdef BOOST_NO_STD_LOCALE
1989 cc = ct.narrow(ch, char());
1990 #endif /* BOOST_NO_STD_LOCALE */
1992 if (cc == ')') // read "((a),q)"
1994 p = ::boost::math::quaternion<T>(a);
1996 o = octonion<T>(p,q);
2000 is.setstate(::std::ios_base::failbit);
2003 else // read "((a),(c" or "((a),(e"
2009 if (!is.good()) goto finish;
2011 is >> ch; // get the next lexeme
2013 if (!is.good()) goto finish;
2015 #ifdef BOOST_NO_STD_LOCALE
2018 cc = ct.narrow(ch, char());
2019 #endif /* BOOST_NO_STD_LOCALE */
2021 if (cc == ')') // read "((a),(c)" (ambiguity resolution)
2023 is >> ch; // get the next lexeme
2025 if (!is.good()) goto finish;
2027 #ifdef BOOST_NO_STD_LOCALE
2030 cc = ct.narrow(ch, char());
2031 #endif /* BOOST_NO_STD_LOCALE */
2033 if (cc == ')') // read "((a),(c))"
2035 o = octonion<T>(a,b,c);
2037 else if (cc == ',') // read "((a),(c),"
2039 u = ::std::complex<T>(a);
2041 v = ::std::complex<T>(c);
2043 is >> x; // read "((a),(c),x"
2045 if (!is.good()) goto finish;
2047 is >> ch; // get the next lexeme
2049 if (!is.good()) goto finish;
2051 #ifdef BOOST_NO_STD_LOCALE
2054 cc = ct.narrow(ch, char());
2055 #endif /* BOOST_NO_STD_LOCALE */
2057 if (cc == ')') // read "((a),(c),x)"
2059 o = octonion<T>(u,v,x);
2061 else if (cc == ',') // read "((a),(c),x,"
2063 is >> y; // read "((a),(c),x,y"
2065 if (!is.good()) goto finish;
2067 is >> ch; // get the next lexeme
2069 if (!is.good()) goto finish;
2071 #ifdef BOOST_NO_STD_LOCALE
2074 cc = ct.narrow(ch, char());
2075 #endif /* BOOST_NO_STD_LOCALE */
2077 if (cc == ')') // read "((a),(c),x,y)"
2079 o = octonion<T>(u,v,x,y);
2083 is.setstate(::std::ios_base::failbit);
2088 is.setstate(::std::ios_base::failbit);
2093 is.setstate(::std::ios_base::failbit);
2096 else if (cc == ',') // read "((a),(c," or "((a),(e,"
2098 is >> ch; // get the next lexeme
2100 if (!is.good()) goto finish;
2102 #ifdef BOOST_NO_STD_LOCALE
2105 cc = ct.narrow(ch, char());
2106 #endif /* BOOST_NO_STD_LOCALE */
2108 if (cc == '(') // read "((a),(e,(" (ambiguity resolution)
2110 p = ::boost::math::quaternion<T>(a);
2112 x = ::std::complex<T>(c); // "c" was actually "e"
2114 is.putback(ch); // we can only backtrace once
2116 is >> y; // read "((a),(e,y"
2118 if (!is.good()) goto finish;
2120 is >> ch; // get the next lexeme
2122 #ifdef BOOST_NO_STD_LOCALE
2125 cc = ct.narrow(ch, char());
2126 #endif /* BOOST_NO_STD_LOCALE */
2128 if (cc == ')') // read "((a),(e,y)"
2130 q = ::boost::math::quaternion<T>(x,y);
2132 is >> ch; // get the next lexeme
2134 #ifdef BOOST_NO_STD_LOCALE
2137 cc = ct.narrow(ch, char());
2138 #endif /* BOOST_NO_STD_LOCALE */
2140 if (cc == ')') // read "((a),(e,y))"
2142 o = octonion<T>(p,q);
2146 is.setstate(::std::ios_base::failbit);
2151 is.setstate(::std::ios_base::failbit);
2154 else // read "((a),(c,d" or "((a),(e,f"
2160 if (!is.good()) goto finish;
2162 is >> ch; // get the next lexeme
2164 if (!is.good()) goto finish;
2166 #ifdef BOOST_NO_STD_LOCALE
2169 cc = ct.narrow(ch, char());
2170 #endif /* BOOST_NO_STD_LOCALE */
2172 if (cc == ')') // read "((a),(c,d)" (ambiguity resolution)
2174 is >> ch; // get the next lexeme
2176 if (!is.good()) goto finish;
2178 #ifdef BOOST_NO_STD_LOCALE
2181 cc = ct.narrow(ch, char());
2182 #endif /* BOOST_NO_STD_LOCALE */
2184 if (cc == ')') // read "((a),(c,d))"
2186 o = octonion<T>(a,b,c,d);
2188 else if (cc == ',') // read "((a),(c,d),"
2190 u = ::std::complex<T>(a);
2192 v = ::std::complex<T>(c,d);
2194 is >> x; // read "((a),(c,d),x"
2196 if (!is.good()) goto finish;
2198 is >> ch; // get the next lexeme
2200 if (!is.good()) goto finish;
2202 #ifdef BOOST_NO_STD_LOCALE
2205 cc = ct.narrow(ch, char());
2206 #endif /* BOOST_NO_STD_LOCALE */
2208 if (cc == ')') // read "((a),(c,d),x)"
2210 o = octonion<T>(u,v,x);
2212 else if (cc == ',') // read "((a),(c,d),x,"
2214 is >> y; // read "((a),(c,d),x,y"
2216 if (!is.good()) goto finish;
2218 is >> ch; // get the next lexeme
2220 if (!is.good()) goto finish;
2222 #ifdef BOOST_NO_STD_LOCALE
2225 cc = ct.narrow(ch, char());
2226 #endif /* BOOST_NO_STD_LOCALE */
2228 if (cc == ')') // read "((a),(c,d),x,y)"
2230 o = octonion<T>(u,v,x,y);
2234 is.setstate(::std::ios_base::failbit);
2239 is.setstate(::std::ios_base::failbit);
2244 is.setstate(::std::ios_base::failbit);
2247 else if (cc == ',') // read "((a),(e,f," (ambiguity resolution)
2249 p = ::boost::math::quaternion<T>(a);
2251 is >> g; // read "((a),(e,f,g" (too late to backtrack)
2253 if (!is.good()) goto finish;
2255 is >> ch; // get the next lexeme
2257 if (!is.good()) goto finish;
2259 #ifdef BOOST_NO_STD_LOCALE
2262 cc = ct.narrow(ch, char());
2263 #endif /* BOOST_NO_STD_LOCALE */
2265 if (cc == ')') // read "((a),(e,f,g)"
2267 q = ::boost::math::quaternion<T>(c,d,g); // "c" was actually "e", and "d" was actually "f"
2269 is >> ch; // get the next lexeme
2271 if (!is.good()) goto finish;
2273 #ifdef BOOST_NO_STD_LOCALE
2276 cc = ct.narrow(ch, char());
2277 #endif /* BOOST_NO_STD_LOCALE */
2279 if (cc == ')') // read "((a),(e,f,g))"
2281 o = octonion<T>(p,q);
2285 is.setstate(::std::ios_base::failbit);
2288 else if (cc == ',') // read "((a),(e,f,g,"
2290 is >> h; // read "((a),(e,f,g,h"
2292 if (!is.good()) goto finish;
2294 is >> ch; // get the next lexeme
2296 if (!is.good()) goto finish;
2298 #ifdef BOOST_NO_STD_LOCALE
2301 cc = ct.narrow(ch, char());
2302 #endif /* BOOST_NO_STD_LOCALE */
2304 if (cc == ')') // read "((a),(e,f,g,h)"
2306 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" was actually "e", and "d" was actually "f"
2308 is >> ch; // get the next lexeme
2310 if (!is.good()) goto finish;
2312 #ifdef BOOST_NO_STD_LOCALE
2315 cc = ct.narrow(ch, char());
2316 #endif /* BOOST_NO_STD_LOCALE */
2318 if (cc == ')') // read "((a),(e,f,g,h))"
2320 o = octonion<T>(p,q);
2324 is.setstate(::std::ios_base::failbit);
2329 is.setstate(::std::ios_base::failbit);
2334 is.setstate(::std::ios_base::failbit);
2339 is.setstate(::std::ios_base::failbit);
2345 is.setstate(::std::ios_base::failbit);
2349 else // read "((a),c" (ambiguity resolution)
2353 is >> c; // we extract the third component
2355 if (!is.good()) goto finish;
2357 is >> ch; // get the next lexeme
2359 if (!is.good()) goto finish;
2361 #ifdef BOOST_NO_STD_LOCALE
2364 cc = ct.narrow(ch, char());
2365 #endif /* BOOST_NO_STD_LOCALE */
2367 if (cc == ')') // read "((a),c)"
2369 o = octonion<T>(a,b,c);
2371 else if (cc == ',') // read "((a),c,"
2373 is >> x; // read "((a),c,x"
2375 if (!is.good()) goto finish;
2377 is >> ch; // get the next lexeme
2379 if (!is.good()) goto finish;
2381 #ifdef BOOST_NO_STD_LOCALE
2384 cc = ct.narrow(ch, char());
2385 #endif /* BOOST_NO_STD_LOCALE */
2387 if (cc == ')') // read "((a),c,x)"
2389 o = octonion<T>(a,b,c,d,x.real(),x.imag());
2391 else if (cc == ',') // read "((a),c,x,"
2393 is >> y;if (!is.good()) goto finish; // read "((a),c,x,y"
2395 is >> ch; // get the next lexeme
2397 if (!is.good()) goto finish;
2399 #ifdef BOOST_NO_STD_LOCALE
2402 cc = ct.narrow(ch, char());
2403 #endif /* BOOST_NO_STD_LOCALE */
2405 if (cc == ')') // read "((a),c,x,y)"
2407 o = octonion<T>(a,b,c,d,x.real(),x.imag(),y.real(),y.imag());
2411 is.setstate(::std::ios_base::failbit);
2416 is.setstate(::std::ios_base::failbit);
2421 is.setstate(::std::ios_base::failbit);
2427 is.setstate(::std::ios_base::failbit);
2430 else if (cc ==',') // read "((a,"
2432 is >> ch; // get the next lexeme
2434 if (!is.good()) goto finish;
2436 #ifdef BOOST_NO_STD_LOCALE
2439 cc = ct.narrow(ch, char());
2440 #endif /* BOOST_NO_STD_LOCALE */
2442 if (cc == '(') // read "((a,("
2444 u = ::std::complex<T>(a);
2446 is.putback(ch); // can only backtrack so much
2448 is >> v; // read "((a,v"
2450 if (!is.good()) goto finish;
2452 is >> ch; // get the next lexeme
2454 if (!is.good()) goto finish;
2456 #ifdef BOOST_NO_STD_LOCALE
2459 cc = ct.narrow(ch, char());
2460 #endif /* BOOST_NO_STD_LOCALE */
2462 if (cc == ')') // read "((a,v)"
2464 is >> ch; // get the next lexeme
2466 if (!is.good()) goto finish;
2468 #ifdef BOOST_NO_STD_LOCALE
2471 cc = ct.narrow(ch, char());
2472 #endif /* BOOST_NO_STD_LOCALE */
2474 if (cc == ')') // read "((a,v))"
2476 o = octonion<T>(u,v);
2478 else if (cc == ',') // read "((a,v),"
2480 p = ::boost::math::quaternion<T>(u,v);
2482 is >> q; // read "((a,v),q"
2484 if (!is.good()) goto finish;
2486 is >> ch; // get the next lexeme
2488 if (!is.good()) goto finish;
2490 #ifdef BOOST_NO_STD_LOCALE
2493 cc = ct.narrow(ch, char());
2494 #endif /* BOOST_NO_STD_LOCALE */
2496 if (cc == ')') // read "((a,v),q)"
2498 o = octonion<T>(p,q);
2502 is.setstate(::std::ios_base::failbit);
2507 is.setstate(::std::ios_base::failbit);
2512 is.setstate(::std::ios_base::failbit);
2519 is >> b; // read "((a,b"
2521 if (!is.good()) goto finish;
2523 is >> ch; // get the next lexeme
2525 if (!is.good()) goto finish;
2527 #ifdef BOOST_NO_STD_LOCALE
2530 cc = ct.narrow(ch, char());
2531 #endif /* BOOST_NO_STD_LOCALE */
2533 if (cc == ')') // read "((a,b)"
2535 is >> ch; // get the next lexeme
2537 if (!is.good()) goto finish;
2539 #ifdef BOOST_NO_STD_LOCALE
2542 cc = ct.narrow(ch, char());
2543 #endif /* BOOST_NO_STD_LOCALE */
2545 if (cc == ')') // read "((a,b))"
2547 o = octonion<T>(a,b);
2549 else if (cc == ',') // read "((a,b),"
2551 is >> ch; // get the next lexeme
2553 if (!is.good()) goto finish;
2555 #ifdef BOOST_NO_STD_LOCALE
2558 cc = ct.narrow(ch, char());
2559 #endif /* BOOST_NO_STD_LOCALE */
2561 if (cc == '(') // read "((a,b),("
2563 is >> ch; // get the next lexeme
2565 if (!is.good()) goto finish;
2567 #ifdef BOOST_NO_STD_LOCALE
2570 cc = ct.narrow(ch, char());
2571 #endif /* BOOST_NO_STD_LOCALE */
2573 if (cc == '(') // read "((a,b),(("
2575 p = ::boost::math::quaternion<T>(a,b);
2579 is.putback(ch); // we backtrack twice, with the same value
2581 is >> q; // read "((a,b),q"
2583 if (!is.good()) goto finish;
2585 is >> ch; // get the next lexeme
2587 if (!is.good()) goto finish;
2589 #ifdef BOOST_NO_STD_LOCALE
2592 cc = ct.narrow(ch, char());
2593 #endif /* BOOST_NO_STD_LOCALE */
2595 if (cc == ')') // read "((a,b),q)"
2597 o = octonion<T>(p,q);
2601 is.setstate(::std::ios_base::failbit);
2604 else // read "((a,b),(c" or "((a,b),(e"
2610 if (!is.good()) goto finish;
2612 is >> ch; // get the next lexeme
2614 if (!is.good()) goto finish;
2616 #ifdef BOOST_NO_STD_LOCALE
2619 cc = ct.narrow(ch, char());
2620 #endif /* BOOST_NO_STD_LOCALE */
2622 if (cc == ')') // read "((a,b),(c)" (ambiguity resolution)
2624 is >> ch; // get the next lexeme
2626 if (!is.good()) goto finish;
2628 #ifdef BOOST_NO_STD_LOCALE
2631 cc = ct.narrow(ch, char());
2632 #endif /* BOOST_NO_STD_LOCALE */
2634 if (cc == ')') // read "((a,b),(c))"
2636 o = octonion<T>(a,b,c);
2638 else if (cc == ',') // read "((a,b),(c),"
2640 u = ::std::complex<T>(a,b);
2642 v = ::std::complex<T>(c);
2644 is >> x; // read "((a,b),(c),x"
2646 if (!is.good()) goto finish;
2648 is >> ch; // get the next lexeme
2650 if (!is.good()) goto finish;
2652 #ifdef BOOST_NO_STD_LOCALE
2655 cc = ct.narrow(ch, char());
2656 #endif /* BOOST_NO_STD_LOCALE */
2658 if (cc == ')') // read "((a,b),(c),x)"
2660 o = octonion<T>(u,v,x);
2662 else if (cc == ',') // read "((a,b),(c),x,"
2664 is >> y; // read "((a,b),(c),x,y"
2666 if (!is.good()) goto finish;
2668 is >> ch; // get the next lexeme
2670 if (!is.good()) goto finish;
2672 #ifdef BOOST_NO_STD_LOCALE
2675 cc = ct.narrow(ch, char());
2676 #endif /* BOOST_NO_STD_LOCALE */
2678 if (cc == ')') // read "((a,b),(c),x,y)"
2680 o = octonion<T>(u,v,x,y);
2684 is.setstate(::std::ios_base::failbit);
2689 is.setstate(::std::ios_base::failbit);
2694 is.setstate(::std::ios_base::failbit);
2697 else if (cc == ',') // read "((a,b),(c," or "((a,b),(e,"
2699 is >> ch; // get the next lexeme
2701 if (!is.good()) goto finish;
2703 #ifdef BOOST_NO_STD_LOCALE
2706 cc = ct.narrow(ch, char());
2707 #endif /* BOOST_NO_STD_LOCALE */
2709 if (cc == '(') // read "((a,b),(e,(" (ambiguity resolution)
2711 u = ::std::complex<T>(a,b);
2713 x = ::std::complex<T>(c); // "c" is actually "e"
2717 is >> y; // read "((a,b),(e,y"
2719 if (!is.good()) goto finish;
2721 is >> ch; // get the next lexeme
2723 if (!is.good()) goto finish;
2725 #ifdef BOOST_NO_STD_LOCALE
2728 cc = ct.narrow(ch, char());
2729 #endif /* BOOST_NO_STD_LOCALE */
2731 if (cc == ')') // read "((a,b),(e,y)"
2733 is >> ch; // get the next lexeme
2735 if (!is.good()) goto finish;
2737 #ifdef BOOST_NO_STD_LOCALE
2740 cc = ct.narrow(ch, char());
2741 #endif /* BOOST_NO_STD_LOCALE */
2743 if (cc == ')') // read "((a,b),(e,y))"
2745 o = octonion<T>(u,v,x,y);
2749 is.setstate(::std::ios_base::failbit);
2754 is.setstate(::std::ios_base::failbit);
2757 else // read "((a,b),(c,d" or "((a,b),(e,f"
2763 if (!is.good()) goto finish;
2765 is >> ch; // get the next lexeme
2767 if (!is.good()) goto finish;
2769 #ifdef BOOST_NO_STD_LOCALE
2772 cc = ct.narrow(ch, char());
2773 #endif /* BOOST_NO_STD_LOCALE */
2775 if (cc == ')') // read "((a,b),(c,d)" (ambiguity resolution)
2777 u = ::std::complex<T>(a,b);
2779 v = ::std::complex<T>(c,d);
2781 is >> ch; // get the next lexeme
2783 if (!is.good()) goto finish;
2785 #ifdef BOOST_NO_STD_LOCALE
2788 cc = ct.narrow(ch, char());
2789 #endif /* BOOST_NO_STD_LOCALE */
2791 if (cc == ')') // read "((a,b),(c,d))"
2793 o = octonion<T>(u,v);
2795 else if (cc == ',') // read "((a,b),(c,d),"
2797 is >> x; // read "((a,b),(c,d),x
2799 if (!is.good()) goto finish;
2801 is >> ch; // get the next lexeme
2803 if (!is.good()) goto finish;
2805 #ifdef BOOST_NO_STD_LOCALE
2808 cc = ct.narrow(ch, char());
2809 #endif /* BOOST_NO_STD_LOCALE */
2811 if (cc == ')') // read "((a,b),(c,d),x)"
2813 o = octonion<T>(u,v,x);
2815 else if (cc == ',') // read "((a,b),(c,d),x,"
2817 is >> y; // read "((a,b),(c,d),x,y"
2819 if (!is.good()) goto finish;
2821 is >> ch; // get the next lexeme
2823 if (!is.good()) goto finish;
2825 #ifdef BOOST_NO_STD_LOCALE
2828 cc = ct.narrow(ch, char());
2829 #endif /* BOOST_NO_STD_LOCALE */
2831 if (cc == ')') // read "((a,b),(c,d),x,y)"
2833 o = octonion<T>(u,v,x,y);
2837 is.setstate(::std::ios_base::failbit);
2842 is.setstate(::std::ios_base::failbit);
2847 is.setstate(::std::ios_base::failbit);
2850 else if (cc == ',') // read "((a,b),(e,f," (ambiguity resolution)
2852 p = ::boost::math::quaternion<T>(a,b); // too late to backtrack
2854 is >> g; // read "((a,b),(e,f,g"
2856 if (!is.good()) goto finish;
2858 is >> ch; // get the next lexeme
2860 if (!is.good()) goto finish;
2862 #ifdef BOOST_NO_STD_LOCALE
2865 cc = ct.narrow(ch, char());
2866 #endif /* BOOST_NO_STD_LOCALE */
2868 if (cc == ')') // read "((a,b),(e,f,g)"
2870 is >> ch; // get the next lexeme
2872 if (!is.good()) goto finish;
2874 #ifdef BOOST_NO_STD_LOCALE
2877 cc = ct.narrow(ch, char());
2878 #endif /* BOOST_NO_STD_LOCALE */
2880 if (cc == ')') // read "((a,b),(e,f,g))"
2882 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f"
2884 o = octonion<T>(p,q);
2888 is.setstate(::std::ios_base::failbit);
2891 else if (cc == ',') // read "((a,b),(e,f,g,"
2893 is >> h; // read "((a,b),(e,f,g,h"
2895 if (!is.good()) goto finish;
2897 is >> ch; // get the next lexeme
2899 if (!is.good()) goto finish;
2901 #ifdef BOOST_NO_STD_LOCALE
2904 cc = ct.narrow(ch, char());
2905 #endif /* BOOST_NO_STD_LOCALE */
2907 if (cc == ')') // read "((a,b),(e,f,g,h)"
2909 is >> ch; // get the next lexeme
2911 if (!is.good()) goto finish;
2913 #ifdef BOOST_NO_STD_LOCALE
2916 cc = ct.narrow(ch, char());
2917 #endif /* BOOST_NO_STD_LOCALE */
2919 if (cc == ')') // read ((a,b),(e,f,g,h))"
2921 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f"
2923 o = octonion<T>(p,q);
2927 is.setstate(::std::ios_base::failbit);
2932 is.setstate(::std::ios_base::failbit);
2937 is.setstate(::std::ios_base::failbit);
2942 is.setstate(::std::ios_base::failbit);
2948 is.setstate(::std::ios_base::failbit);
2954 is.setstate(::std::ios_base::failbit);
2959 is.setstate(::std::ios_base::failbit);
2962 else if (cc == ',') // read "((a,b,"
2964 is >> c; // read "((a,b,c"
2966 if (!is.good()) goto finish;
2968 is >> ch; // get the next lexeme
2970 if (!is.good()) goto finish;
2972 #ifdef BOOST_NO_STD_LOCALE
2975 cc = ct.narrow(ch, char());
2976 #endif /* BOOST_NO_STD_LOCALE */
2978 if (cc == ')') // read "((a,b,c)"
2980 is >> ch; // get the next lexeme
2982 if (!is.good()) goto finish;
2984 #ifdef BOOST_NO_STD_LOCALE
2987 cc = ct.narrow(ch, char());
2988 #endif /* BOOST_NO_STD_LOCALE */
2990 if (cc == ')') // read "((a,b,c))"
2992 o = octonion<T>(a,b,c);
2994 else if (cc == ',') // read "((a,b,c),"
2996 p = ::boost::math::quaternion<T>(a,b,c);
2998 is >> q; // read "((a,b,c),q"
3000 if (!is.good()) goto finish;
3002 is >> ch; // get the next lexeme
3004 if (!is.good()) goto finish;
3006 #ifdef BOOST_NO_STD_LOCALE
3009 cc = ct.narrow(ch, char());
3010 #endif /* BOOST_NO_STD_LOCALE */
3012 if (cc == ')') // read "((a,b,c),q)"
3014 o = octonion<T>(p,q);
3018 is.setstate(::std::ios_base::failbit);
3023 is.setstate(::std::ios_base::failbit);
3026 else if (cc == ',') // read "((a,b,c,"
3028 is >> d; // read "((a,b,c,d"
3030 if (!is.good()) goto finish;
3032 is >> ch; // get the next lexeme
3034 if (!is.good()) goto finish;
3036 #ifdef BOOST_NO_STD_LOCALE
3039 cc = ct.narrow(ch, char());
3040 #endif /* BOOST_NO_STD_LOCALE */
3042 if (cc == ')') // read "((a,b,c,d)"
3044 is >> ch; // get the next lexeme
3046 if (!is.good()) goto finish;
3048 #ifdef BOOST_NO_STD_LOCALE
3051 cc = ct.narrow(ch, char());
3052 #endif /* BOOST_NO_STD_LOCALE */
3054 if (cc == ')') // read "((a,b,c,d))"
3056 o = octonion<T>(a,b,c,d);
3058 else if (cc == ',') // read "((a,b,c,d),"
3060 p = ::boost::math::quaternion<T>(a,b,c,d);
3062 is >> q; // read "((a,b,c,d),q"
3064 if (!is.good()) goto finish;
3066 is >> ch; // get the next lexeme
3068 if (!is.good()) goto finish;
3070 #ifdef BOOST_NO_STD_LOCALE
3073 cc = ct.narrow(ch, char());
3074 #endif /* BOOST_NO_STD_LOCALE */
3076 if (cc == ')') // read "((a,b,c,d),q)"
3078 o = octonion<T>(p,q);
3082 is.setstate(::std::ios_base::failbit);
3087 is.setstate(::std::ios_base::failbit);
3092 is.setstate(::std::ios_base::failbit);
3097 is.setstate(::std::ios_base::failbit);
3102 is.setstate(::std::ios_base::failbit);
3108 is.setstate(::std::ios_base::failbit);
3116 is >> a; // we extract the first component
3118 if (!is.good()) goto finish;
3120 is >> ch; // get the next lexeme
3122 if (!is.good()) goto finish;
3124 #ifdef BOOST_NO_STD_LOCALE
3127 cc = ct.narrow(ch, char());
3128 #endif /* BOOST_NO_STD_LOCALE */
3130 if (cc == ')') // read "(a)"
3134 else if (cc == ',') // read "(a,"
3136 is >> ch; // get the next lexeme
3138 if (!is.good()) goto finish;
3140 #ifdef BOOST_NO_STD_LOCALE
3143 cc = ct.narrow(ch, char());
3144 #endif /* BOOST_NO_STD_LOCALE */
3146 if (cc == '(') // read "(a,("
3148 is >> ch; // get the next lexeme
3150 if (!is.good()) goto finish;
3152 #ifdef BOOST_NO_STD_LOCALE
3155 cc = ct.narrow(ch, char());
3156 #endif /* BOOST_NO_STD_LOCALE */
3158 if (cc == '(') // read "(a,(("
3160 p = ::boost::math::quaternion<T>(a);
3164 is.putback(ch); // we backtrack twice, with the same value
3166 is >> q; // read "(a,q"
3168 if (!is.good()) goto finish;
3170 is >> ch; // get the next lexeme
3172 if (!is.good()) goto finish;
3174 #ifdef BOOST_NO_STD_LOCALE
3177 cc = ct.narrow(ch, char());
3178 #endif /* BOOST_NO_STD_LOCALE */
3180 if (cc == ')') // read "(a,q)"
3182 o = octonion<T>(p,q);
3186 is.setstate(::std::ios_base::failbit);
3189 else // read "(a,(c" or "(a,(e"
3195 if (!is.good()) goto finish;
3197 is >> ch; // get the next lexeme
3199 if (!is.good()) goto finish;
3201 #ifdef BOOST_NO_STD_LOCALE
3204 cc = ct.narrow(ch, char());
3205 #endif /* BOOST_NO_STD_LOCALE */
3207 if (cc == ')') // read "(a,(c)" (ambiguity resolution)
3209 is >> ch; // get the next lexeme
3211 if (!is.good()) goto finish;
3213 #ifdef BOOST_NO_STD_LOCALE
3216 cc = ct.narrow(ch, char());
3217 #endif /* BOOST_NO_STD_LOCALE */
3219 if (cc == ')') // read "(a,(c))"
3221 o = octonion<T>(a,b,c);
3223 else if (cc == ',') // read "(a,(c),"
3225 u = ::std::complex<T>(a);
3227 v = ::std::complex<T>(c);
3229 is >> x; // read "(a,(c),x"
3231 if (!is.good()) goto finish;
3233 is >> ch; // get the next lexeme
3235 if (!is.good()) goto finish;
3237 #ifdef BOOST_NO_STD_LOCALE
3240 cc = ct.narrow(ch, char());
3241 #endif /* BOOST_NO_STD_LOCALE */
3243 if (cc == ')') // read "(a,(c),x)"
3245 o = octonion<T>(u,v,x);
3247 else if (cc == ',') // read "(a,(c),x,"
3249 is >> y; // read "(a,(c),x,y"
3251 if (!is.good()) goto finish;
3253 is >> ch; // get the next lexeme
3255 if (!is.good()) goto finish;
3257 #ifdef BOOST_NO_STD_LOCALE
3260 cc = ct.narrow(ch, char());
3261 #endif /* BOOST_NO_STD_LOCALE */
3263 if (cc == ')') // read "(a,(c),x,y)"
3265 o = octonion<T>(u,v,x,y);
3269 is.setstate(::std::ios_base::failbit);
3274 is.setstate(::std::ios_base::failbit);
3279 is.setstate(::std::ios_base::failbit);
3282 else if (cc == ',') // read "(a,(c," or "(a,(e,"
3284 is >> ch; // get the next lexeme
3286 if (!is.good()) goto finish;
3288 #ifdef BOOST_NO_STD_LOCALE
3291 cc = ct.narrow(ch, char());
3292 #endif /* BOOST_NO_STD_LOCALE */
3294 if (cc == '(') // read "(a,(e,(" (ambiguity resolution)
3296 u = ::std::complex<T>(a);
3298 x = ::std::complex<T>(c); // "c" is actually "e"
3300 is.putback(ch); // we backtrack
3302 is >> y; // read "(a,(e,y"
3304 if (!is.good()) goto finish;
3306 is >> ch; // get the next lexeme
3308 if (!is.good()) goto finish;
3310 #ifdef BOOST_NO_STD_LOCALE
3313 cc = ct.narrow(ch, char());
3314 #endif /* BOOST_NO_STD_LOCALE */
3316 if (cc == ')') // read "(a,(e,y)"
3318 is >> ch; // get the next lexeme
3320 if (!is.good()) goto finish;
3322 #ifdef BOOST_NO_STD_LOCALE
3325 cc = ct.narrow(ch, char());
3326 #endif /* BOOST_NO_STD_LOCALE */
3328 if (cc == ')') // read "(a,(e,y))"
3330 o = octonion<T>(u,v,x,y);
3334 is.setstate(::std::ios_base::failbit);
3339 is.setstate(::std::ios_base::failbit);
3342 else // read "(a,(c,d" or "(a,(e,f"
3348 if (!is.good()) goto finish;
3350 is >> ch; // get the next lexeme
3352 if (!is.good()) goto finish;
3354 #ifdef BOOST_NO_STD_LOCALE
3357 cc = ct.narrow(ch, char());
3358 #endif /* BOOST_NO_STD_LOCALE */
3360 if (cc == ')') // read "(a,(c,d)" (ambiguity resolution)
3362 is >> ch; // get the next lexeme
3364 if (!is.good()) goto finish;
3366 #ifdef BOOST_NO_STD_LOCALE
3369 cc = ct.narrow(ch, char());
3370 #endif /* BOOST_NO_STD_LOCALE */
3372 if (cc == ')') // read "(a,(c,d))"
3374 o = octonion<T>(a,b,c,d);
3376 else if (cc == ',') // read "(a,(c,d),"
3378 u = ::std::complex<T>(a);
3380 v = ::std::complex<T>(c,d);
3382 is >> x; // read "(a,(c,d),x"
3384 if (!is.good()) goto finish;
3386 is >> ch; // get the next lexeme
3388 if (!is.good()) goto finish;
3390 #ifdef BOOST_NO_STD_LOCALE
3393 cc = ct.narrow(ch, char());
3394 #endif /* BOOST_NO_STD_LOCALE */
3396 if (cc == ')') // read "(a,(c,d),x)"
3398 o = octonion<T>(u,v,x);
3400 else if (cc == ',') // read "(a,(c,d),x,"
3402 is >> y; // read "(a,(c,d),x,y"
3404 if (!is.good()) goto finish;
3406 is >> ch; // get the next lexeme
3408 if (!is.good()) goto finish;
3410 #ifdef BOOST_NO_STD_LOCALE
3413 cc = ct.narrow(ch, char());
3414 #endif /* BOOST_NO_STD_LOCALE */
3416 if (cc == ')') // read "(a,(c,d),x,y)"
3418 o = octonion<T>(u,v,x,y);
3422 is.setstate(::std::ios_base::failbit);
3427 is.setstate(::std::ios_base::failbit);
3432 is.setstate(::std::ios_base::failbit);
3435 else if (cc == ',') // read "(a,(e,f," (ambiguity resolution)
3437 p = ::boost::math::quaternion<T>(a);
3439 is >> g; // read "(a,(e,f,g"
3441 if (!is.good()) goto finish;
3443 is >> ch; // get the next lexeme
3445 if (!is.good()) goto finish;
3447 #ifdef BOOST_NO_STD_LOCALE
3450 cc = ct.narrow(ch, char());
3451 #endif /* BOOST_NO_STD_LOCALE */
3453 if (cc == ')') // read "(a,(e,f,g)"
3455 is >> ch; // get the next lexeme
3457 if (!is.good()) goto finish;
3459 #ifdef BOOST_NO_STD_LOCALE
3462 cc = ct.narrow(ch, char());
3463 #endif /* BOOST_NO_STD_LOCALE */
3465 if (cc == ')') // read "(a,(e,f,g))"
3467 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f"
3469 o = octonion<T>(p,q);
3473 is.setstate(::std::ios_base::failbit);
3476 else if (cc == ',') // read "(a,(e,f,g,"
3478 is >> h; // read "(a,(e,f,g,h"
3480 if (!is.good()) goto finish;
3482 is >> ch; // get the next lexeme
3484 if (!is.good()) goto finish;
3486 #ifdef BOOST_NO_STD_LOCALE
3489 cc = ct.narrow(ch, char());
3490 #endif /* BOOST_NO_STD_LOCALE */
3492 if (cc == ')') // read "(a,(e,f,g,h)"
3494 is >> ch; // get the next lexeme
3496 if (!is.good()) goto finish;
3498 #ifdef BOOST_NO_STD_LOCALE
3501 cc = ct.narrow(ch, char());
3502 #endif /* BOOST_NO_STD_LOCALE */
3504 if (cc == ')') // read "(a,(e,f,g,h))"
3506 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f"
3508 o = octonion<T>(p,q);
3512 is.setstate(::std::ios_base::failbit);
3517 is.setstate(::std::ios_base::failbit);
3522 is.setstate(::std::ios_base::failbit);
3527 is.setstate(::std::ios_base::failbit);
3533 is.setstate(::std::ios_base::failbit);
3537 else // read "(a,b" or "(a,c" (ambiguity resolution)
3543 if (!is.good()) goto finish;
3545 is >> ch; // get the next lexeme
3547 if (!is.good()) goto finish;
3549 #ifdef BOOST_NO_STD_LOCALE
3552 cc = ct.narrow(ch, char());
3553 #endif /* BOOST_NO_STD_LOCALE */
3555 if (cc == ')') // read "(a,b)" (ambiguity resolution)
3557 o = octonion<T>(a,b);
3559 else if (cc == ',') // read "(a,b," or "(a,c,"
3561 is >> ch; // get the next lexeme
3563 if (!is.good()) goto finish;
3565 #ifdef BOOST_NO_STD_LOCALE
3568 cc = ct.narrow(ch, char());
3569 #endif /* BOOST_NO_STD_LOCALE */
3571 if (cc == '(') // read "(a,c,(" (ambiguity resolution)
3573 u = ::std::complex<T>(a);
3575 v = ::std::complex<T>(b); // "b" is actually "c"
3577 is.putback(ch); // we backtrack
3579 is >> x; // read "(a,c,x"
3581 if (!is.good()) goto finish;
3583 is >> ch; // get the next lexeme
3585 if (!is.good()) goto finish;
3587 #ifdef BOOST_NO_STD_LOCALE
3590 cc = ct.narrow(ch, char());
3591 #endif /* BOOST_NO_STD_LOCALE */
3593 if (cc == ')') // read "(a,c,x)"
3595 o = octonion<T>(u,v,x);
3597 else if (cc == ',') // read "(a,c,x,"
3599 is >> y; // read "(a,c,x,y" // read "(a,c,x"
3601 if (!is.good()) goto finish;
3603 is >> ch; // get the next lexeme
3605 if (!is.good()) goto finish;
3607 #ifdef BOOST_NO_STD_LOCALE
3610 cc = ct.narrow(ch, char());
3611 #endif /* BOOST_NO_STD_LOCALE */
3613 if (cc == ')') // read "(a,c,x,y)"
3615 o = octonion<T>(u,v,x,y);
3619 is.setstate(::std::ios_base::failbit);
3624 is.setstate(::std::ios_base::failbit);
3627 else // read "(a,b,c" or "(a,c,e"
3633 if (!is.good()) goto finish;
3635 is >> ch; // get the next lexeme
3637 if (!is.good()) goto finish;
3639 #ifdef BOOST_NO_STD_LOCALE
3642 cc = ct.narrow(ch, char());
3643 #endif /* BOOST_NO_STD_LOCALE */
3645 if (cc == ')') // read "(a,b,c)" (ambiguity resolution)
3647 o = octonion<T>(a,b,c);
3649 else if (cc == ',') // read "(a,b,c," or "(a,c,e,"
3651 is >> ch; // get the next lexeme
3653 if (!is.good()) goto finish;
3655 #ifdef BOOST_NO_STD_LOCALE
3658 cc = ct.narrow(ch, char());
3659 #endif /* BOOST_NO_STD_LOCALE */
3661 if (cc == '(') // read "(a,c,e,(") (ambiguity resolution)
3663 u = ::std::complex<T>(a);
3665 v = ::std::complex<T>(b); // "b" is actually "c"
3667 x = ::std::complex<T>(c); // "c" is actually "e"
3669 is.putback(ch); // we backtrack
3671 is >> y; // read "(a,c,e,y"
3673 if (!is.good()) goto finish;
3675 is >> ch; // get the next lexeme
3677 if (!is.good()) goto finish;
3679 #ifdef BOOST_NO_STD_LOCALE
3682 cc = ct.narrow(ch, char());
3683 #endif /* BOOST_NO_STD_LOCALE */
3685 if (cc == ')') // read "(a,c,e,y)"
3687 o = octonion<T>(u,v,x,y);
3691 is.setstate(::std::ios_base::failbit);
3694 else // read "(a,b,c,d" (ambiguity resolution)
3696 is.putback(ch); // we backtrack
3700 if (!is.good()) goto finish;
3702 is >> ch; // get the next lexeme
3704 if (!is.good()) goto finish;
3706 #ifdef BOOST_NO_STD_LOCALE
3709 cc = ct.narrow(ch, char());
3710 #endif /* BOOST_NO_STD_LOCALE */
3712 if (cc == ')') // read "(a,b,c,d)"
3714 o = octonion<T>(a,b,c,d);
3716 else if (cc == ',') // read "(a,b,c,d,"
3718 is >> e; // read "(a,b,c,d,e"
3720 if (!is.good()) goto finish;
3722 is >> ch; // get the next lexeme
3724 if (!is.good()) goto finish;
3726 #ifdef BOOST_NO_STD_LOCALE
3729 cc = ct.narrow(ch, char());
3730 #endif /* BOOST_NO_STD_LOCALE */
3732 if (cc == ')') // read "(a,b,c,d,e)"
3734 o = octonion<T>(a,b,c,d,e);
3736 else if (cc == ',') // read "(a,b,c,d,e,"
3738 is >> f; // read "(a,b,c,d,e,f"
3740 if (!is.good()) goto finish;
3742 is >> ch; // get the next lexeme
3744 if (!is.good()) goto finish;
3746 #ifdef BOOST_NO_STD_LOCALE
3749 cc = ct.narrow(ch, char());
3750 #endif /* BOOST_NO_STD_LOCALE */
3752 if (cc == ')') // read "(a,b,c,d,e,f)"
3754 o = octonion<T>(a,b,c,d,e,f);
3756 else if (cc == ',') // read "(a,b,c,d,e,f,"
3758 is >> g; // read "(a,b,c,d,e,f,g" // read "(a,b,c,d,e,f"
3760 if (!is.good()) goto finish;
3762 is >> ch; // get the next lexeme
3764 if (!is.good()) goto finish;
3766 #ifdef BOOST_NO_STD_LOCALE
3769 cc = ct.narrow(ch, char());
3770 #endif /* BOOST_NO_STD_LOCALE */
3772 if (cc == ')') // read "(a,b,c,d,e,f,g)"
3774 o = octonion<T>(a,b,c,d,e,f,g);
3776 else if (cc == ',') // read "(a,b,c,d,e,f,g,"
3778 is >> h; // read "(a,b,c,d,e,f,g,h" // read "(a,b,c,d,e,f,g" // read "(a,b,c,d,e,f"
3780 if (!is.good()) goto finish;
3782 is >> ch; // get the next lexeme
3784 if (!is.good()) goto finish;
3786 #ifdef BOOST_NO_STD_LOCALE
3789 cc = ct.narrow(ch, char());
3790 #endif /* BOOST_NO_STD_LOCALE */
3792 if (cc == ')') // read "(a,b,c,d,e,f,g,h)"
3794 o = octonion<T>(a,b,c,d,e,f,g,h);
3798 is.setstate(::std::ios_base::failbit);
3803 is.setstate(::std::ios_base::failbit);
3808 is.setstate(::std::ios_base::failbit);
3813 is.setstate(::std::ios_base::failbit);
3818 is.setstate(::std::ios_base::failbit);
3824 is.setstate(::std::ios_base::failbit);
3830 is.setstate(::std::ios_base::failbit);
3836 is.setstate(::std::ios_base::failbit);
3844 is >> a; // we extract the first component
3846 if (!is.good()) goto finish;
3856 template<typename T, typename charT, class traits>
3857 ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
3858 octonion<T> const & o)
3860 ::std::basic_ostringstream<charT,traits> s;
3862 s.flags(os.flags());
3863 #ifdef BOOST_NO_STD_LOCALE
3865 s.imbue(os.getloc());
3866 #endif /* BOOST_NO_STD_LOCALE */
3867 s.precision(os.precision());
3869 s << '(' << o.R_component_1() << ','
3870 << o.R_component_2() << ','
3871 << o.R_component_3() << ','
3872 << o.R_component_4() << ','
3873 << o.R_component_5() << ','
3874 << o.R_component_6() << ','
3875 << o.R_component_7() << ','
3876 << o.R_component_8() << ')';
3878 return os << s.str();
3884 template<typename T>
3885 inline T real(octonion<T> const & o)
3891 template<typename T>
3892 inline octonion<T> unreal(octonion<T> const & o)
3898 #define BOOST_OCTONION_VALARRAY_LOADER \
3899 using ::std::valarray; \
3901 valarray<T> temp(8); \
3903 temp[0] = o.R_component_1(); \
3904 temp[1] = o.R_component_2(); \
3905 temp[2] = o.R_component_3(); \
3906 temp[3] = o.R_component_4(); \
3907 temp[4] = o.R_component_5(); \
3908 temp[5] = o.R_component_6(); \
3909 temp[6] = o.R_component_7(); \
3910 temp[7] = o.R_component_8();
3913 template<typename T>
3914 inline T sup(octonion<T> const & o)
3916 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
3918 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
3920 BOOST_OCTONION_VALARRAY_LOADER
3922 return((abs(temp).max)());
3926 template<typename T>
3927 inline T l1(octonion<T> const & o)
3929 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
3931 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
3933 BOOST_OCTONION_VALARRAY_LOADER
3935 return(abs(temp).sum());
3939 template<typename T>
3940 inline T abs(const octonion<T> & o)
3942 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
3944 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
3948 BOOST_OCTONION_VALARRAY_LOADER
3950 T maxim = (abs(temp).max)(); // overflow protection
3952 if (maxim == static_cast<T>(0))
3958 T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions
3964 return(maxim*sqrt(temp.sum()));
3967 //return(::std::sqrt(norm(o)));
3971 #undef BOOST_OCTONION_VALARRAY_LOADER
3974 // Note: This is the Cayley norm, not the Euclidian norm...
3976 template<typename T>
3977 inline T norm(octonion<T> const & o)
3979 return(real(o*conj(o)));
3983 template<typename T>
3984 inline octonion<T> conj(octonion<T> const & o)
3986 return(octonion<T>( +o.R_component_1(),
3993 -o.R_component_8()));
3997 // Note: There is little point, for the octonions, to introduce the equivalents
3998 // to the complex "arg" and the quaternionic "cylindropolar".
4001 template<typename T>
4002 inline octonion<T> spherical(T const & rho,
4014 //T a = cos(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4015 //T b = sin(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4016 //T c = sin(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4017 //T d = sin(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4018 //T e = sin(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4019 //T f = sin(phi4)*cos(phi5)*cos(phi6);
4020 //T g = sin(phi5)*cos(phi6);
4023 T courrant = static_cast<T>(1);
4027 courrant *= cos(phi6);
4029 T g = sin(phi5)*courrant;
4031 courrant *= cos(phi5);
4033 T f = sin(phi4)*courrant;
4035 courrant *= cos(phi4);
4037 T e = sin(phi3)*courrant;
4039 courrant *= cos(phi3);
4041 T d = sin(phi2)*courrant;
4043 courrant *= cos(phi2);
4045 T c = sin(phi1)*courrant;
4047 courrant *= cos(phi1);
4049 T b = sin(theta)*courrant;
4050 T a = cos(theta)*courrant;
4052 return(rho*octonion<T>(a,b,c,d,e,f,g,h));
4056 template<typename T>
4057 inline octonion<T> multipolar(T const & rho1,
4069 T a = rho1*cos(theta1);
4070 T b = rho1*sin(theta1);
4071 T c = rho2*cos(theta2);
4072 T d = rho2*sin(theta2);
4073 T e = rho3*cos(theta3);
4074 T f = rho3*sin(theta3);
4075 T g = rho4*cos(theta4);
4076 T h = rho4*sin(theta4);
4078 return(octonion<T>(a,b,c,d,e,f,g,h));
4082 template<typename T>
4083 inline octonion<T> cylindrical(T const & r,
4098 return(octonion<T>(a,b,h1,h2,h3,h4,h5,h6));
4102 template<typename T>
4103 inline octonion<T> exp(octonion<T> const & o)
4108 using ::boost::math::sinc_pi;
4112 T z = abs(unreal(o));
4116 return(u*octonion<T>(cos(z),
4117 w*o.R_component_2(), w*o.R_component_3(),
4118 w*o.R_component_4(), w*o.R_component_5(),
4119 w*o.R_component_6(), w*o.R_component_7(),
4120 w*o.R_component_8()));
4124 template<typename T>
4125 inline octonion<T> cos(octonion<T> const & o)
4131 using ::boost::math::sinhc_pi;
4133 T z = abs(unreal(o));
4135 T w = -sin(o.real())*sinhc_pi(z);
4137 return(octonion<T>(cos(o.real())*cosh(z),
4138 w*o.R_component_2(), w*o.R_component_3(),
4139 w*o.R_component_4(), w*o.R_component_5(),
4140 w*o.R_component_6(), w*o.R_component_7(),
4141 w*o.R_component_8()));
4145 template<typename T>
4146 inline octonion<T> sin(octonion<T> const & o)
4152 using ::boost::math::sinhc_pi;
4154 T z = abs(unreal(o));
4156 T w = +cos(o.real())*sinhc_pi(z);
4158 return(octonion<T>(sin(o.real())*cosh(z),
4159 w*o.R_component_2(), w*o.R_component_3(),
4160 w*o.R_component_4(), w*o.R_component_5(),
4161 w*o.R_component_6(), w*o.R_component_7(),
4162 w*o.R_component_8()));
4166 template<typename T>
4167 inline octonion<T> tan(octonion<T> const & o)
4169 return(sin(o)/cos(o));
4173 template<typename T>
4174 inline octonion<T> cosh(octonion<T> const & o)
4176 return((exp(+o)+exp(-o))/static_cast<T>(2));
4180 template<typename T>
4181 inline octonion<T> sinh(octonion<T> const & o)
4183 return((exp(+o)-exp(-o))/static_cast<T>(2));
4187 template<typename T>
4188 inline octonion<T> tanh(octonion<T> const & o)
4190 return(sinh(o)/cosh(o));
4194 template<typename T>
4195 octonion<T> pow(octonion<T> const & o,
4202 octonion<T> result = pow(o, m);
4208 result *= o; // n odd
4219 return(octonion<T>(static_cast<T>(1)));
4223 return(pow(octonion<T>(static_cast<T>(1))/o,-n));
4228 // helper templates for converting copy constructors (definition)
4233 template< typename T,
4236 octonion<T> octonion_type_converter(octonion<U> const & rhs)
4238 return(octonion<T>( static_cast<T>(rhs.R_component_1()),
4239 static_cast<T>(rhs.R_component_2()),
4240 static_cast<T>(rhs.R_component_3()),
4241 static_cast<T>(rhs.R_component_4()),
4242 static_cast<T>(rhs.R_component_5()),
4243 static_cast<T>(rhs.R_component_6()),
4244 static_cast<T>(rhs.R_component_7()),
4245 static_cast<T>(rhs.R_component_8())));
4251 #endif /* BOOST_OCTONION_HPP */