vec_operations.hpp 26 KB

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