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