epoc32/include/stdapis/boost/math/quaternion.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 quaternion.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
#ifndef BOOST_QUATERNION_HPP
williamr@2
    11
#define BOOST_QUATERNION_HPP
williamr@2
    12
williamr@2
    13
williamr@2
    14
#include <complex>
williamr@2
    15
#include <iosfwd>                                    // for the "<<" and ">>" operators
williamr@2
    16
#include <sstream>                                    // for the "<<" operator
williamr@2
    17
williamr@2
    18
#include <boost/config.hpp> // for BOOST_NO_STD_LOCALE
williamr@2
    19
#include <boost/detail/workaround.hpp>
williamr@2
    20
#ifndef    BOOST_NO_STD_LOCALE
williamr@2
    21
    #include <locale>                                    // for the "<<" operator
williamr@2
    22
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
    23
williamr@2
    24
#include <valarray>
williamr@2
    25
williamr@2
    26
williamr@2
    27
williamr@2
    28
#include <boost/math/special_functions/sinc.hpp>    // for the Sinus cardinal
williamr@2
    29
#include <boost/math/special_functions/sinhc.hpp>    // for the Hyperbolic Sinus cardinal
williamr@2
    30
williamr@2
    31
williamr@2
    32
namespace boost
williamr@2
    33
{
williamr@2
    34
    namespace math
williamr@2
    35
    {
williamr@2
    36
#if     BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
    37
        // gcc 2.95.x uses expression templates for valarray calculations, but
williamr@2
    38
        // the result is not conforming. We need BOOST_GET_VALARRAY to get an
williamr@2
    39
        // actual valarray result when we need to call a member function
williamr@2
    40
    #define    BOOST_GET_VALARRAY(T,x)    ::std::valarray<T>(x)
williamr@2
    41
        // gcc 2.95.x has an "std::ios" class that is similar to 
williamr@2
    42
        // "std::ios_base", so we just use a #define
williamr@2
    43
    #define    BOOST_IOS_BASE    ::std::ios
williamr@2
    44
        // gcc 2.x ignores function scope using declarations,
williamr@2
    45
        // put them in the scope of the enclosing namespace instead:
williamr@2
    46
        using    ::std::valarray;
williamr@2
    47
        using    ::std::sqrt;
williamr@2
    48
        using    ::std::cos;
williamr@2
    49
        using    ::std::sin;
williamr@2
    50
        using    ::std::exp;
williamr@2
    51
        using    ::std::cosh;
williamr@2
    52
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
    53
williamr@2
    54
#define    BOOST_QUATERNION_ACCESSOR_GENERATOR(type)                    \
williamr@2
    55
            type                    real() const                        \
williamr@2
    56
            {                                                           \
williamr@2
    57
                return(a);                                              \
williamr@2
    58
            }                                                           \
williamr@2
    59
                                                                        \
williamr@2
    60
            quaternion<type>        unreal() const                      \
williamr@2
    61
            {                                                           \
williamr@2
    62
                return(quaternion<type>(static_cast<type>(0),b,c,d));   \
williamr@2
    63
            }                                                           \
williamr@2
    64
                                                                        \
williamr@2
    65
            type                    R_component_1() const               \
williamr@2
    66
            {                                                           \
williamr@2
    67
                return(a);                                              \
williamr@2
    68
            }                                                           \
williamr@2
    69
                                                                        \
williamr@2
    70
            type                    R_component_2() const               \
williamr@2
    71
            {                                                           \
williamr@2
    72
                return(b);                                              \
williamr@2
    73
            }                                                           \
williamr@2
    74
                                                                        \
williamr@2
    75
            type                    R_component_3() const               \
williamr@2
    76
            {                                                           \
williamr@2
    77
                return(c);                                              \
williamr@2
    78
            }                                                           \
williamr@2
    79
                                                                        \
williamr@2
    80
            type                    R_component_4() const               \
williamr@2
    81
            {                                                           \
williamr@2
    82
                return(d);                                              \
williamr@2
    83
            }                                                           \
williamr@2
    84
                                                                        \
williamr@2
    85
            ::std::complex<type>    C_component_1() const               \
williamr@2
    86
            {                                                           \
williamr@2
    87
                return(::std::complex<type>(a,b));                      \
williamr@2
    88
            }                                                           \
williamr@2
    89
                                                                        \
williamr@2
    90
            ::std::complex<type>    C_component_2() const               \
williamr@2
    91
            {                                                           \
williamr@2
    92
                return(::std::complex<type>(c,d));                      \
williamr@2
    93
            }
williamr@2
    94
        
williamr@2
    95
        
williamr@2
    96
#define    BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type)                               \
williamr@2
    97
            template<typename X>                                                            \
williamr@2
    98
            quaternion<type> &        operator = (quaternion<X> const  & a_affecter)        \
williamr@2
    99
            {                                                                               \
williamr@2
   100
                a = static_cast<type>(a_affecter.R_component_1());                          \
williamr@2
   101
                b = static_cast<type>(a_affecter.R_component_2());                          \
williamr@2
   102
                c = static_cast<type>(a_affecter.R_component_3());                          \
williamr@2
   103
                d = static_cast<type>(a_affecter.R_component_4());                          \
williamr@2
   104
                                                                                            \
williamr@2
   105
                return(*this);                                                              \
williamr@2
   106
            }                                                                               \
williamr@2
   107
                                                                                            \
williamr@2
   108
            quaternion<type> &        operator = (quaternion<type> const & a_affecter)      \
williamr@2
   109
            {                                                                               \
williamr@2
   110
                a = a_affecter.a;                                                           \
williamr@2
   111
                b = a_affecter.b;                                                           \
williamr@2
   112
                c = a_affecter.c;                                                           \
williamr@2
   113
                d = a_affecter.d;                                                           \
williamr@2
   114
                                                                                            \
williamr@2
   115
                return(*this);                                                              \
williamr@2
   116
            }                                                                               \
williamr@2
   117
                                                                                            \
williamr@2
   118
            quaternion<type> &        operator = (type const & a_affecter)                  \
williamr@2
   119
            {                                                                               \
williamr@2
   120
                a = a_affecter;                                                             \
williamr@2
   121
                                                                                            \
williamr@2
   122
                b = c = d = static_cast<type>(0);                                           \
williamr@2
   123
                                                                                            \
williamr@2
   124
                return(*this);                                                              \
williamr@2
   125
            }                                                                               \
williamr@2
   126
                                                                                            \
williamr@2
   127
            quaternion<type> &        operator = (::std::complex<type> const & a_affecter)  \
williamr@2
   128
            {                                                                               \
williamr@2
   129
                a = a_affecter.real();                                                      \
williamr@2
   130
                b = a_affecter.imag();                                                      \
williamr@2
   131
                                                                                            \
williamr@2
   132
                c = d = static_cast<type>(0);                                               \
williamr@2
   133
                                                                                            \
williamr@2
   134
                return(*this);                                                              \
williamr@2
   135
            }
williamr@2
   136
        
williamr@2
   137
        
williamr@2
   138
#define    BOOST_QUATERNION_MEMBER_DATA_GENERATOR(type)       \
williamr@2
   139
            type    a;                                        \
williamr@2
   140
            type    b;                                        \
williamr@2
   141
            type    c;                                        \
williamr@2
   142
            type    d;
williamr@2
   143
        
williamr@2
   144
        
williamr@2
   145
        template<typename T>
williamr@2
   146
        class quaternion
williamr@2
   147
        {
williamr@2
   148
        public:
williamr@2
   149
            
williamr@2
   150
            typedef T value_type;
williamr@2
   151
            
williamr@2
   152
            
williamr@2
   153
            // constructor for H seen as R^4
williamr@2
   154
            // (also default constructor)
williamr@2
   155
            
williamr@2
   156
            explicit            quaternion( T const & requested_a = T(),
williamr@2
   157
                                            T const & requested_b = T(),
williamr@2
   158
                                            T const & requested_c = T(),
williamr@2
   159
                                            T const & requested_d = T())
williamr@2
   160
            :   a(requested_a),
williamr@2
   161
                b(requested_b),
williamr@2
   162
                c(requested_c),
williamr@2
   163
                d(requested_d)
williamr@2
   164
            {
williamr@2
   165
                // nothing to do!
williamr@2
   166
            }
williamr@2
   167
            
williamr@2
   168
            
williamr@2
   169
            // constructor for H seen as C^2
williamr@2
   170
                
williamr@2
   171
            explicit            quaternion( ::std::complex<T> const & z0,
williamr@2
   172
                                            ::std::complex<T> const & z1 = ::std::complex<T>())
williamr@2
   173
            :   a(z0.real()),
williamr@2
   174
                b(z0.imag()),
williamr@2
   175
                c(z1.real()),
williamr@2
   176
                d(z1.imag())
williamr@2
   177
            {
williamr@2
   178
                // nothing to do!
williamr@2
   179
            }
williamr@2
   180
            
williamr@2
   181
            
williamr@2
   182
            // UNtemplated copy constructor
williamr@2
   183
            // (this is taken care of by the compiler itself)
williamr@2
   184
            
williamr@2
   185
            
williamr@2
   186
            // templated copy constructor
williamr@2
   187
            
williamr@2
   188
            template<typename X>
williamr@2
   189
            explicit            quaternion(quaternion<X> const & a_recopier)
williamr@2
   190
            :   a(static_cast<T>(a_recopier.R_component_1())),
williamr@2
   191
                b(static_cast<T>(a_recopier.R_component_2())),
williamr@2
   192
                c(static_cast<T>(a_recopier.R_component_3())),
williamr@2
   193
                d(static_cast<T>(a_recopier.R_component_4()))
williamr@2
   194
            {
williamr@2
   195
                // nothing to do!
williamr@2
   196
            }
williamr@2
   197
            
williamr@2
   198
            
williamr@2
   199
            // destructor
williamr@2
   200
            // (this is taken care of by the compiler itself)
williamr@2
   201
            
williamr@2
   202
            
williamr@2
   203
            // accessors
williamr@2
   204
            //
williamr@2
   205
            // Note:    Like complex number, quaternions do have a meaningful notion of "real part",
williamr@2
   206
            //            but unlike them there is no meaningful notion of "imaginary part".
williamr@2
   207
            //            Instead there is an "unreal part" which itself is a quaternion, and usually
williamr@2
   208
            //            nothing simpler (as opposed to the complex number case).
williamr@2
   209
            //            However, for practicallity, there are accessors for the other components
williamr@2
   210
            //            (these are necessary for the templated copy constructor, for instance).
williamr@2
   211
            
williamr@2
   212
            BOOST_QUATERNION_ACCESSOR_GENERATOR(T)
williamr@2
   213
            
williamr@2
   214
            // assignment operators
williamr@2
   215
            
williamr@2
   216
            BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T)
williamr@2
   217
            
williamr@2
   218
            // other assignment-related operators
williamr@2
   219
            //
williamr@2
   220
            // NOTE:    Quaternion multiplication is *NOT* commutative;
williamr@2
   221
            //            symbolically, "q *= rhs;" means "q = q * rhs;"
williamr@2
   222
            //            and "q /= rhs;" means "q = q * inverse_of(rhs);"
williamr@2
   223
            
williamr@2
   224
            quaternion<T> &        operator += (T const & rhs)
williamr@2
   225
            {
williamr@2
   226
                T    at = a + rhs;    // exception guard
williamr@2
   227
                
williamr@2
   228
                a = at;
williamr@2
   229
                
williamr@2
   230
                return(*this);
williamr@2
   231
            }
williamr@2
   232
            
williamr@2
   233
            
williamr@2
   234
            quaternion<T> &        operator += (::std::complex<T> const & rhs)
williamr@2
   235
            {
williamr@2
   236
                T    at = a + rhs.real();    // exception guard
williamr@2
   237
                T    bt = b + rhs.imag();    // exception guard
williamr@2
   238
                
williamr@2
   239
                a = at; 
williamr@2
   240
                b = bt;
williamr@2
   241
                
williamr@2
   242
                return(*this);
williamr@2
   243
            }
williamr@2
   244
            
williamr@2
   245
            
williamr@2
   246
            template<typename X>
williamr@2
   247
            quaternion<T> &        operator += (quaternion<X> const & rhs)
williamr@2
   248
            {
williamr@2
   249
                T    at = a + static_cast<T>(rhs.R_component_1());    // exception guard
williamr@2
   250
                T    bt = b + static_cast<T>(rhs.R_component_2());    // exception guard
williamr@2
   251
                T    ct = c + static_cast<T>(rhs.R_component_3());    // exception guard
williamr@2
   252
                T    dt = d + static_cast<T>(rhs.R_component_4());    // exception guard
williamr@2
   253
                
williamr@2
   254
                a = at;
williamr@2
   255
                b = bt;
williamr@2
   256
                c = ct;
williamr@2
   257
                d = dt;
williamr@2
   258
                
williamr@2
   259
                return(*this);
williamr@2
   260
            }
williamr@2
   261
            
williamr@2
   262
            
williamr@2
   263
            
williamr@2
   264
            quaternion<T> &        operator -= (T const & rhs)
williamr@2
   265
            {
williamr@2
   266
                T    at = a - rhs;    // exception guard
williamr@2
   267
                
williamr@2
   268
                a = at;
williamr@2
   269
                
williamr@2
   270
                return(*this);
williamr@2
   271
            }
williamr@2
   272
            
williamr@2
   273
            
williamr@2
   274
            quaternion<T> &        operator -= (::std::complex<T> const & rhs)
williamr@2
   275
            {
williamr@2
   276
                T    at = a - rhs.real();    // exception guard
williamr@2
   277
                T    bt = b - rhs.imag();    // exception guard
williamr@2
   278
                
williamr@2
   279
                a = at;
williamr@2
   280
                b = bt;
williamr@2
   281
                
williamr@2
   282
                return(*this);
williamr@2
   283
            }
williamr@2
   284
            
williamr@2
   285
            
williamr@2
   286
            template<typename X>
williamr@2
   287
            quaternion<T> &        operator -= (quaternion<X> const & rhs)
williamr@2
   288
            {
williamr@2
   289
                T    at = a - static_cast<T>(rhs.R_component_1());    // exception guard
williamr@2
   290
                T    bt = b - static_cast<T>(rhs.R_component_2());    // exception guard
williamr@2
   291
                T    ct = c - static_cast<T>(rhs.R_component_3());    // exception guard
williamr@2
   292
                T    dt = d - static_cast<T>(rhs.R_component_4());    // exception guard
williamr@2
   293
                
williamr@2
   294
                a = at;
williamr@2
   295
                b = bt;
williamr@2
   296
                c = ct;
williamr@2
   297
                d = dt;
williamr@2
   298
                
williamr@2
   299
                return(*this);
williamr@2
   300
            }
williamr@2
   301
            
williamr@2
   302
            
williamr@2
   303
            quaternion<T> &        operator *= (T const & rhs)
williamr@2
   304
            {
williamr@2
   305
                T    at = a * rhs;    // exception guard
williamr@2
   306
                T    bt = b * rhs;    // exception guard
williamr@2
   307
                T    ct = c * rhs;    // exception guard
williamr@2
   308
                T    dt = d * rhs;    // exception guard
williamr@2
   309
                
williamr@2
   310
                a = at;
williamr@2
   311
                b = bt;
williamr@2
   312
                c = ct;
williamr@2
   313
                d = dt;
williamr@2
   314
                
williamr@2
   315
                return(*this);
williamr@2
   316
            }
williamr@2
   317
            
williamr@2
   318
            
williamr@2
   319
            quaternion<T> &        operator *= (::std::complex<T> const & rhs)
williamr@2
   320
            {
williamr@2
   321
                T    ar = rhs.real();
williamr@2
   322
                T    br = rhs.imag();
williamr@2
   323
                
williamr@2
   324
                T    at = +a*ar-b*br;
williamr@2
   325
                T    bt = +a*br+b*ar;
williamr@2
   326
                T    ct = +c*ar+d*br;
williamr@2
   327
                T    dt = -c*br+d*ar;
williamr@2
   328
                
williamr@2
   329
                a = at;
williamr@2
   330
                b = bt;
williamr@2
   331
                c = ct;
williamr@2
   332
                d = dt;
williamr@2
   333
                
williamr@2
   334
                return(*this);
williamr@2
   335
            }
williamr@2
   336
            
williamr@2
   337
            
williamr@2
   338
            template<typename X>
williamr@2
   339
            quaternion<T> &        operator *= (quaternion<X> const & rhs)
williamr@2
   340
            {
williamr@2
   341
                T    ar = static_cast<T>(rhs.R_component_1());
williamr@2
   342
                T    br = static_cast<T>(rhs.R_component_2());
williamr@2
   343
                T    cr = static_cast<T>(rhs.R_component_3());
williamr@2
   344
                T    dr = static_cast<T>(rhs.R_component_4());
williamr@2
   345
                
williamr@2
   346
                T    at = +a*ar-b*br-c*cr-d*dr;
williamr@2
   347
                T    bt = +a*br+b*ar+c*dr-d*cr;    //(a*br+ar*b)+(c*dr-cr*d);
williamr@2
   348
                T    ct = +a*cr-b*dr+c*ar+d*br;    //(a*cr+ar*c)+(d*br-dr*b);
williamr@2
   349
                T    dt = +a*dr+b*cr-c*br+d*ar;    //(a*dr+ar*d)+(b*cr-br*c);
williamr@2
   350
                
williamr@2
   351
                a = at;
williamr@2
   352
                b = bt;
williamr@2
   353
                c = ct;
williamr@2
   354
                d = dt;
williamr@2
   355
                
williamr@2
   356
                return(*this);
williamr@2
   357
            }
williamr@2
   358
            
williamr@2
   359
            
williamr@2
   360
            
williamr@2
   361
            quaternion<T> &        operator /= (T const & rhs)
williamr@2
   362
            {
williamr@2
   363
                T    at = a / rhs;    // exception guard
williamr@2
   364
                T    bt = b / rhs;    // exception guard
williamr@2
   365
                T    ct = c / rhs;    // exception guard
williamr@2
   366
                T    dt = d / rhs;    // exception guard
williamr@2
   367
                
williamr@2
   368
                a = at;
williamr@2
   369
                b = bt;
williamr@2
   370
                c = ct;
williamr@2
   371
                d = dt;
williamr@2
   372
                
williamr@2
   373
                return(*this);
williamr@2
   374
            }
williamr@2
   375
            
williamr@2
   376
            
williamr@2
   377
            quaternion<T> &        operator /= (::std::complex<T> const & rhs)
williamr@2
   378
            {
williamr@2
   379
                T    ar = rhs.real();
williamr@2
   380
                T    br = rhs.imag();
williamr@2
   381
                
williamr@2
   382
                T    denominator = ar*ar+br*br;
williamr@2
   383
                
williamr@2
   384
                T    at = (+a*ar+b*br)/denominator;    //(a*ar+b*br)/denominator;
williamr@2
   385
                T    bt = (-a*br+b*ar)/denominator;    //(ar*b-a*br)/denominator;
williamr@2
   386
                T    ct = (+c*ar-d*br)/denominator;    //(ar*c-d*br)/denominator;
williamr@2
   387
                T    dt = (+c*br+d*ar)/denominator;    //(ar*d+br*c)/denominator;
williamr@2
   388
                
williamr@2
   389
                a = at;
williamr@2
   390
                b = bt;
williamr@2
   391
                c = ct;
williamr@2
   392
                d = dt;
williamr@2
   393
                
williamr@2
   394
                return(*this);
williamr@2
   395
            }
williamr@2
   396
            
williamr@2
   397
            
williamr@2
   398
            template<typename X>
williamr@2
   399
            quaternion<T> &        operator /= (quaternion<X> const & rhs)
williamr@2
   400
            {
williamr@2
   401
                T    ar = static_cast<T>(rhs.R_component_1());
williamr@2
   402
                T    br = static_cast<T>(rhs.R_component_2());
williamr@2
   403
                T    cr = static_cast<T>(rhs.R_component_3());
williamr@2
   404
                T    dr = static_cast<T>(rhs.R_component_4());
williamr@2
   405
                
williamr@2
   406
                T    denominator = ar*ar+br*br+cr*cr+dr*dr;
williamr@2
   407
                
williamr@2
   408
                T    at = (+a*ar+b*br+c*cr+d*dr)/denominator;    //(a*ar+b*br+c*cr+d*dr)/denominator;
williamr@2
   409
                T    bt = (-a*br+b*ar-c*dr+d*cr)/denominator;    //((ar*b-a*br)+(cr*d-c*dr))/denominator;
williamr@2
   410
                T    ct = (-a*cr+b*dr+c*ar-d*br)/denominator;    //((ar*c-a*cr)+(dr*b-d*br))/denominator;
williamr@2
   411
                T    dt = (-a*dr-b*cr+c*br+d*ar)/denominator;    //((ar*d-a*dr)+(br*c-b*cr))/denominator;
williamr@2
   412
                
williamr@2
   413
                a = at;
williamr@2
   414
                b = bt;
williamr@2
   415
                c = ct;
williamr@2
   416
                d = dt;
williamr@2
   417
                
williamr@2
   418
                return(*this);
williamr@2
   419
            }
williamr@2
   420
            
williamr@2
   421
            
williamr@2
   422
        protected:
williamr@2
   423
            
williamr@2
   424
            BOOST_QUATERNION_MEMBER_DATA_GENERATOR(T)
williamr@2
   425
            
williamr@2
   426
            
williamr@2
   427
        private:
williamr@2
   428
            
williamr@2
   429
        };
williamr@2
   430
        
williamr@2
   431
        
williamr@2
   432
        // declaration of quaternion specialization
williamr@2
   433
        
williamr@2
   434
        template<>    class quaternion<float>;
williamr@2
   435
        template<>    class quaternion<double>;
williamr@2
   436
        template<>    class quaternion<long double>;
williamr@2
   437
        
williamr@2
   438
        
williamr@2
   439
        // helper templates for converting copy constructors (declaration)
williamr@2
   440
        
williamr@2
   441
        namespace detail
williamr@2
   442
        {
williamr@2
   443
            
williamr@2
   444
            template<   typename T,
williamr@2
   445
                        typename U
williamr@2
   446
                    >
williamr@2
   447
            quaternion<T>    quaternion_type_converter(quaternion<U> const & rhs);
williamr@2
   448
        }
williamr@2
   449
        
williamr@2
   450
        
williamr@2
   451
        // implementation of quaternion specialization
williamr@2
   452
        
williamr@2
   453
        
williamr@2
   454
#define    BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(type)                                                 \
williamr@2
   455
            explicit            quaternion( type const & requested_a = static_cast<type>(0),            \
williamr@2
   456
                                            type const & requested_b = static_cast<type>(0),            \
williamr@2
   457
                                            type const & requested_c = static_cast<type>(0),            \
williamr@2
   458
                                            type const & requested_d = static_cast<type>(0))            \
williamr@2
   459
            :   a(requested_a),                                                                         \
williamr@2
   460
                b(requested_b),                                                                         \
williamr@2
   461
                c(requested_c),                                                                         \
williamr@2
   462
                d(requested_d)                                                                          \
williamr@2
   463
            {                                                                                           \
williamr@2
   464
            }                                                                                           \
williamr@2
   465
                                                                                                        \
williamr@2
   466
            explicit            quaternion( ::std::complex<type> const & z0,                            \
williamr@2
   467
                                            ::std::complex<type> const & z1 = ::std::complex<type>())   \
williamr@2
   468
            :   a(z0.real()),                                                                           \
williamr@2
   469
                b(z0.imag()),                                                                           \
williamr@2
   470
                c(z1.real()),                                                                           \
williamr@2
   471
                d(z1.imag())                                                                            \
williamr@2
   472
            {                                                                                           \
williamr@2
   473
            }
williamr@2
   474
        
williamr@2
   475
        
williamr@2
   476
#define    BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type)             \
williamr@2
   477
            quaternion<type> &        operator += (type const & rhs) \
williamr@2
   478
            {                                                        \
williamr@2
   479
                a += rhs;                                            \
williamr@2
   480
                                                                     \
williamr@2
   481
                return(*this);                                       \
williamr@2
   482
            }
williamr@2
   483
    
williamr@2
   484
#define    BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type)                             \
williamr@2
   485
            quaternion<type> &        operator += (::std::complex<type> const & rhs) \
williamr@2
   486
            {                                                                        \
williamr@2
   487
                a += rhs.real();                                                     \
williamr@2
   488
                b += rhs.imag();                                                     \
williamr@2
   489
                                                                                     \
williamr@2
   490
                return(*this);                                                       \
williamr@2
   491
            }
williamr@2
   492
    
williamr@2
   493
#define    BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type)                      \
williamr@2
   494
            template<typename X>                                              \
williamr@2
   495
            quaternion<type> &        operator += (quaternion<X> const & rhs) \
williamr@2
   496
            {                                                                 \
williamr@2
   497
                a += static_cast<type>(rhs.R_component_1());                  \
williamr@2
   498
                b += static_cast<type>(rhs.R_component_2());                  \
williamr@2
   499
                c += static_cast<type>(rhs.R_component_3());                  \
williamr@2
   500
                d += static_cast<type>(rhs.R_component_4());                  \
williamr@2
   501
                                                                              \
williamr@2
   502
                return(*this);                                                \
williamr@2
   503
            }
williamr@2
   504
    
williamr@2
   505
#define    BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type)             \
williamr@2
   506
            quaternion<type> &        operator -= (type const & rhs) \
williamr@2
   507
            {                                                        \
williamr@2
   508
                a -= rhs;                                            \
williamr@2
   509
                                                                     \
williamr@2
   510
                return(*this);                                       \
williamr@2
   511
            }
williamr@2
   512
    
williamr@2
   513
#define    BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type)                             \
williamr@2
   514
            quaternion<type> &        operator -= (::std::complex<type> const & rhs) \
williamr@2
   515
            {                                                                        \
williamr@2
   516
                a -= rhs.real();                                                     \
williamr@2
   517
                b -= rhs.imag();                                                     \
williamr@2
   518
                                                                                     \
williamr@2
   519
                return(*this);                                                       \
williamr@2
   520
            }
williamr@2
   521
    
williamr@2
   522
#define    BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type)                      \
williamr@2
   523
            template<typename X>                                              \
williamr@2
   524
            quaternion<type> &        operator -= (quaternion<X> const & rhs) \
williamr@2
   525
            {                                                                 \
williamr@2
   526
                a -= static_cast<type>(rhs.R_component_1());                  \
williamr@2
   527
                b -= static_cast<type>(rhs.R_component_2());                  \
williamr@2
   528
                c -= static_cast<type>(rhs.R_component_3());                  \
williamr@2
   529
                d -= static_cast<type>(rhs.R_component_4());                  \
williamr@2
   530
                                                                              \
williamr@2
   531
                return(*this);                                                \
williamr@2
   532
            }
williamr@2
   533
    
williamr@2
   534
#define    BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type)             \
williamr@2
   535
            quaternion<type> &        operator *= (type const & rhs) \
williamr@2
   536
            {                                                        \
williamr@2
   537
                a *= rhs;                                            \
williamr@2
   538
                b *= rhs;                                            \
williamr@2
   539
                c *= rhs;                                            \
williamr@2
   540
                d *= rhs;                                            \
williamr@2
   541
                                                                     \
williamr@2
   542
                return(*this);                                       \
williamr@2
   543
            }
williamr@2
   544
    
williamr@2
   545
#define    BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type)                             \
williamr@2
   546
            quaternion<type> &        operator *= (::std::complex<type> const & rhs) \
williamr@2
   547
            {                                                                        \
williamr@2
   548
                type    ar = rhs.real();                                             \
williamr@2
   549
                type    br = rhs.imag();                                             \
williamr@2
   550
                                                                                     \
williamr@2
   551
                type    at = +a*ar-b*br;                                             \
williamr@2
   552
                type    bt = +a*br+b*ar;                                             \
williamr@2
   553
                type    ct = +c*ar+d*br;                                             \
williamr@2
   554
                type    dt = -c*br+d*ar;                                             \
williamr@2
   555
                                                                                     \
williamr@2
   556
                a = at;                                                              \
williamr@2
   557
                b = bt;                                                              \
williamr@2
   558
                c = ct;                                                              \
williamr@2
   559
                d = dt;                                                              \
williamr@2
   560
                                                                                     \
williamr@2
   561
                return(*this);                                                       \
williamr@2
   562
            }
williamr@2
   563
    
williamr@2
   564
#define    BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type)                      \
williamr@2
   565
            template<typename X>                                              \
williamr@2
   566
            quaternion<type> &        operator *= (quaternion<X> const & rhs) \
williamr@2
   567
            {                                                                 \
williamr@2
   568
                type    ar = static_cast<type>(rhs.R_component_1());          \
williamr@2
   569
                type    br = static_cast<type>(rhs.R_component_2());          \
williamr@2
   570
                type    cr = static_cast<type>(rhs.R_component_3());          \
williamr@2
   571
                type    dr = static_cast<type>(rhs.R_component_4());          \
williamr@2
   572
                                                                              \
williamr@2
   573
                type    at = +a*ar-b*br-c*cr-d*dr;                            \
williamr@2
   574
                type    bt = +a*br+b*ar+c*dr-d*cr;                            \
williamr@2
   575
                type    ct = +a*cr-b*dr+c*ar+d*br;                            \
williamr@2
   576
                type    dt = +a*dr+b*cr-c*br+d*ar;                            \
williamr@2
   577
                                                                              \
williamr@2
   578
                a = at;                                                       \
williamr@2
   579
                b = bt;                                                       \
williamr@2
   580
                c = ct;                                                       \
williamr@2
   581
                d = dt;                                                       \
williamr@2
   582
                                                                              \
williamr@2
   583
                return(*this);                                                \
williamr@2
   584
            }
williamr@2
   585
    
williamr@2
   586
// There is quite a lot of repetition in the code below. This is intentional.
williamr@2
   587
// The last conditional block is the normal form, and the others merely
williamr@2
   588
// consist of workarounds for various compiler deficiencies. Hopefuly, when
williamr@2
   589
// more compilers are conformant and we can retire support for those that are
williamr@2
   590
// not, we will be able to remove the clutter. This is makes the situation
williamr@2
   591
// (painfully) explicit.
williamr@2
   592
    
williamr@2
   593
#define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type)             \
williamr@2
   594
            quaternion<type> &        operator /= (type const & rhs) \
williamr@2
   595
            {                                                        \
williamr@2
   596
                a /= rhs;                                            \
williamr@2
   597
                b /= rhs;                                            \
williamr@2
   598
                c /= rhs;                                            \
williamr@2
   599
                d /= rhs;                                            \
williamr@2
   600
                                                                     \
williamr@2
   601
                return(*this);                                       \
williamr@2
   602
            }
williamr@2
   603
williamr@2
   604
#if defined(__GNUC__) && (__GNUC__ < 3)
williamr@2
   605
    #define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type)                                            \
williamr@2
   606
            quaternion<type> &        operator /= (::std::complex<type> const & rhs)                    \
williamr@2
   607
            {                                                                                           \
williamr@2
   608
                using    ::std::valarray;                                                               \
williamr@2
   609
                                                                                                        \
williamr@2
   610
                valarray<type>    tr(2);                                                                \
williamr@2
   611
                                                                                                        \
williamr@2
   612
                tr[0] = rhs.real();                                                                     \
williamr@2
   613
                tr[1] = rhs.imag();                                                                     \
williamr@2
   614
                                                                                                        \
williamr@2
   615
                type            mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();  \
williamr@2
   616
                                                                                                        \
williamr@2
   617
                tr *= mixam;                                                                            \
williamr@2
   618
                                                                                                        \
williamr@2
   619
                valarray<type>    tt(4);                                                                \
williamr@2
   620
                                                                                                        \
williamr@2
   621
                tt[0] = +a*tr[0]+b*tr[1];                                                               \
williamr@2
   622
                tt[1] = -a*tr[1]+b*tr[0];                                                               \
williamr@2
   623
                tt[2] = +c*tr[0]-d*tr[1];                                                               \
williamr@2
   624
                tt[3] = +c*tr[1]+d*tr[0];                                                               \
williamr@2
   625
                                                                                                        \
williamr@2
   626
                tr *= tr;                                                                               \
williamr@2
   627
                                                                                                        \
williamr@2
   628
                tt *= (mixam/tr.sum());                                                                 \
williamr@2
   629
                                                                                                        \
williamr@2
   630
                a = tt[0];                                                                              \
williamr@2
   631
                b = tt[1];                                                                              \
williamr@2
   632
                c = tt[2];                                                                              \
williamr@2
   633
                d = tt[3];                                                                              \
williamr@2
   634
                                                                                                        \
williamr@2
   635
                return(*this);                                                                          \
williamr@2
   636
            }
williamr@2
   637
#elif    defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
williamr@2
   638
    #define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type)                         \
williamr@2
   639
            quaternion<type> &        operator /= (::std::complex<type> const & rhs) \
williamr@2
   640
            {                                                                        \
williamr@2
   641
                using    ::std::valarray;                                            \
williamr@2
   642
                using    ::std::abs;                                                 \
williamr@2
   643
                                                                                     \
williamr@2
   644
                valarray<type>    tr(2);                                             \
williamr@2
   645
                                                                                     \
williamr@2
   646
                tr[0] = rhs.real();                                                  \
williamr@2
   647
                tr[1] = rhs.imag();                                                  \
williamr@2
   648
                                                                                     \
williamr@2
   649
                type            mixam = static_cast<type>(1)/(abs(tr).max)();        \
williamr@2
   650
                                                                                     \
williamr@2
   651
                tr *= mixam;                                                         \
williamr@2
   652
                                                                                     \
williamr@2
   653
                valarray<type>    tt(4);                                             \
williamr@2
   654
                                                                                     \
williamr@2
   655
                tt[0] = +a*tr[0]+b*tr[1];                                            \
williamr@2
   656
                tt[1] = -a*tr[1]+b*tr[0];                                            \
williamr@2
   657
                tt[2] = +c*tr[0]-d*tr[1];                                            \
williamr@2
   658
                tt[3] = +c*tr[1]+d*tr[0];                                            \
williamr@2
   659
                                                                                     \
williamr@2
   660
                tr *= tr;                                                            \
williamr@2
   661
                                                                                     \
williamr@2
   662
                tt *= (mixam/tr.sum());                                              \
williamr@2
   663
                                                                                     \
williamr@2
   664
                a = tt[0];                                                           \
williamr@2
   665
                b = tt[1];                                                           \
williamr@2
   666
                c = tt[2];                                                           \
williamr@2
   667
                d = tt[3];                                                           \
williamr@2
   668
                                                                                     \
williamr@2
   669
                return(*this);                                                       \
williamr@2
   670
            }
williamr@2
   671
#else
williamr@2
   672
    #define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type)                         \
williamr@2
   673
            quaternion<type> &        operator /= (::std::complex<type> const & rhs) \
williamr@2
   674
            {                                                                        \
williamr@2
   675
                using    ::std::valarray;                                            \
williamr@2
   676
                                                                                     \
williamr@2
   677
                valarray<type>    tr(2);                                             \
williamr@2
   678
                                                                                     \
williamr@2
   679
                tr[0] = rhs.real();                                                  \
williamr@2
   680
                tr[1] = rhs.imag();                                                  \
williamr@2
   681
                                                                                     \
williamr@2
   682
                type            mixam = static_cast<type>(1)/(abs(tr).max)();        \
williamr@2
   683
                                                                                     \
williamr@2
   684
                tr *= mixam;                                                         \
williamr@2
   685
                                                                                     \
williamr@2
   686
                valarray<type>    tt(4);                                             \
williamr@2
   687
                                                                                     \
williamr@2
   688
                tt[0] = +a*tr[0]+b*tr[1];                                            \
williamr@2
   689
                tt[1] = -a*tr[1]+b*tr[0];                                            \
williamr@2
   690
                tt[2] = +c*tr[0]-d*tr[1];                                            \
williamr@2
   691
                tt[3] = +c*tr[1]+d*tr[0];                                            \
williamr@2
   692
                                                                                     \
williamr@2
   693
                tr *= tr;                                                            \
williamr@2
   694
                                                                                     \
williamr@2
   695
                tt *= (mixam/tr.sum());                                              \
williamr@2
   696
                                                                                     \
williamr@2
   697
                a = tt[0];                                                           \
williamr@2
   698
                b = tt[1];                                                           \
williamr@2
   699
                c = tt[2];                                                           \
williamr@2
   700
                d = tt[3];                                                           \
williamr@2
   701
                                                                                     \
williamr@2
   702
                return(*this);                                                       \
williamr@2
   703
            }
williamr@2
   704
#endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
williamr@2
   705
    
williamr@2
   706
#if defined(__GNUC__) && (__GNUC__ < 3)
williamr@2
   707
    #define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)                                            \
williamr@2
   708
            template<typename X>                                                                        \
williamr@2
   709
            quaternion<type> &        operator /= (quaternion<X> const & rhs)                           \
williamr@2
   710
            {                                                                                           \
williamr@2
   711
                using    ::std::valarray;                                                               \
williamr@2
   712
                                                                                                        \
williamr@2
   713
                valarray<type>    tr(4);                                                                \
williamr@2
   714
                                                                                                        \
williamr@2
   715
                tr[0] = static_cast<type>(rhs.R_component_1());                                         \
williamr@2
   716
                tr[1] = static_cast<type>(rhs.R_component_2());                                         \
williamr@2
   717
                tr[2] = static_cast<type>(rhs.R_component_3());                                         \
williamr@2
   718
                tr[3] = static_cast<type>(rhs.R_component_4());                                         \
williamr@2
   719
                                                                                                        \
williamr@2
   720
                type            mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();  \
williamr@2
   721
                                                                                                        \
williamr@2
   722
                tr *= mixam;                                                                            \
williamr@2
   723
                                                                                                        \
williamr@2
   724
                valarray<type>    tt(4);                                                                \
williamr@2
   725
                                                                                                        \
williamr@2
   726
                tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3];                                               \
williamr@2
   727
                tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2];                                               \
