Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright 2008-2022 Emil Dotchevski and Reverge Studios, Inc.
0005 // Copyright 2019 agate-pris
0006 
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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