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