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