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