williamr@2
   728
                tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1];                                               \
williamr@2
   729
                tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0];                                               \
williamr@2
   730
                                                                                                        \
williamr@2
   731
                tr *= tr;                                                                               \
williamr@2
   732
                                                                                                        \
williamr@2
   733
                tt *= (mixam/tr.sum());                                                                 \
williamr@2
   734
                                                                                                        \
williamr@2
   735
                a = tt[0];                                                                              \
williamr@2
   736
                b = tt[1];                                                                              \
williamr@2
   737
                c = tt[2];                                                                              \
williamr@2
   738
                d = tt[3];                                                                              \
williamr@2
   739
                                                                                                        \
williamr@2
   740
                return(*this);                                                                          \
williamr@2
   741
            }
williamr@2
   742
#elif    defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
williamr@2
   743
    #define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)                  \
williamr@2
   744
            template<typename X>                                              \
williamr@2
   745
            quaternion<type> &        operator /= (quaternion<X> const & rhs) \
williamr@2
   746
            {                                                                 \
williamr@2
   747
                using    ::std::valarray;                                     \
williamr@2
   748
                using    ::std::abs;                                          \
williamr@2
   749
                                                                              \
williamr@2
   750
                valarray<type>    tr(4);                                      \
williamr@2
   751
                                                                              \
williamr@2
   752
                tr[0] = static_cast<type>(rhs.R_component_1());               \
williamr@2
   753
                tr[1] = static_cast<type>(rhs.R_component_2());               \
williamr@2
   754
                tr[2] = static_cast<type>(rhs.R_component_3());               \
williamr@2
   755
                tr[3] = static_cast<type>(rhs.R_component_4());               \
williamr@2
   756
                                                                              \
williamr@2
   757
                type            mixam = static_cast<type>(1)/(abs(tr).max)(); \
williamr@2
   758
                                                                              \
williamr@2
   759
                tr *= mixam;                                                  \
williamr@2
   760
                                                                              \
williamr@2
   761
                valarray<type>    tt(4);                                      \
williamr@2
   762
                                                                              \
williamr@2
   763
                tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3];                     \
