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

source code of boost/libs/qvm/include/boost/qvm/vec_operations.hpp