Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / qvm / vec_operations.hpp
1 //Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.\r
2 \r
3 //Distributed under the Boost Software License, Version 1.0. (See accompanying\r
4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
5 \r
6 #ifndef UUID_384AFF3AD23A11DFA80B754FE0D72085\r
7 #define UUID_384AFF3AD23A11DFA80B754FE0D72085\r
8 \r
9 #include <boost/qvm/vec_operations2.hpp>\r
10 #include <boost/qvm/vec_operations3.hpp>\r
11 #include <boost/qvm/vec_operations4.hpp>\r
12 #include <boost/qvm/assert.hpp>\r
13 #include <boost/qvm/scalar_traits.hpp>\r
14 #include <string>\r
15 \r
16 namespace\r
17 boost\r
18     {\r
19     namespace\r
20     qvm\r
21         {\r
22         namespace\r
23         qvm_detail\r
24             {\r
25             BOOST_QVM_INLINE_CRITICAL\r
26             void const *\r
27             get_valid_ptr_vec_operations()\r
28                 {\r
29                 static int const obj=0;\r
30                 return &obj;\r
31                 }\r
32             }\r
33 \r
34         ////////////////////////////////////////////////\r
35 \r
36         namespace\r
37         qvm_to_string_detail\r
38             {\r
39             template <class T>\r
40             std::string to_string( T const & x );\r
41             }\r
42 \r
43         namespace\r
44         qvm_detail\r
45             {\r
46             template <int D>\r
47             struct\r
48             to_string_v_defined\r
49                 {\r
50                 static bool const value=false;\r
51                 };\r
52 \r
53             template <int I,int DimMinusOne>\r
54             struct\r
55             to_string_vector_elements\r
56                 {\r
57                 template <class A>\r
58                 static\r
59                 std::string\r
60                 f( A const & a )\r
61                     {\r
62                     using namespace qvm_to_string_detail;\r
63                     return to_string(vec_traits<A>::template read_element<I>(a))+','+to_string_vector_elements<I+1,DimMinusOne>::f(a);\r
64                     }\r
65                 };\r
66 \r
67             template <int DimMinusOne>\r
68             struct\r
69             to_string_vector_elements<DimMinusOne,DimMinusOne>\r
70                 {\r
71                 template <class A>\r
72                 static\r
73                 std::string\r
74                 f( A const & a )\r
75                     {\r
76                     using namespace qvm_to_string_detail;\r
77                     return to_string(vec_traits<A>::template read_element<DimMinusOne>(a));\r
78                     }\r
79                 };\r
80             }\r
81 \r
82         template <class A>\r
83         inline\r
84         typename boost::enable_if_c<\r
85             is_vec<A>::value  &&\r
86             !qvm_detail::to_string_v_defined<vec_traits<A>::dim>::value,\r
87             std::string>::type\r
88         to_string( A const & a )\r
89             {\r
90             return '('+qvm_detail::to_string_vector_elements<0,vec_traits<A>::dim-1>::f(a)+')';\r
91             }\r
92 \r
93         ////////////////////////////////////////////////\r
94 \r
95         namespace\r
96         qvm_detail\r
97             {\r
98             template <int D>\r
99             struct\r
100             assign_vv_defined\r
101                 {\r
102                 static bool const value=false;\r
103                 };\r
104 \r
105             template <int I,int N>\r
106             struct\r
107             copy_vector_elements\r
108                 {\r
109                 template <class A,class B>\r
110                 static\r
111                 void\r
112                 f( A & a, B const & b )\r
113                     {\r
114                     vec_traits<A>::template write_element<I>(a)=vec_traits<B>::template read_element<I>(b);\r
115                     copy_vector_elements<I+1,N>::f(a,b);\r
116                     }\r
117                 };\r
118 \r
119             template <int N>\r
120             struct\r
121             copy_vector_elements<N,N>\r
122                 {\r
123                 template <class A,class B>\r
124                 static\r
125                 void\r
126                 f( A &, B const & )\r
127                     {\r
128                     }\r
129                 };\r
130             }\r
131 \r
132         template <class A,class B>\r
133         inline\r
134         typename boost::enable_if_c<\r
135             is_vec<A>::value && is_vec<B>::value &&\r
136             vec_traits<A>::dim==vec_traits<B>::dim &&\r
137             !qvm_detail::assign_vv_defined<vec_traits<A>::dim>::value,\r
138             A &>::type\r
139         assign( A & a, B const & b )\r
140             {\r
141             qvm_detail::copy_vector_elements<0,vec_traits<A>::dim>::f(a,b);\r
142             return a;\r
143             }\r
144 \r
145         ////////////////////////////////////////////////\r
146 \r
147         namespace\r
148         qvm_detail\r
149             {\r
150             template <int D>\r
151             struct\r
152             convert_to_v_defined\r
153                 {\r
154                 static bool const value=false;\r
155                 };\r
156             }\r
157 \r
158         template <class R,class A>\r
159         BOOST_QVM_INLINE_TRIVIAL\r
160         typename enable_if_c<\r
161             is_vec<R>::value && is_vec<A>::value &&\r
162             vec_traits<R>::dim==vec_traits<A>::dim &&\r
163             !qvm_detail::convert_to_v_defined<vec_traits<R>::dim>::value,\r
164             R>::type\r
165         convert_to( A const & a )\r
166             {\r
167             R r; assign(r,a);\r
168             return r;\r
169             }\r
170 \r
171         ////////////////////////////////////////////////\r
172 \r
173         template <class A,class B>\r
174         BOOST_QVM_INLINE_OPERATIONS\r
175         typename lazy_enable_if_c<\r
176             is_vec<A>::value && is_vec<B>::value &&\r
177             vec_traits<A>::dim==3 && vec_traits<B>::dim==3,\r
178             deduce_vec2<A,B,3> >::type\r
179         cross( A const & a, B const & b )\r
180             {\r
181             typedef typename deduce_vec2<A,B,3>::type R;\r
182             R r;\r
183             vec_traits<R>::template write_element<0>(r)=\r
184                 vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<2>(b)-\r
185                 vec_traits<A>::template read_element<2>(a)*vec_traits<B>::template read_element<1>(b);\r
186             vec_traits<R>::template write_element<1>(r)=\r
187                 vec_traits<A>::template read_element<2>(a)*vec_traits<B>::template read_element<0>(b)-\r
188                 vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<2>(b);\r
189             vec_traits<R>::template write_element<2>(r)=\r
190                 vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<1>(b)-\r
191                 vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<0>(b);\r
192             return r;\r
193             }\r
194 \r
195         ////////////////////////////////////////////////\r
196 \r
197         template <class A,class B,class Cmp>\r
198         BOOST_QVM_INLINE_OPERATIONS\r
199         typename enable_if_c<\r
200             is_vec<A>::value && is_vec<B>::value &&\r
201             vec_traits<A>::dim==vec_traits<B>::dim,\r
202             bool>::type\r
203         cmp( A const & a, B const & b, Cmp f )\r
204             {\r
205             typedef typename deduce_scalar<\r
206                 typename vec_traits<A>::scalar_type,\r
207                 typename vec_traits<B>::scalar_type>::type T;\r
208             int const dim=vec_traits<A>::dim;\r
209             T v1[dim]; assign(v1,a);\r
210             T v2[dim]; assign(v2,b);\r
211             for( int i=0; i!=dim; ++i )\r
212                 if( !f(v1[i],v2[i]) )\r
213                     return false;\r
214             return true;\r
215             }\r
216 \r
217         ////////////////////////////////////////////////\r
218 \r
219         namespace\r
220         qvm_detail\r
221             {\r
222             template <class T,int Dim>\r
223             class\r
224             zero_vec_\r
225                 {\r
226                 zero_vec_( zero_vec_ const & );\r
227                 zero_vec_ & operator=( zero_vec_ const & );\r
228                 ~zero_vec_();\r
229 \r
230                 public:\r
231 \r
232                 template <class R>\r
233                 BOOST_QVM_INLINE_TRIVIAL\r
234                 operator R() const\r
235                     {\r
236                     R r;\r
237                     assign(r,*this);\r
238                     return r;\r
239                     }\r
240                 };\r
241             }\r
242 \r
243         template <class V>\r
244         struct vec_traits;\r
245 \r
246         template <class T,int Dim>\r
247         struct\r
248         vec_traits< qvm_detail::zero_vec_<T,Dim> >\r
249             {\r
250             typedef qvm_detail::zero_vec_<T,Dim> this_vector;\r
251             typedef T scalar_type;\r
252             static int const dim=Dim;\r
253 \r
254             template <int I>\r
255             static\r
256             BOOST_QVM_INLINE_CRITICAL\r
257             scalar_type\r
258             read_element( this_vector const & )\r
259                 {\r
260                 BOOST_QVM_STATIC_ASSERT(I>=0);\r
261                 BOOST_QVM_STATIC_ASSERT(I<Dim);\r
262                 return scalar_traits<scalar_type>::value(0);\r
263                 }\r
264 \r
265             static\r
266             BOOST_QVM_INLINE_CRITICAL\r
267             scalar_type\r
268             read_element_idx( int i, this_vector const & )\r
269                 {\r
270                 BOOST_QVM_ASSERT(i>=0);\r
271                 BOOST_QVM_ASSERT(i<Dim);\r
272                 return scalar_traits<scalar_type>::value(0);\r
273                 }\r
274             };\r
275 \r
276         template <class T,int Dim,int D>\r
277         struct\r
278         deduce_vec<qvm_detail::zero_vec_<T,Dim>,D>\r
279             {\r
280             typedef vec<T,D> type;\r
281             };\r
282 \r
283         template <class T,int Dim>\r
284         BOOST_QVM_INLINE_TRIVIAL\r
285         qvm_detail::zero_vec_<T,Dim> const &\r
286         zero_vec()\r
287             {\r
288             return *(qvm_detail::zero_vec_<T,Dim> const *)qvm_detail::get_valid_ptr_vec_operations();\r
289             }\r
290 \r
291         template <class A>\r
292         BOOST_QVM_INLINE_OPERATIONS\r
293         typename enable_if_c<\r
294             is_vec<A>::value,\r
295             void>::type\r
296         set_zero( A & a )\r
297             {\r
298             assign(a,zero_vec<typename vec_traits<A>::scalar_type,vec_traits<A>::dim>());\r
299             }\r
300 \r
301         ////////////////////////////////////////////////\r
302 \r
303         namespace\r
304         qvm_detail\r
305             {\r
306             template <class OriginalType,class Scalar>\r
307             class\r
308             vector_scalar_cast_\r
309                 {\r
310                 vector_scalar_cast_( vector_scalar_cast_ const & );\r
311                 vector_scalar_cast_ & operator=( vector_scalar_cast_ const & );\r
312                 ~vector_scalar_cast_();\r
313 \r
314                 public:\r
315 \r
316                 template <class T>\r
317                 BOOST_QVM_INLINE_TRIVIAL\r
318                 vector_scalar_cast_ &\r
319                 operator=( T const & x )\r
320                     {\r
321                     assign(*this,x);\r
322                     return *this;\r
323                     }\r
324 \r
325                 template <class R>\r
326                 BOOST_QVM_INLINE_TRIVIAL\r
327                 operator R() const\r
328                     {\r
329                     R r;\r
330                     assign(r,*this);\r
331                     return r;\r
332                     }\r
333                 };\r
334 \r
335             template <bool> struct scalar_cast_vector_filter { };\r
336             template <> struct scalar_cast_vector_filter<true> { typedef int type; };\r
337             }\r
338 \r
339         template <class OriginalType,class Scalar>\r
340         struct\r
341         vec_traits< qvm_detail::vector_scalar_cast_<OriginalType,Scalar> >\r
342             {\r
343             typedef Scalar scalar_type;\r
344             typedef qvm_detail::vector_scalar_cast_<OriginalType,Scalar> this_vector;\r
345             static int const dim=vec_traits<OriginalType>::dim;\r
346 \r
347             template <int I>\r
348             static\r
349             BOOST_QVM_INLINE_CRITICAL\r
350             scalar_type\r
351             read_element( this_vector const & x )\r
352                 {\r
353                 BOOST_QVM_STATIC_ASSERT(I>=0);\r
354                 BOOST_QVM_STATIC_ASSERT(I<dim);\r
355                 return scalar_type(vec_traits<OriginalType>::template read_element<I>(reinterpret_cast<OriginalType const &>(x)));\r
356                 }\r
357 \r
358             static\r
359             BOOST_QVM_INLINE_CRITICAL\r
360             scalar_type\r
361             read_element_idx( int i, this_vector const & x )\r
362                 {\r
363                 BOOST_QVM_ASSERT(i>=0);\r
364                 BOOST_QVM_ASSERT(i<dim);\r
365                 return scalar_type(vec_traits<OriginalType>::read_element_idx(i,reinterpret_cast<OriginalType const &>(x)));\r
366                 }\r
367             };\r
368 \r
369         template <class OriginalType,class Scalar,int D>\r
370         struct\r
371         deduce_vec<qvm_detail::vector_scalar_cast_<OriginalType,Scalar>,D>\r
372             {\r
373             typedef vec<Scalar,D> type;\r
374             };\r
375 \r
376         template <class Scalar,class T>\r
377         BOOST_QVM_INLINE_TRIVIAL\r
378         qvm_detail::vector_scalar_cast_<T,Scalar> const &\r
379         scalar_cast( T const & x, typename qvm_detail::scalar_cast_vector_filter<is_vec<T>::value>::type=0 )\r
380             {\r
381             return reinterpret_cast<qvm_detail::vector_scalar_cast_<T,Scalar> const &>(x);\r
382             }\r
383 \r
384         ////////////////////////////////////////////////\r
385 \r
386         namespace\r
387         qvm_detail\r
388             {\r
389             template <int D>\r
390             struct\r
391             div_eq_vs_defined\r
392                 {\r
393                 static bool const value=false;\r
394                 };\r
395             }\r
396 \r
397         template <class A,class B>\r
398         BOOST_QVM_INLINE_OPERATIONS\r
399         typename enable_if_c<\r
400             is_vec<A>::value && is_scalar<B>::value &&\r
401             !qvm_detail::div_eq_vs_defined<vec_traits<A>::dim>::value,\r
402             A &>::type\r
403         operator/=( A & a, B b )\r
404             {\r
405             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
406                 vec_traits<A>::write_element_idx(i,a)/=b;\r
407             return a;\r
408             }\r
409 \r
410         ////////////////////////////////////////////////\r
411 \r
412         namespace\r
413         qvm_detail\r
414             {\r
415             template <int D>\r
416             struct\r
417             div_vs_defined\r
418                 {\r
419                 static bool const value=false;\r
420                 };\r
421             }\r
422 \r
423         template <class A,class B>\r
424         BOOST_QVM_INLINE_OPERATIONS\r
425         typename lazy_enable_if_c<\r
426             is_vec<A>::value && is_scalar<B>::value &&\r
427             !qvm_detail::div_vs_defined<vec_traits<A>::dim>::value,\r
428             deduce_vec<A> >::type\r
429         operator/( A const & a, B b )\r
430             {\r
431             typedef typename deduce_vec<A>::type R;\r
432             R r;\r
433             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
434                 vec_traits<R>::write_element_idx(i,r)=vec_traits<A>::read_element_idx(i,a)/b;\r
435             return r;\r
436             }\r
437 \r
438         ////////////////////////////////////////////////\r
439 \r
440         namespace\r
441         qvm_detail\r
442             {\r
443             template <int D>\r
444             struct\r
445             dot_vv_defined\r
446                 {\r
447                 static bool const value=false;\r
448                 };\r
449             }\r
450 \r
451         template <class A,class B>\r
452         BOOST_QVM_INLINE_OPERATIONS\r
453         typename lazy_enable_if_c<\r
454             is_vec<A>::value && is_vec<B>::value &&\r
455             vec_traits<A>::dim==vec_traits<B>::dim &&\r
456             !qvm_detail::dot_vv_defined<vec_traits<A>::dim>::value,\r
457             deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type\r
458         dot( A const & a, B const & b )\r
459             {\r
460             typedef typename deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type>::type T;\r
461             T m(scalar_traits<T>::value(0));\r
462             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
463                 m+=vec_traits<A>::read_element_idx(i,a)*vec_traits<B>::read_element_idx(i,b);\r
464             return m;\r
465             }\r
466 \r
467         ////////////////////////////////////////////////\r
468 \r
469         namespace\r
470         qvm_detail\r
471             {\r
472             template <int D>\r
473             struct\r
474             eq_vv_defined\r
475                 {\r
476                 static bool const value=false;\r
477                 };\r
478             }\r
479 \r
480         template <class A,class B>\r
481         BOOST_QVM_INLINE_OPERATIONS\r
482         typename enable_if_c<\r
483             is_vec<A>::value && is_vec<B>::value &&\r
484             vec_traits<A>::dim==vec_traits<B>::dim &&\r
485             !qvm_detail::eq_vv_defined<vec_traits<A>::dim>::value,\r
486             bool>::type\r
487         operator==( A const & a, B const & b )\r
488             {\r
489             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
490                 if( vec_traits<A>::read_element_idx(i,a)!=vec_traits<B>::read_element_idx(i,b) )\r
491                     return false;\r
492             return true;\r
493             }\r
494 \r
495         ////////////////////////////////////////////////\r
496 \r
497         namespace\r
498         qvm_detail\r
499             {\r
500             template <int D>\r
501             struct\r
502             mag_sqr_v_defined\r
503                 {\r
504                 static bool const value=false;\r
505                 };\r
506             }\r
507 \r
508         template <class A>\r
509         BOOST_QVM_INLINE_OPERATIONS\r
510         typename enable_if_c<\r
511             is_vec<A>::value &&\r
512             !qvm_detail::mag_sqr_v_defined<vec_traits<A>::dim>::value,\r
513             typename vec_traits<A>::scalar_type>::type\r
514         mag_sqr( A const & a )\r
515             {\r
516             typedef typename vec_traits<A>::scalar_type T;\r
517             T m(scalar_traits<T>::value(0));\r
518             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
519                 {\r
520                 T x=vec_traits<A>::read_element_idx(i,a);\r
521                 m+=x*x;\r
522                 }\r
523             return m;\r
524             }\r
525 \r
526         ////////////////////////////////////////////////\r
527 \r
528         namespace\r
529         qvm_detail\r
530             {\r
531             template <int D>\r
532             struct\r
533             mag_v_defined\r
534                 {\r
535                 static bool const value=false;\r
536                 };\r
537             }\r
538 \r
539         template <class A>\r
540         BOOST_QVM_INLINE_OPERATIONS\r
541         typename enable_if_c<\r
542             is_vec<A>::value &&\r
543             !qvm_detail::mag_v_defined<vec_traits<A>::dim>::value,\r
544             typename vec_traits<A>::scalar_type>::type\r
545         mag( A const & a )\r
546             {\r
547             typedef typename vec_traits<A>::scalar_type T;\r
548             T m(scalar_traits<T>::value(0));\r
549             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
550                 {\r
551                 T x=vec_traits<A>::read_element_idx(i,a);\r
552                 m+=x*x;\r
553                 }\r
554             return sqrt<T>(m);\r
555             }\r
556 \r
557         ////////////////////////////////////////////////\r
558 \r
559         namespace\r
560         qvm_detail\r
561             {\r
562             template <int D>\r
563             struct\r
564             minus_eq_vv_defined\r
565                 {\r
566                 static bool const value=false;\r
567                 };\r
568             }\r
569 \r
570         template <class A,class B>\r
571         BOOST_QVM_INLINE_OPERATIONS\r
572         typename enable_if_c<\r
573             is_vec<A>::value && is_vec<B>::value &&\r
574             vec_traits<A>::dim==vec_traits<B>::dim &&\r
575             !qvm_detail::minus_eq_vv_defined<vec_traits<A>::dim>::value,\r
576             A &>::type\r
577         operator-=( A & a, B const & b )\r
578             {\r
579             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
580                 vec_traits<A>::write_element_idx(i,a)-=vec_traits<B>::read_element_idx(i,b);\r
581             return a;\r
582             }\r
583 \r
584         ////////////////////////////////////////////////\r
585 \r
586         namespace\r
587         qvm_detail\r
588             {\r
589             template <int D>\r
590             struct\r
591             minus_v_defined\r
592                 {\r
593                 static bool const value=false;\r
594                 };\r
595             }\r
596 \r
597         template <class A>\r
598         BOOST_QVM_INLINE_OPERATIONS\r
599         typename lazy_enable_if_c<\r
600             is_vec<A>::value &&\r
601             !qvm_detail::minus_v_defined<vec_traits<A>::dim>::value,\r
602             deduce_vec<A> >::type\r
603         operator-( A const & a )\r
604             {\r
605             typedef typename deduce_vec<A>::type R;\r
606             R r;\r
607             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
608                 vec_traits<R>::write_element_idx(i,r)=-vec_traits<A>::read_element_idx(i,a);\r
609             return r;\r
610             }\r
611 \r
612         ////////////////////////////////////////////////\r
613 \r
614         namespace\r
615         qvm_detail\r
616             {\r
617             template <int D>\r
618             struct\r
619             minus_vv_defined\r
620                 {\r
621                 static bool const value=false;\r
622                 };\r
623             }\r
624 \r
625         template <class A,class B>\r
626         BOOST_QVM_INLINE_OPERATIONS\r
627         typename lazy_enable_if_c<\r
628             is_vec<A>::value && is_vec<B>::value &&\r
629             vec_traits<A>::dim==vec_traits<B>::dim &&\r
630             !qvm_detail::minus_vv_defined<vec_traits<A>::dim>::value,\r
631             deduce_vec2<A,B,vec_traits<A>::dim> >::type\r
632         operator-( A const & a, B const & b )\r
633             {\r
634             typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;\r
635             R r;\r
636             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
637                 vec_traits<R>::write_element_idx(i,r)=vec_traits<A>::read_element_idx(i,a)-vec_traits<B>::read_element_idx(i,b);\r
638             return r;\r
639             }\r
640 \r
641         ////////////////////////////////////////////////\r
642 \r
643         namespace\r
644         qvm_detail\r
645             {\r
646             template <int D>\r
647             struct\r
648             mul_eq_vs_defined\r
649                 {\r
650                 static bool const value=false;\r
651                 };\r
652             }\r
653 \r
654         template <class A,class B>\r
655         BOOST_QVM_INLINE_OPERATIONS\r
656         typename enable_if_c<\r
657             is_vec<A>::value && is_scalar<B>::value &&\r
658             !qvm_detail::mul_eq_vs_defined<vec_traits<A>::dim>::value,\r
659             A &>::type\r
660         operator*=( A & a, B b )\r
661             {\r
662             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
663                 vec_traits<A>::write_element_idx(i,a)*=b;\r
664             return a;\r
665             }\r
666 \r
667         ////////////////////////////////////////////////\r
668 \r
669         namespace\r
670         qvm_detail\r
671             {\r
672             template <int D>\r
673             struct\r
674             mul_vs_defined\r
675                 {\r
676                 static bool const value=false;\r
677                 };\r
678             }\r
679 \r
680         template <class A,class B>\r
681         BOOST_QVM_INLINE_OPERATIONS\r
682         typename lazy_enable_if_c<\r
683             is_vec<A>::value && is_scalar<B>::value &&\r
684             !qvm_detail::mul_vs_defined<vec_traits<A>::dim>::value,\r
685             deduce_vec<A> >::type\r
686         operator*( A const & a, B b )\r
687             {\r
688             typedef typename deduce_vec<A>::type R;\r
689             R r;\r
690             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
691                 vec_traits<R>::write_element_idx(i,r)=vec_traits<A>::read_element_idx(i,a)*b;\r
692             return r;\r
693             }\r
694 \r
695         ////////////////////////////////////////////////\r
696 \r
697         namespace\r
698         qvm_detail\r
699             {\r
700             template <int D>\r
701             struct\r
702             mul_sv_defined\r
703                 {\r
704                 static bool const value=false;\r
705                 };\r
706             }\r
707 \r
708         template <class A,class B>\r
709         BOOST_QVM_INLINE_OPERATIONS\r
710         typename lazy_enable_if_c<\r
711             is_scalar<A>::value && is_vec<B>::value &&\r
712             !qvm_detail::mul_sv_defined<vec_traits<B>::dim>::value,\r
713             deduce_vec<B> >::type\r
714         operator*( A a, B const & b )\r
715             {\r
716             typedef typename deduce_vec<B>::type R;\r
717             R r;\r
718             for( int i=0; i!=vec_traits<B>::dim; ++i )\r
719                 vec_traits<R>::write_element_idx(i,r)=a*vec_traits<B>::read_element_idx(i,b);\r
720             return r;\r
721             }\r
722 \r
723         ////////////////////////////////////////////////\r
724 \r
725         namespace\r
726         qvm_detail\r
727             {\r
728             template <int D>\r
729             struct\r
730             neq_vv_defined\r
731                 {\r
732                 static bool const value=false;\r
733                 };\r
734             }\r
735 \r
736         template <class A,class B>\r
737         BOOST_QVM_INLINE_OPERATIONS\r
738         typename enable_if_c<\r
739             is_vec<A>::value && is_vec<B>::value &&\r
740             vec_traits<A>::dim==vec_traits<B>::dim &&\r
741             !qvm_detail::neq_vv_defined<vec_traits<A>::dim>::value,\r
742             bool>::type\r
743         operator!=( A const & a, B const & b )\r
744             {\r
745             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
746                 if( vec_traits<A>::read_element_idx(i,a)!=vec_traits<B>::read_element_idx(i,b) )\r
747                     return true;\r
748             return false;\r
749             }\r
750 \r
751         ////////////////////////////////////////////////\r
752 \r
753         namespace\r
754         qvm_detail\r
755             {\r
756             template <int D>\r
757             struct\r
758             normalize_v_defined\r
759                 {\r
760                 static bool const value=false;\r
761                 };\r
762             }\r
763 \r
764         template <class A>\r
765         BOOST_QVM_INLINE_OPERATIONS\r
766         typename lazy_enable_if_c<\r
767             is_vec<A>::value &&\r
768             !qvm_detail::normalize_v_defined<vec_traits<A>::dim>::value,\r
769             deduce_vec<A> >::type\r
770         normalized( A const & a )\r
771             {\r
772             typedef typename vec_traits<A>::scalar_type T;\r
773             T m(scalar_traits<T>::value(0));\r
774             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
775                 {\r
776                 T x=vec_traits<A>::read_element_idx(i,a);\r
777                 m+=x*x;\r
778                 }\r
779             if( m==scalar_traits<T>::value(0) )\r
780                 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());\r
781             T rm=scalar_traits<T>::value(1)/sqrt<T>(m);\r
782             typedef typename deduce_vec<A>::type R;\r
783             R r;\r
784             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
785                 vec_traits<R>::write_element_idx(i,r)=vec_traits<A>::read_element_idx(i,a)*rm;\r
786             return r;\r
787             }\r
788 \r
789         template <class A>\r
790         BOOST_QVM_INLINE_OPERATIONS\r
791         typename enable_if_c<\r
792             is_vec<A>::value &&\r
793             !qvm_detail::normalize_v_defined<vec_traits<A>::dim>::value,\r
794             void>::type\r
795         normalize( A & a )\r
796             {\r
797             typedef typename vec_traits<A>::scalar_type T;\r
798             T m(scalar_traits<T>::value(0));\r
799             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
800                 {\r
801                 T x=vec_traits<A>::read_element_idx(i,a);\r
802                 m+=x*x;\r
803                 }\r
804             if( m==scalar_traits<T>::value(0) )\r
805                 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());\r
806             T rm=scalar_traits<T>::value(1)/sqrt<T>(m);\r
807             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
808                 vec_traits<A>::write_element_idx(i,a)*=rm;\r
809             }\r
810 \r
811         ////////////////////////////////////////////////\r
812 \r
813         namespace\r
814         qvm_detail\r
815             {\r
816             template <int D>\r
817             struct\r
818             plus_eq_vv_defined\r
819                 {\r
820                 static bool const value=false;\r
821                 };\r
822             }\r
823 \r
824         template <class A,class B>\r
825         BOOST_QVM_INLINE_OPERATIONS\r
826         typename enable_if_c<\r
827             is_vec<A>::value && is_vec<B>::value &&\r
828             vec_traits<A>::dim==vec_traits<B>::dim &&\r
829             !qvm_detail::plus_eq_vv_defined<vec_traits<A>::dim>::value,\r
830             A &>::type\r
831         operator+=( A & a, B const & b )\r
832             {\r
833             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
834                 vec_traits<A>::write_element_idx(i,a)+=vec_traits<B>::read_element_idx(i,b);\r
835             return a;\r
836             }\r
837 \r
838         ////////////////////////////////////////////////\r
839 \r
840         namespace\r
841         qvm_detail\r
842             {\r
843             template <int D>\r
844             struct\r
845             plus_vv_defined\r
846                 {\r
847                 static bool const value=false;\r
848                 };\r
849             }\r
850 \r
851         template <class A,class B>\r
852         BOOST_QVM_INLINE_OPERATIONS\r
853         typename lazy_enable_if_c<\r
854             is_vec<A>::value && is_vec<B>::value &&\r
855             vec_traits<A>::dim==vec_traits<B>::dim &&\r
856             !qvm_detail::plus_vv_defined<vec_traits<A>::dim>::value,\r
857             deduce_vec2<A,B,vec_traits<A>::dim> >::type\r
858         operator+( A const & a, B const & b )\r
859             {\r
860             typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;\r
861             R r;\r
862             for( int i=0; i!=vec_traits<A>::dim; ++i )\r
863                 vec_traits<R>::write_element_idx(i,r)=vec_traits<A>::read_element_idx(i,a)+vec_traits<B>::read_element_idx(i,b);\r
864             return r;\r
865             }\r
866 \r
867         ////////////////////////////////////////////////\r
868 \r
869         namespace\r
870         qvm_detail\r
871             {\r
872             template <class T>\r
873             class\r
874             vref_\r
875                 {\r
876                 vref_( vref_ const & );\r
877                 vref_ & operator=( vref_ const & );\r
878                 ~vref_();\r
879 \r
880                 public:\r
881 \r
882                 template <class R>\r
883                 BOOST_QVM_INLINE_TRIVIAL\r
884                 vref_ &\r
885                 operator=( R const & x )\r
886                     {\r
887                     assign(*this,x);\r
888                     return *this;\r
889                     }\r
890 \r
891                 template <class R>\r
892                 BOOST_QVM_INLINE_TRIVIAL\r
893                 operator R() const\r
894                     {\r
895                     R r;\r
896                     assign(r,*this);\r
897                     return r;\r
898                     }\r
899                 };\r
900             }\r
901 \r
902         template <class V>\r
903         struct\r
904         vec_traits< qvm_detail::vref_<V> >\r
905             {\r
906             typedef typename vec_traits<V>::scalar_type scalar_type;\r
907             typedef qvm_detail::vref_<V> this_vector;\r
908             static int const dim=vec_traits<V>::dim;\r
909 \r
910             template <int I>\r
911             static\r
912             BOOST_QVM_INLINE_CRITICAL\r
913             scalar_type\r
914             read_element( this_vector const & x )\r
915                 {\r
916                 BOOST_QVM_STATIC_ASSERT(I>=0);\r
917                 BOOST_QVM_STATIC_ASSERT(I<dim);\r
918                 return vec_traits<V>::template read_element<I>(reinterpret_cast<V const &>(x));\r
919                 }\r
920 \r
921             template <int I>\r
922             static\r
923             BOOST_QVM_INLINE_CRITICAL\r
924             scalar_type &\r
925             write_element( this_vector & x )\r
926                 {\r
927                 BOOST_QVM_STATIC_ASSERT(I>=0);\r
928                 BOOST_QVM_STATIC_ASSERT(I<dim);\r
929                 return vec_traits<V>::template write_element<I>(reinterpret_cast<V &>(x));\r
930                 }\r
931 \r
932             static\r
933             BOOST_QVM_INLINE_CRITICAL\r
934             scalar_type\r
935             read_element_idx( int i, this_vector const & x )\r
936                 {\r
937                 BOOST_QVM_ASSERT(i>=0);\r
938                 BOOST_QVM_ASSERT(i<dim);\r
939                 return vec_traits<V>::read_element_idx(i,reinterpret_cast<V const &>(x));\r
940                 }\r
941 \r
942             static\r
943             BOOST_QVM_INLINE_CRITICAL\r
944             scalar_type &\r
945             write_element_idx( int i, this_vector & x )\r
946                 {\r
947                 BOOST_QVM_ASSERT(i>=0);\r
948                 BOOST_QVM_ASSERT(i<dim);\r
949                 return vec_traits<V>::write_element_idx(i,reinterpret_cast<V &>(x));\r
950                 }\r
951             };\r
952 \r
953         template <class V,int D>\r
954         struct\r
955         deduce_vec<qvm_detail::vref_<V>,D>\r
956             {\r
957             typedef vec<typename vec_traits<V>::scalar_type,D> type;\r
958             };\r
959 \r
960         template <class V>\r
961         BOOST_QVM_INLINE_TRIVIAL\r
962         typename enable_if_c<\r
963             is_vec<V>::value,\r
964             qvm_detail::vref_<V> const &>::type\r
965         vref( V const & a )\r
966             {\r
967             return reinterpret_cast<qvm_detail::vref_<V> const &>(a);\r
968             }\r
969 \r
970         template <class V>\r
971         BOOST_QVM_INLINE_TRIVIAL\r
972         typename enable_if_c<\r
973             is_vec<V>::value,\r
974             qvm_detail::vref_<V> &>::type\r
975         vref( V & a )\r
976             {\r
977             return reinterpret_cast<qvm_detail::vref_<V> &>(a);\r
978             }\r
979 \r
980         ////////////////////////////////////////////////\r
981 \r
982         namespace\r
983         sfinae\r
984             {\r
985             using ::boost::qvm::to_string;\r
986             using ::boost::qvm::assign;\r
987             using ::boost::qvm::convert_to;\r
988             using ::boost::qvm::cross;\r
989             using ::boost::qvm::cmp;\r
990             using ::boost::qvm::set_zero;\r
991             using ::boost::qvm::scalar_cast;\r
992             using ::boost::qvm::operator/=;\r
993             using ::boost::qvm::operator/;\r
994             using ::boost::qvm::dot;\r
995             using ::boost::qvm::operator==;\r
996             using ::boost::qvm::mag_sqr;\r
997             using ::boost::qvm::mag;\r
998             using ::boost::qvm::operator-=;\r
999             using ::boost::qvm::operator-;\r
1000             using ::boost::qvm::operator*=;\r
1001             using ::boost::qvm::operator*;\r
1002             using ::boost::qvm::operator!=;\r
1003             using ::boost::qvm::normalized;\r
1004             using ::boost::qvm::normalize;\r
1005             using ::boost::qvm::operator+=;\r
1006             using ::boost::qvm::operator+;\r
1007             using ::boost::qvm::vref;\r
1008             }\r
1009 \r
1010         ////////////////////////////////////////////////\r
1011         }\r
1012     }\r
1013 \r
1014 #endif\r