File indexing completed on 2025-01-18 09:51:02
0001 #ifndef BOOST_QVM_GEN_VEC_OPERATIONS2_HPP_INCLUDED
0002 #define BOOST_QVM_GEN_VEC_OPERATIONS2_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <boost/qvm/deduce_scalar.hpp>
0012 #include <boost/qvm/deduce_vec.hpp>
0013 #include <boost/qvm/error.hpp>
0014 #include <boost/qvm/gen/vec_assign2.hpp>
0015 #include <boost/qvm/math.hpp>
0016 #include <boost/qvm/static_assert.hpp>
0017 #include <boost/qvm/throw_exception.hpp>
0018
0019 namespace boost { namespace qvm {
0020
0021 template <class A,class B>
0022 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0023 typename lazy_enable_if_c<
0024 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0025 deduce_vec2<A,B,2> >::type
0026 operator+( A const & a, B const & b )
0027 {
0028 typedef typename deduce_vec2<A,B,2>::type R;
0029 BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim==2);
0030 R r;
0031 write_vec_element<0>(r,vec_traits<A>::template read_element<0>(a)+vec_traits<B>::template read_element<0>(b));
0032 write_vec_element<1>(r,vec_traits<A>::template read_element<1>(a)+vec_traits<B>::template read_element<1>(b));
0033 return r;
0034 }
0035
0036 namespace
0037 sfinae
0038 {
0039 using ::boost::qvm::operator+;
0040 }
0041
0042 namespace
0043 qvm_detail
0044 {
0045 template <int D>
0046 struct plus_vv_defined;
0047
0048 template <>
0049 struct
0050 plus_vv_defined<2>
0051 {
0052 static bool const value=true;
0053 };
0054 }
0055
0056 template <class A,class B>
0057 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0058 typename lazy_enable_if_c<
0059 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0060 deduce_vec2<A,B,2> >::type
0061 operator-( A const & a, B const & b )
0062 {
0063 typedef typename deduce_vec2<A,B,2>::type R;
0064 BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim==2);
0065 R r;
0066 write_vec_element<0>(r,vec_traits<A>::template read_element<0>(a)-vec_traits<B>::template read_element<0>(b));
0067 write_vec_element<1>(r,vec_traits<A>::template read_element<1>(a)-vec_traits<B>::template read_element<1>(b));
0068 return r;
0069 }
0070
0071 namespace
0072 sfinae
0073 {
0074 using ::boost::qvm::operator-;
0075 }
0076
0077 namespace
0078 qvm_detail
0079 {
0080 template <int D>
0081 struct minus_vv_defined;
0082
0083 template <>
0084 struct
0085 minus_vv_defined<2>
0086 {
0087 static bool const value=true;
0088 };
0089 }
0090
0091 template <class A,class B>
0092 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0093 typename enable_if_c<
0094 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0095 A &>::type
0096 operator+=( A & a, B const & b )
0097 {
0098 write_vec_element<0>(a,vec_traits<A>::template read_element<0>(a)+vec_traits<B>::template read_element<0>(b));
0099 write_vec_element<1>(a,vec_traits<A>::template read_element<1>(a)+vec_traits<B>::template read_element<1>(b));
0100 return a;
0101 }
0102
0103 namespace
0104 sfinae
0105 {
0106 using ::boost::qvm::operator+=;
0107 }
0108
0109 namespace
0110 qvm_detail
0111 {
0112 template <int D>
0113 struct plus_eq_vv_defined;
0114
0115 template <>
0116 struct
0117 plus_eq_vv_defined<2>
0118 {
0119 static bool const value=true;
0120 };
0121 }
0122
0123 template <class A,class B>
0124 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0125 typename enable_if_c<
0126 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0127 A &>::type
0128 operator-=( A & a, B const & b )
0129 {
0130 write_vec_element<0>(a,vec_traits<A>::template read_element<0>(a)-vec_traits<B>::template read_element<0>(b));
0131 write_vec_element<1>(a,vec_traits<A>::template read_element<1>(a)-vec_traits<B>::template read_element<1>(b));
0132 return a;
0133 }
0134
0135 namespace
0136 sfinae
0137 {
0138 using ::boost::qvm::operator-=;
0139 }
0140
0141 namespace
0142 qvm_detail
0143 {
0144 template <int D>
0145 struct minus_eq_vv_defined;
0146
0147 template <>
0148 struct
0149 minus_eq_vv_defined<2>
0150 {
0151 static bool const value=true;
0152 };
0153 }
0154
0155 template <class A,class B>
0156 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0157 typename lazy_enable_if_c<
0158 vec_traits<A>::dim==2 && is_scalar<B>::value,
0159 deduce_vec2<A,B,vec_traits<A>::dim> >::type
0160 operator*( A const & a, B b )
0161 {
0162 typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
0163 R r;
0164 write_vec_element<0>(r,vec_traits<A>::template read_element<0>(a)*b);
0165 write_vec_element<1>(r,vec_traits<A>::template read_element<1>(a)*b);
0166 return r;
0167 }
0168
0169 namespace
0170 sfinae
0171 {
0172 using ::boost::qvm::operator*;
0173 }
0174
0175 namespace
0176 qvm_detail
0177 {
0178 template <int D>
0179 struct mul_vs_defined;
0180
0181 template <>
0182 struct
0183 mul_vs_defined<2>
0184 {
0185 static bool const value=true;
0186 };
0187 }
0188
0189 template <class A,class B>
0190 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0191 typename lazy_enable_if_c<
0192 is_scalar<A>::value && vec_traits<B>::dim==2,
0193 deduce_vec2<A,B,vec_traits<B>::dim> >::type
0194 operator*( A a, B const & b )
0195 {
0196 typedef typename deduce_vec2<A,B,vec_traits<B>::dim>::type R;
0197 R r;
0198 write_vec_element<0>(r,a*vec_traits<B>::template read_element<0>(b));
0199 write_vec_element<1>(r,a*vec_traits<B>::template read_element<1>(b));
0200 return r;
0201 }
0202
0203 namespace
0204 sfinae
0205 {
0206 using ::boost::qvm::operator*;
0207 }
0208
0209 namespace
0210 qvm_detail
0211 {
0212 template <int D>
0213 struct mul_sv_defined;
0214
0215 template <>
0216 struct
0217 mul_sv_defined<2>
0218 {
0219 static bool const value=true;
0220 };
0221 }
0222
0223 template <class A,class B>
0224 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0225 typename enable_if_c<
0226 vec_traits<A>::dim==2 && is_scalar<B>::value,
0227 A &>::type
0228 operator*=( A & a, B b )
0229 {
0230 write_vec_element<0>(a, vec_traits<A>::template read_element<0>(a)*b);
0231 write_vec_element<1>(a, vec_traits<A>::template read_element<1>(a)*b);
0232 return a;
0233 }
0234
0235 namespace
0236 sfinae
0237 {
0238 using ::boost::qvm::operator*=;
0239 }
0240
0241 namespace
0242 qvm_detail
0243 {
0244 template <int D>
0245 struct mul_eq_vs_defined;
0246
0247 template <>
0248 struct
0249 mul_eq_vs_defined<2>
0250 {
0251 static bool const value=true;
0252 };
0253 }
0254
0255 template <class A,class B>
0256 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0257 typename lazy_enable_if_c<
0258 vec_traits<A>::dim==2 && is_scalar<B>::value,
0259 deduce_vec2<A,B,vec_traits<A>::dim> >::type
0260 operator/( A const & a, B b )
0261 {
0262 typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
0263 R r;
0264 write_vec_element<0>(r,vec_traits<A>::template read_element<0>(a)/b);
0265 write_vec_element<1>(r,vec_traits<A>::template read_element<1>(a)/b);
0266 return r;
0267 }
0268
0269 namespace
0270 sfinae
0271 {
0272 using ::boost::qvm::operator/;
0273 }
0274
0275 namespace
0276 qvm_detail
0277 {
0278 template <int D>
0279 struct div_vs_defined;
0280
0281 template <>
0282 struct
0283 div_vs_defined<2>
0284 {
0285 static bool const value=true;
0286 };
0287 }
0288
0289 template <class A,class B>
0290 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0291 typename enable_if_c<
0292 vec_traits<A>::dim==2 && is_scalar<B>::value,
0293 A &>::type
0294 operator/=( A & a, B b )
0295 {
0296 write_vec_element<0>(a, vec_traits<A>::template read_element<0>(a)/b);
0297 write_vec_element<1>(a, vec_traits<A>::template read_element<1>(a)/b);
0298 return a;
0299 }
0300
0301 namespace
0302 sfinae
0303 {
0304 using ::boost::qvm::operator/=;
0305 }
0306
0307 namespace
0308 qvm_detail
0309 {
0310 template <int D>
0311 struct div_eq_vs_defined;
0312
0313 template <>
0314 struct
0315 div_eq_vs_defined<2>
0316 {
0317 static bool const value=true;
0318 };
0319 }
0320
0321 template <class R,class A>
0322 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0323 typename enable_if_c<
0324 is_vec<A>::value &&
0325 vec_traits<R>::dim==2 && vec_traits<A>::dim==2,
0326 R>::type
0327 convert_to( A const & a )
0328 {
0329 R r;
0330 write_vec_element<0>(r,vec_traits<A>::template read_element<0>(a));
0331 write_vec_element<1>(r,vec_traits<A>::template read_element<1>(a));
0332 return r;
0333 }
0334
0335 namespace
0336 sfinae
0337 {
0338 using ::boost::qvm::convert_to;
0339 }
0340
0341 namespace
0342 qvm_detail
0343 {
0344 template <int D>
0345 struct convert_to_v_defined;
0346
0347 template <>
0348 struct
0349 convert_to_v_defined<2>
0350 {
0351 static bool const value=true;
0352 };
0353 }
0354
0355 template <class A,class B>
0356 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0357 typename enable_if_c<
0358 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0359 bool>::type
0360 operator==( A const & a, B const & b )
0361 {
0362 return
0363 vec_traits<A>::template read_element<0>(a)==vec_traits<B>::template read_element<0>(b) &&
0364 vec_traits<A>::template read_element<1>(a)==vec_traits<B>::template read_element<1>(b);
0365 }
0366
0367 namespace
0368 sfinae
0369 {
0370 using ::boost::qvm::operator==;
0371 }
0372
0373 namespace
0374 qvm_detail
0375 {
0376 template <int D>
0377 struct eq_vv_defined;
0378
0379 template <>
0380 struct
0381 eq_vv_defined<2>
0382 {
0383 static bool const value=true;
0384 };
0385 }
0386
0387 template <class A,class B>
0388 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0389 typename enable_if_c<
0390 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0391 bool>::type
0392 operator!=( A const & a, B const & b )
0393 {
0394 return
0395 !(vec_traits<A>::template read_element<0>(a)==vec_traits<B>::template read_element<0>(b)) ||
0396 !(vec_traits<A>::template read_element<1>(a)==vec_traits<B>::template read_element<1>(b));
0397 }
0398
0399 namespace
0400 sfinae
0401 {
0402 using ::boost::qvm::operator!=;
0403 }
0404
0405 namespace
0406 qvm_detail
0407 {
0408 template <int D>
0409 struct neq_vv_defined;
0410
0411 template <>
0412 struct
0413 neq_vv_defined<2>
0414 {
0415 static bool const value=true;
0416 };
0417 }
0418
0419 template <class A>
0420 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0421 typename lazy_enable_if_c<
0422 vec_traits<A>::dim==2,
0423 deduce_vec<A> >::type
0424 operator-( A const & a )
0425 {
0426 typedef typename deduce_vec<A>::type R;
0427 R r;
0428 write_vec_element<0>(r,-vec_traits<A>::template read_element<0>(a));
0429 write_vec_element<1>(r,-vec_traits<A>::template read_element<1>(a));
0430 return r;
0431 }
0432
0433 namespace
0434 sfinae
0435 {
0436 using ::boost::qvm::operator-;
0437 }
0438
0439 namespace
0440 qvm_detail
0441 {
0442 template <int D>
0443 struct minus_v_defined;
0444
0445 template <>
0446 struct
0447 minus_v_defined<2>
0448 {
0449 static bool const value=true;
0450 };
0451 }
0452
0453 template <class A>
0454 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0455 typename enable_if_c<
0456 is_vec<A>::value && vec_traits<A>::dim==2,
0457 typename vec_traits<A>::scalar_type>::type
0458 mag( A const & a )
0459 {
0460 typedef typename vec_traits<A>::scalar_type T;
0461 T const a0=vec_traits<A>::template read_element<0>(a);
0462 T const a1=vec_traits<A>::template read_element<1>(a);
0463 T const m2=a0*a0+a1*a1;
0464 T const mag=sqrt(m2);
0465 return mag;
0466 }
0467
0468 namespace
0469 sfinae
0470 {
0471 using ::boost::qvm::mag;
0472 }
0473
0474 namespace
0475 qvm_detail
0476 {
0477 template <int D>
0478 struct mag_v_defined;
0479
0480 template <>
0481 struct
0482 mag_v_defined<2>
0483 {
0484 static bool const value=true;
0485 };
0486 }
0487
0488 template <class A>
0489 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0490 typename enable_if_c<
0491 is_vec<A>::value && vec_traits<A>::dim==2,
0492 typename vec_traits<A>::scalar_type>::type
0493 mag_sqr( A const & a )
0494 {
0495 typedef typename vec_traits<A>::scalar_type T;
0496 T const a0=vec_traits<A>::template read_element<0>(a);
0497 T const a1=vec_traits<A>::template read_element<1>(a);
0498 T const m2=a0*a0+a1*a1;
0499 return m2;
0500 }
0501
0502 namespace
0503 sfinae
0504 {
0505 using ::boost::qvm::mag_sqr;
0506 }
0507
0508 namespace
0509 qvm_detail
0510 {
0511 template <int D>
0512 struct mag_sqr_v_defined;
0513
0514 template <>
0515 struct
0516 mag_sqr_v_defined<2>
0517 {
0518 static bool const value=true;
0519 };
0520 }
0521
0522 template <class A>
0523 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0524 typename lazy_enable_if_c<
0525 vec_traits<A>::dim==2,
0526 deduce_vec<A> >::type
0527 normalized( A const & a )
0528 {
0529 typedef typename vec_traits<A>::scalar_type T;
0530 T const a0=vec_traits<A>::template read_element<0>(a);
0531 T const a1=vec_traits<A>::template read_element<1>(a);
0532 T const m2=a0*a0+a1*a1;
0533 if( m2==scalar_traits<typename vec_traits<A>::scalar_type>::value(0) )
0534 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
0535 T const rm=scalar_traits<T>::value(1)/sqrt(m2);
0536 typedef typename deduce_vec<A>::type R;
0537 R r;
0538 write_vec_element<0>(r,a0*rm);
0539 write_vec_element<1>(r,a1*rm);
0540 return r;
0541 }
0542
0543 namespace
0544 sfinae
0545 {
0546 using ::boost::qvm::normalized;
0547 }
0548
0549 template <class A>
0550 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0551 typename enable_if_c<
0552 vec_traits<A>::dim==2,
0553 void>::type
0554 normalize( A & a )
0555 {
0556 typedef typename vec_traits<A>::scalar_type T;
0557 T const a0=vec_traits<A>::template read_element<0>(a);
0558 T const a1=vec_traits<A>::template read_element<1>(a);
0559 T const m2=a0*a0+a1*a1;
0560 if( m2==scalar_traits<typename vec_traits<A>::scalar_type>::value(0) )
0561 BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
0562 T const rm=scalar_traits<T>::value(1)/sqrt(m2);
0563 write_vec_element<0>(a,vec_traits<A>::template read_element<0>(a)*rm);
0564 write_vec_element<1>(a,vec_traits<A>::template read_element<1>(a)*rm);
0565 }
0566
0567 namespace
0568 sfinae
0569 {
0570 using ::boost::qvm::normalize;
0571 }
0572
0573 namespace
0574 qvm_detail
0575 {
0576 template <int D>
0577 struct normalize_v_defined;
0578
0579 template <>
0580 struct
0581 normalize_v_defined<2>
0582 {
0583 static bool const value=true;
0584 };
0585 }
0586
0587 template <class A,class B>
0588 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0589 typename lazy_enable_if_c<
0590 vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
0591 deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type
0592 dot( A const & a, B const & b )
0593 {
0594 typedef typename vec_traits<A>::scalar_type Ta;
0595 typedef typename vec_traits<B>::scalar_type Tb;
0596 typedef typename deduce_scalar<Ta,Tb>::type Tr;
0597 Ta const a0=vec_traits<A>::template read_element<0>(a);
0598 Ta const a1=vec_traits<A>::template read_element<1>(a);
0599 Tb const b0=vec_traits<B>::template read_element<0>(b);
0600 Tb const b1=vec_traits<B>::template read_element<1>(b);
0601 Tr const dot=a0*b0+a1*b1;
0602 return dot;
0603 }
0604
0605 namespace
0606 sfinae
0607 {
0608 using ::boost::qvm::dot;
0609 }
0610
0611 namespace
0612 qvm_detail
0613 {
0614 template <int D>
0615 struct dot_vv_defined;
0616
0617 template <>
0618 struct
0619 dot_vv_defined<2>
0620 {
0621 static bool const value=true;
0622 };
0623 }
0624
0625 } }
0626
0627 #endif