Back to home page

EIC code displayed by LXR

 
 

    


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