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