swizzle_traits.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #ifndef BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
  2. #define BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
  3. // Copyright 2008-2022 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/config.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_CONSTEXPR 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_CONSTEXPR 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_CONSTEXPR 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_CONSTEXPR 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. #if __cplusplus >= 201103L
  132. , class = typename enable_if<is_vec<R> >::type
  133. #endif
  134. >
  135. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  136. operator R() const
  137. {
  138. R r;
  139. assign(r,*this);
  140. return r;
  141. }
  142. };
  143. template <class OriginalVector,class SwizzleList,bool WriteElementRef=vec_write_element_ref<OriginalVector>::value>
  144. struct sw_write_traits;
  145. template <class OriginalVector,class SwizzleList>
  146. struct
  147. sw_write_traits<OriginalVector,SwizzleList,true>
  148. {
  149. typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
  150. typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
  151. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  152. template <int I>
  153. static
  154. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  155. scalar_type &
  156. write_element( this_vector & x )
  157. {
  158. BOOST_QVM_STATIC_ASSERT(I>=0);
  159. BOOST_QVM_STATIC_ASSERT(I<dim);
  160. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  161. BOOST_QVM_STATIC_ASSERT(idx>=0);
  162. BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
  163. return vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x));
  164. }
  165. };
  166. template <class OriginalVector,class SwizzleList>
  167. struct
  168. sw_write_traits<OriginalVector,SwizzleList,false>
  169. {
  170. typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
  171. typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
  172. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  173. template <int I>
  174. static
  175. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  176. void
  177. write_element( this_vector & x, scalar_type s )
  178. {
  179. BOOST_QVM_STATIC_ASSERT(I>=0);
  180. BOOST_QVM_STATIC_ASSERT(I<dim);
  181. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  182. BOOST_QVM_STATIC_ASSERT(idx>=0);
  183. BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
  184. vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x), s);
  185. }
  186. };
  187. template <class SwizzleList>
  188. class
  189. sw01_
  190. {
  191. sw01_( sw01_ const & );
  192. sw01_ & operator=( sw01_ const & );
  193. ~sw01_();
  194. public:
  195. template <class R
  196. #if __cplusplus >= 201103L
  197. , class = typename enable_if<is_vec<R> >::type
  198. #endif
  199. >
  200. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  201. operator R() const
  202. {
  203. R r;
  204. assign(r,*this);
  205. return r;
  206. }
  207. };
  208. template <class OriginalType,class SwizzleList>
  209. class
  210. sws_
  211. {
  212. sws_( sws_ const & );
  213. sws_ & operator=( sws_ const & );
  214. ~sws_();
  215. BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,1>::value));
  216. public:
  217. template <class R
  218. #if __cplusplus >= 201103L
  219. , class = typename enable_if<is_vec<R> >::type
  220. #endif
  221. >
  222. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  223. operator R() const
  224. {
  225. R r;
  226. assign(r,*this);
  227. return r;
  228. }
  229. };
  230. }
  231. template <class OriginalVector,class SwizzleList>
  232. struct
  233. vec_traits<qvm_detail::sw_<OriginalVector,SwizzleList> >:
  234. qvm_detail::sw_write_traits<OriginalVector,SwizzleList>
  235. {
  236. typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
  237. typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
  238. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  239. template <int I>
  240. static
  241. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  242. scalar_type
  243. read_element( this_vector const & x )
  244. {
  245. BOOST_QVM_STATIC_ASSERT(I>=0);
  246. BOOST_QVM_STATIC_ASSERT(I<dim);
  247. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  248. BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
  249. return idx>=0?
  250. vec_traits<OriginalVector>::template read_element<qvm_detail::neg_zero<idx>::value>(reinterpret_cast<OriginalVector const &>(x)) :
  251. qvm_detail::const_value<this_vector,idx>::value();
  252. }
  253. };
  254. template <class SwizzleList>
  255. struct
  256. vec_traits<qvm_detail::sw01_<SwizzleList> >
  257. {
  258. typedef qvm_detail::sw01_<SwizzleList> this_vector;
  259. typedef int scalar_type;
  260. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  261. template <int I>
  262. static
  263. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  264. scalar_type
  265. read_element( this_vector const & )
  266. {
  267. BOOST_QVM_STATIC_ASSERT(I>=0);
  268. BOOST_QVM_STATIC_ASSERT(I<dim);
  269. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  270. BOOST_QVM_STATIC_ASSERT(idx<0);
  271. return qvm_detail::const_value<this_vector,idx>::value();
  272. }
  273. };
  274. template <class OriginalScalar,class SwizzleList>
  275. struct
  276. vec_traits<qvm_detail::sws_<OriginalScalar,SwizzleList> >
  277. {
  278. typedef qvm_detail::sws_<OriginalScalar,SwizzleList> this_vector;
  279. typedef OriginalScalar scalar_type;
  280. static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
  281. template <int I>
  282. static
  283. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  284. scalar_type
  285. read_element( this_vector const & x )
  286. {
  287. BOOST_QVM_STATIC_ASSERT(I>=0);
  288. BOOST_QVM_STATIC_ASSERT(I<dim);
  289. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  290. BOOST_QVM_STATIC_ASSERT(idx<1);
  291. return idx==0?
  292. reinterpret_cast<OriginalScalar const &>(x) :
  293. qvm_detail::const_value<this_vector,idx>::value();
  294. }
  295. template <int I>
  296. static
  297. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  298. scalar_type &
  299. write_element( this_vector & x )
  300. {
  301. BOOST_QVM_STATIC_ASSERT(I>=0);
  302. BOOST_QVM_STATIC_ASSERT(I<dim);
  303. int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
  304. BOOST_QVM_STATIC_ASSERT(idx<1);
  305. return reinterpret_cast<OriginalScalar &>(x);
  306. }
  307. };
  308. template <class OriginalVector,class SwizzleList,int D>
  309. struct
  310. deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D>
  311. {
  312. typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
  313. };
  314. template <class OriginalVector,class SwizzleList,int D>
  315. struct
  316. deduce_vec2<qvm_detail::sw_<OriginalVector,SwizzleList>,qvm_detail::sw_<OriginalVector,SwizzleList>,D>
  317. {
  318. typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
  319. };
  320. template <class Scalar,class SwizzleList,int D>
  321. struct
  322. deduce_vec<qvm_detail::sws_<Scalar,SwizzleList>,D>
  323. {
  324. typedef vec<Scalar,D> type;
  325. };
  326. template <class Scalar,class SwizzleList,int D>
  327. struct
  328. deduce_vec2<qvm_detail::sws_<Scalar,SwizzleList>,qvm_detail::sws_<Scalar,SwizzleList>,D>
  329. {
  330. typedef vec<Scalar,D> type;
  331. };
  332. } }
  333. #endif