swizzle_traits.hpp 8.5 KB

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