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