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