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