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