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