williamr@2
   764
                tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2];                     \
williamr@2
   765
                tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1];                     \
williamr@2
   766
                tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0];                     \
williamr@2
   767
                                                                              \
williamr@2
   768
                tr *= tr;                                                     \
williamr@2
   769
                                                                              \
williamr@2
   770
                tt *= (mixam/tr.sum());                                       \
williamr@2
   771
                                                                              \
williamr@2
   772
                a = tt[0];                                                    \
williamr@2
   773
                b = tt[1];                                                    \
williamr@2
   774
                c = tt[2];                                                    \
williamr@2
   775
                d = tt[3];                                                    \
williamr@2
   776
                                                                              \
williamr@2
   777
                return(*this);                                                \
williamr@2
   778
            }
williamr@2
   779
#else
williamr@2
   780
    #define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)                  \
williamr@2
   781
            template<typename X>                                              \
williamr@2
   782
            quaternion<type> &        operator /= (quaternion<X> const & rhs) \
williamr@2
   783
            {                                                                 \
williamr@2
   784
                using    ::std::valarray;                                     \
williamr@2
   785
                                                                              \
williamr@2
   786
                valarray<type>    tr(4);                                      \
williamr@2
   787
                                                                              \
williamr@2
   788
                tr[0] = static_cast<type>(rhs.R_component_1());               \
williamr@2
   789
                tr[1] = static_cast<type>(rhs.R_component_2());               \
williamr@2
   790
                tr[2] = static_cast<type>(rhs.R_component_3());               \
williamr@2
   791
                tr[3] = static_cast<type>(rhs.R_component_4());               \
williamr@2
   792
                                                                              \
williamr@2
   793
                type            mixam = static_cast<type>(1)/(abs(tr).max)(); \
williamr@2
   794
                                                                              \
williamr@2
   795
                tr *= mixam;                                                  \
williamr@2
   796
                                                                              \
williamr@2
   797
                valarray<type>    tt(4);                                      \
williamr@2
   798
                                                                              \
williamr@2
   799
                tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3];                     \
