]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/qvm/quat_operations.hpp
1c0cc4db72615a88d77bcb3b37b6440ee4ffbd98
[ceph.git] / ceph / src / boost / boost / qvm / quat_operations.hpp
1 //Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
2
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)
5
6 #ifndef UUID_E6519754D19211DFB8405F74DFD72085
7 #define UUID_E6519754D19211DFB8405F74DFD72085
8
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>
17 #include <string>
18
19 namespace
20 boost
21 {
22 namespace
23 qvm
24 {
25 namespace
26 qvm_detail
27 {
28 BOOST_QVM_INLINE_CRITICAL
29 void const *
30 get_valid_ptr_quat_operations()
31 {
32 static int const obj=0;
33 return &obj;
34 }
35 }
36
37 ////////////////////////////////////////////////
38
39 namespace
40 msvc_parse_bug_workaround
41 {
42 template <class A,class B>
43 struct
44 quats
45 {
46 static bool const value=is_quat<A>::value && is_quat<B>::value;
47 };
48 }
49
50 namespace
51 qvm_to_string_detail
52 {
53 template <class T>
54 std::string to_string( T const & x );
55 }
56
57 template <class A>
58 inline
59 typename boost::enable_if_c<
60 is_quat<A>::value,
61 std::string>::type
62 to_string( A const & a )
63 {
64 using namespace qvm_to_string_detail;
65 return '('+
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))+')';
70 }
71
72 ////////////////////////////////////////////////
73
74 template <class A,class B,class Cmp>
75 BOOST_QVM_INLINE_OPERATIONS
76 typename enable_if_c<
77 is_quat<A>::value && is_quat<B>::value,
78 bool>::type
79 cmp( A const & a, B const & b, Cmp f )
80 {
81 typedef typename deduce_scalar<
82 typename quat_traits<A>::scalar_type,
83 typename quat_traits<B>::scalar_type>::type T;
84 T q1[4] =
85 {
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)
90 };
91 T q2[4] =
92 {
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)
97 };
98 int i;
99 for( i=0; i!=4; ++i )
100 if( !f(q1[i],q2[i]) )
101 break;
102 if( i==4 )
103 return true;
104 for( i=0; i!=4; ++i )
105 if( !f(q1[i],-q2[i]) )
106 return false;
107 return true;
108 }
109
110 ////////////////////////////////////////////////
111
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,
116 R>::type
117 convert_to( A const & a )
118 {
119 R r;
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);
124 return r;
125 }
126
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,
132 R>::type
133 convert_to( A const & a )
134 {
135 typedef typename mat_traits<A>::scalar_type T;
136 T const mat[3][3] =
137 {
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) }
141 };
142 R r;
143 if( mat[0][0]+mat[1][1]+mat[2][2] > scalar_traits<T>::value(0) )
144 {
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;
151 }
152 else if( mat[0][0]>mat[1][1] && mat[0][0]>mat[2][2] )
153 {
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;
160 }
161 else if( mat[1][1]>mat[2][2] )
162 {
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;
169 }
170 else
171 {
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;
178 }
179 return r;
180 }
181
182 ////////////////////////////////////////////////
183
184 template <class A>
185 BOOST_QVM_INLINE_OPERATIONS
186 typename lazy_enable_if_c<
187 is_quat<A>::value,
188 deduce_quat<A> >::type
189 conjugate( A const & a )
190 {
191 typedef typename deduce_quat<A>::type R;
192 R 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);
197 return r;
198 }
199
200 ////////////////////////////////////////////////
201
202 namespace
203 qvm_detail
204 {
205 template <class T>
206 class
207 identity_quat_
208 {
209 identity_quat_( identity_quat_ const & );
210 identity_quat_ & operator=( identity_quat_ const & );
211 ~identity_quat_();
212
213 public:
214
215 template <class R>
216 BOOST_QVM_INLINE_TRIVIAL
217 operator R() const
218 {
219 R r;
220 assign(r,*this);
221 return r;
222 }
223 };
224 }
225
226 template <class T>
227 struct
228 quat_traits< qvm_detail::identity_quat_<T> >
229 {
230 typedef qvm_detail::identity_quat_<T> this_quaternion;
231 typedef T scalar_type;
232
233 template <int I>
234 static
235 BOOST_QVM_INLINE_CRITICAL
236 scalar_type
237 read_element( this_quaternion const & x )
238 {
239 BOOST_QVM_STATIC_ASSERT(I>=0);
240 BOOST_QVM_STATIC_ASSERT(I<4);
241 return scalar_traits<T>::value(I==0);
242 }
243
244 static
245 BOOST_QVM_INLINE_CRITICAL
246 scalar_type
247 read_element_idx( int i, this_quaternion const & x )
248 {
249 BOOST_QVM_ASSERT(i>=0);
250 BOOST_QVM_ASSERT(i<4);
251 return scalar_traits<T>::value(i==0);
252 }
253 };
254
255 template <class T>
256 struct
257 deduce_quat< qvm_detail::identity_quat_<T> >
258 {
259 typedef quat<T> type;
260 };
261
262 template <class T>
263 struct
264 deduce_quat2< qvm_detail::identity_quat_<T>, qvm_detail::identity_quat_<T> >
265 {
266 typedef quat<T> type;
267 };
268
269 template <class T>
270 BOOST_QVM_INLINE_TRIVIAL
271 qvm_detail::identity_quat_<T> const &
272 identity_quat()
273 {
274 return *(qvm_detail::identity_quat_<T> const *)qvm_detail::get_valid_ptr_quat_operations();
275 }
276
277 template <class A>
278 BOOST_QVM_INLINE_OPERATIONS
279 typename enable_if_c<
280 is_quat<A>::value,
281 void>::type
282 set_identity( A & a )
283 {
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;
291 }
292
293 ////////////////////////////////////////////////
294
295 namespace
296 qvm_detail
297 {
298 template <class OriginalType,class Scalar>
299 class
300 quaternion_scalar_cast_
301 {
302 quaternion_scalar_cast_( quaternion_scalar_cast_ const & );
303 quaternion_scalar_cast_ & operator=( quaternion_scalar_cast_ const & );
304 ~quaternion_scalar_cast_();
305
306 public:
307
308 template <class T>
309 BOOST_QVM_INLINE_TRIVIAL
310 quaternion_scalar_cast_ &
311 operator=( T const & x )
312 {
313 assign(*this,x);
314 return *this;
315 }
316
317 template <class R>
318 BOOST_QVM_INLINE_TRIVIAL
319 operator R() const
320 {
321 R r;
322 assign(r,*this);
323 return r;
324 }
325 };
326
327 template <bool> struct scalar_cast_quaternion_filter { };
328 template <> struct scalar_cast_quaternion_filter<true> { typedef int type; };
329 }
330
331 template <class OriginalType,class Scalar>
332 struct
333 quat_traits< qvm_detail::quaternion_scalar_cast_<OriginalType,Scalar> >
334 {
335 typedef Scalar scalar_type;
336 typedef qvm_detail::quaternion_scalar_cast_<OriginalType,Scalar> this_quaternion;
337
338 template <int I>
339 static
340 BOOST_QVM_INLINE_CRITICAL
341 scalar_type
342 read_element( this_quaternion const & x )
343 {
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)));
347 }
348
349 static
350 BOOST_QVM_INLINE_CRITICAL
351 scalar_type
352 read_element_idx( int i, this_quaternion const & x )
353 {
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)));
357 }
358 };
359
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 )
364 {
365 return reinterpret_cast<qvm_detail::quaternion_scalar_cast_<T,Scalar> const &>(x);
366 }
367
368 ////////////////////////////////////////////////
369
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,
374 A &>::type
375 operator/=( A & a, B b )
376 {
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;
381 return a;
382 }
383
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 )
390 {
391 typedef typename deduce_quat<A>::type R;
392 R 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;
397 return r;
398 }
399
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 )
406 {
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;
419 return dp;
420 }
421
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,
426 bool>::type
427 operator==( A const & a, B const & b )
428 {
429 return
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);
434 }
435
436 template <class A>
437 BOOST_QVM_INLINE_OPERATIONS
438 typename lazy_enable_if_c<
439 is_quat<A>::value,
440 deduce_quat<A> >::type
441 inverse( A const & a )
442 {
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;
453 R r;
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;
458 return r;
459 }
460
461 template <class A>
462 BOOST_QVM_INLINE_OPERATIONS
463 typename enable_if_c<
464 is_quat<A>::value,
465 typename quat_traits<A>::scalar_type>::type
466 mag_sqr( A const & a )
467 {
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;
474 }
475
476 template <class A>
477 BOOST_QVM_INLINE_OPERATIONS
478 typename enable_if_c<
479 is_quat<A>::value,
480 typename quat_traits<A>::scalar_type>::type
481 mag( A const & a )
482 {
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);
489 }
490
491 template <class A,class B>
492 BOOST_QVM_INLINE_OPERATIONS
493 typename enable_if<
494 msvc_parse_bug_workaround::quats<A,B>,
495 A &>::type
496 operator-=( A & a, B const & b )
497 {
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);
502 return a;
503 }
504
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 )
511 {
512 typedef typename deduce_quat2<A,B>::type R;
513 R 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);
518 return r;
519 }
520
521 template <class A>
522 BOOST_QVM_INLINE_OPERATIONS
523 typename lazy_enable_if_c<
524 is_quat<A>::value,
525 deduce_quat<A> >::type
526 operator-( A const & a )
527 {
528 typedef typename deduce_quat<A>::type R;
529 R 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);
534 return r;
535 }
536
537 template <class A,class B>
538 BOOST_QVM_INLINE_OPERATIONS
539 typename enable_if<
540 msvc_parse_bug_workaround::quats<A,B>,
541 A &>::type
542 operator*=( A & a, B const & b )
543 {
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;
558 return a;
559 }
560
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,
565 A &>::type
566 operator*=( A & a, B b )
567 {
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;
572 return a;
573 }
574
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 )
581 {
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);
593 R r;
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;
598 return r;
599 }
600
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 )
607 {
608 typedef typename deduce_quat<A>::type R;
609 R 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;
614 return r;
615 }
616
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,
621 bool>::type
622 operator!=( A const & a, B const & b )
623 {
624 return
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);
629 }
630
631 template <class A>
632 BOOST_QVM_INLINE_OPERATIONS
633 typename lazy_enable_if_c<
634 is_quat<A>::value,
635 deduce_quat<A> >::type
636 normalized( A const & a )
637 {
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;
648 R 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;
653 return r;
654 }
655
656 template <class A>
657 BOOST_QVM_INLINE_OPERATIONS
658 typename enable_if_c<
659 is_quat<A>::value,
660 void>::type
661 normalize( A & a )
662 {
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;
676 }
677
678 template <class A,class B>
679 BOOST_QVM_INLINE_OPERATIONS
680 typename enable_if<
681 msvc_parse_bug_workaround::quats<A,B>,
682 A &>::type
683 operator+=( A & a, B const & b )
684 {
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);
689 return a;
690 }
691
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 )
698 {
699 typedef typename deduce_quat2<A,B>::type R;
700 R 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);
705 return r;
706 }
707
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 )
714 {
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);
718 TR dp = dot(a,b);
719 TR sc=one;
720 if( dp < one )
721 {
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;
727 }
728 else
729 return normalized(a+(b-a)*t);
730 }
731
732 ////////////////////////////////////////////////
733
734 namespace
735 qvm_detail
736 {
737 template <class T>
738 class
739 qref_
740 {
741 qref_( qref_ const & );
742 qref_ & operator=( qref_ const & );
743 ~qref_();
744
745 public:
746
747 template <class R>
748 BOOST_QVM_INLINE_TRIVIAL
749 qref_ &
750 operator=( R const & x )
751 {
752 assign(*this,x);
753 return *this;
754 }
755
756 template <class R>
757 BOOST_QVM_INLINE_TRIVIAL
758 operator R() const
759 {
760 R r;
761 assign(r,*this);
762 return r;
763 }
764 };
765 }
766
767 template <class Q>
768 struct quat_traits;
769
770 template <class Q>
771 struct
772 quat_traits< qvm_detail::qref_<Q> >
773 {
774 typedef typename quat_traits<Q>::scalar_type scalar_type;
775 typedef qvm_detail::qref_<Q> this_quaternion;
776
777 template <int I>
778 static
779 BOOST_QVM_INLINE_CRITICAL
780 scalar_type
781 read_element( this_quaternion const & x )
782 {
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));
786 }
787
788 template <int I>
789 static
790 BOOST_QVM_INLINE_CRITICAL
791 scalar_type &
792 write_element( this_quaternion & x )
793 {
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));
797 }
798 };
799
800 template <class Q>
801 struct
802 deduce_quat< qvm_detail::qref_<Q> >
803 {
804 typedef quat<typename quat_traits<Q>::scalar_type> type;
805 };
806
807 template <class Q>
808 BOOST_QVM_INLINE_TRIVIAL
809 typename enable_if_c<
810 is_quat<Q>::value,
811 qvm_detail::qref_<Q> const &>::type
812 qref( Q const & a )
813 {
814 return reinterpret_cast<qvm_detail::qref_<Q> const &>(a);
815 }
816
817 template <class Q>
818 BOOST_QVM_INLINE_TRIVIAL
819 typename enable_if_c<
820 is_quat<Q>::value,
821 qvm_detail::qref_<Q> &>::type
822 qref( Q & a )
823 {
824 return reinterpret_cast<qvm_detail::qref_<Q> &>(a);
825 }
826
827 ////////////////////////////////////////////////
828
829 namespace
830 qvm_detail
831 {
832 template <class T>
833 class
834 zero_q_
835 {
836 zero_q_( zero_q_ const & );
837 zero_q_ & operator=( zero_q_ const & );
838 ~zero_q_();
839
840 public:
841
842 template <class R>
843 BOOST_QVM_INLINE_TRIVIAL
844 operator R() const
845 {
846 R r;
847 assign(r,*this);
848 return r;
849 }
850 };
851 }
852
853 template <class T>
854 struct
855 quat_traits< qvm_detail::zero_q_<T> >
856 {
857 typedef qvm_detail::zero_q_<T> this_quaternion;
858 typedef T scalar_type;
859
860 template <int I>
861 static
862 BOOST_QVM_INLINE_CRITICAL
863 scalar_type
864 read_element( this_quaternion const & x )
865 {
866 BOOST_QVM_STATIC_ASSERT(I>=0);
867 BOOST_QVM_STATIC_ASSERT(I<4);
868 return scalar_traits<scalar_type>::value(0);
869 }
870
871 static
872 BOOST_QVM_INLINE_CRITICAL
873 scalar_type
874 read_element_idx( int i, this_quaternion const & x )
875 {
876 BOOST_QVM_ASSERT(i>=0);
877 BOOST_QVM_ASSERT(i<4);
878 return scalar_traits<scalar_type>::value(0);
879 }
880 };
881
882 template <class T>
883 BOOST_QVM_INLINE_TRIVIAL
884 qvm_detail::zero_q_<T> const &
885 zero_quat()
886 {
887 return *(qvm_detail::zero_q_<T> const *)qvm_detail::get_valid_ptr_quat_operations();
888 }
889
890 template <class A>
891 BOOST_QVM_INLINE_OPERATIONS
892 typename enable_if_c<
893 is_quat<A>::value,
894 void>::type
895 set_zero( A & a )
896 {
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;
903 }
904
905 ////////////////////////////////////////////////
906
907 namespace
908 qvm_detail
909 {
910 template <class V>
911 struct
912 rot_quat_
913 {
914 typedef typename vec_traits<V>::scalar_type scalar_type;
915 scalar_type a[4];
916
917 template <class Angle>
918 BOOST_QVM_INLINE
919 rot_quat_( V const & axis, Angle angle )
920 {
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);
928 angle/=2;
929 scalar_type const s=sin<Angle>(angle);
930 a[0] = cos<Angle>(angle);
931 a[1] = rm*x*s;
932 a[2] = rm*y*s;
933 a[3] = rm*z*s;
934 }
935
936 template <class R>
937 BOOST_QVM_INLINE_TRIVIAL
938 operator R() const
939 {
940 R r;
941 assign(r,*this);
942 return r;
943 }
944 };
945 }
946
947 template <class V>
948 struct
949 quat_traits< qvm_detail::rot_quat_<V> >
950 {
951 typedef qvm_detail::rot_quat_<V> this_quaternion;
952 typedef typename this_quaternion::scalar_type scalar_type;
953
954 template <int I>
955 static
956 BOOST_QVM_INLINE_CRITICAL
957 scalar_type
958 read_element( this_quaternion const & x )
959 {
960 BOOST_QVM_STATIC_ASSERT(I>=0);
961 BOOST_QVM_STATIC_ASSERT(I<4);
962 return x.a[I];
963 }
964 };
965
966 template <class V>
967 struct
968 deduce_quat< qvm_detail::rot_quat_<V> >
969 {
970 typedef quat<typename vec_traits<V>::scalar_type> type;
971 };
972
973 template <class A,class Angle>
974 BOOST_QVM_INLINE
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 )
979 {
980 return qvm_detail::rot_quat_<A>(axis,angle);
981 }
982
983 template <class A,class B,class Angle>
984 BOOST_QVM_INLINE_OPERATIONS
985 typename enable_if_c<
986 is_quat<A>::value &&
987 is_vec<B>::value && vec_traits<B>::dim==3,
988 void>::type
989 set_rot( A & a, B const & axis, Angle angle )
990 {
991 assign(a,rot_quat(axis,angle));
992 }
993
994 template <class A,class B,class Angle>
995 BOOST_QVM_INLINE_OPERATIONS
996 typename enable_if_c<
997 is_quat<A>::value &&
998 is_vec<B>::value && vec_traits<B>::dim==3,
999 void>::type
1000 rotate( A & a, B const & axis, Angle angle )
1001 {
1002 a *= rot_quat(axis,angle);
1003 }
1004
1005 ////////////////////////////////////////////////
1006
1007 namespace
1008 qvm_detail
1009 {
1010 template <class T>
1011 struct
1012 rotx_quat_
1013 {
1014 BOOST_QVM_INLINE_TRIVIAL
1015 rotx_quat_()
1016 {
1017 }
1018
1019 template <class R>
1020 BOOST_QVM_INLINE_TRIVIAL
1021 operator R() const
1022 {
1023 R r;
1024 assign(r,*this);
1025 return r;
1026 }
1027
1028 private:
1029
1030 rotx_quat_( rotx_quat_ const & );
1031 rotx_quat_ & operator=( rotx_quat_ const & );
1032 ~rotx_quat_();
1033 };
1034
1035 template <int I>
1036 struct
1037 rotx_q_get
1038 {
1039 template <class T>
1040 static
1041 BOOST_QVM_INLINE_CRITICAL
1042 T
1043 get( T const & )
1044 {
1045 return scalar_traits<T>::value(0);
1046 }
1047 };
1048
1049 template <>
1050 struct
1051 rotx_q_get<1>
1052 {
1053 template <class T>
1054 static
1055 BOOST_QVM_INLINE_CRITICAL
1056 T
1057 get( T const & angle )
1058 {
1059 return sin<T>(angle/2);
1060 }
1061 };
1062
1063 template <>
1064 struct
1065 rotx_q_get<0>
1066 {
1067 template <class T>
1068 static
1069 BOOST_QVM_INLINE_CRITICAL
1070 T
1071 get( T const & angle )
1072 {
1073 return cos<T>(angle/2);
1074 }
1075 };
1076 }
1077
1078 template <class Angle>
1079 struct
1080 quat_traits< qvm_detail::rotx_quat_<Angle> >
1081 {
1082 typedef qvm_detail::rotx_quat_<Angle> this_quaternion;
1083 typedef Angle scalar_type;
1084
1085 template <int I>
1086 static
1087 BOOST_QVM_INLINE_CRITICAL
1088 scalar_type
1089 read_element( this_quaternion const & x )
1090 {
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));
1094 }
1095 };
1096
1097 template <class Angle>
1098 struct
1099 deduce_quat< qvm_detail::rotx_quat_<Angle> >
1100 {
1101 typedef quat<Angle> type;
1102 };
1103
1104 template <class Angle>
1105 struct
1106 deduce_quat2< qvm_detail::rotx_quat_<Angle>, qvm_detail::rotx_quat_<Angle> >
1107 {
1108 typedef quat<Angle> type;
1109 };
1110
1111 template <class Angle>
1112 BOOST_QVM_INLINE_TRIVIAL
1113 qvm_detail::rotx_quat_<Angle> const &
1114 rotx_quat( Angle const & angle )
1115 {
1116 return reinterpret_cast<qvm_detail::rotx_quat_<Angle> const &>(angle);
1117 }
1118
1119 template <class A,class Angle>
1120 BOOST_QVM_INLINE_OPERATIONS
1121 typename enable_if_c<
1122 is_quat<A>::value,
1123 void>::type
1124 set_rotx( A & a, Angle angle )
1125 {
1126 assign(a,rotx_quat(angle));
1127 }
1128
1129 template <class A,class Angle>
1130 BOOST_QVM_INLINE_OPERATIONS
1131 typename enable_if_c<
1132 is_quat<A>::value,
1133 void>::type
1134 rotate_x( A & a, Angle angle )
1135 {
1136 a *= rotx_quat(angle);
1137 }
1138
1139 ////////////////////////////////////////////////
1140
1141 namespace
1142 qvm_detail
1143 {
1144 template <class T>
1145 struct
1146 roty_quat_
1147 {
1148 BOOST_QVM_INLINE_TRIVIAL
1149 roty_quat_()
1150 {
1151 }
1152
1153 template <class R>
1154 BOOST_QVM_INLINE_TRIVIAL
1155 operator R() const
1156 {
1157 R r;
1158 assign(r,*this);
1159 return r;
1160 }
1161
1162 private:
1163
1164 roty_quat_( roty_quat_ const & );
1165 roty_quat_ & operator=( roty_quat_ const & );
1166 ~roty_quat_();
1167 };
1168
1169 template <int I>
1170 struct
1171 roty_q_get
1172 {
1173 template <class T>
1174 static
1175 BOOST_QVM_INLINE_CRITICAL
1176 T
1177 get( T const & )
1178 {
1179 return scalar_traits<T>::value(0);
1180 }
1181 };
1182
1183 template <>
1184 struct
1185 roty_q_get<2>
1186 {
1187 template <class T>
1188 static
1189 BOOST_QVM_INLINE_CRITICAL
1190 T
1191 get( T const & angle )
1192 {
1193 return sin<T>(angle/2);
1194 }
1195 };
1196
1197 template <>
1198 struct
1199 roty_q_get<0>
1200 {
1201 template <class T>
1202 static
1203 BOOST_QVM_INLINE_CRITICAL
1204 T
1205 get( T const & angle )
1206 {
1207 return cos<T>(angle/2);
1208 }
1209 };
1210 }
1211
1212 template <class Angle>
1213 struct
1214 quat_traits< qvm_detail::roty_quat_<Angle> >
1215 {
1216 typedef qvm_detail::roty_quat_<Angle> this_quaternion;
1217 typedef Angle scalar_type;
1218
1219 template <int I>
1220 static
1221 BOOST_QVM_INLINE_CRITICAL
1222 scalar_type
1223 read_element( this_quaternion const & x )
1224 {
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));
1228 }
1229 };
1230
1231 template <class Angle>
1232 struct
1233 deduce_quat< qvm_detail::roty_quat_<Angle> >
1234 {
1235 typedef quat<Angle> type;
1236 };
1237
1238 template <class Angle>
1239 struct
1240 deduce_quat2< qvm_detail::roty_quat_<Angle>, qvm_detail::roty_quat_<Angle> >
1241 {
1242 typedef quat<Angle> type;
1243 };
1244
1245 template <class Angle>
1246 BOOST_QVM_INLINE_TRIVIAL
1247 qvm_detail::roty_quat_<Angle> const &
1248 roty_quat( Angle const & angle )
1249 {
1250 return reinterpret_cast<qvm_detail::roty_quat_<Angle> const &>(angle);
1251 }
1252
1253 template <class A,class Angle>
1254 BOOST_QVM_INLINE_OPERATIONS
1255 typename enable_if_c<
1256 is_quat<A>::value,
1257 void>::type
1258 set_roty( A & a, Angle angle )
1259 {
1260 assign(a,roty_quat(angle));
1261 }
1262
1263 template <class A,class Angle>
1264 BOOST_QVM_INLINE_OPERATIONS
1265 typename enable_if_c<
1266 is_quat<A>::value,
1267 void>::type
1268 rotate_y( A & a, Angle angle )
1269 {
1270 a *= roty_quat(angle);
1271 }
1272
1273 ////////////////////////////////////////////////
1274
1275 namespace
1276 qvm_detail
1277 {
1278 template <class T>
1279 struct
1280 rotz_quat_
1281 {
1282 BOOST_QVM_INLINE_TRIVIAL
1283 rotz_quat_()
1284 {
1285 }
1286
1287 template <class R>
1288 BOOST_QVM_INLINE_TRIVIAL
1289 operator R() const
1290 {
1291 R r;
1292 assign(r,*this);
1293 return r;
1294 }
1295
1296 private:
1297
1298 rotz_quat_( rotz_quat_ const & );
1299 rotz_quat_ & operator=( rotz_quat_ const & );
1300 ~rotz_quat_();
1301 };
1302
1303 template <int I>
1304 struct
1305 rotz_q_get
1306 {
1307 template <class T>
1308 static
1309 BOOST_QVM_INLINE_CRITICAL
1310 T
1311 get( T const & )
1312 {
1313 return scalar_traits<T>::value(0);
1314 }
1315 };
1316
1317 template <>
1318 struct
1319 rotz_q_get<3>
1320 {
1321 template <class T>
1322 static
1323 BOOST_QVM_INLINE_CRITICAL
1324 T
1325 get( T const & angle )
1326 {
1327 return sin<T>(angle/2);
1328 }
1329 };
1330
1331 template <>
1332 struct
1333 rotz_q_get<0>
1334 {
1335 template <class T>
1336 static
1337 BOOST_QVM_INLINE_CRITICAL
1338 T
1339 get( T const & angle )
1340 {
1341 return cos<T>(angle/2);
1342 }
1343 };
1344 }
1345
1346 template <class Angle>
1347 struct
1348 quat_traits< qvm_detail::rotz_quat_<Angle> >
1349 {
1350 typedef qvm_detail::rotz_quat_<Angle> this_quaternion;
1351 typedef Angle scalar_type;
1352
1353 template <int I>
1354 static
1355 BOOST_QVM_INLINE_CRITICAL
1356 scalar_type
1357 read_element( this_quaternion const & x )
1358 {
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));
1362 }
1363 };
1364
1365 template <class Angle>
1366 struct
1367 deduce_quat< qvm_detail::rotz_quat_<Angle> >
1368 {
1369 typedef quat<Angle> type;
1370 };
1371
1372 template <class Angle>
1373 struct
1374 deduce_quat2< qvm_detail::rotz_quat_<Angle>, qvm_detail::rotz_quat_<Angle> >
1375 {
1376 typedef quat<Angle> type;
1377 };
1378
1379 template <class Angle>
1380 BOOST_QVM_INLINE_TRIVIAL
1381 qvm_detail::rotz_quat_<Angle> const &
1382 rotz_quat( Angle const & angle )
1383 {
1384 return reinterpret_cast<qvm_detail::rotz_quat_<Angle> const &>(angle);
1385 }
1386
1387 template <class A,class Angle>
1388 BOOST_QVM_INLINE_OPERATIONS
1389 typename enable_if_c<
1390 is_quat<A>::value,
1391 void>::type
1392 set_rotz( A & a, Angle angle )
1393 {
1394 assign(a,rotz_quat(angle));
1395 }
1396
1397 template <class A,class Angle>
1398 BOOST_QVM_INLINE_OPERATIONS
1399 typename enable_if_c<
1400 is_quat<A>::value,
1401 void>::type
1402 rotate_z( A & a, Angle angle )
1403 {
1404 a *= rotz_quat(angle);
1405 }
1406
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 )
1413 {
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);
1419 if( a0>1 )
1420 {
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);
1425 a0/=s;
1426 a1/=s;
1427 a2/=s;
1428 a3/=s;
1429 }
1430 if( T s=sqrt<T>(1-a0*a0) )
1431 {
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;
1435 }
1436 else
1437 {
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);
1441 }
1442 return scalar_traits<T>::value(2) * qvm::acos(a0);
1443 }
1444
1445 ////////////////////////////////////////////////
1446
1447 namespace
1448 sfinae
1449 {
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;
1487 }
1488
1489 ////////////////////////////////////////////////
1490 }
1491 }
1492
1493 #endif