ossrv_pub/boost_apis/boost/math/quaternion.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 */