williamr@2
   800
                tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2];                     \
williamr@2
   801
                tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1];                     \
williamr@2
   802
                tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0];                     \
williamr@2
   803
                                                                              \
williamr@2
   804
                tr *= tr;                                                     \
williamr@2
   805
                                                                              \
williamr@2
   806
                tt *= (mixam/tr.sum());                                       \
williamr@2
   807
                                                                              \
williamr@2
   808
                a = tt[0];                                                    \
williamr@2
   809
                b = tt[1];                                                    \
williamr@2
   810
                c = tt[2];                                                    \
williamr@2
   811
                d = tt[3];                                                    \
williamr@2
   812
                                                                              \
williamr@2
   813
                return(*this);                                                \
williamr@2
   814
            }
williamr@2
   815
#endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
williamr@2
   816
    
williamr@2
   817
#define    BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type)   \
williamr@2
   818
        BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type)    \
williamr@2
   819
        BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type)    \
williamr@2
   820
        BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type)
williamr@2
   821
        
williamr@2
   822
#define    BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type)   \
williamr@2
   823
        BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type)    \
williamr@2
   824
        BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type)    \
williamr@2
   825
        BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type)
williamr@2
   826
        
williamr@2
   827
#define    BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type)   \
williamr@2
   828
        BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type)    \
williamr@2
   829
        BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type)    \
williamr@2
   830
        BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type)
williamr@2
   831
        
williamr@2
   832
#define    BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type)   \
williamr@2
   833
        BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type)    \
williamr@2
   834
        BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type)    \
williamr@2
   835
        BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)
williamr@2
   836
        
williamr@2
   837
#define    BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(type)   \
williamr@2
   838
        BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type)            \
williamr@2
   839
        BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type)            \
williamr@2
   840
        BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type)            \
williamr@2
   841
        BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type)
williamr@2
   842
        
williamr@2
   843
        
williamr@2
   844
        template<>
williamr@2
   845
        class quaternion<float>
williamr@2
   846
        {
williamr@2
   847
        public:
williamr@2
   848
            
williamr@2
   849
            typedef float value_type;
williamr@2
   850
            
williamr@2
   851
            BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(float)
williamr@2
   852
            
williamr@2
   853
            // UNtemplated copy constructor
williamr@2
   854
            // (this is taken care of by the compiler itself)
williamr@2
   855
            
williamr@2
   856
            // explicit copy constructors (precision-loosing converters)
williamr@2
   857
            
williamr@2
   858
            explicit            quaternion(quaternion<double> const & a_recopier)
williamr@2
   859
            {
williamr@2
   860
                *this = detail::quaternion_type_converter<float, double>(a_recopier);
williamr@2
   861
            }
williamr@2
   862
            
williamr@2
   863
            explicit            quaternion(quaternion<long double> const & a_recopier)
williamr@2
   864
            {
williamr@2
   865
                *this = detail::quaternion_type_converter<float, long double>(a_recopier);
williamr@2
   866
            }
williamr@2
   867
            
williamr@2
   868
            // destructor
williamr@2
   869
            // (this is taken care of by the compiler itself)
williamr@2
   870
            
williamr@2
   871
            // accessors
williamr@2
   872
            //
williamr@2
   873
            // Note:    Like complex number, quaternions do have a meaningful notion of "real part",
williamr@2
   874
            //            but unlike them there is no meaningful notion of "imaginary part".
williamr@2
   875
            //            Instead there is an "unreal part" which itself is a quaternion, and usually
williamr@2
   876
            //            nothing simpler (as opposed to the complex number case).
williamr@2
   877
            //            However, for practicallity, there are accessors for the other components
williamr@2
   878
            //            (these are necessary for the templated copy constructor, for instance).
williamr@2
   879
            
williamr@2
   880
            BOOST_QUATERNION_ACCESSOR_GENERATOR(float)
williamr@2
   881
            
williamr@2
   882
            // assignment operators
williamr@2
   883
            
williamr@2
   884
            BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(float)
williamr@2
   885
            
williamr@2
   886
            // other assignment-related operators
williamr@2
   887
            //
williamr@2
   888
            // NOTE:    Quaternion multiplication is *NOT* commutative;
williamr@2
   889
            //            symbolically, "q *= rhs;" means "q = q * rhs;"
williamr@2
   890
            //            and "q /= rhs;" means "q = q * inverse_of(rhs);"
williamr@2
   891
            
williamr@2
   892
            BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(float)
williamr@2
   893
            
williamr@2
   894
            
williamr@2
   895
        protected:
williamr@2
   896
            
williamr@2
   897
            BOOST_QUATERNION_MEMBER_DATA_GENERATOR(float)
williamr@2
   898
            
williamr@2
   899
            
williamr@2
   900
        private:
williamr@2
   901
            
williamr@2
   902
        };
williamr@2
   903
        
williamr@2
   904
        
williamr@2
   905
        template<>
williamr@2
   906
        class quaternion<double>
