comparison DEPENDENCIES/generic/include/boost/math/octonion.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 // boost octonion.hpp header file
2
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)
7
8 // See http://www.boost.org for updates, documentation, and revision history.
9
10
11 #ifndef BOOST_OCTONION_HPP
12 #define BOOST_OCTONION_HPP
13
14 #include <boost/math/quaternion.hpp>
15
16
17 namespace boost
18 {
19 namespace math
20 {
21 #if BOOST_WORKAROUND(__GNUC__, < 3)
22 // gcc 2.95.x uses expression templates for valarray calculations, but
23 // the result is not conforming. We need BOOST_GET_VALARRAY to get an
24 // actual valarray result when we need to call a member function
25 #define BOOST_GET_VALARRAY(T,x) ::std::valarray<T>(x)
26 // gcc 2.95.x has an "std::ios" class that is similar to
27 // "std::ios_base", so we just use a #define
28 #define BOOST_IOS_BASE ::std::ios
29 // gcc 2.x ignores function scope using declarations,
30 // put them in the scope of the enclosing namespace instead:
31 using ::std::valarray;
32 using ::std::sqrt;
33 using ::std::cos;
34 using ::std::sin;
35 using ::std::exp;
36 using ::std::cosh;
37 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
38
39 #define BOOST_OCTONION_ACCESSOR_GENERATOR(type) \
40 type real() const \
41 { \
42 return(a); \
43 } \
44 \
45 octonion<type> unreal() const \
46 { \
47 return( octonion<type>(static_cast<type>(0),b,c,d,e,f,g,h)); \
48 } \
49 \
50 type R_component_1() const \
51 { \
52 return(a); \
53 } \
54 \
55 type R_component_2() const \
56 { \
57 return(b); \
58 } \
59 \
60 type R_component_3() const \
61 { \
62 return(c); \
63 } \
64 \
65 type R_component_4() const \
66 { \
67 return(d); \
68 } \
69 \
70 type R_component_5() const \
71 { \
72 return(e); \
73 } \
74 \
75 type R_component_6() const \
76 { \
77 return(f); \
78 } \
79 \
80 type R_component_7() const \
81 { \
82 return(g); \
83 } \
84 \
85 type R_component_8() const \
86 { \
87 return(h); \
88 } \
89 \
90 ::std::complex<type> C_component_1() const \
91 { \
92 return(::std::complex<type>(a,b)); \
93 } \
94 \
95 ::std::complex<type> C_component_2() const \
96 { \
97 return(::std::complex<type>(c,d)); \
98 } \
99 \
100 ::std::complex<type> C_component_3() const \
101 { \
102 return(::std::complex<type>(e,f)); \
103 } \
104 \
105 ::std::complex<type> C_component_4() const \
106 { \
107 return(::std::complex<type>(g,h)); \
108 } \
109 \
110 ::boost::math::quaternion<type> H_component_1() const \
111 { \
112 return(::boost::math::quaternion<type>(a,b,c,d)); \
113 } \
114 \
115 ::boost::math::quaternion<type> H_component_2() const \
116 { \
117 return(::boost::math::quaternion<type>(e,f,g,h)); \
118 }
119
120
121 #define BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(type) \
122 template<typename X> \
123 octonion<type> & operator = (octonion<X> const & a_affecter) \
124 { \
125 a = static_cast<type>(a_affecter.R_component_1()); \
126 b = static_cast<type>(a_affecter.R_component_2()); \
127 c = static_cast<type>(a_affecter.R_component_3()); \
128 d = static_cast<type>(a_affecter.R_component_4()); \
129 e = static_cast<type>(a_affecter.R_component_5()); \
130 f = static_cast<type>(a_affecter.R_component_6()); \
131 g = static_cast<type>(a_affecter.R_component_7()); \
132 h = static_cast<type>(a_affecter.R_component_8()); \
133 \
134 return(*this); \
135 } \
136 \
137 octonion<type> & operator = (octonion<type> const & a_affecter) \
138 { \
139 a = a_affecter.a; \
140 b = a_affecter.b; \
141 c = a_affecter.c; \
142 d = a_affecter.d; \
143 e = a_affecter.e; \
144 f = a_affecter.f; \
145 g = a_affecter.g; \
146 h = a_affecter.h; \
147 \
148 return(*this); \
149 } \
150 \
151 octonion<type> & operator = (type const & a_affecter) \
152 { \
153 a = a_affecter; \
154 \
155 b = c = d = e = f= g = h = static_cast<type>(0); \
156 \
157 return(*this); \
158 } \
159 \
160 octonion<type> & operator = (::std::complex<type> const & a_affecter) \
161 { \
162 a = a_affecter.real(); \
163 b = a_affecter.imag(); \
164 \
165 c = d = e = f = g = h = static_cast<type>(0); \
166 \
167 return(*this); \
168 } \
169 \
170 octonion<type> & operator = (::boost::math::quaternion<type> const & a_affecter) \
171 { \
172 a = a_affecter.R_component_1(); \
173 b = a_affecter.R_component_2(); \
174 c = a_affecter.R_component_3(); \
175 d = a_affecter.R_component_4(); \
176 \
177 e = f = g = h = static_cast<type>(0); \
178 \
179 return(*this); \
180 }
181
182
183 #define BOOST_OCTONION_MEMBER_DATA_GENERATOR(type) \
184 type a; \
185 type b; \
186 type c; \
187 type d; \
188 type e; \
189 type f; \
190 type g; \
191 type h; \
192
193
194 template<typename T>
195 class octonion
196 {
197 public:
198
199 typedef T value_type;
200
201 // constructor for O seen as R^8
202 // (also default constructor)
203
204 explicit octonion( T const & requested_a = T(),
205 T const & requested_b = T(),
206 T const & requested_c = T(),
207 T const & requested_d = T(),
208 T const & requested_e = T(),
209 T const & requested_f = T(),
210 T const & requested_g = T(),
211 T const & requested_h = T())
212 : a(requested_a),
213 b(requested_b),
214 c(requested_c),
215 d(requested_d),
216 e(requested_e),
217 f(requested_f),
218 g(requested_g),
219 h(requested_h)
220 {
221 // nothing to do!
222 }
223
224
225 // constructor for H seen as C^4
226
227 explicit octonion( ::std::complex<T> const & z0,
228 ::std::complex<T> const & z1 = ::std::complex<T>(),
229 ::std::complex<T> const & z2 = ::std::complex<T>(),
230 ::std::complex<T> const & z3 = ::std::complex<T>())
231 : a(z0.real()),
232 b(z0.imag()),
233 c(z1.real()),
234 d(z1.imag()),
235 e(z2.real()),
236 f(z2.imag()),
237 g(z3.real()),
238 h(z3.imag())
239 {
240 // nothing to do!
241 }
242
243
244 // constructor for O seen as H^2
245
246 explicit octonion( ::boost::math::quaternion<T> const & q0,
247 ::boost::math::quaternion<T> const & q1 = ::boost::math::quaternion<T>())
248 : a(q0.R_component_1()),
249 b(q0.R_component_2()),
250 c(q0.R_component_3()),
251 d(q0.R_component_4()),
252 e(q1.R_component_1()),
253 f(q1.R_component_2()),
254 g(q1.R_component_3()),
255 h(q1.R_component_4())
256 {
257 // nothing to do!
258 }
259
260
261 // UNtemplated copy constructor
262 // (this is taken care of by the compiler itself)
263
264
265 // templated copy constructor
266
267 template<typename X>
268 explicit octonion(octonion<X> const & a_recopier)
269 : a(static_cast<T>(a_recopier.R_component_1())),
270 b(static_cast<T>(a_recopier.R_component_2())),
271 c(static_cast<T>(a_recopier.R_component_3())),
272 d(static_cast<T>(a_recopier.R_component_4())),
273 e(static_cast<T>(a_recopier.R_component_5())),
274 f(static_cast<T>(a_recopier.R_component_6())),
275 g(static_cast<T>(a_recopier.R_component_7())),
276 h(static_cast<T>(a_recopier.R_component_8()))
277 {
278 // nothing to do!
279 }
280
281
282 // destructor
283 // (this is taken care of by the compiler itself)
284
285
286 // accessors
287 //
288 // Note: Like complex number, octonions do have a meaningful notion of "real part",
289 // but unlike them there is no meaningful notion of "imaginary part".
290 // Instead there is an "unreal part" which itself is an octonion, and usually
291 // nothing simpler (as opposed to the complex number case).
292 // However, for practicallity, there are accessors for the other components
293 // (these are necessary for the templated copy constructor, for instance).
294
295 BOOST_OCTONION_ACCESSOR_GENERATOR(T)
296
297 // assignment operators
298
299 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(T)
300
301 // other assignment-related operators
302 //
303 // NOTE: Octonion multiplication is *NOT* commutative;
304 // symbolically, "q *= rhs;" means "q = q * rhs;"
305 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
306 // octonion multiplication is also *NOT* associative
307
308 octonion<T> & operator += (T const & rhs)
309 {
310 T at = a + rhs; // exception guard
311
312 a = at;
313
314 return(*this);
315 }
316
317
318 octonion<T> & operator += (::std::complex<T> const & rhs)
319 {
320 T at = a + rhs.real(); // exception guard
321 T bt = b + rhs.imag(); // exception guard
322
323 a = at;
324 b = bt;
325
326 return(*this);
327 }
328
329
330 octonion<T> & operator += (::boost::math::quaternion<T> const & rhs)
331 {
332 T at = a + rhs.R_component_1(); // exception guard
333 T bt = b + rhs.R_component_2(); // exception guard
334 T ct = c + rhs.R_component_3(); // exception guard
335 T dt = d + rhs.R_component_4(); // exception guard
336
337 a = at;
338 b = bt;
339 c = ct;
340 d = dt;
341
342 return(*this);
343 }
344
345
346 template<typename X>
347 octonion<T> & operator += (octonion<X> const & rhs)
348 {
349 T at = a + static_cast<T>(rhs.R_component_1()); // exception guard
350 T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard
351 T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard
352 T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard
353 T et = e + static_cast<T>(rhs.R_component_5()); // exception guard
354 T ft = f + static_cast<T>(rhs.R_component_6()); // exception guard
355 T gt = g + static_cast<T>(rhs.R_component_7()); // exception guard
356 T ht = h + static_cast<T>(rhs.R_component_8()); // exception guard
357
358 a = at;
359 b = bt;
360 c = ct;
361 d = dt;
362 e = et;
363 f = ft;
364 g = gt;
365 h = ht;
366
367 return(*this);
368 }
369
370
371
372 octonion<T> & operator -= (T const & rhs)
373 {
374 T at = a - rhs; // exception guard
375
376 a = at;
377
378 return(*this);
379 }
380
381
382 octonion<T> & operator -= (::std::complex<T> const & rhs)
383 {
384 T at = a - rhs.real(); // exception guard
385 T bt = b - rhs.imag(); // exception guard
386
387 a = at;
388 b = bt;
389
390 return(*this);
391 }
392
393
394 octonion<T> & operator -= (::boost::math::quaternion<T> const & rhs)
395 {
396 T at = a - rhs.R_component_1(); // exception guard
397 T bt = b - rhs.R_component_2(); // exception guard
398 T ct = c - rhs.R_component_3(); // exception guard
399 T dt = d - rhs.R_component_4(); // exception guard
400
401 a = at;
402 b = bt;
403 c = ct;
404 d = dt;
405
406 return(*this);
407 }
408
409
410 template<typename X>
411 octonion<T> & operator -= (octonion<X> const & rhs)
412 {
413 T at = a - static_cast<T>(rhs.R_component_1()); // exception guard
414 T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard
415 T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard
416 T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard
417 T et = e - static_cast<T>(rhs.R_component_5()); // exception guard
418 T ft = f - static_cast<T>(rhs.R_component_6()); // exception guard
419 T gt = g - static_cast<T>(rhs.R_component_7()); // exception guard
420 T ht = h - static_cast<T>(rhs.R_component_8()); // exception guard
421
422 a = at;
423 b = bt;
424 c = ct;
425 d = dt;
426 e = et;
427 f = ft;
428 g = gt;
429 h = ht;
430
431 return(*this);
432 }
433
434
435 octonion<T> & operator *= (T const & rhs)
436 {
437 T at = a * rhs; // exception guard
438 T bt = b * rhs; // exception guard
439 T ct = c * rhs; // exception guard
440 T dt = d * rhs; // exception guard
441 T et = e * rhs; // exception guard
442 T ft = f * rhs; // exception guard
443 T gt = g * rhs; // exception guard
444 T ht = h * rhs; // exception guard
445
446 a = at;
447 b = bt;
448 c = ct;
449 d = dt;
450 e = et;
451 f = ft;
452 g = gt;
453 h = ht;
454
455 return(*this);
456 }
457
458
459 octonion<T> & operator *= (::std::complex<T> const & rhs)
460 {
461 T ar = rhs.real();
462 T br = rhs.imag();
463
464 T at = +a*ar-b*br;
465 T bt = +a*br+b*ar;
466 T ct = +c*ar+d*br;
467 T dt = -c*br+d*ar;
468 T et = +e*ar+f*br;
469 T ft = -e*br+f*ar;
470 T gt = +g*ar-h*br;
471 T ht = +g*br+h*ar;
472
473 a = at;
474 b = bt;
475 c = ct;
476 d = dt;
477 e = et;
478 f = ft;
479 g = gt;
480 h = ht;
481
482 return(*this);
483 }
484
485
486 octonion<T> & operator *= (::boost::math::quaternion<T> const & rhs)
487 {
488 T ar = rhs.R_component_1();
489 T br = rhs.R_component_2();
490 T cr = rhs.R_component_2();
491 T dr = rhs.R_component_2();
492
493 T at = +a*ar-b*br-c*cr-d*dr;
494 T bt = +a*br+b*ar+c*dr-d*cr;
495 T ct = +a*cr-b*dr+c*ar+d*br;
496 T dt = +a*dr+b*cr-c*br+d*ar;
497 T et = +e*ar+f*br+g*cr+h*dr;
498 T ft = -e*br+f*ar-g*dr+h*cr;
499 T gt = -e*cr+f*dr+g*ar-h*br;
500 T ht = -e*dr-f*cr+g*br+h*ar;
501
502 a = at;
503 b = bt;
504 c = ct;
505 d = dt;
506 e = et;
507 f = ft;
508 g = gt;
509 h = ht;
510
511 return(*this);
512 }
513
514
515 template<typename X>
516 octonion<T> & operator *= (octonion<X> const & rhs)
517 {
518 T ar = static_cast<T>(rhs.R_component_1());
519 T br = static_cast<T>(rhs.R_component_2());
520 T cr = static_cast<T>(rhs.R_component_3());
521 T dr = static_cast<T>(rhs.R_component_4());
522 T er = static_cast<T>(rhs.R_component_5());
523 T fr = static_cast<T>(rhs.R_component_6());
524 T gr = static_cast<T>(rhs.R_component_7());
525 T hr = static_cast<T>(rhs.R_component_8());
526
527 T at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr;
528 T bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr;
529 T ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr;
530 T dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er;
531 T et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr;
532 T ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr;
533 T gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br;
534 T ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar;
535
536 a = at;
537 b = bt;
538 c = ct;
539 d = dt;
540 e = et;
541 f = ft;
542 g = gt;
543 h = ht;
544
545 return(*this);
546 }
547
548
549 octonion<T> & operator /= (T const & rhs)
550 {
551 T at = a / rhs; // exception guard
552 T bt = b / rhs; // exception guard
553 T ct = c / rhs; // exception guard
554 T dt = d / rhs; // exception guard
555 T et = e / rhs; // exception guard
556 T ft = f / rhs; // exception guard
557 T gt = g / rhs; // exception guard
558 T ht = h / rhs; // exception guard
559
560 a = at;
561 b = bt;
562 c = ct;
563 d = dt;
564 e = et;
565 f = ft;
566 g = gt;
567 h = ht;
568
569 return(*this);
570 }
571
572
573 octonion<T> & operator /= (::std::complex<T> const & rhs)
574 {
575 T ar = rhs.real();
576 T br = rhs.imag();
577
578 T denominator = ar*ar+br*br;
579
580 T at = (+a*ar-b*br)/denominator;
581 T bt = (-a*br+b*ar)/denominator;
582 T ct = (+c*ar-d*br)/denominator;
583 T dt = (+c*br+d*ar)/denominator;
584 T et = (+e*ar-f*br)/denominator;
585 T ft = (+e*br+f*ar)/denominator;
586 T gt = (+g*ar+h*br)/denominator;
587 T ht = (+g*br+h*ar)/denominator;
588
589 a = at;
590 b = bt;
591 c = ct;
592 d = dt;
593 e = et;
594 f = ft;
595 g = gt;
596 h = ht;
597
598 return(*this);
599 }
600
601
602 octonion<T> & operator /= (::boost::math::quaternion<T> const & rhs)
603 {
604 T ar = rhs.R_component_1();
605 T br = rhs.R_component_2();
606 T cr = rhs.R_component_2();
607 T dr = rhs.R_component_2();
608
609 T denominator = ar*ar+br*br+cr*cr+dr*dr;
610
611 T at = (+a*ar+b*br+c*cr+d*dr)/denominator;
612 T bt = (-a*br+b*ar-c*dr+d*cr)/denominator;
613 T ct = (-a*cr+b*dr+c*ar-d*br)/denominator;
614 T dt = (-a*dr-b*cr+c*br+d*ar)/denominator;
615 T et = (+e*ar-f*br-g*cr-h*dr)/denominator;
616 T ft = (+e*br+f*ar+g*dr-h*cr)/denominator;
617 T gt = (+e*cr-f*dr+g*ar+h*br)/denominator;
618 T ht = (+e*dr+f*cr-g*br+h*ar)/denominator;
619
620 a = at;
621 b = bt;
622 c = ct;
623 d = dt;
624 e = et;
625 f = ft;
626 g = gt;
627 h = ht;
628
629 return(*this);
630 }
631
632
633 template<typename X>
634 octonion<T> & operator /= (octonion<X> const & rhs)
635 {
636 T ar = static_cast<T>(rhs.R_component_1());
637 T br = static_cast<T>(rhs.R_component_2());
638 T cr = static_cast<T>(rhs.R_component_3());
639 T dr = static_cast<T>(rhs.R_component_4());
640 T er = static_cast<T>(rhs.R_component_5());
641 T fr = static_cast<T>(rhs.R_component_6());
642 T gr = static_cast<T>(rhs.R_component_7());
643 T hr = static_cast<T>(rhs.R_component_8());
644
645 T denominator = ar*ar+br*br+cr*cr+dr*dr+er*er+fr*fr+gr*gr+hr*hr;
646
647 T at = (+a*ar+b*br+c*cr+d*dr+e*er+f*fr+g*gr+h*hr)/denominator;
648 T bt = (-a*br+b*ar-c*dr+d*cr-e*fr+f*er+g*hr-h*gr)/denominator;
649 T ct = (-a*cr+b*dr+c*ar-d*br-e*gr-f*hr+g*er+h*fr)/denominator;
650 T dt = (-a*dr-b*cr+c*br+d*ar-e*hr+f*gr-g*fr+h*er)/denominator;
651 T et = (-a*er+b*fr+c*gr+d*hr+e*ar-f*br-g*cr-h*dr)/denominator;
652 T ft = (-a*fr-b*er+c*hr-d*gr+e*br+f*ar+g*dr-h*cr)/denominator;
653 T gt = (-a*gr-b*hr-c*er+d*fr+e*cr-f*dr+g*ar+h*br)/denominator;
654 T ht = (-a*hr+b*gr-c*fr-d*er+e*dr+f*cr-g*br+h*ar)/denominator;
655
656 a = at;
657 b = bt;
658 c = ct;
659 d = dt;
660 e = et;
661 f = ft;
662 g = gt;
663 h = ht;
664
665 return(*this);
666 }
667
668
669 protected:
670
671 BOOST_OCTONION_MEMBER_DATA_GENERATOR(T)
672
673
674 private:
675
676 };
677
678
679 // declaration of octonion specialization
680
681 template<> class octonion<float>;
682 template<> class octonion<double>;
683 template<> class octonion<long double>;
684
685
686 // helper templates for converting copy constructors (declaration)
687
688 namespace detail
689 {
690
691 template< typename T,
692 typename U
693 >
694 octonion<T> octonion_type_converter(octonion<U> const & rhs);
695 }
696
697
698 // implementation of octonion specialization
699
700
701 #define BOOST_OCTONION_CONSTRUCTOR_GENERATOR(type) \
702 explicit octonion( type const & requested_a = static_cast<type>(0), \
703 type const & requested_b = static_cast<type>(0), \
704 type const & requested_c = static_cast<type>(0), \
705 type const & requested_d = static_cast<type>(0), \
706 type const & requested_e = static_cast<type>(0), \
707 type const & requested_f = static_cast<type>(0), \
708 type const & requested_g = static_cast<type>(0), \
709 type const & requested_h = static_cast<type>(0)) \
710 : a(requested_a), \
711 b(requested_b), \
712 c(requested_c), \
713 d(requested_d), \
714 e(requested_e), \
715 f(requested_f), \
716 g(requested_g), \
717 h(requested_h) \
718 { \
719 } \
720 \
721 explicit octonion( ::std::complex<type> const & z0, \
722 ::std::complex<type> const & z1 = ::std::complex<type>(), \
723 ::std::complex<type> const & z2 = ::std::complex<type>(), \
724 ::std::complex<type> const & z3 = ::std::complex<type>()) \
725 : a(z0.real()), \
726 b(z0.imag()), \
727 c(z1.real()), \
728 d(z1.imag()), \
729 e(z2.real()), \
730 f(z2.imag()), \
731 g(z3.real()), \
732 h(z3.imag()) \
733 { \
734 } \
735 \
736 explicit octonion( ::boost::math::quaternion<type> const & q0, \
737 ::boost::math::quaternion<type> const & q1 = ::boost::math::quaternion<type>()) \
738 : a(q0.R_component_1()), \
739 b(q0.R_component_2()), \
740 c(q0.R_component_3()), \
741 d(q0.R_component_4()), \
742 e(q1.R_component_1()), \
743 f(q1.R_component_2()), \
744 g(q1.R_component_3()), \
745 h(q1.R_component_4()) \
746 { \
747 }
748
749
750 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \
751 octonion<type> & operator += (type const & rhs) \
752 { \
753 a += rhs; \
754 \
755 return(*this); \
756 }
757
758 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \
759 octonion<type> & operator += (::std::complex<type> const & rhs) \
760 { \
761 a += rhs.real(); \
762 b += rhs.imag(); \
763 \
764 return(*this); \
765 }
766
767 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \
768 octonion<type> & operator += (::boost::math::quaternion<type> const & rhs) \
769 { \
770 a += rhs.R_component_1(); \
771 b += rhs.R_component_2(); \
772 c += rhs.R_component_3(); \
773 d += rhs.R_component_4(); \
774 \
775 return(*this); \
776 }
777
778 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type) \
779 template<typename X> \
780 octonion<type> & operator += (octonion<X> const & rhs) \
781 { \
782 a += static_cast<type>(rhs.R_component_1()); \
783 b += static_cast<type>(rhs.R_component_2()); \
784 c += static_cast<type>(rhs.R_component_3()); \
785 d += static_cast<type>(rhs.R_component_4()); \
786 e += static_cast<type>(rhs.R_component_5()); \
787 f += static_cast<type>(rhs.R_component_6()); \
788 g += static_cast<type>(rhs.R_component_7()); \
789 h += static_cast<type>(rhs.R_component_8()); \
790 \
791 return(*this); \
792 }
793
794 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \
795 octonion<type> & operator -= (type const & rhs) \
796 { \
797 a -= rhs; \
798 \
799 return(*this); \
800 }
801
802 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \
803 octonion<type> & operator -= (::std::complex<type> const & rhs) \
804 { \
805 a -= rhs.real(); \
806 b -= rhs.imag(); \
807 \
808 return(*this); \
809 }
810
811 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \
812 octonion<type> & operator -= (::boost::math::quaternion<type> const & rhs) \
813 { \
814 a -= rhs.R_component_1(); \
815 b -= rhs.R_component_2(); \
816 c -= rhs.R_component_3(); \
817 d -= rhs.R_component_4(); \
818 \
819 return(*this); \
820 }
821
822 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type) \
823 template<typename X> \
824 octonion<type> & operator -= (octonion<X> const & rhs) \
825 { \
826 a -= static_cast<type>(rhs.R_component_1()); \
827 b -= static_cast<type>(rhs.R_component_2()); \
828 c -= static_cast<type>(rhs.R_component_3()); \
829 d -= static_cast<type>(rhs.R_component_4()); \
830 e -= static_cast<type>(rhs.R_component_5()); \
831 f -= static_cast<type>(rhs.R_component_6()); \
832 g -= static_cast<type>(rhs.R_component_7()); \
833 h -= static_cast<type>(rhs.R_component_8()); \
834 \
835 return(*this); \
836 }
837
838 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \
839 octonion<type> & operator *= (type const & rhs) \
840 { \
841 a *= rhs; \
842 b *= rhs; \
843 c *= rhs; \
844 d *= rhs; \
845 e *= rhs; \
846 f *= rhs; \
847 g *= rhs; \
848 h *= rhs; \
849 \
850 return(*this); \
851 }
852
853 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \
854 octonion<type> & operator *= (::std::complex<type> const & rhs) \
855 { \
856 type ar = rhs.real(); \
857 type br = rhs.imag(); \
858 \
859 type at = +a*ar-b*br; \
860 type bt = +a*br+b*ar; \
861 type ct = +c*ar+d*br; \
862 type dt = -c*br+d*ar; \
863 type et = +e*ar+f*br; \
864 type ft = -e*br+f*ar; \
865 type gt = +g*ar-h*br; \
866 type ht = +g*br+h*ar; \
867 \
868 a = at; \
869 b = bt; \
870 c = ct; \
871 d = dt; \
872 e = et; \
873 f = ft; \
874 g = gt; \
875 h = ht; \
876 \
877 return(*this); \
878 }
879
880 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \
881 octonion<type> & operator *= (::boost::math::quaternion<type> const & rhs) \
882 { \
883 type ar = rhs.R_component_1(); \
884 type br = rhs.R_component_2(); \
885 type cr = rhs.R_component_2(); \
886 type dr = rhs.R_component_2(); \
887 \
888 type at = +a*ar-b*br-c*cr-d*dr; \
889 type bt = +a*br+b*ar+c*dr-d*cr; \
890 type ct = +a*cr-b*dr+c*ar+d*br; \
891 type dt = +a*dr+b*cr-c*br+d*ar; \
892 type et = +e*ar+f*br+g*cr+h*dr; \
893 type ft = -e*br+f*ar-g*dr+h*cr; \
894 type gt = -e*cr+f*dr+g*ar-h*br; \
895 type ht = -e*dr-f*cr+g*br+h*ar; \
896 \
897 a = at; \
898 b = bt; \
899 c = ct; \
900 d = dt; \
901 e = et; \
902 f = ft; \
903 g = gt; \
904 h = ht; \
905 \
906 return(*this); \
907 }
908
909 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type) \
910 template<typename X> \
911 octonion<type> & operator *= (octonion<X> const & rhs) \
912 { \
913 type ar = static_cast<type>(rhs.R_component_1()); \
914 type br = static_cast<type>(rhs.R_component_2()); \
915 type cr = static_cast<type>(rhs.R_component_3()); \
916 type dr = static_cast<type>(rhs.R_component_4()); \
917 type er = static_cast<type>(rhs.R_component_5()); \
918 type fr = static_cast<type>(rhs.R_component_6()); \
919 type gr = static_cast<type>(rhs.R_component_7()); \
920 type hr = static_cast<type>(rhs.R_component_8()); \
921 \
922 type at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr; \
923 type bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr; \
924 type ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr; \
925 type dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er; \
926 type et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr; \
927 type ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr; \
928 type gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br; \
929 type ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar; \
930 \
931 a = at; \
932 b = bt; \
933 c = ct; \
934 d = dt; \
935 e = et; \
936 f = ft; \
937 g = gt; \
938 h = ht; \
939 \
940 return(*this); \
941 }
942
943 // There is quite a lot of repetition in the code below. This is intentional.
944 // The last conditional block is the normal form, and the others merely
945 // consist of workarounds for various compiler deficiencies. Hopefuly, when
946 // more compilers are conformant and we can retire support for those that are
947 // not, we will be able to remove the clutter. This is makes the situation
948 // (painfully) explicit.
949
950 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \
951 octonion<type> & operator /= (type const & rhs) \
952 { \
953 a /= rhs; \
954 b /= rhs; \
955 c /= rhs; \
956 d /= rhs; \
957 \
958 return(*this); \
959 }
960
961 #if defined(__GNUC__) && (__GNUC__ < 3)
962 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
963 octonion<type> & operator /= (::std::complex<type> const & rhs) \
964 { \
965 using ::std::valarray; \
966 \
967 valarray<type> tr(2); \
968 \
969 tr[0] = rhs.real(); \
970 tr[1] = rhs.imag(); \
971 \
972 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
973 \
974 tr *= mixam; \
975 \
976 valarray<type> tt(8); \
977 \
978 tt[0] = +a*tr[0]-b*tr[1]; \
979 tt[1] = -a*tr[1]+b*tr[0]; \
980 tt[2] = +c*tr[0]-d*tr[1]; \
981 tt[3] = +c*tr[1]+d*tr[0]; \
982 tt[4] = +e*tr[0]-f*tr[1]; \
983 tt[5] = +e*tr[1]+f*tr[0]; \
984 tt[6] = +g*tr[0]+h*tr[1]; \
985 tt[7] = +g*tr[1]+h*tr[0]; \
986 \
987 tr *= tr; \
988 \
989 tt *= (mixam/tr.sum()); \
990 \
991 a = tt[0]; \
992 b = tt[1]; \
993 c = tt[2]; \
994 d = tt[3]; \
995 e = tt[4]; \
996 f = tt[5]; \
997 g = tt[6]; \
998 h = tt[7]; \
999 \
1000 return(*this); \
1001 }
1002 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1003 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
1004 octonion<type> & operator /= (::std::complex<type> const & rhs) \
1005 { \
1006 using ::std::valarray; \
1007 using ::std::abs; \
1008 \
1009 valarray<type> tr(2); \
1010 \
1011 tr[0] = rhs.real(); \
1012 tr[1] = rhs.imag(); \
1013 \
1014 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1015 \
1016 tr *= mixam; \
1017 \
1018 valarray<type> tt(8); \
1019 \
1020 tt[0] = +a*tr[0]-b*tr[1]; \
1021 tt[1] = -a*tr[1]+b*tr[0]; \
1022 tt[2] = +c*tr[0]-d*tr[1]; \
1023 tt[3] = +c*tr[1]+d*tr[0]; \
1024 tt[4] = +e*tr[0]-f*tr[1]; \
1025 tt[5] = +e*tr[1]+f*tr[0]; \
1026 tt[6] = +g*tr[0]+h*tr[1]; \
1027 tt[7] = +g*tr[1]+h*tr[0]; \
1028 \
1029 tr *= tr; \
1030 \
1031 tt *= (mixam/tr.sum()); \
1032 \
1033 a = tt[0]; \
1034 b = tt[1]; \
1035 c = tt[2]; \
1036 d = tt[3]; \
1037 e = tt[4]; \
1038 f = tt[5]; \
1039 g = tt[6]; \
1040 h = tt[7]; \
1041 \
1042 return(*this); \
1043 }
1044 #else
1045 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
1046 octonion<type> & operator /= (::std::complex<type> const & rhs) \
1047 { \
1048 using ::std::valarray; \
1049 \
1050 valarray<type> tr(2); \
1051 \
1052 tr[0] = rhs.real(); \
1053 tr[1] = rhs.imag(); \
1054 \
1055 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1056 \
1057 tr *= mixam; \
1058 \
1059 valarray<type> tt(8); \
1060 \
1061 tt[0] = +a*tr[0]-b*tr[1]; \
1062 tt[1] = -a*tr[1]+b*tr[0]; \
1063 tt[2] = +c*tr[0]-d*tr[1]; \
1064 tt[3] = +c*tr[1]+d*tr[0]; \
1065 tt[4] = +e*tr[0]-f*tr[1]; \
1066 tt[5] = +e*tr[1]+f*tr[0]; \
1067 tt[6] = +g*tr[0]+h*tr[1]; \
1068 tt[7] = +g*tr[1]+h*tr[0]; \
1069 \
1070 tr *= tr; \
1071 \
1072 tt *= (mixam/tr.sum()); \
1073 \
1074 a = tt[0]; \
1075 b = tt[1]; \
1076 c = tt[2]; \
1077 d = tt[3]; \
1078 e = tt[4]; \
1079 f = tt[5]; \
1080 g = tt[6]; \
1081 h = tt[7]; \
1082 \
1083 return(*this); \
1084 }
1085 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1086
1087 #if defined(__GNUC__) && (__GNUC__ < 3)
1088 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
1089 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \
1090 { \
1091 using ::std::valarray; \
1092 \
1093 valarray<type> tr(4); \
1094 \
1095 tr[0] = static_cast<type>(rhs.R_component_1()); \
1096 tr[1] = static_cast<type>(rhs.R_component_2()); \
1097 tr[2] = static_cast<type>(rhs.R_component_3()); \
1098 tr[3] = static_cast<type>(rhs.R_component_4()); \
1099 \
1100 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();\
1101 \
1102 tr *= mixam; \
1103 \
1104 valarray<type> tt(8); \
1105 \
1106 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
1107 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
1108 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
1109 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
1110 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
1111 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
1112 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
1113 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
1114 \
1115 tr *= tr; \
1116 \
1117 tt *= (mixam/tr.sum()); \
1118 \
1119 a = tt[0]; \
1120 b = tt[1]; \
1121 c = tt[2]; \
1122 d = tt[3]; \
1123 e = tt[4]; \
1124 f = tt[5]; \
1125 g = tt[6]; \
1126 h = tt[7]; \
1127 \
1128 return(*this); \
1129 }
1130 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1131 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
1132 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \
1133 { \
1134 using ::std::valarray; \
1135 using ::std::abs; \
1136 \
1137 valarray<type> tr(4); \
1138 \
1139 tr[0] = static_cast<type>(rhs.R_component_1()); \
1140 tr[1] = static_cast<type>(rhs.R_component_2()); \
1141 tr[2] = static_cast<type>(rhs.R_component_3()); \
1142 tr[3] = static_cast<type>(rhs.R_component_4()); \
1143 \
1144 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1145 \
1146 tr *= mixam; \
1147 \
1148 valarray<type> tt(8); \
1149 \
1150 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
1151 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
1152 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
1153 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
1154 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
1155 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
1156 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
1157 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
1158 \
1159 tr *= tr; \
1160 \
1161 tt *= (mixam/tr.sum()); \
1162 \
1163 a = tt[0]; \
1164 b = tt[1]; \
1165 c = tt[2]; \
1166 d = tt[3]; \
1167 e = tt[4]; \
1168 f = tt[5]; \
1169 g = tt[6]; \
1170 h = tt[7]; \
1171 \
1172 return(*this); \
1173 }
1174 #else
1175 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
1176 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \
1177 { \
1178 using ::std::valarray; \
1179 \
1180 valarray<type> tr(4); \
1181 \
1182 tr[0] = static_cast<type>(rhs.R_component_1()); \
1183 tr[1] = static_cast<type>(rhs.R_component_2()); \
1184 tr[2] = static_cast<type>(rhs.R_component_3()); \
1185 tr[3] = static_cast<type>(rhs.R_component_4()); \
1186 \
1187 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1188 \
1189 tr *= mixam; \
1190 \
1191 valarray<type> tt(8); \
1192 \
1193 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
1194 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
1195 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
1196 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
1197 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \
1198 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \
1199 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \
1200 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \
1201 \
1202 tr *= tr; \
1203 \
1204 tt *= (mixam/tr.sum()); \
1205 \
1206 a = tt[0]; \
1207 b = tt[1]; \
1208 c = tt[2]; \
1209 d = tt[3]; \
1210 e = tt[4]; \
1211 f = tt[5]; \
1212 g = tt[6]; \
1213 h = tt[7]; \
1214 \
1215 return(*this); \
1216 }
1217 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1218
1219 #if defined(__GNUC__) && (__GNUC__ < 3)
1220 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \
1221 template<typename X> \
1222 octonion<type> & operator /= (octonion<X> const & rhs) \
1223 { \
1224 using ::std::valarray; \
1225 \
1226 valarray<type> tr(8); \
1227 \
1228 tr[0] = static_cast<type>(rhs.R_component_1()); \
1229 tr[1] = static_cast<type>(rhs.R_component_2()); \
1230 tr[2] = static_cast<type>(rhs.R_component_3()); \
1231 tr[3] = static_cast<type>(rhs.R_component_4()); \
1232 tr[4] = static_cast<type>(rhs.R_component_5()); \
1233 tr[5] = static_cast<type>(rhs.R_component_6()); \
1234 tr[6] = static_cast<type>(rhs.R_component_7()); \
1235 tr[7] = static_cast<type>(rhs.R_component_8()); \
1236 \
1237 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();\
1238 \
1239 tr *= mixam; \
1240 \
1241 valarray<type> tt(8); \
1242 \
1243 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]; \
1244 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]; \
1245 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]; \
1246 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]; \
1247 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]; \
1248 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]; \
1249 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]; \
1250 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]; \
1251 \
1252 tr *= tr; \
1253 \
1254 tt *= (mixam/tr.sum()); \
1255 \
1256 a = tt[0]; \
1257 b = tt[1]; \
1258 c = tt[2]; \
1259 d = tt[3]; \
1260 e = tt[4]; \
1261 f = tt[5]; \
1262 g = tt[6]; \
1263 h = tt[7]; \
1264 \
1265 return(*this); \
1266 }
1267 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1268 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \
1269 template<typename X> \
1270 octonion<type> & operator /= (octonion<X> const & rhs) \
1271 { \
1272 using ::std::valarray; \
1273 using ::std::abs; \
1274 \
1275 valarray<type> tr(8); \
1276 \
1277 tr[0] = static_cast<type>(rhs.R_component_1()); \
1278 tr[1] = static_cast<type>(rhs.R_component_2()); \
1279 tr[2] = static_cast<type>(rhs.R_component_3()); \
1280 tr[3] = static_cast<type>(rhs.R_component_4()); \
1281 tr[4] = static_cast<type>(rhs.R_component_5()); \
1282 tr[5] = static_cast<type>(rhs.R_component_6()); \
1283 tr[6] = static_cast<type>(rhs.R_component_7()); \
1284 tr[7] = static_cast<type>(rhs.R_component_8()); \
1285 \
1286 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1287 \
1288 tr *= mixam; \
1289 \
1290 valarray<type> tt(8); \
1291 \
1292 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]; \
1293 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]; \
1294 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]; \
1295 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]; \
1296 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]; \
1297 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]; \
1298 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]; \
1299 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]; \
1300 \
1301 tr *= tr; \
1302 \
1303 tt *= (mixam/tr.sum()); \
1304 \
1305 a = tt[0]; \
1306 b = tt[1]; \
1307 c = tt[2]; \
1308 d = tt[3]; \
1309 e = tt[4]; \
1310 f = tt[5]; \
1311 g = tt[6]; \
1312 h = tt[7]; \
1313 \
1314 return(*this); \
1315 }
1316 #else
1317 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \
1318 template<typename X> \
1319 octonion<type> & operator /= (octonion<X> const & rhs) \
1320 { \
1321 using ::std::valarray; \
1322 \
1323 valarray<type> tr(8); \
1324 \
1325 tr[0] = static_cast<type>(rhs.R_component_1()); \
1326 tr[1] = static_cast<type>(rhs.R_component_2()); \
1327 tr[2] = static_cast<type>(rhs.R_component_3()); \
1328 tr[3] = static_cast<type>(rhs.R_component_4()); \
1329 tr[4] = static_cast<type>(rhs.R_component_5()); \
1330 tr[5] = static_cast<type>(rhs.R_component_6()); \
1331 tr[6] = static_cast<type>(rhs.R_component_7()); \
1332 tr[7] = static_cast<type>(rhs.R_component_8()); \
1333 \
1334 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
1335 \
1336 tr *= mixam; \
1337 \
1338 valarray<type> tt(8); \
1339 \
1340 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]; \
1341 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]; \
1342 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]; \
1343 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]; \
1344 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]; \
1345 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]; \
1346 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]; \
1347 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]; \
1348 \
1349 tr *= tr; \
1350 \
1351 tt *= (mixam/tr.sum()); \
1352 \
1353 a = tt[0]; \
1354 b = tt[1]; \
1355 c = tt[2]; \
1356 d = tt[3]; \
1357 e = tt[4]; \
1358 f = tt[5]; \
1359 g = tt[6]; \
1360 h = tt[7]; \
1361 \
1362 return(*this); \
1363 }
1364 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1365
1366
1367 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \
1368 BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \
1369 BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \
1370 BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \
1371 BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type)
1372
1373 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \
1374 BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \
1375 BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \
1376 BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \
1377 BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type)
1378
1379 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \
1380 BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \
1381 BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \
1382 BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \
1383 BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type)
1384
1385 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR(type) \
1386 BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \
1387 BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \
1388 BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \
1389 BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type)
1390
1391 #define BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(type) \
1392 BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \
1393 BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \
1394 BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \
1395 BOOST_OCTONION_MEMBER_DIV_GENERATOR(type)
1396
1397
1398 template<>
1399 class octonion<float>
1400 {
1401 public:
1402
1403 typedef float value_type;
1404
1405 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(float)
1406
1407 // UNtemplated copy constructor
1408 // (this is taken care of by the compiler itself)
1409
1410 // explicit copy constructors (precision-loosing converters)
1411
1412 explicit octonion(octonion<double> const & a_recopier)
1413 {
1414 *this = detail::octonion_type_converter<float, double>(a_recopier);
1415 }
1416
1417 explicit octonion(octonion<long double> const & a_recopier)
1418 {
1419 *this = detail::octonion_type_converter<float, long double>(a_recopier);
1420 }
1421
1422 // destructor
1423 // (this is taken care of by the compiler itself)
1424
1425 // accessors
1426 //
1427 // Note: Like complex number, octonions do have a meaningful notion of "real part",
1428 // but unlike them there is no meaningful notion of "imaginary part".
1429 // Instead there is an "unreal part" which itself is an octonion, and usually
1430 // nothing simpler (as opposed to the complex number case).
1431 // However, for practicallity, there are accessors for the other components
1432 // (these are necessary for the templated copy constructor, for instance).
1433
1434 BOOST_OCTONION_ACCESSOR_GENERATOR(float)
1435
1436 // assignment operators
1437
1438 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(float)
1439
1440 // other assignment-related operators
1441 //
1442 // NOTE: Octonion multiplication is *NOT* commutative;
1443 // symbolically, "q *= rhs;" means "q = q * rhs;"
1444 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
1445 // octonion multiplication is also *NOT* associative
1446
1447 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(float)
1448
1449
1450 protected:
1451
1452 BOOST_OCTONION_MEMBER_DATA_GENERATOR(float)
1453
1454
1455 private:
1456
1457 };
1458
1459
1460 template<>
1461 class octonion<double>
1462 {
1463 public:
1464
1465 typedef double value_type;
1466
1467 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(double)
1468
1469 // UNtemplated copy constructor
1470 // (this is taken care of by the compiler itself)
1471
1472 // converting copy constructor
1473
1474 explicit octonion(octonion<float> const & a_recopier)
1475 {
1476 *this = detail::octonion_type_converter<double, float>(a_recopier);
1477 }
1478
1479 // explicit copy constructors (precision-loosing converters)
1480
1481 explicit octonion(octonion<long double> const & a_recopier)
1482 {
1483 *this = detail::octonion_type_converter<double, long double>(a_recopier);
1484 }
1485
1486 // destructor
1487 // (this is taken care of by the compiler itself)
1488
1489 // accessors
1490 //
1491 // Note: Like complex number, octonions do have a meaningful notion of "real part",
1492 // but unlike them there is no meaningful notion of "imaginary part".
1493 // Instead there is an "unreal part" which itself is an octonion, and usually
1494 // nothing simpler (as opposed to the complex number case).
1495 // However, for practicallity, there are accessors for the other components
1496 // (these are necessary for the templated copy constructor, for instance).
1497
1498 BOOST_OCTONION_ACCESSOR_GENERATOR(double)
1499
1500 // assignment operators
1501
1502 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(double)
1503
1504 // other assignment-related operators
1505 //
1506 // NOTE: Octonion multiplication is *NOT* commutative;
1507 // symbolically, "q *= rhs;" means "q = q * rhs;"
1508 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
1509 // octonion multiplication is also *NOT* associative
1510
1511 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(double)
1512
1513
1514 protected:
1515
1516 BOOST_OCTONION_MEMBER_DATA_GENERATOR(double)
1517
1518
1519 private:
1520
1521 };
1522
1523
1524 template<>
1525 class octonion<long double>
1526 {
1527 public:
1528
1529 typedef long double value_type;
1530
1531 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(long double)
1532
1533 // UNtemplated copy constructor
1534 // (this is taken care of by the compiler itself)
1535
1536 // converting copy constructor
1537
1538 explicit octonion(octonion<float> const & a_recopier)
1539 {
1540 *this = detail::octonion_type_converter<long double, float>(a_recopier);
1541 }
1542
1543
1544 explicit octonion(octonion<double> const & a_recopier)
1545 {
1546 *this = detail::octonion_type_converter<long double, double>(a_recopier);
1547 }
1548
1549
1550 // destructor
1551 // (this is taken care of by the compiler itself)
1552
1553 // accessors
1554 //
1555 // Note: Like complex number, octonions do have a meaningful notion of "real part",
1556 // but unlike them there is no meaningful notion of "imaginary part".
1557 // Instead there is an "unreal part" which itself is an octonion, and usually
1558 // nothing simpler (as opposed to the complex number case).
1559 // However, for practicallity, there are accessors for the other components
1560 // (these are necessary for the templated copy constructor, for instance).
1561
1562 BOOST_OCTONION_ACCESSOR_GENERATOR(long double)
1563
1564 // assignment operators
1565
1566 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(long double)
1567
1568 // other assignment-related operators
1569 //
1570 // NOTE: Octonion multiplication is *NOT* commutative;
1571 // symbolically, "q *= rhs;" means "q = q * rhs;"
1572 // and "q /= rhs;" means "q = q * inverse_of(rhs);";
1573 // octonion multiplication is also *NOT* associative
1574
1575 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(long double)
1576
1577
1578 protected:
1579
1580 BOOST_OCTONION_MEMBER_DATA_GENERATOR(long double)
1581
1582
1583 private:
1584
1585 };
1586
1587
1588 #undef BOOST_OCTONION_CONSTRUCTOR_GENERATOR
1589
1590 #undef BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR
1591
1592 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR
1593 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR
1594 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR
1595 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR
1596
1597 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_1
1598 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_2
1599 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_3
1600 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_4
1601 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_1
1602 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_2
1603 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_3
1604 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_4
1605 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_1
1606 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_2
1607 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_3
1608 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_4
1609 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_1
1610 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_2
1611 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_3
1612 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_4
1613
1614
1615 #undef BOOST_OCTONION_MEMBER_DATA_GENERATOR
1616
1617 #undef BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR
1618
1619 #undef BOOST_OCTONION_ACCESSOR_GENERATOR
1620
1621
1622 // operators
1623
1624 #define BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) \
1625 { \
1626 octonion<T> res(lhs); \
1627 res op##= rhs; \
1628 return(res); \
1629 }
1630
1631 #define BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \
1632 template<typename T> \
1633 inline octonion<T> operator op (T const & lhs, octonion<T> const & rhs) \
1634 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1635
1636 #define BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \
1637 template<typename T> \
1638 inline octonion<T> operator op (octonion<T> const & lhs, T const & rhs) \
1639 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1640
1641 #define BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \
1642 template<typename T> \
1643 inline octonion<T> operator op (::std::complex<T> const & lhs, octonion<T> const & rhs) \
1644 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1645
1646 #define BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \
1647 template<typename T> \
1648 inline octonion<T> operator op (octonion<T> const & lhs, ::std::complex<T> const & rhs) \
1649 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1650
1651 #define BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \
1652 template<typename T> \
1653 inline octonion<T> operator op (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs) \
1654 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1655
1656 #define BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \
1657 template<typename T> \
1658 inline octonion<T> operator op (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs) \
1659 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1660
1661 #define BOOST_OCTONION_OPERATOR_GENERATOR_4(op) \
1662 template<typename T> \
1663 inline octonion<T> operator op (octonion<T> const & lhs, octonion<T> const & rhs) \
1664 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1665
1666 #define BOOST_OCTONION_OPERATOR_GENERATOR(op) \
1667 BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \
1668 BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \
1669 BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \
1670 BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \
1671 BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \
1672 BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \
1673 BOOST_OCTONION_OPERATOR_GENERATOR_4(op)
1674
1675
1676 BOOST_OCTONION_OPERATOR_GENERATOR(+)
1677 BOOST_OCTONION_OPERATOR_GENERATOR(-)
1678 BOOST_OCTONION_OPERATOR_GENERATOR(*)
1679 BOOST_OCTONION_OPERATOR_GENERATOR(/)
1680
1681
1682 #undef BOOST_OCTONION_OPERATOR_GENERATOR
1683
1684 #undef BOOST_OCTONION_OPERATOR_GENERATOR_1_L
1685 #undef BOOST_OCTONION_OPERATOR_GENERATOR_1_R
1686 #undef BOOST_OCTONION_OPERATOR_GENERATOR_2_L
1687 #undef BOOST_OCTONION_OPERATOR_GENERATOR_2_R
1688 #undef BOOST_OCTONION_OPERATOR_GENERATOR_3_L
1689 #undef BOOST_OCTONION_OPERATOR_GENERATOR_3_R
1690 #undef BOOST_OCTONION_OPERATOR_GENERATOR_4
1691
1692 #undef BOOST_OCTONION_OPERATOR_GENERATOR_BODY
1693
1694
1695 template<typename T>
1696 inline octonion<T> operator + (octonion<T> const & o)
1697 {
1698 return(o);
1699 }
1700
1701
1702 template<typename T>
1703 inline octonion<T> operator - (octonion<T> const & o)
1704 {
1705 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()));
1706 }
1707
1708
1709 template<typename T>
1710 inline bool operator == (T const & lhs, octonion<T> const & rhs)
1711 {
1712 return(
1713 (rhs.R_component_1() == lhs)&&
1714 (rhs.R_component_2() == static_cast<T>(0))&&
1715 (rhs.R_component_3() == static_cast<T>(0))&&
1716 (rhs.R_component_4() == static_cast<T>(0))&&
1717 (rhs.R_component_5() == static_cast<T>(0))&&
1718 (rhs.R_component_6() == static_cast<T>(0))&&
1719 (rhs.R_component_7() == static_cast<T>(0))&&
1720 (rhs.R_component_8() == static_cast<T>(0))
1721 );
1722 }
1723
1724
1725 template<typename T>
1726 inline bool operator == (octonion<T> const & lhs, T const & rhs)
1727 {
1728 return(
1729 (lhs.R_component_1() == rhs)&&
1730 (lhs.R_component_2() == static_cast<T>(0))&&
1731 (lhs.R_component_3() == static_cast<T>(0))&&
1732 (lhs.R_component_4() == static_cast<T>(0))&&
1733 (lhs.R_component_5() == static_cast<T>(0))&&
1734 (lhs.R_component_6() == static_cast<T>(0))&&
1735 (lhs.R_component_7() == static_cast<T>(0))&&
1736 (lhs.R_component_8() == static_cast<T>(0))
1737 );
1738 }
1739
1740
1741 template<typename T>
1742 inline bool operator == (::std::complex<T> const & lhs, octonion<T> const & rhs)
1743 {
1744 return(
1745 (rhs.R_component_1() == lhs.real())&&
1746 (rhs.R_component_2() == lhs.imag())&&
1747 (rhs.R_component_3() == static_cast<T>(0))&&
1748 (rhs.R_component_4() == static_cast<T>(0))&&
1749 (rhs.R_component_5() == static_cast<T>(0))&&
1750 (rhs.R_component_6() == static_cast<T>(0))&&
1751 (rhs.R_component_7() == static_cast<T>(0))&&
1752 (rhs.R_component_8() == static_cast<T>(0))
1753 );
1754 }
1755
1756
1757 template<typename T>
1758 inline bool operator == (octonion<T> const & lhs, ::std::complex<T> const & rhs)
1759 {
1760 return(
1761 (lhs.R_component_1() == rhs.real())&&
1762 (lhs.R_component_2() == rhs.imag())&&
1763 (lhs.R_component_3() == static_cast<T>(0))&&
1764 (lhs.R_component_4() == static_cast<T>(0))&&
1765 (lhs.R_component_5() == static_cast<T>(0))&&
1766 (lhs.R_component_6() == static_cast<T>(0))&&
1767 (lhs.R_component_7() == static_cast<T>(0))&&
1768 (lhs.R_component_8() == static_cast<T>(0))
1769 );
1770 }
1771
1772
1773 template<typename T>
1774 inline bool operator == (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)
1775 {
1776 return(
1777 (rhs.R_component_1() == lhs.R_component_1())&&
1778 (rhs.R_component_2() == lhs.R_component_2())&&
1779 (rhs.R_component_3() == lhs.R_component_3())&&
1780 (rhs.R_component_4() == lhs.R_component_4())&&
1781 (rhs.R_component_5() == static_cast<T>(0))&&
1782 (rhs.R_component_6() == static_cast<T>(0))&&
1783 (rhs.R_component_7() == static_cast<T>(0))&&
1784 (rhs.R_component_8() == static_cast<T>(0))
1785 );
1786 }
1787
1788
1789 template<typename T>
1790 inline bool operator == (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)
1791 {
1792 return(
1793 (lhs.R_component_1() == rhs.R_component_1())&&
1794 (lhs.R_component_2() == rhs.R_component_2())&&
1795 (lhs.R_component_3() == rhs.R_component_3())&&
1796 (lhs.R_component_4() == rhs.R_component_4())&&
1797 (lhs.R_component_5() == static_cast<T>(0))&&
1798 (lhs.R_component_6() == static_cast<T>(0))&&
1799 (lhs.R_component_7() == static_cast<T>(0))&&
1800 (lhs.R_component_8() == static_cast<T>(0))
1801 );
1802 }
1803
1804
1805 template<typename T>
1806 inline bool operator == (octonion<T> const & lhs, octonion<T> const & rhs)
1807 {
1808 return(
1809 (rhs.R_component_1() == lhs.R_component_1())&&
1810 (rhs.R_component_2() == lhs.R_component_2())&&
1811 (rhs.R_component_3() == lhs.R_component_3())&&
1812 (rhs.R_component_4() == lhs.R_component_4())&&
1813 (rhs.R_component_5() == lhs.R_component_5())&&
1814 (rhs.R_component_6() == lhs.R_component_6())&&
1815 (rhs.R_component_7() == lhs.R_component_7())&&
1816 (rhs.R_component_8() == lhs.R_component_8())
1817 );
1818 }
1819
1820
1821 #define BOOST_OCTONION_NOT_EQUAL_GENERATOR \
1822 { \
1823 return(!(lhs == rhs)); \
1824 }
1825
1826 template<typename T>
1827 inline bool operator != (T const & lhs, octonion<T> const & rhs)
1828 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1829
1830 template<typename T>
1831 inline bool operator != (octonion<T> const & lhs, T const & rhs)
1832 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1833
1834 template<typename T>
1835 inline bool operator != (::std::complex<T> const & lhs, octonion<T> const & rhs)
1836 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1837
1838 template<typename T>
1839 inline bool operator != (octonion<T> const & lhs, ::std::complex<T> const & rhs)
1840 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1841
1842 template<typename T>
1843 inline bool operator != (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)
1844 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1845
1846 template<typename T>
1847 inline bool operator != (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)
1848 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1849
1850 template<typename T>
1851 inline bool operator != (octonion<T> const & lhs, octonion<T> const & rhs)
1852 BOOST_OCTONION_NOT_EQUAL_GENERATOR
1853
1854 #undef BOOST_OCTONION_NOT_EQUAL_GENERATOR
1855
1856
1857 // Note: the default values in the constructors of the complex and quaternions make for
1858 // a very complex and ambiguous situation; we have made choices to disambiguate.
1859
1860 #if BOOST_WORKAROUND(__GNUC__, < 3)
1861 template<typename T>
1862 ::std::istream & operator >> ( ::std::istream & is,
1863 octonion<T>& o)
1864 #else
1865 template<typename T, typename charT, class traits>
1866 ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
1867 octonion<T> & o)
1868 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1869 {
1870 #if BOOST_WORKAROUND(__GNUC__, < 3)
1871 typedef char charT;
1872 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1873
1874 #ifdef BOOST_NO_STD_LOCALE
1875 #else
1876 const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
1877 #endif /* BOOST_NO_STD_LOCALE */
1878
1879 T a = T();
1880 T b = T();
1881 T c = T();
1882 T d = T();
1883 T e = T();
1884 T f = T();
1885 T g = T();
1886 T h = T();
1887
1888 ::std::complex<T> u = ::std::complex<T>();
1889 ::std::complex<T> v = ::std::complex<T>();
1890 ::std::complex<T> x = ::std::complex<T>();
1891 ::std::complex<T> y = ::std::complex<T>();
1892
1893 ::boost::math::quaternion<T> p = ::boost::math::quaternion<T>();
1894 ::boost::math::quaternion<T> q = ::boost::math::quaternion<T>();
1895
1896 charT ch = charT();
1897 char cc;
1898
1899 is >> ch; // get the first lexeme
1900
1901 if (!is.good()) goto finish;
1902
1903 #ifdef BOOST_NO_STD_LOCALE
1904 cc = ch;
1905 #else
1906 cc = ct.narrow(ch, char());
1907 #endif /* BOOST_NO_STD_LOCALE */
1908
1909 if (cc == '(') // read "("
1910 {
1911 is >> ch; // get the second lexeme
1912
1913 if (!is.good()) goto finish;
1914
1915 #ifdef BOOST_NO_STD_LOCALE
1916 cc = ch;
1917 #else
1918 cc = ct.narrow(ch, char());
1919 #endif /* BOOST_NO_STD_LOCALE */
1920
1921 if (cc == '(') // read "(("
1922 {
1923 is >> ch; // get the third lexeme
1924
1925 if (!is.good()) goto finish;
1926
1927 #ifdef BOOST_NO_STD_LOCALE
1928 cc = ch;
1929 #else
1930 cc = ct.narrow(ch, char());
1931 #endif /* BOOST_NO_STD_LOCALE */
1932
1933 if (cc == '(') // read "((("
1934 {
1935 is.putback(ch);
1936
1937 is >> u; // read "((u"
1938
1939 if (!is.good()) goto finish;
1940
1941 is >> ch; // get the next lexeme
1942
1943 if (!is.good()) goto finish;
1944
1945 #ifdef BOOST_NO_STD_LOCALE
1946 cc = ch;
1947 #else
1948 cc = ct.narrow(ch, char());
1949 #endif /* BOOST_NO_STD_LOCALE */
1950
1951 if (cc == ')') // read "((u)"
1952 {
1953 is >> ch; // get the next lexeme
1954
1955 if (!is.good()) goto finish;
1956
1957 #ifdef BOOST_NO_STD_LOCALE
1958 cc = ch;
1959 #else
1960 cc = ct.narrow(ch, char());
1961 #endif /* BOOST_NO_STD_LOCALE */
1962
1963 if (cc == ')') // format: (((a))), (((a,b)))
1964 {
1965 o = octonion<T>(u);
1966 }
1967 else if (cc == ',') // read "((u),"
1968 {
1969 p = ::boost::math::quaternion<T>(u);
1970
1971 is >> q; // read "((u),q"
1972
1973 if (!is.good()) goto finish;
1974
1975 is >> ch; // get the next lexeme
1976
1977 if (!is.good()) goto finish;
1978
1979 #ifdef BOOST_NO_STD_LOCALE
1980 cc = ch;
1981 #else
1982 cc = ct.narrow(ch, char());
1983 #endif /* BOOST_NO_STD_LOCALE */
1984
1985 if (cc == ')') // format: (((a)),q), (((a,b)),q)
1986 {
1987 o = octonion<T>(p,q);
1988 }
1989 else // error
1990 {
1991 #if BOOST_WORKAROUND(__GNUC__, < 3)
1992 is.setstate(::std::ios::failbit);
1993 #else
1994 is.setstate(::std::ios_base::failbit);
1995 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
1996 }
1997 }
1998 else // error
1999 {
2000 #if BOOST_WORKAROUND(__GNUC__, < 3)
2001 is.setstate(::std::ios::failbit);
2002 #else
2003 is.setstate(::std::ios_base::failbit);
2004 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2005 }
2006 }
2007 else if (cc ==',') // read "((u,"
2008 {
2009 is >> v; // read "((u,v"
2010
2011 if (!is.good()) goto finish;
2012
2013 is >> ch; // get the next lexeme
2014
2015 if (!is.good()) goto finish;
2016
2017 #ifdef BOOST_NO_STD_LOCALE
2018 cc = ch;
2019 #else
2020 cc = ct.narrow(ch, char());
2021 #endif /* BOOST_NO_STD_LOCALE */
2022
2023 if (cc == ')') // read "((u,v)"
2024 {
2025 p = ::boost::math::quaternion<T>(u,v);
2026
2027 is >> ch; // get the next lexeme
2028
2029 if (!is.good()) goto finish;
2030
2031 #ifdef BOOST_NO_STD_LOCALE
2032 cc = ch;
2033 #else
2034 cc = ct.narrow(ch, char());
2035 #endif /* BOOST_NO_STD_LOCALE */
2036
2037 if (cc == ')') // format: (((a),v)), (((a,b),v))
2038 {
2039 o = octonion<T>(p);
2040 }
2041 else if (cc == ',') // read "((u,v),"
2042 {
2043 is >> q; // read "(p,q"
2044
2045 if (!is.good()) goto finish;
2046
2047 is >> ch; // get the next lexeme
2048
2049 if (!is.good()) goto finish;
2050
2051 #ifdef BOOST_NO_STD_LOCALE
2052 cc = ch;
2053 #else
2054 cc = ct.narrow(ch, char());
2055 #endif /* BOOST_NO_STD_LOCALE */
2056
2057 if (cc == ')') // format: (((a),v),q), (((a,b),v),q)
2058 {
2059 o = octonion<T>(p,q);
2060 }
2061 else // error
2062 {
2063 #if BOOST_WORKAROUND(__GNUC__, < 3)
2064 is.setstate(::std::ios::failbit);
2065 #else
2066 is.setstate(::std::ios_base::failbit);
2067 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2068 }
2069 }
2070 else // error
2071 {
2072 #if BOOST_WORKAROUND(__GNUC__, < 3)
2073 is.setstate(::std::ios::failbit);
2074 #else
2075 is.setstate(::std::ios_base::failbit);
2076 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2077 }
2078 }
2079 else // error
2080 {
2081 #if BOOST_WORKAROUND(__GNUC__, < 3)
2082 is.setstate(::std::ios::failbit);
2083 #else
2084 is.setstate(::std::ios_base::failbit);
2085 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2086 }
2087 }
2088 else // error
2089 {
2090 #if BOOST_WORKAROUND(__GNUC__, < 3)
2091 is.setstate(::std::ios::failbit);
2092 #else
2093 is.setstate(::std::ios_base::failbit);
2094 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2095 }
2096 }
2097 else // read "((a"
2098 {
2099 is.putback(ch);
2100
2101 is >> a; // we extract the first component
2102
2103 if (!is.good()) goto finish;
2104
2105 is >> ch; // get the next lexeme
2106
2107 if (!is.good()) goto finish;
2108
2109 #ifdef BOOST_NO_STD_LOCALE
2110 cc = ch;
2111 #else
2112 cc = ct.narrow(ch, char());
2113 #endif /* BOOST_NO_STD_LOCALE */
2114
2115 if (cc == ')') // read "((a)"
2116 {
2117 is >> ch; // get the next lexeme
2118
2119 if (!is.good()) goto finish;
2120
2121 #ifdef BOOST_NO_STD_LOCALE
2122 cc = ch;
2123 #else
2124 cc = ct.narrow(ch, char());
2125 #endif /* BOOST_NO_STD_LOCALE */
2126
2127 if (cc == ')') // read "((a))"
2128 {
2129 o = octonion<T>(a);
2130 }
2131 else if (cc == ',') // read "((a),"
2132 {
2133 is >> ch; // get the next lexeme
2134
2135 if (!is.good()) goto finish;
2136
2137 #ifdef BOOST_NO_STD_LOCALE
2138 cc = ch;
2139 #else
2140 cc = ct.narrow(ch, char());
2141 #endif /* BOOST_NO_STD_LOCALE */
2142
2143 if (cc == '(') // read "((a),("
2144 {
2145 is >> ch; // get the next lexeme
2146
2147 if (!is.good()) goto finish;
2148
2149 #ifdef BOOST_NO_STD_LOCALE
2150 cc = ch;
2151 #else
2152 cc = ct.narrow(ch, char());
2153 #endif /* BOOST_NO_STD_LOCALE */
2154
2155 if (cc == '(') // read "((a),(("
2156 {
2157 is.putback(ch);
2158
2159 is.putback(ch); // we backtrack twice, with the same value!
2160
2161 is >> q; // read "((a),q"
2162
2163 if (!is.good()) goto finish;
2164
2165 is >> ch; // get the next lexeme
2166
2167 if (!is.good()) goto finish;
2168
2169 #ifdef BOOST_NO_STD_LOCALE
2170 cc = ch;
2171 #else
2172 cc = ct.narrow(ch, char());
2173 #endif /* BOOST_NO_STD_LOCALE */
2174
2175 if (cc == ')') // read "((a),q)"
2176 {
2177 p = ::boost::math::quaternion<T>(a);
2178
2179 o = octonion<T>(p,q);
2180 }
2181 else // error
2182 {
2183 #if BOOST_WORKAROUND(__GNUC__, < 3)
2184 is.setstate(::std::ios::failbit);
2185 #else
2186 is.setstate(::std::ios_base::failbit);
2187 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2188 }
2189 }
2190 else // read "((a),(c" or "((a),(e"
2191 {
2192 is.putback(ch);
2193
2194 is >> c;
2195
2196 if (!is.good()) goto finish;
2197
2198 is >> ch; // get the next lexeme
2199
2200 if (!is.good()) goto finish;
2201
2202 #ifdef BOOST_NO_STD_LOCALE
2203 cc = ch;
2204 #else
2205 cc = ct.narrow(ch, char());
2206 #endif /* BOOST_NO_STD_LOCALE */
2207
2208 if (cc == ')') // read "((a),(c)" (ambiguity resolution)
2209 {
2210 is >> ch; // get the next lexeme
2211
2212 if (!is.good()) goto finish;
2213
2214 #ifdef BOOST_NO_STD_LOCALE
2215 cc = ch;
2216 #else
2217 cc = ct.narrow(ch, char());
2218 #endif /* BOOST_NO_STD_LOCALE */
2219
2220 if (cc == ')') // read "((a),(c))"
2221 {
2222 o = octonion<T>(a,b,c);
2223 }
2224 else if (cc == ',') // read "((a),(c),"
2225 {
2226 u = ::std::complex<T>(a);
2227
2228 v = ::std::complex<T>(c);
2229
2230 is >> x; // read "((a),(c),x"
2231
2232 if (!is.good()) goto finish;
2233
2234 is >> ch; // get the next lexeme
2235
2236 if (!is.good()) goto finish;
2237
2238 #ifdef BOOST_NO_STD_LOCALE
2239 cc = ch;
2240 #else
2241 cc = ct.narrow(ch, char());
2242 #endif /* BOOST_NO_STD_LOCALE */
2243
2244 if (cc == ')') // read "((a),(c),x)"
2245 {
2246 o = octonion<T>(u,v,x);
2247 }
2248 else if (cc == ',') // read "((a),(c),x,"
2249 {
2250 is >> y; // read "((a),(c),x,y"
2251
2252 if (!is.good()) goto finish;
2253
2254 is >> ch; // get the next lexeme
2255
2256 if (!is.good()) goto finish;
2257
2258 #ifdef BOOST_NO_STD_LOCALE
2259 cc = ch;
2260 #else
2261 cc = ct.narrow(ch, char());
2262 #endif /* BOOST_NO_STD_LOCALE */
2263
2264 if (cc == ')') // read "((a),(c),x,y)"
2265 {
2266 o = octonion<T>(u,v,x,y);
2267 }
2268 else // error
2269 {
2270 #if BOOST_WORKAROUND(__GNUC__, < 3)
2271 is.setstate(::std::ios::failbit);
2272 #else
2273 is.setstate(::std::ios_base::failbit);
2274 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2275 }
2276 }
2277 else // error
2278 {
2279 #if BOOST_WORKAROUND(__GNUC__, < 3)
2280 is.setstate(::std::ios::failbit);
2281 #else
2282 is.setstate(::std::ios_base::failbit);
2283 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2284 }
2285 }
2286 else // error
2287 {
2288 #if BOOST_WORKAROUND(__GNUC__, < 3)
2289 is.setstate(::std::ios::failbit);
2290 #else
2291 is.setstate(::std::ios_base::failbit);
2292 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2293 }
2294 }
2295 else if (cc == ',') // read "((a),(c," or "((a),(e,"
2296 {
2297 is >> ch; // get the next lexeme
2298
2299 if (!is.good()) goto finish;
2300
2301 #ifdef BOOST_NO_STD_LOCALE
2302 cc = ch;
2303 #else
2304 cc = ct.narrow(ch, char());
2305 #endif /* BOOST_NO_STD_LOCALE */
2306
2307 if (cc == '(') // read "((a),(e,(" (ambiguity resolution)
2308 {
2309 p = ::boost::math::quaternion<T>(a);
2310
2311 x = ::std::complex<T>(c); // "c" was actually "e"
2312
2313 is.putback(ch); // we can only backtrace once
2314
2315 is >> y; // read "((a),(e,y"
2316
2317 if (!is.good()) goto finish;
2318
2319 is >> ch; // get the next lexeme
2320
2321 #ifdef BOOST_NO_STD_LOCALE
2322 cc = ch;
2323 #else
2324 cc = ct.narrow(ch, char());
2325 #endif /* BOOST_NO_STD_LOCALE */
2326
2327 if (cc == ')') // read "((a),(e,y)"
2328 {
2329 q = ::boost::math::quaternion<T>(x,y);
2330
2331 is >> ch; // get the next lexeme
2332
2333 #ifdef BOOST_NO_STD_LOCALE
2334 cc = ch;
2335 #else
2336 cc = ct.narrow(ch, char());
2337 #endif /* BOOST_NO_STD_LOCALE */
2338
2339 if (cc == ')') // read "((a),(e,y))"
2340 {
2341 o = octonion<T>(p,q);
2342 }
2343 else // error
2344 {
2345 #if BOOST_WORKAROUND(__GNUC__, < 3)
2346 is.setstate(::std::ios::failbit);
2347 #else
2348 is.setstate(::std::ios_base::failbit);
2349 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2350 }
2351 }
2352 else // error
2353 {
2354 #if BOOST_WORKAROUND(__GNUC__, < 3)
2355 is.setstate(::std::ios::failbit);
2356 #else
2357 is.setstate(::std::ios_base::failbit);
2358 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2359 }
2360 }
2361 else // read "((a),(c,d" or "((a),(e,f"
2362 {
2363 is.putback(ch);
2364
2365 is >> d;
2366
2367 if (!is.good()) goto finish;
2368
2369 is >> ch; // get the next lexeme
2370
2371 if (!is.good()) goto finish;
2372
2373 #ifdef BOOST_NO_STD_LOCALE
2374 cc = ch;
2375 #else
2376 cc = ct.narrow(ch, char());
2377 #endif /* BOOST_NO_STD_LOCALE */
2378
2379 if (cc == ')') // read "((a),(c,d)" (ambiguity resolution)
2380 {
2381 is >> ch; // get the next lexeme
2382
2383 if (!is.good()) goto finish;
2384
2385 #ifdef BOOST_NO_STD_LOCALE
2386 cc = ch;
2387 #else
2388 cc = ct.narrow(ch, char());
2389 #endif /* BOOST_NO_STD_LOCALE */
2390
2391 if (cc == ')') // read "((a),(c,d))"
2392 {
2393 o = octonion<T>(a,b,c,d);
2394 }
2395 else if (cc == ',') // read "((a),(c,d),"
2396 {
2397 u = ::std::complex<T>(a);
2398
2399 v = ::std::complex<T>(c,d);
2400
2401 is >> x; // read "((a),(c,d),x"
2402
2403 if (!is.good()) goto finish;
2404
2405 is >> ch; // get the next lexeme
2406
2407 if (!is.good()) goto finish;
2408
2409 #ifdef BOOST_NO_STD_LOCALE
2410 cc = ch;
2411 #else
2412 cc = ct.narrow(ch, char());
2413 #endif /* BOOST_NO_STD_LOCALE */
2414
2415 if (cc == ')') // read "((a),(c,d),x)"
2416 {
2417 o = octonion<T>(u,v,x);
2418 }
2419 else if (cc == ',') // read "((a),(c,d),x,"
2420 {
2421 is >> y; // read "((a),(c,d),x,y"
2422
2423 if (!is.good()) goto finish;
2424
2425 is >> ch; // get the next lexeme
2426
2427 if (!is.good()) goto finish;
2428
2429 #ifdef BOOST_NO_STD_LOCALE
2430 cc = ch;
2431 #else
2432 cc = ct.narrow(ch, char());
2433 #endif /* BOOST_NO_STD_LOCALE */
2434
2435 if (cc == ')') // read "((a),(c,d),x,y)"
2436 {
2437 o = octonion<T>(u,v,x,y);
2438 }
2439 else // error
2440 {
2441 #if BOOST_WORKAROUND(__GNUC__, < 3)
2442 is.setstate(::std::ios::failbit);
2443 #else
2444 is.setstate(::std::ios_base::failbit);
2445 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2446 }
2447 }
2448 else // error
2449 {
2450 #if BOOST_WORKAROUND(__GNUC__, < 3)
2451 is.setstate(::std::ios::failbit);
2452 #else
2453 is.setstate(::std::ios_base::failbit);
2454 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2455 }
2456 }
2457 else // error
2458 {
2459 #if BOOST_WORKAROUND(__GNUC__, < 3)
2460 is.setstate(::std::ios::failbit);
2461 #else
2462 is.setstate(::std::ios_base::failbit);
2463 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2464 }
2465 }
2466 else if (cc == ',') // read "((a),(e,f," (ambiguity resolution)
2467 {
2468 p = ::boost::math::quaternion<T>(a);
2469
2470 is >> g; // read "((a),(e,f,g" (too late to backtrack)
2471
2472 if (!is.good()) goto finish;
2473
2474 is >> ch; // get the next lexeme
2475
2476 if (!is.good()) goto finish;
2477
2478 #ifdef BOOST_NO_STD_LOCALE
2479 cc = ch;
2480 #else
2481 cc = ct.narrow(ch, char());
2482 #endif /* BOOST_NO_STD_LOCALE */
2483
2484 if (cc == ')') // read "((a),(e,f,g)"
2485 {
2486 q = ::boost::math::quaternion<T>(c,d,g); // "c" was actually "e", and "d" was actually "f"
2487
2488 is >> ch; // get the next lexeme
2489
2490 if (!is.good()) goto finish;
2491
2492 #ifdef BOOST_NO_STD_LOCALE
2493 cc = ch;
2494 #else
2495 cc = ct.narrow(ch, char());
2496 #endif /* BOOST_NO_STD_LOCALE */
2497
2498 if (cc == ')') // read "((a),(e,f,g))"
2499 {
2500 o = octonion<T>(p,q);
2501 }
2502 else // error
2503 {
2504 #if BOOST_WORKAROUND(__GNUC__, < 3)
2505 is.setstate(::std::ios::failbit);
2506 #else
2507 is.setstate(::std::ios_base::failbit);
2508 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2509 }
2510 }
2511 else if (cc == ',') // read "((a),(e,f,g,"
2512 {
2513 is >> h; // read "((a),(e,f,g,h"
2514
2515 if (!is.good()) goto finish;
2516
2517 is >> ch; // get the next lexeme
2518
2519 if (!is.good()) goto finish;
2520
2521 #ifdef BOOST_NO_STD_LOCALE
2522 cc = ch;
2523 #else
2524 cc = ct.narrow(ch, char());
2525 #endif /* BOOST_NO_STD_LOCALE */
2526
2527 if (cc == ')') // read "((a),(e,f,g,h)"
2528 {
2529 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" was actually "e", and "d" was actually "f"
2530
2531 is >> ch; // get the next lexeme
2532
2533 if (!is.good()) goto finish;
2534
2535 #ifdef BOOST_NO_STD_LOCALE
2536 cc = ch;
2537 #else
2538 cc = ct.narrow(ch, char());
2539 #endif /* BOOST_NO_STD_LOCALE */
2540
2541 if (cc == ')') // read "((a),(e,f,g,h))"
2542 {
2543 o = octonion<T>(p,q);
2544 }
2545 else // error
2546 {
2547 #if BOOST_WORKAROUND(__GNUC__, < 3)
2548 is.setstate(::std::ios::failbit);
2549 #else
2550 is.setstate(::std::ios_base::failbit);
2551 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2552 }
2553 }
2554 else // error
2555 {
2556 #if BOOST_WORKAROUND(__GNUC__, < 3)
2557 is.setstate(::std::ios::failbit);
2558 #else
2559 is.setstate(::std::ios_base::failbit);
2560 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2561 }
2562 }
2563 else // error
2564 {
2565 #if BOOST_WORKAROUND(__GNUC__, < 3)
2566 is.setstate(::std::ios::failbit);
2567 #else
2568 is.setstate(::std::ios_base::failbit);
2569 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2570 }
2571 }
2572 else // error
2573 {
2574 #if BOOST_WORKAROUND(__GNUC__, < 3)
2575 is.setstate(::std::ios::failbit);
2576 #else
2577 is.setstate(::std::ios_base::failbit);
2578 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2579 }
2580 }
2581 }
2582 else // error
2583 {
2584 #if BOOST_WORKAROUND(__GNUC__, < 3)
2585 is.setstate(::std::ios::failbit);
2586 #else
2587 is.setstate(::std::ios_base::failbit);
2588 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2589 }
2590 }
2591 }
2592 else // read "((a),c" (ambiguity resolution)
2593 {
2594 is.putback(ch);
2595
2596 is >> c; // we extract the third component
2597
2598 if (!is.good()) goto finish;
2599
2600 is >> ch; // get the next lexeme
2601
2602 if (!is.good()) goto finish;
2603
2604 #ifdef BOOST_NO_STD_LOCALE
2605 cc = ch;
2606 #else
2607 cc = ct.narrow(ch, char());
2608 #endif /* BOOST_NO_STD_LOCALE */
2609
2610 if (cc == ')') // read "((a),c)"
2611 {
2612 o = octonion<T>(a,b,c);
2613 }
2614 else if (cc == ',') // read "((a),c,"
2615 {
2616 is >> x; // read "((a),c,x"
2617
2618 if (!is.good()) goto finish;
2619
2620 is >> ch; // get the next lexeme
2621
2622 if (!is.good()) goto finish;
2623
2624 #ifdef BOOST_NO_STD_LOCALE
2625 cc = ch;
2626 #else
2627 cc = ct.narrow(ch, char());
2628 #endif /* BOOST_NO_STD_LOCALE */
2629
2630 if (cc == ')') // read "((a),c,x)"
2631 {
2632 o = octonion<T>(a,b,c,d,x.real(),x.imag());
2633 }
2634 else if (cc == ',') // read "((a),c,x,"
2635 {
2636 is >> y;if (!is.good()) goto finish; // read "((a),c,x,y"
2637
2638 is >> ch; // get the next lexeme
2639
2640 if (!is.good()) goto finish;
2641
2642 #ifdef BOOST_NO_STD_LOCALE
2643 cc = ch;
2644 #else
2645 cc = ct.narrow(ch, char());
2646 #endif /* BOOST_NO_STD_LOCALE */
2647
2648 if (cc == ')') // read "((a),c,x,y)"
2649 {
2650 o = octonion<T>(a,b,c,d,x.real(),x.imag(),y.real(),y.imag());
2651 }
2652 else // error
2653 {
2654 #if BOOST_WORKAROUND(__GNUC__, < 3)
2655 is.setstate(::std::ios::failbit);
2656 #else
2657 is.setstate(::std::ios_base::failbit);
2658 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2659 }
2660 }
2661 else // error
2662 {
2663 #if BOOST_WORKAROUND(__GNUC__, < 3)
2664 is.setstate(::std::ios::failbit);
2665 #else
2666 is.setstate(::std::ios_base::failbit);
2667 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2668 }
2669 }
2670 else // error
2671 {
2672 #if BOOST_WORKAROUND(__GNUC__, < 3)
2673 is.setstate(::std::ios::failbit);
2674 #else
2675 is.setstate(::std::ios_base::failbit);
2676 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2677 }
2678 }
2679 }
2680 else // error
2681 {
2682 #if BOOST_WORKAROUND(__GNUC__, < 3)
2683 is.setstate(::std::ios::failbit);
2684 #else
2685 is.setstate(::std::ios_base::failbit);
2686 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2687 }
2688 }
2689 else if (cc ==',') // read "((a,"
2690 {
2691 is >> ch; // get the next lexeme
2692
2693 if (!is.good()) goto finish;
2694
2695 #ifdef BOOST_NO_STD_LOCALE
2696 cc = ch;
2697 #else
2698 cc = ct.narrow(ch, char());
2699 #endif /* BOOST_NO_STD_LOCALE */
2700
2701 if (cc == '(') // read "((a,("
2702 {
2703 u = ::std::complex<T>(a);
2704
2705 is.putback(ch); // can only backtrack so much
2706
2707 is >> v; // read "((a,v"
2708
2709 if (!is.good()) goto finish;
2710
2711 is >> ch; // get the next lexeme
2712
2713 if (!is.good()) goto finish;
2714
2715 #ifdef BOOST_NO_STD_LOCALE
2716 cc = ch;
2717 #else
2718 cc = ct.narrow(ch, char());
2719 #endif /* BOOST_NO_STD_LOCALE */
2720
2721 if (cc == ')') // read "((a,v)"
2722 {
2723 is >> ch; // get the next lexeme
2724
2725 if (!is.good()) goto finish;
2726
2727 #ifdef BOOST_NO_STD_LOCALE
2728 cc = ch;
2729 #else
2730 cc = ct.narrow(ch, char());
2731 #endif /* BOOST_NO_STD_LOCALE */
2732
2733 if (cc == ')') // read "((a,v))"
2734 {
2735 o = octonion<T>(u,v);
2736 }
2737 else if (cc == ',') // read "((a,v),"
2738 {
2739 p = ::boost::math::quaternion<T>(u,v);
2740
2741 is >> q; // read "((a,v),q"
2742
2743 if (!is.good()) goto finish;
2744
2745 is >> ch; // get the next lexeme
2746
2747 if (!is.good()) goto finish;
2748
2749 #ifdef BOOST_NO_STD_LOCALE
2750 cc = ch;
2751 #else
2752 cc = ct.narrow(ch, char());
2753 #endif /* BOOST_NO_STD_LOCALE */
2754
2755 if (cc == ')') // read "((a,v),q)"
2756 {
2757 o = octonion<T>(p,q);
2758 }
2759 else // error
2760 {
2761 #if BOOST_WORKAROUND(__GNUC__, < 3)
2762 is.setstate(::std::ios::failbit);
2763 #else
2764 is.setstate(::std::ios_base::failbit);
2765 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2766 }
2767 }
2768 else // error
2769 {
2770 #if BOOST_WORKAROUND(__GNUC__, < 3)
2771 is.setstate(::std::ios::failbit);
2772 #else
2773 is.setstate(::std::ios_base::failbit);
2774 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2775 }
2776 }
2777 else // error
2778 {
2779 #if BOOST_WORKAROUND(__GNUC__, < 3)
2780 is.setstate(::std::ios::failbit);
2781 #else
2782 is.setstate(::std::ios_base::failbit);
2783 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2784 }
2785 }
2786 else
2787 {
2788 is.putback(ch);
2789
2790 is >> b; // read "((a,b"
2791
2792 if (!is.good()) goto finish;
2793
2794 is >> ch; // get the next lexeme
2795
2796 if (!is.good()) goto finish;
2797
2798 #ifdef BOOST_NO_STD_LOCALE
2799 cc = ch;
2800 #else
2801 cc = ct.narrow(ch, char());
2802 #endif /* BOOST_NO_STD_LOCALE */
2803
2804 if (cc == ')') // read "((a,b)"
2805 {
2806 is >> ch; // get the next lexeme
2807
2808 if (!is.good()) goto finish;
2809
2810 #ifdef BOOST_NO_STD_LOCALE
2811 cc = ch;
2812 #else
2813 cc = ct.narrow(ch, char());
2814 #endif /* BOOST_NO_STD_LOCALE */
2815
2816 if (cc == ')') // read "((a,b))"
2817 {
2818 o = octonion<T>(a,b);
2819 }
2820 else if (cc == ',') // read "((a,b),"
2821 {
2822 is >> ch; // get the next lexeme
2823
2824 if (!is.good()) goto finish;
2825
2826 #ifdef BOOST_NO_STD_LOCALE
2827 cc = ch;
2828 #else
2829 cc = ct.narrow(ch, char());
2830 #endif /* BOOST_NO_STD_LOCALE */
2831
2832 if (cc == '(') // read "((a,b),("
2833 {
2834 is >> ch; // get the next lexeme
2835
2836 if (!is.good()) goto finish;
2837
2838 #ifdef BOOST_NO_STD_LOCALE
2839 cc = ch;
2840 #else
2841 cc = ct.narrow(ch, char());
2842 #endif /* BOOST_NO_STD_LOCALE */
2843
2844 if (cc == '(') // read "((a,b),(("
2845 {
2846 p = ::boost::math::quaternion<T>(a,b);
2847
2848 is.putback(ch);
2849
2850 is.putback(ch); // we backtrack twice, with the same value
2851
2852 is >> q; // read "((a,b),q"
2853
2854 if (!is.good()) goto finish;
2855
2856 is >> ch; // get the next lexeme
2857
2858 if (!is.good()) goto finish;
2859
2860 #ifdef BOOST_NO_STD_LOCALE
2861 cc = ch;
2862 #else
2863 cc = ct.narrow(ch, char());
2864 #endif /* BOOST_NO_STD_LOCALE */
2865
2866 if (cc == ')') // read "((a,b),q)"
2867 {
2868 o = octonion<T>(p,q);
2869 }
2870 else // error
2871 {
2872 #if BOOST_WORKAROUND(__GNUC__, < 3)
2873 is.setstate(::std::ios::failbit);
2874 #else
2875 is.setstate(::std::ios_base::failbit);
2876 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2877 }
2878 }
2879 else // read "((a,b),(c" or "((a,b),(e"
2880 {
2881 is.putback(ch);
2882
2883 is >> c;
2884
2885 if (!is.good()) goto finish;
2886
2887 is >> ch; // get the next lexeme
2888
2889 if (!is.good()) goto finish;
2890
2891 #ifdef BOOST_NO_STD_LOCALE
2892 cc = ch;
2893 #else
2894 cc = ct.narrow(ch, char());
2895 #endif /* BOOST_NO_STD_LOCALE */
2896
2897 if (cc == ')') // read "((a,b),(c)" (ambiguity resolution)
2898 {
2899 is >> ch; // get the next lexeme
2900
2901 if (!is.good()) goto finish;
2902
2903 #ifdef BOOST_NO_STD_LOCALE
2904 cc = ch;
2905 #else
2906 cc = ct.narrow(ch, char());
2907 #endif /* BOOST_NO_STD_LOCALE */
2908
2909 if (cc == ')') // read "((a,b),(c))"
2910 {
2911 o = octonion<T>(a,b,c);
2912 }
2913 else if (cc == ',') // read "((a,b),(c),"
2914 {
2915 u = ::std::complex<T>(a,b);
2916
2917 v = ::std::complex<T>(c);
2918
2919 is >> x; // read "((a,b),(c),x"
2920
2921 if (!is.good()) goto finish;
2922
2923 is >> ch; // get the next lexeme
2924
2925 if (!is.good()) goto finish;
2926
2927 #ifdef BOOST_NO_STD_LOCALE
2928 cc = ch;
2929 #else
2930 cc = ct.narrow(ch, char());
2931 #endif /* BOOST_NO_STD_LOCALE */
2932
2933 if (cc == ')') // read "((a,b),(c),x)"
2934 {
2935 o = octonion<T>(u,v,x);
2936 }
2937 else if (cc == ',') // read "((a,b),(c),x,"
2938 {
2939 is >> y; // read "((a,b),(c),x,y"
2940
2941 if (!is.good()) goto finish;
2942
2943 is >> ch; // get the next lexeme
2944
2945 if (!is.good()) goto finish;
2946
2947 #ifdef BOOST_NO_STD_LOCALE
2948 cc = ch;
2949 #else
2950 cc = ct.narrow(ch, char());
2951 #endif /* BOOST_NO_STD_LOCALE */
2952
2953 if (cc == ')') // read "((a,b),(c),x,y)"
2954 {
2955 o = octonion<T>(u,v,x,y);
2956 }
2957 else // error
2958 {
2959 #if BOOST_WORKAROUND(__GNUC__, < 3)
2960 is.setstate(::std::ios::failbit);
2961 #else
2962 is.setstate(::std::ios_base::failbit);
2963 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2964 }
2965 }
2966 else // error
2967 {
2968 #if BOOST_WORKAROUND(__GNUC__, < 3)
2969 is.setstate(::std::ios::failbit);
2970 #else
2971 is.setstate(::std::ios_base::failbit);
2972 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2973 }
2974 }
2975 else // error
2976 {
2977 #if BOOST_WORKAROUND(__GNUC__, < 3)
2978 is.setstate(::std::ios::failbit);
2979 #else
2980 is.setstate(::std::ios_base::failbit);
2981 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
2982 }
2983 }
2984 else if (cc == ',') // read "((a,b),(c," or "((a,b),(e,"
2985 {
2986 is >> ch; // get the next lexeme
2987
2988 if (!is.good()) goto finish;
2989
2990 #ifdef BOOST_NO_STD_LOCALE
2991 cc = ch;
2992 #else
2993 cc = ct.narrow(ch, char());
2994 #endif /* BOOST_NO_STD_LOCALE */
2995
2996 if (cc == '(') // read "((a,b),(e,(" (ambiguity resolution)
2997 {
2998 u = ::std::complex<T>(a,b);
2999
3000 x = ::std::complex<T>(c); // "c" is actually "e"
3001
3002 is.putback(ch);
3003
3004 is >> y; // read "((a,b),(e,y"
3005
3006 if (!is.good()) goto finish;
3007
3008 is >> ch; // get the next lexeme
3009
3010 if (!is.good()) goto finish;
3011
3012 #ifdef BOOST_NO_STD_LOCALE
3013 cc = ch;
3014 #else
3015 cc = ct.narrow(ch, char());
3016 #endif /* BOOST_NO_STD_LOCALE */
3017
3018 if (cc == ')') // read "((a,b),(e,y)"
3019 {
3020 is >> ch; // get the next lexeme
3021
3022 if (!is.good()) goto finish;
3023
3024 #ifdef BOOST_NO_STD_LOCALE
3025 cc = ch;
3026 #else
3027 cc = ct.narrow(ch, char());
3028 #endif /* BOOST_NO_STD_LOCALE */
3029
3030 if (cc == ')') // read "((a,b),(e,y))"
3031 {
3032 o = octonion<T>(u,v,x,y);
3033 }
3034 else // error
3035 {
3036 #if BOOST_WORKAROUND(__GNUC__, < 3)
3037 is.setstate(::std::ios::failbit);
3038 #else
3039 is.setstate(::std::ios_base::failbit);
3040 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3041 }
3042 }
3043 else // error
3044 {
3045 #if BOOST_WORKAROUND(__GNUC__, < 3)
3046 is.setstate(::std::ios::failbit);
3047 #else
3048 is.setstate(::std::ios_base::failbit);
3049 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3050 }
3051 }
3052 else // read "((a,b),(c,d" or "((a,b),(e,f"
3053 {
3054 is.putback(ch);
3055
3056 is >> d;
3057
3058 if (!is.good()) goto finish;
3059
3060 is >> ch; // get the next lexeme
3061
3062 if (!is.good()) goto finish;
3063
3064 #ifdef BOOST_NO_STD_LOCALE
3065 cc = ch;
3066 #else
3067 cc = ct.narrow(ch, char());
3068 #endif /* BOOST_NO_STD_LOCALE */
3069
3070 if (cc == ')') // read "((a,b),(c,d)" (ambiguity resolution)
3071 {
3072 u = ::std::complex<T>(a,b);
3073
3074 v = ::std::complex<T>(c,d);
3075
3076 is >> ch; // get the next lexeme
3077
3078 if (!is.good()) goto finish;
3079
3080 #ifdef BOOST_NO_STD_LOCALE
3081 cc = ch;
3082 #else
3083 cc = ct.narrow(ch, char());
3084 #endif /* BOOST_NO_STD_LOCALE */
3085
3086 if (cc == ')') // read "((a,b),(c,d))"
3087 {
3088 o = octonion<T>(u,v);
3089 }
3090 else if (cc == ',') // read "((a,b),(c,d),"
3091 {
3092 is >> x; // read "((a,b),(c,d),x
3093
3094 if (!is.good()) goto finish;
3095
3096 is >> ch; // get the next lexeme
3097
3098 if (!is.good()) goto finish;
3099
3100 #ifdef BOOST_NO_STD_LOCALE
3101 cc = ch;
3102 #else
3103 cc = ct.narrow(ch, char());
3104 #endif /* BOOST_NO_STD_LOCALE */
3105
3106 if (cc == ')') // read "((a,b),(c,d),x)"
3107 {
3108 o = octonion<T>(u,v,x);
3109 }
3110 else if (cc == ',') // read "((a,b),(c,d),x,"
3111 {
3112 is >> y; // read "((a,b),(c,d),x,y"
3113
3114 if (!is.good()) goto finish;
3115
3116 is >> ch; // get the next lexeme
3117
3118 if (!is.good()) goto finish;
3119
3120 #ifdef BOOST_NO_STD_LOCALE
3121 cc = ch;
3122 #else
3123 cc = ct.narrow(ch, char());
3124 #endif /* BOOST_NO_STD_LOCALE */
3125
3126 if (cc == ')') // read "((a,b),(c,d),x,y)"
3127 {
3128 o = octonion<T>(u,v,x,y);
3129 }
3130 else // error
3131 {
3132 #if BOOST_WORKAROUND(__GNUC__, < 3)
3133 is.setstate(::std::ios::failbit);
3134 #else
3135 is.setstate(::std::ios_base::failbit);
3136 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3137 }
3138 }
3139 else // error
3140 {
3141 #if BOOST_WORKAROUND(__GNUC__, < 3)
3142 is.setstate(::std::ios::failbit);
3143 #else
3144 is.setstate(::std::ios_base::failbit);
3145 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3146 }
3147 }
3148 else // error
3149 {
3150 #if BOOST_WORKAROUND(__GNUC__, < 3)
3151 is.setstate(::std::ios::failbit);
3152 #else
3153 is.setstate(::std::ios_base::failbit);
3154 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3155 }
3156 }
3157 else if (cc == ',') // read "((a,b),(e,f," (ambiguity resolution)
3158 {
3159 p = ::boost::math::quaternion<T>(a,b); // too late to backtrack
3160
3161 is >> g; // read "((a,b),(e,f,g"
3162
3163 if (!is.good()) goto finish;
3164
3165 is >> ch; // get the next lexeme
3166
3167 if (!is.good()) goto finish;
3168
3169 #ifdef BOOST_NO_STD_LOCALE
3170 cc = ch;
3171 #else
3172 cc = ct.narrow(ch, char());
3173 #endif /* BOOST_NO_STD_LOCALE */
3174
3175 if (cc == ')') // read "((a,b),(e,f,g)"
3176 {
3177 is >> ch; // get the next lexeme
3178
3179 if (!is.good()) goto finish;
3180
3181 #ifdef BOOST_NO_STD_LOCALE
3182 cc = ch;
3183 #else
3184 cc = ct.narrow(ch, char());
3185 #endif /* BOOST_NO_STD_LOCALE */
3186
3187 if (cc == ')') // read "((a,b),(e,f,g))"
3188 {
3189 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f"
3190
3191 o = octonion<T>(p,q);
3192 }
3193 else // error
3194 {
3195 #if BOOST_WORKAROUND(__GNUC__, < 3)
3196 is.setstate(::std::ios::failbit);
3197 #else
3198 is.setstate(::std::ios_base::failbit);
3199 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3200 }
3201 }
3202 else if (cc == ',') // read "((a,b),(e,f,g,"
3203 {
3204 is >> h; // read "((a,b),(e,f,g,h"
3205
3206 if (!is.good()) goto finish;
3207
3208 is >> ch; // get the next lexeme
3209
3210 if (!is.good()) goto finish;
3211
3212 #ifdef BOOST_NO_STD_LOCALE
3213 cc = ch;
3214 #else
3215 cc = ct.narrow(ch, char());
3216 #endif /* BOOST_NO_STD_LOCALE */
3217
3218 if (cc == ')') // read "((a,b),(e,f,g,h)"
3219 {
3220 is >> ch; // get the next lexeme
3221
3222 if (!is.good()) goto finish;
3223
3224 #ifdef BOOST_NO_STD_LOCALE
3225 cc = ch;
3226 #else
3227 cc = ct.narrow(ch, char());
3228 #endif /* BOOST_NO_STD_LOCALE */
3229
3230 if (cc == ')') // read ((a,b),(e,f,g,h))"
3231 {
3232 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f"
3233
3234 o = octonion<T>(p,q);
3235 }
3236 else // error
3237 {
3238 #if BOOST_WORKAROUND(__GNUC__, < 3)
3239 is.setstate(::std::ios::failbit);
3240 #else
3241 is.setstate(::std::ios_base::failbit);
3242 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3243 }
3244 }
3245 else // error
3246 {
3247 #if BOOST_WORKAROUND(__GNUC__, < 3)
3248 is.setstate(::std::ios::failbit);
3249 #else
3250 is.setstate(::std::ios_base::failbit);
3251 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3252 }
3253 }
3254 else // error
3255 {
3256 #if BOOST_WORKAROUND(__GNUC__, < 3)
3257 is.setstate(::std::ios::failbit);
3258 #else
3259 is.setstate(::std::ios_base::failbit);
3260 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3261 }
3262 }
3263 else // error
3264 {
3265 #if BOOST_WORKAROUND(__GNUC__, < 3)
3266 is.setstate(::std::ios::failbit);
3267 #else
3268 is.setstate(::std::ios_base::failbit);
3269 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3270 }
3271 }
3272 }
3273 else // error
3274 {
3275 #if BOOST_WORKAROUND(__GNUC__, < 3)
3276 is.setstate(::std::ios::failbit);
3277 #else
3278 is.setstate(::std::ios_base::failbit);
3279 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3280 }
3281 }
3282 }
3283 else // error
3284 {
3285 #if BOOST_WORKAROUND(__GNUC__, < 3)
3286 is.setstate(::std::ios::failbit);
3287 #else
3288 is.setstate(::std::ios_base::failbit);
3289 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3290 }
3291 }
3292 else // error
3293 {
3294 #if BOOST_WORKAROUND(__GNUC__, < 3)
3295 is.setstate(::std::ios::failbit);
3296 #else
3297 is.setstate(::std::ios_base::failbit);
3298 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3299 }
3300 }
3301 else if (cc == ',') // read "((a,b,"
3302 {
3303 is >> c; // read "((a,b,c"
3304
3305 if (!is.good()) goto finish;
3306
3307 is >> ch; // get the next lexeme
3308
3309 if (!is.good()) goto finish;
3310
3311 #ifdef BOOST_NO_STD_LOCALE
3312 cc = ch;
3313 #else
3314 cc = ct.narrow(ch, char());
3315 #endif /* BOOST_NO_STD_LOCALE */
3316
3317 if (cc == ')') // read "((a,b,c)"
3318 {
3319 is >> ch; // get the next lexeme
3320
3321 if (!is.good()) goto finish;
3322
3323 #ifdef BOOST_NO_STD_LOCALE
3324 cc = ch;
3325 #else
3326 cc = ct.narrow(ch, char());
3327 #endif /* BOOST_NO_STD_LOCALE */
3328
3329 if (cc == ')') // read "((a,b,c))"
3330 {
3331 o = octonion<T>(a,b,c);
3332 }
3333 else if (cc == ',') // read "((a,b,c),"
3334 {
3335 p = ::boost::math::quaternion<T>(a,b,c);
3336
3337 is >> q; // read "((a,b,c),q"
3338
3339 if (!is.good()) goto finish;
3340
3341 is >> ch; // get the next lexeme
3342
3343 if (!is.good()) goto finish;
3344
3345 #ifdef BOOST_NO_STD_LOCALE
3346 cc = ch;
3347 #else
3348 cc = ct.narrow(ch, char());
3349 #endif /* BOOST_NO_STD_LOCALE */
3350
3351 if (cc == ')') // read "((a,b,c),q)"
3352 {
3353 o = octonion<T>(p,q);
3354 }
3355 else // error
3356 {
3357 #if BOOST_WORKAROUND(__GNUC__, < 3)
3358 is.setstate(::std::ios::failbit);
3359 #else
3360 is.setstate(::std::ios_base::failbit);
3361 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3362 }
3363 }
3364 else // error
3365 {
3366 #if BOOST_WORKAROUND(__GNUC__, < 3)
3367 is.setstate(::std::ios::failbit);
3368 #else
3369 is.setstate(::std::ios_base::failbit);
3370 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3371 }
3372 }
3373 else if (cc == ',') // read "((a,b,c,"
3374 {
3375 is >> d; // read "((a,b,c,d"
3376
3377 if (!is.good()) goto finish;
3378
3379 is >> ch; // get the next lexeme
3380
3381 if (!is.good()) goto finish;
3382
3383 #ifdef BOOST_NO_STD_LOCALE
3384 cc = ch;
3385 #else
3386 cc = ct.narrow(ch, char());
3387 #endif /* BOOST_NO_STD_LOCALE */
3388
3389 if (cc == ')') // read "((a,b,c,d)"
3390 {
3391 is >> ch; // get the next lexeme
3392
3393 if (!is.good()) goto finish;
3394
3395 #ifdef BOOST_NO_STD_LOCALE
3396 cc = ch;
3397 #else
3398 cc = ct.narrow(ch, char());
3399 #endif /* BOOST_NO_STD_LOCALE */
3400
3401 if (cc == ')') // read "((a,b,c,d))"
3402 {
3403 o = octonion<T>(a,b,c,d);
3404 }
3405 else if (cc == ',') // read "((a,b,c,d),"
3406 {
3407 p = ::boost::math::quaternion<T>(a,b,c,d);
3408
3409 is >> q; // read "((a,b,c,d),q"
3410
3411 if (!is.good()) goto finish;
3412
3413 is >> ch; // get the next lexeme
3414
3415 if (!is.good()) goto finish;
3416
3417 #ifdef BOOST_NO_STD_LOCALE
3418 cc = ch;
3419 #else
3420 cc = ct.narrow(ch, char());
3421 #endif /* BOOST_NO_STD_LOCALE */
3422
3423 if (cc == ')') // read "((a,b,c,d),q)"
3424 {
3425 o = octonion<T>(p,q);
3426 }
3427 else // error
3428 {
3429 #if BOOST_WORKAROUND(__GNUC__, < 3)
3430 is.setstate(::std::ios::failbit);
3431 #else
3432 is.setstate(::std::ios_base::failbit);
3433 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3434 }
3435 }
3436 else // error
3437 {
3438 #if BOOST_WORKAROUND(__GNUC__, < 3)
3439 is.setstate(::std::ios::failbit);
3440 #else
3441 is.setstate(::std::ios_base::failbit);
3442 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3443 }
3444 }
3445 else // error
3446 {
3447 #if BOOST_WORKAROUND(__GNUC__, < 3)
3448 is.setstate(::std::ios::failbit);
3449 #else
3450 is.setstate(::std::ios_base::failbit);
3451 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3452 }
3453 }
3454 else // error
3455 {
3456 #if BOOST_WORKAROUND(__GNUC__, < 3)
3457 is.setstate(::std::ios::failbit);
3458 #else
3459 is.setstate(::std::ios_base::failbit);
3460 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3461 }
3462 }
3463 else // error
3464 {
3465 #if BOOST_WORKAROUND(__GNUC__, < 3)
3466 is.setstate(::std::ios::failbit);
3467 #else
3468 is.setstate(::std::ios_base::failbit);
3469 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3470 }
3471 }
3472 }
3473 else // error
3474 {
3475 #if BOOST_WORKAROUND(__GNUC__, < 3)
3476 is.setstate(::std::ios::failbit);
3477 #else
3478 is.setstate(::std::ios_base::failbit);
3479 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3480 }
3481 }
3482 }
3483 else // read "(a"
3484 {
3485 is.putback(ch);
3486
3487 is >> a; // we extract the first component
3488
3489 if (!is.good()) goto finish;
3490
3491 is >> ch; // get the next lexeme
3492
3493 if (!is.good()) goto finish;
3494
3495 #ifdef BOOST_NO_STD_LOCALE
3496 cc = ch;
3497 #else
3498 cc = ct.narrow(ch, char());
3499 #endif /* BOOST_NO_STD_LOCALE */
3500
3501 if (cc == ')') // read "(a)"
3502 {
3503 o = octonion<T>(a);
3504 }
3505 else if (cc == ',') // read "(a,"
3506 {
3507 is >> ch; // get the next lexeme
3508
3509 if (!is.good()) goto finish;
3510
3511 #ifdef BOOST_NO_STD_LOCALE
3512 cc = ch;
3513 #else
3514 cc = ct.narrow(ch, char());
3515 #endif /* BOOST_NO_STD_LOCALE */
3516
3517 if (cc == '(') // read "(a,("
3518 {
3519 is >> ch; // get the next lexeme
3520
3521 if (!is.good()) goto finish;
3522
3523 #ifdef BOOST_NO_STD_LOCALE
3524 cc = ch;
3525 #else
3526 cc = ct.narrow(ch, char());
3527 #endif /* BOOST_NO_STD_LOCALE */
3528
3529 if (cc == '(') // read "(a,(("
3530 {
3531 p = ::boost::math::quaternion<T>(a);
3532
3533 is.putback(ch);
3534
3535 is.putback(ch); // we backtrack twice, with the same value
3536
3537 is >> q; // read "(a,q"
3538
3539 if (!is.good()) goto finish;
3540
3541 is >> ch; // get the next lexeme
3542
3543 if (!is.good()) goto finish;
3544
3545 #ifdef BOOST_NO_STD_LOCALE
3546 cc = ch;
3547 #else
3548 cc = ct.narrow(ch, char());
3549 #endif /* BOOST_NO_STD_LOCALE */
3550
3551 if (cc == ')') // read "(a,q)"
3552 {
3553 o = octonion<T>(p,q);
3554 }
3555 else // error
3556 {
3557 #if BOOST_WORKAROUND(__GNUC__, < 3)
3558 is.setstate(::std::ios::failbit);
3559 #else
3560 is.setstate(::std::ios_base::failbit);
3561 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3562 }
3563 }
3564 else // read "(a,(c" or "(a,(e"
3565 {
3566 is.putback(ch);
3567
3568 is >> c;
3569
3570 if (!is.good()) goto finish;
3571
3572 is >> ch; // get the next lexeme
3573
3574 if (!is.good()) goto finish;
3575
3576 #ifdef BOOST_NO_STD_LOCALE
3577 cc = ch;
3578 #else
3579 cc = ct.narrow(ch, char());
3580 #endif /* BOOST_NO_STD_LOCALE */
3581
3582 if (cc == ')') // read "(a,(c)" (ambiguity resolution)
3583 {
3584 is >> ch; // get the next lexeme
3585
3586 if (!is.good()) goto finish;
3587
3588 #ifdef BOOST_NO_STD_LOCALE
3589 cc = ch;
3590 #else
3591 cc = ct.narrow(ch, char());
3592 #endif /* BOOST_NO_STD_LOCALE */
3593
3594 if (cc == ')') // read "(a,(c))"
3595 {
3596 o = octonion<T>(a,b,c);
3597 }
3598 else if (cc == ',') // read "(a,(c),"
3599 {
3600 u = ::std::complex<T>(a);
3601
3602 v = ::std::complex<T>(c);
3603
3604 is >> x; // read "(a,(c),x"
3605
3606 if (!is.good()) goto finish;
3607
3608 is >> ch; // get the next lexeme
3609
3610 if (!is.good()) goto finish;
3611
3612 #ifdef BOOST_NO_STD_LOCALE
3613 cc = ch;
3614 #else
3615 cc = ct.narrow(ch, char());
3616 #endif /* BOOST_NO_STD_LOCALE */
3617
3618 if (cc == ')') // read "(a,(c),x)"
3619 {
3620 o = octonion<T>(u,v,x);
3621 }
3622 else if (cc == ',') // read "(a,(c),x,"
3623 {
3624 is >> y; // read "(a,(c),x,y"
3625
3626 if (!is.good()) goto finish;
3627
3628 is >> ch; // get the next lexeme
3629
3630 if (!is.good()) goto finish;
3631
3632 #ifdef BOOST_NO_STD_LOCALE
3633 cc = ch;
3634 #else
3635 cc = ct.narrow(ch, char());
3636 #endif /* BOOST_NO_STD_LOCALE */
3637
3638 if (cc == ')') // read "(a,(c),x,y)"
3639 {
3640 o = octonion<T>(u,v,x,y);
3641 }
3642 else // error
3643 {
3644 #if BOOST_WORKAROUND(__GNUC__, < 3)
3645 is.setstate(::std::ios::failbit);
3646 #else
3647 is.setstate(::std::ios_base::failbit);
3648 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3649 }
3650 }
3651 else // error
3652 {
3653 #if BOOST_WORKAROUND(__GNUC__, < 3)
3654 is.setstate(::std::ios::failbit);
3655 #else
3656 is.setstate(::std::ios_base::failbit);
3657 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3658 }
3659 }
3660 else // error
3661 {
3662 #if BOOST_WORKAROUND(__GNUC__, < 3)
3663 is.setstate(::std::ios::failbit);
3664 #else
3665 is.setstate(::std::ios_base::failbit);
3666 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3667 }
3668 }
3669 else if (cc == ',') // read "(a,(c," or "(a,(e,"
3670 {
3671 is >> ch; // get the next lexeme
3672
3673 if (!is.good()) goto finish;
3674
3675 #ifdef BOOST_NO_STD_LOCALE
3676 cc = ch;
3677 #else
3678 cc = ct.narrow(ch, char());
3679 #endif /* BOOST_NO_STD_LOCALE */
3680
3681 if (cc == '(') // read "(a,(e,(" (ambiguity resolution)
3682 {
3683 u = ::std::complex<T>(a);
3684
3685 x = ::std::complex<T>(c); // "c" is actually "e"
3686
3687 is.putback(ch); // we backtrack
3688
3689 is >> y; // read "(a,(e,y"
3690
3691 if (!is.good()) goto finish;
3692
3693 is >> ch; // get the next lexeme
3694
3695 if (!is.good()) goto finish;
3696
3697 #ifdef BOOST_NO_STD_LOCALE
3698 cc = ch;
3699 #else
3700 cc = ct.narrow(ch, char());
3701 #endif /* BOOST_NO_STD_LOCALE */
3702
3703 if (cc == ')') // read "(a,(e,y)"
3704 {
3705 is >> ch; // get the next lexeme
3706
3707 if (!is.good()) goto finish;
3708
3709 #ifdef BOOST_NO_STD_LOCALE
3710 cc = ch;
3711 #else
3712 cc = ct.narrow(ch, char());
3713 #endif /* BOOST_NO_STD_LOCALE */
3714
3715 if (cc == ')') // read "(a,(e,y))"
3716 {
3717 o = octonion<T>(u,v,x,y);
3718 }
3719 else // error
3720 {
3721 #if BOOST_WORKAROUND(__GNUC__, < 3)
3722 is.setstate(::std::ios::failbit);
3723 #else
3724 is.setstate(::std::ios_base::failbit);
3725 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3726 }
3727 }
3728 else // error
3729 {
3730 #if BOOST_WORKAROUND(__GNUC__, < 3)
3731 is.setstate(::std::ios::failbit);
3732 #else
3733 is.setstate(::std::ios_base::failbit);
3734 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3735 }
3736 }
3737 else // read "(a,(c,d" or "(a,(e,f"
3738 {
3739 is.putback(ch);
3740
3741 is >> d;
3742
3743 if (!is.good()) goto finish;
3744
3745 is >> ch; // get the next lexeme
3746
3747 if (!is.good()) goto finish;
3748
3749 #ifdef BOOST_NO_STD_LOCALE
3750 cc = ch;
3751 #else
3752 cc = ct.narrow(ch, char());
3753 #endif /* BOOST_NO_STD_LOCALE */
3754
3755 if (cc == ')') // read "(a,(c,d)" (ambiguity resolution)
3756 {
3757 is >> ch; // get the next lexeme
3758
3759 if (!is.good()) goto finish;
3760
3761 #ifdef BOOST_NO_STD_LOCALE
3762 cc = ch;
3763 #else
3764 cc = ct.narrow(ch, char());
3765 #endif /* BOOST_NO_STD_LOCALE */
3766
3767 if (cc == ')') // read "(a,(c,d))"
3768 {
3769 o = octonion<T>(a,b,c,d);
3770 }
3771 else if (cc == ',') // read "(a,(c,d),"
3772 {
3773 u = ::std::complex<T>(a);
3774
3775 v = ::std::complex<T>(c,d);
3776
3777 is >> x; // read "(a,(c,d),x"
3778
3779 if (!is.good()) goto finish;
3780
3781 is >> ch; // get the next lexeme
3782
3783 if (!is.good()) goto finish;
3784
3785 #ifdef BOOST_NO_STD_LOCALE
3786 cc = ch;
3787 #else
3788 cc = ct.narrow(ch, char());
3789 #endif /* BOOST_NO_STD_LOCALE */
3790
3791 if (cc == ')') // read "(a,(c,d),x)"
3792 {
3793 o = octonion<T>(u,v,x);
3794 }
3795 else if (cc == ',') // read "(a,(c,d),x,"
3796 {
3797 is >> y; // read "(a,(c,d),x,y"
3798
3799 if (!is.good()) goto finish;
3800
3801 is >> ch; // get the next lexeme
3802
3803 if (!is.good()) goto finish;
3804
3805 #ifdef BOOST_NO_STD_LOCALE
3806 cc = ch;
3807 #else
3808 cc = ct.narrow(ch, char());
3809 #endif /* BOOST_NO_STD_LOCALE */
3810
3811 if (cc == ')') // read "(a,(c,d),x,y)"
3812 {
3813 o = octonion<T>(u,v,x,y);
3814 }
3815 else // error
3816 {
3817 #if BOOST_WORKAROUND(__GNUC__, < 3)
3818 is.setstate(::std::ios::failbit);
3819 #else
3820 is.setstate(::std::ios_base::failbit);
3821 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3822 }
3823 }
3824 else // error
3825 {
3826 #if BOOST_WORKAROUND(__GNUC__, < 3)
3827 is.setstate(::std::ios::failbit);
3828 #else
3829 is.setstate(::std::ios_base::failbit);
3830 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3831 }
3832 }
3833 else // error
3834 {
3835 #if BOOST_WORKAROUND(__GNUC__, < 3)
3836 is.setstate(::std::ios::failbit);
3837 #else
3838 is.setstate(::std::ios_base::failbit);
3839 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3840 }
3841 }
3842 else if (cc == ',') // read "(a,(e,f," (ambiguity resolution)
3843 {
3844 p = ::boost::math::quaternion<T>(a);
3845
3846 is >> g; // read "(a,(e,f,g"
3847
3848 if (!is.good()) goto finish;
3849
3850 is >> ch; // get the next lexeme
3851
3852 if (!is.good()) goto finish;
3853
3854 #ifdef BOOST_NO_STD_LOCALE
3855 cc = ch;
3856 #else
3857 cc = ct.narrow(ch, char());
3858 #endif /* BOOST_NO_STD_LOCALE */
3859
3860 if (cc == ')') // read "(a,(e,f,g)"
3861 {
3862 is >> ch; // get the next lexeme
3863
3864 if (!is.good()) goto finish;
3865
3866 #ifdef BOOST_NO_STD_LOCALE
3867 cc = ch;
3868 #else
3869 cc = ct.narrow(ch, char());
3870 #endif /* BOOST_NO_STD_LOCALE */
3871
3872 if (cc == ')') // read "(a,(e,f,g))"
3873 {
3874 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f"
3875
3876 o = octonion<T>(p,q);
3877 }
3878 else // error
3879 {
3880 #if BOOST_WORKAROUND(__GNUC__, < 3)
3881 is.setstate(::std::ios::failbit);
3882 #else
3883 is.setstate(::std::ios_base::failbit);
3884 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3885 }
3886 }
3887 else if (cc == ',') // read "(a,(e,f,g,"
3888 {
3889 is >> h; // read "(a,(e,f,g,h"
3890
3891 if (!is.good()) goto finish;
3892
3893 is >> ch; // get the next lexeme
3894
3895 if (!is.good()) goto finish;
3896
3897 #ifdef BOOST_NO_STD_LOCALE
3898 cc = ch;
3899 #else
3900 cc = ct.narrow(ch, char());
3901 #endif /* BOOST_NO_STD_LOCALE */
3902
3903 if (cc == ')') // read "(a,(e,f,g,h)"
3904 {
3905 is >> ch; // get the next lexeme
3906
3907 if (!is.good()) goto finish;
3908
3909 #ifdef BOOST_NO_STD_LOCALE
3910 cc = ch;
3911 #else
3912 cc = ct.narrow(ch, char());
3913 #endif /* BOOST_NO_STD_LOCALE */
3914
3915 if (cc == ')') // read "(a,(e,f,g,h))"
3916 {
3917 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f"
3918
3919 o = octonion<T>(p,q);
3920 }
3921 else // error
3922 {
3923 #if BOOST_WORKAROUND(__GNUC__, < 3)
3924 is.setstate(::std::ios::failbit);
3925 #else
3926 is.setstate(::std::ios_base::failbit);
3927 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3928 }
3929 }
3930 else // error
3931 {
3932 #if BOOST_WORKAROUND(__GNUC__, < 3)
3933 is.setstate(::std::ios::failbit);
3934 #else
3935 is.setstate(::std::ios_base::failbit);
3936 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3937 }
3938 }
3939 else // error
3940 {
3941 #if BOOST_WORKAROUND(__GNUC__, < 3)
3942 is.setstate(::std::ios::failbit);
3943 #else
3944 is.setstate(::std::ios_base::failbit);
3945 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3946 }
3947 }
3948 else // error
3949 {
3950 #if BOOST_WORKAROUND(__GNUC__, < 3)
3951 is.setstate(::std::ios::failbit);
3952 #else
3953 is.setstate(::std::ios_base::failbit);
3954 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3955 }
3956 }
3957 }
3958 else // error
3959 {
3960 #if BOOST_WORKAROUND(__GNUC__, < 3)
3961 is.setstate(::std::ios::failbit);
3962 #else
3963 is.setstate(::std::ios_base::failbit);
3964 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
3965 }
3966 }
3967 }
3968 else // read "(a,b" or "(a,c" (ambiguity resolution)
3969 {
3970 is.putback(ch);
3971
3972 is >> b;
3973
3974 if (!is.good()) goto finish;
3975
3976 is >> ch; // get the next lexeme
3977
3978 if (!is.good()) goto finish;
3979
3980 #ifdef BOOST_NO_STD_LOCALE
3981 cc = ch;
3982 #else
3983 cc = ct.narrow(ch, char());
3984 #endif /* BOOST_NO_STD_LOCALE */
3985
3986 if (cc == ')') // read "(a,b)" (ambiguity resolution)
3987 {
3988 o = octonion<T>(a,b);
3989 }
3990 else if (cc == ',') // read "(a,b," or "(a,c,"
3991 {
3992 is >> ch; // get the next lexeme
3993
3994 if (!is.good()) goto finish;
3995
3996 #ifdef BOOST_NO_STD_LOCALE
3997 cc = ch;
3998 #else
3999 cc = ct.narrow(ch, char());
4000 #endif /* BOOST_NO_STD_LOCALE */
4001
4002 if (cc == '(') // read "(a,c,(" (ambiguity resolution)
4003 {
4004 u = ::std::complex<T>(a);
4005
4006 v = ::std::complex<T>(b); // "b" is actually "c"
4007
4008 is.putback(ch); // we backtrack
4009
4010 is >> x; // read "(a,c,x"
4011
4012 if (!is.good()) goto finish;
4013
4014 is >> ch; // get the next lexeme
4015
4016 if (!is.good()) goto finish;
4017
4018 #ifdef BOOST_NO_STD_LOCALE
4019 cc = ch;
4020 #else
4021 cc = ct.narrow(ch, char());
4022 #endif /* BOOST_NO_STD_LOCALE */
4023
4024 if (cc == ')') // read "(a,c,x)"
4025 {
4026 o = octonion<T>(u,v,x);
4027 }
4028 else if (cc == ',') // read "(a,c,x,"
4029 {
4030 is >> y; // read "(a,c,x,y" // read "(a,c,x"
4031
4032 if (!is.good()) goto finish;
4033
4034 is >> ch; // get the next lexeme
4035
4036 if (!is.good()) goto finish;
4037
4038 #ifdef BOOST_NO_STD_LOCALE
4039 cc = ch;
4040 #else
4041 cc = ct.narrow(ch, char());
4042 #endif /* BOOST_NO_STD_LOCALE */
4043
4044 if (cc == ')') // read "(a,c,x,y)"
4045 {
4046 o = octonion<T>(u,v,x,y);
4047 }
4048 else // error
4049 {
4050 #if BOOST_WORKAROUND(__GNUC__, < 3)
4051 is.setstate(::std::ios::failbit);
4052 #else
4053 is.setstate(::std::ios_base::failbit);
4054 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4055 }
4056 }
4057 else // error
4058 {
4059 #if BOOST_WORKAROUND(__GNUC__, < 3)
4060 is.setstate(::std::ios::failbit);
4061 #else
4062 is.setstate(::std::ios_base::failbit);
4063 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4064 }
4065 }
4066 else // read "(a,b,c" or "(a,c,e"
4067 {
4068 is.putback(ch);
4069
4070 is >> c;
4071
4072 if (!is.good()) goto finish;
4073
4074 is >> ch; // get the next lexeme
4075
4076 if (!is.good()) goto finish;
4077
4078 #ifdef BOOST_NO_STD_LOCALE
4079 cc = ch;
4080 #else
4081 cc = ct.narrow(ch, char());
4082 #endif /* BOOST_NO_STD_LOCALE */
4083
4084 if (cc == ')') // read "(a,b,c)" (ambiguity resolution)
4085 {
4086 o = octonion<T>(a,b,c);
4087 }
4088 else if (cc == ',') // read "(a,b,c," or "(a,c,e,"
4089 {
4090 is >> ch; // get the next lexeme
4091
4092 if (!is.good()) goto finish;
4093
4094 #ifdef BOOST_NO_STD_LOCALE
4095 cc = ch;
4096 #else
4097 cc = ct.narrow(ch, char());
4098 #endif /* BOOST_NO_STD_LOCALE */
4099
4100 if (cc == '(') // read "(a,c,e,(") (ambiguity resolution)
4101 {
4102 u = ::std::complex<T>(a);
4103
4104 v = ::std::complex<T>(b); // "b" is actually "c"
4105
4106 x = ::std::complex<T>(c); // "c" is actually "e"
4107
4108 is.putback(ch); // we backtrack
4109
4110 is >> y; // read "(a,c,e,y"
4111
4112 if (!is.good()) goto finish;
4113
4114 is >> ch; // get the next lexeme
4115
4116 if (!is.good()) goto finish;
4117
4118 #ifdef BOOST_NO_STD_LOCALE
4119 cc = ch;
4120 #else
4121 cc = ct.narrow(ch, char());
4122 #endif /* BOOST_NO_STD_LOCALE */
4123
4124 if (cc == ')') // read "(a,c,e,y)"
4125 {
4126 o = octonion<T>(u,v,x,y);
4127 }
4128 else // error
4129 {
4130 #if BOOST_WORKAROUND(__GNUC__, < 3)
4131 is.setstate(::std::ios::failbit);
4132 #else
4133 is.setstate(::std::ios_base::failbit);
4134 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4135 }
4136 }
4137 else // read "(a,b,c,d" (ambiguity resolution)
4138 {
4139 is.putback(ch); // we backtrack
4140
4141 is >> d;
4142
4143 if (!is.good()) goto finish;
4144
4145 is >> ch; // get the next lexeme
4146
4147 if (!is.good()) goto finish;
4148
4149 #ifdef BOOST_NO_STD_LOCALE
4150 cc = ch;
4151 #else
4152 cc = ct.narrow(ch, char());
4153 #endif /* BOOST_NO_STD_LOCALE */
4154
4155 if (cc == ')') // read "(a,b,c,d)"
4156 {
4157 o = octonion<T>(a,b,c,d);
4158 }
4159 else if (cc == ',') // read "(a,b,c,d,"
4160 {
4161 is >> e; // read "(a,b,c,d,e"
4162
4163 if (!is.good()) goto finish;
4164
4165 is >> ch; // get the next lexeme
4166
4167 if (!is.good()) goto finish;
4168
4169 #ifdef BOOST_NO_STD_LOCALE
4170 cc = ch;
4171 #else
4172 cc = ct.narrow(ch, char());
4173 #endif /* BOOST_NO_STD_LOCALE */
4174
4175 if (cc == ')') // read "(a,b,c,d,e)"
4176 {
4177 o = octonion<T>(a,b,c,d,e);
4178 }
4179 else if (cc == ',') // read "(a,b,c,d,e,"
4180 {
4181 is >> f; // read "(a,b,c,d,e,f"
4182
4183 if (!is.good()) goto finish;
4184
4185 is >> ch; // get the next lexeme
4186
4187 if (!is.good()) goto finish;
4188
4189 #ifdef BOOST_NO_STD_LOCALE
4190 cc = ch;
4191 #else
4192 cc = ct.narrow(ch, char());
4193 #endif /* BOOST_NO_STD_LOCALE */
4194
4195 if (cc == ')') // read "(a,b,c,d,e,f)"
4196 {
4197 o = octonion<T>(a,b,c,d,e,f);
4198 }
4199 else if (cc == ',') // read "(a,b,c,d,e,f,"
4200 {
4201 is >> g; // read "(a,b,c,d,e,f,g" // read "(a,b,c,d,e,f"
4202
4203 if (!is.good()) goto finish;
4204
4205 is >> ch; // get the next lexeme
4206
4207 if (!is.good()) goto finish;
4208
4209 #ifdef BOOST_NO_STD_LOCALE
4210 cc = ch;
4211 #else
4212 cc = ct.narrow(ch, char());
4213 #endif /* BOOST_NO_STD_LOCALE */
4214
4215 if (cc == ')') // read "(a,b,c,d,e,f,g)"
4216 {
4217 o = octonion<T>(a,b,c,d,e,f,g);
4218 }
4219 else if (cc == ',') // read "(a,b,c,d,e,f,g,"
4220 {
4221 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"
4222
4223 if (!is.good()) goto finish;
4224
4225 is >> ch; // get the next lexeme
4226
4227 if (!is.good()) goto finish;
4228
4229 #ifdef BOOST_NO_STD_LOCALE
4230 cc = ch;
4231 #else
4232 cc = ct.narrow(ch, char());
4233 #endif /* BOOST_NO_STD_LOCALE */
4234
4235 if (cc == ')') // read "(a,b,c,d,e,f,g,h)"
4236 {
4237 o = octonion<T>(a,b,c,d,e,f,g,h);
4238 }
4239 else // error
4240 {
4241 #if BOOST_WORKAROUND(__GNUC__, < 3)
4242 is.setstate(::std::ios::failbit);
4243 #else
4244 is.setstate(::std::ios_base::failbit);
4245 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4246 }
4247 }
4248 else // error
4249 {
4250 #if BOOST_WORKAROUND(__GNUC__, < 3)
4251 is.setstate(::std::ios::failbit);
4252 #else
4253 is.setstate(::std::ios_base::failbit);
4254 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4255 }
4256 }
4257 else // error
4258 {
4259 #if BOOST_WORKAROUND(__GNUC__, < 3)
4260 is.setstate(::std::ios::failbit);
4261 #else
4262 is.setstate(::std::ios_base::failbit);
4263 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4264 }
4265 }
4266 else // error
4267 {
4268 #if BOOST_WORKAROUND(__GNUC__, < 3)
4269 is.setstate(::std::ios::failbit);
4270 #else
4271 is.setstate(::std::ios_base::failbit);
4272 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4273 }
4274 }
4275 else // error
4276 {
4277 #if BOOST_WORKAROUND(__GNUC__, < 3)
4278 is.setstate(::std::ios::failbit);
4279 #else
4280 is.setstate(::std::ios_base::failbit);
4281 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4282 }
4283 }
4284 }
4285 else // error
4286 {
4287 #if BOOST_WORKAROUND(__GNUC__, < 3)
4288 is.setstate(::std::ios::failbit);
4289 #else
4290 is.setstate(::std::ios_base::failbit);
4291 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4292 }
4293 }
4294 }
4295 else // error
4296 {
4297 #if BOOST_WORKAROUND(__GNUC__, < 3)
4298 is.setstate(::std::ios::failbit);
4299 #else
4300 is.setstate(::std::ios_base::failbit);
4301 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4302 }
4303 }
4304 }
4305 else // error
4306 {
4307 #if BOOST_WORKAROUND(__GNUC__, < 3)
4308 is.setstate(::std::ios::failbit);
4309 #else
4310 is.setstate(::std::ios_base::failbit);
4311 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4312 }
4313 }
4314 }
4315 else // format: a
4316 {
4317 is.putback(ch);
4318
4319 is >> a; // we extract the first component
4320
4321 if (!is.good()) goto finish;
4322
4323 o = octonion<T>(a);
4324 }
4325
4326 finish:
4327 return(is);
4328 }
4329
4330
4331 #if BOOST_WORKAROUND(__GNUC__, < 3)
4332 template<typename T>
4333 ::std::ostream & operator << ( ::std::ostream & os,
4334 octonion<T> const & o)
4335 #else
4336 template<typename T, typename charT, class traits>
4337 ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
4338 octonion<T> const & o)
4339 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4340 {
4341 #if BOOST_WORKAROUND(__GNUC__, < 3)
4342 ::std::ostringstream s;
4343 #else
4344 ::std::basic_ostringstream<charT,traits> s;
4345 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4346
4347 s.flags(os.flags());
4348 #ifdef BOOST_NO_STD_LOCALE
4349 #else
4350 s.imbue(os.getloc());
4351 #endif /* BOOST_NO_STD_LOCALE */
4352 s.precision(os.precision());
4353
4354 s << '(' << o.R_component_1() << ','
4355 << o.R_component_2() << ','
4356 << o.R_component_3() << ','
4357 << o.R_component_4() << ','
4358 << o.R_component_5() << ','
4359 << o.R_component_6() << ','
4360 << o.R_component_7() << ','
4361 << o.R_component_8() << ')';
4362
4363 return os << s.str();
4364 }
4365
4366
4367 // values
4368
4369 template<typename T>
4370 inline T real(octonion<T> const & o)
4371 {
4372 return(o.real());
4373 }
4374
4375
4376 template<typename T>
4377 inline octonion<T> unreal(octonion<T> const & o)
4378 {
4379 return(o.unreal());
4380 }
4381
4382
4383 #define BOOST_OCTONION_VALARRAY_LOADER \
4384 using ::std::valarray; \
4385 \
4386 valarray<T> temp(8); \
4387 \
4388 temp[0] = o.R_component_1(); \
4389 temp[1] = o.R_component_2(); \
4390 temp[2] = o.R_component_3(); \
4391 temp[3] = o.R_component_4(); \
4392 temp[4] = o.R_component_5(); \
4393 temp[5] = o.R_component_6(); \
4394 temp[6] = o.R_component_7(); \
4395 temp[7] = o.R_component_8();
4396
4397
4398 template<typename T>
4399 inline T sup(octonion<T> const & o)
4400 {
4401 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
4402 using ::std::abs;
4403 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
4404
4405 BOOST_OCTONION_VALARRAY_LOADER
4406
4407 #if BOOST_WORKAROUND(__GNUC__, < 3)
4408 return((BOOST_GET_VALARRAY(T, abs(temp)).max)());
4409 #else
4410 return((abs(temp).max)());
4411 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4412 }
4413
4414
4415 template<typename T>
4416 inline T l1(octonion<T> const & o)
4417 {
4418 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
4419 using ::std::abs;
4420 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
4421
4422 BOOST_OCTONION_VALARRAY_LOADER
4423
4424 #if BOOST_WORKAROUND(__GNUC__, < 3)
4425 return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
4426 #else
4427 return(abs(temp).sum());
4428 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4429 }
4430
4431
4432 template<typename T>
4433 inline T abs(const octonion<T> & o)
4434 {
4435 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
4436 using ::std::abs;
4437 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
4438
4439 using ::std::sqrt;
4440
4441 BOOST_OCTONION_VALARRAY_LOADER
4442
4443 #if BOOST_WORKAROUND(__GNUC__, < 3)
4444 T maxim = (BOOST_GET_VALARRAY(T,abs(temp)).max)(); // overflow protection
4445 #else
4446 T maxim = (abs(temp).max)(); // overflow protection
4447 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4448
4449 if (maxim == static_cast<T>(0))
4450 {
4451 return(maxim);
4452 }
4453 else
4454 {
4455 T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions
4456
4457 temp *= mixam;
4458
4459 temp *= temp;
4460
4461 return(maxim*sqrt(temp.sum()));
4462 }
4463
4464 //return(::std::sqrt(norm(o)));
4465 }
4466
4467
4468 #undef BOOST_OCTONION_VALARRAY_LOADER
4469
4470
4471 // Note: This is the Cayley norm, not the Euclidian norm...
4472
4473 template<typename T>
4474 inline T norm(octonion<T> const & o)
4475 {
4476 return(real(o*conj(o)));
4477 }
4478
4479
4480 template<typename T>
4481 inline octonion<T> conj(octonion<T> const & o)
4482 {
4483 return(octonion<T>( +o.R_component_1(),
4484 -o.R_component_2(),
4485 -o.R_component_3(),
4486 -o.R_component_4(),
4487 -o.R_component_5(),
4488 -o.R_component_6(),
4489 -o.R_component_7(),
4490 -o.R_component_8()));
4491 }
4492
4493
4494 // Note: There is little point, for the octonions, to introduce the equivalents
4495 // to the complex "arg" and the quaternionic "cylindropolar".
4496
4497
4498 template<typename T>
4499 inline octonion<T> spherical(T const & rho,
4500 T const & theta,
4501 T const & phi1,
4502 T const & phi2,
4503 T const & phi3,
4504 T const & phi4,
4505 T const & phi5,
4506 T const & phi6)
4507 {
4508 using ::std::cos;
4509 using ::std::sin;
4510
4511 //T a = cos(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4512 //T b = sin(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4513 //T c = sin(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4514 //T d = sin(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4515 //T e = sin(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4516 //T f = sin(phi4)*cos(phi5)*cos(phi6);
4517 //T g = sin(phi5)*cos(phi6);
4518 //T h = sin(phi6);
4519
4520 T courrant = static_cast<T>(1);
4521
4522 T h = sin(phi6);
4523
4524 courrant *= cos(phi6);
4525
4526 T g = sin(phi5)*courrant;
4527
4528 courrant *= cos(phi5);
4529
4530 T f = sin(phi4)*courrant;
4531
4532 courrant *= cos(phi4);
4533
4534 T e = sin(phi3)*courrant;
4535
4536 courrant *= cos(phi3);
4537
4538 T d = sin(phi2)*courrant;
4539
4540 courrant *= cos(phi2);
4541
4542 T c = sin(phi1)*courrant;
4543
4544 courrant *= cos(phi1);
4545
4546 T b = sin(theta)*courrant;
4547 T a = cos(theta)*courrant;
4548
4549 return(rho*octonion<T>(a,b,c,d,e,f,g,h));
4550 }
4551
4552
4553 template<typename T>
4554 inline octonion<T> multipolar(T const & rho1,
4555 T const & theta1,
4556 T const & rho2,
4557 T const & theta2,
4558 T const & rho3,
4559 T const & theta3,
4560 T const & rho4,
4561 T const & theta4)
4562 {
4563 using ::std::cos;
4564 using ::std::sin;
4565
4566 T a = rho1*cos(theta1);
4567 T b = rho1*sin(theta1);
4568 T c = rho2*cos(theta2);
4569 T d = rho2*sin(theta2);
4570 T e = rho3*cos(theta3);
4571 T f = rho3*sin(theta3);
4572 T g = rho4*cos(theta4);
4573 T h = rho4*sin(theta4);
4574
4575 return(octonion<T>(a,b,c,d,e,f,g,h));
4576 }
4577
4578
4579 template<typename T>
4580 inline octonion<T> cylindrical(T const & r,
4581 T const & angle,
4582 T const & h1,
4583 T const & h2,
4584 T const & h3,
4585 T const & h4,
4586 T const & h5,
4587 T const & h6)
4588 {
4589 using ::std::cos;
4590 using ::std::sin;
4591
4592 T a = r*cos(angle);
4593 T b = r*sin(angle);
4594
4595 return(octonion<T>(a,b,h1,h2,h3,h4,h5,h6));
4596 }
4597
4598
4599 template<typename T>
4600 inline octonion<T> exp(octonion<T> const & o)
4601 {
4602 using ::std::exp;
4603 using ::std::cos;
4604
4605 using ::boost::math::sinc_pi;
4606
4607 T u = exp(real(o));
4608
4609 T z = abs(unreal(o));
4610
4611 T w = sinc_pi(z);
4612
4613 return(u*octonion<T>(cos(z),
4614 w*o.R_component_2(), w*o.R_component_3(),
4615 w*o.R_component_4(), w*o.R_component_5(),
4616 w*o.R_component_6(), w*o.R_component_7(),
4617 w*o.R_component_8()));
4618 }
4619
4620
4621 template<typename T>
4622 inline octonion<T> cos(octonion<T> const & o)
4623 {
4624 using ::std::sin;
4625 using ::std::cos;
4626 using ::std::cosh;
4627
4628 using ::boost::math::sinhc_pi;
4629
4630 T z = abs(unreal(o));
4631
4632 T w = -sin(o.real())*sinhc_pi(z);
4633
4634 return(octonion<T>(cos(o.real())*cosh(z),
4635 w*o.R_component_2(), w*o.R_component_3(),
4636 w*o.R_component_4(), w*o.R_component_5(),
4637 w*o.R_component_6(), w*o.R_component_7(),
4638 w*o.R_component_8()));
4639 }
4640
4641
4642 template<typename T>
4643 inline octonion<T> sin(octonion<T> const & o)
4644 {
4645 using ::std::sin;
4646 using ::std::cos;
4647 using ::std::cosh;
4648
4649 using ::boost::math::sinhc_pi;
4650
4651 T z = abs(unreal(o));
4652
4653 T w = +cos(o.real())*sinhc_pi(z);
4654
4655 return(octonion<T>(sin(o.real())*cosh(z),
4656 w*o.R_component_2(), w*o.R_component_3(),
4657 w*o.R_component_4(), w*o.R_component_5(),
4658 w*o.R_component_6(), w*o.R_component_7(),
4659 w*o.R_component_8()));
4660 }
4661
4662
4663 template<typename T>
4664 inline octonion<T> tan(octonion<T> const & o)
4665 {
4666 return(sin(o)/cos(o));
4667 }
4668
4669
4670 template<typename T>
4671 inline octonion<T> cosh(octonion<T> const & o)
4672 {
4673 return((exp(+o)+exp(-o))/static_cast<T>(2));
4674 }
4675
4676
4677 template<typename T>
4678 inline octonion<T> sinh(octonion<T> const & o)
4679 {
4680 return((exp(+o)-exp(-o))/static_cast<T>(2));
4681 }
4682
4683
4684 template<typename T>
4685 inline octonion<T> tanh(octonion<T> const & o)
4686 {
4687 return(sinh(o)/cosh(o));
4688 }
4689
4690
4691 template<typename T>
4692 octonion<T> pow(octonion<T> const & o,
4693 int n)
4694 {
4695 if (n > 1)
4696 {
4697 int m = n>>1;
4698
4699 octonion<T> result = pow(o, m);
4700
4701 result *= result;
4702
4703 if (n != (m<<1))
4704 {
4705 result *= o; // n odd
4706 }
4707
4708 return(result);
4709 }
4710 else if (n == 1)
4711 {
4712 return(o);
4713 }
4714 else if (n == 0)
4715 {
4716 return(octonion<T>(static_cast<T>(1)));
4717 }
4718 else /* n < 0 */
4719 {
4720 return(pow(octonion<T>(static_cast<T>(1))/o,-n));
4721 }
4722 }
4723
4724
4725 // helper templates for converting copy constructors (definition)
4726
4727 namespace detail
4728 {
4729
4730 template< typename T,
4731 typename U
4732 >
4733 octonion<T> octonion_type_converter(octonion<U> const & rhs)
4734 {
4735 return(octonion<T>( static_cast<T>(rhs.R_component_1()),
4736 static_cast<T>(rhs.R_component_2()),
4737 static_cast<T>(rhs.R_component_3()),
4738 static_cast<T>(rhs.R_component_4()),
4739 static_cast<T>(rhs.R_component_5()),
4740 static_cast<T>(rhs.R_component_6()),
4741 static_cast<T>(rhs.R_component_7()),
4742 static_cast<T>(rhs.R_component_8())));
4743 }
4744 }
4745 }
4746 }
4747
4748
4749 #if BOOST_WORKAROUND(__GNUC__, < 3)
4750 #undef BOOST_GET_VALARRAY
4751 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
4752
4753
4754 #endif /* BOOST_OCTONION_HPP */