swizzle_traits.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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_E831FAD6B38F11DE8CECBF0D56D89593
  5. #define UUID_E831FAD6B38F11DE8CECBF0D56D89593
  6. #include <boost/qvm/inline.hpp>
  7. #include <boost/qvm/deduce_vec.hpp>
  8. #include <boost/qvm/enable_if.hpp>
  9. #include <boost/qvm/assert.hpp>
  10. namespace
  11. boost
  12. {
  13. namespace
  14. qvm
  15. {
  16. namespace
  17. qvm_detail
  18. {
  19. BOOST_QVM_INLINE_CRITICAL
  20. void const *
  21. get_null()
  22. {
  23. static int const obj=0;
  24. return &obj;
  25. }
  26. template <int A,class Next=void> struct swizzle_idx { static int const value=A; typedef Next next; };
  27. template <class V,int Idx>
  28. struct
  29. const_value
  30. {
  31. static
  32. BOOST_QVM_INLINE_TRIVIAL
  33. typename vec_traits<V>::scalar_type
  34. value()
  35. {
  36. BOOST_QVM_ASSERT(0);
  37. return typename vec_traits<V>::scalar_type();
  38. }
  39. };
  40. template <class V>
  41. struct
  42. const_value<V,-1>
  43. {
  44. static
  45. BOOST_QVM_INLINE_TRIVIAL
  46. typename vec_traits<V>::scalar_type
  47. value()
  48. {
  49. return scalar_traits<typename vec_traits<V>::scalar_type>::value(0);
  50. }
  51. };
  52. template <class V>
  53. struct
  54. const_value<V,-2>
  55. {
  56. static
  57. BOOST_QVM_INLINE_TRIVIAL
  58. typename vec_traits<V>::scalar_type
  59. value()
  60. {
  61. return scalar_traits<typename vec_traits<V>::scalar_type>::value(1);
  62. }
  63. };
  64. template <int Index,bool Neg=(Index<0)>
  65. struct neg_zero;
  66. template <int Index>
  67. struct
  68. neg_zero<Index,true>
  69. {
  70. static int const value=0;
  71. };
  72. template <int Index>
  73. struct
  74. neg_zero<Index,false>
  75. {
  76. static int const value=Index;
  77. };
  78. template <class SwizzleList,int Index,int C=0>
  79. struct
  80. swizzle
  81. {
  82. static int const value=swizzle<typename SwizzleList::next,Index,C+1>::value;
  83. };
  84. template <class SwizzleList,int Match>
  85. struct
  86. swizzle<SwizzleList,Match,Match>
  87. {
  88. static int const value=SwizzleList::value;
  89. };
  90. template <int Index,int C>
  91. struct swizzle<void,Index,C>;
  92. template <class SwizzleList,int C=0>
  93. struct
  94. swizzle_list_length
  95. {
  96. static int const value=swizzle_list_length<typename SwizzleList::next,C+1>::value;
  97. };
  98. template <int C>
  99. struct
  100. swizzle_list_length<void,C>
  101. {
  102. static int const value=C;
  103. };
  104. template <class SwizzleList,int D>
  105. struct
  106. validate_swizzle_list
  107. {
  108. static bool const value =
  109. ((SwizzleList::value)<D) && //don't touch extra (), MSVC parsing bug.
  110. validate_swizzle_list<typename SwizzleList::next,D>::value;
  111. };
  112. template <int D>
  113. struct
  114. validate_swizzle_list<void,D>
  115. {
  116. static bool const value=true;
  117. };
  118. template <class OriginalType,class SwizzleList>
  119. class
  120. sw_
  121. {
  122. sw_( sw_ const & );
  123. sw_ & operator=( sw_ const & );
  124. ~sw_();
  125. BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,vec_traits<OriginalType>::dim>::value));
  126. public:
  127. template <class T>
  128. BOOST_QVM_INLINE_TRIVIAL
  129. sw_ &
  130. operator=( T const & x )
  131. {
  132. assign(*this,x);
  133. return *this;
  134. }
  135. template <class R>
  136. BOOST_QVM_INLINE_TRIVIAL
  137. operator R() const
  138. {
  139. R r;
  140. assign(r,*this);
  141. return r;
  142. }
  143. };
  144. template <class SwizzleList>
  145. class
  146. sw01_
  147. {
  148. sw01_( sw01_ const & );
  149. sw01_ & operator=( sw01_ const & );
  150. ~sw01_();
  151. public:
  152. template <class R>
  153. BOOST_QVM_INLINE_TRIVIAL
  154. operator R() const
  155. {
  156. R r;
  157. assign(r,*this);
  158. return r;
  159. }
  160. };
  161. template <class OriginalType,class SwizzleList>
  162. class
  163. sws_
  164. {
  165. sws_( sws_ const & );
  166. sws_ & operator=( sws_ const & );
  167. ~sws_();
  168. BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,1>::value));
  169. public:
  170. template <class R>
  171. 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 OriginalVector,class SwizzleList>
  181. struct
  182. vec_traits<qvm_detail::sw_<OriginalVector,SwizzleList> >
  183. {
  184. typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
  185. typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
  186. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  187. template <int I>
  188. static
  189. BOOST_QVM_INLINE_CRITICAL
  190. scalar_type
  191. read_element( this_vector const & x )
  192. {
  193. BOOST_QVM_STATIC_ASSERT(I>=0);
  194. BOOST_QVM_STATIC_ASSERT(I<dim);
  195. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  196. BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
  197. return idx>=0?
  198. vec_traits<OriginalVector>::template read_element<qvm_detail::neg_zero<idx>::value>(reinterpret_cast<OriginalVector const &>(x)) :
  199. qvm_detail::const_value<this_vector,idx>::value();
  200. }
  201. template <int I>
  202. static
  203. BOOST_QVM_INLINE_CRITICAL
  204. scalar_type &
  205. write_element( this_vector & x )
  206. {
  207. BOOST_QVM_STATIC_ASSERT(I>=0);
  208. BOOST_QVM_STATIC_ASSERT(I<dim);
  209. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  210. BOOST_QVM_STATIC_ASSERT(idx>=0);
  211. BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
  212. return vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x));
  213. }
  214. };
  215. template <class SwizzleList>
  216. struct
  217. vec_traits<qvm_detail::sw01_<SwizzleList> >
  218. {
  219. typedef qvm_detail::sw01_<SwizzleList> this_vector;
  220. typedef int scalar_type;
  221. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  222. template <int I>
  223. static
  224. BOOST_QVM_INLINE_CRITICAL
  225. scalar_type
  226. read_element( this_vector const & )
  227. {
  228. BOOST_QVM_STATIC_ASSERT(I>=0);
  229. BOOST_QVM_STATIC_ASSERT(I<dim);
  230. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  231. BOOST_QVM_STATIC_ASSERT(idx<0);
  232. return qvm_detail::const_value<this_vector,idx>::value();
  233. }
  234. };
  235. template <class OriginalScalar,class SwizzleList>
  236. struct
  237. vec_traits<qvm_detail::sws_<OriginalScalar,SwizzleList> >
  238. {
  239. typedef qvm_detail::sws_<OriginalScalar,SwizzleList> this_vector;
  240. typedef OriginalScalar scalar_type;
  241. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  242. template <int I>
  243. static
  244. BOOST_QVM_INLINE_CRITICAL
  245. scalar_type
  246. read_element( this_vector const & x )
  247. {
  248. BOOST_QVM_STATIC_ASSERT(I>=0);
  249. BOOST_QVM_STATIC_ASSERT(I<dim);
  250. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  251. BOOST_QVM_STATIC_ASSERT(idx<1);
  252. return idx==0?
  253. reinterpret_cast<OriginalScalar const &>(x) :
  254. qvm_detail::const_value<this_vector,idx>::value();
  255. }
  256. template <int I>
  257. static
  258. BOOST_QVM_INLINE_CRITICAL
  259. scalar_type &
  260. write_element( this_vector & x )
  261. {
  262. BOOST_QVM_STATIC_ASSERT(I>=0);
  263. BOOST_QVM_STATIC_ASSERT(I<dim);
  264. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  265. BOOST_QVM_STATIC_ASSERT(idx==0);
  266. return reinterpret_cast<OriginalScalar &>(x);
  267. }
  268. };
  269. template <class OriginalVector,class SwizzleList,int D>
  270. struct
  271. deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D>
  272. {
  273. typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
  274. };
  275. template <class OriginalVector,class SwizzleList,int D>
  276. struct
  277. deduce_vec2<qvm_detail::sw_<OriginalVector,SwizzleList>,qvm_detail::sw_<OriginalVector,SwizzleList>,D>
  278. {
  279. typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
  280. };
  281. template <class Scalar,class SwizzleList,int D>
  282. struct
  283. deduce_vec<qvm_detail::sws_<Scalar,SwizzleList>,D>
  284. {
  285. typedef vec<Scalar,D> type;
  286. };
  287. template <class Scalar,class SwizzleList,int D>
  288. struct
  289. deduce_vec2<qvm_detail::sws_<Scalar,SwizzleList>,qvm_detail::sws_<Scalar,SwizzleList>,D>
  290. {
  291. typedef vec<Scalar,D> type;
  292. };
  293. }
  294. }
  295. #endif