Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-30 08:19:25

0001 //    boost octonion.hpp header file
0002 
0003 //  (C) Copyright Hubert Holin 2001.
0004 //  Distributed under the Boost Software License, Version 1.0. (See
0005 //  accompanying file LICENSE_1_0.txt or copy at
0006 //  http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 // See http://www.boost.org for updates, documentation, and revision history.
0009 
0010 
0011 #ifndef BOOST_OCTONION_HPP
0012 #define BOOST_OCTONION_HPP
0013 
0014 #include <boost/math/quaternion.hpp>
0015 #include <valarray>
0016 
0017 
0018 namespace boost
0019 {
0020     namespace math
0021     {
0022 
0023 #define    BOOST_OCTONION_ACCESSOR_GENERATOR(type)                      \
0024             type                        real() const                    \
0025             {                                                           \
0026                 return(a);                                              \
0027             }                                                           \
0028                                                                         \
0029             octonion<type>                unreal() const                \
0030             {                                                           \
0031                 return( octonion<type>(static_cast<type>(0),b,c,d,e,f,g,h));   \
0032             }                                                           \
0033                                                                         \
0034             type                            R_component_1() const       \
0035             {                                                           \
0036                 return(a);                                              \
0037             }                                                           \
0038                                                                         \
0039             type                            R_component_2() const       \
0040             {                                                           \
0041                 return(b);                                              \
0042             }                                                           \
0043                                                                         \
0044             type                            R_component_3() const       \
0045             {                                                           \
0046                 return(c);                                              \
0047             }                                                           \
0048                                                                         \
0049             type                            R_component_4() const       \
0050             {                                                           \
0051                 return(d);                                              \
0052             }                                                           \
0053                                                                         \
0054             type                            R_component_5() const       \
0055             {                                                           \
0056                 return(e);                                              \
0057             }                                                           \
0058                                                                         \
0059             type                            R_component_6() const       \
0060             {                                                           \
0061                 return(f);                                              \
0062             }                                                           \
0063                                                                         \
0064             type                            R_component_7() const       \
0065             {                                                           \
0066                 return(g);                                              \
0067             }                                                           \
0068                                                                         \
0069             type                            R_component_8() const       \
0070             {                                                           \
0071                 return(h);                                              \
0072             }                                                           \
0073                                                                         \
0074             ::std::complex<type>            C_component_1() const       \
0075             {                                                           \
0076                 return(::std::complex<type>(a,b));                      \
0077             }                                                           \
0078                                                                         \
0079             ::std::complex<type>            C_component_2() const       \
0080             {                                                           \
0081                 return(::std::complex<type>(c,d));                      \
0082             }                                                           \
0083                                                                         \
0084             ::std::complex<type>            C_component_3() const       \
0085             {                                                           \
0086                 return(::std::complex<type>(e,f));                      \
0087             }                                                           \
0088                                                                         \
0089             ::std::complex<type>            C_component_4() const       \
0090             {                                                           \
0091                 return(::std::complex<type>(g,h));                      \
0092             }                                                           \
0093                                                                         \
0094             ::boost::math::quaternion<type>    H_component_1() const    \
0095             {                                                           \
0096                 return(::boost::math::quaternion<type>(a,b,c,d));       \
0097             }                                                           \
0098                                                                         \
0099             ::boost::math::quaternion<type>    H_component_2() const    \
0100             {                                                           \
0101                 return(::boost::math::quaternion<type>(e,f,g,h));       \
0102             }
0103 
0104 
0105 #define    BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(type)                                         \
0106             template<typename X>                                                                    \
0107             octonion<type> &        operator = (octonion<X> const & a_affecter)                     \
0108             {                                                                                       \
0109                 a = static_cast<type>(a_affecter.R_component_1());                                  \
0110                 b = static_cast<type>(a_affecter.R_component_2());                                  \
0111                 c = static_cast<type>(a_affecter.R_component_3());                                  \
0112                 d = static_cast<type>(a_affecter.R_component_4());                                  \
0113                 e = static_cast<type>(a_affecter.R_component_5());                                  \
0114                 f = static_cast<type>(a_affecter.R_component_6());                                  \
0115                 g = static_cast<type>(a_affecter.R_component_7());                                  \
0116                 h = static_cast<type>(a_affecter.R_component_8());                                  \
0117                                                                                                     \
0118                 return(*this);                                                                      \
0119             }                                                                                       \
0120                                                                                                     \
0121             octonion<type> &        operator = (octonion<type> const & a_affecter)                  \
0122             {                                                                                       \
0123                 a = a_affecter.a;                                                                   \
0124                 b = a_affecter.b;                                                                   \
0125                 c = a_affecter.c;                                                                   \
0126                 d = a_affecter.d;                                                                   \
0127                 e = a_affecter.e;                                                                   \
0128                 f = a_affecter.f;                                                                   \
0129                 g = a_affecter.g;                                                                   \
0130                 h = a_affecter.h;                                                                   \
0131                                                                                                     \
0132                 return(*this);                                                                      \
0133             }                                                                                       \
0134                                                                                                     \
0135             octonion<type> &        operator = (type const & a_affecter)                            \
0136             {                                                                                       \
0137                 a = a_affecter;                                                                     \
0138                                                                                                     \
0139                 b = c = d = e = f= g = h = static_cast<type>(0);                                    \
0140                                                                                                     \
0141                 return(*this);                                                                      \
0142             }                                                                                       \
0143                                                                                                     \
0144             octonion<type> &        operator = (::std::complex<type> const & a_affecter)            \
0145             {                                                                                       \
0146                 a = a_affecter.real();                                                              \
0147                 b = a_affecter.imag();                                                              \
0148                                                                                                     \
0149                 c = d = e = f = g = h = static_cast<type>(0);                                       \
0150                                                                                                     \
0151                 return(*this);                                                                      \
0152             }                                                                                       \
0153                                                                                                     \
0154             octonion<type> &        operator = (::boost::math::quaternion<type> const & a_affecter) \
0155             {                                                                                       \
0156                 a = a_affecter.R_component_1();                                                     \
0157                 b = a_affecter.R_component_2();                                                     \
0158                 c = a_affecter.R_component_3();                                                     \
0159                 d = a_affecter.R_component_4();                                                     \
0160                                                                                                     \
0161                 e = f = g = h = static_cast<type>(0);                                               \
0162                                                                                                     \
0163                 return(*this);                                                                      \
0164             }
0165 
0166 
0167 #define    BOOST_OCTONION_MEMBER_DATA_GENERATOR(type) \
0168             type    a;                                \
0169             type    b;                                \
0170             type    c;                                \
0171             type    d;                                \
0172             type    e;                                \
0173             type    f;                                \
0174             type    g;                                \
0175             type    h;                                \
0176 
0177         // LCOV_EXCL_START
0178         // No code coverage for the generic case, like std::complex,
0179         // the The behavior of octonion is unspecified if T is not
0180         // one of float, double or long double.
0181 
0182         template<typename T>
0183         class octonion
0184         {
0185         public:
0186 
0187             using value_type = T;
0188 
0189             // constructor for O seen as R^8
0190             // (also default constructor)
0191 
0192             explicit                octonion(   T const & requested_a = T(),
0193                                                 T const & requested_b = T(),
0194                                                 T const & requested_c = T(),
0195                                                 T const & requested_d = T(),
0196                                                 T const & requested_e = T(),
0197                                                 T const & requested_f = T(),
0198                                                 T const & requested_g = T(),
0199                                                 T const & requested_h = T())
0200             :   a(requested_a),
0201                 b(requested_b),
0202                 c(requested_c),
0203                 d(requested_d),
0204                 e(requested_e),
0205                 f(requested_f),
0206                 g(requested_g),
0207                 h(requested_h)
0208             {
0209                 // nothing to do!
0210             }
0211 
0212 
0213             // constructor for H seen as C^4
0214 
0215             explicit                octonion(   ::std::complex<T> const & z0,
0216                                                 ::std::complex<T> const & z1 = ::std::complex<T>(),
0217                                                 ::std::complex<T> const & z2 = ::std::complex<T>(),
0218                                                 ::std::complex<T> const & z3 = ::std::complex<T>())
0219             :   a(z0.real()),
0220                 b(z0.imag()),
0221                 c(z1.real()),
0222                 d(z1.imag()),
0223                 e(z2.real()),
0224                 f(z2.imag()),
0225                 g(z3.real()),
0226                 h(z3.imag())
0227             {
0228                 // nothing to do!
0229             }
0230 
0231 
0232             // constructor for O seen as H^2
0233 
0234             explicit                octonion(   ::boost::math::quaternion<T> const & q0,
0235                                                 ::boost::math::quaternion<T> const & q1 = ::boost::math::quaternion<T>())
0236             :   a(q0.R_component_1()),
0237                 b(q0.R_component_2()),
0238                 c(q0.R_component_3()),
0239                 d(q0.R_component_4()),
0240                 e(q1.R_component_1()),
0241                 f(q1.R_component_2()),
0242                 g(q1.R_component_3()),
0243                 h(q1.R_component_4())
0244             {
0245                 // nothing to do!
0246             }
0247 
0248 
0249             // UNtemplated copy constructor
0250             octonion(const octonion&) = default;
0251 
0252 
0253             // templated copy constructor
0254 
0255             template<typename X>
0256             explicit                octonion(octonion<X> const & a_recopier)
0257             :   a(static_cast<T>(a_recopier.R_component_1())),
0258                 b(static_cast<T>(a_recopier.R_component_2())),
0259                 c(static_cast<T>(a_recopier.R_component_3())),
0260                 d(static_cast<T>(a_recopier.R_component_4())),
0261                 e(static_cast<T>(a_recopier.R_component_5())),
0262                 f(static_cast<T>(a_recopier.R_component_6())),
0263                 g(static_cast<T>(a_recopier.R_component_7())),
0264                 h(static_cast<T>(a_recopier.R_component_8()))
0265             {
0266                 // nothing to do!
0267             }
0268 
0269 
0270             // destructor
0271             ~octonion() = default;
0272 
0273 
0274             // accessors
0275             //
0276             // Note:    Like complex number, octonions do have a meaningful notion of "real part",
0277             //            but unlike them there is no meaningful notion of "imaginary part".
0278             //            Instead there is an "unreal part" which itself is an octonion, and usually
0279             //            nothing simpler (as opposed to the complex number case).
0280             //            However, for practicality, there are accessors for the other components
0281             //            (these are necessary for the templated copy constructor, for instance).
0282 
0283             BOOST_OCTONION_ACCESSOR_GENERATOR(T)
0284 
0285             // assignment operators
0286 
0287             BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(T)
0288 
0289             // other assignment-related operators
0290             //
0291             // NOTE:    Octonion multiplication is *NOT* commutative;
0292             //            symbolically, "q *= rhs;" means "q = q * rhs;"
0293             //            and "q /= rhs;" means "q = q * inverse_of(rhs);";
0294             //            octonion multiplication is also *NOT* associative
0295 
0296             octonion<T> &            operator += (T const & rhs)
0297             {
0298                 T    at = a + rhs;    // exception guard
0299 
0300                 a = at;
0301 
0302                 return(*this);
0303             }
0304 
0305 
0306             octonion<T> &            operator += (::std::complex<T> const & rhs)
0307             {
0308                 T    at = a + rhs.real();    // exception guard
0309                 T    bt = b + rhs.imag();    // exception guard
0310 
0311                 a = at;
0312                 b = bt;
0313 
0314                 return(*this);
0315             }
0316 
0317 
0318             octonion<T> &            operator += (::boost::math::quaternion<T> const & rhs)
0319             {
0320                 T    at = a + rhs.R_component_1();    // exception guard
0321                 T    bt = b + rhs.R_component_2();    // exception guard
0322                 T    ct = c + rhs.R_component_3();    // exception guard
0323                 T    dt = d + rhs.R_component_4();    // exception guard
0324 
0325                 a = at;
0326                 b = bt;
0327                 c = ct;
0328                 d = dt;
0329 
0330                 return(*this);
0331             }
0332 
0333 
0334             template<typename X>
0335             octonion<T> &            operator += (octonion<X> const & rhs)
0336             {
0337                 T    at = a + static_cast<T>(rhs.R_component_1());    // exception guard
0338                 T    bt = b + static_cast<T>(rhs.R_component_2());    // exception guard
0339                 T    ct = c + static_cast<T>(rhs.R_component_3());    // exception guard
0340                 T    dt = d + static_cast<T>(rhs.R_component_4());    // exception guard
0341                 T    et = e + static_cast<T>(rhs.R_component_5());    // exception guard
0342                 T    ft = f + static_cast<T>(rhs.R_component_6());    // exception guard
0343                 T    gt = g + static_cast<T>(rhs.R_component_7());    // exception guard
0344                 T    ht = h + static_cast<T>(rhs.R_component_8());    // exception guard
0345 
0346                 a = at;
0347                 b = bt;
0348                 c = ct;
0349                 d = dt;
0350                 e = et;
0351                 f = ft;
0352                 g = gt;
0353                 h = ht;
0354 
0355                 return(*this);
0356             }
0357 
0358 
0359 
0360             octonion<T> &            operator -= (T const & rhs)
0361             {
0362                 T    at = a - rhs;    // exception guard
0363 
0364                 a = at;
0365 
0366                 return(*this);
0367             }
0368 
0369 
0370             octonion<T> &            operator -= (::std::complex<T> const & rhs)
0371             {
0372                 T    at = a - rhs.real();    // exception guard
0373                 T    bt = b - rhs.imag();    // exception guard
0374 
0375                 a = at;
0376                 b = bt;
0377 
0378                 return(*this);
0379             }
0380 
0381 
0382             octonion<T> &            operator -= (::boost::math::quaternion<T> const & rhs)
0383             {
0384                 T    at = a - rhs.R_component_1();    // exception guard
0385                 T    bt = b - rhs.R_component_2();    // exception guard
0386                 T    ct = c - rhs.R_component_3();    // exception guard
0387                 T    dt = d - rhs.R_component_4();    // exception guard
0388 
0389                 a = at;
0390                 b = bt;
0391                 c = ct;
0392                 d = dt;
0393 
0394                 return(*this);
0395             }
0396 
0397 
0398             template<typename X>
0399             octonion<T> &            operator -= (octonion<X> const & rhs)
0400             {
0401                 T    at = a - static_cast<T>(rhs.R_component_1());    // exception guard
0402                 T    bt = b - static_cast<T>(rhs.R_component_2());    // exception guard
0403                 T    ct = c - static_cast<T>(rhs.R_component_3());    // exception guard
0404                 T    dt = d - static_cast<T>(rhs.R_component_4());    // exception guard
0405                 T    et = e - static_cast<T>(rhs.R_component_5());    // exception guard
0406                 T    ft = f - static_cast<T>(rhs.R_component_6());    // exception guard
0407                 T    gt = g - static_cast<T>(rhs.R_component_7());    // exception guard
0408                 T    ht = h - static_cast<T>(rhs.R_component_8());    // exception guard
0409 
0410                 a = at;
0411                 b = bt;
0412                 c = ct;
0413                 d = dt;
0414                 e = et;
0415                 f = ft;
0416                 g = gt;
0417                 h = ht;
0418 
0419                 return(*this);
0420             }
0421 
0422 
0423             octonion<T> &            operator *= (T const & rhs)
0424             {
0425                 T    at = a * rhs;    // exception guard
0426                 T    bt = b * rhs;    // exception guard
0427                 T    ct = c * rhs;    // exception guard
0428                 T    dt = d * rhs;    // exception guard
0429                 T    et = e * rhs;    // exception guard
0430                 T    ft = f * rhs;    // exception guard
0431                 T    gt = g * rhs;    // exception guard
0432                 T    ht = h * rhs;    // exception guard
0433 
0434                 a = at;
0435                 b = bt;
0436                 c = ct;
0437                 d = dt;
0438                 e = et;
0439                 f = ft;
0440                 g = gt;
0441                 h = ht;
0442 
0443                 return(*this);
0444             }
0445 
0446 
0447             octonion<T> &            operator *= (::std::complex<T> const & rhs)
0448             {
0449                 T    ar = rhs.real();
0450                 T    br = rhs.imag();
0451 
0452                 T    at = +a*ar-b*br;
0453                 T    bt = +a*br+b*ar;
0454                 T    ct = +c*ar+d*br;
0455                 T    dt = -c*br+d*ar;
0456                 T    et = +e*ar+f*br;
0457                 T    ft = -e*br+f*ar;
0458                 T    gt = +g*ar-h*br;
0459                 T    ht = +g*br+h*ar;
0460 
0461                 a = at;
0462                 b = bt;
0463                 c = ct;
0464                 d = dt;
0465                 e = et;
0466                 f = ft;
0467                 g = gt;
0468                 h = ht;
0469 
0470                 return(*this);
0471             }
0472 
0473 
0474             octonion<T> &            operator *= (::boost::math::quaternion<T> const & rhs)
0475             {
0476                 T    ar = rhs.R_component_1();
0477                 T    br = rhs.R_component_2();
0478                 T    cr = rhs.R_component_2();
0479                 T    dr = rhs.R_component_2();
0480 
0481                 T    at = +a*ar-b*br-c*cr-d*dr;
0482                 T    bt = +a*br+b*ar+c*dr-d*cr;
0483                 T    ct = +a*cr-b*dr+c*ar+d*br;
0484                 T    dt = +a*dr+b*cr-c*br+d*ar;
0485                 T    et = +e*ar+f*br+g*cr+h*dr;
0486                 T    ft = -e*br+f*ar-g*dr+h*cr;
0487                 T    gt = -e*cr+f*dr+g*ar-h*br;
0488                 T    ht = -e*dr-f*cr+g*br+h*ar;
0489 
0490                 a = at;
0491                 b = bt;
0492                 c = ct;
0493                 d = dt;
0494                 e = et;
0495                 f = ft;
0496                 g = gt;
0497                 h = ht;
0498 
0499                 return(*this);
0500             }
0501 
0502 
0503             template<typename X>
0504             octonion<T> &            operator *= (octonion<X> const & rhs)
0505             {
0506                 T    ar = static_cast<T>(rhs.R_component_1());
0507                 T    br = static_cast<T>(rhs.R_component_2());
0508                 T    cr = static_cast<T>(rhs.R_component_3());
0509                 T    dr = static_cast<T>(rhs.R_component_4());
0510                 T    er = static_cast<T>(rhs.R_component_5());
0511                 T    fr = static_cast<T>(rhs.R_component_6());
0512                 T    gr = static_cast<T>(rhs.R_component_7());
0513                 T    hr = static_cast<T>(rhs.R_component_8());
0514 
0515                 T    at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr;
0516                 T    bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr;
0517                 T    ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr;
0518                 T    dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er;
0519                 T    et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr;
0520                 T    ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr;
0521                 T    gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br;
0522                 T    ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar;
0523 
0524                 a = at;
0525                 b = bt;
0526                 c = ct;
0527                 d = dt;
0528                 e = et;
0529                 f = ft;
0530                 g = gt;
0531                 h = ht;
0532 
0533                 return(*this);
0534             }
0535 
0536 
0537             octonion<T> &            operator /= (T const & rhs)
0538             {
0539                 T    at = a / rhs;    // exception guard
0540                 T    bt = b / rhs;    // exception guard
0541                 T    ct = c / rhs;    // exception guard
0542                 T    dt = d / rhs;    // exception guard
0543                 T    et = e / rhs;    // exception guard
0544                 T    ft = f / rhs;    // exception guard
0545                 T    gt = g / rhs;    // exception guard
0546                 T    ht = h / rhs;    // exception guard
0547 
0548                 a = at;
0549                 b = bt;
0550                 c = ct;
0551                 d = dt;
0552                 e = et;
0553                 f = ft;
0554                 g = gt;
0555                 h = ht;
0556 
0557                 return(*this);
0558             }
0559 
0560 
0561             octonion<T> &            operator /= (::std::complex<T> const & rhs)
0562             {
0563                 T    ar = rhs.real();
0564                 T    br = rhs.imag();
0565 
0566                 T    denominator = ar*ar+br*br;
0567 
0568                 T    at = (+a*ar-b*br)/denominator;
0569                 T    bt = (-a*br+b*ar)/denominator;
0570                 T    ct = (+c*ar-d*br)/denominator;
0571                 T    dt = (+c*br+d*ar)/denominator;
0572                 T    et = (+e*ar-f*br)/denominator;
0573                 T    ft = (+e*br+f*ar)/denominator;
0574                 T    gt = (+g*ar+h*br)/denominator;
0575                 T    ht = (+g*br+h*ar)/denominator;
0576 
0577                 a = at;
0578                 b = bt;
0579                 c = ct;
0580                 d = dt;
0581                 e = et;
0582                 f = ft;
0583                 g = gt;
0584                 h = ht;
0585 
0586                 return(*this);
0587             }
0588 
0589 
0590             octonion<T> &            operator /= (::boost::math::quaternion<T> const & rhs)
0591             {
0592                 T    ar = rhs.R_component_1();
0593                 T    br = rhs.R_component_2();
0594                 T    cr = rhs.R_component_2();
0595                 T    dr = rhs.R_component_2();
0596 
0597                 T    denominator = ar*ar+br*br+cr*cr+dr*dr;
0598 
0599                 T    at = (+a*ar+b*br+c*cr+d*dr)/denominator;
0600                 T    bt = (-a*br+b*ar-c*dr+d*cr)/denominator;
0601                 T    ct = (-a*cr+b*dr+c*ar-d*br)/denominator;
0602                 T    dt = (-a*dr-b*cr+c*br+d*ar)/denominator;
0603                 T    et = (+e*ar-f*br-g*cr-h*dr)/denominator;
0604                 T    ft = (+e*br+f*ar+g*dr-h*cr)/denominator;
0605                 T    gt = (+e*cr-f*dr+g*ar+h*br)/denominator;
0606                 T    ht = (+e*dr+f*cr-g*br+h*ar)/denominator;
0607 
0608                 a = at;
0609                 b = bt;
0610                 c = ct;
0611                 d = dt;
0612                 e = et;
0613                 f = ft;
0614                 g = gt;
0615                 h = ht;
0616 
0617                 return(*this);
0618             }
0619 
0620 
0621             template<typename X>
0622             octonion<T> &            operator /= (octonion<X> const & rhs)
0623             {
0624                 T    ar = static_cast<T>(rhs.R_component_1());
0625                 T    br = static_cast<T>(rhs.R_component_2());
0626                 T    cr = static_cast<T>(rhs.R_component_3());
0627                 T    dr = static_cast<T>(rhs.R_component_4());
0628                 T    er = static_cast<T>(rhs.R_component_5());
0629                 T    fr = static_cast<T>(rhs.R_component_6());
0630                 T    gr = static_cast<T>(rhs.R_component_7());
0631                 T    hr = static_cast<T>(rhs.R_component_8());
0632 
0633                 T    denominator = ar*ar+br*br+cr*cr+dr*dr+er*er+fr*fr+gr*gr+hr*hr;
0634 
0635                 T    at = (+a*ar+b*br+c*cr+d*dr+e*er+f*fr+g*gr+h*hr)/denominator;
0636                 T    bt = (-a*br+b*ar-c*dr+d*cr-e*fr+f*er+g*hr-h*gr)/denominator;
0637                 T    ct = (-a*cr+b*dr+c*ar-d*br-e*gr-f*hr+g*er+h*fr)/denominator;
0638                 T    dt = (-a*dr-b*cr+c*br+d*ar-e*hr+f*gr-g*fr+h*er)/denominator;
0639                 T    et = (-a*er+b*fr+c*gr+d*hr+e*ar-f*br-g*cr-h*dr)/denominator;
0640                 T    ft = (-a*fr-b*er+c*hr-d*gr+e*br+f*ar+g*dr-h*cr)/denominator;
0641                 T    gt = (-a*gr-b*hr-c*er+d*fr+e*cr-f*dr+g*ar+h*br)/denominator;
0642                 T    ht = (-a*hr+b*gr-c*fr-d*er+e*dr+f*cr-g*br+h*ar)/denominator;
0643 
0644                 a = at;
0645                 b = bt;
0646                 c = ct;
0647                 d = dt;
0648                 e = et;
0649                 f = ft;
0650                 g = gt;
0651                 h = ht;
0652 
0653                 return(*this);
0654             }
0655 
0656 
0657         protected:
0658 
0659             BOOST_OCTONION_MEMBER_DATA_GENERATOR(T)
0660 
0661 
0662         private:
0663 
0664         };
0665         // LCOV_EXCL_STOP
0666 
0667         // declaration of octonion specialization
0668 
0669         template<>    class octonion<float>;
0670         template<>    class octonion<double>;
0671         template<>    class octonion<long double>;
0672 
0673 
0674         // helper templates for converting copy constructors (declaration)
0675 
0676         namespace detail
0677         {
0678 
0679             template<   typename T,
0680                         typename U
0681                     >
0682             octonion<T>    octonion_type_converter(octonion<U> const & rhs);
0683         }
0684 
0685 
0686         // implementation of octonion specialization
0687 
0688 
0689 #define    BOOST_OCTONION_CONSTRUCTOR_GENERATOR(type)                                                                               \
0690             explicit                    octonion(   type const & requested_a = static_cast<type>(0),                                \
0691                                                     type const & requested_b = static_cast<type>(0),                                \
0692                                                     type const & requested_c = static_cast<type>(0),                                \
0693                                                     type const & requested_d = static_cast<type>(0),                                \
0694                                                     type const & requested_e = static_cast<type>(0),                                \
0695                                                     type const & requested_f = static_cast<type>(0),                                \
0696                                                     type const & requested_g = static_cast<type>(0),                                \
0697                                                     type const & requested_h = static_cast<type>(0))                                \
0698             :   a(requested_a),                                                                                                     \
0699                 b(requested_b),                                                                                                     \
0700                 c(requested_c),                                                                                                     \
0701                 d(requested_d),                                                                                                     \
0702                 e(requested_e),                                                                                                     \
0703                 f(requested_f),                                                                                                     \
0704                 g(requested_g),                                                                                                     \
0705                 h(requested_h)                                                                                                      \
0706             {                                                                                                                       \
0707             }                                                                                                                       \
0708                                                                                                                                     \
0709             explicit                    octonion(   ::std::complex<type> const & z0,                                                \
0710                                                     ::std::complex<type> const & z1 = ::std::complex<type>(),                       \
0711                                                     ::std::complex<type> const & z2 = ::std::complex<type>(),                       \
0712                                                     ::std::complex<type> const & z3 = ::std::complex<type>())                       \
0713             :   a(z0.real()),                                                                                                       \
0714                 b(z0.imag()),                                                                                                       \
0715                 c(z1.real()),                                                                                                       \
0716                 d(z1.imag()),                                                                                                       \
0717                 e(z2.real()),                                                                                                       \
0718                 f(z2.imag()),                                                                                                       \
0719                 g(z3.real()),                                                                                                       \
0720                 h(z3.imag())                                                                                                        \
0721             {                                                                                                                       \
0722             }                                                                                                                       \
0723                                                                                                                                     \
0724             explicit                    octonion(   ::boost::math::quaternion<type> const & q0,                                     \
0725                                                     ::boost::math::quaternion<type> const & q1 = ::boost::math::quaternion<type>()) \
0726             :   a(q0.R_component_1()),                                                                                              \
0727                 b(q0.R_component_2()),                                                                                              \
0728                 c(q0.R_component_3()),                                                                                              \
0729                 d(q0.R_component_4()),                                                                                              \
0730                 e(q1.R_component_1()),                                                                                              \
0731                 f(q1.R_component_2()),                                                                                              \
0732                 g(q1.R_component_3()),                                                                                              \
0733                 h(q1.R_component_4())                                                                                               \
0734             {                                                                                                                       \
0735             }
0736 
0737 
0738 #define    BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type)                  \
0739             octonion<type> &            operator += (type const & rhs)  \
0740             {                                                           \
0741                 a += rhs;                                               \
0742                                                                         \
0743                 return(*this);                                          \
0744             }
0745 
0746 #define    BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type)                                  \
0747             octonion<type> &            operator += (::std::complex<type> const & rhs)  \
0748             {                                                                           \
0749                 a += rhs.real();                                                        \
0750                 b += rhs.imag();                                                        \
0751                                                                                         \
0752                 return(*this);                                                          \
0753             }
0754 
0755 #define    BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type)                                              \
0756             octonion<type> &            operator += (::boost::math::quaternion<type> const & rhs)   \
0757             {                                                                                       \
0758                 a += rhs.R_component_1();                                                           \
0759                 b += rhs.R_component_2();                                                           \
0760                 c += rhs.R_component_3();                                                           \
0761                 d += rhs.R_component_4();                                                           \
0762                                                                                                     \
0763                 return(*this);                                                                      \
0764             }
0765 
0766 #define    BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type)                          \
0767             template<typename X>                                                \
0768             octonion<type> &            operator += (octonion<X> const & rhs)   \
0769             {                                                                   \
0770                 a += static_cast<type>(rhs.R_component_1());                    \
0771                 b += static_cast<type>(rhs.R_component_2());                    \
0772                 c += static_cast<type>(rhs.R_component_3());                    \
0773                 d += static_cast<type>(rhs.R_component_4());                    \
0774                 e += static_cast<type>(rhs.R_component_5());                    \
0775                 f += static_cast<type>(rhs.R_component_6());                    \
0776                 g += static_cast<type>(rhs.R_component_7());                    \
0777                 h += static_cast<type>(rhs.R_component_8());                    \
0778                                                                                 \
0779                 return(*this);                                                  \
0780             }
0781 
0782 #define    BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type)                  \
0783             octonion<type> &            operator -= (type const & rhs)  \
0784             {                                                           \
0785                 a -= rhs;                                               \
0786                                                                         \
0787                 return(*this);                                          \
0788             }
0789 
0790 #define    BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type)                                  \
0791             octonion<type> &            operator -= (::std::complex<type> const & rhs)  \
0792             {                                                                           \
0793                 a -= rhs.real();                                                        \
0794                 b -= rhs.imag();                                                        \
0795                                                                                         \
0796                 return(*this);                                                          \
0797             }
0798 
0799 #define    BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type)                                              \
0800             octonion<type> &            operator -= (::boost::math::quaternion<type> const & rhs)   \
0801             {                                                                                       \
0802                 a -= rhs.R_component_1();                                                           \
0803                 b -= rhs.R_component_2();                                                           \
0804                 c -= rhs.R_component_3();                                                           \
0805                 d -= rhs.R_component_4();                                                           \
0806                                                                                                     \
0807                 return(*this);                                                                      \
0808             }
0809 
0810 #define    BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type)                        \
0811             template<typename X>                                              \
0812             octonion<type> &            operator -= (octonion<X> const & rhs) \
0813             {                                                                 \
0814                 a -= static_cast<type>(rhs.R_component_1());                  \
0815                 b -= static_cast<type>(rhs.R_component_2());                  \
0816                 c -= static_cast<type>(rhs.R_component_3());                  \
0817                 d -= static_cast<type>(rhs.R_component_4());                  \
0818                 e -= static_cast<type>(rhs.R_component_5());                  \
0819                 f -= static_cast<type>(rhs.R_component_6());                  \
0820                 g -= static_cast<type>(rhs.R_component_7());                  \
0821                 h -= static_cast<type>(rhs.R_component_8());                  \
0822                                                                               \
0823                 return(*this);                                                \
0824             }
0825 
0826 #define    BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type)                   \
0827             octonion<type> &            operator *= (type const & rhs)   \
0828             {                                                            \
0829                 a *= rhs;                                                \
0830                 b *= rhs;                                                \
0831                 c *= rhs;                                                \
0832                 d *= rhs;                                                \
0833                 e *= rhs;                                                \
0834                 f *= rhs;                                                \
0835                 g *= rhs;                                                \
0836                 h *= rhs;                                                \
0837                                                                          \
0838                 return(*this);                                           \
0839             }
0840 
0841 #define    BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type)                                  \
0842             octonion<type> &            operator *= (::std::complex<type> const & rhs)  \
0843             {                                                                           \
0844                 type    ar = rhs.real();                                                \
0845                 type    br = rhs.imag();                                                \
0846                                                                                         \
0847                 type    at = +a*ar-b*br;                                                \
0848                 type    bt = +a*br+b*ar;                                                \
0849                 type    ct = +c*ar+d*br;                                                \
0850                 type    dt = -c*br+d*ar;                                                \
0851                 type    et = +e*ar+f*br;                                                \
0852                 type    ft = -e*br+f*ar;                                                \
0853                 type    gt = +g*ar-h*br;                                                \
0854                 type    ht = +g*br+h*ar;                                                \
0855                                                                                         \
0856                 a = at;                                                                 \
0857                 b = bt;                                                                 \
0858                 c = ct;                                                                 \
0859                 d = dt;                                                                 \
0860                 e = et;                                                                 \
0861                 f = ft;                                                                 \
0862                 g = gt;                                                                 \
0863                 h = ht;                                                                 \
0864                                                                                         \
0865                 return(*this);                                                          \
0866             }
0867 
0868 #define    BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type)                                                    \
0869             octonion<type> &            operator *= (::boost::math::quaternion<type> const & rhs)   \
0870             {                                                                                       \
0871                 type    ar = rhs.R_component_1();                                                   \
0872                 type    br = rhs.R_component_2();                                                   \
0873                 type    cr = rhs.R_component_2();                                                   \
0874                 type    dr = rhs.R_component_2();                                                   \
0875                                                                                                     \
0876                 type    at = +a*ar-b*br-c*cr-d*dr;                                                  \
0877                 type    bt = +a*br+b*ar+c*dr-d*cr;                                                  \
0878                 type    ct = +a*cr-b*dr+c*ar+d*br;                                                  \
0879                 type    dt = +a*dr+b*cr-c*br+d*ar;                                                  \
0880                 type    et = +e*ar+f*br+g*cr+h*dr;                                                  \
0881                 type    ft = -e*br+f*ar-g*dr+h*cr;                                                  \
0882                 type    gt = -e*cr+f*dr+g*ar-h*br;                                                  \
0883                 type    ht = -e*dr-f*cr+g*br+h*ar;                                                  \
0884                                                                                                     \
0885                 a = at;                                                                             \
0886                 b = bt;                                                                             \
0887                 c = ct;                                                                             \
0888                 d = dt;                                                                             \
0889                 e = et;                                                                             \
0890                 f = ft;                                                                             \
0891                 g = gt;                                                                             \
0892                 h = ht;                                                                             \
0893                                                                                                     \
0894                 return(*this);                                                                      \
0895             }
0896 
0897 #define    BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type)                          \
0898             template<typename X>                                                \
0899             octonion<type> &            operator *= (octonion<X> const & rhs)   \
0900             {                                                                   \
0901                 type    ar = static_cast<type>(rhs.R_component_1());            \
0902                 type    br = static_cast<type>(rhs.R_component_2());            \
0903                 type    cr = static_cast<type>(rhs.R_component_3());            \
0904                 type    dr = static_cast<type>(rhs.R_component_4());            \
0905                 type    er = static_cast<type>(rhs.R_component_5());            \
0906                 type    fr = static_cast<type>(rhs.R_component_6());            \
0907                 type    gr = static_cast<type>(rhs.R_component_7());            \
0908                 type    hr = static_cast<type>(rhs.R_component_8());            \
0909                                                                                 \
0910                 type    at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr;          \
0911                 type    bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr;          \
0912                 type    ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr;          \
0913                 type    dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er;          \
0914                 type    et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr;          \
0915                 type    ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr;          \
0916                 type    gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br;          \
0917                 type    ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar;          \
0918                                                                                 \
0919                 a = at;                                                         \
0920                 b = bt;                                                         \
0921                 c = ct;                                                         \
0922                 d = dt;                                                         \
0923                 e = et;                                                         \
0924                 f = ft;                                                         \
0925                 g = gt;                                                         \
0926                 h = ht;                                                         \
0927                                                                                 \
0928                 return(*this);                                                  \
0929             }
0930 
0931 // There is quite a lot of repetition in the code below. This is intentional.
0932 // The last conditional block is the normal form, and the others merely
0933 // consist of workarounds for various compiler deficiencies. Hopefully, when
0934 // more compilers are conformant and we can retire support for those that are
0935 // not, we will be able to remove the clutter. This is makes the situation
0936 // (painfully) explicit.
0937 
0938 #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type)                  \
0939             octonion<type> &            operator /= (type const & rhs)  \
0940             {                                                           \
0941                 a /= rhs;                                               \
0942                 b /= rhs;                                               \
0943                 c /= rhs;                                               \
0944                 d /= rhs;                                               \
0945                                                                         \
0946                 return(*this);                                          \
0947             }
0948 
0949 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
0950     #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type)                              \
0951             octonion<type> &            operator /= (::std::complex<type> const & rhs)  \
0952             {                                                                           \
0953                 using    ::std::valarray;                                               \
0954                 using    ::std::abs;                                                    \
0955                                                                                         \
0956                 valarray<type>    tr(2);                                                \
0957                                                                                         \
0958                 tr[0] = rhs.real();                                                     \
0959                 tr[1] = rhs.imag();                                                     \
0960                                                                                         \
0961                 type            mixam = static_cast<type>(1)/(abs(tr).max)();           \
0962                                                                                         \
0963                 tr *= mixam;                                                            \
0964                                                                                         \
0965                 valarray<type>    tt(8);                                                \
0966                                                                                         \
0967                 tt[0] = +a*tr[0]-b*tr[1];                                               \
0968                 tt[1] = -a*tr[1]+b*tr[0];                                               \
0969                 tt[2] = +c*tr[0]-d*tr[1];                                               \
0970                 tt[3] = +c*tr[1]+d*tr[0];                                               \
0971                 tt[4] = +e*tr[0]-f*tr[1];                                               \
0972                 tt[5] = +e*tr[1]+f*tr[0];                                               \
0973                 tt[6] = +g*tr[0]+h*tr[1];                                               \
0974                 tt[7] = +g*tr[1]+h*tr[0];                                               \
0975                                                                                         \
0976                 tr *= tr;                                                               \
0977                                                                                         \
0978                 tt *= (mixam/tr.sum());                                                 \
0979                                                                                         \
0980                 a = tt[0];                                                              \
0981                 b = tt[1];                                                              \
0982                 c = tt[2];                                                              \
0983                 d = tt[3];                                                              \
0984                 e = tt[4];                                                              \
0985                 f = tt[5];                                                              \
0986                 g = tt[6];                                                              \
0987                 h = tt[7];                                                              \
0988                                                                                         \
0989                 return(*this);                                                          \
0990             }
0991 #else
0992     #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type)                              \
0993             octonion<type> &            operator /= (::std::complex<type> const & rhs)  \
0994             {                                                                           \
0995                 using    ::std::valarray;                                               \
0996                                                                                         \
0997                 valarray<type>    tr(2);                                                \
0998                                                                                         \
0999                 tr[0] = rhs.real();                                                     \
1000                 tr[1] = rhs.imag();                                                     \
1001                                                                                         \
1002                 type            mixam = static_cast<type>(1)/(abs(tr).max)();           \
1003                                                                                         \
1004                 tr *= mixam;                                                            \
1005                                                                                         \
1006                 valarray<type>    tt(8);                                                \
1007                                                                                         \
1008                 tt[0] = +a*tr[0]-b*tr[1];                                               \
1009                 tt[1] = -a*tr[1]+b*tr[0];                                               \
1010                 tt[2] = +c*tr[0]-d*tr[1];                                               \
1011                 tt[3] = +c*tr[1]+d*tr[0];                                               \
1012                 tt[4] = +e*tr[0]-f*tr[1];                                               \
1013                 tt[5] = +e*tr[1]+f*tr[0];                                               \
1014                 tt[6] = +g*tr[0]+h*tr[1];                                               \
1015                 tt[7] = +g*tr[1]+h*tr[0];                                               \
1016                                                                                         \
1017                 tr *= tr;                                                               \
1018                                                                                         \
1019                 tt *= (mixam/tr.sum());                                                 \
1020                                                                                         \
1021                 a = tt[0];                                                              \
1022                 b = tt[1];                                                              \
1023                 c = tt[2];                                                              \
1024                 d = tt[3];                                                              \
1025                 e = tt[4];                                                              \
1026                 f = tt[5];                                                              \
1027                 g = tt[6];                                                              \
1028                 h = tt[7];                                                              \
1029                                                                                         \
1030                 return(*this);                                                          \
1031             }
1032 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1033 
1034 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1035     #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type)                                           \
1036             octonion<type> &            operator /= (::boost::math::quaternion<type> const & rhs)    \
1037             {                                                                                        \
1038                 using    ::std::valarray;                                                            \
1039                 using    ::std::abs;                                                                 \
1040                                                                                                      \
1041                 valarray<type>    tr(4);                                                             \
1042                                                                                                      \
1043                 tr[0] = static_cast<type>(rhs.R_component_1());                                      \
1044                 tr[1] = static_cast<type>(rhs.R_component_2());                                      \
1045                 tr[2] = static_cast<type>(rhs.R_component_3());                                      \
1046                 tr[3] = static_cast<type>(rhs.R_component_4());                                      \
1047                                                                                                      \
1048                 type            mixam = static_cast<type>(1)/(abs(tr).max)();                        \
1049                                                                                                      \
1050                 tr *= mixam;                                                                         \
1051                                                                                                      \
1052                 valarray<type>    tt(8);                                                             \
1053                                                                                                      \
1054                 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3];                                            \
1055                 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2];                                            \
1056                 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1];                                            \
1057                 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0];                                            \
1058                 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3];                                            \
1059                 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2];                                            \
1060                 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1];                                            \
1061                 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0];                                            \
1062                                                                                                      \
1063                 tr *= tr;                                                                            \
1064                                                                                                      \
1065                 tt *= (mixam/tr.sum());                                                              \
1066                                                                                                      \
1067                 a = tt[0];                                                                           \
1068                 b = tt[1];                                                                           \
1069                 c = tt[2];                                                                           \
1070                 d = tt[3];                                                                           \
1071                 e = tt[4];                                                                           \
1072                 f = tt[5];                                                                           \
1073                 g = tt[6];                                                                           \
1074                 h = tt[7];                                                                           \
1075                                                                                                      \
1076                 return(*this);                                                                       \
1077             }
1078 #else
1079     #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type)                                           \
1080             octonion<type> &            operator /= (::boost::math::quaternion<type> const & rhs)    \
1081             {                                                                                        \
1082                 using    ::std::valarray;                                                            \
1083                                                                                                      \
1084                 valarray<type>    tr(4);                                                             \
1085                                                                                                      \
1086                 tr[0] = static_cast<type>(rhs.R_component_1());                                      \
1087                 tr[1] = static_cast<type>(rhs.R_component_2());                                      \
1088                 tr[2] = static_cast<type>(rhs.R_component_3());                                      \
1089                 tr[3] = static_cast<type>(rhs.R_component_4());                                      \
1090                                                                                                      \
1091                 type            mixam = static_cast<type>(1)/(abs(tr).max)();                        \
1092                                                                                                      \
1093                 tr *= mixam;                                                                         \
1094                                                                                                      \
1095                 valarray<type>    tt(8);                                                             \
1096                                                                                                      \
1097                 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3];                                            \
1098                 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2];                                            \
1099                 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1];                                            \
1100                 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0];                                            \
1101                 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3];                                            \
1102                 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2];                                            \
1103                 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1];                                            \
1104                 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0];                                            \
1105                                                                                                      \
1106                 tr *= tr;                                                                            \
1107                                                                                                      \
1108                 tt *= (mixam/tr.sum());                                                              \
1109                                                                                                      \
1110                 a = tt[0];                                                                           \
1111                 b = tt[1];                                                                           \
1112                 c = tt[2];                                                                           \
1113                 d = tt[3];                                                                           \
1114                 e = tt[4];                                                                           \
1115                 f = tt[5];                                                                           \
1116                 g = tt[6];                                                                           \
1117                 h = tt[7];                                                                           \
1118                                                                                                      \
1119                 return(*this);                                                                       \
1120             }
1121 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1122 
1123 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
1124     #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type)                                           \
1125             template<typename X>                                                                     \
1126             octonion<type> &            operator /= (octonion<X> const & rhs)                        \
1127             {                                                                                        \
1128                 using    ::std::valarray;                                                            \
1129                 using    ::std::abs;                                                                 \
1130                                                                                                      \
1131                 valarray<type>    tr(8);                                                             \
1132                                                                                                      \
1133                 tr[0] = static_cast<type>(rhs.R_component_1());                                      \
1134                 tr[1] = static_cast<type>(rhs.R_component_2());                                      \
1135                 tr[2] = static_cast<type>(rhs.R_component_3());                                      \
1136                 tr[3] = static_cast<type>(rhs.R_component_4());                                      \
1137                 tr[4] = static_cast<type>(rhs.R_component_5());                                      \
1138                 tr[5] = static_cast<type>(rhs.R_component_6());                                      \
1139                 tr[6] = static_cast<type>(rhs.R_component_7());                                      \
1140                 tr[7] = static_cast<type>(rhs.R_component_8());                                      \
1141                                                                                                      \
1142                 type            mixam = static_cast<type>(1)/(abs(tr).max)();                        \
1143                                                                                                      \
1144                 tr *= mixam;                                                                         \
1145                                                                                                      \
1146                 valarray<type>    tt(8);                                                             \
1147                                                                                                      \
1148                 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];            \
1149                 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];            \
1150                 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];            \
1151                 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];            \
1152                 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];            \
1153                 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];            \
1154                 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];            \
1155                 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];            \
1156                                                                                                      \
1157                 tr *= tr;                                                                            \
1158                                                                                                      \
1159                 tt *= (mixam/tr.sum());                                                              \
1160                                                                                                      \
1161                 a = tt[0];                                                                           \
1162                 b = tt[1];                                                                           \
1163                 c = tt[2];                                                                           \
1164                 d = tt[3];                                                                           \
1165                 e = tt[4];                                                                           \
1166                 f = tt[5];                                                                           \
1167                 g = tt[6];                                                                           \
1168                 h = tt[7];                                                                           \
1169                                                                                                      \
1170                 return(*this);                                                                       \
1171             }
1172 #else
1173     #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type)                                           \
1174             template<typename X>                                                                     \
1175             octonion<type> &            operator /= (octonion<X> const & rhs)                        \
1176             {                                                                                        \
1177                 using    ::std::valarray;                                                            \
1178                                                                                                      \
1179                 valarray<type>    tr(8);                                                             \
1180                                                                                                      \
1181                 tr[0] = static_cast<type>(rhs.R_component_1());                                      \
1182                 tr[1] = static_cast<type>(rhs.R_component_2());                                      \
1183                 tr[2] = static_cast<type>(rhs.R_component_3());                                      \
1184                 tr[3] = static_cast<type>(rhs.R_component_4());                                      \
1185                 tr[4] = static_cast<type>(rhs.R_component_5());                                      \
1186                 tr[5] = static_cast<type>(rhs.R_component_6());                                      \
1187                 tr[6] = static_cast<type>(rhs.R_component_7());                                      \
1188                 tr[7] = static_cast<type>(rhs.R_component_8());                                      \
1189                                                                                                      \
1190                 type            mixam = static_cast<type>(1)/(abs(tr).max)();                        \
1191                                                                                                      \
1192                 tr *= mixam;                                                                         \
1193                                                                                                      \
1194                 valarray<type>    tt(8);                                                             \
1195                                                                                                      \
1196                 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];            \
1197                 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];            \
1198                 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];            \
1199                 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];            \
1200                 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];            \
1201                 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];            \
1202                 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];            \
1203                 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];            \
1204                                                                                                      \
1205                 tr *= tr;                                                                            \
1206                                                                                                      \
1207                 tt *= (mixam/tr.sum());                                                              \
1208                                                                                                      \
1209                 a = tt[0];                                                                           \
1210                 b = tt[1];                                                                           \
1211                 c = tt[2];                                                                           \
1212                 d = tt[3];                                                                           \
1213                 e = tt[4];                                                                           \
1214                 f = tt[5];                                                                           \
1215                 g = tt[6];                                                                           \
1216                 h = tt[7];                                                                           \
1217                                                                                                      \
1218                 return(*this);                                                                       \
1219             }
1220 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
1221 
1222 
1223 #define    BOOST_OCTONION_MEMBER_ADD_GENERATOR(type)       \
1224         BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type)        \
1225         BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type)        \
1226         BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type)        \
1227         BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type)
1228 
1229 #define    BOOST_OCTONION_MEMBER_SUB_GENERATOR(type)       \
1230         BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type)        \
1231         BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type)        \
1232         BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type)        \
1233         BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type)
1234 
1235 #define    BOOST_OCTONION_MEMBER_MUL_GENERATOR(type)       \
1236         BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type)        \
1237         BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type)        \
1238         BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type)        \
1239         BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type)
1240 
1241 #define    BOOST_OCTONION_MEMBER_DIV_GENERATOR(type)       \
1242         BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type)        \
1243         BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type)        \
1244         BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type)        \
1245         BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type)
1246 
1247 #define    BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(type) \
1248         BOOST_OCTONION_MEMBER_ADD_GENERATOR(type)          \
1249         BOOST_OCTONION_MEMBER_SUB_GENERATOR(type)          \
1250         BOOST_OCTONION_MEMBER_MUL_GENERATOR(type)          \
1251         BOOST_OCTONION_MEMBER_DIV_GENERATOR(type)
1252 
1253 
1254         template<>
1255         class octonion<float>
1256         {
1257         public:
1258 
1259             using value_type = float;
1260 
1261             BOOST_OCTONION_CONSTRUCTOR_GENERATOR(float)
1262 
1263             // UNtemplated copy constructor
1264             octonion(const octonion&) = default;
1265 
1266             // explicit copy constructors (precision-losing converters)
1267 
1268             explicit                    octonion(octonion<double> const & a_recopier)
1269             {
1270                 *this = detail::octonion_type_converter<float, double>(a_recopier);
1271             }
1272 
1273             explicit                    octonion(octonion<long double> const & a_recopier)
1274             {
1275                 *this = detail::octonion_type_converter<float, long double>(a_recopier);
1276             }
1277 
1278             // destructor
1279             ~octonion() = default;
1280 
1281             // accessors
1282             //
1283             // Note:    Like complex number, octonions do have a meaningful notion of "real part",
1284             //            but unlike them there is no meaningful notion of "imaginary part".
1285             //            Instead there is an "unreal part" which itself is an octonion, and usually
1286             //            nothing simpler (as opposed to the complex number case).
1287             //            However, for practicality, there are accessors for the other components
1288             //            (these are necessary for the templated copy constructor, for instance).
1289 
1290             BOOST_OCTONION_ACCESSOR_GENERATOR(float)
1291 
1292             // assignment operators
1293 
1294             BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(float)
1295 
1296             // other assignment-related operators
1297             //
1298             // NOTE:    Octonion multiplication is *NOT* commutative;
1299             //            symbolically, "q *= rhs;" means "q = q * rhs;"
1300             //            and "q /= rhs;" means "q = q * inverse_of(rhs);";
1301             //            octonion multiplication is also *NOT* associative
1302 
1303             BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(float)
1304 
1305 
1306         protected:
1307 
1308             BOOST_OCTONION_MEMBER_DATA_GENERATOR(float)
1309         };
1310 
1311 
1312         template<>
1313         class octonion<double>
1314         {
1315         public:
1316 
1317             using value_type = double;
1318 
1319             BOOST_OCTONION_CONSTRUCTOR_GENERATOR(double)
1320 
1321             // Untemplated copy constructor
1322             octonion(const octonion&) = default;
1323 
1324             // converting copy constructor
1325 
1326             explicit                    octonion(octonion<float> const & a_recopier)
1327             {
1328                 *this = detail::octonion_type_converter<double, float>(a_recopier);
1329             }
1330 
1331             // explicit copy constructors (precision-losing converters)
1332 
1333             explicit                    octonion(octonion<long double> const & a_recopier)
1334             {
1335                 *this = detail::octonion_type_converter<double, long double>(a_recopier);
1336             }
1337 
1338             // destructor
1339             // (this is taken care of by the compiler itself)
1340 
1341             // accessors
1342             //
1343             // Note:    Like complex number, octonions do have a meaningful notion of "real part",
1344             //            but unlike them there is no meaningful notion of "imaginary part".
1345             //            Instead there is an "unreal part" which itself is an octonion, and usually
1346             //            nothing simpler (as opposed to the complex number case).
1347             //            However, for practicality, there are accessors for the other components
1348             //            (these are necessary for the templated copy constructor, for instance).
1349 
1350             BOOST_OCTONION_ACCESSOR_GENERATOR(double)
1351 
1352             // assignment operators
1353 
1354             BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(double)
1355 
1356             // other assignment-related operators
1357             //
1358             // NOTE:    Octonion multiplication is *NOT* commutative;
1359             //            symbolically, "q *= rhs;" means "q = q * rhs;"
1360             //            and "q /= rhs;" means "q = q * inverse_of(rhs);";
1361             //            octonion multiplication is also *NOT* associative
1362 
1363             BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(double)
1364 
1365 
1366         protected:
1367 
1368             BOOST_OCTONION_MEMBER_DATA_GENERATOR(double)
1369         };
1370 
1371 
1372         template<>
1373         class octonion<long double>
1374         {
1375         public:
1376 
1377             using value_type = long double;
1378 
1379             BOOST_OCTONION_CONSTRUCTOR_GENERATOR(long double)
1380 
1381             // UNtemplated copy constructor
1382             octonion(const octonion&) = default;
1383 
1384             // converting copy constructor
1385 
1386             explicit                            octonion(octonion<float> const & a_recopier)
1387             {
1388                 *this = detail::octonion_type_converter<long double, float>(a_recopier);
1389             }
1390 
1391 
1392             explicit                            octonion(octonion<double> const & a_recopier)
1393             {
1394                 *this = detail::octonion_type_converter<long double, double>(a_recopier);
1395             }
1396 
1397 
1398             // destructor
1399             // (this is taken care of by the compiler itself)
1400 
1401             // accessors
1402             //
1403             // Note:    Like complex number, octonions do have a meaningful notion of "real part",
1404             //            but unlike them there is no meaningful notion of "imaginary part".
1405             //            Instead there is an "unreal part" which itself is an octonion, and usually
1406             //            nothing simpler (as opposed to the complex number case).
1407             //            However, for practicality, there are accessors for the other components
1408             //            (these are necessary for the templated copy constructor, for instance).
1409 
1410             BOOST_OCTONION_ACCESSOR_GENERATOR(long double)
1411 
1412             // assignment operators
1413 
1414             BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(long double)
1415 
1416             // other assignment-related operators
1417             //
1418             // NOTE:    Octonion multiplication is *NOT* commutative;
1419             //            symbolically, "q *= rhs;" means "q = q * rhs;"
1420             //            and "q /= rhs;" means "q = q * inverse_of(rhs);";
1421             //            octonion multiplication is also *NOT* associative
1422 
1423             BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(long double)
1424 
1425 
1426         protected:
1427 
1428             BOOST_OCTONION_MEMBER_DATA_GENERATOR(long double)
1429 
1430 
1431         private:
1432 
1433         };
1434 
1435 
1436 #undef    BOOST_OCTONION_CONSTRUCTOR_GENERATOR
1437 
1438 #undef    BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR
1439 
1440 #undef    BOOST_OCTONION_MEMBER_ADD_GENERATOR
1441 #undef    BOOST_OCTONION_MEMBER_SUB_GENERATOR
1442 #undef    BOOST_OCTONION_MEMBER_MUL_GENERATOR
1443 #undef    BOOST_OCTONION_MEMBER_DIV_GENERATOR
1444 
1445 #undef    BOOST_OCTONION_MEMBER_ADD_GENERATOR_1
1446 #undef    BOOST_OCTONION_MEMBER_ADD_GENERATOR_2
1447 #undef    BOOST_OCTONION_MEMBER_ADD_GENERATOR_3
1448 #undef    BOOST_OCTONION_MEMBER_ADD_GENERATOR_4
1449 #undef    BOOST_OCTONION_MEMBER_SUB_GENERATOR_1
1450 #undef    BOOST_OCTONION_MEMBER_SUB_GENERATOR_2
1451 #undef    BOOST_OCTONION_MEMBER_SUB_GENERATOR_3
1452 #undef    BOOST_OCTONION_MEMBER_SUB_GENERATOR_4
1453 #undef    BOOST_OCTONION_MEMBER_MUL_GENERATOR_1
1454 #undef    BOOST_OCTONION_MEMBER_MUL_GENERATOR_2
1455 #undef    BOOST_OCTONION_MEMBER_MUL_GENERATOR_3
1456 #undef    BOOST_OCTONION_MEMBER_MUL_GENERATOR_4
1457 #undef    BOOST_OCTONION_MEMBER_DIV_GENERATOR_1
1458 #undef    BOOST_OCTONION_MEMBER_DIV_GENERATOR_2
1459 #undef    BOOST_OCTONION_MEMBER_DIV_GENERATOR_3
1460 #undef    BOOST_OCTONION_MEMBER_DIV_GENERATOR_4
1461 
1462 
1463 #undef    BOOST_OCTONION_MEMBER_DATA_GENERATOR
1464 
1465 #undef    BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR
1466 
1467 #undef    BOOST_OCTONION_ACCESSOR_GENERATOR
1468 
1469 
1470         // operators
1471 
1472 #define    BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) \
1473         {                                             \
1474             octonion<T>    res(lhs);                  \
1475             res op##= rhs;                            \
1476             return(res);                              \
1477         }
1478 
1479 #define    BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op)                                                                              \
1480         template<typename T>                                                                                                      \
1481         inline octonion<T>                        operator op (T const & lhs, octonion<T> const & rhs)                            \
1482         BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1483 
1484 #define    BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op)                                                                              \
1485         template<typename T>                                                                                                      \
1486         inline octonion<T>                        operator op (octonion<T> const & lhs, T const & rhs)                            \
1487         BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1488 
1489 #define    BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op)                                                                              \
1490         template<typename T>                                                                                                      \
1491         inline octonion<T>                        operator op (::std::complex<T> const & lhs, octonion<T> const & rhs)            \
1492         BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1493 
1494 #define    BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op)                                                                              \
1495         template<typename T>                                                                                                      \
1496         inline octonion<T>                        operator op (octonion<T> const & lhs, ::std::complex<T> const & rhs)            \
1497         BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1498 
1499 #define    BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op)                                                                              \
1500         template<typename T>                                                                                                      \
1501         inline octonion<T>                        operator op (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs) \
1502         BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1503 
1504 #define    BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op)                                                                              \
1505         template<typename T>                                                                                                      \
1506         inline octonion<T>                        operator op (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs) \
1507         BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1508 
1509 #define    BOOST_OCTONION_OPERATOR_GENERATOR_4(op)                                                                                \
1510         template<typename T>                                                                                                      \
1511         inline octonion<T>                        operator op (octonion<T> const & lhs, octonion<T> const & rhs)                  \
1512         BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)
1513 
1514 #define    BOOST_OCTONION_OPERATOR_GENERATOR(op)     \
1515         BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op)    \
1516         BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op)    \
1517         BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op)    \
1518         BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op)    \
1519         BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op)    \
1520         BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op)    \
1521         BOOST_OCTONION_OPERATOR_GENERATOR_4(op)
1522 
1523 
1524         BOOST_OCTONION_OPERATOR_GENERATOR(+)
1525         BOOST_OCTONION_OPERATOR_GENERATOR(-)
1526         BOOST_OCTONION_OPERATOR_GENERATOR(*)
1527         BOOST_OCTONION_OPERATOR_GENERATOR(/)
1528 
1529 
1530 #undef    BOOST_OCTONION_OPERATOR_GENERATOR
1531 
1532 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_1_L
1533 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_1_R
1534 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_2_L
1535 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_2_R
1536 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_3_L
1537 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_3_R
1538 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_4
1539 
1540 #undef    BOOST_OCTONION_OPERATOR_GENERATOR_BODY
1541 
1542 
1543         template<typename T>
1544         inline octonion<T>                        operator + (octonion<T> const & o)
1545         {
1546             return(o);
1547         }
1548 
1549 
1550         template<typename T>
1551         inline octonion<T>                        operator - (octonion<T> const & o)
1552         {
1553             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()));
1554         }
1555 
1556 
1557         template<typename T>
1558         inline bool                                operator == (T const & lhs, octonion<T> const & rhs)
1559         {
1560             return(
1561                         (rhs.R_component_1() == lhs)&&
1562                         (rhs.R_component_2() == static_cast<T>(0))&&
1563                         (rhs.R_component_3() == static_cast<T>(0))&&
1564                         (rhs.R_component_4() == static_cast<T>(0))&&
1565                         (rhs.R_component_5() == static_cast<T>(0))&&
1566                         (rhs.R_component_6() == static_cast<T>(0))&&
1567                         (rhs.R_component_7() == static_cast<T>(0))&&
1568                         (rhs.R_component_8() == static_cast<T>(0))
1569                     );
1570         }
1571 
1572 
1573         template<typename T>
1574         inline bool                                operator == (octonion<T> const & lhs, T const & rhs)
1575         {
1576             return(
1577                         (lhs.R_component_1() == rhs)&&
1578                         (lhs.R_component_2() == static_cast<T>(0))&&
1579                         (lhs.R_component_3() == static_cast<T>(0))&&
1580                         (lhs.R_component_4() == static_cast<T>(0))&&
1581                         (lhs.R_component_5() == static_cast<T>(0))&&
1582                         (lhs.R_component_6() == static_cast<T>(0))&&
1583                         (lhs.R_component_7() == static_cast<T>(0))&&
1584                         (lhs.R_component_8() == static_cast<T>(0))
1585                     );
1586         }
1587 
1588 
1589         template<typename T>
1590         inline bool                                operator == (::std::complex<T> const & lhs, octonion<T> const & rhs)
1591         {
1592             return(
1593                         (rhs.R_component_1() == lhs.real())&&
1594                         (rhs.R_component_2() == lhs.imag())&&
1595                         (rhs.R_component_3() == static_cast<T>(0))&&
1596                         (rhs.R_component_4() == static_cast<T>(0))&&
1597                         (rhs.R_component_5() == static_cast<T>(0))&&
1598                         (rhs.R_component_6() == static_cast<T>(0))&&
1599                         (rhs.R_component_7() == static_cast<T>(0))&&
1600                         (rhs.R_component_8() == static_cast<T>(0))
1601                     );
1602         }
1603 
1604 
1605         template<typename T>
1606         inline bool                                operator == (octonion<T> const & lhs, ::std::complex<T> const & rhs)
1607         {
1608             return(
1609                         (lhs.R_component_1() == rhs.real())&&
1610                         (lhs.R_component_2() == rhs.imag())&&
1611                         (lhs.R_component_3() == static_cast<T>(0))&&
1612                         (lhs.R_component_4() == static_cast<T>(0))&&
1613                         (lhs.R_component_5() == static_cast<T>(0))&&
1614                         (lhs.R_component_6() == static_cast<T>(0))&&
1615                         (lhs.R_component_7() == static_cast<T>(0))&&
1616                         (lhs.R_component_8() == static_cast<T>(0))
1617                     );
1618         }
1619 
1620 
1621         template<typename T>
1622         inline bool                                operator == (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)
1623         {
1624             return(
1625                         (rhs.R_component_1() == lhs.R_component_1())&&
1626                         (rhs.R_component_2() == lhs.R_component_2())&&
1627                         (rhs.R_component_3() == lhs.R_component_3())&&
1628                         (rhs.R_component_4() == lhs.R_component_4())&&
1629                         (rhs.R_component_5() == static_cast<T>(0))&&
1630                         (rhs.R_component_6() == static_cast<T>(0))&&
1631                         (rhs.R_component_7() == static_cast<T>(0))&&
1632                         (rhs.R_component_8() == static_cast<T>(0))
1633                     );
1634         }
1635 
1636 
1637         template<typename T>
1638         inline bool                                operator == (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)
1639         {
1640             return(
1641                         (lhs.R_component_1() == rhs.R_component_1())&&
1642                         (lhs.R_component_2() == rhs.R_component_2())&&
1643                         (lhs.R_component_3() == rhs.R_component_3())&&
1644                         (lhs.R_component_4() == rhs.R_component_4())&&
1645                         (lhs.R_component_5() == static_cast<T>(0))&&
1646                         (lhs.R_component_6() == static_cast<T>(0))&&
1647                         (lhs.R_component_7() == static_cast<T>(0))&&
1648                         (lhs.R_component_8() == static_cast<T>(0))
1649                     );
1650         }
1651 
1652 
1653         template<typename T>
1654         inline bool                                operator == (octonion<T> const & lhs, octonion<T> const & rhs)
1655         {
1656             return(
1657                         (rhs.R_component_1() == lhs.R_component_1())&&
1658                         (rhs.R_component_2() == lhs.R_component_2())&&
1659                         (rhs.R_component_3() == lhs.R_component_3())&&
1660                         (rhs.R_component_4() == lhs.R_component_4())&&
1661                         (rhs.R_component_5() == lhs.R_component_5())&&
1662                         (rhs.R_component_6() == lhs.R_component_6())&&
1663                         (rhs.R_component_7() == lhs.R_component_7())&&
1664                         (rhs.R_component_8() == lhs.R_component_8())
1665                     );
1666         }
1667 
1668 
1669 #define    BOOST_OCTONION_NOT_EQUAL_GENERATOR \
1670         {                                     \
1671             return(!(lhs == rhs));            \
1672         }
1673 
1674         template<typename T>
1675         inline bool                                operator != (T const & lhs, octonion<T> const & rhs)
1676         BOOST_OCTONION_NOT_EQUAL_GENERATOR
1677 
1678         template<typename T>
1679         inline bool                                operator != (octonion<T> const & lhs, T const & rhs)
1680         BOOST_OCTONION_NOT_EQUAL_GENERATOR
1681 
1682         template<typename T>
1683         inline bool                                operator != (::std::complex<T> const & lhs, octonion<T> const & rhs)
1684         BOOST_OCTONION_NOT_EQUAL_GENERATOR
1685 
1686         template<typename T>
1687         inline bool                                operator != (octonion<T> const & lhs, ::std::complex<T> const & rhs)
1688         BOOST_OCTONION_NOT_EQUAL_GENERATOR
1689 
1690         template<typename T>
1691         inline bool                                operator != (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)
1692         BOOST_OCTONION_NOT_EQUAL_GENERATOR
1693 
1694         template<typename T>
1695         inline bool                                operator != (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)
1696         BOOST_OCTONION_NOT_EQUAL_GENERATOR
1697 
1698         template<typename T>
1699         inline bool                                operator != (octonion<T> const & lhs, octonion<T> const & rhs)
1700         BOOST_OCTONION_NOT_EQUAL_GENERATOR
1701 
1702     #undef    BOOST_OCTONION_NOT_EQUAL_GENERATOR
1703 
1704         // LCOV_EXCL_START
1705         // Something like 2,100 lines of input-streaming up to line 3,800 and beyond.
1706 
1707         // Note:    the default values in the constructors of the complex and quaternions make for
1708         //            a very complex and ambiguous situation; we have made choices to disambiguate.
1709         template<typename T, typename charT, class traits>
1710         ::std::basic_istream<charT,traits> &    operator >> (    ::std::basic_istream<charT,traits> & is,
1711                                                                 octonion<T> & o)
1712         {
1713 #ifdef     BOOST_NO_STD_LOCALE
1714 #else
1715             const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
1716 #endif /* BOOST_NO_STD_LOCALE */
1717 
1718             T    a = T();
1719             T    b = T();
1720             T    c = T();
1721             T    d = T();
1722             T    e = T();
1723             T    f = T();
1724             T    g = T();
1725             T    h = T();
1726 
1727             ::std::complex<T>    u = ::std::complex<T>();
1728             ::std::complex<T>    v = ::std::complex<T>();
1729             ::std::complex<T>    x = ::std::complex<T>();
1730             ::std::complex<T>    y = ::std::complex<T>();
1731 
1732             ::boost::math::quaternion<T>    p = ::boost::math::quaternion<T>();
1733             ::boost::math::quaternion<T>    q = ::boost::math::quaternion<T>();
1734 
1735             charT    ch = charT();
1736             char    cc;
1737 
1738             is >> ch;                                        // get the first lexeme
1739 
1740             if    (!is.good())    goto finish;
1741 
1742 #ifdef    BOOST_NO_STD_LOCALE
1743             cc = ch;
1744 #else
1745             cc = ct.narrow(ch, char());
1746 #endif /* BOOST_NO_STD_LOCALE */
1747 
1748             if    (cc == '(')                            // read "("
1749             {
1750                 is >> ch;                                    // get the second lexeme
1751 
1752                 if    (!is.good())    goto finish;
1753 
1754 #ifdef    BOOST_NO_STD_LOCALE
1755                 cc = ch;
1756 #else
1757                 cc = ct.narrow(ch, char());
1758 #endif /* BOOST_NO_STD_LOCALE */
1759 
1760                 if    (cc == '(')                                // read "(("
1761                 {
1762                     is >> ch;                                    // get the third lexeme
1763 
1764                     if    (!is.good())    goto finish;
1765 
1766 #ifdef    BOOST_NO_STD_LOCALE
1767                     cc = ch;
1768 #else
1769                     cc = ct.narrow(ch, char());
1770 #endif /* BOOST_NO_STD_LOCALE */
1771 
1772                     if    (cc == '(')                                // read "((("
1773                     {
1774                         is.putback(ch);
1775 
1776                         is >> u;                                // read "((u"
1777 
1778                         if    (!is.good())    goto finish;
1779 
1780                         is >> ch;                                // get the next lexeme
1781 
1782                         if    (!is.good())    goto finish;
1783 
1784 #ifdef    BOOST_NO_STD_LOCALE
1785                         cc = ch;
1786 #else
1787                         cc = ct.narrow(ch, char());
1788 #endif /* BOOST_NO_STD_LOCALE */
1789 
1790                         if        (cc == ')')                        // read "((u)"
1791                         {
1792                             is >> ch;                                // get the next lexeme
1793 
1794                             if    (!is.good())    goto finish;
1795 
1796 #ifdef    BOOST_NO_STD_LOCALE
1797                             cc = ch;
1798 #else
1799                             cc = ct.narrow(ch, char());
1800 #endif /* BOOST_NO_STD_LOCALE */
1801 
1802                             if        (cc == ')')                        // format: (((a))), (((a,b)))
1803                             {
1804                                 o = octonion<T>(u);
1805                             }
1806                             else if    (cc == ',')                        // read "((u),"
1807                             {
1808                                 p = ::boost::math::quaternion<T>(u);
1809 
1810                                 is >> q;                                // read "((u),q"
1811 
1812                                 if    (!is.good())    goto finish;
1813 
1814                                 is >> ch;                                // get the next lexeme
1815 
1816                                 if    (!is.good())    goto finish;
1817 
1818 #ifdef    BOOST_NO_STD_LOCALE
1819                                 cc = ch;
1820 #else
1821                                 cc = ct.narrow(ch, char());
1822 #endif /* BOOST_NO_STD_LOCALE */
1823 
1824                                 if        (cc == ')')                        // format: (((a)),q), (((a,b)),q)
1825                                 {
1826                                     o = octonion<T>(p,q);
1827                                 }
1828                                 else                                    // error
1829                                 {
1830                                     is.setstate(::std::ios_base::failbit);
1831                                 }
1832                             }
1833                             else                                    // error
1834                             {
1835                                 is.setstate(::std::ios_base::failbit);
1836                             }
1837                         }
1838                         else if    (cc ==',')                        // read "((u,"
1839                         {
1840                             is >> v;                                // read "((u,v"
1841 
1842                             if    (!is.good())    goto finish;
1843 
1844                             is >> ch;                                // get the next lexeme
1845 
1846                             if    (!is.good())    goto finish;
1847 
1848 #ifdef    BOOST_NO_STD_LOCALE
1849                             cc = ch;
1850 #else
1851                             cc = ct.narrow(ch, char());
1852 #endif /* BOOST_NO_STD_LOCALE */
1853 
1854                             if        (cc == ')')                        // read "((u,v)"
1855                             {
1856                                 p = ::boost::math::quaternion<T>(u,v);
1857 
1858                                 is >> ch;                                // get the next lexeme
1859 
1860                                 if    (!is.good())    goto finish;
1861 
1862 #ifdef    BOOST_NO_STD_LOCALE
1863                                 cc = ch;
1864 #else
1865                                 cc = ct.narrow(ch, char());
1866 #endif /* BOOST_NO_STD_LOCALE */
1867 
1868                                 if        (cc == ')')                        // format: (((a),v)), (((a,b),v))
1869                                 {
1870                                     o = octonion<T>(p);
1871                                 }
1872                                 else if    (cc == ',')                        // read "((u,v),"
1873                                 {
1874                                     is >> q;                                // read "(p,q"
1875 
1876                                     if    (!is.good())    goto finish;
1877 
1878                                     is >> ch;                                // get the next lexeme
1879 
1880                                     if    (!is.good())    goto finish;
1881 
1882 #ifdef    BOOST_NO_STD_LOCALE
1883                                     cc = ch;
1884 #else
1885                                     cc = ct.narrow(ch, char());
1886 #endif /* BOOST_NO_STD_LOCALE */
1887 
1888                                     if        (cc == ')')                        // format: (((a),v),q), (((a,b),v),q)
1889                                     {
1890                                         o = octonion<T>(p,q);
1891                                     }
1892                                     else                                    // error
1893                                     {
1894                                         is.setstate(::std::ios_base::failbit);
1895                                     }
1896                                 }
1897                                 else                                    // error
1898                                 {
1899                                     is.setstate(::std::ios_base::failbit);
1900                                 }
1901                             }
1902                             else                                    // error
1903                             {
1904                                 is.setstate(::std::ios_base::failbit);
1905                             }
1906                         }
1907                         else                                    // error
1908                         {
1909                             is.setstate(::std::ios_base::failbit);
1910                         }
1911                     }
1912                     else                                        // read "((a"
1913                     {
1914                         is.putback(ch);
1915 
1916                         is >> a;                                    // we extract the first component
1917 
1918                         if    (!is.good())    goto finish;
1919 
1920                         is >> ch;                                    // get the next lexeme
1921 
1922                         if    (!is.good())    goto finish;
1923 
1924 #ifdef    BOOST_NO_STD_LOCALE
1925                         cc = ch;
1926 #else
1927                         cc = ct.narrow(ch, char());
1928 #endif /* BOOST_NO_STD_LOCALE */
1929 
1930                         if        (cc == ')')                            // read "((a)"
1931                         {
1932                             is >> ch;                                    // get the next lexeme
1933 
1934                             if    (!is.good())    goto finish;
1935 
1936 #ifdef    BOOST_NO_STD_LOCALE
1937                             cc = ch;
1938 #else
1939                             cc = ct.narrow(ch, char());
1940 #endif /* BOOST_NO_STD_LOCALE */
1941 
1942                             if        (cc == ')')                            // read "((a))"
1943                             {
1944                                 o = octonion<T>(a);
1945                             }
1946                             else if    (cc == ',')                            // read "((a),"
1947                             {
1948                                 is >> ch;                                    // get the next lexeme
1949 
1950                                 if    (!is.good())    goto finish;
1951 
1952 #ifdef    BOOST_NO_STD_LOCALE
1953                                 cc = ch;
1954 #else
1955                                 cc = ct.narrow(ch, char());
1956 #endif /* BOOST_NO_STD_LOCALE */
1957 
1958                                 if        (cc == '(')                            // read "((a),("
1959                                 {
1960                                     is >> ch;                                    // get the next lexeme
1961 
1962                                     if    (!is.good())    goto finish;
1963 
1964 #ifdef    BOOST_NO_STD_LOCALE
1965                                     cc = ch;
1966 #else
1967                                     cc = ct.narrow(ch, char());
1968 #endif /* BOOST_NO_STD_LOCALE */
1969 
1970                                     if        (cc == '(')                            // read "((a),(("
1971                                     {
1972                                         is.putback(ch);
1973 
1974                                         is.putback(ch);                                // we backtrack twice, with the same value!
1975 
1976                                         is >> q;                                    // read "((a),q"
1977 
1978                                         if    (!is.good())    goto finish;
1979 
1980                                         is >> ch;                                    // get the next lexeme
1981 
1982                                         if    (!is.good())    goto finish;
1983 
1984 #ifdef    BOOST_NO_STD_LOCALE
1985                                         cc = ch;
1986 #else
1987                                         cc = ct.narrow(ch, char());
1988 #endif /* BOOST_NO_STD_LOCALE */
1989 
1990                                         if        (cc == ')')                            // read "((a),q)"
1991                                         {
1992                                             p = ::boost::math::quaternion<T>(a);
1993 
1994                                             o = octonion<T>(p,q);
1995                                         }
1996                                         else                                        // error
1997                                         {
1998                                             is.setstate(::std::ios_base::failbit);
1999                                         }
2000                                     }
2001                                     else                                        // read "((a),(c" or "((a),(e"
2002                                     {
2003                                         is.putback(ch);
2004 
2005                                         is >> c;
2006 
2007                                         if    (!is.good())    goto finish;
2008 
2009                                         is >> ch;                                    // get the next lexeme
2010 
2011                                         if    (!is.good())    goto finish;
2012 
2013 #ifdef    BOOST_NO_STD_LOCALE
2014                                         cc = ch;
2015 #else
2016                                         cc = ct.narrow(ch, char());
2017 #endif /* BOOST_NO_STD_LOCALE */
2018 
2019                                         if        (cc == ')')                            // read "((a),(c)" (ambiguity resolution)
2020                                         {
2021                                             is >> ch;                                    // get the next lexeme
2022 
2023                                             if    (!is.good())    goto finish;
2024 
2025 #ifdef    BOOST_NO_STD_LOCALE
2026                                             cc = ch;
2027 #else
2028                                             cc = ct.narrow(ch, char());
2029 #endif /* BOOST_NO_STD_LOCALE */
2030 
2031                                             if        (cc == ')')                        // read "((a),(c))"
2032                                             {
2033                                                 o = octonion<T>(a,b,c);
2034                                             }
2035                                             else if    (cc == ',')                        // read "((a),(c),"
2036                                             {
2037                                                 u = ::std::complex<T>(a);
2038 
2039                                                 v = ::std::complex<T>(c);
2040 
2041                                                 is >> x;                            // read "((a),(c),x"
2042 
2043                                                 if    (!is.good())    goto finish;
2044 
2045                                                 is >> ch;                                // get the next lexeme
2046 
2047                                                 if    (!is.good())    goto finish;
2048 
2049 #ifdef    BOOST_NO_STD_LOCALE
2050                                                 cc = ch;
2051 #else
2052                                                 cc = ct.narrow(ch, char());
2053 #endif /* BOOST_NO_STD_LOCALE */
2054 
2055                                                 if        (cc == ')')                        // read "((a),(c),x)"
2056                                                 {
2057                                                     o = octonion<T>(u,v,x);
2058                                                 }
2059                                                 else if    (cc == ',')                        // read "((a),(c),x,"
2060                                                 {
2061                                                     is >> y;                                // read "((a),(c),x,y"
2062 
2063                                                     if    (!is.good())    goto finish;
2064 
2065                                                     is >> ch;                                // get the next lexeme
2066 
2067                                                     if    (!is.good())    goto finish;
2068 
2069 #ifdef    BOOST_NO_STD_LOCALE
2070                                                     cc = ch;
2071 #else
2072                                                     cc = ct.narrow(ch, char());
2073 #endif /* BOOST_NO_STD_LOCALE */
2074 
2075                                                     if        (cc == ')')                        // read "((a),(c),x,y)"
2076                                                     {
2077                                                         o = octonion<T>(u,v,x,y);
2078                                                     }
2079                                                     else                                    // error
2080                                                     {
2081                                                         is.setstate(::std::ios_base::failbit);
2082                                                     }
2083                                                 }
2084                                                 else                                    // error
2085                                                 {
2086                                                     is.setstate(::std::ios_base::failbit);
2087                                                 }
2088                                             }
2089                                             else                                    // error
2090                                             {
2091                                                 is.setstate(::std::ios_base::failbit);
2092                                             }
2093                                         }
2094                                         else if    (cc == ',')                            // read "((a),(c," or "((a),(e,"
2095                                         {
2096                                             is >> ch;                                // get the next lexeme
2097 
2098                                             if    (!is.good())    goto finish;
2099 
2100 #ifdef    BOOST_NO_STD_LOCALE
2101                                             cc = ch;
2102 #else
2103                                             cc = ct.narrow(ch, char());
2104 #endif /* BOOST_NO_STD_LOCALE */
2105 
2106                                             if        (cc == '(')                        // read "((a),(e,(" (ambiguity resolution)
2107                                             {
2108                                                 p = ::boost::math::quaternion<T>(a);
2109 
2110                                                 x = ::std::complex<T>(c);                // "c" was actually "e"
2111 
2112                                                 is.putback(ch);                            // we can only backtrace once
2113 
2114                                                 is >> y;                                // read "((a),(e,y"
2115 
2116                                                 if    (!is.good())    goto finish;
2117 
2118                                                 is >> ch;                                // get the next lexeme
2119 
2120 #ifdef    BOOST_NO_STD_LOCALE
2121                                                 cc = ch;
2122 #else
2123                                                 cc = ct.narrow(ch, char());
2124 #endif /* BOOST_NO_STD_LOCALE */
2125 
2126                                                 if        (cc == ')')                        // read "((a),(e,y)"
2127                                                 {
2128                                                     q = ::boost::math::quaternion<T>(x,y);
2129 
2130                                                     is >> ch;                                // get the next lexeme
2131 
2132 #ifdef    BOOST_NO_STD_LOCALE
2133                                                     cc = ch;
2134 #else
2135                                                     cc = ct.narrow(ch, char());
2136 #endif /* BOOST_NO_STD_LOCALE */
2137 
2138                                                     if        (cc == ')')                        // read "((a),(e,y))"
2139                                                     {
2140                                                         o = octonion<T>(p,q);
2141                                                     }
2142                                                     else                                    // error
2143                                                     {
2144                                                         is.setstate(::std::ios_base::failbit);
2145                                                     }
2146                                                 }
2147                                                 else                                    // error
2148                                                 {
2149                                                     is.setstate(::std::ios_base::failbit);
2150                                                 }
2151                                             }
2152                                             else                                    // read "((a),(c,d" or "((a),(e,f"
2153                                             {
2154                                                 is.putback(ch);
2155 
2156                                                 is >> d;
2157 
2158                                                 if    (!is.good())    goto finish;
2159 
2160                                                 is >> ch;                                // get the next lexeme
2161 
2162                                                 if    (!is.good())    goto finish;
2163 
2164 #ifdef    BOOST_NO_STD_LOCALE
2165                                                 cc = ch;
2166 #else
2167                                                 cc = ct.narrow(ch, char());
2168 #endif /* BOOST_NO_STD_LOCALE */
2169 
2170                                                 if        (cc == ')')                        // read "((a),(c,d)" (ambiguity resolution)
2171                                                 {
2172                                                     is >> ch;                                // get the next lexeme
2173 
2174                                                     if    (!is.good())    goto finish;
2175 
2176 #ifdef    BOOST_NO_STD_LOCALE
2177                                                     cc = ch;
2178 #else
2179                                                     cc = ct.narrow(ch, char());
2180 #endif /* BOOST_NO_STD_LOCALE */
2181 
2182                                                     if        (cc == ')')                        // read "((a),(c,d))"
2183                                                     {
2184                                                         o = octonion<T>(a,b,c,d);
2185                                                     }
2186                                                     else if    (cc == ',')                        // read "((a),(c,d),"
2187                                                     {
2188                                                         u = ::std::complex<T>(a);
2189 
2190                                                         v = ::std::complex<T>(c,d);
2191 
2192                                                         is >> x;                                // read "((a),(c,d),x"
2193 
2194                                                         if    (!is.good())    goto finish;
2195 
2196                                                         is >> ch;                                // get the next lexeme
2197 
2198                                                         if    (!is.good())    goto finish;
2199 
2200 #ifdef    BOOST_NO_STD_LOCALE
2201                                                         cc = ch;
2202 #else
2203                                                         cc = ct.narrow(ch, char());
2204 #endif /* BOOST_NO_STD_LOCALE */
2205 
2206                                                         if        (cc == ')')                        // read "((a),(c,d),x)"
2207                                                         {
2208                                                             o = octonion<T>(u,v,x);
2209                                                         }
2210                                                         else if    (cc == ',')                        // read "((a),(c,d),x,"
2211                                                         {
2212                                                             is >> y;                                // read "((a),(c,d),x,y"
2213 
2214                                                             if    (!is.good())    goto finish;
2215 
2216                                                             is >> ch;                                // get the next lexeme
2217 
2218                                                             if    (!is.good())    goto finish;
2219 
2220 #ifdef    BOOST_NO_STD_LOCALE
2221                                                             cc = ch;
2222 #else
2223                                                             cc = ct.narrow(ch, char());
2224 #endif /* BOOST_NO_STD_LOCALE */
2225 
2226                                                             if        (cc == ')')                        // read "((a),(c,d),x,y)"
2227                                                             {
2228                                                                 o = octonion<T>(u,v,x,y);
2229                                                             }
2230                                                             else                                    // error
2231                                                             {
2232                                                                 is.setstate(::std::ios_base::failbit);
2233                                                             }
2234                                                         }
2235                                                         else                                    // error
2236                                                         {
2237                                                             is.setstate(::std::ios_base::failbit);
2238                                                         }
2239                                                     }
2240                                                     else                                    // error
2241                                                     {
2242                                                         is.setstate(::std::ios_base::failbit);
2243                                                     }
2244                                                 }
2245                                                 else if    (cc == ',')                        // read "((a),(e,f," (ambiguity resolution)
2246                                                 {
2247                                                     p = ::boost::math::quaternion<T>(a);
2248 
2249                                                     is >> g;                                // read "((a),(e,f,g" (too late to backtrack)
2250 
2251                                                     if    (!is.good())    goto finish;
2252 
2253                                                     is >> ch;                                // get the next lexeme
2254 
2255                                                     if    (!is.good())    goto finish;
2256 
2257 #ifdef    BOOST_NO_STD_LOCALE
2258                                                     cc = ch;
2259 #else
2260                                                     cc = ct.narrow(ch, char());
2261 #endif /* BOOST_NO_STD_LOCALE */
2262 
2263                                                     if        (cc == ')')                        // read "((a),(e,f,g)"
2264                                                     {
2265                                                         q = ::boost::math::quaternion<T>(c,d,g);        // "c" was actually "e", and "d" was actually "f"
2266 
2267                                                         is >> ch;                                // get the next lexeme
2268 
2269                                                         if    (!is.good())    goto finish;
2270 
2271 #ifdef    BOOST_NO_STD_LOCALE
2272                                                         cc = ch;
2273 #else
2274                                                         cc = ct.narrow(ch, char());
2275 #endif /* BOOST_NO_STD_LOCALE */
2276 
2277                                                         if        (cc == ')')                        // read "((a),(e,f,g))"
2278                                                         {
2279                                                             o = octonion<T>(p,q);
2280                                                         }
2281                                                         else                                    // error
2282                                                         {
2283                                                             is.setstate(::std::ios_base::failbit);
2284                                                         }
2285                                                     }
2286                                                     else if    (cc == ',')                        // read "((a),(e,f,g,"
2287                                                     {
2288                                                         is >> h;                                // read "((a),(e,f,g,h"
2289 
2290                                                         if    (!is.good())    goto finish;
2291 
2292                                                         is >> ch;                                // get the next lexeme
2293 
2294                                                         if    (!is.good())    goto finish;
2295 
2296 #ifdef    BOOST_NO_STD_LOCALE
2297                                                         cc = ch;
2298 #else
2299                                                         cc = ct.narrow(ch, char());
2300 #endif /* BOOST_NO_STD_LOCALE */
2301 
2302                                                         if        (cc == ')')                        // read "((a),(e,f,g,h)"
2303                                                         {
2304                                                             q = ::boost::math::quaternion<T>(c,d,g,h);    // "c" was actually "e", and "d" was actually "f"
2305 
2306                                                             is >> ch;                                // get the next lexeme
2307 
2308                                                             if    (!is.good())    goto finish;
2309 
2310 #ifdef    BOOST_NO_STD_LOCALE
2311                                                             cc = ch;
2312 #else
2313                                                             cc = ct.narrow(ch, char());
2314 #endif /* BOOST_NO_STD_LOCALE */
2315 
2316                                                             if        (cc == ')')                        // read "((a),(e,f,g,h))"
2317                                                             {
2318                                                                 o = octonion<T>(p,q);
2319                                                             }
2320                                                             else                                    // error
2321                                                             {
2322                                                                 is.setstate(::std::ios_base::failbit);
2323                                                             }
2324                                                         }
2325                                                         else                                    // error
2326                                                         {
2327                                                             is.setstate(::std::ios_base::failbit);
2328                                                         }
2329                                                     }
2330                                                     else                                    // error
2331                                                     {
2332                                                         is.setstate(::std::ios_base::failbit);
2333                                                     }
2334                                                 }
2335                                                 else                                    // error
2336                                                 {
2337                                                     is.setstate(::std::ios_base::failbit);
2338                                                 }
2339                                             }
2340                                         }
2341                                         else                                        // error
2342                                         {
2343                                             is.setstate(::std::ios_base::failbit);
2344                                         }
2345                                     }
2346                                 }
2347                                 else                                        // read "((a),c" (ambiguity resolution)
2348                                 {
2349                                     is.putback(ch);
2350 
2351                                     is >> c;                                    // we extract the third component
2352 
2353                                     if    (!is.good())    goto finish;
2354 
2355                                     is >> ch;                                    // get the next lexeme
2356 
2357                                     if    (!is.good())    goto finish;
2358 
2359 #ifdef    BOOST_NO_STD_LOCALE
2360                                     cc = ch;
2361 #else
2362                                     cc = ct.narrow(ch, char());
2363 #endif /* BOOST_NO_STD_LOCALE */
2364 
2365                                     if        (cc == ')')                            // read "((a),c)"
2366                                     {
2367                                         o = octonion<T>(a,b,c);
2368                                     }
2369                                     else if    (cc == ',')                            // read "((a),c,"
2370                                     {
2371                                         is >> x;                                    // read "((a),c,x"
2372 
2373                                         if    (!is.good())    goto finish;
2374 
2375                                         is >> ch;                                    // get the next lexeme
2376 
2377                                         if    (!is.good())    goto finish;
2378 
2379 #ifdef    BOOST_NO_STD_LOCALE
2380                                         cc = ch;
2381 #else
2382                                         cc = ct.narrow(ch, char());
2383 #endif /* BOOST_NO_STD_LOCALE */
2384 
2385                                         if        (cc == ')')                            // read "((a),c,x)"
2386                                         {
2387                                             o = octonion<T>(a,b,c,d,x.real(),x.imag());
2388                                         }
2389                                         else if    (cc == ',')                            // read "((a),c,x,"
2390                                         {
2391                                             is >> y;if    (!is.good())    goto finish;        // read "((a),c,x,y"
2392 
2393                                             is >> ch;                                    // get the next lexeme
2394 
2395                                             if    (!is.good())    goto finish;
2396 
2397 #ifdef    BOOST_NO_STD_LOCALE
2398                                             cc = ch;
2399 #else
2400                                             cc = ct.narrow(ch, char());
2401 #endif /* BOOST_NO_STD_LOCALE */
2402 
2403                                             if        (cc == ')')                            // read "((a),c,x,y)"
2404                                             {
2405                                                 o = octonion<T>(a,b,c,d,x.real(),x.imag(),y.real(),y.imag());
2406                                             }
2407                                             else                                        // error
2408                                             {
2409                                                 is.setstate(::std::ios_base::failbit);
2410                                             }
2411                                         }
2412                                         else                                        // error
2413                                         {
2414                                             is.setstate(::std::ios_base::failbit);
2415                                         }
2416                                     }
2417                                     else                                        // error
2418                                     {
2419                                         is.setstate(::std::ios_base::failbit);
2420                                     }
2421                                 }
2422                             }
2423                             else                                        // error
2424                             {
2425                                 is.setstate(::std::ios_base::failbit);
2426                             }
2427                         }
2428                         else if    (cc ==',')                            // read "((a,"
2429                         {
2430                             is >> ch;                                    // get the next lexeme
2431 
2432                             if    (!is.good())    goto finish;
2433 
2434 #ifdef    BOOST_NO_STD_LOCALE
2435                             cc = ch;
2436 #else
2437                             cc = ct.narrow(ch, char());
2438 #endif /* BOOST_NO_STD_LOCALE */
2439 
2440                             if        (cc == '(')                            // read "((a,("
2441                             {
2442                                 u = ::std::complex<T>(a);
2443 
2444                                 is.putback(ch);                                // can only backtrack so much
2445 
2446                                 is >> v;                                    // read "((a,v"
2447 
2448                                 if    (!is.good())    goto finish;
2449 
2450                                 is >> ch;                                    // get the next lexeme
2451 
2452                                 if    (!is.good())    goto finish;
2453 
2454 #ifdef    BOOST_NO_STD_LOCALE
2455                                 cc = ch;
2456 #else
2457                                 cc = ct.narrow(ch, char());
2458 #endif /* BOOST_NO_STD_LOCALE */
2459 
2460                                 if        (cc == ')')                            // read "((a,v)"
2461                                 {
2462                                     is >> ch;                                    // get the next lexeme
2463 
2464                                     if    (!is.good())    goto finish;
2465 
2466 #ifdef    BOOST_NO_STD_LOCALE
2467                                     cc = ch;
2468 #else
2469                                     cc = ct.narrow(ch, char());
2470 #endif /* BOOST_NO_STD_LOCALE */
2471 
2472                                     if        (cc == ')')                            // read "((a,v))"
2473                                     {
2474                                         o = octonion<T>(u,v);
2475                                     }
2476                                     else if    (cc == ',')                            // read "((a,v),"
2477                                     {
2478                                         p = ::boost::math::quaternion<T>(u,v);
2479 
2480                                         is >> q;                                    // read "((a,v),q"
2481 
2482                                         if    (!is.good())    goto finish;
2483 
2484                                         is >> ch;                                    // get the next lexeme
2485 
2486                                         if    (!is.good())    goto finish;
2487 
2488 #ifdef    BOOST_NO_STD_LOCALE
2489                                         cc = ch;
2490 #else
2491                                         cc = ct.narrow(ch, char());
2492 #endif /* BOOST_NO_STD_LOCALE */
2493 
2494                                         if        (cc == ')')                            // read "((a,v),q)"
2495                                         {
2496                                             o = octonion<T>(p,q);
2497                                         }
2498                                         else                                        // error
2499                                         {
2500                                             is.setstate(::std::ios_base::failbit);
2501                                         }
2502                                     }
2503                                     else                                        // error
2504                                     {
2505                                         is.setstate(::std::ios_base::failbit);
2506                                     }
2507                                 }
2508                                 else                                        // error
2509                                 {
2510                                     is.setstate(::std::ios_base::failbit);
2511                                 }
2512                             }
2513                             else
2514                             {
2515                                 is.putback(ch);
2516 
2517                                 is >> b;                                    // read "((a,b"
2518 
2519                                 if    (!is.good())    goto finish;
2520 
2521                                 is >> ch;                                    // get the next lexeme
2522 
2523                                 if    (!is.good())    goto finish;
2524 
2525 #ifdef    BOOST_NO_STD_LOCALE
2526                                 cc = ch;
2527 #else
2528                                 cc = ct.narrow(ch, char());
2529 #endif /* BOOST_NO_STD_LOCALE */
2530 
2531                                 if        (cc == ')')                            // read "((a,b)"
2532                                 {
2533                                     is >> ch;                                    // get the next lexeme
2534 
2535                                     if    (!is.good())    goto finish;
2536 
2537 #ifdef    BOOST_NO_STD_LOCALE
2538                                     cc = ch;
2539 #else
2540                                     cc = ct.narrow(ch, char());
2541 #endif /* BOOST_NO_STD_LOCALE */
2542 
2543                                     if        (cc == ')')                            // read "((a,b))"
2544                                     {
2545                                         o = octonion<T>(a,b);
2546                                     }
2547                                     else if    (cc == ',')                            // read "((a,b),"
2548                                     {
2549                                         is >> ch;                                    // get the next lexeme
2550 
2551                                         if    (!is.good())    goto finish;
2552 
2553 #ifdef    BOOST_NO_STD_LOCALE
2554                                         cc = ch;
2555 #else
2556                                         cc = ct.narrow(ch, char());
2557 #endif /* BOOST_NO_STD_LOCALE */
2558 
2559                                         if        (cc == '(')                            // read "((a,b),("
2560                                         {
2561                                             is >> ch;                                    // get the next lexeme
2562 
2563                                             if    (!is.good())    goto finish;
2564 
2565 #ifdef    BOOST_NO_STD_LOCALE
2566                                             cc = ch;
2567 #else
2568                                             cc = ct.narrow(ch, char());
2569 #endif /* BOOST_NO_STD_LOCALE */
2570 
2571                                             if        (cc == '(')                            // read "((a,b),(("
2572                                             {
2573                                                 p = ::boost::math::quaternion<T>(a,b);
2574 
2575                                                 is.putback(ch);
2576 
2577                                                 is.putback(ch);                            // we backtrack twice, with the same value
2578 
2579                                                 is >> q;                                // read "((a,b),q"
2580 
2581                                                 if    (!is.good())    goto finish;
2582 
2583                                                 is >> ch;                                    // get the next lexeme
2584 
2585                                                 if    (!is.good())    goto finish;
2586 
2587 #ifdef    BOOST_NO_STD_LOCALE
2588                                                 cc = ch;
2589 #else
2590                                                 cc = ct.narrow(ch, char());
2591 #endif /* BOOST_NO_STD_LOCALE */
2592 
2593                                                 if        (cc == ')')                            // read "((a,b),q)"
2594                                                 {
2595                                                     o = octonion<T>(p,q);
2596                                                 }
2597                                                 else                                        // error
2598                                                 {
2599                                                     is.setstate(::std::ios_base::failbit);
2600                                                 }
2601                                             }
2602                                             else                                        // read "((a,b),(c" or "((a,b),(e"
2603                                             {
2604                                                 is.putback(ch);
2605 
2606                                                 is >> c;
2607 
2608                                                 if    (!is.good())    goto finish;
2609 
2610                                                 is >> ch;                                    // get the next lexeme
2611 
2612                                                 if    (!is.good())    goto finish;
2613 
2614 #ifdef    BOOST_NO_STD_LOCALE
2615                                                 cc = ch;
2616 #else
2617                                                 cc = ct.narrow(ch, char());
2618 #endif /* BOOST_NO_STD_LOCALE */
2619 
2620                                                 if        (cc == ')')                            // read "((a,b),(c)" (ambiguity resolution)
2621                                                 {
2622                                                     is >> ch;                                    // get the next lexeme
2623 
2624                                                     if    (!is.good())    goto finish;
2625 
2626 #ifdef    BOOST_NO_STD_LOCALE
2627                                                     cc = ch;
2628 #else
2629                                                     cc = ct.narrow(ch, char());
2630 #endif /* BOOST_NO_STD_LOCALE */
2631 
2632                                                     if        (cc == ')')                            // read "((a,b),(c))"
2633                                                     {
2634                                                         o = octonion<T>(a,b,c);
2635                                                     }
2636                                                     else if    (cc == ',')                            // read "((a,b),(c),"
2637                                                     {
2638                                                         u = ::std::complex<T>(a,b);
2639 
2640                                                         v = ::std::complex<T>(c);
2641 
2642                                                         is >> x;                                    // read "((a,b),(c),x"
2643 
2644                                                         if    (!is.good())    goto finish;
2645 
2646                                                         is >> ch;                                    // get the next lexeme
2647 
2648                                                         if    (!is.good())    goto finish;
2649 
2650 #ifdef    BOOST_NO_STD_LOCALE
2651                                                         cc = ch;
2652 #else
2653                                                         cc = ct.narrow(ch, char());
2654 #endif /* BOOST_NO_STD_LOCALE */
2655 
2656                                                         if        (cc == ')')                            // read "((a,b),(c),x)"
2657                                                         {
2658                                                             o = octonion<T>(u,v,x);
2659                                                         }
2660                                                         else if    (cc == ',')                            // read "((a,b),(c),x,"
2661                                                         {
2662                                                             is >> y;                                    // read "((a,b),(c),x,y"
2663 
2664                                                             if    (!is.good())    goto finish;
2665 
2666                                                             is >> ch;                                    // get the next lexeme
2667 
2668                                                             if    (!is.good())    goto finish;
2669 
2670 #ifdef    BOOST_NO_STD_LOCALE
2671                                                             cc = ch;
2672 #else
2673                                                             cc = ct.narrow(ch, char());
2674 #endif /* BOOST_NO_STD_LOCALE */
2675 
2676                                                             if        (cc == ')')                            // read "((a,b),(c),x,y)"
2677                                                             {
2678                                                                 o = octonion<T>(u,v,x,y);
2679                                                             }
2680                                                             else                                        // error
2681                                                             {
2682                                                                 is.setstate(::std::ios_base::failbit);
2683                                                             }
2684                                                         }
2685                                                         else                                        // error
2686                                                         {
2687                                                             is.setstate(::std::ios_base::failbit);
2688                                                         }
2689                                                     }
2690                                                     else                                        // error
2691                                                     {
2692                                                         is.setstate(::std::ios_base::failbit);
2693                                                     }
2694                                                 }
2695                                                 else if    (cc == ',')                            // read "((a,b),(c," or "((a,b),(e,"
2696                                                 {
2697                                                     is >> ch;                                    // get the next lexeme
2698 
2699                                                     if    (!is.good())    goto finish;
2700 
2701 #ifdef    BOOST_NO_STD_LOCALE
2702                                                     cc = ch;
2703 #else
2704                                                     cc = ct.narrow(ch, char());
2705 #endif /* BOOST_NO_STD_LOCALE */
2706 
2707                                                     if        (cc == '(')                            // read "((a,b),(e,(" (ambiguity resolution)
2708                                                     {
2709                                                         u = ::std::complex<T>(a,b);
2710 
2711                                                         x = ::std::complex<T>(c);                    // "c" is actually "e"
2712 
2713                                                         is.putback(ch);
2714 
2715                                                         is >> y;                                    // read "((a,b),(e,y"
2716 
2717                                                         if    (!is.good())    goto finish;
2718 
2719                                                         is >> ch;                                    // get the next lexeme
2720 
2721                                                         if    (!is.good())    goto finish;
2722 
2723 #ifdef    BOOST_NO_STD_LOCALE
2724                                                         cc = ch;
2725 #else
2726                                                         cc = ct.narrow(ch, char());
2727 #endif /* BOOST_NO_STD_LOCALE */
2728 
2729                                                         if        (cc == ')')                            // read "((a,b),(e,y)"
2730                                                         {
2731                                                             is >> ch;                                    // get the next lexeme
2732 
2733                                                             if    (!is.good())    goto finish;
2734 
2735 #ifdef    BOOST_NO_STD_LOCALE
2736                                                             cc = ch;
2737 #else
2738                                                             cc = ct.narrow(ch, char());
2739 #endif /* BOOST_NO_STD_LOCALE */
2740 
2741                                                             if        (cc == ')')                            // read "((a,b),(e,y))"
2742                                                             {
2743                                                                 o = octonion<T>(u,v,x,y);
2744                                                             }
2745                                                             else                                        // error
2746                                                             {
2747                                                                 is.setstate(::std::ios_base::failbit);
2748                                                             }
2749                                                         }
2750                                                         else                                        // error
2751                                                         {
2752                                                             is.setstate(::std::ios_base::failbit);
2753                                                         }
2754                                                     }
2755                                                     else                                        // read "((a,b),(c,d" or "((a,b),(e,f"
2756                                                     {
2757                                                         is.putback(ch);
2758 
2759                                                         is >> d;
2760 
2761                                                         if    (!is.good())    goto finish;
2762 
2763                                                         is >> ch;                                    // get the next lexeme
2764 
2765                                                         if    (!is.good())    goto finish;
2766 
2767 #ifdef    BOOST_NO_STD_LOCALE
2768                                                         cc = ch;
2769 #else
2770                                                         cc = ct.narrow(ch, char());
2771 #endif /* BOOST_NO_STD_LOCALE */
2772 
2773                                                         if        (cc == ')')                            // read "((a,b),(c,d)" (ambiguity resolution)
2774                                                         {
2775                                                             u = ::std::complex<T>(a,b);
2776 
2777                                                             v = ::std::complex<T>(c,d);
2778 
2779                                                             is >> ch;                                    // get the next lexeme
2780 
2781                                                             if    (!is.good())    goto finish;
2782 
2783 #ifdef    BOOST_NO_STD_LOCALE
2784                                                             cc = ch;
2785 #else
2786                                                             cc = ct.narrow(ch, char());
2787 #endif /* BOOST_NO_STD_LOCALE */
2788 
2789                                                             if        (cc == ')')                            // read "((a,b),(c,d))"
2790                                                             {
2791                                                                 o = octonion<T>(u,v);
2792                                                             }
2793                                                             else if    (cc == ',')                            // read "((a,b),(c,d),"
2794                                                             {
2795                                                                 is >> x;                                    // read "((a,b),(c,d),x
2796 
2797                                                                 if    (!is.good())    goto finish;
2798 
2799                                                                 is >> ch;                                    // get the next lexeme
2800 
2801                                                                 if    (!is.good())    goto finish;
2802 
2803 #ifdef    BOOST_NO_STD_LOCALE
2804                                                                 cc = ch;
2805 #else
2806                                                                 cc = ct.narrow(ch, char());
2807 #endif /* BOOST_NO_STD_LOCALE */
2808 
2809                                                                 if        (cc == ')')                            // read "((a,b),(c,d),x)"
2810                                                                 {
2811                                                                     o = octonion<T>(u,v,x);
2812                                                                 }
2813                                                                 else if    (cc == ',')                            // read "((a,b),(c,d),x,"
2814                                                                 {
2815                                                                     is >> y;                                    // read "((a,b),(c,d),x,y"
2816 
2817                                                                     if    (!is.good())    goto finish;
2818 
2819                                                                     is >> ch;                                    // get the next lexeme
2820 
2821                                                                     if    (!is.good())    goto finish;
2822 
2823 #ifdef    BOOST_NO_STD_LOCALE
2824                                                                     cc = ch;
2825 #else
2826                                                                     cc = ct.narrow(ch, char());
2827 #endif /* BOOST_NO_STD_LOCALE */
2828 
2829                                                                     if        (cc == ')')                            // read "((a,b),(c,d),x,y)"
2830                                                                     {
2831                                                                         o = octonion<T>(u,v,x,y);
2832                                                                     }
2833                                                                     else                                        // error
2834                                                                     {
2835                                                                         is.setstate(::std::ios_base::failbit);
2836                                                                     }
2837                                                                 }
2838                                                                 else                                        // error
2839                                                                 {
2840                                                                     is.setstate(::std::ios_base::failbit);
2841                                                                 }
2842                                                             }
2843                                                             else                                        // error
2844                                                             {
2845                                                                 is.setstate(::std::ios_base::failbit);
2846                                                             }
2847                                                         }
2848                                                         else if    (cc == ',')                            // read "((a,b),(e,f," (ambiguity resolution)
2849                                                         {
2850                                                             p = ::boost::math::quaternion<T>(a,b);                // too late to backtrack
2851 
2852                                                             is >> g;                                    // read "((a,b),(e,f,g"
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),(e,f,g)"
2867                                                             {
2868                                                                 is >> ch;                                    // get the next lexeme
2869 
2870                                                                 if    (!is.good())    goto finish;
2871 
2872 #ifdef    BOOST_NO_STD_LOCALE
2873                                                                 cc = ch;
2874 #else
2875                                                                 cc = ct.narrow(ch, char());
2876 #endif /* BOOST_NO_STD_LOCALE */
2877 
2878                                                                 if        (cc == ')')                            // read "((a,b),(e,f,g))"
2879                                                                 {
2880                                                                     q = ::boost::math::quaternion<T>(c,d,g);            // "c" is actually "e" and "d" is actually "f"
2881 
2882                                                                     o = octonion<T>(p,q);
2883                                                                 }
2884                                                                 else                                        // error
2885                                                                 {
2886                                                                     is.setstate(::std::ios_base::failbit);
2887                                                                 }
2888                                                             }
2889                                                             else if    (cc == ',')                            // read "((a,b),(e,f,g,"
2890                                                             {
2891                                                                 is >> h;                                    // read "((a,b),(e,f,g,h"
2892 
2893                                                                 if    (!is.good())    goto finish;
2894 
2895                                                                 is >> ch;                                    // get the next lexeme
2896 
2897                                                                 if    (!is.good())    goto finish;
2898 
2899 #ifdef    BOOST_NO_STD_LOCALE
2900                                                                 cc = ch;
2901 #else
2902                                                                 cc = ct.narrow(ch, char());
2903 #endif /* BOOST_NO_STD_LOCALE */
2904 
2905                                                                 if        (cc == ')')                            // read "((a,b),(e,f,g,h)"
2906                                                                 {
2907                                                                     is >> ch;                                    // get the next lexeme
2908 
2909                                                                     if    (!is.good())    goto finish;
2910 
2911 #ifdef    BOOST_NO_STD_LOCALE
2912                                                                     cc = ch;
2913 #else
2914                                                                     cc = ct.narrow(ch, char());
2915 #endif /* BOOST_NO_STD_LOCALE */
2916 
2917                                                                     if        (cc == ')')                            // read ((a,b),(e,f,g,h))"
2918                                                                     {
2919                                                                         q = ::boost::math::quaternion<T>(c,d,g,h);            // "c" is actually "e" and "d" is actually "f"
2920 
2921                                                                         o = octonion<T>(p,q);
2922                                                                     }
2923                                                                     else                                        // error
2924                                                                     {
2925                                                                         is.setstate(::std::ios_base::failbit);
2926                                                                     }
2927                                                                 }
2928                                                                 else                                        // error
2929                                                                 {
2930                                                                     is.setstate(::std::ios_base::failbit);
2931                                                                 }
2932                                                             }
2933                                                             else                                        // error
2934                                                             {
2935                                                                 is.setstate(::std::ios_base::failbit);
2936                                                             }
2937                                                         }
2938                                                         else                                        // error
2939                                                         {
2940                                                             is.setstate(::std::ios_base::failbit);
2941                                                         }
2942                                                     }
2943                                                 }
2944                                                 else                                        // error
2945                                                 {
2946                                                     is.setstate(::std::ios_base::failbit);
2947                                                 }
2948                                             }
2949                                         }
2950                                         else                                        // error
2951                                         {
2952                                             is.setstate(::std::ios_base::failbit);
2953                                         }
2954                                     }
2955                                     else                                        // error
2956                                     {
2957                                         is.setstate(::std::ios_base::failbit);
2958                                     }
2959                                 }
2960                                 else if    (cc == ',')                            // read "((a,b,"
2961                                 {
2962                                     is >> c;                                    // read "((a,b,c"
2963 
2964                                     if    (!is.good())    goto finish;
2965 
2966                                     is >> ch;                                    // get the next lexeme
2967 
2968                                     if    (!is.good())    goto finish;
2969 
2970 #ifdef    BOOST_NO_STD_LOCALE
2971                                     cc = ch;
2972 #else
2973                                     cc = ct.narrow(ch, char());
2974 #endif /* BOOST_NO_STD_LOCALE */
2975 
2976                                     if        (cc == ')')                            // read "((a,b,c)"
2977                                     {
2978                                         is >> ch;                                    // get the next lexeme
2979 
2980                                         if    (!is.good())    goto finish;
2981 
2982 #ifdef    BOOST_NO_STD_LOCALE
2983                                         cc = ch;
2984 #else
2985                                         cc = ct.narrow(ch, char());
2986 #endif /* BOOST_NO_STD_LOCALE */
2987 
2988                                         if        (cc == ')')                            // read "((a,b,c))"
2989                                         {
2990                                             o = octonion<T>(a,b,c);
2991                                         }
2992                                         else if    (cc == ',')                            // read "((a,b,c),"
2993                                         {
2994                                             p = ::boost::math::quaternion<T>(a,b,c);
2995 
2996                                             is >> q;                                    // read "((a,b,c),q"
2997 
2998                                             if    (!is.good())    goto finish;
2999 
3000                                             is >> ch;                                    // get the next lexeme
3001 
3002                                             if    (!is.good())    goto finish;
3003 
3004 #ifdef    BOOST_NO_STD_LOCALE
3005                                             cc = ch;
3006 #else
3007                                             cc = ct.narrow(ch, char());
3008 #endif /* BOOST_NO_STD_LOCALE */
3009 
3010                                             if        (cc == ')')                            // read "((a,b,c),q)"
3011                                             {
3012                                                 o = octonion<T>(p,q);
3013                                             }
3014                                             else                                        // error
3015                                             {
3016                                                 is.setstate(::std::ios_base::failbit);
3017                                             }
3018                                         }
3019                                         else                                        // error
3020                                         {
3021                                             is.setstate(::std::ios_base::failbit);
3022                                         }
3023                                     }
3024                                     else if    (cc == ',')                            // read "((a,b,c,"
3025                                     {
3026                                         is >> d;                                    // read "((a,b,c,d"
3027 
3028                                         if    (!is.good())    goto finish;
3029 
3030                                         is >> ch;                                    // get the next lexeme
3031 
3032                                         if    (!is.good())    goto finish;
3033 
3034 #ifdef    BOOST_NO_STD_LOCALE
3035                                         cc = ch;
3036 #else
3037                                         cc = ct.narrow(ch, char());
3038 #endif /* BOOST_NO_STD_LOCALE */
3039 
3040                                         if        (cc == ')')                            // read "((a,b,c,d)"
3041                                         {
3042                                             is >> ch;                                    // get the next lexeme
3043 
3044                                             if    (!is.good())    goto finish;
3045 
3046 #ifdef    BOOST_NO_STD_LOCALE
3047                                             cc = ch;
3048 #else
3049                                             cc = ct.narrow(ch, char());
3050 #endif /* BOOST_NO_STD_LOCALE */
3051 
3052                                             if        (cc == ')')                            // read "((a,b,c,d))"
3053                                             {
3054                                                 o = octonion<T>(a,b,c,d);
3055                                             }
3056                                             else if    (cc == ',')                            // read "((a,b,c,d),"
3057                                             {
3058                                                 p = ::boost::math::quaternion<T>(a,b,c,d);
3059 
3060                                                 is >> q;                                    // read "((a,b,c,d),q"
3061 
3062                                                 if    (!is.good())    goto finish;
3063 
3064                                                 is >> ch;                                    // get the next lexeme
3065 
3066                                                 if    (!is.good())    goto finish;
3067 
3068 #ifdef    BOOST_NO_STD_LOCALE
3069                                                 cc = ch;
3070 #else
3071                                                 cc = ct.narrow(ch, char());
3072 #endif /* BOOST_NO_STD_LOCALE */
3073 
3074                                                 if        (cc == ')')                            // read "((a,b,c,d),q)"
3075                                                 {
3076                                                     o = octonion<T>(p,q);
3077                                                 }
3078                                                 else                                        // error
3079                                                 {
3080                                                     is.setstate(::std::ios_base::failbit);
3081                                                 }
3082                                             }
3083                                             else                                        // error
3084                                             {
3085                                                 is.setstate(::std::ios_base::failbit);
3086                                             }
3087                                         }
3088                                         else                                        // error
3089                                         {
3090                                             is.setstate(::std::ios_base::failbit);
3091                                         }
3092                                     }
3093                                     else                                        // error
3094                                     {
3095                                         is.setstate(::std::ios_base::failbit);
3096                                     }
3097                                 }
3098                                 else                                        // error
3099                                 {
3100                                     is.setstate(::std::ios_base::failbit);
3101                                 }
3102                             }
3103                         }
3104                         else                                        // error
3105                         {
3106                             is.setstate(::std::ios_base::failbit);
3107                         }
3108                     }
3109                 }
3110                 else                                        // read "(a"
3111                 {
3112                     is.putback(ch);
3113 
3114                     is >> a;                                    // we extract the first component
3115 
3116                     if    (!is.good())    goto finish;
3117 
3118                     is >> ch;                                    // get the next lexeme
3119 
3120                     if    (!is.good())    goto finish;
3121 
3122 #ifdef    BOOST_NO_STD_LOCALE
3123                     cc = ch;
3124 #else
3125                     cc = ct.narrow(ch, char());
3126 #endif /* BOOST_NO_STD_LOCALE */
3127 
3128                     if        (cc == ')')                            // read "(a)"
3129                     {
3130                         o = octonion<T>(a);
3131                     }
3132                     else if    (cc == ',')                            // read "(a,"
3133                     {
3134                         is >> ch;                                    // get the next lexeme
3135 
3136                         if    (!is.good())    goto finish;
3137 
3138 #ifdef    BOOST_NO_STD_LOCALE
3139                         cc = ch;
3140 #else
3141                         cc = ct.narrow(ch, char());
3142 #endif /* BOOST_NO_STD_LOCALE */
3143 
3144                         if        (cc == '(')                            // read "(a,("
3145                         {
3146                             is >> ch;                                    // get the next lexeme
3147 
3148                             if    (!is.good())    goto finish;
3149 
3150 #ifdef    BOOST_NO_STD_LOCALE
3151                             cc = ch;
3152 #else
3153                             cc = ct.narrow(ch, char());
3154 #endif /* BOOST_NO_STD_LOCALE */
3155 
3156                             if        (cc == '(')                            // read "(a,(("
3157                             {
3158                                 p = ::boost::math::quaternion<T>(a);
3159 
3160                                 is.putback(ch);
3161 
3162                                 is.putback(ch);                                // we backtrack twice, with the same value
3163 
3164                                 is >> q;                                    // read "(a,q"
3165 
3166                                 if    (!is.good())    goto finish;
3167 
3168                                 is >> ch;                                    // get the next lexeme
3169 
3170                                 if    (!is.good())    goto finish;
3171 
3172 #ifdef    BOOST_NO_STD_LOCALE
3173                                 cc = ch;
3174 #else
3175                                 cc = ct.narrow(ch, char());
3176 #endif /* BOOST_NO_STD_LOCALE */
3177 
3178                                 if        (cc == ')')                            // read "(a,q)"
3179                                 {
3180                                     o = octonion<T>(p,q);
3181                                 }
3182                                 else                                        // error
3183                                 {
3184                                     is.setstate(::std::ios_base::failbit);
3185                                 }
3186                             }
3187                             else                                        // read "(a,(c" or "(a,(e"
3188                             {
3189                                 is.putback(ch);
3190 
3191                                 is >> c;
3192 
3193                                 if    (!is.good())    goto finish;
3194 
3195                                 is >> ch;                                    // get the next lexeme
3196 
3197                                 if    (!is.good())    goto finish;
3198 
3199 #ifdef    BOOST_NO_STD_LOCALE
3200                                 cc = ch;
3201 #else
3202                                 cc = ct.narrow(ch, char());
3203 #endif /* BOOST_NO_STD_LOCALE */
3204 
3205                                 if        (cc == ')')                            // read "(a,(c)" (ambiguity resolution)
3206                                 {
3207                                     is >> ch;                                    // get the next lexeme
3208 
3209                                     if    (!is.good())    goto finish;
3210 
3211 #ifdef    BOOST_NO_STD_LOCALE
3212                                     cc = ch;
3213 #else
3214                                     cc = ct.narrow(ch, char());
3215 #endif /* BOOST_NO_STD_LOCALE */
3216 
3217                                     if        (cc == ')')                            // read "(a,(c))"
3218                                     {
3219                                         o = octonion<T>(a,b,c);
3220                                     }
3221                                     else if    (cc == ',')                            // read "(a,(c),"
3222                                     {
3223                                         u = ::std::complex<T>(a);
3224 
3225                                         v = ::std::complex<T>(c);
3226 
3227                                         is >> x;                                // read "(a,(c),x"
3228 
3229                                         if    (!is.good())    goto finish;
3230 
3231                                         is >> ch;                                    // get the next lexeme
3232 
3233                                         if    (!is.good())    goto finish;
3234 
3235 #ifdef    BOOST_NO_STD_LOCALE
3236                                         cc = ch;
3237 #else
3238                                         cc = ct.narrow(ch, char());
3239 #endif /* BOOST_NO_STD_LOCALE */
3240 
3241                                         if        (cc == ')')                            // read "(a,(c),x)"
3242                                         {
3243                                             o = octonion<T>(u,v,x);
3244                                         }
3245                                         else if    (cc == ',')                            // read "(a,(c),x,"
3246                                         {
3247                                             is >> y;                                    // read "(a,(c),x,y"
3248 
3249                                             if    (!is.good())    goto finish;
3250 
3251                                             is >> ch;                                    // get the next lexeme
3252 
3253                                             if    (!is.good())    goto finish;
3254 
3255 #ifdef    BOOST_NO_STD_LOCALE
3256                                             cc = ch;
3257 #else
3258                                             cc = ct.narrow(ch, char());
3259 #endif /* BOOST_NO_STD_LOCALE */
3260 
3261                                             if        (cc == ')')                            // read "(a,(c),x,y)"
3262                                             {
3263                                                 o = octonion<T>(u,v,x,y);
3264                                             }
3265                                             else                                        // error
3266                                             {
3267                                                 is.setstate(::std::ios_base::failbit);
3268                                             }
3269                                         }
3270                                         else                                        // error
3271                                         {
3272                                             is.setstate(::std::ios_base::failbit);
3273                                         }
3274                                     }
3275                                     else                                        // error
3276                                     {
3277                                         is.setstate(::std::ios_base::failbit);
3278                                     }
3279                                 }
3280                                 else if    (cc == ',')                            // read "(a,(c," or "(a,(e,"
3281                                 {
3282                                     is >> ch;                                    // get the next lexeme
3283 
3284                                     if    (!is.good())    goto finish;
3285 
3286 #ifdef    BOOST_NO_STD_LOCALE
3287                                     cc = ch;
3288 #else
3289                                     cc = ct.narrow(ch, char());
3290 #endif /* BOOST_NO_STD_LOCALE */
3291 
3292                                     if        (cc == '(')                            // read "(a,(e,(" (ambiguity resolution)
3293                                     {
3294                                         u = ::std::complex<T>(a);
3295 
3296                                         x = ::std::complex<T>(c);                // "c" is actually "e"
3297 
3298                                         is.putback(ch);                            // we backtrack
3299 
3300                                         is >> y;                                // read "(a,(e,y"
3301 
3302                                         if    (!is.good())    goto finish;
3303 
3304                                         is >> ch;                                    // get the next lexeme
3305 
3306                                         if    (!is.good())    goto finish;
3307 
3308 #ifdef    BOOST_NO_STD_LOCALE
3309                                         cc = ch;
3310 #else
3311                                         cc = ct.narrow(ch, char());
3312 #endif /* BOOST_NO_STD_LOCALE */
3313 
3314                                         if        (cc == ')')                            // read "(a,(e,y)"
3315                                         {
3316                                             is >> ch;                                    // get the next lexeme
3317 
3318                                             if    (!is.good())    goto finish;
3319 
3320 #ifdef    BOOST_NO_STD_LOCALE
3321                                             cc = ch;
3322 #else
3323                                             cc = ct.narrow(ch, char());
3324 #endif /* BOOST_NO_STD_LOCALE */
3325 
3326                                             if        (cc == ')')                            // read "(a,(e,y))"
3327                                             {
3328                                                 o = octonion<T>(u,v,x,y);
3329                                             }
3330                                             else                                        // error
3331                                             {
3332                                                 is.setstate(::std::ios_base::failbit);
3333                                             }
3334                                         }
3335                                         else                                        // error
3336                                         {
3337                                             is.setstate(::std::ios_base::failbit);
3338                                         }
3339                                     }
3340                                     else                                        // read "(a,(c,d" or "(a,(e,f"
3341                                     {
3342                                         is.putback(ch);
3343 
3344                                         is >> d;
3345 
3346                                         if    (!is.good())    goto finish;
3347 
3348                                         is >> ch;                                    // get the next lexeme
3349 
3350                                         if    (!is.good())    goto finish;
3351 
3352 #ifdef    BOOST_NO_STD_LOCALE
3353                                         cc = ch;
3354 #else
3355                                         cc = ct.narrow(ch, char());
3356 #endif /* BOOST_NO_STD_LOCALE */
3357 
3358                                         if        (cc == ')')                            // read "(a,(c,d)" (ambiguity resolution)
3359                                         {
3360                                             is >> ch;                                    // get the next lexeme
3361 
3362                                             if    (!is.good())    goto finish;
3363 
3364 #ifdef    BOOST_NO_STD_LOCALE
3365                                             cc = ch;
3366 #else
3367                                             cc = ct.narrow(ch, char());
3368 #endif /* BOOST_NO_STD_LOCALE */
3369 
3370                                             if        (cc == ')')                            // read "(a,(c,d))"
3371                                             {
3372                                                 o = octonion<T>(a,b,c,d);
3373                                             }
3374                                             else if    (cc == ',')                            // read "(a,(c,d),"
3375                                             {
3376                                                 u = ::std::complex<T>(a);
3377 
3378                                                 v = ::std::complex<T>(c,d);
3379 
3380                                                 is >> x;                                // read "(a,(c,d),x"
3381 
3382                                                 if    (!is.good())    goto finish;
3383 
3384                                                 is >> ch;                                    // get the next lexeme
3385 
3386                                                 if    (!is.good())    goto finish;
3387 
3388 #ifdef    BOOST_NO_STD_LOCALE
3389                                                 cc = ch;
3390 #else
3391                                                 cc = ct.narrow(ch, char());
3392 #endif /* BOOST_NO_STD_LOCALE */
3393 
3394                                                 if        (cc == ')')                            // read "(a,(c,d),x)"
3395                                                 {
3396                                                     o = octonion<T>(u,v,x);
3397                                                 }
3398                                                 else if    (cc == ',')                            // read "(a,(c,d),x,"
3399                                                 {
3400                                                     is >> y;                                    // read "(a,(c,d),x,y"
3401 
3402                                                     if    (!is.good())    goto finish;
3403 
3404                                                     is >> ch;                                    // get the next lexeme
3405 
3406                                                     if    (!is.good())    goto finish;
3407 
3408 #ifdef    BOOST_NO_STD_LOCALE
3409                                                     cc = ch;
3410 #else
3411                                                     cc = ct.narrow(ch, char());
3412 #endif /* BOOST_NO_STD_LOCALE */
3413 
3414                                                     if        (cc == ')')                            // read "(a,(c,d),x,y)"
3415                                                     {
3416                                                         o = octonion<T>(u,v,x,y);
3417                                                     }
3418                                                     else                                        // error
3419                                                     {
3420                                                         is.setstate(::std::ios_base::failbit);
3421                                                     }
3422                                                 }
3423                                                 else                                        // error
3424                                                 {
3425                                                     is.setstate(::std::ios_base::failbit);
3426                                                 }
3427                                             }
3428                                             else                                        // error
3429                                             {
3430                                                 is.setstate(::std::ios_base::failbit);
3431                                             }
3432                                         }
3433                                         else if    (cc == ',')                            // read "(a,(e,f," (ambiguity resolution)
3434                                         {
3435                                             p = ::boost::math::quaternion<T>(a);
3436 
3437                                             is >> g;                                    // read "(a,(e,f,g"
3438 
3439                                             if    (!is.good())    goto finish;
3440 
3441                                             is >> ch;                                    // get the next lexeme
3442 
3443                                             if    (!is.good())    goto finish;
3444 
3445 #ifdef    BOOST_NO_STD_LOCALE
3446                                             cc = ch;
3447 #else
3448                                             cc = ct.narrow(ch, char());
3449 #endif /* BOOST_NO_STD_LOCALE */
3450 
3451                                             if        (cc == ')')                            // read "(a,(e,f,g)"
3452                                             {
3453                                                 is >> ch;                                    // get the next lexeme
3454 
3455                                                 if    (!is.good())    goto finish;
3456 
3457 #ifdef    BOOST_NO_STD_LOCALE
3458                                                 cc = ch;
3459 #else
3460                                                 cc = ct.narrow(ch, char());
3461 #endif /* BOOST_NO_STD_LOCALE */
3462 
3463                                                 if        (cc == ')')                            // read "(a,(e,f,g))"
3464                                                 {
3465                                                     q = ::boost::math::quaternion<T>(c,d,g);            // "c" is actually "e" and "d" is actually "f"
3466 
3467                                                     o = octonion<T>(p,q);
3468                                                 }
3469                                                 else                                        // error
3470                                                 {
3471                                                     is.setstate(::std::ios_base::failbit);
3472                                                 }
3473                                             }
3474                                             else if    (cc == ',')                            // read "(a,(e,f,g,"
3475                                             {
3476                                                 is >> h;                                    // read "(a,(e,f,g,h"
3477 
3478                                                 if    (!is.good())    goto finish;
3479 
3480                                                 is >> ch;                                    // get the next lexeme
3481 
3482                                                 if    (!is.good())    goto finish;
3483 
3484 #ifdef    BOOST_NO_STD_LOCALE
3485                                                 cc = ch;
3486 #else
3487                                                 cc = ct.narrow(ch, char());
3488 #endif /* BOOST_NO_STD_LOCALE */
3489 
3490                                                 if        (cc == ')')                            // read "(a,(e,f,g,h)"
3491                                                 {
3492                                                     is >> ch;                                    // get the next lexeme
3493 
3494                                                     if    (!is.good())    goto finish;
3495 
3496 #ifdef    BOOST_NO_STD_LOCALE
3497                                                     cc = ch;
3498 #else
3499                                                     cc = ct.narrow(ch, char());
3500 #endif /* BOOST_NO_STD_LOCALE */
3501 
3502                                                     if        (cc == ')')                            // read "(a,(e,f,g,h))"
3503                                                     {
3504                                                         q = ::boost::math::quaternion<T>(c,d,g,h);            // "c" is actually "e" and "d" is actually "f"
3505 
3506                                                         o = octonion<T>(p,q);
3507                                                     }
3508                                                     else                                        // error
3509                                                     {
3510                                                         is.setstate(::std::ios_base::failbit);
3511                                                     }
3512                                                 }
3513                                                 else                                        // error
3514                                                 {
3515                                                     is.setstate(::std::ios_base::failbit);
3516                                                 }
3517                                             }
3518                                             else                                        // error
3519                                             {
3520                                                 is.setstate(::std::ios_base::failbit);
3521                                             }
3522                                         }
3523                                         else                                        // error
3524                                         {
3525                                             is.setstate(::std::ios_base::failbit);
3526                                         }
3527                                     }
3528                                 }
3529                                 else                                        // error
3530                                 {
3531                                     is.setstate(::std::ios_base::failbit);
3532                                 }
3533                             }
3534                         }
3535                         else                                        // read "(a,b" or "(a,c" (ambiguity resolution)
3536                         {
3537                             is.putback(ch);
3538 
3539                             is >> b;
3540 
3541                             if    (!is.good())    goto finish;
3542 
3543                             is >> ch;                                    // get the next lexeme
3544 
3545                             if    (!is.good())    goto finish;
3546 
3547 #ifdef    BOOST_NO_STD_LOCALE
3548                             cc = ch;
3549 #else
3550                             cc = ct.narrow(ch, char());
3551 #endif /* BOOST_NO_STD_LOCALE */
3552 
3553                             if        (cc == ')')                            // read "(a,b)" (ambiguity resolution)
3554                             {
3555                                 o = octonion<T>(a,b);
3556                             }
3557                             else if    (cc == ',')                            // read "(a,b," or "(a,c,"
3558                             {
3559                                 is >> ch;                                    // get the next lexeme
3560 
3561                                 if    (!is.good())    goto finish;
3562 
3563 #ifdef    BOOST_NO_STD_LOCALE
3564                                 cc = ch;
3565 #else
3566                                 cc = ct.narrow(ch, char());
3567 #endif /* BOOST_NO_STD_LOCALE */
3568 
3569                                 if        (cc == '(')                            // read "(a,c,(" (ambiguity resolution)
3570                                 {
3571                                     u = ::std::complex<T>(a);
3572 
3573                                     v = ::std::complex<T>(b);                    // "b" is actually "c"
3574 
3575                                     is.putback(ch);                                // we backtrack
3576 
3577                                     is >> x;                                    // read "(a,c,x"
3578 
3579                                     if    (!is.good())    goto finish;
3580 
3581                                     is >> ch;                                    // get the next lexeme
3582 
3583                                     if    (!is.good())    goto finish;
3584 
3585 #ifdef    BOOST_NO_STD_LOCALE
3586                                     cc = ch;
3587 #else
3588                                     cc = ct.narrow(ch, char());
3589 #endif /* BOOST_NO_STD_LOCALE */
3590 
3591                                     if        (cc == ')')                            // read "(a,c,x)"
3592                                     {
3593                                         o = octonion<T>(u,v,x);
3594                                     }
3595                                     else if    (cc == ',')                            // read "(a,c,x,"
3596                                     {
3597                                         is >> y;                                    // read "(a,c,x,y"                                    // read "(a,c,x"
3598 
3599                                         if    (!is.good())    goto finish;
3600 
3601                                         is >> ch;                                    // get the next lexeme
3602 
3603                                         if    (!is.good())    goto finish;
3604 
3605 #ifdef    BOOST_NO_STD_LOCALE
3606                                         cc = ch;
3607 #else
3608                                         cc = ct.narrow(ch, char());
3609 #endif /* BOOST_NO_STD_LOCALE */
3610 
3611                                         if        (cc == ')')                            // read "(a,c,x,y)"
3612                                         {
3613                                             o = octonion<T>(u,v,x,y);
3614                                         }
3615                                         else                                        // error
3616                                         {
3617                                             is.setstate(::std::ios_base::failbit);
3618                                         }
3619                                     }
3620                                     else                                        // error
3621                                     {
3622                                         is.setstate(::std::ios_base::failbit);
3623                                     }
3624                                 }
3625                                 else                                        // read "(a,b,c" or "(a,c,e"
3626                                 {
3627                                     is.putback(ch);
3628 
3629                                     is >> c;
3630 
3631                                     if    (!is.good())    goto finish;
3632 
3633                                     is >> ch;                                    // get the next lexeme
3634 
3635                                     if    (!is.good())    goto finish;
3636 
3637 #ifdef    BOOST_NO_STD_LOCALE
3638                                     cc = ch;
3639 #else
3640                                     cc = ct.narrow(ch, char());
3641 #endif /* BOOST_NO_STD_LOCALE */
3642 
3643                                     if        (cc == ')')                            // read "(a,b,c)" (ambiguity resolution)
3644                                     {
3645                                         o = octonion<T>(a,b,c);
3646                                     }
3647                                     else if    (cc == ',')                            // read "(a,b,c," or "(a,c,e,"
3648                                     {
3649                                         is >> ch;                                    // get the next lexeme
3650 
3651                                         if    (!is.good())    goto finish;
3652 
3653 #ifdef    BOOST_NO_STD_LOCALE
3654                                         cc = ch;
3655 #else
3656                                         cc = ct.narrow(ch, char());
3657 #endif /* BOOST_NO_STD_LOCALE */
3658 
3659                                         if        (cc == '(')                            // read "(a,c,e,(") (ambiguity resolution)
3660                                         {
3661                                             u = ::std::complex<T>(a);
3662 
3663                                             v = ::std::complex<T>(b);                    // "b" is actually "c"
3664 
3665                                             x = ::std::complex<T>(c);                    // "c" is actually "e"
3666 
3667                                             is.putback(ch);                                // we backtrack
3668 
3669                                             is >> y;                                    // read "(a,c,e,y"
3670 
3671                                             if    (!is.good())    goto finish;
3672 
3673                                             is >> ch;                                    // get the next lexeme
3674 
3675                                             if    (!is.good())    goto finish;
3676 
3677 #ifdef    BOOST_NO_STD_LOCALE
3678                                             cc = ch;
3679 #else
3680                                             cc = ct.narrow(ch, char());
3681 #endif /* BOOST_NO_STD_LOCALE */
3682 
3683                                             if        (cc == ')')                            // read "(a,c,e,y)"
3684                                             {
3685                                                 o = octonion<T>(u,v,x,y);
3686                                             }
3687                                             else                                        // error
3688                                             {
3689                                                 is.setstate(::std::ios_base::failbit);
3690                                             }
3691                                         }
3692                                         else                                        // read "(a,b,c,d" (ambiguity resolution)
3693                                         {
3694                                             is.putback(ch);                                // we backtrack
3695 
3696                                             is >> d;
3697 
3698                                             if    (!is.good())    goto finish;
3699 
3700                                             is >> ch;                                    // get the next lexeme
3701 
3702                                             if    (!is.good())    goto finish;
3703 
3704 #ifdef    BOOST_NO_STD_LOCALE
3705                                             cc = ch;
3706 #else
3707                                             cc = ct.narrow(ch, char());
3708 #endif /* BOOST_NO_STD_LOCALE */
3709 
3710                                             if        (cc == ')')                            // read "(a,b,c,d)"
3711                                             {
3712                                                 o = octonion<T>(a,b,c,d);
3713                                             }
3714                                             else if    (cc == ',')                            // read "(a,b,c,d,"
3715                                             {
3716                                                 is >> e;                                    // read "(a,b,c,d,e"
3717 
3718                                                 if    (!is.good())    goto finish;
3719 
3720                                                 is >> ch;                                    // get the next lexeme
3721 
3722                                                 if    (!is.good())    goto finish;
3723 
3724 #ifdef    BOOST_NO_STD_LOCALE
3725                                                 cc = ch;
3726 #else
3727                                                 cc = ct.narrow(ch, char());
3728 #endif /* BOOST_NO_STD_LOCALE */
3729 
3730                                                 if        (cc == ')')                            // read "(a,b,c,d,e)"
3731                                                 {
3732                                                     o = octonion<T>(a,b,c,d,e);
3733                                                 }
3734                                                 else if    (cc == ',')                            // read "(a,b,c,d,e,"
3735                                                 {
3736                                                     is >> f;                                    // read "(a,b,c,d,e,f"
3737 
3738                                                     if    (!is.good())    goto finish;
3739 
3740                                                     is >> ch;                                    // get the next lexeme
3741 
3742                                                     if    (!is.good())    goto finish;
3743 
3744 #ifdef    BOOST_NO_STD_LOCALE
3745                                                     cc = ch;
3746 #else
3747                                                     cc = ct.narrow(ch, char());
3748 #endif /* BOOST_NO_STD_LOCALE */
3749 
3750                                                     if        (cc == ')')                            // read "(a,b,c,d,e,f)"
3751                                                     {
3752                                                         o = octonion<T>(a,b,c,d,e,f);
3753                                                     }
3754                                                     else if    (cc == ',')                            // read "(a,b,c,d,e,f,"
3755                                                     {
3756                                                         is >> g;                                    // read "(a,b,c,d,e,f,g"                                    // read "(a,b,c,d,e,f"
3757 
3758                                                         if    (!is.good())    goto finish;
3759 
3760                                                         is >> ch;                                    // get the next lexeme
3761 
3762                                                         if    (!is.good())    goto finish;
3763 
3764 #ifdef    BOOST_NO_STD_LOCALE
3765                                                         cc = ch;
3766 #else
3767                                                         cc = ct.narrow(ch, char());
3768 #endif /* BOOST_NO_STD_LOCALE */
3769 
3770                                                         if        (cc == ')')                            // read "(a,b,c,d,e,f,g)"
3771                                                         {
3772                                                             o = octonion<T>(a,b,c,d,e,f,g);
3773                                                         }
3774                                                         else if    (cc == ',')                            // read "(a,b,c,d,e,f,g,"
3775                                                         {
3776                                                             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"
3777 
3778                                                             if    (!is.good())    goto finish;
3779 
3780                                                             is >> ch;                                    // get the next lexeme
3781 
3782                                                             if    (!is.good())    goto finish;
3783 
3784 #ifdef    BOOST_NO_STD_LOCALE
3785                                                             cc = ch;
3786 #else
3787                                                             cc = ct.narrow(ch, char());
3788 #endif /* BOOST_NO_STD_LOCALE */
3789 
3790                                                             if        (cc == ')')                            // read "(a,b,c,d,e,f,g,h)"
3791                                                             {
3792                                                                 o = octonion<T>(a,b,c,d,e,f,g,h);
3793                                                             }
3794                                                             else                                        // error
3795                                                             {
3796                                                                 is.setstate(::std::ios_base::failbit);
3797                                                             }
3798                                                         }
3799                                                         else                                        // error
3800                                                         {
3801                                                             is.setstate(::std::ios_base::failbit);
3802                                                         }
3803                                                     }
3804                                                     else                                        // error
3805                                                     {
3806                                                         is.setstate(::std::ios_base::failbit);
3807                                                     }
3808                                                 }
3809                                                 else                                        // error
3810                                                 {
3811                                                     is.setstate(::std::ios_base::failbit);
3812                                                 }
3813                                             }
3814                                             else                                        // error
3815                                             {
3816                                                 is.setstate(::std::ios_base::failbit);
3817                                             }
3818                                         }
3819                                     }
3820                                     else                                        // error
3821                                     {
3822                                         is.setstate(::std::ios_base::failbit);
3823                                     }
3824                                 }
3825                             }
3826                             else                                        // error
3827                             {
3828                                 is.setstate(::std::ios_base::failbit);
3829                             }
3830                         }
3831                     }
3832                     else                                        // error
3833                     {
3834                         is.setstate(::std::ios_base::failbit);
3835                     }
3836                 }
3837             }
3838             else                                        // format:    a
3839             {
3840                 is.putback(ch);
3841 
3842                 is >> a;                                    // we extract the first component
3843 
3844                 if    (!is.good())    goto finish;
3845 
3846                 o = octonion<T>(a);
3847             }
3848 
3849             finish:
3850             return(is);
3851         }
3852         // LCOV_EXCL_STOP
3853 
3854 
3855         template<typename T, typename charT, class traits>
3856         ::std::basic_ostream<charT,traits> &    operator << (    ::std::basic_ostream<charT,traits> & os,
3857                                                                 octonion<T> const & o)
3858         {
3859             ::std::basic_ostringstream<charT,traits>    s;
3860 
3861             s.flags(os.flags());
3862 #ifdef    BOOST_NO_STD_LOCALE
3863 #else
3864             s.imbue(os.getloc());
3865 #endif /* BOOST_NO_STD_LOCALE */
3866             s.precision(os.precision());
3867 
3868             s << '('    << o.R_component_1() << ','
3869                         << o.R_component_2() << ','
3870                         << o.R_component_3() << ','
3871                         << o.R_component_4() << ','
3872                         << o.R_component_5() << ','
3873                         << o.R_component_6() << ','
3874                         << o.R_component_7() << ','
3875                         << o.R_component_8() << ')';
3876 
3877             return os << s.str();
3878         }
3879 
3880 
3881         // values
3882 
3883         template<typename T>
3884         inline T                                real(octonion<T> const & o)
3885         {
3886             return(o.real());
3887         }
3888 
3889 
3890         template<typename T>
3891         inline octonion<T>                        unreal(octonion<T> const & o)
3892         {
3893             return(o.unreal());
3894         }
3895 
3896 
3897 #define    BOOST_OCTONION_VALARRAY_LOADER   \
3898             using    ::std::valarray;       \
3899                                             \
3900             valarray<T>    temp(8);         \
3901                                             \
3902             temp[0] = o.R_component_1();    \
3903             temp[1] = o.R_component_2();    \
3904             temp[2] = o.R_component_3();    \
3905             temp[3] = o.R_component_4();    \
3906             temp[4] = o.R_component_5();    \
3907             temp[5] = o.R_component_6();    \
3908             temp[6] = o.R_component_7();    \
3909             temp[7] = o.R_component_8();
3910 
3911 
3912         template<typename T>
3913         inline T                                sup(octonion<T> const & o)
3914         {
3915 #ifdef    BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
3916             using    ::std::abs;
3917 #endif    /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
3918 
3919             BOOST_OCTONION_VALARRAY_LOADER
3920 
3921             return((abs(temp).max)());
3922         }
3923 
3924 
3925         template<typename T>
3926         inline T                                l1(octonion<T> const & o)
3927         {
3928 #ifdef    BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
3929             using    ::std::abs;
3930 #endif    /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
3931 
3932             BOOST_OCTONION_VALARRAY_LOADER
3933 
3934             return(abs(temp).sum());
3935         }
3936 
3937 
3938         template<typename T>
3939         inline T                                abs(const octonion<T> & o)
3940         {
3941 #ifdef    BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
3942             using    ::std::abs;
3943 #endif    /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
3944 
3945             using    ::std::sqrt;
3946 
3947             BOOST_OCTONION_VALARRAY_LOADER
3948 
3949             T            maxim = (abs(temp).max)();    // overflow protection
3950 
3951             if    (maxim == static_cast<T>(0))
3952             {
3953                 return(maxim);
3954             }
3955             else
3956             {
3957                 T    mixam = static_cast<T>(1)/maxim;    // prefer multiplications over divisions
3958 
3959                 temp *= mixam;
3960 
3961                 temp *= temp;
3962 
3963                 return(maxim*sqrt(temp.sum()));
3964             }
3965 
3966             //return(::std::sqrt(norm(o)));
3967         }
3968 
3969 
3970 #undef    BOOST_OCTONION_VALARRAY_LOADER
3971 
3972 
3973         // Note:    This is the Cayley norm, not the Euclidean norm...
3974 
3975         template<typename T>
3976         inline T                                norm(octonion<T> const & o)
3977         {
3978             return(real(o*conj(o)));
3979         }
3980 
3981 
3982         template<typename T>
3983         inline octonion<T>                        conj(octonion<T> const & o)
3984         {
3985             return(octonion<T>( +o.R_component_1(),
3986                                 -o.R_component_2(),
3987                                 -o.R_component_3(),
3988                                 -o.R_component_4(),
3989                                 -o.R_component_5(),
3990                                 -o.R_component_6(),
3991                                 -o.R_component_7(),
3992                                 -o.R_component_8()));
3993         }
3994 
3995 
3996         // Note:    There is little point, for the octonions, to introduce the equivalents
3997         //            to the complex "arg" and the quaternionic "cylindropolar".
3998 
3999 
4000         template<typename T>
4001         inline octonion<T>                        spherical(T const & rho,
4002                                                             T const & theta,
4003                                                             T const & phi1,
4004                                                             T const & phi2,
4005                                                             T const & phi3,
4006                                                             T const & phi4,
4007                                                             T const & phi5,
4008                                                             T const & phi6)
4009         {
4010             using ::std::cos;
4011             using ::std::sin;
4012 
4013             //T    a = cos(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4014             //T    b = sin(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4015             //T    c = sin(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4016             //T    d = sin(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4017             //T    e = sin(phi3)*cos(phi4)*cos(phi5)*cos(phi6);
4018             //T    f = sin(phi4)*cos(phi5)*cos(phi6);
4019             //T    g = sin(phi5)*cos(phi6);
4020             //T    h = sin(phi6);
4021 
4022             T    courrant = static_cast<T>(1);
4023 
4024             T    h = sin(phi6);
4025 
4026             courrant *= cos(phi6);
4027 
4028             T    g = sin(phi5)*courrant;
4029 
4030             courrant *= cos(phi5);
4031 
4032             T    f = sin(phi4)*courrant;
4033 
4034             courrant *= cos(phi4);
4035 
4036             T    e = sin(phi3)*courrant;
4037 
4038             courrant *= cos(phi3);
4039 
4040             T    d = sin(phi2)*courrant;
4041 
4042             courrant *= cos(phi2);
4043 
4044             T    c = sin(phi1)*courrant;
4045 
4046             courrant *= cos(phi1);
4047 
4048             T    b = sin(theta)*courrant;
4049             T    a = cos(theta)*courrant;
4050 
4051             return(rho*octonion<T>(a,b,c,d,e,f,g,h));
4052         }
4053 
4054 
4055         template<typename T>
4056         inline octonion<T>                        multipolar(T const & rho1,
4057                                                              T const & theta1,
4058                                                              T const & rho2,
4059                                                              T const & theta2,
4060                                                              T const & rho3,
4061                                                              T const & theta3,
4062                                                              T const & rho4,
4063                                                              T const & theta4)
4064         {
4065             using ::std::cos;
4066             using ::std::sin;
4067 
4068             T    a = rho1*cos(theta1);
4069             T    b = rho1*sin(theta1);
4070             T    c = rho2*cos(theta2);
4071             T    d = rho2*sin(theta2);
4072             T    e = rho3*cos(theta3);
4073             T    f = rho3*sin(theta3);
4074             T    g = rho4*cos(theta4);
4075             T    h = rho4*sin(theta4);
4076 
4077             return(octonion<T>(a,b,c,d,e,f,g,h));
4078         }
4079 
4080 
4081         template<typename T>
4082         inline octonion<T>                        cylindrical(T const & r,
4083                                                               T const & angle,
4084                                                               T const & h1,
4085                                                               T const & h2,
4086                                                               T const & h3,
4087                                                               T const & h4,
4088                                                               T const & h5,
4089                                                               T const & h6)
4090         {
4091             using ::std::cos;
4092             using ::std::sin;
4093 
4094             T    a = r*cos(angle);
4095             T    b = r*sin(angle);
4096 
4097             return(octonion<T>(a,b,h1,h2,h3,h4,h5,h6));
4098         }
4099 
4100 
4101         template<typename T>
4102         inline octonion<T>                        exp(octonion<T> const & o)
4103         {
4104             using    ::std::exp;
4105             using    ::std::cos;
4106 
4107             using    ::boost::math::sinc_pi;
4108 
4109             T    u = exp(real(o));
4110 
4111             T    z = abs(unreal(o));
4112 
4113             T    w = sinc_pi(z);
4114 
4115             return(u*octonion<T>(cos(z),
4116                 w*o.R_component_2(), w*o.R_component_3(),
4117                 w*o.R_component_4(), w*o.R_component_5(),
4118                 w*o.R_component_6(), w*o.R_component_7(),
4119                 w*o.R_component_8()));
4120         }
4121 
4122 
4123         template<typename T>
4124         inline octonion<T>                        cos(octonion<T> const & o)
4125         {
4126             using    ::std::sin;
4127             using    ::std::cos;
4128             using    ::std::cosh;
4129 
4130             using    ::boost::math::sinhc_pi;
4131 
4132             T    z = abs(unreal(o));
4133 
4134             T    w = -sin(o.real())*sinhc_pi(z);
4135 
4136             return(octonion<T>(cos(o.real())*cosh(z),
4137                 w*o.R_component_2(), w*o.R_component_3(),
4138                 w*o.R_component_4(), w*o.R_component_5(),
4139                 w*o.R_component_6(), w*o.R_component_7(),
4140                 w*o.R_component_8()));
4141         }
4142 
4143 
4144         template<typename T>
4145         inline octonion<T>                        sin(octonion<T> const & o)
4146         {
4147             using    ::std::sin;
4148             using    ::std::cos;
4149             using    ::std::cosh;
4150 
4151             using    ::boost::math::sinhc_pi;
4152 
4153             T    z = abs(unreal(o));
4154 
4155             T    w = +cos(o.real())*sinhc_pi(z);
4156 
4157             return(octonion<T>(sin(o.real())*cosh(z),
4158                 w*o.R_component_2(), w*o.R_component_3(),
4159                 w*o.R_component_4(), w*o.R_component_5(),
4160                 w*o.R_component_6(), w*o.R_component_7(),
4161                 w*o.R_component_8()));
4162         }
4163 
4164 
4165         template<typename T>
4166         inline octonion<T>                        tan(octonion<T> const & o)
4167         {
4168             return(sin(o)/cos(o));
4169         }
4170 
4171 
4172         template<typename T>
4173         inline octonion<T>                        cosh(octonion<T> const & o)
4174         {
4175             return((exp(+o)+exp(-o))/static_cast<T>(2));
4176         }
4177 
4178 
4179         template<typename T>
4180         inline octonion<T>                        sinh(octonion<T> const & o)
4181         {
4182             return((exp(+o)-exp(-o))/static_cast<T>(2));
4183         }
4184 
4185 
4186         template<typename T>
4187         inline octonion<T>                        tanh(octonion<T> const & o)
4188         {
4189             return(sinh(o)/cosh(o));
4190         }
4191 
4192 
4193         template<typename T>
4194         octonion<T>                                pow(octonion<T> const & o,
4195                                                     int n)
4196         {
4197             if        (n > 1)
4198             {
4199                 int    m = n>>1;
4200 
4201                 octonion<T>    result = pow(o, m);
4202 
4203                 result *= result;
4204 
4205                 if    (n != (m<<1))
4206                 {
4207                     result *= o; // n odd
4208                 }
4209 
4210                 return(result);
4211             }
4212             else if    (n == 1)
4213             {
4214                 return(o);
4215             }
4216             else if    (n == 0)
4217             {
4218                 return(octonion<T>(static_cast<T>(1)));
4219             }
4220             else    /* n < 0 */
4221             {
4222                 return(pow(octonion<T>(static_cast<T>(1))/o,-n));
4223             }
4224         }
4225 
4226 
4227         // helper templates for converting copy constructors (definition)
4228 
4229         namespace detail
4230         {
4231 
4232             template<   typename T,
4233                         typename U
4234                     >
4235             octonion<T>    octonion_type_converter(octonion<U> const & rhs)
4236             {
4237                 return(octonion<T>( static_cast<T>(rhs.R_component_1()),
4238                                     static_cast<T>(rhs.R_component_2()),
4239                                     static_cast<T>(rhs.R_component_3()),
4240                                     static_cast<T>(rhs.R_component_4()),
4241                                     static_cast<T>(rhs.R_component_5()),
4242                                     static_cast<T>(rhs.R_component_6()),
4243                                     static_cast<T>(rhs.R_component_7()),
4244                                     static_cast<T>(rhs.R_component_8())));
4245             }
4246         }
4247     }
4248 }
4249 
4250 #endif /* BOOST_OCTONION_HPP */