vec_operations.hpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. #ifndef BOOST_QVM_VEC_OPERATIONS_HPP_INCLUDED
  2. #define BOOST_QVM_VEC_OPERATIONS_HPP_INCLUDED
  3. // Copyright 2008-2022 Emil Dotchevski and Reverge Studios, Inc.
  4. // Copyright 2019 agate-pris
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #include <boost/qvm/detail/vec_assign.hpp>
  8. #include <boost/qvm/vec_operations2.hpp>
  9. #include <boost/qvm/vec_operations3.hpp>
  10. #include <boost/qvm/vec_operations4.hpp>
  11. #include <boost/qvm/assert.hpp>
  12. #include <boost/qvm/scalar_traits.hpp>
  13. #include <boost/qvm/to_string.hpp>
  14. namespace boost { namespace qvm {
  15. namespace
  16. qvm_detail
  17. {
  18. BOOST_QVM_INLINE_CRITICAL
  19. void const *
  20. get_valid_ptr_vec_operations()
  21. {
  22. static int const obj=0;
  23. return &obj;
  24. }
  25. }
  26. ////////////////////////////////////////////////
  27. namespace
  28. qvm_detail
  29. {
  30. template <int D>
  31. struct
  32. to_string_v_defined
  33. {
  34. static bool const value=false;
  35. };
  36. template <int I,int DimMinusOne>
  37. struct
  38. to_string_vector_elements
  39. {
  40. template <class A>
  41. static
  42. std::string
  43. f( A const & a )
  44. {
  45. using namespace qvm_to_string_detail;
  46. return to_string(vec_traits<A>::template read_element<I>(a))+','+to_string_vector_elements<I+1,DimMinusOne>::f(a);
  47. }
  48. };
  49. template <int DimMinusOne>
  50. struct
  51. to_string_vector_elements<DimMinusOne,DimMinusOne>
  52. {
  53. template <class A>
  54. static
  55. std::string
  56. f( A const & a )
  57. {
  58. using namespace qvm_to_string_detail;
  59. return to_string(vec_traits<A>::template read_element<DimMinusOne>(a));
  60. }
  61. };
  62. }
  63. template <class A>
  64. inline
  65. typename enable_if_c<
  66. is_vec<A>::value &&
  67. !qvm_detail::to_string_v_defined<vec_traits<A>::dim>::value,
  68. std::string>::type
  69. to_string( A const & a )
  70. {
  71. return '('+qvm_detail::to_string_vector_elements<0,vec_traits<A>::dim-1>::f(a)+')';
  72. }
  73. ////////////////////////////////////////////////
  74. namespace
  75. qvm_detail
  76. {
  77. template <int D>
  78. struct
  79. convert_to_v_defined
  80. {
  81. static bool const value=false;
  82. };
  83. }
  84. template <class R,class A>
  85. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  86. typename enable_if_c<
  87. is_vec<R>::value && is_vec<A>::value &&
  88. vec_traits<R>::dim==vec_traits<A>::dim &&
  89. !qvm_detail::convert_to_v_defined<vec_traits<R>::dim>::value,
  90. R>::type
  91. convert_to( A const & a )
  92. {
  93. R r; assign(r,a);
  94. return r;
  95. }
  96. ////////////////////////////////////////////////
  97. template <class A,class B>
  98. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  99. typename lazy_enable_if_c<
  100. is_vec<A>::value && is_vec<B>::value &&
  101. vec_traits<A>::dim==3 && vec_traits<B>::dim==3,
  102. deduce_vec2<A,B,3> >::type
  103. cross( A const & a, B const & b )
  104. {
  105. typedef typename deduce_vec2<A,B,3>::type R;
  106. R r;
  107. write_vec_element<0>(r,
  108. vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<2>(b)-
  109. vec_traits<A>::template read_element<2>(a)*vec_traits<B>::template read_element<1>(b));
  110. write_vec_element<1>(r,
  111. vec_traits<A>::template read_element<2>(a)*vec_traits<B>::template read_element<0>(b)-
  112. vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<2>(b));
  113. write_vec_element<2>(r,
  114. vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<1>(b)-
  115. vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<0>(b));
  116. return r;
  117. }
  118. template <class A,class B>
  119. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  120. typename lazy_enable_if_c<
  121. is_vec<A>::value && is_vec<B>::value &&
  122. vec_traits<A>::dim==2 && vec_traits<B>::dim==2,
  123. deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type
  124. cross( A const & a, B const & b )
  125. {
  126. typedef typename deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type>::type R;
  127. R const r =
  128. vec_traits<A>::template read_element<0>(a)*vec_traits<B>::template read_element<1>(b)-
  129. vec_traits<A>::template read_element<1>(a)*vec_traits<B>::template read_element<0>(b);
  130. return r;
  131. }
  132. ////////////////////////////////////////////////
  133. template <class A,class B,class Cmp>
  134. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  135. typename enable_if_c<
  136. is_vec<A>::value && is_vec<B>::value &&
  137. vec_traits<A>::dim==vec_traits<B>::dim,
  138. bool>::type
  139. cmp( A const & a, B const & b, Cmp f )
  140. {
  141. for( int i=0; i!=vec_traits<A>::dim; ++i )
  142. if( !f(
  143. vec_traits<A>::read_element_idx(i,a),
  144. vec_traits<B>::read_element_idx(i,b)) )
  145. return false;
  146. return true;
  147. }
  148. ////////////////////////////////////////////////
  149. namespace
  150. qvm_detail
  151. {
  152. template <class T,int Dim>
  153. class
  154. zero_vec_
  155. {
  156. zero_vec_( zero_vec_ const & );
  157. zero_vec_ & operator=( zero_vec_ const & );
  158. ~zero_vec_();
  159. public:
  160. template <class R
  161. #if __cplusplus >= 201103L
  162. , class = typename enable_if<is_vec<R> >::type
  163. #endif
  164. >
  165. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  166. operator R() const
  167. {
  168. R r;
  169. assign(r,*this);
  170. return r;
  171. }
  172. };
  173. }
  174. template <class V>
  175. struct vec_traits;
  176. template <class T,int Dim>
  177. struct
  178. vec_traits< qvm_detail::zero_vec_<T,Dim> >
  179. {
  180. typedef qvm_detail::zero_vec_<T,Dim> this_vector;
  181. typedef T scalar_type;
  182. static int const dim=Dim;
  183. template <int I>
  184. static
  185. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  186. scalar_type
  187. read_element( this_vector const & )
  188. {
  189. BOOST_QVM_STATIC_ASSERT(I>=0);
  190. BOOST_QVM_STATIC_ASSERT(I<Dim);
  191. return scalar_traits<scalar_type>::value(0);
  192. }
  193. static
  194. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  195. scalar_type
  196. read_element_idx( int i, this_vector const & )
  197. {
  198. BOOST_QVM_ASSERT(i>=0);
  199. BOOST_QVM_ASSERT(i<Dim);
  200. return scalar_traits<scalar_type>::value(0);
  201. }
  202. };
  203. template <class T,int Dim,int D>
  204. struct
  205. deduce_vec<qvm_detail::zero_vec_<T,Dim>,D>
  206. {
  207. typedef vec<T,D> type;
  208. };
  209. template <class T,int Dim>
  210. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  211. qvm_detail::zero_vec_<T,Dim> const &
  212. zero_vec()
  213. {
  214. return *(qvm_detail::zero_vec_<T,Dim> const *)qvm_detail::get_valid_ptr_vec_operations();
  215. }
  216. template <class A>
  217. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  218. typename enable_if_c<
  219. is_vec<A>::value,
  220. void>::type
  221. set_zero( A & a )
  222. {
  223. assign(a,zero_vec<typename vec_traits<A>::scalar_type,vec_traits<A>::dim>());
  224. }
  225. ////////////////////////////////////////////////
  226. namespace
  227. qvm_detail
  228. {
  229. template <class OriginalType,class Scalar>
  230. class
  231. vector_scalar_cast_
  232. {
  233. vector_scalar_cast_( vector_scalar_cast_ const & );
  234. vector_scalar_cast_ & operator=( vector_scalar_cast_ const & );
  235. ~vector_scalar_cast_();
  236. public:
  237. template <class T>
  238. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  239. vector_scalar_cast_ &
  240. operator=( T const & x )
  241. {
  242. assign(*this,x);
  243. return *this;
  244. }
  245. template <class R
  246. #if __cplusplus >= 201103L
  247. , class = typename enable_if<is_vec<R> >::type
  248. #endif
  249. >
  250. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  251. operator R() const
  252. {
  253. R r;
  254. assign(r,*this);
  255. return r;
  256. }
  257. };
  258. template <bool> struct scalar_cast_vector_filter { };
  259. template <> struct scalar_cast_vector_filter<true> { typedef int type; };
  260. }
  261. template <class OriginalType,class Scalar>
  262. struct
  263. vec_traits< qvm_detail::vector_scalar_cast_<OriginalType,Scalar> >
  264. {
  265. typedef Scalar scalar_type;
  266. typedef qvm_detail::vector_scalar_cast_<OriginalType,Scalar> this_vector;
  267. static int const dim=vec_traits<OriginalType>::dim;
  268. template <int I>
  269. static
  270. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  271. scalar_type
  272. read_element( this_vector const & x )
  273. {
  274. BOOST_QVM_STATIC_ASSERT(I>=0);
  275. BOOST_QVM_STATIC_ASSERT(I<dim);
  276. return scalar_type(vec_traits<OriginalType>::template read_element<I>(reinterpret_cast<OriginalType const &>(x)));
  277. }
  278. static
  279. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  280. scalar_type
  281. read_element_idx( int i, this_vector const & x )
  282. {
  283. BOOST_QVM_ASSERT(i>=0);
  284. BOOST_QVM_ASSERT(i<dim);
  285. return scalar_type(vec_traits<OriginalType>::read_element_idx(i,reinterpret_cast<OriginalType const &>(x)));
  286. }
  287. };
  288. template <class OriginalType,class Scalar,int D>
  289. struct
  290. deduce_vec<qvm_detail::vector_scalar_cast_<OriginalType,Scalar>,D>
  291. {
  292. typedef vec<Scalar,D> type;
  293. };
  294. template <class Scalar,class T>
  295. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  296. qvm_detail::vector_scalar_cast_<T,Scalar> const &
  297. scalar_cast( T const & x, typename qvm_detail::scalar_cast_vector_filter<is_vec<T>::value>::type=0 )
  298. {
  299. return reinterpret_cast<qvm_detail::vector_scalar_cast_<T,Scalar> const &>(x);
  300. }
  301. ////////////////////////////////////////////////
  302. namespace
  303. qvm_detail
  304. {
  305. template <int D>
  306. struct
  307. div_eq_vs_defined
  308. {
  309. static bool const value=false;
  310. };
  311. }
  312. template <class A,class B>
  313. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  314. typename enable_if_c<
  315. is_vec<A>::value && is_scalar<B>::value &&
  316. !qvm_detail::div_eq_vs_defined<vec_traits<A>::dim>::value,
  317. A &>::type
  318. operator/=( A & a, B b )
  319. {
  320. for( int i=0; i!=vec_traits<A>::dim; ++i )
  321. write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)/b);
  322. return a;
  323. }
  324. ////////////////////////////////////////////////
  325. namespace
  326. qvm_detail
  327. {
  328. template <int D>
  329. struct
  330. div_vs_defined
  331. {
  332. static bool const value=false;
  333. };
  334. }
  335. template <class A,class B>
  336. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  337. typename lazy_enable_if_c<
  338. is_vec<A>::value && is_scalar<B>::value &&
  339. !qvm_detail::div_vs_defined<vec_traits<A>::dim>::value,
  340. deduce_vec2<A,B,vec_traits<A>::dim> >::type
  341. operator/( A const & a, B b )
  342. {
  343. typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
  344. R r;
  345. for( int i=0; i!=vec_traits<A>::dim; ++i )
  346. write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)/b);
  347. return r;
  348. }
  349. ////////////////////////////////////////////////
  350. namespace
  351. qvm_detail
  352. {
  353. template <int D>
  354. struct
  355. dot_vv_defined
  356. {
  357. static bool const value=false;
  358. };
  359. }
  360. template <class A,class B>
  361. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  362. typename lazy_enable_if_c<
  363. is_vec<A>::value && is_vec<B>::value &&
  364. vec_traits<A>::dim==vec_traits<B>::dim &&
  365. !qvm_detail::dot_vv_defined<vec_traits<A>::dim>::value,
  366. deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type
  367. dot( A const & a, B const & b )
  368. {
  369. typedef typename deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type>::type T;
  370. T m(scalar_traits<T>::value(0));
  371. for( int i=0; i!=vec_traits<A>::dim; ++i )
  372. m+=vec_traits<A>::read_element_idx(i,a)*vec_traits<B>::read_element_idx(i,b);
  373. return m;
  374. }
  375. ////////////////////////////////////////////////
  376. namespace
  377. qvm_detail
  378. {
  379. template <int D>
  380. struct
  381. eq_vv_defined
  382. {
  383. static bool const value=false;
  384. };
  385. }
  386. template <class A,class B>
  387. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  388. typename enable_if_c<
  389. is_vec<A>::value && is_vec<B>::value &&
  390. vec_traits<A>::dim==vec_traits<B>::dim &&
  391. !qvm_detail::eq_vv_defined<vec_traits<A>::dim>::value,
  392. bool>::type
  393. operator==( A const & a, B const & b )
  394. {
  395. for( int i=0; i!=vec_traits<A>::dim; ++i )
  396. if( vec_traits<A>::read_element_idx(i,a)!=vec_traits<B>::read_element_idx(i,b) )
  397. return false;
  398. return true;
  399. }
  400. ////////////////////////////////////////////////
  401. namespace
  402. qvm_detail
  403. {
  404. template <int D>
  405. struct
  406. mag_sqr_v_defined
  407. {
  408. static bool const value=false;
  409. };
  410. }
  411. template <class A>
  412. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  413. typename enable_if_c<
  414. is_vec<A>::value &&
  415. !qvm_detail::mag_sqr_v_defined<vec_traits<A>::dim>::value,
  416. typename vec_traits<A>::scalar_type>::type
  417. mag_sqr( A const & a )
  418. {
  419. typedef typename vec_traits<A>::scalar_type T;
  420. T m(scalar_traits<T>::value(0));
  421. for( int i=0; i!=vec_traits<A>::dim; ++i )
  422. {
  423. T x=vec_traits<A>::read_element_idx(i,a);
  424. m+=x*x;
  425. }
  426. return m;
  427. }
  428. ////////////////////////////////////////////////
  429. namespace
  430. qvm_detail
  431. {
  432. template <int D>
  433. struct
  434. mag_v_defined
  435. {
  436. static bool const value=false;
  437. };
  438. }
  439. template <class A>
  440. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  441. typename enable_if_c<
  442. is_vec<A>::value &&
  443. !qvm_detail::mag_v_defined<vec_traits<A>::dim>::value,
  444. typename vec_traits<A>::scalar_type>::type
  445. mag( A const & a )
  446. {
  447. typedef typename vec_traits<A>::scalar_type T;
  448. T m(scalar_traits<T>::value(0));
  449. for( int i=0; i!=vec_traits<A>::dim; ++i )
  450. {
  451. T x=vec_traits<A>::read_element_idx(i,a);
  452. m+=x*x;
  453. }
  454. return sqrt(m);
  455. }
  456. ////////////////////////////////////////////////
  457. namespace
  458. qvm_detail
  459. {
  460. template <int D>
  461. struct
  462. minus_eq_vv_defined
  463. {
  464. static bool const value=false;
  465. };
  466. }
  467. template <class A,class B>
  468. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  469. typename enable_if_c<
  470. is_vec<A>::value && is_vec<B>::value &&
  471. vec_traits<A>::dim==vec_traits<B>::dim &&
  472. !qvm_detail::minus_eq_vv_defined<vec_traits<A>::dim>::value,
  473. A &>::type
  474. operator-=( A & a, B const & b )
  475. {
  476. for( int i=0; i!=vec_traits<A>::dim; ++i )
  477. write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)-vec_traits<B>::read_element_idx(i,b));
  478. return a;
  479. }
  480. ////////////////////////////////////////////////
  481. namespace
  482. qvm_detail
  483. {
  484. template <int D>
  485. struct
  486. minus_v_defined
  487. {
  488. static bool const value=false;
  489. };
  490. }
  491. template <class A>
  492. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  493. typename lazy_enable_if_c<
  494. is_vec<A>::value &&
  495. !qvm_detail::minus_v_defined<vec_traits<A>::dim>::value,
  496. deduce_vec<A> >::type
  497. operator-( A const & a )
  498. {
  499. typedef typename deduce_vec<A>::type R;
  500. R r;
  501. for( int i=0; i!=vec_traits<A>::dim; ++i )
  502. write_vec_element_idx(i,r,-vec_traits<A>::read_element_idx(i,a));
  503. return r;
  504. }
  505. ////////////////////////////////////////////////
  506. namespace
  507. qvm_detail
  508. {
  509. template <int D>
  510. struct
  511. minus_vv_defined
  512. {
  513. static bool const value=false;
  514. };
  515. }
  516. template <class A,class B>
  517. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  518. typename lazy_enable_if_c<
  519. is_vec<A>::value && is_vec<B>::value &&
  520. vec_traits<A>::dim==vec_traits<B>::dim &&
  521. !qvm_detail::minus_vv_defined<vec_traits<A>::dim>::value,
  522. deduce_vec2<A,B,vec_traits<A>::dim> >::type
  523. operator-( A const & a, B const & b )
  524. {
  525. typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
  526. R r;
  527. for( int i=0; i!=vec_traits<A>::dim; ++i )
  528. write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)-vec_traits<B>::read_element_idx(i,b));
  529. return r;
  530. }
  531. ////////////////////////////////////////////////
  532. namespace
  533. qvm_detail
  534. {
  535. template <int D>
  536. struct
  537. mul_eq_vs_defined
  538. {
  539. static bool const value=false;
  540. };
  541. }
  542. template <class A,class B>
  543. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  544. typename enable_if_c<
  545. is_vec<A>::value && is_scalar<B>::value &&
  546. !qvm_detail::mul_eq_vs_defined<vec_traits<A>::dim>::value,
  547. A &>::type
  548. operator*=( A & a, B b )
  549. {
  550. for( int i=0; i!=vec_traits<A>::dim; ++i )
  551. write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)*b);
  552. return a;
  553. }
  554. ////////////////////////////////////////////////
  555. namespace
  556. qvm_detail
  557. {
  558. template <int D>
  559. struct
  560. mul_vs_defined
  561. {
  562. static bool const value=false;
  563. };
  564. }
  565. template <class A,class B>
  566. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  567. typename lazy_enable_if_c<
  568. is_vec<A>::value && is_scalar<B>::value &&
  569. !qvm_detail::mul_vs_defined<vec_traits<A>::dim>::value,
  570. deduce_vec2<A,B,vec_traits<A>::dim> >::type
  571. operator*( A const & a, B b )
  572. {
  573. typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
  574. R r;
  575. for( int i=0; i!=vec_traits<A>::dim; ++i )
  576. write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)*b);
  577. return r;
  578. }
  579. ////////////////////////////////////////////////
  580. namespace
  581. qvm_detail
  582. {
  583. template <int D>
  584. struct
  585. mul_sv_defined
  586. {
  587. static bool const value=false;
  588. };
  589. }
  590. template <class A,class B>
  591. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  592. typename lazy_enable_if_c<
  593. is_scalar<A>::value && is_vec<B>::value &&
  594. !qvm_detail::mul_sv_defined<vec_traits<B>::dim>::value,
  595. deduce_vec2<A,B,vec_traits<B>::dim> >::type
  596. operator*( A a, B const & b )
  597. {
  598. typedef typename deduce_vec2<A,B,vec_traits<B>::dim>::type R;
  599. R r;
  600. for( int i=0; i!=vec_traits<B>::dim; ++i )
  601. write_vec_element_idx(i,r,a*vec_traits<B>::read_element_idx(i,b));
  602. return r;
  603. }
  604. ////////////////////////////////////////////////
  605. namespace
  606. qvm_detail
  607. {
  608. template <int D>
  609. struct
  610. neq_vv_defined
  611. {
  612. static bool const value=false;
  613. };
  614. }
  615. template <class A,class B>
  616. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  617. typename enable_if_c<
  618. is_vec<A>::value && is_vec<B>::value &&
  619. vec_traits<A>::dim==vec_traits<B>::dim &&
  620. !qvm_detail::neq_vv_defined<vec_traits<A>::dim>::value,
  621. bool>::type
  622. operator!=( A const & a, B const & b )
  623. {
  624. for( int i=0; i!=vec_traits<A>::dim; ++i )
  625. if( vec_traits<A>::read_element_idx(i,a)!=vec_traits<B>::read_element_idx(i,b) )
  626. return true;
  627. return false;
  628. }
  629. ////////////////////////////////////////////////
  630. namespace
  631. qvm_detail
  632. {
  633. template <int D>
  634. struct
  635. normalize_v_defined
  636. {
  637. static bool const value=false;
  638. };
  639. }
  640. template <class A>
  641. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  642. typename lazy_enable_if_c<
  643. is_vec<A>::value &&
  644. !qvm_detail::normalize_v_defined<vec_traits<A>::dim>::value,
  645. deduce_vec<A> >::type
  646. normalized( A const & a )
  647. {
  648. typedef typename vec_traits<A>::scalar_type T;
  649. T m(scalar_traits<T>::value(0));
  650. for( int i=0; i!=vec_traits<A>::dim; ++i )
  651. {
  652. T x=vec_traits<A>::read_element_idx(i,a);
  653. m+=x*x;
  654. }
  655. if( m==scalar_traits<T>::value(0) )
  656. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  657. T rm=scalar_traits<T>::value(1)/sqrt(m);
  658. typedef typename deduce_vec<A>::type R;
  659. R r;
  660. for( int i=0; i!=vec_traits<A>::dim; ++i )
  661. write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)*rm);
  662. return r;
  663. }
  664. template <class A>
  665. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  666. typename enable_if_c<
  667. is_vec<A>::value &&
  668. !qvm_detail::normalize_v_defined<vec_traits<A>::dim>::value,
  669. void>::type
  670. normalize( A & a )
  671. {
  672. typedef typename vec_traits<A>::scalar_type T;
  673. T m(scalar_traits<T>::value(0));
  674. for( int i=0; i!=vec_traits<A>::dim; ++i )
  675. {
  676. T x=vec_traits<A>::read_element_idx(i,a);
  677. m+=x*x;
  678. }
  679. if( m==scalar_traits<T>::value(0) )
  680. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  681. T rm=scalar_traits<T>::value(1)/sqrt(m);
  682. for( int i=0; i!=vec_traits<A>::dim; ++i )
  683. write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)*rm);
  684. }
  685. ////////////////////////////////////////////////
  686. namespace
  687. qvm_detail
  688. {
  689. template <int D>
  690. struct
  691. plus_eq_vv_defined
  692. {
  693. static bool const value=false;
  694. };
  695. }
  696. template <class A,class B>
  697. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  698. typename enable_if_c<
  699. is_vec<A>::value && is_vec<B>::value &&
  700. vec_traits<A>::dim==vec_traits<B>::dim &&
  701. !qvm_detail::plus_eq_vv_defined<vec_traits<A>::dim>::value,
  702. A &>::type
  703. operator+=( A & a, B const & b )
  704. {
  705. for( int i=0; i!=vec_traits<A>::dim; ++i )
  706. write_vec_element_idx(i,a,vec_traits<A>::read_element_idx(i,a)+vec_traits<B>::read_element_idx(i,b));
  707. return a;
  708. }
  709. ////////////////////////////////////////////////
  710. namespace
  711. qvm_detail
  712. {
  713. template <int D>
  714. struct
  715. plus_vv_defined
  716. {
  717. static bool const value=false;
  718. };
  719. }
  720. template <class A,class B>
  721. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  722. typename lazy_enable_if_c<
  723. is_vec<A>::value && is_vec<B>::value &&
  724. vec_traits<A>::dim==vec_traits<B>::dim &&
  725. !qvm_detail::plus_vv_defined<vec_traits<A>::dim>::value,
  726. deduce_vec2<A,B,vec_traits<A>::dim> >::type
  727. operator+( A const & a, B const & b )
  728. {
  729. typedef typename deduce_vec2<A,B,vec_traits<A>::dim>::type R;
  730. R r;
  731. for( int i=0; i!=vec_traits<A>::dim; ++i )
  732. write_vec_element_idx(i,r,vec_traits<A>::read_element_idx(i,a)+vec_traits<B>::read_element_idx(i,b));
  733. return r;
  734. }
  735. ////////////////////////////////////////////////
  736. namespace
  737. qvm_detail
  738. {
  739. template <class T>
  740. class
  741. vref_
  742. {
  743. vref_( vref_ const & );
  744. vref_ & operator=( vref_ const & );
  745. ~vref_();
  746. public:
  747. template <class R>
  748. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  749. vref_ &
  750. operator=( R const & x )
  751. {
  752. assign(*this,x);
  753. return *this;
  754. }
  755. template <class R
  756. #if __cplusplus >= 201103L
  757. , class = typename enable_if<is_vec<R> >::type
  758. #endif
  759. >
  760. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  761. operator R() const
  762. {
  763. R r;
  764. assign(r,*this);
  765. return r;
  766. }
  767. };
  768. template <class V,bool WriteElementRef=vec_write_element_ref<V>::value>
  769. struct vref_write_traits;
  770. template <class V>
  771. struct
  772. vref_write_traits<V,true>
  773. {
  774. typedef typename vec_traits<V>::scalar_type scalar_type;
  775. typedef qvm_detail::vref_<V> this_vector;
  776. static int const dim=vec_traits<V>::dim;
  777. template <int I>
  778. static
  779. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  780. scalar_type &
  781. write_element( this_vector & x )
  782. {
  783. BOOST_QVM_STATIC_ASSERT(I>=0);
  784. BOOST_QVM_STATIC_ASSERT(I<dim);
  785. return vec_traits<V>::template write_element<I>(reinterpret_cast<V &>(x));
  786. }
  787. static
  788. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  789. scalar_type &
  790. write_element_idx( int i, this_vector & x )
  791. {
  792. BOOST_QVM_ASSERT(i>=0);
  793. BOOST_QVM_ASSERT(i<dim);
  794. return vec_traits<V>::write_element_idx(i,reinterpret_cast<V &>(x));
  795. }
  796. };
  797. template <class V>
  798. struct
  799. vref_write_traits<V,false>
  800. {
  801. typedef typename vec_traits<V>::scalar_type scalar_type;
  802. typedef qvm_detail::vref_<V> this_vector;
  803. static int const dim=vec_traits<V>::dim;
  804. template <int I>
  805. static
  806. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  807. void
  808. write_element( this_vector & x, scalar_type s )
  809. {
  810. BOOST_QVM_STATIC_ASSERT(I>=0);
  811. BOOST_QVM_STATIC_ASSERT(I<dim);
  812. vec_traits<V>::template write_element<I>(reinterpret_cast<V &>(x), s);
  813. }
  814. static
  815. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  816. void
  817. write_element_idx( int i, this_vector & x, scalar_type s )
  818. {
  819. BOOST_QVM_ASSERT(i>=0);
  820. BOOST_QVM_ASSERT(i<dim);
  821. vec_traits<V>::write_element_idx(i,reinterpret_cast<V &>(x), s);
  822. }
  823. };
  824. }
  825. template <class V>
  826. struct
  827. vec_traits< qvm_detail::vref_<V> >:
  828. qvm_detail::vref_write_traits<V>
  829. {
  830. typedef typename vec_traits<V>::scalar_type scalar_type;
  831. typedef qvm_detail::vref_<V> this_vector;
  832. static int const dim=vec_traits<V>::dim;
  833. template <int I>
  834. static
  835. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  836. scalar_type
  837. read_element( this_vector const & x )
  838. {
  839. BOOST_QVM_STATIC_ASSERT(I>=0);
  840. BOOST_QVM_STATIC_ASSERT(I<dim);
  841. return vec_traits<V>::template read_element<I>(reinterpret_cast<V const &>(x));
  842. }
  843. static
  844. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  845. scalar_type
  846. read_element_idx( int i, this_vector const & x )
  847. {
  848. BOOST_QVM_ASSERT(i>=0);
  849. BOOST_QVM_ASSERT(i<dim);
  850. return vec_traits<V>::read_element_idx(i,reinterpret_cast<V const &>(x));
  851. }
  852. };
  853. template <class V,int D>
  854. struct
  855. deduce_vec<qvm_detail::vref_<V>,D>
  856. {
  857. typedef vec<typename vec_traits<V>::scalar_type,D> type;
  858. };
  859. template <class V>
  860. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  861. typename enable_if_c<
  862. is_vec<V>::value,
  863. qvm_detail::vref_<V> const &>::type
  864. vref( V const & a )
  865. {
  866. return reinterpret_cast<qvm_detail::vref_<V> const &>(a);
  867. }
  868. template <class V>
  869. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  870. typename enable_if_c<
  871. is_vec<V>::value,
  872. qvm_detail::vref_<V> &>::type
  873. vref( V & a )
  874. {
  875. return reinterpret_cast<qvm_detail::vref_<V> &>(a);
  876. }
  877. ////////////////////////////////////////////////
  878. namespace
  879. sfinae
  880. {
  881. using ::boost::qvm::to_string;
  882. using ::boost::qvm::assign;
  883. using ::boost::qvm::convert_to;
  884. using ::boost::qvm::cross;
  885. using ::boost::qvm::cmp;
  886. using ::boost::qvm::set_zero;
  887. using ::boost::qvm::scalar_cast;
  888. using ::boost::qvm::operator/=;
  889. using ::boost::qvm::operator/;
  890. using ::boost::qvm::dot;
  891. using ::boost::qvm::operator==;
  892. using ::boost::qvm::mag_sqr;
  893. using ::boost::qvm::mag;
  894. using ::boost::qvm::operator-=;
  895. using ::boost::qvm::operator-;
  896. using ::boost::qvm::operator*=;
  897. using ::boost::qvm::operator*;
  898. using ::boost::qvm::operator!=;
  899. using ::boost::qvm::normalized;
  900. using ::boost::qvm::normalize;
  901. using ::boost::qvm::operator+=;
  902. using ::boost::qvm::operator+;
  903. using ::boost::qvm::vref;
  904. }
  905. } }
  906. #endif