williamr@2
   907
        {
williamr@2
   908
        public:
williamr@2
   909
            
williamr@2
   910
            typedef double value_type;
williamr@2
   911
            
williamr@2
   912
            BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(double)
williamr@2
   913
            
williamr@2
   914
            // UNtemplated copy constructor
williamr@2
   915
            // (this is taken care of by the compiler itself)
williamr@2
   916
            
williamr@2
   917
            // converting copy constructor
williamr@2
   918
            
williamr@2
   919
            explicit                quaternion(quaternion<float> const & a_recopier)
williamr@2
   920
            {
williamr@2
   921
                *this = detail::quaternion_type_converter<double, float>(a_recopier);
williamr@2
   922
            }
williamr@2
   923
            
williamr@2
   924
            // explicit copy constructors (precision-loosing converters)
williamr@2
   925
            
williamr@2
   926
            explicit                quaternion(quaternion<long double> const & a_recopier)
williamr@2
   927
            {
williamr@2
   928
                *this = detail::quaternion_type_converter<double, long double>(a_recopier);
williamr@2
   929
            }
williamr@2
   930
            
williamr@2
   931
            // destructor
williamr@2
   932
            // (this is taken care of by the compiler itself)
williamr@2
   933
            
williamr@2
   934
            // accessors
williamr@2
   935
            //
williamr@2
   936
            // Note:    Like complex number, quaternions do have a meaningful notion of "real part",
williamr@2
   937
            //            but unlike them there is no meaningful notion of "imaginary part".
williamr@2
   938
            //            Instead there is an "unreal part" which itself is a quaternion, and usually
williamr@2
   939
            //            nothing simpler (as opposed to the complex number case).
williamr@2
   940
            //            However, for practicallity, there are accessors for the other components
williamr@2
   941
            //            (these are necessary for the templated copy constructor, for instance).
williamr@2
   942
            
williamr@2
   943
            BOOST_QUATERNION_ACCESSOR_GENERATOR(double)
williamr@2
   944
            
williamr@2
   945
            // assignment operators
williamr@2
   946
            
williamr@2
   947
            BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(double)
williamr@2
   948
            
williamr@2
   949
            // other assignment-related operators
williamr@2
   950
            //
williamr@2
   951
            // NOTE:    Quaternion multiplication is *NOT* commutative;
williamr@2
   952
            //            symbolically, "q *= rhs;" means "q = q * rhs;"
williamr@2
   953
            //            and "q /= rhs;" means "q = q * inverse_of(rhs);"
williamr@2
   954
            
williamr@2
   955
            BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(double)
williamr@2
   956
            
williamr@2
   957
            
williamr@2
   958
        protected:
williamr@2
   959
            
williamr@2
   960
            BOOST_QUATERNION_MEMBER_DATA_GENERATOR(double)
williamr@2
   961
            
williamr@2
   962
            
williamr@2
   963
        private:
williamr@2
   964
            
williamr@2
   965
        };
williamr@2
   966
        
williamr@2
   967
        
williamr@2
   968
        template<>
williamr@2
   969
        class quaternion<long double>
williamr@2
   970
        {
williamr@2
   971
        public:
williamr@2
   972
            
williamr@2
   973
            typedef long double value_type;
williamr@2
   974
            
williamr@2
   975
            BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(long double)
williamr@2
   976
            
williamr@2
   977
            // UNtemplated copy constructor
williamr@2
   978
            // (this is taken care of by the compiler itself)
williamr@2
   979
            
williamr@2
   980
            // converting copy constructors
williamr@2
   981
            
williamr@2
   982
            explicit                    quaternion(quaternion<float> const & a_recopier)
williamr@2
   983
            {
williamr@2
   984
                *this = detail::quaternion_type_converter<long double, float>(a_recopier);
williamr@2
   985
            }
williamr@2
   986
            
williamr@2
   987
            explicit                    quaternion(quaternion<double> const & a_recopier)
williamr@2
   988
            {
williamr@2
   989
                *this = detail::quaternion_type_converter<long double, double>(a_recopier);
williamr@2
   990
            }
williamr@2
   991
            
williamr@2
   992
            // destructor
williamr@2
   993
            // (this is taken care of by the compiler itself)
williamr@2
   994
            
williamr@2
   995
            // accessors
williamr@2
   996
            //
williamr@2
   997
            // Note:    Like complex number, quaternions do have a meaningful notion of "real part",
williamr@2
   998
            //            but unlike them there is no meaningful notion of "imaginary part".
williamr@2
   999
            //            Instead there is an "unreal part" which itself is a quaternion, and usually
williamr@2
  1000
            //            nothing simpler (as opposed to the complex number case).
williamr@2
  1001
            //            However, for practicallity, there are accessors for the other components
williamr@2
  1002
            //            (these are necessary for the templated copy constructor, for instance).
williamr@2
  1003
            
williamr@2
  1004
            BOOST_QUATERNION_ACCESSOR_GENERATOR(long double)
williamr@2
  1005
            
williamr@2
  1006
            // assignment operators
williamr@2
  1007
            
williamr@2
  1008
            BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(long double)
williamr@2
  1009
            
williamr@2
  1010
            // other assignment-related operators
williamr@2
  1011
            //
williamr@2
  1012
            // NOTE:    Quaternion multiplication is *NOT* commutative;
williamr@2
  1013
            //            symbolically, "q *= rhs;" means "q = q * rhs;"
williamr@2
  1014
            //            and "q /= rhs;" means "q = q * inverse_of(rhs);"
williamr@2
  1015
            
williamr@2
  1016
            BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(long double)
williamr@2
  1017
            
williamr@2
  1018
            
williamr@2
  1019
        protected:
williamr@2
  1020
            
williamr@2
  1021
            BOOST_QUATERNION_MEMBER_DATA_GENERATOR(long double)
williamr@2
  1022
            
williamr@2
  1023
            
williamr@2
  1024
        private:
williamr@2
  1025
            
williamr@2
  1026
        };
williamr@2
  1027
        
williamr@2
  1028
        
williamr@2
  1029
#undef    BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR
williamr@2
  1030
#undef    BOOST_QUATERNION_MEMBER_ADD_GENERATOR
williamr@2
  1031
#undef    BOOST_QUATERNION_MEMBER_SUB_GENERATOR
williamr@2
  1032
#undef    BOOST_QUATERNION_MEMBER_MUL_GENERATOR
williamr@2
  1033
#undef    BOOST_QUATERNION_MEMBER_DIV_GENERATOR
williamr@2
  1034
#undef    BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1
williamr@2
  1035
#undef    BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2
williamr@2
  1036
#undef    BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3
williamr@2
  1037
#undef    BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1
williamr@2
  1038
#undef    BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2
williamr@2
  1039
#undef    BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3
williamr@2
  1040
#undef    BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1
williamr@2
  1041
#undef    BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2
williamr@2
  1042
#undef    BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3
williamr@2
  1043
#undef    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1
williamr@2
  1044
#undef    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2
williamr@2
  1045
#undef    BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3
williamr@2
  1046
        
williamr@2
  1047
#undef    BOOST_QUATERNION_CONSTRUCTOR_GENERATOR
williamr@2
  1048
        
williamr@2
  1049
        
williamr@2
  1050
#undef    BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR
williamr@2
  1051
        
williamr@2
  1052
#undef    BOOST_QUATERNION_MEMBER_DATA_GENERATOR
williamr@2
  1053
        
williamr@2
  1054
#undef    BOOST_QUATERNION_ACCESSOR_GENERATOR
williamr@2
  1055
        
williamr@2
  1056
        
williamr@2
  1057
        // operators
williamr@2
  1058
        
williamr@2
  1059
#define    BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)      \
williamr@2
  1060
        {                                                    \
williamr@2
  1061
            quaternion<T>    res(lhs);                       \
williamr@2
  1062
            res op##= rhs;                                   \
williamr@2
  1063
            return(res);                                     \
williamr@2
  1064
        }
williamr@2
  1065
        
williamr@2
  1066
#define    BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op)                                                  \
williamr@2
  1067
        template<typename T>                                                                            \
williamr@2
  1068
        inline quaternion<T>    operator op (T const & lhs, quaternion<T> const & rhs)                  \
williamr@2
  1069
        BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
williamr@2
  1070
        
williamr@2
  1071
#define    BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op)                                                  \
williamr@2
  1072
        template<typename T>                                                                            \
williamr@2
  1073
        inline quaternion<T>    operator op (quaternion<T> const & lhs, T const & rhs)                  \
williamr@2
  1074
        BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
williamr@2
  1075
        
williamr@2
  1076
#define    BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op)                                                  \
williamr@2
  1077
        template<typename T>                                                                            \
williamr@2
  1078
        inline quaternion<T>    operator op (::std::complex<T> const & lhs, quaternion<T> const & rhs)  \
williamr@2
  1079
        BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
williamr@2
  1080
        
williamr@2
  1081
#define    BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op)                                                  \
williamr@2
  1082
        template<typename T>                                                                            \
williamr@2
  1083
        inline quaternion<T>    operator op (quaternion<T> const & lhs, ::std::complex<T> const & rhs)  \
williamr@2
  1084
        BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
williamr@2
  1085
        
williamr@2
  1086
#define    BOOST_QUATERNION_OPERATOR_GENERATOR_3(op)                                                    \
williamr@2
  1087
        template<typename T>                                                                            \
williamr@2
  1088
        inline quaternion<T>    operator op (quaternion<T> const & lhs, quaternion<T> const & rhs)      \
williamr@2
  1089
        BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
williamr@2
  1090
        
williamr@2
  1091
#define    BOOST_QUATERNION_OPERATOR_GENERATOR(op)     \
williamr@2
  1092
        BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op)    \
williamr@2
  1093
        BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op)    \
williamr@2
  1094
        BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op)    \
williamr@2
  1095
        BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op)    \
williamr@2
  1096
        BOOST_QUATERNION_OPERATOR_GENERATOR_3(op)
williamr@2
  1097
        
williamr@2
  1098
        
williamr@2
  1099
        BOOST_QUATERNION_OPERATOR_GENERATOR(+)
williamr@2
  1100
        BOOST_QUATERNION_OPERATOR_GENERATOR(-)
williamr@2
  1101
        BOOST_QUATERNION_OPERATOR_GENERATOR(*)
williamr@2
  1102
        BOOST_QUATERNION_OPERATOR_GENERATOR(/)
williamr@2
  1103
williamr@2
  1104
williamr@2
  1105
#undef    BOOST_QUATERNION_OPERATOR_GENERATOR
williamr@2
  1106
        
williamr@2
  1107
#undef    BOOST_QUATERNION_OPERATOR_GENERATOR_1_L
williamr@2
  1108
#undef    BOOST_QUATERNION_OPERATOR_GENERATOR_1_R
williamr@2
  1109
#undef    BOOST_QUATERNION_OPERATOR_GENERATOR_2_L
williamr@2
  1110
#undef    BOOST_QUATERNION_OPERATOR_GENERATOR_2_R
williamr@2
  1111
#undef    BOOST_QUATERNION_OPERATOR_GENERATOR_3
williamr@2
  1112
williamr@2
  1113
#undef    BOOST_QUATERNION_OPERATOR_GENERATOR_BODY
williamr@2
  1114
        
williamr@2
  1115
        
williamr@2
  1116
        template<typename T>
williamr@2
  1117
        inline quaternion<T>                    operator + (quaternion<T> const & q)
williamr@2
  1118
        {
williamr@2
  1119
            return(q);
williamr@2
  1120
        }
williamr@2
  1121
        
williamr@2
  1122
        
williamr@2
  1123
        template<typename T>
williamr@2
  1124
        inline quaternion<T>                    operator - (quaternion<T> const & q)
williamr@2
  1125
        {
williamr@2
  1126
            return(quaternion<T>(-q.R_component_1(),-q.R_component_2(),-q.R_component_3(),-q.R_component_4()));
williamr@2
  1127
        }
williamr@2
  1128
        
williamr@2
  1129
        
williamr@2
  1130
        template<typename T>
williamr@2
  1131
        inline bool                                operator == (T const & lhs, quaternion<T> const & rhs)
williamr@2
  1132
        {
williamr@2
  1133
            return    (
williamr@2
  1134
                        (rhs.R_component_1() == lhs)&&
williamr@2
  1135
                        (rhs.R_component_2() == static_cast<T>(0))&&
williamr@2
  1136
                        (rhs.R_component_3() == static_cast<T>(0))&&
williamr@2
  1137
                        (rhs.R_component_4() == static_cast<T>(0))
williamr@2
  1138
                    );
williamr@2
  1139
        }
williamr@2
  1140
        
williamr@2
  1141
        
williamr@2
  1142
        template<typename T>
williamr@2
  1143
        inline bool                                operator == (quaternion<T> const & lhs, T const & rhs)
williamr@2
  1144
        {
williamr@2
  1145
            return    (
williamr@2
  1146
                        (lhs.R_component_1() == rhs)&&
williamr@2
  1147
                        (lhs.R_component_2() == static_cast<T>(0))&&
williamr@2
  1148
                        (lhs.R_component_3() == static_cast<T>(0))&&
williamr@2
  1149
                        (lhs.R_component_4() == static_cast<T>(0))
williamr@2
  1150
                    );
williamr@2
  1151
        }
williamr@2
  1152
        
williamr@2
  1153
        
williamr@2
  1154
        template<typename T>
williamr@2
  1155
        inline bool                                operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs)
