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