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