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