williamr@2
  1156
        {
williamr@2
  1157
            return    (
williamr@2
  1158
                        (rhs.R_component_1() == lhs.real())&&
williamr@2
  1159
                        (rhs.R_component_2() == lhs.imag())&&
williamr@2
  1160
                        (rhs.R_component_3() == static_cast<T>(0))&&
williamr@2
  1161
                        (rhs.R_component_4() == static_cast<T>(0))
williamr@2
  1162
                    );
williamr@2
  1163
        }
williamr@2
  1164
        
williamr@2
  1165
        
williamr@2
  1166
        template<typename T>
williamr@2
  1167
        inline bool                                operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
williamr@2
  1168
        {
williamr@2
  1169
            return    (
williamr@2
  1170
                        (lhs.R_component_1() == rhs.real())&&
williamr@2
  1171
                        (lhs.R_component_2() == rhs.imag())&&
williamr@2
  1172
                        (lhs.R_component_3() == static_cast<T>(0))&&
williamr@2
  1173
                        (lhs.R_component_4() == static_cast<T>(0))
williamr@2
  1174
                    );
williamr@2
  1175
        }
williamr@2
  1176
        
williamr@2
  1177
        
williamr@2
  1178
        template<typename T>
williamr@2
  1179
        inline bool                                operator == (quaternion<T> const & lhs, quaternion<T> const & rhs)
williamr@2
  1180
        {
williamr@2
  1181
            return    (
williamr@2
  1182
                        (rhs.R_component_1() == lhs.R_component_1())&&
williamr@2
  1183
                        (rhs.R_component_2() == lhs.R_component_2())&&
williamr@2
  1184
                        (rhs.R_component_3() == lhs.R_component_3())&&
williamr@2
  1185
                        (rhs.R_component_4() == lhs.R_component_4())
williamr@2
  1186
                    );
williamr@2
  1187
        }
williamr@2
  1188
        
williamr@2
  1189
        
williamr@2
  1190
#define    BOOST_QUATERNION_NOT_EQUAL_GENERATOR  \
williamr@2
  1191
        {                                        \
williamr@2
  1192
            return(!(lhs == rhs));               \
williamr@2
  1193
        }
williamr@2
  1194
        
williamr@2
  1195
        template<typename T>
williamr@2
  1196
        inline bool                                operator != (T const & lhs, quaternion<T> const & rhs)
williamr@2
  1197
        BOOST_QUATERNION_NOT_EQUAL_GENERATOR
williamr@2
  1198
        
williamr@2
  1199
        template<typename T>
williamr@2
  1200
        inline bool                                operator != (quaternion<T> const & lhs, T const & rhs)
williamr@2
  1201
        BOOST_QUATERNION_NOT_EQUAL_GENERATOR
williamr@2
  1202
        
williamr@2
  1203
        template<typename T>
williamr@2
  1204
        inline bool                                operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs)
williamr@2
  1205
        BOOST_QUATERNION_NOT_EQUAL_GENERATOR
williamr@2
  1206
        
williamr@2
  1207
        template<typename T>
williamr@2
  1208
        inline bool                                operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
williamr@2
  1209
        BOOST_QUATERNION_NOT_EQUAL_GENERATOR
williamr@2
  1210
        
williamr@2
  1211
        template<typename T>
williamr@2
  1212
        inline bool                                operator != (quaternion<T> const & lhs, quaternion<T> const & rhs)
williamr@2
  1213
        BOOST_QUATERNION_NOT_EQUAL_GENERATOR
williamr@2
  1214
        
williamr@2
  1215
#undef    BOOST_QUATERNION_NOT_EQUAL_GENERATOR
williamr@2
  1216
        
williamr@2
  1217
        
williamr@2
  1218
        // Note:    we allow the following formats, whith a, b, c, and d reals
williamr@2
  1219
        //            a
williamr@2
  1220
        //            (a), (a,b), (a,b,c), (a,b,c,d)
williamr@2
  1221
        //            (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))
williamr@2
  1222
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1223
        template<typename T>
williamr@2
  1224
        std::istream &                            operator >> (    ::std::istream & is,
williamr@2
  1225
                                                                quaternion<T> & q)
williamr@2
  1226
#else
williamr@2
  1227
        template<typename T, typename charT, class traits>
williamr@2
  1228
        ::std::basic_istream<charT,traits> &    operator >> (    ::std::basic_istream<charT,traits> & is,
williamr@2
  1229
                                                                quaternion<T> & q)
williamr@2
  1230
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1231
        {
williamr@2
  1232
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1233
            typedef char    charT;
williamr@2
  1234
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1235
            
williamr@2
  1236
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1237
#else
williamr@2
  1238
            const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
williamr@2
  1239
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1240
            
williamr@2
  1241
            T    a = T();
williamr@2
  1242
            T    b = T();
williamr@2
  1243
            T    c = T();
williamr@2
  1244
            T    d = T();
williamr@2
  1245
            
williamr@2
  1246
            ::std::complex<T>    u = ::std::complex<T>();
williamr@2
  1247
            ::std::complex<T>    v = ::std::complex<T>();
williamr@2
  1248
            
williamr@2
  1249
            charT    ch = charT();
williamr@2
  1250
            char    cc;
williamr@2
  1251
            
williamr@2
  1252
            is >> ch;                                        // get the first lexeme
williamr@2
  1253
            
williamr@2
  1254
            if    (!is.good())    goto finish;
williamr@2
  1255
            
williamr@2
  1256
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1257
            cc = ch;
williamr@2
  1258
#else
williamr@2
  1259
            cc = ct.narrow(ch, char());
williamr@2
  1260
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1261
            
williamr@2
  1262
            if    (cc == '(')                            // read "(", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
williamr@2
  1263
            {
williamr@2
  1264
                is >> ch;                                    // get the second lexeme
williamr@2
  1265
                
williamr@2
  1266
                if    (!is.good())    goto finish;
williamr@2
  1267
                
williamr@2
  1268
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1269
                cc = ch;
williamr@2
  1270
#else
williamr@2
  1271
                cc = ct.narrow(ch, char());
williamr@2
  1272
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1273
                
williamr@2
  1274
                if    (cc == '(')                        // read "((", possible: ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
williamr@2
  1275
                {
williamr@2
  1276
                    is.putback(ch);
williamr@2
  1277
                    
williamr@2
  1278
                    is >> u;                                // we extract the first and second components
williamr@2
  1279
                    a = u.real();
williamr@2
  1280
                    b = u.imag();
williamr@2
  1281
                    
williamr@2
  1282
                    if    (!is.good())    goto finish;
williamr@2
  1283
                    
williamr@2
  1284
                    is >> ch;                                // get the next lexeme
williamr@2
  1285
                    
williamr@2
  1286
                    if    (!is.good())    goto finish;
williamr@2
  1287
                    
williamr@2
  1288
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1289
                    cc = ch;
williamr@2
  1290
#else
williamr@2
  1291
                    cc = ct.narrow(ch, char());
williamr@2
  1292
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1293
                    
williamr@2
  1294
                    if        (cc == ')')                    // format: ((a)) or ((a,b))
williamr@2
  1295
                    {
williamr@2
  1296
                        q = quaternion<T>(a,b);
williamr@2
  1297
                    }
williamr@2
  1298
                    else if    (cc == ',')                // read "((a)," or "((a,b),", possible: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
williamr@2
  1299
                    {
williamr@2
  1300
                        is >> v;                            // we extract the third and fourth components
williamr@2
  1301
                        c = v.real();
williamr@2
  1302
                        d = v.imag();
williamr@2
  1303
                        
williamr@2
  1304
                        if    (!is.good())    goto finish;
williamr@2
  1305
                        
williamr@2
  1306
                        is >> ch;                                // get the last lexeme
williamr@2
  1307
                        
williamr@2
  1308
                        if    (!is.good())    goto finish;
williamr@2
  1309
                        
williamr@2
  1310
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1311
                        cc = ch;
williamr@2
  1312
#else
williamr@2
  1313
                        cc = ct.narrow(ch, char());
williamr@2
  1314
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1315
                        
williamr@2
  1316
                        if    (cc == ')')                    // format: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)) or ((a,b,),(c,d,))
williamr@2
  1317
                        {
williamr@2
  1318
                            q = quaternion<T>(a,b,c,d);
williamr@2
  1319
                        }
williamr@2
  1320
                        else                            // error
williamr@2
  1321
                        {
williamr@2
  1322
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1323
                            is.setstate(::std::ios::failbit);
williamr@2
  1324
#else
williamr@2
  1325
                            is.setstate(::std::ios_base::failbit);
williamr@2
  1326
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1327
                        }
williamr@2
  1328
                    }
williamr@2
  1329
                    else                                // error
williamr@2
  1330
                    {
williamr@2
  1331
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1332
                        is.setstate(::std::ios::failbit);
williamr@2
  1333
#else
williamr@2
  1334
                        is.setstate(::std::ios_base::failbit);
williamr@2
  1335
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1336
                    }
williamr@2
  1337
                }
williamr@2
  1338
                else                                // read "(a", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
williamr@2
  1339
                {
williamr@2
  1340
                    is.putback(ch);
williamr@2
  1341
                    
williamr@2
  1342
                    is >> a;                                // we extract the first component
williamr@2
  1343
                    
williamr@2
  1344
                    if    (!is.good())    goto finish;
williamr@2
  1345
                    
williamr@2
  1346
                    is >> ch;                                // get the third lexeme
williamr@2
  1347
                    
williamr@2
  1348
                    if    (!is.good())    goto finish;
williamr@2
  1349
                    
williamr@2
  1350
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1351
                    cc = ch;
williamr@2
  1352
#else
williamr@2
  1353
                    cc = ct.narrow(ch, char());
williamr@2
  1354
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1355
                    
williamr@2
  1356
                    if        (cc == ')')                    // format: (a)
williamr@2
  1357
                    {
williamr@2
  1358
                        q = quaternion<T>(a);
williamr@2
  1359
                    }
williamr@2
  1360
                    else if    (cc == ',')                // read "(a,", possible: (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
williamr@2
  1361
                    {
williamr@2
  1362
                        is >> ch;                            // get the fourth lexeme
williamr@2
  1363
                        
williamr@2
  1364
                        if    (!is.good())    goto finish;
williamr@2
  1365
                        
williamr@2
  1366
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1367
                        cc = ch;
williamr@2
  1368
#else
williamr@2
  1369
                        cc = ct.narrow(ch, char());
williamr@2
  1370
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1371
                        
williamr@2
  1372
                        if    (cc == '(')                // read "(a,(", possible: (a,(c)), (a,(c,d))
williamr@2
  1373
                        {
williamr@2
  1374
                            is.putback(ch);
williamr@2
  1375
                            
williamr@2
  1376
                            is >> v;                        // we extract the third and fourth component
williamr@2
  1377
                            
williamr@2
  1378
                            c = v.real();
williamr@2
  1379
                            d = v.imag();
williamr@2
  1380
                            
williamr@2
  1381
                            if    (!is.good())    goto finish;
williamr@2
  1382
                            
williamr@2
  1383
                            is >> ch;                        // get the ninth lexeme
williamr@2
  1384
                            
williamr@2
  1385
                            if    (!is.good())    goto finish;
williamr@2
  1386
                            
williamr@2
  1387
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1388
                            cc = ch;
williamr@2
  1389
#else
williamr@2
  1390
                            cc = ct.narrow(ch, char());
williamr@2
  1391
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1392
                            
williamr@2
  1393
                            if    (cc == ')')                // format: (a,(c)) or (a,(c,d))
williamr@2
  1394
                            {
williamr@2
  1395
                                q = quaternion<T>(a,b,c,d);
williamr@2
  1396
                            }
williamr@2
  1397
                            else                        // error
williamr@2
  1398
                            {
williamr@2
  1399
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1400
                                is.setstate(::std::ios::failbit);
williamr@2
  1401
#else
williamr@2
  1402
                                is.setstate(::std::ios_base::failbit);
williamr@2
  1403
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1404
                            }
williamr@2
  1405
                        }
williamr@2
  1406
                        else                        // read "(a,b", possible: (a,b), (a,b,c), (a,b,c,d)
williamr@2
  1407
                        {
williamr@2
  1408
                            is.putback(ch);
williamr@2
  1409
                            
williamr@2
  1410
                            is >> b;                        // we extract the second component
williamr@2
  1411
                            
williamr@2
  1412
                            if    (!is.good())    goto finish;
williamr@2
  1413
                            
williamr@2
  1414
                            is >> ch;                        // get the fifth lexeme
williamr@2
  1415
                            
williamr@2
  1416
                            if    (!is.good())    goto finish;
williamr@2
  1417
                            
williamr@2
  1418
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1419
                            cc = ch;
williamr@2
  1420
#else
williamr@2
  1421
                            cc = ct.narrow(ch, char());
williamr@2
  1422
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1423
                            
williamr@2
  1424
                            if    (cc == ')')                // format: (a,b)
williamr@2
  1425
                            {
williamr@2
  1426
                                q = quaternion<T>(a,b);
williamr@2
  1427
                            }
williamr@2
  1428
                            else if    (cc == ',')        // read "(a,b,", possible: (a,b,c), (a,b,c,d)
williamr@2
  1429
                            {
williamr@2
  1430
                                is >> c;                    // we extract the third component
williamr@2
  1431
                                
williamr@2
  1432
                                if    (!is.good())    goto finish;
williamr@2
  1433
                                
williamr@2
  1434
                                is >> ch;                    // get the seventh lexeme
williamr@2
  1435
                                
williamr@2
  1436
                                if    (!is.good())    goto finish;
williamr@2
  1437
                                
williamr@2
  1438
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1439
                                cc = ch;
williamr@2
  1440
#else
williamr@2
  1441
                                cc = ct.narrow(ch, char());
williamr@2
  1442
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1443
                                
williamr@2
  1444
                                if        (cc == ')')        // format: (a,b,c)
williamr@2
  1445
                                {
williamr@2
  1446
                                    q = quaternion<T>(a,b,c);
williamr@2
  1447
                                }
williamr@2
  1448
                                else if    (cc == ',')    // read "(a,b,c,", possible: (a,b,c,d)
williamr@2
  1449
                                {
williamr@2
  1450
                                    is >> d;                // we extract the fourth component
williamr@2
  1451
                                    
williamr@2
  1452
                                    if    (!is.good())    goto finish;
williamr@2
  1453
                                    
williamr@2
  1454
                                    is >> ch;                // get the ninth lexeme
williamr@2
  1455
                                    
williamr@2
  1456
                                    if    (!is.good())    goto finish;
williamr@2
  1457
                                    
williamr@2
  1458
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1459
                                    cc = ch;
williamr@2
  1460
#else
williamr@2
  1461
                                    cc = ct.narrow(ch, char());
williamr@2
  1462
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1463
                                    
williamr@2
  1464
                                    if    (cc == ')')        // format: (a,b,c,d)
williamr@2
  1465
                                    {
williamr@2
  1466
                                        q = quaternion<T>(a,b,c,d);
williamr@2
  1467
                                    }
williamr@2
  1468
                                    else                // error
williamr@2
  1469
                                    {
williamr@2
  1470
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1471
                                        is.setstate(::std::ios::failbit);
williamr@2
  1472
#else
williamr@2
  1473
                                        is.setstate(::std::ios_base::failbit);
williamr@2
  1474
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1475
                                    }
williamr@2
  1476
                                }
williamr@2
  1477
                                else                    // error
williamr@2
  1478
                                {
williamr@2
  1479
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1480
                                    is.setstate(::std::ios::failbit);
williamr@2
  1481
#else
williamr@2
  1482
                                    is.setstate(::std::ios_base::failbit);
williamr@2
  1483
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1484
                                }
williamr@2
  1485
                            }
williamr@2
  1486
                            else                        // error
williamr@2
  1487
                            {
williamr@2
  1488
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1489
                                is.setstate(::std::ios::failbit);
williamr@2
  1490
#else
williamr@2
  1491
                                is.setstate(::std::ios_base::failbit);
williamr@2
  1492
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1493
                            }
williamr@2
  1494
                        }
williamr@2
  1495
                    }
williamr@2
  1496
                    else                                // error
williamr@2
  1497
                    {
williamr@2
  1498
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1499
                        is.setstate(::std::ios::failbit);
williamr@2
  1500
#else
williamr@2
  1501
                        is.setstate(::std::ios_base::failbit);
williamr@2
  1502
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1503
                    }
williamr@2
  1504
                }
williamr@2
  1505
            }
williamr@2
  1506
            else                                        // format:    a
williamr@2
  1507
            {
williamr@2
  1508
                is.putback(ch);
williamr@2
  1509
                
williamr@2
  1510
                is >> a;                                    // we extract the first component
williamr@2
  1511
                
williamr@2
  1512
                if    (!is.good())    goto finish;
williamr@2
  1513
                
williamr@2
  1514
                q = quaternion<T>(a);
williamr@2
  1515
            }
williamr@2
  1516
            
williamr@2
  1517
            finish:
williamr@2
  1518
            return(is);
williamr@2
  1519
        }
