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