vec_operations.hpp 30 KB

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