source: NonGTP/Boost/boost/math/quaternion.hpp @ 857

Revision 857, 91.3 KB checked in by igarcia, 18 years ago (diff)
Line 
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
32namespace 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 */
Note: See TracBrowser for help on using the repository browser.