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 BOOST_QVM_5265FC7CA1C011DE9EBDFFA956D89593
7 #define BOOST_QVM_5265FC7CA1C011DE9EBDFFA956D89593
8 
9 #include <boost/qvm/inline.hpp>
10 #include <boost/qvm/mat_traits.hpp>
11 #include <boost/qvm/deduce_vec.hpp>
12 #include <boost/qvm/assert.hpp>
13 #include <boost/qvm/enable_if.hpp>
14 
15 namespace
16 boost
17     {
18     namespace
19     qvm
20         {
21         ////////////////////////////////////////////////
22 
23         namespace
24         qvm_detail
25             {
26             template <int Col,class OriginalMatrix>
27             class
28             col_
29                 {
30                 col_( col_ const & );
31                 col_ & operator=( col_ const & );
32                 ~col_();
33 
34                 public:
35 
36                 template <class T>
37                 BOOST_QVM_INLINE_TRIVIAL
38                 col_ &
operator =(T const & x)39                 operator=( T const & x )
40                     {
41                     assign(*this,x);
42                     return *this;
43                     }
44 
45                 template <class R>
46                 BOOST_QVM_INLINE_TRIVIAL
operator R() const47                 operator R() const
48                     {
49                     R r;
50                     assign(r,*this);
51                     return r;
52                     }
53                 };
54             }
55 
56         template <int Col,class OriginalMatrix>
57         struct
58         vec_traits< qvm_detail::col_<Col,OriginalMatrix> >
59             {
60             typedef qvm_detail::col_<Col,OriginalMatrix> this_vector;
61             typedef typename mat_traits<OriginalMatrix>::scalar_type scalar_type;
62             static int const dim=mat_traits<OriginalMatrix>::rows;
63             BOOST_QVM_STATIC_ASSERT(Col>=0);
64             BOOST_QVM_STATIC_ASSERT(Col<mat_traits<OriginalMatrix>::cols);
65 
66             template <int I>
67             static
68             BOOST_QVM_INLINE_CRITICAL
69             scalar_type
read_elementboost::qvm::vec_traits70             read_element( this_vector const & x )
71                 {
72                 BOOST_QVM_STATIC_ASSERT(I>=0);
73                 BOOST_QVM_STATIC_ASSERT(I<dim);
74                 return mat_traits<OriginalMatrix>::template read_element<I,Col>(reinterpret_cast<OriginalMatrix const &>(x));
75                 }
76 
77             template <int I>
78             static
79             BOOST_QVM_INLINE_CRITICAL
80             scalar_type &
write_elementboost::qvm::vec_traits81             write_element( this_vector & x )
82                 {
83                 BOOST_QVM_STATIC_ASSERT(I>=0);
84                 BOOST_QVM_STATIC_ASSERT(I<dim);
85                 return mat_traits<OriginalMatrix>::template write_element<I,Col>(reinterpret_cast<OriginalMatrix &>(x));
86                 }
87 
88             static
89             BOOST_QVM_INLINE_CRITICAL
90             scalar_type
read_element_idxboost::qvm::vec_traits91             read_element_idx( int i, this_vector const & x )
92                 {
93                 BOOST_QVM_ASSERT(i>=0);
94                 BOOST_QVM_ASSERT(i<dim);
95                 return mat_traits<OriginalMatrix>::read_element_idx(i,Col,reinterpret_cast<OriginalMatrix const &>(x));
96                 }
97 
98             static
99             BOOST_QVM_INLINE_CRITICAL
100             scalar_type &
write_element_idxboost::qvm::vec_traits101             write_element_idx( int i, this_vector & x )
102                 {
103                 BOOST_QVM_ASSERT(i>=0);
104                 BOOST_QVM_ASSERT(i<dim);
105                 return mat_traits<OriginalMatrix>::write_element_idx(i,Col,reinterpret_cast<OriginalMatrix &>(x));
106                 }
107             };
108 
109         template <int Col,class OriginalMatrix,int D>
110         struct
111         deduce_vec<qvm_detail::col_<Col,OriginalMatrix>,D>
112             {
113             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
114             };
115 
116         template <int Col,class OriginalMatrix,int D>
117         struct
118         deduce_vec2<qvm_detail::col_<Col,OriginalMatrix>,qvm_detail::col_<Col,OriginalMatrix>,D>
119             {
120             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
121             };
122 
123         template <int Col,class A>
124         typename boost::enable_if_c<
125             is_mat<A>::value,
126             qvm_detail::col_<Col,A> const &>::type
127         BOOST_QVM_INLINE_TRIVIAL
col(A const & a)128         col( A const & a )
129             {
130             return reinterpret_cast<typename qvm_detail::col_<Col,A> const &>(a);
131             }
132 
133         template <int Col,class A>
134         typename boost::enable_if_c<
135             is_mat<A>::value,
136             qvm_detail::col_<Col,A> &>::type
137         BOOST_QVM_INLINE_TRIVIAL
col(A & a)138         col( A & a )
139             {
140             return reinterpret_cast<typename qvm_detail::col_<Col,A> &>(a);
141             }
142 
143         ////////////////////////////////////////////////
144 
145         namespace
146         qvm_detail
147             {
148             template <int Row,class OriginalMatrix>
149             class
150             row_
151                 {
152                 row_( row_ const & );
153                 row_ & operator=( row_ const & );
154                 ~row_();
155 
156                 public:
157 
158                 template <class T>
159                 BOOST_QVM_INLINE_TRIVIAL
160                 row_ &
operator =(T const & x)161                 operator=( T const & x )
162                     {
163                     assign(*this,x);
164                     return *this;
165                     }
166 
167                 template <class R>
168                 BOOST_QVM_INLINE_TRIVIAL
operator R() const169                 operator R() const
170                     {
171                     R r;
172                     assign(r,*this);
173                     return r;
174                     }
175                 };
176             }
177 
178         template <int Row,class OriginalMatrix>
179         struct
180         vec_traits< qvm_detail::row_<Row,OriginalMatrix> >
181             {
182             typedef qvm_detail::row_<Row,OriginalMatrix> this_vector;
183             typedef typename mat_traits<OriginalMatrix>::scalar_type scalar_type;
184             static int const dim=mat_traits<OriginalMatrix>::cols;
185             BOOST_QVM_STATIC_ASSERT(Row>=0);
186             BOOST_QVM_STATIC_ASSERT(Row<mat_traits<OriginalMatrix>::rows);
187 
188             template <int I>
189             static
190             BOOST_QVM_INLINE_CRITICAL
191             scalar_type
read_elementboost::qvm::vec_traits192             read_element( this_vector const & x )
193                 {
194                 BOOST_QVM_STATIC_ASSERT(I>=0);
195                 BOOST_QVM_STATIC_ASSERT(I<dim);
196                 return mat_traits<OriginalMatrix>::template read_element<Row,I>(reinterpret_cast<OriginalMatrix const &>(x));
197                 }
198 
199             template <int I>
200             static
201             BOOST_QVM_INLINE_CRITICAL
202             scalar_type &
write_elementboost::qvm::vec_traits203             write_element( this_vector & x )
204                 {
205                 BOOST_QVM_STATIC_ASSERT(I>=0);
206                 BOOST_QVM_STATIC_ASSERT(I<dim);
207                 return mat_traits<OriginalMatrix>::template write_element<Row,I>(reinterpret_cast<OriginalMatrix &>(x));
208                 }
209 
210             static
211             BOOST_QVM_INLINE_CRITICAL
212             scalar_type
read_element_idxboost::qvm::vec_traits213             read_element_idx( int i, this_vector const & x )
214                 {
215                 BOOST_QVM_ASSERT(i>=0);
216                 BOOST_QVM_ASSERT(i<dim);
217                 return mat_traits<OriginalMatrix>::read_element_idx(Row,i,reinterpret_cast<OriginalMatrix const &>(x));
218                 }
219 
220             static
221             BOOST_QVM_INLINE_CRITICAL
222             scalar_type &
write_element_idxboost::qvm::vec_traits223             write_element_idx( int i, this_vector & x )
224                 {
225                 BOOST_QVM_ASSERT(i>=0);
226                 BOOST_QVM_ASSERT(i<dim);
227                 return mat_traits<OriginalMatrix>::write_element_idx(Row,i,reinterpret_cast<OriginalMatrix &>(x));
228                 }
229             };
230 
231         template <int Row,class OriginalMatrix,int D>
232         struct
233         deduce_vec<qvm_detail::row_<Row,OriginalMatrix>,D>
234             {
235             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
236             };
237 
238         template <int Row,class OriginalMatrix,int D>
239         struct
240         deduce_vec2<qvm_detail::row_<Row,OriginalMatrix>,qvm_detail::row_<Row,OriginalMatrix>,D>
241             {
242             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
243             };
244 
245         template <int Row,class A>
246         typename boost::enable_if_c<
247             is_mat<A>::value,
248             qvm_detail::row_<Row,A> const &>::type
249         BOOST_QVM_INLINE_TRIVIAL
row(A const & a)250         row( A const & a )
251             {
252             return reinterpret_cast<typename qvm_detail::row_<Row,A> const &>(a);
253             }
254 
255         template <int Row,class A>
256         typename boost::enable_if_c<
257             is_mat<A>::value,
258             qvm_detail::row_<Row,A> &>::type
259         BOOST_QVM_INLINE_TRIVIAL
row(A & a)260         row( A & a )
261             {
262             return reinterpret_cast<typename qvm_detail::row_<Row,A> &>(a);
263             }
264 
265         ////////////////////////////////////////////////
266 
267         namespace
268         qvm_detail
269             {
270             template <class OriginalMatrix>
271             class
272             diag_
273                 {
274                 diag_( diag_ const & );
275                 diag_ & operator=( diag_ const & );
276                 ~diag_();
277 
278                 public:
279 
280                 template <class T>
281                 BOOST_QVM_INLINE_TRIVIAL
282                 diag_ &
operator =(T const & x)283                 operator=( T const & x )
284                     {
285                     assign(*this,x);
286                     return *this;
287                     }
288 
289                 template <class R>
290                 BOOST_QVM_INLINE_TRIVIAL
operator R() const291                 operator R() const
292                     {
293                     R r;
294                     assign(r,*this);
295                     return r;
296                     }
297                 };
298 
299             template <int X,int Y,bool Which>
300             struct diag_bool_dispatch;
301 
302             template <int X,int Y>
303             struct
304             diag_bool_dispatch<X,Y,true>
305                 {
306                 static int const value=X;
307                 };
308 
309             template <int X,int Y>
310             struct
311             diag_bool_dispatch<X,Y,false>
312                 {
313                 static int const value=Y;
314                 };
315             }
316 
317         template <class OriginalMatrix>
318         struct
319         vec_traits< qvm_detail::diag_<OriginalMatrix> >
320             {
321             typedef qvm_detail::diag_<OriginalMatrix> this_vector;
322             typedef typename mat_traits<OriginalMatrix>::scalar_type scalar_type;
323             static int const dim=qvm_detail::diag_bool_dispatch<
324                     mat_traits<OriginalMatrix>::rows,
325                     mat_traits<OriginalMatrix>::cols,
326                     mat_traits<OriginalMatrix>::rows<=mat_traits<OriginalMatrix>::cols>::value;
327 
328             template <int I>
329             static
330             BOOST_QVM_INLINE_CRITICAL
331             scalar_type
read_elementboost::qvm::vec_traits332             read_element( this_vector const & x )
333                 {
334                 BOOST_QVM_STATIC_ASSERT(I>=0);
335                 BOOST_QVM_STATIC_ASSERT(I<dim);
336                 return mat_traits<OriginalMatrix>::template read_element<I,I>(reinterpret_cast<OriginalMatrix const &>(x));
337                 }
338 
339             template <int I>
340             static
341             BOOST_QVM_INLINE_CRITICAL
342             scalar_type &
write_elementboost::qvm::vec_traits343             write_element( this_vector & x )
344                 {
345                 BOOST_QVM_STATIC_ASSERT(I>=0);
346                 BOOST_QVM_STATIC_ASSERT(I<dim);
347                 return mat_traits<OriginalMatrix>::template write_element<I,I>(reinterpret_cast<OriginalMatrix &>(x));
348                 }
349 
350             static
351             BOOST_QVM_INLINE_CRITICAL
352             scalar_type
read_element_idxboost::qvm::vec_traits353             read_element_idx( int i, this_vector const & x )
354                 {
355                 BOOST_QVM_ASSERT(i>=0);
356                 BOOST_QVM_ASSERT(i<dim);
357                 return mat_traits<OriginalMatrix>::read_element_idx(i,i,reinterpret_cast<OriginalMatrix const &>(x));
358                 }
359 
360             static
361             BOOST_QVM_INLINE_CRITICAL
362             scalar_type &
write_element_idxboost::qvm::vec_traits363             write_element_idx( int i, this_vector & x )
364                 {
365                 BOOST_QVM_ASSERT(i>=0);
366                 BOOST_QVM_ASSERT(i<dim);
367                 return mat_traits<OriginalMatrix>::write_element_idx(i,i,reinterpret_cast<OriginalMatrix &>(x));
368                 }
369             };
370 
371         template <class OriginalMatrix,int D>
372         struct
373         deduce_vec<qvm_detail::diag_<OriginalMatrix>,D>
374             {
375             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
376             };
377 
378         template <class OriginalMatrix,int D>
379         struct
380         deduce_vec2<qvm_detail::diag_<OriginalMatrix>,qvm_detail::diag_<OriginalMatrix>,D>
381             {
382             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
383             };
384 
385         template <class A>
386         typename boost::enable_if_c<
387             is_mat<A>::value,
388             qvm_detail::diag_<A> const &>::type
389         BOOST_QVM_INLINE_TRIVIAL
diag(A const & a)390         diag( A const & a )
391             {
392             return reinterpret_cast<typename qvm_detail::diag_<A> const &>(a);
393             }
394 
395         template <class A>
396         typename boost::enable_if_c<
397             is_mat<A>::value,
398             qvm_detail::diag_<A> &>::type
399         BOOST_QVM_INLINE_TRIVIAL
diag(A & a)400         diag( A & a )
401             {
402             return reinterpret_cast<typename qvm_detail::diag_<A> &>(a);
403             }
404 
405         ////////////////////////////////////////////////
406 
407         namespace
408         qvm_detail
409             {
410             template <class OriginalMatrix>
411             class
412             translation_
413                 {
414                 translation_( translation_ const & );
415                 ~translation_();
416 
417                 public:
418 
419                 translation_ &
operator =(translation_ const & x)420                 operator=( translation_ const & x )
421                     {
422                     assign(*this,x);
423                     return *this;
424                     }
425 
426                 template <class T>
427                 BOOST_QVM_INLINE_TRIVIAL
428                 translation_ &
operator =(T const & x)429                 operator=( T const & x )
430                     {
431                     assign(*this,x);
432                     return *this;
433                     }
434 
435                 template <class R>
436                 BOOST_QVM_INLINE_TRIVIAL
operator R() const437                 operator R() const
438                     {
439                     R r;
440                     assign(r,*this);
441                     return r;
442                     }
443                 };
444             }
445 
446         template <class OriginalMatrix>
447         struct
448         vec_traits< qvm_detail::translation_<OriginalMatrix> >
449             {
450             typedef qvm_detail::translation_<OriginalMatrix> this_vector;
451             typedef typename mat_traits<OriginalMatrix>::scalar_type scalar_type;
452             static int const dim=mat_traits<OriginalMatrix>::rows-1;
453             BOOST_QVM_STATIC_ASSERT(mat_traits<OriginalMatrix>::rows==mat_traits<OriginalMatrix>::cols);
454             BOOST_QVM_STATIC_ASSERT(mat_traits<OriginalMatrix>::rows>=3);
455 
456             template <int I>
457             static
458             BOOST_QVM_INLINE_CRITICAL
459             scalar_type
read_elementboost::qvm::vec_traits460             read_element( this_vector const & x )
461                 {
462                 BOOST_QVM_STATIC_ASSERT(I>=0);
463                 BOOST_QVM_STATIC_ASSERT(I<dim);
464                 return mat_traits<OriginalMatrix>::template read_element<I,dim>(reinterpret_cast<OriginalMatrix const &>(x));
465                 }
466 
467             template <int I>
468             static
469             BOOST_QVM_INLINE_CRITICAL
470             scalar_type &
write_elementboost::qvm::vec_traits471             write_element( this_vector & x )
472                 {
473                 BOOST_QVM_STATIC_ASSERT(I>=0);
474                 BOOST_QVM_STATIC_ASSERT(I<dim);
475                 return mat_traits<OriginalMatrix>::template write_element<I,dim>(reinterpret_cast<OriginalMatrix &>(x));
476                 }
477 
478             static
479             BOOST_QVM_INLINE_CRITICAL
480             scalar_type
read_element_idxboost::qvm::vec_traits481             read_element_idx( int i, this_vector const & x )
482                 {
483                 BOOST_QVM_ASSERT(i>=0);
484                 BOOST_QVM_ASSERT(i<dim);
485                 return mat_traits<OriginalMatrix>::read_element_idx(i,dim,reinterpret_cast<OriginalMatrix const &>(x));
486                 }
487 
488             static
489             BOOST_QVM_INLINE_CRITICAL
490             scalar_type &
write_element_idxboost::qvm::vec_traits491             write_element_idx( int i, this_vector & x )
492                 {
493                 BOOST_QVM_ASSERT(i>=0);
494                 BOOST_QVM_ASSERT(i<dim);
495                 return mat_traits<OriginalMatrix>::write_element_idx(i,dim,reinterpret_cast<OriginalMatrix &>(x));
496                 }
497             };
498 
499         template <class OriginalMatrix,int D>
500         struct
501         deduce_vec<qvm_detail::translation_<OriginalMatrix>,D>
502             {
503             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
504             };
505 
506         template <class OriginalMatrix,int D>
507         struct
508         deduce_vec2<qvm_detail::translation_<OriginalMatrix>,qvm_detail::translation_<OriginalMatrix>,D>
509             {
510             typedef vec<typename mat_traits<OriginalMatrix>::scalar_type,D> type;
511             };
512 
513         template <class A>
514         typename boost::enable_if_c<
515             is_mat<A>::value && mat_traits<A>::rows==mat_traits<A>::cols && mat_traits<A>::rows>=3,
516             qvm_detail::translation_<A> const &>::type
517         BOOST_QVM_INLINE_TRIVIAL
518         translation( A const & a )
519             {
520             return reinterpret_cast<typename qvm_detail::translation_<A> const &>(a);
521             }
522 
523         template <class A>
524         typename boost::enable_if_c<
525             is_mat<A>::value && mat_traits<A>::rows==mat_traits<A>::cols && mat_traits<A>::rows>=3,
526             qvm_detail::translation_<A> &>::type
527         BOOST_QVM_INLINE_TRIVIAL
528         translation( A & a )
529             {
530             return reinterpret_cast<typename qvm_detail::translation_<A> &>(a);
531             }
532 
533         ////////////////////////////////////////////////
534         }
535     }
536 
537 #endif
538