Warning, file /include/boost/qvm/vec_operations.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 #ifndef BOOST_QVM_VEC_OPERATIONS_HPP_INCLUDED
0002 #define BOOST_QVM_VEC_OPERATIONS_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009 #include <boost/qvm/detail/vec_assign.hpp>
0010 #include <boost/qvm/vec_operations2.hpp>
0011 #include <boost/qvm/vec_operations3.hpp>
0012 #include <boost/qvm/vec_operations4.hpp>
0013 #include <boost/qvm/assert.hpp>
0014 #include <boost/qvm/scalar_traits.hpp>
0015 #include <boost/qvm/to_string.hpp>
0016
0017 namespace boost { namespace qvm {
0018
0019 namespace
0020 qvm_detail
0021 {
0022 BOOST_QVM_INLINE_CRITICAL
0023 void const *
0024 get_valid_ptr_vec_operations()
0025 {
0026 static int const obj=0;
0027 return &obj;
0028 }
0029 }
0030
0031
0032
0033
0034 namespace
0035 qvm_detail
0036 {
0037 template <int D>
0038 struct
0039 to_string_v_defined
0040 {
0041 static bool const value=false;
0042 };
0043
0044 template <int I,int DimMinusOne>
0045 struct
0046 to_string_vector_elements
0047 {
0048 template <class A>
0049 static
0050 std::string
0051 f( A const & a )
0052 {
0053 using namespace qvm_to_string_detail;
0054 return to_string(vec_traits<A>::template read_element<I>(a))+','+to_string_vector_elements<I+1,DimMinusOne>::f(a);
0055 }
0056 };
0057
0058 template <int DimMinusOne>
0059 struct
0060 to_string_vector_elements<DimMinusOne,DimMinusOne>
0061 {
0062 template <class A>
0063 static
0064 std::string
0065 f( A const & a )
0066 {
0067 using namespace qvm_to_string_detail;
0068 return to_string(vec_traits<A>::template read_element<DimMinusOne>(a));
0069 }
0070 };
0071 }
0072
0073 template <class A>
0074 inline
0075 typename enable_if_c<
0076 is_vec<A>::value &&
0077 !qvm_detail::to_string_v_defined<vec_traits<A>::dim>::value,
0078 std::string>::type
0079 to_string( A const & a )
0080 {
0081 return '('+qvm_detail::to_string_vector_elements<0,vec_traits<A>::dim-1>::f(a)+')';
0082 }
0083
0084
0085
0086 namespace
0087 qvm_detail
0088 {
0089 template <int D>
0090 struct
0091 convert_to_v_defined
0092 {
0093 static bool const value=false;
0094 };
0095 }
0096
0097 template <class R,class A>
0098 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0099 typename enable_if_c<
0100 is_vec<R>::value && is_vec<A>::value &&
0101 vec_traits<R>::dim==vec_traits<A>::dim &&
0102 !qvm_detail::convert_to_v_defined<vec_traits<R>::dim>::value,
0103 R>::type
0104 convert_to( A const & a )
0105 {
0106 R r; assign(r,a);
0107 return r;
0108 }
0109
0110
0111
0112 template <class A,class B>
0113 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0114 typename lazy_enable_if_c<
0115 is_vec<A>::value && is_vec<B>::value &&
0116 vec_traits<A>::dim==3 && vec_traits<B>::dim==3,
0117 deduce_vec2<A,B,3> >::type
0118 cross( A const & a, B const & b )
0119 {
0120 typedef typename deduce_vec2<A,B,3>::type R;
0121 R r;
0122 write_vec_element<0>(r,
0123 vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<2>(b)-
0124 vec_traits<A>::template read_element<2>(a)*vec_traits<B>::template read_element<1>(b));
0125 write_vec_element<1>(r,
0126 vec_traits<A>::template read_element<2>(a)*vec_traits<B>::template read_element<0>(b)-
0127 vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<2>(b));
0128 write_vec_element<2>(r,
0129 vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<1>(b)-
0130 vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<0>(b));
0131 return r;
0132 }
0133
0134 template <class A,class B>
0135 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0136 typename lazy_enable_if_c<
0137 is_vec<A>::value && is_vec<B>::value &&
0138 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0139 deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type
0140 cross( A const & a, B const & b )
0141 {
0142 typedef typename deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type>::type R;
0143 R const r =
0144 vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<1>(b)-
0145 vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<0>(b);
0146 return r;
0147 }
0148
0149
0150
0151 template <class A,class B,class Cmp>
0152 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0153 typename enable_if_c<
0154 is_vec<A>::value && is_vec<B>::value &&
0155 vec_traits<A>::dim==vec_traits<B>::dim,
0156 bool>::type
0157 cmp( A const & a, B const & b, Cmp f )
0158 {
0159 for( int i=0; i!=vec_traits<A>::dim; ++i )
0160 if( !f(
0161 vec_traits<A>::read_element_idx(i,a),
0162 vec_traits<B>::read_element_idx(i,b)) )
0163 return false;
0164 return true;
0165 }
0166
0167
0168
0169 namespace
0170 qvm_detail
0171 {
0172 template <class T,int Dim>
0173 class
0174 zero_vec_
0175 {
0176 zero_vec_( zero_vec_ const & );
0177 zero_vec_ & operator=( zero_vec_ const & );
0178 ~zero_vec_();
0179
0180 public:
0181
0182 template <class R
0183 #if __cplusplus >= 201103L
0184 , class = typename enable_if<is_vec<R> >::type
0185 #endif
0186 >
0187 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0188 operator R() const
0189 {
0190 R r;
0191 assign(r,*this);
0192 return r;
0193 }
0194 };
0195 }
0196
0197 template <class V>
0198 struct vec_traits;
0199
0200 template <class T,int Dim>
0201 struct
0202 vec_traits< qvm_detail::zero_vec_<T,Dim> >
0203 {
0204 typedef qvm_detail::zero_vec_<T,Dim> this_vector;
0205 typedef T scalar_type;
0206 static int const dim=Dim;
0207
0208 template <int I>
0209 static
0210 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0211 scalar_type
0212 read_element( this_vector const & )
0213 {
0214 BOOST_QVM_STATIC_ASSERT(I>=0);
0215 BOOST_QVM_STATIC_ASSERT(I<Dim);
0216 return scalar_traits<scalar_type>::value(0);
0217 }
0218
0219 static
0220 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0221 scalar_type
0222 read_element_idx( int i, this_vector const & )
0223 {
0224 BOOST_QVM_ASSERT(i>=0); (void)i;
0225 BOOST_QVM_ASSERT(i<Dim);
0226 return scalar_traits<scalar_type>::value(0);
0227 }
0228 };
0229
0230 template <class T,int Dim,int D>
0231 struct
0232 deduce_vec<qvm_detail::zero_vec_<T,Dim>,D>
0233 {
0234 typedef vec<T,D> type;
0235 };
0236
0237 template <class T,int Dim>
0238 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0239 qvm_detail::zero_vec_<T,Dim> const &
0240 zero_vec()
0241 {
0242 return *(qvm_detail::zero_vec_<T,Dim> const *)qvm_detail::get_valid_ptr_vec_operations();
0243 }
0244
0245 template <class A>
0246 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0247 typename enable_if_c<
0248 is_vec<A>::value,
0249 void>::type
0250 set_zero( A & a )
0251 {
0252 assign(a,zero_vec<typename vec_traits<A>::scalar_type,vec_traits<A>::dim>());
0253 }
0254
0255
0256
0257 namespace
0258 qvm_detail
0259 {
0260 template <class OriginalType,class Scalar>
0261 class
0262 vector_scalar_cast_
0263 {
0264 vector_scalar_cast_( vector_scalar_cast_ const & );
0265 vector_scalar_cast_ & operator=( vector_scalar_cast_ const & );
0266 ~vector_scalar_cast_();
0267
0268 public:
0269
0270 template <class T>
0271 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0272 vector_scalar_cast_ &
0273 operator=( T const & x )
0274 {
0275 assign(*this,x);
0276 return *this;
0277 }
0278
0279 template <class R
0280 #if __cplusplus >= 201103L
0281 , class = typename enable_if<is_vec<R> >::type
0282 #endif
0283 >
0284 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0285 operator R() const
0286 {
0287 R r;
0288 assign(r,*this);
0289 return r;
0290 }
0291 };
0292
0293 template <bool> struct scalar_cast_vector_filter { };
0294 template <> struct scalar_cast_vector_filter<true> { typedef int type; };
0295 }
0296
0297 template <class OriginalType,class Scalar>
0298 struct
0299 vec_traits< qvm_detail::vector_scalar_cast_<OriginalType,Scalar> >
0300 {
0301 typedef Scalar scalar_type;
0302 typedef qvm_detail::vector_scalar_cast_<OriginalType,Scalar> this_vector;
0303 static int const dim=vec_traits<OriginalType>::dim;
0304
0305 template <int I>
0306 static
0307 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0308 scalar_type
0309 read_element( this_vector const & x )
0310 {
0311 BOOST_QVM_STATIC_ASSERT(I>=0);
0312 BOOST_QVM_STATIC_ASSERT(I<dim);
0313 return scalar_type(vec_traits<OriginalType>::template read_element<I>(reinterpret_cast<OriginalType const &>(x)));
0314 }
0315
0316 static
0317 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0318 scalar_type
0319 read_element_idx( int i, this_vector const & x )
0320 {
0321 BOOST_QVM_ASSERT(i>=0);
0322 BOOST_QVM_ASSERT(i<dim);
0323 return scalar_type(vec_traits<OriginalType>::read_element_idx(i,reinterpret_cast<OriginalType const &>(x)));
0324 }
0325 };
0326
0327 template <class OriginalType,class Scalar,int D>
0328 struct
0329 deduce_vec<qvm_detail::vector_scalar_cast_<OriginalType,Scalar>,D>
0330 {
0331 typedef vec<Scalar,D> type;
0332 };
0333
0334 template <class Scalar,class T>
0335 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0336 qvm_detail::vector_scalar_cast_<T,Scalar> const &
0337 scalar_cast( T const & x, typename qvm_detail::scalar_cast_vector_filter<is_vec<T>::value>::type=0 )
0338 {
0339 return reinterpret_cast<qvm_detail::vector_scalar_cast_<T,Scalar> const &>(x);
0340 }
0341
0342
0343
0344 namespace
0345 qvm_detail
0346 {
0347 template <int D>
0348 struct
0349 div_eq_vs_defined
0350 {
0351 static bool const value=false;
0352 };
0353 }
0354
0355 template <class A,class B>
0356 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0357 typename enable_if_c<
0358 is_vec<A>::value && is_scalar<B>::value &&
0359 !qvm_detail::div_eq_vs_defined<vec_traits<A>::dim>::value,
0360 A &>::type
0361 operator/=( A & a, B b )
0362 {
0363 for( int i=0; i!=vec_traits<A>::dim; ++i )
0364 write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)/b);
0365 return a;
0366 }
0367
0368
0369
0370 namespace
0371 qvm_detail
0372 {
0373 template <int D>
0374 struct
0375 div_vs_defined
0376 {
0377 static bool const value=false;
0378 };
0379 }
0380
0381 template <class A,class B>
0382 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0383 typename lazy_enable_if_c<
0384 is_vec<A>::value && is_scalar<B>::value &&
0385 !qvm_detail::div_vs_defined<vec_traits<A>::dim>::value,
0386 deduce_vec2<A,B,vec_traits<A>::dim> >::type
0387 operator/( A const & a, B b )
0388 {
0389 typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
0390 R r;
0391 for( int i=0; i!=vec_traits<A>::dim; ++i )
0392 write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)/b);
0393 return r;
0394 }
0395
0396
0397
0398 namespace
0399 qvm_detail
0400 {
0401 template <int D>
0402 struct
0403 dot_vv_defined
0404 {
0405 static bool const value=false;
0406 };
0407 }
0408
0409 template <class A,class B>
0410 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0411 typename lazy_enable_if_c<
0412 is_vec<A>::value && is_vec<B>::value &&
0413 vec_traits<A>::dim==vec_traits<B>::dim &&
0414 !qvm_detail::dot_vv_defined<vec_traits<A>::dim>::value,
0415 deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type
0416 dot( A const & a, B const & b )
0417 {
0418 typedef typename deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type>::type T;
0419 T m(scalar_traits<T>::value(0));
0420 for( int i=0; i!=vec_traits<A>::dim; ++i )
0421 m+=vec_traits<A>::read_element_idx(i,a)*vec_traits<B>::read_element_idx(i,b);
0422 return m;
0423 }
0424
0425
0426
0427 namespace
0428 qvm_detail
0429 {
0430 template <int D>
0431 struct
0432 eq_vv_defined
0433 {
0434 static bool const value=false;
0435 };
0436 }
0437
0438 template <class A,class B>
0439 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0440 typename enable_if_c<
0441 is_vec<A>::value && is_vec<B>::value &&
0442 vec_traits<A>::dim==vec_traits<B>::dim &&
0443 !qvm_detail::eq_vv_defined<vec_traits<A>::dim>::value,
0444 bool>::type
0445 operator==( A const & a, B const & b )
0446 {
0447 for( int i=0; i!=vec_traits<A>::dim; ++i )
0448 if( vec_traits<A>::read_element_idx(i,a)!=vec_traits<B>::read_element_idx(i,b) )
0449 return false;
0450 return true;
0451 }
0452
0453
0454
0455 namespace
0456 qvm_detail
0457 {
0458 template <int D>
0459 struct
0460 mag_sqr_v_defined
0461 {
0462 static bool const value=false;
0463 };
0464 }
0465
0466 template <class A>
0467 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0468 typename enable_if_c<
0469 is_vec<A>::value &&
0470 !qvm_detail::mag_sqr_v_defined<vec_traits<A>::dim>::value,
0471 typename vec_traits<A>::scalar_type>::type
0472 mag_sqr( A const & a )
0473 {
0474 typedef typename vec_traits<A>::scalar_type T;
0475 T m(scalar_traits<T>::value(0));
0476 for( int i=0; i!=vec_traits<A>::dim; ++i )
0477 {
0478 T x=vec_traits<A>::read_element_idx(i,a);
0479 m+=x*x;
0480 }
0481 return m;
0482 }
0483
0484
0485
0486 namespace
0487 qvm_detail
0488 {
0489 template <int D>
0490 struct
0491 mag_v_defined
0492 {
0493 static bool const value=false;
0494 };
0495 }
0496
0497 template <class A>
0498 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0499 typename enable_if_c<
0500 is_vec<A>::value &&
0501 !qvm_detail::mag_v_defined<vec_traits<A>::dim>::value,
0502 typename vec_traits<A>::scalar_type>::type
0503 mag( A const & a )
0504 {
0505 typedef typename vec_traits<A>::scalar_type T;
0506 T m(scalar_traits<T>::value(0));
0507 for( int i=0; i!=vec_traits<A>::dim; ++i )
0508 {
0509 T x=vec_traits<A>::read_element_idx(i,a);
0510 m+=x*x;
0511 }
0512 return sqrt(m);
0513 }
0514
0515
0516
0517 namespace
0518 qvm_detail
0519 {
0520 template <int D>
0521 struct
0522 minus_eq_vv_defined
0523 {
0524 static bool const value=false;
0525 };
0526 }
0527
0528 template <class A,class B>
0529 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0530 typename enable_if_c<
0531 is_vec<A>::value && is_vec<B>::value &&
0532 vec_traits<A>::dim==vec_traits<B>::dim &&
0533 !qvm_detail::minus_eq_vv_defined<vec_traits<A>::dim>::value,
0534 A &>::type
0535 operator-=( A & a, B const & b )
0536 {
0537 for( int i=0; i!=vec_traits<A>::dim; ++i )
0538 write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)-vec_traits<B>::read_element_idx(i,b));
0539 return a;
0540 }
0541
0542
0543
0544 namespace
0545 qvm_detail
0546 {
0547 template <int D>
0548 struct
0549 minus_v_defined
0550 {
0551 static bool const value=false;
0552 };
0553 }
0554
0555 template <class A>
0556 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0557 typename lazy_enable_if_c<
0558 is_vec<A>::value &&
0559 !qvm_detail::minus_v_defined<vec_traits<A>::dim>::value,
0560 deduce_vec<A> >::type
0561 operator-( A const & a )
0562 {
0563 typedef typename deduce_vec<A>::type R;
0564 R r;
0565 for( int i=0; i!=vec_traits<A>::dim; ++i )
0566 write_vec_element_idx(i,r,-vec_traits<A>::read_element_idx(i,a));
0567 return r;
0568 }
0569
0570
0571
0572 namespace
0573 qvm_detail
0574 {
0575 template <int D>
0576 struct
0577 minus_vv_defined
0578 {
0579 static bool const value=false;
0580 };
0581 }
0582
0583 template <class A,class B>
0584 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0585 typename lazy_enable_if_c<
0586 is_vec<A>::value && is_vec<B>::value &&
0587 vec_traits<A>::dim==vec_traits<B>::dim &&
0588 !qvm_detail::minus_vv_defined<vec_traits<A>::dim>::value,
0589 deduce_vec2<A,B,vec_traits<A>::dim> >::type
0590 operator-( A const & a, B const & b )
0591 {
0592 typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
0593 R r;
0594 for( int i=0; i!=vec_traits<A>::dim; ++i )
0595 write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)-vec_traits<B>::read_element_idx(i,b));
0596 return r;
0597 }
0598
0599
0600
0601 namespace
0602 qvm_detail
0603 {
0604 template <int D>
0605 struct
0606 mul_eq_vs_defined
0607 {
0608 static bool const value=false;
0609 };
0610 }
0611
0612 template <class A,class B>
0613 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0614 typename enable_if_c<
0615 is_vec<A>::value && is_scalar<B>::value &&
0616 !qvm_detail::mul_eq_vs_defined<vec_traits<A>::dim>::value,
0617 A &>::type
0618 operator*=( A & a, B b )
0619 {
0620 for( int i=0; i!=vec_traits<A>::dim; ++i )
0621 write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)*b);
0622 return a;
0623 }
0624
0625
0626
0627 namespace
0628 qvm_detail
0629 {
0630 template <int D>
0631 struct
0632 mul_vs_defined
0633 {
0634 static bool const value=false;
0635 };
0636 }
0637
0638 template <class A,class B>
0639 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0640 typename lazy_enable_if_c<
0641 is_vec<A>::value && is_scalar<B>::value &&
0642 !qvm_detail::mul_vs_defined<vec_traits<A>::dim>::value,
0643 deduce_vec2<A,B,vec_traits<A>::dim> >::type
0644 operator*( A const & a, B b )
0645 {
0646 typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
0647 R r;
0648 for( int i=0; i!=vec_traits<A>::dim; ++i )
0649 write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)*b);
0650 return r;
0651 }
0652
0653
0654
0655 namespace
0656 qvm_detail
0657 {
0658 template <int D>
0659 struct
0660 mul_sv_defined
0661 {
0662 static bool const value=false;
0663 };
0664 }
0665
0666 template <class A,class B>
0667 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0668 typename lazy_enable_if_c<
0669 is_scalar<A>::value && is_vec<B>::value &&
0670 !qvm_detail::mul_sv_defined<vec_traits<B>::dim>::value,
0671 deduce_vec2<A,B,vec_traits<B>::dim> >::type
0672 operator*( A a, B const & b )
0673 {
0674 typedef typename deduce_vec2<A,B,vec_traits<B>::dim>::type R;
0675 R r;
0676 for( int i=0; i!=vec_traits<B>::dim; ++i )
0677 write_vec_element_idx(i,r,a*vec_traits<B>::read_element_idx(i,b));
0678 return r;
0679 }
0680
0681
0682
0683 namespace
0684 qvm_detail
0685 {
0686 template <int D>
0687 struct
0688 neq_vv_defined
0689 {
0690 static bool const value=false;
0691 };
0692 }
0693
0694 template <class A,class B>
0695 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0696 typename enable_if_c<
0697 is_vec<A>::value && is_vec<B>::value &&
0698 vec_traits<A>::dim==vec_traits<B>::dim &&
0699 !qvm_detail::neq_vv_defined<vec_traits<A>::dim>::value,
0700 bool>::type
0701 operator!=( A const & a, B const & b )
0702 {
0703 for( int i=0; i!=vec_traits<A>::dim; ++i )
0704 if( vec_traits<A>::read_element_idx(i,a)!=vec_traits<B>::read_element_idx(i,b) )
0705 return true;
0706 return false;
0707 }
0708
0709
0710
0711 namespace
0712 qvm_detail
0713 {
0714 template <int D>
0715 struct
0716 normalize_v_defined
0717 {
0718 static bool const value=false;
0719 };
0720 }
0721
0722 template <class A>
0723 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0724 typename lazy_enable_if_c<
0725 is_vec<A>::value &&
0726 !qvm_detail::normalize_v_defined<vec_traits<A>::dim>::value,
0727 deduce_vec<A> >::type
0728 normalized( A const & a )
0729 {
0730 typedef typename vec_traits<A>::scalar_type T;
0731 T m(scalar_traits<T>::value(0));
0732 for( int i=0; i!=vec_traits<A>::dim; ++i )
0733 {
0734 T x=vec_traits<A>::read_element_idx(i,a);
0735 m+=x*x;
0736 }
0737 if( m==scalar_traits<T>::value(0) )
0738 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
0739 T rm=scalar_traits<T>::value(1)/sqrt(m);
0740 typedef typename deduce_vec<A>::type R;
0741 R r;
0742 for( int i=0; i!=vec_traits<A>::dim; ++i )
0743 write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)*rm);
0744 return r;
0745 }
0746
0747 template <class A>
0748 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0749 typename enable_if_c<
0750 is_vec<A>::value &&
0751 !qvm_detail::normalize_v_defined<vec_traits<A>::dim>::value,
0752 void>::type
0753 normalize( A & a )
0754 {
0755 typedef typename vec_traits<A>::scalar_type T;
0756 T m(scalar_traits<T>::value(0));
0757 for( int i=0; i!=vec_traits<A>::dim; ++i )
0758 {
0759 T x=vec_traits<A>::read_element_idx(i,a);
0760 m+=x*x;
0761 }
0762 if( m==scalar_traits<T>::value(0) )
0763 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
0764 T rm=scalar_traits<T>::value(1)/sqrt(m);
0765 for( int i=0; i!=vec_traits<A>::dim; ++i )
0766 write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)*rm);
0767 }
0768
0769
0770
0771 namespace
0772 qvm_detail
0773 {
0774 template <int D>
0775 struct
0776 plus_eq_vv_defined
0777 {
0778 static bool const value=false;
0779 };
0780 }
0781
0782 template <class A,class B>
0783 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0784 typename enable_if_c<
0785 is_vec<A>::value && is_vec<B>::value &&
0786 vec_traits<A>::dim==vec_traits<B>::dim &&
0787 !qvm_detail::plus_eq_vv_defined<vec_traits<A>::dim>::value,
0788 A &>::type
0789 operator+=( A & a, B const & b )
0790 {
0791 for( int i=0; i!=vec_traits<A>::dim; ++i )
0792 write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)+vec_traits<B>::read_element_idx(i,b));
0793 return a;
0794 }
0795
0796
0797
0798 namespace
0799 qvm_detail
0800 {
0801 template <int D>
0802 struct
0803 plus_vv_defined
0804 {
0805 static bool const value=false;
0806 };
0807 }
0808
0809 template <class A,class B>
0810 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0811 typename lazy_enable_if_c<
0812 is_vec<A>::value && is_vec<B>::value &&
0813 vec_traits<A>::dim==vec_traits<B>::dim &&
0814 !qvm_detail::plus_vv_defined<vec_traits<A>::dim>::value,
0815 deduce_vec2<A,B,vec_traits<A>::dim> >::type
0816 operator+( A const & a, B const & b )
0817 {
0818 typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
0819 R r;
0820 for( int i=0; i!=vec_traits<A>::dim; ++i )
0821 write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)+vec_traits<B>::read_element_idx(i,b));
0822 return r;
0823 }
0824
0825
0826
0827 namespace
0828 qvm_detail
0829 {
0830 template <class T>
0831 class
0832 vref_
0833 {
0834 vref_( vref_ const & );
0835 vref_ & operator=( vref_ const & );
0836 ~vref_();
0837
0838 public:
0839
0840 template <class R>
0841 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0842 vref_ &
0843 operator=( R const & x )
0844 {
0845 assign(*this,x);
0846 return *this;
0847 }
0848
0849 template <class R
0850 #if __cplusplus >= 201103L
0851 , class = typename enable_if<is_vec<R> >::type
0852 #endif
0853 >
0854 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0855 operator R() const
0856 {
0857 R r;
0858 assign(r,*this);
0859 return r;
0860 }
0861 };
0862
0863 template <class V,bool WriteElementRef=vec_write_element_ref<V>::value>
0864 struct vref_write_traits;
0865
0866 template <class V>
0867 struct
0868 vref_write_traits<V,true>
0869 {
0870 typedef typename vec_traits<V>::scalar_type scalar_type;
0871 typedef qvm_detail::vref_<V> this_vector;
0872 static int const dim=vec_traits<V>::dim;
0873
0874 template <int I>
0875 static
0876 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0877 scalar_type &
0878 write_element( this_vector & x )
0879 {
0880 BOOST_QVM_STATIC_ASSERT(I>=0);
0881 BOOST_QVM_STATIC_ASSERT(I<dim);
0882 return vec_traits<V>::template write_element<I>(reinterpret_cast<V &>(x));
0883 }
0884
0885 static
0886 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0887 scalar_type &
0888 write_element_idx( int i, this_vector & x )
0889 {
0890 BOOST_QVM_ASSERT(i>=0);
0891 BOOST_QVM_ASSERT(i<dim);
0892 return vec_traits<V>::write_element_idx(i,reinterpret_cast<V &>(x));
0893 }
0894 };
0895
0896 template <class V>
0897 struct
0898 vref_write_traits<V,false>
0899 {
0900 typedef typename vec_traits<V>::scalar_type scalar_type;
0901 typedef qvm_detail::vref_<V> this_vector;
0902 static int const dim=vec_traits<V>::dim;
0903
0904 template <int I>
0905 static
0906 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0907 void
0908 write_element( this_vector & x, scalar_type s )
0909 {
0910 BOOST_QVM_STATIC_ASSERT(I>=0);
0911 BOOST_QVM_STATIC_ASSERT(I<dim);
0912 vec_traits<V>::template write_element<I>(reinterpret_cast<V &>(x), s);
0913 }
0914
0915 static
0916 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0917 void
0918 write_element_idx( int i, this_vector & x, scalar_type s )
0919 {
0920 BOOST_QVM_ASSERT(i>=0);
0921 BOOST_QVM_ASSERT(i<dim);
0922 vec_traits<V>::write_element_idx(i,reinterpret_cast<V &>(x), s);
0923 }
0924 };
0925 }
0926
0927 template <class V>
0928 struct
0929 vec_traits< qvm_detail::vref_<V> >:
0930 qvm_detail::vref_write_traits<V>
0931 {
0932 typedef typename vec_traits<V>::scalar_type scalar_type;
0933 typedef qvm_detail::vref_<V> this_vector;
0934 static int const dim=vec_traits<V>::dim;
0935
0936 template <int I>
0937 static
0938 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0939 scalar_type
0940 read_element( this_vector const & x )
0941 {
0942 BOOST_QVM_STATIC_ASSERT(I>=0);
0943 BOOST_QVM_STATIC_ASSERT(I<dim);
0944 return vec_traits<V>::template read_element<I>(reinterpret_cast<V const &>(x));
0945 }
0946
0947 static
0948 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
0949 scalar_type
0950 read_element_idx( int i, this_vector const & x )
0951 {
0952 BOOST_QVM_ASSERT(i>=0);
0953 BOOST_QVM_ASSERT(i<dim);
0954 return vec_traits<V>::read_element_idx(i,reinterpret_cast<V const &>(x));
0955 }
0956 };
0957
0958 template <class V,int D>
0959 struct
0960 deduce_vec<qvm_detail::vref_<V>,D>
0961 {
0962 typedef vec<typename vec_traits<V>::scalar_type,D> type;
0963 };
0964
0965 template <class V>
0966 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0967 typename enable_if_c<
0968 is_vec<V>::value,
0969 qvm_detail::vref_<V> const &>::type
0970 vref( V const & a )
0971 {
0972 return reinterpret_cast<qvm_detail::vref_<V> const &>(a);
0973 }
0974
0975 template <class V>
0976 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
0977 typename enable_if_c<
0978 is_vec<V>::value,
0979 qvm_detail::vref_<V> &>::type
0980 vref( V & a )
0981 {
0982 return reinterpret_cast<qvm_detail::vref_<V> &>(a);
0983 }
0984
0985
0986
0987 namespace
0988 sfinae
0989 {
0990 using ::boost::qvm::to_string;
0991 using ::boost::qvm::assign;
0992 using ::boost::qvm::convert_to;
0993 using ::boost::qvm::cross;
0994 using ::boost::qvm::cmp;
0995 using ::boost::qvm::set_zero;
0996 using ::boost::qvm::scalar_cast;
0997 using ::boost::qvm::operator/=;
0998 using ::boost::qvm::operator/;
0999 using ::boost::qvm::dot;
1000 using ::boost::qvm::operator==;
1001 using ::boost::qvm::mag_sqr;
1002 using ::boost::qvm::mag;
1003 using ::boost::qvm::operator-=;
1004 using ::boost::qvm::operator-;
1005 using ::boost::qvm::operator*=;
1006 using ::boost::qvm::operator*;
1007 using ::boost::qvm::operator!=;
1008 using ::boost::qvm::normalized;
1009 using ::boost::qvm::normalize;
1010 using ::boost::qvm::operator+=;
1011 using ::boost::qvm::operator+;
1012 using ::boost::qvm::vref;
1013 }
1014
1015 } }
1016
1017 #endif