]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/qvm/include/boost/qvm/mat_operations.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / qvm / include / boost / qvm / mat_operations.hpp
CommitLineData
7c673cae
FG
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_4F915D9ED30A11DF962186E3DFD72085
7#define UUID_4F915D9ED30A11DF962186E3DFD72085
8
9#include <boost/qvm/mat_operations2.hpp>
10#include <boost/qvm/mat_operations3.hpp>
11#include <boost/qvm/mat_operations4.hpp>
12#include <boost/qvm/math.hpp>
13#include <boost/qvm/detail/determinant_impl.hpp>
14#include <boost/qvm/detail/cofactor_impl.hpp>
15#include <boost/qvm/detail/transp_impl.hpp>
16#include <boost/qvm/scalar_traits.hpp>
17#include <string>
18
19namespace
20boost
21 {
22 namespace
23 qvm
24 {
25 namespace
26 qvm_detail
27 {
28 BOOST_QVM_INLINE_CRITICAL
29 void const *
30 get_valid_ptr_mat_operations()
31 {
32 static int const obj=0;
33 return &obj;
34 }
35 }
36
37 ////////////////////////////////////////////////
38
39 namespace
40 qvm_to_string_detail
41 {
42 template <class T>
43 std::string to_string( T const & x );
44 }
45
46 namespace
47 qvm_detail
48 {
49 template <int R,int C>
50 struct
51 to_string_m_defined
52 {
53 static bool const value=false;
54 };
55
56 template <int I,int SizeMinusOne>
57 struct
58 to_string_matrix_elements
59 {
60 template <class A>
61 static
62 std::string
63 f( A const & a )
64 {
65 using namespace qvm_to_string_detail;
66 return
67 ( (I%mat_traits<A>::cols)==0 ? '(' : ',' ) +
68 to_string(mat_traits<A>::template read_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a)) +
69 ( (I%mat_traits<A>::cols)==mat_traits<A>::cols-1 ? ")" : "" ) +
70 to_string_matrix_elements<I+1,SizeMinusOne>::f(a);
71 }
72 };
73
74 template <int SizeMinusOne>
75 struct
76 to_string_matrix_elements<SizeMinusOne,SizeMinusOne>
77 {
78 template <class A>
79 static
80 std::string
81 f( A const & a )
82 {
83 using namespace qvm_to_string_detail;
84 return
85 ( (SizeMinusOne%mat_traits<A>::cols)==0 ? '(' : ',' ) +
86 to_string(mat_traits<A>::template read_element<SizeMinusOne/mat_traits<A>::cols,SizeMinusOne%mat_traits<A>::cols>(a)) +
87 ')';
88 }
89 };
90 }
91
92 template <class A>
93 inline
94 typename boost::enable_if_c<
95 is_mat<A>::value &&
96 !qvm_detail::to_string_m_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
97 std::string>::type
98 to_string( A const & a )
99 {
100 return "("+qvm_detail::to_string_matrix_elements<0,mat_traits<A>::rows*mat_traits<A>::cols-1>::f(a)+')';
101 }
102
103 ////////////////////////////////////////////////
104
105 namespace
106 qvm_detail
107 {
108 template <int M,int N>
109 struct
110 assign_mm_defined
111 {
112 static bool const value=false;
113 };
114
115 template <int I,int N>
116 struct
117 copy_matrix_elements
118 {
119 template <class A,class B>
120 static
121 BOOST_QVM_INLINE_CRITICAL
122 void
123 f( A & a, B const & b )
124 {
125 mat_traits<A>::template write_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a) =
126 mat_traits<B>::template read_element<I/mat_traits<B>::cols,I%mat_traits<B>::cols>(b);
127 copy_matrix_elements<I+1,N>::f(a,b);
128 }
129 };
130
131 template <int N>
132 struct
133 copy_matrix_elements<N,N>
134 {
135 template <class A,class B>
136 static
137 BOOST_QVM_INLINE_CRITICAL
138 void
139 f( A &, B const & )
140 {
141 }
142 };
143 }
144
145 template <class A,class B>
146 BOOST_QVM_INLINE_TRIVIAL
147 typename boost::enable_if_c<
148 is_mat<A>::value && is_mat<B>::value &&
149 mat_traits<A>::rows==mat_traits<B>::rows &&
150 mat_traits<A>::cols==mat_traits<B>::cols &&
151 !qvm_detail::assign_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
152 A &>::type
153 assign( A & a, B const & b )
154 {
155 qvm_detail::copy_matrix_elements<0,mat_traits<A>::rows*mat_traits<A>::cols>::f(a,b);
156 return a;
157 }
158
159 ////////////////////////////////////////////////
160
161 template <class A,class B,class Cmp>
162 BOOST_QVM_INLINE_OPERATIONS
163 typename enable_if_c<
164 is_mat<A>::value && is_mat<B>::value &&
165 mat_traits<A>::rows==mat_traits<B>::rows &&
166 mat_traits<A>::cols==mat_traits<B>::cols,
167 bool>::type
168 cmp( A const & a, B const & b, Cmp f )
169 {
170 typedef typename deduce_scalar<
171 typename mat_traits<A>::scalar_type,
172 typename mat_traits<B>::scalar_type>::type T;
173 int const rows=mat_traits<A>::rows;
174 int const cols=mat_traits<A>::cols;
175 T m1[rows][cols]; assign(m1,a);
176 T m2[rows][cols]; assign(m2,b);
177 for( int i=0; i!=rows; ++i )
178 for( int j=0; j!=cols; ++j )
179 if( !f(m1[i][j],m2[i][j]) )
180 return false;
181 return true;
182 }
183
184 ////////////////////////////////////////////////
185
186 namespace
187 qvm_detail
188 {
189 template <int M,int N>
190 struct
191 convert_to_m_defined
192 {
193 static bool const value=false;
194 };
195 }
196
197 template <class R,class A>
198 BOOST_QVM_INLINE_TRIVIAL
199 typename enable_if_c<
200 is_mat<R>::value && is_mat<A>::value &&
201 mat_traits<R>::rows==mat_traits<A>::rows &&
202 mat_traits<R>::cols==mat_traits<A>::cols &&
203 !qvm_detail::convert_to_m_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
204 R>::type
205 convert_to( A const & a )
206 {
207 R r; assign(r,a);
208 return r;
209 }
210
211 ////////////////////////////////////////////////
212
213 namespace
214 qvm_detail
215 {
216 template <int D>
217 struct
218 determinant_defined
219 {
220 static bool const value=false;
221 };
222 }
223
224 template <class A>
225 BOOST_QVM_INLINE_TRIVIAL
226 typename enable_if_c<
227 is_mat<A>::value &&
228 mat_traits<A>::rows==mat_traits<A>::cols &&
229 !qvm_detail::determinant_defined<mat_traits<A>::rows>::value,
230 typename mat_traits<A>::scalar_type>::type
231 determinant( A const & a )
232 {
233 return qvm_detail::determinant_impl(a);
234 }
235
236 ////////////////////////////////////////////////
237
238 namespace
239 qvm_detail
240 {
241 template <class T,int Dim>
242 class
243 identity_mat_
244 {
245 identity_mat_( identity_mat_ const & );
246 identity_mat_ & operator=( identity_mat_ const & );
247 ~identity_mat_();
248
249 public:
250
251 template <class R>
252 BOOST_QVM_INLINE_TRIVIAL
253 operator R() const
254 {
255 R r;
256 assign(r,*this);
257 return r;
258 }
259 };
260 }
261
262 template <class T,int Dim>
263 struct
264 mat_traits< qvm_detail::identity_mat_<T,Dim> >
265 {
266 typedef qvm_detail::identity_mat_<T,Dim> this_matrix;
267 typedef T scalar_type;
268 static int const rows=Dim;
269 static int const cols=Dim;
270
271 template <int Row,int Col>
272 static
273 BOOST_QVM_INLINE_CRITICAL
274 scalar_type
275 read_element( this_matrix const & x )
276 {
277 BOOST_QVM_STATIC_ASSERT(Row>=0);
278 BOOST_QVM_STATIC_ASSERT(Row<Dim);
279 BOOST_QVM_STATIC_ASSERT(Col>=0);
280 BOOST_QVM_STATIC_ASSERT(Col<Dim);
281 return scalar_traits<scalar_type>::value(Row==Col);
282 }
283
284 static
285 BOOST_QVM_INLINE_CRITICAL
286 scalar_type
287 read_element_idx( int row, int col, this_matrix const & x )
288 {
289 BOOST_QVM_ASSERT(row>=0);
290 BOOST_QVM_ASSERT(row<Dim);
291 BOOST_QVM_ASSERT(col>=0);
292 BOOST_QVM_ASSERT(col<Dim);
293 return scalar_traits<scalar_type>::value(row==col);
294 }
295 };
296
297 template <class T,int Dim>
298 BOOST_QVM_INLINE_TRIVIAL
299 qvm_detail::identity_mat_<T,Dim> const &
300 identity_mat()
301 {
302 return *(qvm_detail::identity_mat_<T,Dim> const *)qvm_detail::get_valid_ptr_mat_operations();
303 }
304
305 template <class A>
306 BOOST_QVM_INLINE_OPERATIONS
307 typename enable_if_c<
308 is_mat<A>::value &&
309 mat_traits<A>::rows==mat_traits<A>::cols,
310 void>::type
311 set_identity( A & a )
312 {
313 assign(a,identity_mat<typename mat_traits<A>::scalar_type,mat_traits<A>::rows>());
314 }
315
316 ////////////////////////////////////////////////
317
318 namespace
319 qvm_detail
320 {
321 template <class T>
322 struct
323 projection_
324 {
325 T const _00;
326 T const _11;
327 T const _22;
328 T const _23;
329 T const _32;
330
331 BOOST_QVM_INLINE_TRIVIAL
332 projection_( T _00, T _11, T _22, T _23, T _32 ):
333 _00(_00),
334 _11(_11),
335 _22(_22),
336 _23(_23),
337 _32(_32)
338 {
339 }
340
341 template <class R>
342 BOOST_QVM_INLINE_TRIVIAL
343 operator R() const
344 {
345 R r;
346 assign(r,*this);
347 return r;
348 }
349 };
350
351 template <int Row,int Col>
352 struct
353 projection_get
354 {
355 template <class T>
356 static
357 BOOST_QVM_INLINE_CRITICAL
358 T
359 get( projection_<T> const & )
360 {
361 return scalar_traits<T>::value(0);
362 }
363 };
364
365 template <> struct projection_get<0,0> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._00; } };
366 template <> struct projection_get<1,1> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._11; } };
367 template <> struct projection_get<2,2> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._22; } };
368 template <> struct projection_get<2,3> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._23; } };
369 template <> struct projection_get<3,2> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._32; } };
370 }
371
372 template <class T>
373 struct
374 mat_traits< qvm_detail::projection_<T> >
375 {
376 typedef qvm_detail::projection_<T> this_matrix;
377 typedef T scalar_type;
378 static int const rows=4;
379 static int const cols=4;
380
381 template <int Row,int Col>
382 static
383 BOOST_QVM_INLINE_CRITICAL
384 scalar_type
385 read_element( this_matrix const & x )
386 {
387 BOOST_QVM_STATIC_ASSERT(Row>=0);
388 BOOST_QVM_STATIC_ASSERT(Row<rows);
389 BOOST_QVM_STATIC_ASSERT(Col>=0);
390 BOOST_QVM_STATIC_ASSERT(Col<cols);
391 return qvm_detail::projection_get<Row,Col>::get(x);
392 }
393 };
394
395 template <class T>
396 qvm_detail::projection_<T>
397 BOOST_QVM_INLINE_OPERATIONS
398 perspective_lh( T fov_y, T aspect_ratio, T z_near, T z_far )
399 {
400 T const one = scalar_traits<T>::value(1);
401 T const ys = one/tan<T>(fov_y/scalar_traits<T>::value(2));
402 T const xs = ys/aspect_ratio;
403 T const zd = z_far-z_near;
404 T const z1 = z_far/zd;
405 T const z2 = -z_near*z1;
406 return qvm_detail::projection_<T>(xs,ys,z1,z2,one);
407 }
408
409 template <class T>
410 qvm_detail::projection_<T>
411 BOOST_QVM_INLINE_OPERATIONS
412 perspective_rh( T fov_y, T aspect_ratio, T z_near, T z_far )
413 {
414 T const one = scalar_traits<T>::value(1);
415 T const ys = one/tan<T>(fov_y/scalar_traits<T>::value(2));
416 T const xs = ys/aspect_ratio;
417 T const zd = z_near-z_far;
418 T const z1 = z_far/zd;
419 T const z2 = z_near*z1;
420 return qvm_detail::projection_<T>(xs,ys,z1,z2,-one);
421 }
422
423 ////////////////////////////////////////////////
424
425 namespace
426 qvm_detail
427 {
428 template <class OriginalType,class Scalar>
429 class
430 matrix_scalar_cast_
431 {
432 matrix_scalar_cast_( matrix_scalar_cast_ const & );
433 matrix_scalar_cast_ & operator=( matrix_scalar_cast_ const & );
434 ~matrix_scalar_cast_();
435
436 public:
437
438 template <class T>
439 BOOST_QVM_INLINE_TRIVIAL
440 matrix_scalar_cast_ &
441 operator=( T const & x )
442 {
443 assign(*this,x);
444 return *this;
445 }
446
447 template <class R>
448 BOOST_QVM_INLINE_TRIVIAL
449 operator R() const
450 {
451 R r;
452 assign(r,*this);
453 return r;
454 }
455 };
456
457 template <bool> struct scalar_cast_matrix_filter { };
458 template <> struct scalar_cast_matrix_filter<true> { typedef int type; };
459 }
460
461 template <class OriginalType,class Scalar>
462 struct
463 mat_traits< qvm_detail::matrix_scalar_cast_<OriginalType,Scalar> >
464 {
465 typedef Scalar scalar_type;
466 typedef qvm_detail::matrix_scalar_cast_<OriginalType,Scalar> this_matrix;
467 static int const rows=mat_traits<OriginalType>::rows;
468 static int const cols=mat_traits<OriginalType>::cols;
469
470 template <int Row,int Col>
471 static
472 BOOST_QVM_INLINE_CRITICAL
473 scalar_type
474 read_element( this_matrix const & x )
475 {
476 BOOST_QVM_STATIC_ASSERT(Row>=0);
477 BOOST_QVM_STATIC_ASSERT(Row<rows);
478 BOOST_QVM_STATIC_ASSERT(Col>=0);
479 BOOST_QVM_STATIC_ASSERT(Col<cols);
480 return scalar_type(mat_traits<OriginalType>::template read_element<Row,Col>(reinterpret_cast<OriginalType const &>(x)));
481 }
482
483 static
484 BOOST_QVM_INLINE_CRITICAL
485 scalar_type
486 read_element_idx( int row, int col, this_matrix const & x )
487 {
488 BOOST_QVM_ASSERT(row>=0);
489 BOOST_QVM_ASSERT(row<rows);
490 BOOST_QVM_ASSERT(col>=0);
491 BOOST_QVM_ASSERT(col<cols);
492 return scalar_type(mat_traits<OriginalType>::read_element_idx(col,row,reinterpret_cast<OriginalType const &>(x)));
493 }
494 };
495
496 template <class OriginalType,class Scalar,int R,int C>
497 struct
498 deduce_mat<qvm_detail::matrix_scalar_cast_<OriginalType,Scalar>,R,C>
499 {
500 typedef mat<Scalar,R,C> type;
501 };
502
503 template <class Scalar,class T>
504 BOOST_QVM_INLINE_TRIVIAL
505 qvm_detail::matrix_scalar_cast_<T,Scalar> const &
506 scalar_cast( T const & x, typename qvm_detail::scalar_cast_matrix_filter<is_mat<T>::value>::type=0 )
507 {
508 return reinterpret_cast<qvm_detail::matrix_scalar_cast_<T,Scalar> const &>(x);
509 }
510
511 ////////////////////////////////////////////////
512
513 namespace
514 qvm_detail
515 {
516 template <int M,int N>
517 struct
518 div_eq_ms_defined
519 {
520 static bool const value=false;
521 };
522 }
523
524 template <class A,class B>
525 BOOST_QVM_INLINE_OPERATIONS
526 typename enable_if_c<
527 is_mat<A>::value && is_scalar<B>::value &&
528 !qvm_detail::div_eq_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
529 A &>::type
530 operator/=( A & a, B b )
531 {
532 for( int i=0; i!=mat_traits<A>::rows; ++i )
533 for( int j=0; j!=mat_traits<A>::cols; ++j )
534 mat_traits<A>::write_element_idx(i,j,a)/=b;
535 return a;
536 }
537
538 ////////////////////////////////////////////////
539
540 namespace
541 qvm_detail
542 {
543 template <int M,int N>
544 struct
545 div_ms_defined
546 {
547 static bool const value=false;
548 };
549 }
550
551 template <class A,class B>
552 BOOST_QVM_INLINE_OPERATIONS
553 typename lazy_enable_if_c<
554 is_mat<A>::value && is_scalar<B>::value &&
555 !qvm_detail::div_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
556 deduce_mat<A> >::type
557 operator/( A const & a, B b )
558 {
559 typedef typename deduce_mat<A>::type R;
560 R r;
561 for( int i=0; i!=mat_traits<A>::rows; ++i )
562 for( int j=0; j!=mat_traits<A>::cols; ++j )
563 mat_traits<R>::write_element_idx(i,j,r)=mat_traits<A>::read_element_idx(i,j,a)/b;
564 return r;
565 }
566
567 ////////////////////////////////////////////////
568
569 namespace
570 qvm_detail
571 {
572 template <int M,int N>
573 struct
574 eq_mm_defined
575 {
576 static bool const value=false;
577 };
578 }
579
580 template <class A,class B>
581 BOOST_QVM_INLINE_OPERATIONS
582 typename enable_if_c<
583 is_mat<A>::value && is_mat<B>::value &&
584 mat_traits<A>::rows==mat_traits<B>::rows &&
585 mat_traits<A>::cols==mat_traits<B>::cols &&
586 !qvm_detail::eq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
587 bool>::type
588 operator==( A const & a, B const & b )
589 {
590 for( int i=0; i!=mat_traits<A>::rows; ++i )
591 for( int j=0; j!=mat_traits<A>::cols; ++j )
592 if( mat_traits<A>::read_element_idx(i,j,a)!=mat_traits<B>::read_element_idx(i,j,b) )
593 return false;
594 return true;
595 }
596
597 ////////////////////////////////////////////////
598
599 namespace
600 qvm_detail
601 {
602 template <int M,int N>
603 struct
604 minus_eq_mm_defined
605 {
606 static bool const value=false;
607 };
608 }
609
610 template <class A,class B>
611 BOOST_QVM_INLINE_OPERATIONS
612 typename enable_if_c<
613 is_mat<A>::value && is_mat<B>::value &&
614 mat_traits<A>::rows==mat_traits<B>::rows &&
615 mat_traits<A>::cols==mat_traits<B>::cols &&
616 !qvm_detail::minus_eq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
617 A &>::type
618 operator-=( A & a, B const & b )
619 {
620 for( int i=0; i!=mat_traits<A>::rows; ++i )
621 for( int j=0; j!=mat_traits<A>::cols; ++j )
622 mat_traits<A>::write_element_idx(i,j,a)-=mat_traits<B>::read_element_idx(i,j,b);
623 return a;
624 }
625
626 ////////////////////////////////////////////////
627
628 namespace
629 qvm_detail
630 {
631 template <int M,int N>
632 struct
633 minus_m_defined
634 {
635 static bool const value=false;
636 };
637 }
638
639 template <class A>
640 BOOST_QVM_INLINE_OPERATIONS
641 typename lazy_enable_if_c<
642 is_mat<A>::value &&
643 !qvm_detail::minus_m_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
644 deduce_mat<A> >::type
645 operator-( A const & a )
646 {
647 typedef typename deduce_mat<A>::type R;
648 R r;
649 for( int i=0; i!=mat_traits<A>::rows; ++i )
650 for( int j=0; j!=mat_traits<A>::cols; ++j )
651 mat_traits<R>::write_element_idx(i,j,r)=-mat_traits<A>::read_element_idx(i,j,a);
652 return r;
653 }
654
655 ////////////////////////////////////////////////
656
657 namespace
658 qvm_detail
659 {
660 template <int M,int N>
661 struct
662 minus_mm_defined
663 {
664 static bool const value=false;
665 };
666 }
667
668 template <class A,class B>
669 BOOST_QVM_INLINE_OPERATIONS
670 typename lazy_enable_if_c<
671 is_mat<A>::value && is_mat<B>::value &&
672 mat_traits<A>::rows==mat_traits<B>::rows &&
673 mat_traits<A>::cols==mat_traits<B>::cols &&
674 !qvm_detail::minus_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
675 deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
676 operator-( A const & a, B const & b )
677 {
678 typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
679 R r;
680 for( int i=0; i!=mat_traits<A>::rows; ++i )
681 for( int j=0; j!=mat_traits<A>::cols; ++j )
682 mat_traits<R>::write_element_idx(i,j,r)=mat_traits<A>::read_element_idx(i,j,a)-mat_traits<B>::read_element_idx(i,j,b);
683 return r;
684 }
685
686 ////////////////////////////////////////////////
687
688 namespace
689 qvm_detail
690 {
691 template <int D>
692 struct
693 mul_eq_mm_defined
694 {
695 static bool const value=false;
696 };
697 }
698
699 template <class A,class B>
700 BOOST_QVM_INLINE_OPERATIONS
701 typename enable_if_c<
702 is_mat<A>::value &&
703 is_mat<B>::value &&
704 mat_traits<A>::rows==mat_traits<A>::cols &&
705 mat_traits<A>::rows==mat_traits<B>::rows &&
706 mat_traits<A>::cols==mat_traits<B>::cols &&
707 !qvm_detail::mul_eq_mm_defined<mat_traits<A>::rows>::value,
708 A &>::type
709 operator*=( A & r, B const & b )
710 {
711 typedef typename mat_traits<A>::scalar_type Ta;
712 Ta a[mat_traits<A>::rows][mat_traits<A>::cols];
713 for( int i=0; i<mat_traits<A>::rows; ++i )
714 for( int j=0; j<mat_traits<B>::cols; ++j )
715 a[i][j]=mat_traits<A>::read_element_idx(i,j,r);
716 for( int i=0; i<mat_traits<A>::rows; ++i )
717 for( int j=0; j<mat_traits<B>::cols; ++j )
718 {
719 Ta x(scalar_traits<Ta>::value(0));
720 for( int k=0; k<mat_traits<A>::cols; ++k )
721 x += a[i][k]*mat_traits<B>::read_element_idx(k,j,b);
722 mat_traits<A>::write_element_idx(i,j,r) = x;
723 }
724 return r;
725 }
726
727 ////////////////////////////////////////////////
728
729 namespace
730 qvm_detail
731 {
732 template <int M,int N>
733 struct
734 mul_eq_ms_defined
735 {
736 static bool const value=false;
737 };
738 }
739
740 template <class A,class B>
741 BOOST_QVM_INLINE_OPERATIONS
742 typename enable_if_c<
743 is_mat<A>::value && is_scalar<B>::value &&
744 !qvm_detail::mul_eq_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
745 A &>::type
746 operator*=( A & a, B b )
747 {
748 for( int i=0; i!=mat_traits<A>::rows; ++i )
749 for( int j=0; j!=mat_traits<A>::cols; ++j )
750 mat_traits<A>::write_element_idx(i,j,a)*=b;
751 return a;
752 }
753
754 ////////////////////////////////////////////////
755
756 namespace
757 qvm_detail
758 {
759 template <int R,int CR,int C>
760 struct
761 mul_mm_defined
762 {
763 static bool const value=false;
764 };
765 }
766
767 template <class A,class B>
768 BOOST_QVM_INLINE_OPERATIONS
769 typename lazy_enable_if_c<
770 is_mat<A>::value && is_mat<B>::value &&
771 mat_traits<A>::cols==mat_traits<B>::rows &&
772 !qvm_detail::mul_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols,mat_traits<B>::cols>::value,
773 deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<B>::cols> >::type
774 operator*( A const & a, B const & b )
775 {
776 typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<B>::cols>::type R;
777 R r;
778 for( int i=0; i<mat_traits<A>::rows; ++i )
779 for( int j=0; j<mat_traits<B>::cols; ++j )
780 {
781 typedef typename mat_traits<A>::scalar_type Ta;
782 Ta x(scalar_traits<Ta>::value(0));
783 for( int k=0; k<mat_traits<A>::cols; ++k )
784 x += mat_traits<A>::read_element_idx(i,k,a)*mat_traits<B>::read_element_idx(k,j,b);
785 mat_traits<R>::write_element_idx(i,j,r) = x;
786 }
787 return r;
788 }
789
790 ////////////////////////////////////////////////
791
792 namespace
793 qvm_detail
794 {
795 template <int M,int N>
796 struct
797 mul_ms_defined
798 {
799 static bool const value=false;
800 };
801 }
802
803 template <class A,class B>
804 BOOST_QVM_INLINE_OPERATIONS
805 typename lazy_enable_if_c<
806 is_mat<A>::value && is_scalar<B>::value &&
807 !qvm_detail::mul_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
808 deduce_mat<A> >::type
809 operator*( A const & a, B b )
810 {
811 typedef typename deduce_mat<A>::type R;
812 R r;
813 for( int i=0; i!=mat_traits<A>::rows; ++i )
814 for( int j=0; j!=mat_traits<A>::cols; ++j )
815 mat_traits<R>::write_element_idx(i,j,r)=mat_traits<A>::read_element_idx(i,j,a)*b;
816 return r;
817 }
818
819 ////////////////////////////////////////////////
820
821 namespace
822 qvm_detail
823 {
824 template <int M,int N>
825 struct
826 neq_mm_defined
827 {
828 static bool const value=false;
829 };
830 }
831
832 template <class A,class B>
833 BOOST_QVM_INLINE_OPERATIONS
834 typename enable_if_c<
835 is_mat<A>::value && is_mat<B>::value &&
836 mat_traits<A>::rows==mat_traits<B>::rows &&
837 mat_traits<A>::cols==mat_traits<B>::cols &&
838 !qvm_detail::neq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
839 bool>::type
840 operator!=( A const & a, B const & b )
841 {
842 for( int i=0; i!=mat_traits<A>::rows; ++i )
843 for( int j=0; j!=mat_traits<A>::cols; ++j )
844 if( mat_traits<A>::read_element_idx(i,j,a)!=mat_traits<B>::read_element_idx(i,j,b) )
845 return true;
846 return false;
847 }
848
849 ////////////////////////////////////////////////
850
851 namespace
852 qvm_detail
853 {
854 template <int M,int N>
855 struct
856 plus_eq_mm_defined
857 {
858 static bool const value=false;
859 };
860 }
861
862 template <class A,class B>
863 BOOST_QVM_INLINE_OPERATIONS
864 typename enable_if_c<
865 is_mat<A>::value && is_mat<B>::value &&
866 mat_traits<A>::rows==mat_traits<B>::rows &&
867 mat_traits<A>::cols==mat_traits<B>::cols &&
868 !qvm_detail::plus_eq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
869 A &>::type
870 operator+=( A & a, B const & b )
871 {
872 for( int i=0; i!=mat_traits<A>::rows; ++i )
873 for( int j=0; j!=mat_traits<A>::cols; ++j )
874 mat_traits<A>::write_element_idx(i,j,a)+=mat_traits<B>::read_element_idx(i,j,b);
875 return a;
876 }
877
878 ////////////////////////////////////////////////
879
880 namespace
881 qvm_detail
882 {
883 template <int M,int N>
884 struct
885 plus_mm_defined
886 {
887 static bool const value=false;
888 };
889 }
890
891 template <class A,class B>
892 BOOST_QVM_INLINE_OPERATIONS
893 typename lazy_enable_if_c<
894 is_mat<A>::value && is_mat<B>::value &&
895 mat_traits<A>::rows==mat_traits<B>::rows &&
896 mat_traits<A>::cols==mat_traits<B>::cols &&
897 !qvm_detail::plus_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
898 deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
899 operator+( A const & a, B const & b )
900 {
901 typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
902 R r;
903 for( int i=0; i!=mat_traits<A>::rows; ++i )
904 for( int j=0; j!=mat_traits<A>::cols; ++j )
905 mat_traits<R>::write_element_idx(i,j,r)=mat_traits<A>::read_element_idx(i,j,a)+mat_traits<B>::read_element_idx(i,j,b);
906 return r;
907 }
908
909 ////////////////////////////////////////////////
910
911 namespace
912 qvm_detail
913 {
914 template <class T>
915 class
916 mref_
917 {
918 mref_( mref_ const & );
919 mref_ & operator=( mref_ const & );
920 ~mref_();
921
922 public:
923
924 template <class R>
925 BOOST_QVM_INLINE_TRIVIAL
926 mref_ &
927 operator=( R const & x )
928 {
929 assign(*this,x);
930 return *this;
931 }
932
933 template <class R>
934 BOOST_QVM_INLINE_TRIVIAL
935 operator R() const
936 {
937 R r;
938 assign(r,*this);
939 return r;
940 }
941 };
942 }
943
944 template <class M>
945 struct
946 mat_traits< qvm_detail::mref_<M> >
947 {
948 typedef typename mat_traits<M>::scalar_type scalar_type;
949 typedef qvm_detail::mref_<M> this_matrix;
950 static int const rows=mat_traits<M>::rows;
951 static int const cols=mat_traits<M>::cols;
952
953 template <int Row,int Col>
954 static
955 BOOST_QVM_INLINE_CRITICAL
956 scalar_type
957 read_element( this_matrix const & x )
958 {
959 BOOST_QVM_STATIC_ASSERT(Row>=0);
960 BOOST_QVM_STATIC_ASSERT(Row<rows);
961 BOOST_QVM_STATIC_ASSERT(Col>=0);
962 BOOST_QVM_STATIC_ASSERT(Col<cols);
963 return mat_traits<M>::template read_element<Row,Col>(reinterpret_cast<M const &>(x));
964 }
965
966 template <int Row,int Col>
967 static
968 BOOST_QVM_INLINE_CRITICAL
969 scalar_type &
970 write_element( this_matrix & x )
971 {
972 BOOST_QVM_STATIC_ASSERT(Row>=0);
973 BOOST_QVM_STATIC_ASSERT(Row<rows);
974 BOOST_QVM_STATIC_ASSERT(Col>=0);
975 BOOST_QVM_STATIC_ASSERT(Col<cols);
976 return mat_traits<M>::template write_element<Row,Col>(reinterpret_cast<M &>(x));
977 }
978
979 static
980 BOOST_QVM_INLINE_CRITICAL
981 scalar_type
982 read_element_idx( int row, int col, this_matrix const & x )
983 {
984 BOOST_QVM_ASSERT(row>=0);
985 BOOST_QVM_ASSERT(row<rows);
986 BOOST_QVM_ASSERT(col>=0);
987 BOOST_QVM_ASSERT(col<cols);
988 return mat_traits<M>::read_element_idx(row,col,reinterpret_cast<M const &>(x));
989 }
990
991 static
992 BOOST_QVM_INLINE_CRITICAL
993 scalar_type &
994 write_element_idx( int row, int col, this_matrix & x )
995 {
996 BOOST_QVM_ASSERT(row>=0);
997 BOOST_QVM_ASSERT(row<rows);
998 BOOST_QVM_ASSERT(col>=0);
999 BOOST_QVM_ASSERT(col<cols);
1000 return mat_traits<M>::write_element_idx(row,col,reinterpret_cast<M &>(x));
1001 }
1002 };
1003
1004 template <class M,int R,int C>
1005 struct
1006 deduce_mat<qvm_detail::mref_<M>,R,C>
1007 {
1008 typedef mat<typename mat_traits<M>::scalar_type,R,C> type;
1009 };
1010
1011 template <class M>
1012 BOOST_QVM_INLINE_TRIVIAL
1013 typename enable_if_c<
1014 is_mat<M>::value,
1015 qvm_detail::mref_<M> const &>::type
1016 mref( M const & a )
1017 {
1018 return reinterpret_cast<qvm_detail::mref_<M> const &>(a);
1019 }
1020
1021 template <class M>
1022 BOOST_QVM_INLINE_TRIVIAL
1023 typename enable_if_c<
1024 is_mat<M>::value,
1025 qvm_detail::mref_<M> &>::type
1026 mref( M & a )
1027 {
1028 return reinterpret_cast<qvm_detail::mref_<M> &>(a);
1029 }
1030
1031 ////////////////////////////////////////////////
1032
1033 namespace
1034 qvm_detail
1035 {
1036 template <class T,int Rows,int Cols>
1037 class
1038 zero_mat_
1039 {
1040 zero_mat_( zero_mat_ const & );
1041 zero_mat_ & operator=( zero_mat_ const & );
1042 ~zero_mat_();
1043
1044 public:
1045
1046 template <class R>
1047 BOOST_QVM_INLINE_TRIVIAL
1048 operator R() const
1049 {
1050 R r;
1051 assign(r,*this);
1052 return r;
1053 }
1054 };
1055 }
1056
1057 template <class T,int Rows,int Cols>
1058 struct
1059 mat_traits< qvm_detail::zero_mat_<T,Rows,Cols> >
1060 {
1061 typedef qvm_detail::zero_mat_<T,Rows,Cols> this_matrix;
1062 typedef T scalar_type;
1063 static int const rows=Rows;
1064 static int const cols=Cols;
1065
1066 template <int Row,int Col>
1067 static
1068 BOOST_QVM_INLINE_CRITICAL
1069 scalar_type
1070 read_element( this_matrix const & x )
1071 {
1072 BOOST_QVM_STATIC_ASSERT(Row>=0);
1073 BOOST_QVM_STATIC_ASSERT(Row<Rows);
1074 BOOST_QVM_STATIC_ASSERT(Col>=0);
1075 BOOST_QVM_STATIC_ASSERT(Col<Cols);
1076 return scalar_traits<scalar_type>::value(0);
1077 }
1078
1079 static
1080 BOOST_QVM_INLINE_CRITICAL
1081 scalar_type
1082 read_element_idx( int row, int col, this_matrix const & x )
1083 {
1084 BOOST_QVM_ASSERT(row>=0);
1085 BOOST_QVM_ASSERT(row<rows);
1086 BOOST_QVM_ASSERT(col>=0);
1087 BOOST_QVM_ASSERT(col<cols);
1088 return scalar_traits<scalar_type>::value(0);
1089 }
1090 };
1091
1092 template <class T,int Rows,int Cols,int R,int C>
1093 struct
1094 deduce_mat<qvm_detail::zero_mat_<T,Rows,Cols>,R,C>
1095 {
1096 typedef mat<T,R,C> type;
1097 };
1098
1099 template <class T,int Rows,int Cols>
1100 BOOST_QVM_INLINE_TRIVIAL
1101 qvm_detail::zero_mat_<T,Rows,Cols> const &
1102 zero_mat()
1103 {
1104 return *(qvm_detail::zero_mat_<T,Rows,Cols> const *)qvm_detail::get_valid_ptr_mat_operations();
1105 }
1106
1107 template <class T,int Dim>
1108 BOOST_QVM_INLINE_TRIVIAL
1109 qvm_detail::zero_mat_<T,Dim,Dim> const &
1110 zero_mat()
1111 {
1112 return *(qvm_detail::zero_mat_<T,Dim,Dim> const *)qvm_detail::get_valid_ptr_mat_operations();
1113 }
1114
1115 template <class A>
1116 BOOST_QVM_INLINE_OPERATIONS
1117 typename enable_if_c<
1118 is_mat<A>::value,
1119 void>::type
1120 set_zero( A & a )
1121 {
1122 assign(a,zero_mat<typename mat_traits<A>::scalar_type,mat_traits<A>::rows,mat_traits<A>::cols>());
1123 }
1124
1125 ////////////////////////////////////////////////
1126
1127 namespace
1128 qvm_detail
1129 {
1130 template <int D,class V>
1131 struct
1132 rot_mat_
1133 {
1134 typedef typename vec_traits<V>::scalar_type scalar_type;
1135 scalar_type a[3][3];
1136
1137 template <class Angle>
1138 BOOST_QVM_INLINE
1139 rot_mat_( V const & axis, Angle angle )
1140 {
1141 scalar_type const x=vec_traits<V>::template read_element<0>(axis);
1142 scalar_type const y=vec_traits<V>::template read_element<1>(axis);
1143 scalar_type const z=vec_traits<V>::template read_element<2>(axis);
1144 scalar_type const m2=x*x+y*y+z*z;
1145 if( m2==scalar_traits<scalar_type>::value(0) )
1146 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
1147 scalar_type const s = sin<Angle>(angle);
1148 scalar_type const c = cos<Angle>(angle);
1149 scalar_type const x2 = x*x;
1150 scalar_type const y2 = y*y;
1151 scalar_type const z2 = z*z;
1152 scalar_type const xy = x*y;
1153 scalar_type const xz = x*z;
1154 scalar_type const yz = y*z;
1155 scalar_type const xs = x*s;
1156 scalar_type const ys = y*s;
1157 scalar_type const zs = z*s;
1158 scalar_type const one = scalar_traits<scalar_type>::value(1);
1159 scalar_type const c1 = one-c;
1160 a[0][0] = x2+(one-x2)*c;
1161 a[0][1] = xy*c1-zs;
1162 a[0][2] = xz*(one-c)+ys;
1163 a[1][0] = xy*c1+zs;
1164 a[1][1] = y2+(one-y2)*c;
1165 a[1][2] = yz*c1-xs;
1166 a[2][0] = xz*c1-ys;
1167 a[2][1] = yz*c1+xs;
1168 a[2][2] = z2+(one-z2)*c;
1169 }
1170
1171 template <class R>
1172 BOOST_QVM_INLINE_TRIVIAL
1173 operator R() const
1174 {
1175 R r;
1176 assign(r,*this);
1177 return r;
1178 }
1179 };
1180
1181 template <int Row,int Col>
1182 struct
1183 rot_m_get
1184 {
1185 template <class T>
1186 static
1187 BOOST_QVM_INLINE_CRITICAL
1188 T
1189 get( T const (&)[3][3] )
1190 {
1191 return scalar_traits<T>::value(Row==Col);
1192 }
1193 };
1194
1195 template <> struct rot_m_get<0,0> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[0][0]; } };
1196 template <> struct rot_m_get<0,1> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[0][1]; } };
1197 template <> struct rot_m_get<0,2> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[0][2]; } };
1198 template <> struct rot_m_get<1,0> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[1][0]; } };
1199 template <> struct rot_m_get<1,1> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[1][1]; } };
1200 template <> struct rot_m_get<1,2> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[1][2]; } };
1201 template <> struct rot_m_get<2,0> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[2][0]; } };
1202 template <> struct rot_m_get<2,1> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[2][1]; } };
1203 template <> struct rot_m_get<2,2> { template <class T> static BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[2][2]; } };
1204 }
1205
1206 template <class M>
1207 struct mat_traits;
1208
1209 template <int D,class V>
1210 struct
1211 mat_traits< qvm_detail::rot_mat_<D,V> >
1212 {
1213 typedef qvm_detail::rot_mat_<D,V> this_matrix;
1214 typedef typename this_matrix::scalar_type scalar_type;
1215 static int const rows=D;
1216 static int const cols=D;
1217
1218 template <int Row,int Col>
1219 static
1220 BOOST_QVM_INLINE_CRITICAL
1221 scalar_type
1222 read_element( this_matrix const & x )
1223 {
1224 BOOST_QVM_STATIC_ASSERT(Row>=0);
1225 BOOST_QVM_STATIC_ASSERT(Row<D);
1226 BOOST_QVM_STATIC_ASSERT(Col>=0);
1227 BOOST_QVM_STATIC_ASSERT(Col<D);
1228 return qvm_detail::rot_m_get<Row,Col>::get(x.a);
1229 }
1230
1231 static
1232 BOOST_QVM_INLINE_CRITICAL
1233 scalar_type
1234 read_element_idx( int row, int col, this_matrix const & x )
1235 {
1236 BOOST_QVM_ASSERT(row>=0);
1237 BOOST_QVM_ASSERT(row<D);
1238 BOOST_QVM_ASSERT(col>=0);
1239 BOOST_QVM_ASSERT(col<D);
1240 return row<3 && col<3?
1241 x.a[row][col] :
1242 scalar_traits<scalar_type>::value(row==col);
1243 }
1244 };
1245
1246 template <int Dim,class A,class Angle>
1247 BOOST_QVM_INLINE
1248 typename enable_if_c<
1249 is_vec<A>::value && vec_traits<A>::dim==3,
1250 qvm_detail::rot_mat_<Dim,A> >::type
1251 rot_mat( A const & axis, Angle angle )
1252 {
1253 return qvm_detail::rot_mat_<Dim,A>(axis,angle);
1254 }
1255
1256 template <class A,class B,class Angle>
1257 BOOST_QVM_INLINE_OPERATIONS
1258 typename enable_if_c<
1259 is_mat<A>::value &&
1260 mat_traits<A>::rows==mat_traits<A>::cols &&
1261 mat_traits<A>::rows>=3 &&
1262 is_vec<B>::value && vec_traits<B>::dim==3,
1263 void>::type
1264 set_rot( A & a, B const & axis, Angle angle )
1265 {
1266 assign(a,rot_mat<mat_traits<A>::rows>(axis,angle));
1267 }
1268
1269 template <class A,class B,class Angle>
1270 BOOST_QVM_INLINE_OPERATIONS
1271 typename enable_if_c<
1272 is_mat<A>::value &&
1273 mat_traits<A>::rows==mat_traits<A>::cols &&
1274 mat_traits<A>::rows>=3 &&
1275 is_vec<B>::value && vec_traits<B>::dim==3,
1276 void>::type
1277 rotate( A & a, B const & axis, Angle angle )
1278 {
1279 a *= rot_mat<mat_traits<A>::rows>(axis,angle);
1280 }
1281
1282 ////////////////////////////////////////////////
1283
1284 namespace
1285 qvm_detail
1286 {
1287 template <int Dim,class Angle>
1288 struct
1289 rotx_mat_
1290 {
1291 BOOST_QVM_INLINE_TRIVIAL
1292 rotx_mat_()
1293 {
1294 }
1295
1296 template <class R>
1297 BOOST_QVM_INLINE_TRIVIAL
1298 operator R() const
1299 {
1300 R r;
1301 assign(r,*this);
1302 return r;
1303 }
1304
1305 private:
1306
1307 rotx_mat_( rotx_mat_ const & );
1308 rotx_mat_ & operator=( rotx_mat_ const & );
1309 ~rotx_mat_();
1310 };
1311
1312 template <int Row,int Col>
1313 struct
1314 rotx_m_get
1315 {
1316 template <class T>
1317 static
1318 BOOST_QVM_INLINE_CRITICAL
1319 T
1320 get( T const & )
1321 {
1322 return scalar_traits<T>::value(Row==Col);
1323 }
1324 };
1325
1326 template <>
1327 struct
1328 rotx_m_get<1,1>
1329 {
1330 template <class T>
1331 static
1332 BOOST_QVM_INLINE_CRITICAL
1333 T
1334 get( T const & angle )
1335 {
1336 return cos<T>(angle);
1337 }
1338 };
1339
1340 template <>
1341 struct
1342 rotx_m_get<1,2>
1343 {
1344 template <class T>
1345 static
1346 BOOST_QVM_INLINE_CRITICAL
1347 T
1348 get( T const & angle )
1349 {
1350 return -sin<T>(angle);
1351 }
1352 };
1353
1354 template <>
1355 struct
1356 rotx_m_get<2,1>
1357 {
1358 template <class T>
1359 static
1360 BOOST_QVM_INLINE_CRITICAL
1361 T
1362 get( T const & angle )
1363 {
1364 return sin<T>(angle);
1365 }
1366 };
1367
1368 template <>
1369 struct
1370 rotx_m_get<2,2>
1371 {
1372 template <class T>
1373 static
1374 BOOST_QVM_INLINE_CRITICAL
1375 T
1376 get( T const & angle )
1377 {
1378 return cos<T>(angle);
1379 }
1380 };
1381 }
1382
1383 template <int Dim,class Angle>
1384 struct
1385 mat_traits< qvm_detail::rotx_mat_<Dim,Angle> >
1386 {
1387 typedef qvm_detail::rotx_mat_<Dim,Angle> this_matrix;
1388 typedef Angle scalar_type;
1389 static int const rows=Dim;
1390 static int const cols=Dim;
1391
1392 template <int Row,int Col>
1393 static
1394 BOOST_QVM_INLINE_CRITICAL
1395 scalar_type
1396 read_element( this_matrix const & x )
1397 {
1398 BOOST_QVM_STATIC_ASSERT(Row>=0);
1399 BOOST_QVM_STATIC_ASSERT(Col>=0);
1400 BOOST_QVM_STATIC_ASSERT(Row<Dim);
1401 BOOST_QVM_STATIC_ASSERT(Col<Dim);
1402 return qvm_detail::rotx_m_get<Row,Col>::get(reinterpret_cast<Angle const &>(x));
1403 }
1404
1405 static
1406 BOOST_QVM_INLINE_CRITICAL
1407 scalar_type
1408 read_element_idx( int row, int col, this_matrix const & x )
1409 {
1410 BOOST_QVM_ASSERT(row>=0);
1411 BOOST_QVM_ASSERT(col>=0);
1412 BOOST_QVM_ASSERT(row<Dim);
1413 BOOST_QVM_ASSERT(col<Dim);
1414 Angle const & a=reinterpret_cast<Angle const &>(x);
1415 if( row==1 )
1416 {
1417 if( col==1 )
1418 return cos<scalar_type>(a);
1419 if( col==2 )
1420 return -sin<scalar_type>(a);
1421 }
1422 if( row==2 )
1423 {
1424 if( col==1 )
1425 return sin<scalar_type>(a);
1426 if( col==2 )
1427 return cos<scalar_type>(a);
1428 }
1429 return scalar_traits<scalar_type>::value(row==col);
1430 }
1431 };
1432
1433 template <int Dim,class Angle>
1434 struct
1435 deduce_mat<qvm_detail::rotx_mat_<Dim,Angle>,Dim,Dim>
1436 {
1437 typedef mat<Angle,Dim,Dim> type;
1438 };
1439
1440 template <int Dim,class Angle>
1441 struct
1442 deduce_mat2<qvm_detail::rotx_mat_<Dim,Angle>,qvm_detail::rotx_mat_<Dim,Angle>,Dim,Dim>
1443 {
1444 typedef mat<Angle,Dim,Dim> type;
1445 };
1446
1447 template <int Dim,class Angle>
1448 BOOST_QVM_INLINE_TRIVIAL
1449 qvm_detail::rotx_mat_<Dim,Angle> const &
1450 rotx_mat( Angle const & angle )
1451 {
1452 BOOST_QVM_STATIC_ASSERT(Dim>=3);
1453 return reinterpret_cast<qvm_detail::rotx_mat_<Dim,Angle> const &>(angle);
1454 }
1455
1456 template <class A,class Angle>
1457 BOOST_QVM_INLINE_OPERATIONS
1458 typename enable_if_c<
1459 is_mat<A>::value &&
1460 mat_traits<A>::rows>=3 &&
1461 mat_traits<A>::rows==mat_traits<A>::cols,
1462 void>::type
1463 set_rotx( A & a, Angle angle )
1464 {
1465 assign(a,rotx_mat<mat_traits<A>::rows>(angle));
1466 }
1467
1468 template <class A,class Angle>
1469 BOOST_QVM_INLINE_OPERATIONS
1470 typename enable_if_c<
1471 is_mat<A>::value &&
1472 mat_traits<A>::rows>=3 &&
1473 mat_traits<A>::rows==mat_traits<A>::cols,
1474 void>::type
1475 rotate_x( A & a, Angle angle )
1476 {
1477 a *= rotx_mat<mat_traits<A>::rows>(angle);
1478 }
1479
1480 ////////////////////////////////////////////////
1481
1482 namespace
1483 qvm_detail
1484 {
1485 template <int Dim,class Angle>
1486 struct
1487 roty_mat_
1488 {
1489 BOOST_QVM_INLINE_TRIVIAL
1490 roty_mat_()
1491 {
1492 }
1493
1494 template <class R>
1495 BOOST_QVM_INLINE_TRIVIAL
1496 operator R() const
1497 {
1498 R r;
1499 assign(r,*this);
1500 return r;
1501 }
1502
1503 private:
1504
1505 roty_mat_( roty_mat_ const & );
1506 roty_mat_ & operator=( roty_mat_ const & );
1507 ~roty_mat_();
1508 };
1509
1510 template <int Row,int Col>
1511 struct
1512 roty_m_get
1513 {
1514 template <class T>
1515 static
1516 BOOST_QVM_INLINE_CRITICAL
1517 T
1518 get( T const & )
1519 {
1520 return scalar_traits<T>::value(Row==Col);
1521 }
1522 };
1523
1524 template <>
1525 struct
1526 roty_m_get<0,0>
1527 {
1528 template <class T>
1529 static
1530 BOOST_QVM_INLINE_CRITICAL
1531 T
1532 get( T const & angle )
1533 {
1534 return cos<T>(angle);
1535 }
1536 };
1537
1538 template <>
1539 struct
1540 roty_m_get<0,2>
1541 {
1542 template <class T>
1543 static
1544 BOOST_QVM_INLINE_CRITICAL
1545 T
1546 get( T const & angle )
1547 {
1548 return sin<T>(angle);
1549 }
1550 };
1551
1552 template <>
1553 struct
1554 roty_m_get<2,0>
1555 {
1556 template <class T>
1557 static
1558 BOOST_QVM_INLINE_CRITICAL
1559 T
1560 get( T const & angle )
1561 {
1562 return -sin<T>(angle);
1563 }
1564 };
1565
1566 template <>
1567 struct
1568 roty_m_get<2,2>
1569 {
1570 template <class T>
1571 static
1572 BOOST_QVM_INLINE_CRITICAL
1573 T
1574 get( T const & angle )
1575 {
1576 return cos<T>(angle);
1577 }
1578 };
1579 }
1580
1581 template <int Dim,class Angle>
1582 struct
1583 mat_traits< qvm_detail::roty_mat_<Dim,Angle> >
1584 {
1585 typedef qvm_detail::roty_mat_<Dim,Angle> this_matrix;
1586 typedef Angle scalar_type;
1587 static int const rows=Dim;
1588 static int const cols=Dim;
1589
1590 template <int Row,int Col>
1591 static
1592 BOOST_QVM_INLINE_CRITICAL
1593 scalar_type
1594 read_element( this_matrix const & x )
1595 {
1596 BOOST_QVM_STATIC_ASSERT(Row>=0);
1597 BOOST_QVM_STATIC_ASSERT(Col>=0);
1598 BOOST_QVM_STATIC_ASSERT(Row<Dim);
1599 BOOST_QVM_STATIC_ASSERT(Col<Dim);
1600 return qvm_detail::roty_m_get<Row,Col>::get(reinterpret_cast<Angle const &>(x));
1601 }
1602
1603 static
1604 BOOST_QVM_INLINE_CRITICAL
1605 scalar_type
1606 read_element_idx( int row, int col, this_matrix const & x )
1607 {
1608 BOOST_QVM_ASSERT(row>=0);
1609 BOOST_QVM_ASSERT(col>=0);
1610 BOOST_QVM_ASSERT(row<Dim);
1611 BOOST_QVM_ASSERT(col<Dim);
1612 Angle const & a=reinterpret_cast<Angle const &>(x);
1613 if( row==0 )
1614 {
1615 if( col==0 )
1616 return cos<scalar_type>(a);
1617 if( col==2 )
1618 return sin<scalar_type>(a);
1619 }
1620 if( row==2 )
1621 {
1622 if( col==0 )
1623 return -sin<scalar_type>(a);
1624 if( col==2 )
1625 return cos<scalar_type>(a);
1626 }
1627 return scalar_traits<scalar_type>::value(row==col);
1628 }
1629 };
1630
1631 template <int Dim,class Angle>
1632 struct
1633 deduce_mat<qvm_detail::roty_mat_<Dim,Angle>,Dim,Dim>
1634 {
1635 typedef mat<Angle,Dim,Dim> type;
1636 };
1637
1638 template <int Dim,class Angle>
1639 struct
1640 deduce_mat2<qvm_detail::roty_mat_<Dim,Angle>,qvm_detail::roty_mat_<Dim,Angle>,Dim,Dim>
1641 {
1642 typedef mat<Angle,Dim,Dim> type;
1643 };
1644
1645 template <int Dim,class Angle>
1646 BOOST_QVM_INLINE_TRIVIAL
1647 qvm_detail::roty_mat_<Dim,Angle> const &
1648 roty_mat( Angle const & angle )
1649 {
1650 BOOST_QVM_STATIC_ASSERT(Dim>=3);
1651 return reinterpret_cast<qvm_detail::roty_mat_<Dim,Angle> const &>(angle);
1652 }
1653
1654 template <class A,class Angle>
1655 BOOST_QVM_INLINE_OPERATIONS
1656 typename enable_if_c<
1657 is_mat<A>::value &&
1658 mat_traits<A>::rows>=2 &&
1659 mat_traits<A>::rows==mat_traits<A>::cols,
1660 void>::type
1661 set_roty( A & a, Angle angle )
1662 {
1663 assign(a,roty_mat<mat_traits<A>::rows>(angle));
1664 }
1665
1666 template <class A,class Angle>
1667 BOOST_QVM_INLINE_OPERATIONS
1668 typename enable_if_c<
1669 is_mat<A>::value &&
1670 mat_traits<A>::rows>=3 &&
1671 mat_traits<A>::rows==mat_traits<A>::cols,
1672 void>::type
1673 rotate_y( A & a, Angle angle )
1674 {
1675 a *= roty_mat<mat_traits<A>::rows>(angle);
1676 }
1677
1678 ////////////////////////////////////////////////
1679
1680 namespace
1681 qvm_detail
1682 {
1683 template <int Dim,class Angle>
1684 struct
1685 rotz_mat_
1686 {
1687 BOOST_QVM_INLINE_TRIVIAL
1688 rotz_mat_()
1689 {
1690 }
1691
1692 template <class R>
1693 BOOST_QVM_INLINE_TRIVIAL
1694 operator R() const
1695 {
1696 R r;
1697 assign(r,*this);
1698 return r;
1699 }
1700
1701 private:
1702
1703 rotz_mat_( rotz_mat_ const & );
1704 rotz_mat_ & operator=( rotz_mat_ const & );
1705 ~rotz_mat_();
1706 };
1707
1708 template <int Row,int Col>
1709 struct
1710 rotz_m_get
1711 {
1712 template <class T>
1713 static
1714 BOOST_QVM_INLINE_CRITICAL
1715 T
1716 get( T const & )
1717 {
1718 return scalar_traits<T>::value(Row==Col);
1719 }
1720 };
1721
1722 template <>
1723 struct
1724 rotz_m_get<0,0>
1725 {
1726 template <class T>
1727 static
1728 BOOST_QVM_INLINE_CRITICAL
1729 T
1730 get( T const & angle )
1731 {
1732 return cos<T>(angle);
1733 }
1734 };
1735
1736 template <>
1737 struct
1738 rotz_m_get<0,1>
1739 {
1740 template <class T>
1741 static
1742 BOOST_QVM_INLINE_CRITICAL
1743 T
1744 get( T const & angle )
1745 {
1746 return -sin<T>(angle);
1747 }
1748 };
1749
1750 template <>
1751 struct
1752 rotz_m_get<1,0>
1753 {
1754 template <class T>
1755 static
1756 BOOST_QVM_INLINE_CRITICAL
1757 T
1758 get( T const & angle )
1759 {
1760 return sin<T>(angle);
1761 }
1762 };
1763
1764 template <>
1765 struct
1766 rotz_m_get<1,1>
1767 {
1768 template <class T>
1769 static
1770 BOOST_QVM_INLINE_CRITICAL
1771 T
1772 get( T const & angle )
1773 {
1774 return cos<T>(angle);
1775 }
1776 };
1777 }
1778
1779 template <int Dim,class Angle>
1780 struct
1781 mat_traits< qvm_detail::rotz_mat_<Dim,Angle> >
1782 {
1783 typedef qvm_detail::rotz_mat_<Dim,Angle> this_matrix;
1784 typedef Angle scalar_type;
1785 static int const rows=Dim;
1786 static int const cols=Dim;
1787
1788 template <int Row,int Col>
1789 static
1790 BOOST_QVM_INLINE_CRITICAL
1791 scalar_type
1792 read_element( this_matrix const & x )
1793 {
1794 BOOST_QVM_STATIC_ASSERT(Row>=0);
1795 BOOST_QVM_STATIC_ASSERT(Col>=0);
1796 BOOST_QVM_STATIC_ASSERT(Row<Dim);
1797 BOOST_QVM_STATIC_ASSERT(Col<Dim);
1798 return qvm_detail::rotz_m_get<Row,Col>::get(reinterpret_cast<Angle const &>(x));
1799 }
1800
1801 static
1802 BOOST_QVM_INLINE_CRITICAL
1803 scalar_type
1804 read_element_idx( int row, int col, this_matrix const & x )
1805 {
1806 BOOST_QVM_ASSERT(row>=0);
1807 BOOST_QVM_ASSERT(col>=0);
1808 BOOST_QVM_ASSERT(row<Dim);
1809 BOOST_QVM_ASSERT(col<Dim);
1810 Angle const & a=reinterpret_cast<Angle const &>(x);
1811 if( row==0 )
1812 {
1813 if( col==0 )
1814 return cos<scalar_type>(a);
1815 if( col==1 )
1816 return -sin<scalar_type>(a);
1817 }
1818 if( row==1 )
1819 {
1820 if( col==0 )
1821 return sin<scalar_type>(a);
1822 if( col==1 )
1823 return cos<scalar_type>(a);
1824 }
1825 return scalar_traits<scalar_type>::value(row==col);
1826 }
1827 };
1828
1829 template <int Dim,class Angle>
1830 struct
1831 deduce_mat<qvm_detail::rotz_mat_<Dim,Angle>,Dim,Dim>
1832 {
1833 typedef mat<Angle,Dim,Dim> type;
1834 };
1835
1836 template <int Dim,class Angle,int R,int C>
1837 struct
1838 deduce_mat2<qvm_detail::rotz_mat_<Dim,Angle>,qvm_detail::rotz_mat_<Dim,Angle>,R,C>
1839 {
1840 typedef mat<Angle,R,C> type;
1841 };
1842
1843 template <int Dim,class Angle>
1844 BOOST_QVM_INLINE_TRIVIAL
1845 qvm_detail::rotz_mat_<Dim,Angle> const &
1846 rotz_mat( Angle const & angle )
1847 {
1848 BOOST_QVM_STATIC_ASSERT(Dim>=2);
1849 return reinterpret_cast<qvm_detail::rotz_mat_<Dim,Angle> const &>(angle);
1850 }
1851
1852 template <class A,class Angle>
1853 BOOST_QVM_INLINE_OPERATIONS
1854 typename enable_if_c<
1855 is_mat<A>::value &&
1856 mat_traits<A>::rows>=2 &&
1857 mat_traits<A>::rows==mat_traits<A>::cols,
1858 void>::type
1859 set_rotz( A & a, Angle angle )
1860 {
1861 assign(a,rotz_mat<mat_traits<A>::rows>(angle));
1862 }
1863
1864 template <class A,class Angle>
1865 BOOST_QVM_INLINE_OPERATIONS
1866 typename enable_if_c<
1867 is_mat<A>::value &&
1868 mat_traits<A>::rows>=2 &&
1869 mat_traits<A>::rows==mat_traits<A>::cols,
1870 void>::type
1871 rotate_z( A & a, Angle angle )
1872 {
1873 a *= rotz_mat<mat_traits<A>::rows>(angle);
1874 }
1875
1876 ////////////////////////////////////////////////
1877
1878 namespace
1879 qvm_detail
1880 {
1881 template <int D>
1882 struct
1883 inverse_m_defined
1884 {
1885 static bool const value=false;
1886 };
1887 }
1888
1889 template <class A,class B>
1890 BOOST_QVM_INLINE_TRIVIAL
1891 typename lazy_enable_if_c<
1892 is_mat<A>::value && is_scalar<B>::value &&
1893 mat_traits<A>::rows==mat_traits<A>::cols &&
1894 !qvm_detail::inverse_m_defined<mat_traits<A>::rows>::value,
1895 deduce_mat<A> >::type
1896 inverse( A const & a, B det )
1897 {
1898 typedef typename mat_traits<A>::scalar_type T;
1899 BOOST_QVM_ASSERT(det!=scalar_traits<T>::value(0));
1900 T f=scalar_traits<T>::value(1)/det;
1901 typedef typename deduce_mat<A>::type cofactor_return_type;
1902 cofactor_return_type c=qvm_detail::cofactor_impl(a);
1903 return reinterpret_cast<qvm_detail::transposed_<cofactor_return_type> const &>(c) * f;
1904 }
1905
1906 template <class A>
1907 BOOST_QVM_INLINE_TRIVIAL
1908 typename lazy_enable_if_c<
1909 is_mat<A>::value &&
1910 mat_traits<A>::rows==mat_traits<A>::cols &&
1911 !qvm_detail::inverse_m_defined<mat_traits<A>::rows>::value,
1912 deduce_mat<A> >::type
1913 inverse( A const & a )
1914 {
1915 typedef typename mat_traits<A>::scalar_type T;
1916 T det=determinant(a);
1917 if( det==scalar_traits<T>::value(0) )
1918 BOOST_QVM_THROW_EXCEPTION(zero_determinant_error());
1919 return inverse(a,det);
1920 }
1921
1922 ////////////////////////////////////////////////
1923
1924 namespace
1925 sfinae
1926 {
1927 using ::boost::qvm::to_string;
1928 using ::boost::qvm::assign;
1929 using ::boost::qvm::determinant;
1930 using ::boost::qvm::cmp;
1931 using ::boost::qvm::convert_to;
1932 using ::boost::qvm::set_identity;
1933 using ::boost::qvm::set_zero;
1934 using ::boost::qvm::scalar_cast;
1935 using ::boost::qvm::operator/=;
1936 using ::boost::qvm::operator/;
1937 using ::boost::qvm::operator==;
1938 using ::boost::qvm::operator-=;
1939 using ::boost::qvm::operator-;
1940 using ::boost::qvm::operator*=;
1941 using ::boost::qvm::operator*;
1942 using ::boost::qvm::operator!=;
1943 using ::boost::qvm::operator+=;
1944 using ::boost::qvm::operator+;
1945 using ::boost::qvm::mref;
1946 using ::boost::qvm::rot_mat;
1947 using ::boost::qvm::set_rot;
1948 using ::boost::qvm::rotate;
1949 using ::boost::qvm::set_rotx;
1950 using ::boost::qvm::rotate_x;
1951 using ::boost::qvm::set_roty;
1952 using ::boost::qvm::rotate_y;
1953 using ::boost::qvm::set_rotz;
1954 using ::boost::qvm::rotate_z;
1955 using ::boost::qvm::inverse;
1956 }
1957
1958 ////////////////////////////////////////////////
1959 }
1960 }
1961
1962#endif