1#ifndef BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
2#define BOOST_QVM_DETAIL_SWIZZLE_TRAITS_HPP_INCLUDED
3
4// Copyright 2008-2022 Emil Dotchevski and Reverge Studios, Inc.
5
6// Distributed under the Boost Software License, Version 1.0. (See accompanying
7// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9#include <boost/qvm/config.hpp>
10#include <boost/qvm/deduce_vec.hpp>
11#include <boost/qvm/enable_if.hpp>
12#include <boost/qvm/assert.hpp>
13
14namespace boost { namespace qvm {
15
16namespace
17qvm_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
27 template <int A,class Next=void> struct swizzle_idx { static int const value=A; typedef Next next; };
28
29 template <class V,int Idx>
30 struct
31 const_value
32 {
33 static
34 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
35 typename vec_traits<V>::scalar_type
36 value()
37 {
38 BOOST_QVM_ASSERT(0);
39 return typename vec_traits<V>::scalar_type();
40 }
41 };
42
43 template <class V>
44 struct
45 const_value<V,-1>
46 {
47 static
48 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
49 typename vec_traits<V>::scalar_type
50 value()
51 {
52 return scalar_traits<typename vec_traits<V>::scalar_type>::value(0);
53 }
54 };
55
56 template <class V>
57 struct
58 const_value<V,-2>
59 {
60 static
61 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
62 typename vec_traits<V>::scalar_type
63 value()
64 {
65 return scalar_traits<typename vec_traits<V>::scalar_type>::value(1);
66 }
67 };
68
69 template <int Index,bool Neg=(Index<0)>
70 struct neg_zero;
71
72 template <int Index>
73 struct
74 neg_zero<Index,true>
75 {
76 static int const value=0;
77 };
78
79 template <int Index>
80 struct
81 neg_zero<Index,false>
82 {
83 static int const value=Index;
84 };
85
86 template <class SwizzleList,int Index,int C=0>
87 struct
88 swizzle
89 {
90 static int const value=swizzle<typename SwizzleList::next,Index,C+1>::value;
91 };
92
93 template <class SwizzleList,int Match>
94 struct
95 swizzle<SwizzleList,Match,Match>
96 {
97 static int const value=SwizzleList::value;
98 };
99
100 template <int Index,int C>
101 struct swizzle<void,Index,C>;
102
103 template <class SwizzleList,int C=0>
104 struct
105 swizzle_list_length
106 {
107 static int const value=swizzle_list_length<typename SwizzleList::next,C+1>::value;
108 };
109
110 template <int C>
111 struct
112 swizzle_list_length<void,C>
113 {
114 static int const value=C;
115 };
116
117 template <class SwizzleList,int D>
118 struct
119 validate_swizzle_list
120 {
121 static bool const value =
122 ((SwizzleList::value)<D) && //don't touch extra (), MSVC parsing bug.
123 validate_swizzle_list<typename SwizzleList::next,D>::value;
124 };
125
126 template <int D>
127 struct
128 validate_swizzle_list<void,D>
129 {
130 static bool const value=true;
131 };
132
133 template <class OriginalType,class SwizzleList>
134 class
135 sw_
136 {
137 sw_( sw_ const & );
138 sw_ & operator=( sw_ const & );
139 ~sw_();
140
141 BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,vec_traits<OriginalType>::dim>::value));
142
143 public:
144
145 template <class T>
146 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
147 sw_ &
148 operator=( T const & x )
149 {
150 assign(*this,x);
151 return *this;
152 }
153
154 template <class R
155#if __cplusplus >= 201103L
156 , class = typename enable_if<is_vec<R> >::type
157#endif
158 >
159 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
160 operator R() const
161 {
162 R r;
163 assign(r,*this);
164 return r;
165 }
166 };
167
168 template <class OriginalVector,class SwizzleList,bool WriteElementRef=vec_write_element_ref<OriginalVector>::value>
169 struct sw_write_traits;
170
171 template <class OriginalVector,class SwizzleList>
172 struct
173 sw_write_traits<OriginalVector,SwizzleList,true>
174 {
175 typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
176 typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
177 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
178
179 template <int I>
180 static
181 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
182 scalar_type &
183 write_element( this_vector & x )
184 {
185 BOOST_QVM_STATIC_ASSERT(I>=0);
186 BOOST_QVM_STATIC_ASSERT(I<dim);
187 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
188 BOOST_QVM_STATIC_ASSERT(idx>=0);
189 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
190 return vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x));
191 }
192 };
193
194 template <class OriginalVector,class SwizzleList>
195 struct
196 sw_write_traits<OriginalVector,SwizzleList,false>
197 {
198 typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
199 typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
200 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
201
202 template <int I>
203 static
204 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
205 void
206 write_element( this_vector & x, scalar_type s )
207 {
208 BOOST_QVM_STATIC_ASSERT(I>=0);
209 BOOST_QVM_STATIC_ASSERT(I<dim);
210 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
211 BOOST_QVM_STATIC_ASSERT(idx>=0);
212 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
213 vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x), s);
214 }
215 };
216
217 template <class SwizzleList>
218 class
219 sw01_
220 {
221 sw01_( sw01_ const & );
222 sw01_ & operator=( sw01_ const & );
223 ~sw01_();
224
225 public:
226
227 template <class R
228#if __cplusplus >= 201103L
229 , class = typename enable_if<is_vec<R> >::type
230#endif
231 >
232 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
233 operator R() const
234 {
235 R r;
236 assign(r,*this);
237 return r;
238 }
239 };
240
241 template <class OriginalType,class SwizzleList>
242 class
243 sws_
244 {
245 sws_( sws_ const & );
246 sws_ & operator=( sws_ const & );
247 ~sws_();
248
249 BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,1>::value));
250
251 public:
252
253 template <class R
254#if __cplusplus >= 201103L
255 , class = typename enable_if<is_vec<R> >::type
256#endif
257 >
258 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
259 operator R() const
260 {
261 R r;
262 assign(r,*this);
263 return r;
264 }
265 };
266 }
267
268template <class OriginalVector,class SwizzleList>
269struct
270vec_traits<qvm_detail::sw_<OriginalVector,SwizzleList> >:
271 qvm_detail::sw_write_traits<OriginalVector,SwizzleList>
272 {
273 typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector;
274 typedef typename vec_traits<OriginalVector>::scalar_type scalar_type;
275 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
276
277 template <int I>
278 static
279 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
280 scalar_type
281 read_element( this_vector const & x )
282 {
283 BOOST_QVM_STATIC_ASSERT(I>=0);
284 BOOST_QVM_STATIC_ASSERT(I<dim);
285 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
286 BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim);
287 return idx>=0?
288 vec_traits<OriginalVector>::template read_element<qvm_detail::neg_zero<idx>::value>(reinterpret_cast<OriginalVector const &>(x)) :
289 qvm_detail::const_value<this_vector,idx>::value();
290 }
291 };
292
293template <class SwizzleList>
294struct
295vec_traits<qvm_detail::sw01_<SwizzleList> >
296 {
297 typedef qvm_detail::sw01_<SwizzleList> this_vector;
298 typedef int scalar_type;
299 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
300
301 template <int I>
302 static
303 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
304 scalar_type
305 read_element( this_vector const & )
306 {
307 BOOST_QVM_STATIC_ASSERT(I>=0);
308 BOOST_QVM_STATIC_ASSERT(I<dim);
309 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
310 BOOST_QVM_STATIC_ASSERT(idx<0);
311 return qvm_detail::const_value<this_vector,idx>::value();
312 }
313 };
314
315template <class OriginalScalar,class SwizzleList>
316struct
317vec_traits<qvm_detail::sws_<OriginalScalar,SwizzleList> >
318 {
319 typedef qvm_detail::sws_<OriginalScalar,SwizzleList> this_vector;
320 typedef OriginalScalar scalar_type;
321 static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
322
323 template <int I>
324 static
325 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
326 scalar_type
327 read_element( this_vector const & x )
328 {
329 BOOST_QVM_STATIC_ASSERT(I>=0);
330 BOOST_QVM_STATIC_ASSERT(I<dim);
331 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
332 BOOST_QVM_STATIC_ASSERT(idx<1);
333 return idx==0?
334 reinterpret_cast<OriginalScalar const &>(x) :
335 qvm_detail::const_value<this_vector,idx>::value();
336 }
337
338 template <int I>
339 static
340 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
341 scalar_type &
342 write_element( this_vector & x )
343 {
344 BOOST_QVM_STATIC_ASSERT(I>=0);
345 BOOST_QVM_STATIC_ASSERT(I<dim);
346 int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
347 BOOST_QVM_STATIC_ASSERT(idx<1);
348 return reinterpret_cast<OriginalScalar &>(x);
349 }
350 };
351
352template <class OriginalVector,class SwizzleList,int D>
353struct
354deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D>
355 {
356 typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
357 };
358
359template <class OriginalVector,class SwizzleList,int D>
360struct
361deduce_vec2<qvm_detail::sw_<OriginalVector,SwizzleList>,qvm_detail::sw_<OriginalVector,SwizzleList>,D>
362 {
363 typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
364 };
365
366template <class Scalar,class SwizzleList,int D>
367struct
368deduce_vec<qvm_detail::sws_<Scalar,SwizzleList>,D>
369 {
370 typedef vec<Scalar,D> type;
371 };
372
373template <class Scalar,class SwizzleList,int D>
374struct
375deduce_vec2<qvm_detail::sws_<Scalar,SwizzleList>,qvm_detail::sws_<Scalar,SwizzleList>,D>
376 {
377 typedef vec<Scalar,D> type;
378 };
379
380} }
381
382#endif
383

source code of boost/libs/qvm/include/boost/qvm/detail/swizzle_traits.hpp