1 //Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
3 //Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef UUID_E6519754D19211DFB8405F74DFD72085
7 #define UUID_E6519754D19211DFB8405F74DFD72085
9 #include <boost/qvm/detail/quat_assign.hpp>
10 #include <boost/qvm/deduce_quat.hpp>
11 #include <boost/qvm/mat_traits.hpp>
12 #include <boost/qvm/scalar_traits.hpp>
13 #include <boost/qvm/math.hpp>
14 #include <boost/qvm/assert.hpp>
15 #include <boost/qvm/error.hpp>
16 #include <boost/qvm/throw_exception.hpp>
28 BOOST_QVM_INLINE_CRITICAL
30 get_valid_ptr_quat_operations()
32 static int const obj=0;
37 ////////////////////////////////////////////////
40 msvc_parse_bug_workaround
42 template <class A,class B>
46 static bool const value=is_quat<A>::value && is_quat<B>::value;
54 std::string to_string( T const & x );
59 typename boost::enable_if_c<
62 to_string( A const & a )
64 using namespace qvm_to_string_detail;
66 to_string(quat_traits<A>::template read_element<0>(a))+','+
67 to_string(quat_traits<A>::template read_element<1>(a))+','+
68 to_string(quat_traits<A>::template read_element<2>(a))+','+
69 to_string(quat_traits<A>::template read_element<3>(a))+')';
72 ////////////////////////////////////////////////
74 template <class A,class B,class Cmp>
75 BOOST_QVM_INLINE_OPERATIONS
77 is_quat<A>::value && is_quat<B>::value,
79 cmp( A const & a, B const & b, Cmp f )
81 typedef typename deduce_scalar<
82 typename quat_traits<A>::scalar_type,
83 typename quat_traits<B>::scalar_type>::type T;
86 quat_traits<A>::template read_element<0>(a),
87 quat_traits<A>::template read_element<1>(a),
88 quat_traits<A>::template read_element<2>(a),
89 quat_traits<A>::template read_element<3>(a)
93 quat_traits<B>::template read_element<0>(b),
94 quat_traits<B>::template read_element<1>(b),
95 quat_traits<B>::template read_element<2>(b),
96 quat_traits<B>::template read_element<3>(b)
100 if( !f(q1[i],q2[i]) )
104 for( i=0; i!=4; ++i )
105 if( !f(q1[i],-q2[i]) )
110 ////////////////////////////////////////////////
112 template <class R,class A>
113 BOOST_QVM_INLINE_TRIVIAL
114 typename enable_if_c<
115 is_quat<R>::value && is_quat<A>::value,
117 convert_to( A const & a )
120 quat_traits<R>::template write_element<0>(r) = quat_traits<A>::template read_element<0>(a);
121 quat_traits<R>::template write_element<1>(r) = quat_traits<A>::template read_element<1>(a);
122 quat_traits<R>::template write_element<2>(r) = quat_traits<A>::template read_element<2>(a);
123 quat_traits<R>::template write_element<3>(r) = quat_traits<A>::template read_element<3>(a);
127 template <class R,class A>
128 BOOST_QVM_INLINE_OPERATIONS
129 typename enable_if_c<
130 is_quat<R>::value && is_mat<A>::value &&
131 mat_traits<A>::rows==3 && mat_traits<A>::cols==3,
133 convert_to( A const & a )
135 typedef typename mat_traits<A>::scalar_type T;
138 { mat_traits<A>::template read_element<0,0>(a), mat_traits<A>::template read_element<0,1>(a), mat_traits<A>::template read_element<0,2>(a) },
139 { mat_traits<A>::template read_element<1,0>(a), mat_traits<A>::template read_element<1,1>(a), mat_traits<A>::template read_element<1,2>(a) },
140 { mat_traits<A>::template read_element<2,0>(a), mat_traits<A>::template read_element<2,1>(a), mat_traits<A>::template read_element<2,2>(a) }
143 if( mat[0][0]+mat[1][1]+mat[2][2] > scalar_traits<T>::value(0) )
145 T t = mat[0][0] + mat[1][1] + mat[2][2] + scalar_traits<T>::value(1);
146 T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
147 quat_traits<R>::template write_element<0>(r)=s*t;
148 quat_traits<R>::template write_element<1>(r)=(mat[2][1]-mat[1][2])*s;
149 quat_traits<R>::template write_element<2>(r)=(mat[0][2]-mat[2][0])*s;
150 quat_traits<R>::template write_element<3>(r)=(mat[1][0]-mat[0][1])*s;
152 else if( mat[0][0]>mat[1][1] && mat[0][0]>mat[2][2] )
154 T t = mat[0][0] - mat[1][1] - mat[2][2] + scalar_traits<T>::value(1);
155 T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
156 quat_traits<R>::template write_element<0>(r)=(mat[2][1]-mat[1][2])*s;
157 quat_traits<R>::template write_element<1>(r)=s*t;
158 quat_traits<R>::template write_element<2>(r)=(mat[1][0]+mat[0][1])*s;
159 quat_traits<R>::template write_element<3>(r)=(mat[0][2]+mat[2][0])*s;
161 else if( mat[1][1]>mat[2][2] )
163 T t = - mat[0][0] + mat[1][1] - mat[2][2] + scalar_traits<T>::value(1);
164 T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
165 quat_traits<R>::template write_element<0>(r)=(mat[0][2]-mat[2][0])*s;
166 quat_traits<R>::template write_element<1>(r)=(mat[1][0]+mat[0][1])*s;
167 quat_traits<R>::template write_element<2>(r)=s*t;
168 quat_traits<R>::template write_element<3>(r)=(mat[2][1]+mat[1][2])*s;
172 T t = - mat[0][0] - mat[1][1] + mat[2][2] + scalar_traits<T>::value(1);
173 T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
174 quat_traits<R>::template write_element<0>(r)=(mat[1][0]-mat[0][1])*s;
175 quat_traits<R>::template write_element<1>(r)=(mat[0][2]+mat[2][0])*s;
176 quat_traits<R>::template write_element<2>(r)=(mat[2][1]+mat[1][2])*s;
177 quat_traits<R>::template write_element<3>(r)=s*t;
182 ////////////////////////////////////////////////
185 BOOST_QVM_INLINE_OPERATIONS
186 typename lazy_enable_if_c<
188 deduce_quat<A> >::type
189 conjugate( A const & a )
191 typedef typename deduce_quat<A>::type R;
193 quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a);
194 quat_traits<R>::template write_element<1>(r)=-quat_traits<A>::template read_element<1>(a);
195 quat_traits<R>::template write_element<2>(r)=-quat_traits<A>::template read_element<2>(a);
196 quat_traits<R>::template write_element<3>(r)=-quat_traits<A>::template read_element<3>(a);
200 ////////////////////////////////////////////////
209 identity_quat_( identity_quat_ const & );
210 identity_quat_ & operator=( identity_quat_ const & );
216 BOOST_QVM_INLINE_TRIVIAL
228 quat_traits< qvm_detail::identity_quat_<T> >
230 typedef qvm_detail::identity_quat_<T> this_quaternion;
231 typedef T scalar_type;
235 BOOST_QVM_INLINE_CRITICAL
237 read_element( this_quaternion const & x )
239 BOOST_QVM_STATIC_ASSERT(I>=0);
240 BOOST_QVM_STATIC_ASSERT(I<4);
241 return scalar_traits<T>::value(I==0);
245 BOOST_QVM_INLINE_CRITICAL
247 read_element_idx( int i, this_quaternion const & x )
249 BOOST_QVM_ASSERT(i>=0);
250 BOOST_QVM_ASSERT(i<4);
251 return scalar_traits<T>::value(i==0);
257 deduce_quat< qvm_detail::identity_quat_<T> >
259 typedef quat<T> type;
264 deduce_quat2< qvm_detail::identity_quat_<T>, qvm_detail::identity_quat_<T> >
266 typedef quat<T> type;
270 BOOST_QVM_INLINE_TRIVIAL
271 qvm_detail::identity_quat_<T> const &
274 return *(qvm_detail::identity_quat_<T> const *)qvm_detail::get_valid_ptr_quat_operations();
278 BOOST_QVM_INLINE_OPERATIONS
279 typename enable_if_c<
282 set_identity( A & a )
284 typedef typename quat_traits<A>::scalar_type T;
285 T const zero=scalar_traits<T>::value(0);
286 T const one=scalar_traits<T>::value(1);
287 quat_traits<A>::template write_element<0>(a) = one;
288 quat_traits<A>::template write_element<1>(a) = zero;
289 quat_traits<A>::template write_element<2>(a) = zero;
290 quat_traits<A>::template write_element<3>(a) = zero;
293 ////////////////////////////////////////////////
298 template <class OriginalType,class Scalar>
300 quaternion_scalar_cast_
302 quaternion_scalar_cast_( quaternion_scalar_cast_ const & );
303 quaternion_scalar_cast_ & operator=( quaternion_scalar_cast_ const & );
304 ~quaternion_scalar_cast_();
309 BOOST_QVM_INLINE_TRIVIAL
310 quaternion_scalar_cast_ &
311 operator=( T const & x )
318 BOOST_QVM_INLINE_TRIVIAL
327 template <bool> struct scalar_cast_quaternion_filter { };
328 template <> struct scalar_cast_quaternion_filter<true> { typedef int type; };
331 template <class OriginalType,class Scalar>
333 quat_traits< qvm_detail::quaternion_scalar_cast_<OriginalType,Scalar> >
335 typedef Scalar scalar_type;
336 typedef qvm_detail::quaternion_scalar_cast_<OriginalType,Scalar> this_quaternion;
340 BOOST_QVM_INLINE_CRITICAL
342 read_element( this_quaternion const & x )
344 BOOST_QVM_STATIC_ASSERT(I>=0);
345 BOOST_QVM_STATIC_ASSERT(I<4);
346 return scalar_type(quat_traits<OriginalType>::template read_element<I>(reinterpret_cast<OriginalType const &>(x)));
350 BOOST_QVM_INLINE_CRITICAL
352 read_element_idx( int i, this_quaternion const & x )
354 BOOST_QVM_ASSERT(i>=0);
355 BOOST_QVM_ASSERT(i<4);
356 return scalar_type(quat_traits<OriginalType>::read_element_idx(i,reinterpret_cast<OriginalType const &>(x)));
360 template <class Scalar,class T>
361 BOOST_QVM_INLINE_TRIVIAL
362 qvm_detail::quaternion_scalar_cast_<T,Scalar> const &
363 scalar_cast( T const & x, typename qvm_detail::scalar_cast_quaternion_filter<is_quat<T>::value>::type=0 )
365 return reinterpret_cast<qvm_detail::quaternion_scalar_cast_<T,Scalar> const &>(x);
368 ////////////////////////////////////////////////
370 template <class A,class B>
371 BOOST_QVM_INLINE_OPERATIONS
372 typename enable_if_c<
373 is_quat<A>::value && is_scalar<B>::value,
375 operator/=( A & a, B b )
377 quat_traits<A>::template write_element<0>(a)/=b;
378 quat_traits<A>::template write_element<1>(a)/=b;
379 quat_traits<A>::template write_element<2>(a)/=b;
380 quat_traits<A>::template write_element<3>(a)/=b;
384 template <class A,class B>
385 BOOST_QVM_INLINE_OPERATIONS
386 typename lazy_enable_if_c<
387 is_quat<A>::value && is_scalar<B>::value,
388 deduce_quat<A> >::type
389 operator/( A const & a, B b )
391 typedef typename deduce_quat<A>::type R;
393 quat_traits<R>::template write_element<0>(r) = quat_traits<A>::template read_element<0>(a)/b;
394 quat_traits<R>::template write_element<1>(r) = quat_traits<A>::template read_element<1>(a)/b;
395 quat_traits<R>::template write_element<2>(r) = quat_traits<A>::template read_element<2>(a)/b;
396 quat_traits<R>::template write_element<3>(r) = quat_traits<A>::template read_element<3>(a)/b;
400 template <class A,class B>
401 BOOST_QVM_INLINE_OPERATIONS
402 typename lazy_enable_if_c<
403 is_quat<A>::value && is_quat<B>::value,
404 deduce_scalar<typename quat_traits<A>::scalar_type,typename quat_traits<B>::scalar_type> >::type
405 dot( A const & a, B const & b )
407 typedef typename quat_traits<A>::scalar_type Ta;
408 typedef typename quat_traits<B>::scalar_type Tb;
409 typedef typename deduce_scalar<Ta,Tb>::type Tr;
410 Ta const a0=quat_traits<A>::template read_element<0>(a);
411 Ta const a1=quat_traits<A>::template read_element<1>(a);
412 Ta const a2=quat_traits<A>::template read_element<2>(a);
413 Ta const a3=quat_traits<A>::template read_element<3>(a);
414 Tb const b0=quat_traits<B>::template read_element<0>(b);
415 Tb const b1=quat_traits<B>::template read_element<1>(b);
416 Tb const b2=quat_traits<B>::template read_element<2>(b);
417 Tb const b3=quat_traits<B>::template read_element<3>(b);
418 Tr const dp=a0*b0+a1*b1+a2*b2+a3*b3;
422 template <class A,class B>
423 BOOST_QVM_INLINE_OPERATIONS
424 typename enable_if_c<
425 is_quat<A>::value && is_quat<B>::value,
427 operator==( A const & a, B const & b )
430 quat_traits<A>::template read_element<0>(a)==quat_traits<B>::template read_element<0>(b) &&
431 quat_traits<A>::template read_element<1>(a)==quat_traits<B>::template read_element<1>(b) &&
432 quat_traits<A>::template read_element<2>(a)==quat_traits<B>::template read_element<2>(b) &&
433 quat_traits<A>::template read_element<3>(a)==quat_traits<B>::template read_element<3>(b);
437 BOOST_QVM_INLINE_OPERATIONS
438 typename lazy_enable_if_c<
440 deduce_quat<A> >::type
441 inverse( A const & a )
443 typedef typename deduce_quat<A>::type R;
444 typedef typename quat_traits<A>::scalar_type TA;
445 TA aa = quat_traits<A>::template read_element<0>(a);
446 TA ab = quat_traits<A>::template read_element<1>(a);
447 TA ac = quat_traits<A>::template read_element<2>(a);
448 TA ad = quat_traits<A>::template read_element<3>(a);
449 TA m2 = ab*ab + ac*ac + ad*ad + aa*aa;
450 if( m2==scalar_traits<TA>::value(0) )
451 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
452 TA rm=scalar_traits<TA>::value(1)/m2;
454 quat_traits<R>::template write_element<0>(r) = aa*rm;
455 quat_traits<R>::template write_element<1>(r) = -ab*rm;
456 quat_traits<R>::template write_element<2>(r) = -ac*rm;
457 quat_traits<R>::template write_element<3>(r) = -ad*rm;
462 BOOST_QVM_INLINE_OPERATIONS
463 typename enable_if_c<
465 typename quat_traits<A>::scalar_type>::type
466 mag_sqr( A const & a )
468 typedef typename quat_traits<A>::scalar_type T;
469 T x=quat_traits<A>::template read_element<0>(a);
470 T y=quat_traits<A>::template read_element<1>(a);
471 T z=quat_traits<A>::template read_element<2>(a);
472 T w=quat_traits<A>::template read_element<3>(a);
473 return x*x+y*y+z*z+w*w;
477 BOOST_QVM_INLINE_OPERATIONS
478 typename enable_if_c<
480 typename quat_traits<A>::scalar_type>::type
483 typedef typename quat_traits<A>::scalar_type T;
484 T x=quat_traits<A>::template read_element<0>(a);
485 T y=quat_traits<A>::template read_element<1>(a);
486 T z=quat_traits<A>::template read_element<2>(a);
487 T w=quat_traits<A>::template read_element<3>(a);
488 return sqrt<T>(x*x+y*y+z*z+w*w);
491 template <class A,class B>
492 BOOST_QVM_INLINE_OPERATIONS
494 msvc_parse_bug_workaround::quats<A,B>,
496 operator-=( A & a, B const & b )
498 quat_traits<A>::template write_element<0>(a)-=quat_traits<B>::template read_element<0>(b);
499 quat_traits<A>::template write_element<1>(a)-=quat_traits<B>::template read_element<1>(b);
500 quat_traits<A>::template write_element<2>(a)-=quat_traits<B>::template read_element<2>(b);
501 quat_traits<A>::template write_element<3>(a)-=quat_traits<B>::template read_element<3>(b);
505 template <class A,class B>
506 BOOST_QVM_INLINE_OPERATIONS
507 typename lazy_enable_if_c<
508 is_quat<A>::value && is_quat<B>::value,
509 deduce_quat2<A,B> >::type
510 operator-( A const & a, B const & b )
512 typedef typename deduce_quat2<A,B>::type R;
514 quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a)-quat_traits<B>::template read_element<0>(b);
515 quat_traits<R>::template write_element<1>(r)=quat_traits<A>::template read_element<1>(a)-quat_traits<B>::template read_element<1>(b);
516 quat_traits<R>::template write_element<2>(r)=quat_traits<A>::template read_element<2>(a)-quat_traits<B>::template read_element<2>(b);
517 quat_traits<R>::template write_element<3>(r)=quat_traits<A>::template read_element<3>(a)-quat_traits<B>::template read_element<3>(b);
522 BOOST_QVM_INLINE_OPERATIONS
523 typename lazy_enable_if_c<
525 deduce_quat<A> >::type
526 operator-( A const & a )
528 typedef typename deduce_quat<A>::type R;
530 quat_traits<R>::template write_element<0>(r)=-quat_traits<A>::template read_element<0>(a);
531 quat_traits<R>::template write_element<1>(r)=-quat_traits<A>::template read_element<1>(a);
532 quat_traits<R>::template write_element<2>(r)=-quat_traits<A>::template read_element<2>(a);
533 quat_traits<R>::template write_element<3>(r)=-quat_traits<A>::template read_element<3>(a);
537 template <class A,class B>
538 BOOST_QVM_INLINE_OPERATIONS
540 msvc_parse_bug_workaround::quats<A,B>,
542 operator*=( A & a, B const & b )
544 typedef typename quat_traits<A>::scalar_type TA;
545 typedef typename quat_traits<B>::scalar_type TB;
546 TA const aa=quat_traits<A>::template read_element<0>(a);
547 TA const ab=quat_traits<A>::template read_element<1>(a);
548 TA const ac=quat_traits<A>::template read_element<2>(a);
549 TA const ad=quat_traits<A>::template read_element<3>(a);
550 TB const ba=quat_traits<B>::template read_element<0>(b);
551 TB const bb=quat_traits<B>::template read_element<1>(b);
552 TB const bc=quat_traits<B>::template read_element<2>(b);
553 TB const bd=quat_traits<B>::template read_element<3>(b);
554 quat_traits<A>::template write_element<0>(a) = aa*ba - ab*bb - ac*bc - ad*bd;
555 quat_traits<A>::template write_element<1>(a) = aa*bb + ab*ba + ac*bd - ad*bc;
556 quat_traits<A>::template write_element<2>(a) = aa*bc + ac*ba + ad*bb - ab*bd;
557 quat_traits<A>::template write_element<3>(a) = aa*bd + ad*ba + ab*bc - ac*bb;
561 template <class A,class B>
562 BOOST_QVM_INLINE_OPERATIONS
563 typename enable_if_c<
564 is_quat<A>::value && is_scalar<B>::value,
566 operator*=( A & a, B b )
568 quat_traits<A>::template write_element<0>(a)*=b;
569 quat_traits<A>::template write_element<1>(a)*=b;
570 quat_traits<A>::template write_element<2>(a)*=b;
571 quat_traits<A>::template write_element<3>(a)*=b;
575 template <class A,class B>
576 BOOST_QVM_INLINE_OPERATIONS
577 typename lazy_enable_if_c<
578 is_quat<A>::value && is_quat<B>::value,
579 deduce_quat2<A,B> >::type
580 operator*( A const & a, B const & b )
582 typedef typename deduce_quat2<A,B>::type R;
583 typedef typename quat_traits<A>::scalar_type TA;
584 typedef typename quat_traits<B>::scalar_type TB;
585 TA const aa=quat_traits<A>::template read_element<0>(a);
586 TA const ab=quat_traits<A>::template read_element<1>(a);
587 TA const ac=quat_traits<A>::template read_element<2>(a);
588 TA const ad=quat_traits<A>::template read_element<3>(a);
589 TB const ba=quat_traits<B>::template read_element<0>(b);
590 TB const bb=quat_traits<B>::template read_element<1>(b);
591 TB const bc=quat_traits<B>::template read_element<2>(b);
592 TB const bd=quat_traits<B>::template read_element<3>(b);
594 quat_traits<R>::template write_element<0>(r) = aa*ba - ab*bb - ac*bc - ad*bd;
595 quat_traits<R>::template write_element<1>(r) = aa*bb + ab*ba + ac*bd - ad*bc;
596 quat_traits<R>::template write_element<2>(r) = aa*bc + ac*ba + ad*bb - ab*bd;
597 quat_traits<R>::template write_element<3>(r) = aa*bd + ad*ba + ab*bc - ac*bb;
601 template <class A,class B>
602 BOOST_QVM_INLINE_OPERATIONS
603 typename lazy_enable_if_c<
604 is_quat<A>::value && is_scalar<B>::value,
605 deduce_quat<A> >::type
606 operator*( A const & a, B b )
608 typedef typename deduce_quat<A>::type R;
610 quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a)*b;
611 quat_traits<R>::template write_element<1>(r)=quat_traits<A>::template read_element<1>(a)*b;
612 quat_traits<R>::template write_element<2>(r)=quat_traits<A>::template read_element<2>(a)*b;
613 quat_traits<R>::template write_element<3>(r)=quat_traits<A>::template read_element<3>(a)*b;
617 template <class A,class B>
618 BOOST_QVM_INLINE_OPERATIONS
619 typename enable_if_c<
620 is_quat<A>::value && is_quat<B>::value,
622 operator!=( A const & a, B const & b )
625 quat_traits<A>::template read_element<0>(a)!=quat_traits<B>::template read_element<0>(b) ||
626 quat_traits<A>::template read_element<1>(a)!=quat_traits<B>::template read_element<1>(b) ||
627 quat_traits<A>::template read_element<2>(a)!=quat_traits<B>::template read_element<2>(b) ||
628 quat_traits<A>::template read_element<3>(a)!=quat_traits<B>::template read_element<3>(b);
632 BOOST_QVM_INLINE_OPERATIONS
633 typename lazy_enable_if_c<
635 deduce_quat<A> >::type
636 normalized( A const & a )
638 typedef typename quat_traits<A>::scalar_type T;
639 T const a0=quat_traits<A>::template read_element<0>(a);
640 T const a1=quat_traits<A>::template read_element<1>(a);
641 T const a2=quat_traits<A>::template read_element<2>(a);
642 T const a3=quat_traits<A>::template read_element<3>(a);
643 T const m2=a0*a0+a1*a1+a2*a2+a3*a3;
644 if( m2==scalar_traits<typename quat_traits<A>::scalar_type>::value(0) )
645 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
646 T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);
647 typedef typename deduce_quat<A>::type R;
649 quat_traits<R>::template write_element<0>(r)=a0*rm;
650 quat_traits<R>::template write_element<1>(r)=a1*rm;
651 quat_traits<R>::template write_element<2>(r)=a2*rm;
652 quat_traits<R>::template write_element<3>(r)=a3*rm;
657 BOOST_QVM_INLINE_OPERATIONS
658 typename enable_if_c<
663 typedef typename quat_traits<A>::scalar_type T;
664 T const a0=quat_traits<A>::template read_element<0>(a);
665 T const a1=quat_traits<A>::template read_element<1>(a);
666 T const a2=quat_traits<A>::template read_element<2>(a);
667 T const a3=quat_traits<A>::template read_element<3>(a);
668 T const m2=a0*a0+a1*a1+a2*a2+a3*a3;
669 if( m2==scalar_traits<typename quat_traits<A>::scalar_type>::value(0) )
670 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
671 T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);
672 quat_traits<A>::template write_element<0>(a)*=rm;
673 quat_traits<A>::template write_element<1>(a)*=rm;
674 quat_traits<A>::template write_element<2>(a)*=rm;
675 quat_traits<A>::template write_element<3>(a)*=rm;
678 template <class A,class B>
679 BOOST_QVM_INLINE_OPERATIONS
681 msvc_parse_bug_workaround::quats<A,B>,
683 operator+=( A & a, B const & b )
685 quat_traits<A>::template write_element<0>(a)+=quat_traits<B>::template read_element<0>(b);
686 quat_traits<A>::template write_element<1>(a)+=quat_traits<B>::template read_element<1>(b);
687 quat_traits<A>::template write_element<2>(a)+=quat_traits<B>::template read_element<2>(b);
688 quat_traits<A>::template write_element<3>(a)+=quat_traits<B>::template read_element<3>(b);
692 template <class A,class B>
693 BOOST_QVM_INLINE_OPERATIONS
694 typename lazy_enable_if_c<
695 is_quat<A>::value && is_quat<B>::value,
696 deduce_quat2<A,B> >::type
697 operator+( A const & a, B const & b )
699 typedef typename deduce_quat2<A,B>::type R;
701 quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a)+quat_traits<B>::template read_element<0>(b);
702 quat_traits<R>::template write_element<1>(r)=quat_traits<A>::template read_element<1>(a)+quat_traits<B>::template read_element<1>(b);
703 quat_traits<R>::template write_element<2>(r)=quat_traits<A>::template read_element<2>(a)+quat_traits<B>::template read_element<2>(b);
704 quat_traits<R>::template write_element<3>(r)=quat_traits<A>::template read_element<3>(a)+quat_traits<B>::template read_element<3>(b);
708 template <class A,class B,class C>
709 BOOST_QVM_INLINE_OPERATIONS
710 typename lazy_enable_if_c<
711 is_quat<A>::value && is_quat<B>::value && is_scalar<C>::value,
712 deduce_quat2<A,B> >::type
713 slerp( A const & a, B const & b, C t )
715 typedef typename deduce_quat2<A,B>::type R;
716 typedef typename quat_traits<R>::scalar_type TR;
717 TR const one = scalar_traits<TR>::value(1);
722 TR const theta = acos<TR>(dp);
723 TR const invsintheta = one/sin<TR>(theta);
724 TR const scale = sin<TR>(theta*(one-t)) * invsintheta;
725 TR const invscale = sin<TR>(theta*t) * invsintheta * sc;
726 return a*scale + b*invscale;
729 return normalized(a+(b-a)*t);
732 ////////////////////////////////////////////////
741 qref_( qref_ const & );
742 qref_ & operator=( qref_ const & );
748 BOOST_QVM_INLINE_TRIVIAL
750 operator=( R const & x )
757 BOOST_QVM_INLINE_TRIVIAL
772 quat_traits< qvm_detail::qref_<Q> >
774 typedef typename quat_traits<Q>::scalar_type scalar_type;
775 typedef qvm_detail::qref_<Q> this_quaternion;
779 BOOST_QVM_INLINE_CRITICAL
781 read_element( this_quaternion const & x )
783 BOOST_QVM_STATIC_ASSERT(I>=0);
784 BOOST_QVM_STATIC_ASSERT(I<4);
785 return quat_traits<Q>::template read_element<I>(reinterpret_cast<Q const &>(x));
790 BOOST_QVM_INLINE_CRITICAL
792 write_element( this_quaternion & x )
794 BOOST_QVM_STATIC_ASSERT(I>=0);
795 BOOST_QVM_STATIC_ASSERT(I<4);
796 return quat_traits<Q>::template write_element<I>(reinterpret_cast<Q &>(x));
802 deduce_quat< qvm_detail::qref_<Q> >
804 typedef quat<typename quat_traits<Q>::scalar_type> type;
808 BOOST_QVM_INLINE_TRIVIAL
809 typename enable_if_c<
811 qvm_detail::qref_<Q> const &>::type
814 return reinterpret_cast<qvm_detail::qref_<Q> const &>(a);
818 BOOST_QVM_INLINE_TRIVIAL
819 typename enable_if_c<
821 qvm_detail::qref_<Q> &>::type
824 return reinterpret_cast<qvm_detail::qref_<Q> &>(a);
827 ////////////////////////////////////////////////
836 zero_q_( zero_q_ const & );
837 zero_q_ & operator=( zero_q_ const & );
843 BOOST_QVM_INLINE_TRIVIAL
855 quat_traits< qvm_detail::zero_q_<T> >
857 typedef qvm_detail::zero_q_<T> this_quaternion;
858 typedef T scalar_type;
862 BOOST_QVM_INLINE_CRITICAL
864 read_element( this_quaternion const & x )
866 BOOST_QVM_STATIC_ASSERT(I>=0);
867 BOOST_QVM_STATIC_ASSERT(I<4);
868 return scalar_traits<scalar_type>::value(0);
872 BOOST_QVM_INLINE_CRITICAL
874 read_element_idx( int i, this_quaternion const & x )
876 BOOST_QVM_ASSERT(i>=0);
877 BOOST_QVM_ASSERT(i<4);
878 return scalar_traits<scalar_type>::value(0);
883 BOOST_QVM_INLINE_TRIVIAL
884 qvm_detail::zero_q_<T> const &
887 return *(qvm_detail::zero_q_<T> const *)qvm_detail::get_valid_ptr_quat_operations();
891 BOOST_QVM_INLINE_OPERATIONS
892 typename enable_if_c<
897 typedef typename quat_traits<A>::scalar_type T;
898 T const zero=scalar_traits<T>::value(0);
899 quat_traits<A>::template write_element<0>(a) = zero;
900 quat_traits<A>::template write_element<1>(a) = zero;
901 quat_traits<A>::template write_element<2>(a) = zero;
902 quat_traits<A>::template write_element<3>(a) = zero;
905 ////////////////////////////////////////////////
914 typedef typename vec_traits<V>::scalar_type scalar_type;
917 template <class Angle>
919 rot_quat_( V const & axis, Angle angle )
921 scalar_type const x=vec_traits<V>::template read_element<0>(axis);
922 scalar_type const y=vec_traits<V>::template read_element<1>(axis);
923 scalar_type const z=vec_traits<V>::template read_element<2>(axis);
924 scalar_type const m2=x*x+y*y+z*z;
925 if( m2==scalar_traits<scalar_type>::value(0) )
926 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
927 scalar_type const rm=scalar_traits<scalar_type>::value(1)/sqrt<scalar_type>(m2);
929 scalar_type const s=sin<Angle>(angle);
930 a[0] = cos<Angle>(angle);
937 BOOST_QVM_INLINE_TRIVIAL
949 quat_traits< qvm_detail::rot_quat_<V> >
951 typedef qvm_detail::rot_quat_<V> this_quaternion;
952 typedef typename this_quaternion::scalar_type scalar_type;
956 BOOST_QVM_INLINE_CRITICAL
958 read_element( this_quaternion const & x )
960 BOOST_QVM_STATIC_ASSERT(I>=0);
961 BOOST_QVM_STATIC_ASSERT(I<4);
968 deduce_quat< qvm_detail::rot_quat_<V> >
970 typedef quat<typename vec_traits<V>::scalar_type> type;
973 template <class A,class Angle>
975 typename enable_if_c<
976 is_vec<A>::value && vec_traits<A>::dim==3,
977 qvm_detail::rot_quat_<A> >::type
978 rot_quat( A const & axis, Angle angle )
980 return qvm_detail::rot_quat_<A>(axis,angle);
983 template <class A,class B,class Angle>
984 BOOST_QVM_INLINE_OPERATIONS
985 typename enable_if_c<
987 is_vec<B>::value && vec_traits<B>::dim==3,
989 set_rot( A & a, B const & axis, Angle angle )
991 assign(a,rot_quat(axis,angle));
994 template <class A,class B,class Angle>
995 BOOST_QVM_INLINE_OPERATIONS
996 typename enable_if_c<
998 is_vec<B>::value && vec_traits<B>::dim==3,
1000 rotate( A & a, B const & axis, Angle angle )
1002 a *= rot_quat(axis,angle);
1005 ////////////////////////////////////////////////
1014 BOOST_QVM_INLINE_TRIVIAL
1020 BOOST_QVM_INLINE_TRIVIAL
1030 rotx_quat_( rotx_quat_ const & );
1031 rotx_quat_ & operator=( rotx_quat_ const & );
1041 BOOST_QVM_INLINE_CRITICAL
1045 return scalar_traits<T>::value(0);
1055 BOOST_QVM_INLINE_CRITICAL
1057 get( T const & angle )
1059 return sin<T>(angle/2);
1069 BOOST_QVM_INLINE_CRITICAL
1071 get( T const & angle )
1073 return cos<T>(angle/2);
1078 template <class Angle>
1080 quat_traits< qvm_detail::rotx_quat_<Angle> >
1082 typedef qvm_detail::rotx_quat_<Angle> this_quaternion;
1083 typedef Angle scalar_type;
1087 BOOST_QVM_INLINE_CRITICAL
1089 read_element( this_quaternion const & x )
1091 BOOST_QVM_STATIC_ASSERT(I>=0);
1092 BOOST_QVM_STATIC_ASSERT(I<4);
1093 return qvm_detail::rotx_q_get<I>::get(reinterpret_cast<Angle const &>(x));
1097 template <class Angle>
1099 deduce_quat< qvm_detail::rotx_quat_<Angle> >
1101 typedef quat<Angle> type;
1104 template <class Angle>
1106 deduce_quat2< qvm_detail::rotx_quat_<Angle>, qvm_detail::rotx_quat_<Angle> >
1108 typedef quat<Angle> type;
1111 template <class Angle>
1112 BOOST_QVM_INLINE_TRIVIAL
1113 qvm_detail::rotx_quat_<Angle> const &
1114 rotx_quat( Angle const & angle )
1116 return reinterpret_cast<qvm_detail::rotx_quat_<Angle> const &>(angle);
1119 template <class A,class Angle>
1120 BOOST_QVM_INLINE_OPERATIONS
1121 typename enable_if_c<
1124 set_rotx( A & a, Angle angle )
1126 assign(a,rotx_quat(angle));
1129 template <class A,class Angle>
1130 BOOST_QVM_INLINE_OPERATIONS
1131 typename enable_if_c<
1134 rotate_x( A & a, Angle angle )
1136 a *= rotx_quat(angle);
1139 ////////////////////////////////////////////////
1148 BOOST_QVM_INLINE_TRIVIAL
1154 BOOST_QVM_INLINE_TRIVIAL
1164 roty_quat_( roty_quat_ const & );
1165 roty_quat_ & operator=( roty_quat_ const & );
1175 BOOST_QVM_INLINE_CRITICAL
1179 return scalar_traits<T>::value(0);
1189 BOOST_QVM_INLINE_CRITICAL
1191 get( T const & angle )
1193 return sin<T>(angle/2);
1203 BOOST_QVM_INLINE_CRITICAL
1205 get( T const & angle )
1207 return cos<T>(angle/2);
1212 template <class Angle>
1214 quat_traits< qvm_detail::roty_quat_<Angle> >
1216 typedef qvm_detail::roty_quat_<Angle> this_quaternion;
1217 typedef Angle scalar_type;
1221 BOOST_QVM_INLINE_CRITICAL
1223 read_element( this_quaternion const & x )
1225 BOOST_QVM_STATIC_ASSERT(I>=0);
1226 BOOST_QVM_STATIC_ASSERT(I<4);
1227 return qvm_detail::roty_q_get<I>::get(reinterpret_cast<Angle const &>(x));
1231 template <class Angle>
1233 deduce_quat< qvm_detail::roty_quat_<Angle> >
1235 typedef quat<Angle> type;
1238 template <class Angle>
1240 deduce_quat2< qvm_detail::roty_quat_<Angle>, qvm_detail::roty_quat_<Angle> >
1242 typedef quat<Angle> type;
1245 template <class Angle>
1246 BOOST_QVM_INLINE_TRIVIAL
1247 qvm_detail::roty_quat_<Angle> const &
1248 roty_quat( Angle const & angle )
1250 return reinterpret_cast<qvm_detail::roty_quat_<Angle> const &>(angle);
1253 template <class A,class Angle>
1254 BOOST_QVM_INLINE_OPERATIONS
1255 typename enable_if_c<
1258 set_roty( A & a, Angle angle )
1260 assign(a,roty_quat(angle));
1263 template <class A,class Angle>
1264 BOOST_QVM_INLINE_OPERATIONS
1265 typename enable_if_c<
1268 rotate_y( A & a, Angle angle )
1270 a *= roty_quat(angle);
1273 ////////////////////////////////////////////////
1282 BOOST_QVM_INLINE_TRIVIAL
1288 BOOST_QVM_INLINE_TRIVIAL
1298 rotz_quat_( rotz_quat_ const & );
1299 rotz_quat_ & operator=( rotz_quat_ const & );
1309 BOOST_QVM_INLINE_CRITICAL
1313 return scalar_traits<T>::value(0);
1323 BOOST_QVM_INLINE_CRITICAL
1325 get( T const & angle )
1327 return sin<T>(angle/2);
1337 BOOST_QVM_INLINE_CRITICAL
1339 get( T const & angle )
1341 return cos<T>(angle/2);
1346 template <class Angle>
1348 quat_traits< qvm_detail::rotz_quat_<Angle> >
1350 typedef qvm_detail::rotz_quat_<Angle> this_quaternion;
1351 typedef Angle scalar_type;
1355 BOOST_QVM_INLINE_CRITICAL
1357 read_element( this_quaternion const & x )
1359 BOOST_QVM_STATIC_ASSERT(I>=0);
1360 BOOST_QVM_STATIC_ASSERT(I<4);
1361 return qvm_detail::rotz_q_get<I>::get(reinterpret_cast<Angle const &>(x));
1365 template <class Angle>
1367 deduce_quat< qvm_detail::rotz_quat_<Angle> >
1369 typedef quat<Angle> type;
1372 template <class Angle>
1374 deduce_quat2< qvm_detail::rotz_quat_<Angle>, qvm_detail::rotz_quat_<Angle> >
1376 typedef quat<Angle> type;
1379 template <class Angle>
1380 BOOST_QVM_INLINE_TRIVIAL
1381 qvm_detail::rotz_quat_<Angle> const &
1382 rotz_quat( Angle const & angle )
1384 return reinterpret_cast<qvm_detail::rotz_quat_<Angle> const &>(angle);
1387 template <class A,class Angle>
1388 BOOST_QVM_INLINE_OPERATIONS
1389 typename enable_if_c<
1392 set_rotz( A & a, Angle angle )
1394 assign(a,rotz_quat(angle));
1397 template <class A,class Angle>
1398 BOOST_QVM_INLINE_OPERATIONS
1399 typename enable_if_c<
1402 rotate_z( A & a, Angle angle )
1404 a *= rotz_quat(angle);
1407 template <class A,class B>
1408 BOOST_QVM_INLINE_OPERATIONS
1409 typename enable_if_c<
1410 is_quat<A>::value && is_vec<B>::value && vec_traits<B>::dim==3,
1411 typename quat_traits<A>::scalar_type>::type
1412 axis_angle( A const & a, B & b )
1414 typedef typename quat_traits<A>::scalar_type T;
1415 T a0=quat_traits<A>::template read_element<0>(a);
1416 T a1=quat_traits<A>::template read_element<1>(a);
1417 T a2=quat_traits<A>::template read_element<2>(a);
1418 T a3=quat_traits<A>::template read_element<3>(a);
1421 T const m2=a0*a0+a1*a1+a2*a2+a3*a3;
1422 if( m2==scalar_traits<T>::value(0) )
1423 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
1424 T const s=sqrt<T>(m2);
1430 if( T s=sqrt<T>(1-a0*a0) )
1432 vec_traits<B>::template write_element<0>(b) = a1/s;
1433 vec_traits<B>::template write_element<1>(b) = a2/s;
1434 vec_traits<B>::template write_element<2>(b) = a3/s;
1438 typedef typename vec_traits<B>::scalar_type U;
1439 vec_traits<B>::template write_element<0>(b) = scalar_traits<U>::value(1);
1440 vec_traits<B>::template write_element<1>(b) = vec_traits<B>::template write_element<2>(b) = scalar_traits<U>::value(0);
1442 return scalar_traits<T>::value(2) * qvm::acos(a0);
1445 ////////////////////////////////////////////////
1450 using ::boost::qvm::assign;
1451 using ::boost::qvm::cmp;
1452 using ::boost::qvm::convert_to;
1453 using ::boost::qvm::conjugate;
1454 using ::boost::qvm::set_identity;
1455 using ::boost::qvm::set_zero;
1456 using ::boost::qvm::scalar_cast;
1457 using ::boost::qvm::operator/=;
1458 using ::boost::qvm::operator/;
1459 using ::boost::qvm::dot;
1460 using ::boost::qvm::operator==;
1461 using ::boost::qvm::inverse;
1462 using ::boost::qvm::mag_sqr;
1463 using ::boost::qvm::mag;
1464 using ::boost::qvm::slerp;
1465 using ::boost::qvm::operator-=;
1466 using ::boost::qvm::operator-;
1467 using ::boost::qvm::operator*=;
1468 using ::boost::qvm::operator*;
1469 using ::boost::qvm::operator!=;
1470 using ::boost::qvm::normalized;
1471 using ::boost::qvm::normalize;
1472 using ::boost::qvm::operator+=;
1473 using ::boost::qvm::operator+;
1474 using ::boost::qvm::qref;
1475 using ::boost::qvm::rot_quat;
1476 using ::boost::qvm::set_rot;
1477 using ::boost::qvm::rotate;
1478 using ::boost::qvm::rotx_quat;
1479 using ::boost::qvm::set_rotx;
1480 using ::boost::qvm::rotate_x;
1481 using ::boost::qvm::roty_quat;
1482 using ::boost::qvm::set_roty;
1483 using ::boost::qvm::rotate_y;
1484 using ::boost::qvm::rotz_quat;
1485 using ::boost::qvm::set_rotz;
1486 using ::boost::qvm::rotate_z;
1489 ////////////////////////////////////////////////