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