williamr@2
  1520
        
williamr@2
  1521
        
williamr@2
  1522
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1523
        template<typename T>
williamr@2
  1524
        ::std::ostream &                         operator << (    ::std::ostream & os,
williamr@2
  1525
                                                                quaternion<T> const & q)
williamr@2
  1526
#else
williamr@2
  1527
        template<typename T, typename charT, class traits>
williamr@2
  1528
        ::std::basic_ostream<charT,traits> &    operator << (    ::std::basic_ostream<charT,traits> & os,
williamr@2
  1529
                                                                quaternion<T> const & q)
williamr@2
  1530
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1531
        {
williamr@2
  1532
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1533
            ::std::ostringstream                        s;
williamr@2
  1534
#else
williamr@2
  1535
            ::std::basic_ostringstream<charT,traits>    s;
williamr@2
  1536
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1537
            
williamr@2
  1538
            s.flags(os.flags());
williamr@2
  1539
#ifdef    BOOST_NO_STD_LOCALE
williamr@2
  1540
#else
williamr@2
  1541
            s.imbue(os.getloc());
williamr@2
  1542
#endif /* BOOST_NO_STD_LOCALE */
williamr@2
  1543
            s.precision(os.precision());
williamr@2
  1544
            
williamr@2
  1545
            s << '('    << q.R_component_1() << ','
williamr@2
  1546
                        << q.R_component_2() << ','
williamr@2
  1547
                        << q.R_component_3() << ','
williamr@2
  1548
                        << q.R_component_4() << ')';
williamr@2
  1549
            
williamr@2
  1550
            return os << s.str();
williamr@2
  1551
        }
williamr@2
  1552
        
williamr@2
  1553
        
williamr@2
  1554
        // values
williamr@2
  1555
        
williamr@2
  1556
        template<typename T>
williamr@2
  1557
        inline T                                real(quaternion<T> const & q)
williamr@2
  1558
        {
williamr@2
  1559
            return(q.real());
williamr@2
  1560
        }
williamr@2
  1561
        
williamr@2
  1562
        
williamr@2
  1563
        template<typename T>
williamr@2
  1564
        inline quaternion<T>                    unreal(quaternion<T> const & q)
williamr@2
  1565
        {
williamr@2
  1566
            return(q.unreal());
williamr@2
  1567
        }
williamr@2
  1568
        
williamr@2
  1569
        
williamr@2
  1570
#define    BOOST_QUATERNION_VALARRAY_LOADER  \
williamr@2
  1571
            using    ::std::valarray;        \
williamr@2
  1572
                                             \
williamr@2
  1573
            valarray<T>    temp(4);          \
williamr@2
  1574
                                             \
williamr@2
  1575
            temp[0] = q.R_component_1();     \
williamr@2
  1576
            temp[1] = q.R_component_2();     \
williamr@2
  1577
            temp[2] = q.R_component_3();     \
williamr@2
  1578
            temp[3] = q.R_component_4();
williamr@2
  1579
        
williamr@2
  1580
        
williamr@2
  1581
        template<typename T>
williamr@2
  1582
        inline T                                sup(quaternion<T> const & q)
williamr@2
  1583
        {
williamr@2
  1584
#ifdef    BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
williamr@2
  1585
            using    ::std::abs;
williamr@2
  1586
#endif    /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
williamr@2
  1587
            
williamr@2
  1588
            BOOST_QUATERNION_VALARRAY_LOADER
williamr@2
  1589
            
williamr@2
  1590
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1591
            return((BOOST_GET_VALARRAY(T, abs(temp)).max)());
williamr@2
  1592
#else
williamr@2
  1593
            return((abs(temp).max)());
williamr@2
  1594
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1595
        }
williamr@2
  1596
        
williamr@2
  1597
        
williamr@2
  1598
        template<typename T>
williamr@2
  1599
        inline T                                l1(quaternion<T> const & q)
williamr@2
  1600
        {
williamr@2
  1601
#ifdef    BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
williamr@2
  1602
            using    ::std::abs;
williamr@2
  1603
#endif    /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
williamr@2
  1604
            
williamr@2
  1605
            BOOST_QUATERNION_VALARRAY_LOADER
williamr@2
  1606
            
williamr@2
  1607
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1608
            return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
williamr@2
  1609
#else
williamr@2
  1610
            return(abs(temp).sum());
williamr@2
  1611
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1612
        }
williamr@2
  1613
        
williamr@2
  1614
        
williamr@2
  1615
        template<typename T>
williamr@2
  1616
        inline T                                abs(quaternion<T> const & q)
williamr@2
  1617
        {
williamr@2
  1618
#ifdef    BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
williamr@2
  1619
            using    ::std::abs;
williamr@2
  1620
#endif    /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
williamr@2
  1621
            
williamr@2
  1622
            using    ::std::sqrt;
williamr@2
  1623
            
williamr@2
  1624
            BOOST_QUATERNION_VALARRAY_LOADER
williamr@2
  1625
            
williamr@2
  1626
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1627
            T            maxim = (BOOST_GET_VALARRAY(T, abs(temp)).max)();    // overflow protection
williamr@2
  1628
#else
williamr@2
  1629
            T            maxim = (abs(temp).max)();    // overflow protection
williamr@2
  1630
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1631
            
williamr@2
  1632
            if    (maxim == static_cast<T>(0))
williamr@2
  1633
            {
williamr@2
  1634
                return(maxim);
williamr@2
  1635
            }
williamr@2
  1636
            else
williamr@2
  1637
            {
williamr@2
  1638
                T    mixam = static_cast<T>(1)/maxim;    // prefer multiplications over divisions
williamr@2
  1639
                
williamr@2
  1640
                temp *= mixam;
williamr@2
  1641
                
williamr@2
  1642
                temp *= temp;
williamr@2
  1643
                
williamr@2
  1644
                return(maxim*sqrt(temp.sum()));
williamr@2
  1645
            }
williamr@2
  1646
            
williamr@2
  1647
            //return(sqrt(norm(q)));
williamr@2
  1648
        }
williamr@2
  1649
        
williamr@2
  1650
        
williamr@2
  1651
#undef    BOOST_QUATERNION_VALARRAY_LOADER
williamr@2
  1652
        
williamr@2
  1653
        
williamr@2
  1654
        // Note:    This is the Cayley norm, not the Euclidian norm...
williamr@2
  1655
        
williamr@2
  1656
        template<typename T>
williamr@2
  1657
        inline T                                norm(quaternion<T>const  & q)
williamr@2
  1658
        {
williamr@2
  1659
            return(real(q*conj(q)));
williamr@2
  1660
        }
williamr@2
  1661
        
williamr@2
  1662
        
williamr@2
  1663
        template<typename T>
williamr@2
  1664
        inline quaternion<T>                    conj(quaternion<T> const & q)
williamr@2
  1665
        {
williamr@2
  1666
            return(quaternion<T>(   +q.R_component_1(),
williamr@2
  1667
                                    -q.R_component_2(),
williamr@2
  1668
                                    -q.R_component_3(),
williamr@2
  1669
                                    -q.R_component_4()));
williamr@2
  1670
        }
williamr@2
  1671
        
williamr@2
  1672
        
williamr@2
  1673
        template<typename T>
williamr@2
  1674
        inline quaternion<T>                    spherical(  T const & rho,
williamr@2
  1675
                                                            T const & theta,
williamr@2
  1676
                                                            T const & phi1,
williamr@2
  1677
                                                            T const & phi2)
williamr@2
  1678
        {
williamr@2
  1679
            using ::std::cos;
williamr@2
  1680
            using ::std::sin;
williamr@2
  1681
            
williamr@2
  1682
            //T    a = cos(theta)*cos(phi1)*cos(phi2);
williamr@2
  1683
            //T    b = sin(theta)*cos(phi1)*cos(phi2);
williamr@2
  1684
            //T    c = sin(phi1)*cos(phi2);
williamr@2
  1685
            //T    d = sin(phi2);
williamr@2
  1686
            
williamr@2
  1687
            T    courrant = static_cast<T>(1);
williamr@2
  1688
            
williamr@2
  1689
            T    d = sin(phi2);
williamr@2
  1690
            
williamr@2
  1691
            courrant *= cos(phi2);
williamr@2
  1692
            
williamr@2
  1693
            T    c = sin(phi1)*courrant;
williamr@2
  1694
            
williamr@2
  1695
            courrant *= cos(phi1);
williamr@2
  1696
            
williamr@2
  1697
            T    b = sin(theta)*courrant;
williamr@2
  1698
            T    a = cos(theta)*courrant;
williamr@2
  1699
            
williamr@2
  1700
            return(rho*quaternion<T>(a,b,c,d));
williamr@2
  1701
        }
williamr@2
  1702
        
williamr@2
  1703
        
williamr@2
  1704
        template<typename T>
williamr@2
  1705
        inline quaternion<T>                    semipolar(  T const & rho,
williamr@2
  1706
                                                            T const & alpha,
williamr@2
  1707
                                                            T const & theta1,
williamr@2
  1708
                                                            T const & theta2)
williamr@2
  1709
        {
williamr@2
  1710
            using ::std::cos;
williamr@2
  1711
            using ::std::sin;
williamr@2
  1712
            
williamr@2
  1713
            T    a = cos(alpha)*cos(theta1);
williamr@2
  1714
            T    b = cos(alpha)*sin(theta1);
williamr@2
  1715
            T    c = sin(alpha)*cos(theta2);
williamr@2
  1716
            T    d = sin(alpha)*sin(theta2);
williamr@2
  1717
            
williamr@2
  1718
            return(rho*quaternion<T>(a,b,c,d));
williamr@2
  1719
        }
williamr@2
  1720
        
williamr@2
  1721
        
williamr@2
  1722
        template<typename T>
williamr@2
  1723
        inline quaternion<T>                    multipolar( T const & rho1,
williamr@2
  1724
                                                            T const & theta1,
williamr@2
  1725
                                                            T const & rho2,
williamr@2
  1726
                                                            T const & theta2)
williamr@2
  1727
        {
williamr@2
  1728
            using ::std::cos;
williamr@2
  1729
            using ::std::sin;
williamr@2
  1730
            
williamr@2
  1731
            T    a = rho1*cos(theta1);
williamr@2
  1732
            T    b = rho1*sin(theta1);
williamr@2
  1733
            T    c = rho2*cos(theta2);
williamr@2
  1734
            T    d = rho2*sin(theta2);
williamr@2
  1735
            
williamr@2
  1736
            return(quaternion<T>(a,b,c,d));
williamr@2
  1737
        }
williamr@2
  1738
        
williamr@2
  1739
        
williamr@2
  1740
        template<typename T>
williamr@2
  1741
        inline quaternion<T>                    cylindrospherical(  T const & t,
williamr@2
  1742
                                                                    T const & radius,
williamr@2
  1743
                                                                    T const & longitude,
williamr@2
  1744
                                                                    T const & latitude)
williamr@2
  1745
        {
williamr@2
  1746
            using ::std::cos;
williamr@2
  1747
            using ::std::sin;
williamr@2
  1748
            
williamr@2
  1749
            
williamr@2
  1750
            
williamr@2
  1751
            T    b = radius*cos(longitude)*cos(latitude);
williamr@2
  1752
            T    c = radius*sin(longitude)*cos(latitude);
williamr@2
  1753
            T    d = radius*sin(latitude);
williamr@2
  1754
            
williamr@2
  1755
            return(quaternion<T>(t,b,c,d));
williamr@2
  1756
        }
williamr@2
  1757
        
williamr@2
  1758
        
williamr@2
  1759
        template<typename T>
williamr@2
  1760
        inline quaternion<T>                    cylindrical(T const & r,
williamr@2
  1761
                                                            T const & angle,
williamr@2
  1762
                                                            T const & h1,
williamr@2
  1763
                                                            T const & h2)
williamr@2
  1764
        {
williamr@2
  1765
            using ::std::cos;
williamr@2
  1766
            using ::std::sin;
williamr@2
  1767
            
williamr@2
  1768
            T    a = r*cos(angle);
williamr@2
  1769
            T    b = r*sin(angle);
williamr@2
  1770
            
williamr@2
  1771
            return(quaternion<T>(a,b,h1,h2));
williamr@2
  1772
        }
williamr@2
  1773
        
williamr@2
  1774
        
williamr@2
  1775
        // transcendentals
williamr@2
  1776
        // (please see the documentation)
williamr@2
  1777
        
williamr@2
  1778
        
williamr@2
  1779
        template<typename T>
williamr@2
  1780
        inline quaternion<T>                    exp(quaternion<T> const & q)
williamr@2
  1781
        {
williamr@2
  1782
            using    ::std::exp;
williamr@2
  1783
            using    ::std::cos;
williamr@2
  1784
            
williamr@2
  1785
            using    ::boost::math::sinc_pi;
williamr@2
  1786
            
williamr@2
  1787
            T    u = exp(real(q));
williamr@2
  1788
            
williamr@2
  1789
            T    z = abs(unreal(q));
williamr@2
  1790
            
williamr@2
  1791
            T    w = sinc_pi(z);
williamr@2
  1792
            
williamr@2
  1793
            return(u*quaternion<T>(cos(z),
williamr@2
  1794
                w*q.R_component_2(), w*q.R_component_3(),
williamr@2
  1795
                w*q.R_component_4()));
williamr@2
  1796
        }
williamr@2
  1797
        
williamr@2
  1798
        
williamr@2
  1799
        template<typename T>
williamr@2
  1800
        inline quaternion<T>                    cos(quaternion<T> const & q)
williamr@2
  1801
        {
williamr@2
  1802
            using    ::std::sin;
williamr@2
  1803
            using    ::std::cos;
williamr@2
  1804
            using    ::std::cosh;
williamr@2
  1805
            
williamr@2
  1806
            using    ::boost::math::sinhc_pi;
williamr@2
  1807
            
williamr@2
  1808
            T    z = abs(unreal(q));
williamr@2
  1809
            
williamr@2
  1810
            T    w = -sin(q.real())*sinhc_pi(z);
williamr@2
  1811
            
williamr@2
  1812
            return(quaternion<T>(cos(q.real())*cosh(z),
williamr@2
  1813
                w*q.R_component_2(), w*q.R_component_3(),
williamr@2
  1814
                w*q.R_component_4()));
williamr@2
  1815
        }
williamr@2
  1816
        
williamr@2
  1817
        
williamr@2
  1818
        template<typename T>
williamr@2
  1819
        inline quaternion<T>                    sin(quaternion<T> const & q)
williamr@2
  1820
        {
williamr@2
  1821
            using    ::std::sin;
williamr@2
  1822
            using    ::std::cos;
williamr@2
  1823
            using    ::std::cosh;
williamr@2
  1824
            
williamr@2
  1825
            using    ::boost::math::sinhc_pi;
williamr@2
  1826
            
williamr@2
  1827
            T    z = abs(unreal(q));
williamr@2
  1828
            
williamr@2
  1829
            T    w = +cos(q.real())*sinhc_pi(z);
williamr@2
  1830
            
williamr@2
  1831
            return(quaternion<T>(sin(q.real())*cosh(z),
williamr@2
  1832
                w*q.R_component_2(), w*q.R_component_3(),
williamr@2
  1833
                w*q.R_component_4()));
williamr@2
  1834
        }
williamr@2
  1835
        
williamr@2
  1836
        
williamr@2
  1837
        template<typename T>
williamr@2
  1838
        inline quaternion<T>                    tan(quaternion<T> const & q)
williamr@2
  1839
        {
williamr@2
  1840
            return(sin(q)/cos(q));
williamr@2
  1841
        }
williamr@2
  1842
        
williamr@2
  1843
        
williamr@2
  1844
        template<typename T>
williamr@2
  1845
        inline quaternion<T>                    cosh(quaternion<T> const & q)
williamr@2
  1846
        {
williamr@2
  1847
            return((exp(+q)+exp(-q))/static_cast<T>(2));
williamr@2
  1848
        }
williamr@2
  1849
        
williamr@2
  1850
        
williamr@2
  1851
        template<typename T>
williamr@2
  1852
        inline quaternion<T>                    sinh(quaternion<T> const & q)
williamr@2
  1853
        {
williamr@2
  1854
            return((exp(+q)-exp(-q))/static_cast<T>(2));
williamr@2
  1855
        }
williamr@2
  1856
        
williamr@2
  1857
        
williamr@2
  1858
        template<typename T>
williamr@2
  1859
        inline quaternion<T>                    tanh(quaternion<T> const & q)
williamr@2
  1860
        {
williamr@2
  1861
            return(sinh(q)/cosh(q));
williamr@2
  1862
        }
williamr@2
  1863
        
williamr@2
  1864
        
williamr@2
  1865
        template<typename T>
williamr@2
  1866
        quaternion<T>                            pow(quaternion<T> const & q,
williamr@2
  1867
                                                    int n)
williamr@2
  1868
        {
williamr@2
  1869
            if        (n > 1)
williamr@2
  1870
            {
williamr@2
  1871
                int    m = n>>1;
williamr@2
  1872
                
williamr@2
  1873
                quaternion<T>    result = pow(q, m);
williamr@2
  1874
                
williamr@2
  1875
                result *= result;
williamr@2
  1876
                
williamr@2
  1877
                if    (n != (m<<1))
williamr@2
  1878
                {
williamr@2
  1879
                    result *= q; // n odd
williamr@2
  1880
                }
williamr@2
  1881
                
williamr@2
  1882
                return(result);
williamr@2
  1883
            }
williamr@2
  1884
            else if    (n == 1)
williamr@2
  1885
            {
williamr@2
  1886
                return(q);
williamr@2
  1887
            }
williamr@2
  1888
            else if    (n == 0)
williamr@2
  1889
            {
williamr@2
  1890
                return(quaternion<T>(1));
williamr@2
  1891
            }
williamr@2
  1892
            else    /* n < 0 */
williamr@2
  1893
            {
williamr@2
  1894
                return(pow(quaternion<T>(1)/q,-n));
williamr@2
  1895
            }
williamr@2
  1896
        }
williamr@2
  1897
        
williamr@2
  1898
        
williamr@2
  1899
        // helper templates for converting copy constructors (definition)
williamr@2
  1900
        
williamr@2
  1901
        namespace detail
williamr@2
  1902
        {
williamr@2
  1903
            
williamr@2
  1904
            template<   typename T,
williamr@2
  1905
                        typename U
williamr@2
  1906
                    >
williamr@2
  1907
            quaternion<T>    quaternion_type_converter(quaternion<U> const & rhs)
williamr@2
  1908
            {
williamr@2
  1909
                return(quaternion<T>(   static_cast<T>(rhs.R_component_1()),
williamr@2
  1910
                                        static_cast<T>(rhs.R_component_2()),
williamr@2
  1911
                                        static_cast<T>(rhs.R_component_3()),
williamr@2
  1912
                                        static_cast<T>(rhs.R_component_4())));
williamr@2
  1913
            }
williamr@2
  1914
        }
williamr@2
  1915
    }
williamr@2
  1916
}
williamr@2
  1917
williamr@2
  1918
williamr@2
  1919
#if    BOOST_WORKAROUND(__GNUC__, < 3)
williamr@2
  1920
    #undef    BOOST_GET_VALARRAY
williamr@2
  1921
#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
williamr@2
  1922
williamr@2
  1923
williamr@2
  1924
#endif /* BOOST_QUATERNION_HPP */