]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
6 | #ifndef UUID_E831FAD6B38F11DE8CECBF0D56D89593 | |
7 | #define UUID_E831FAD6B38F11DE8CECBF0D56D89593 | |
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 | ||
189 | template <class OriginalVector,class SwizzleList> | |
190 | struct | |
191 | vec_traits<qvm_detail::sw_<OriginalVector,SwizzleList> > | |
192 | { | |
193 | typedef qvm_detail::sw_<OriginalVector,SwizzleList> this_vector; | |
194 | typedef typename vec_traits<OriginalVector>::scalar_type scalar_type; | |
195 | static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value; | |
196 | ||
197 | template <int I> | |
198 | static | |
199 | BOOST_QVM_INLINE_CRITICAL | |
200 | scalar_type | |
201 | read_element( this_vector const & x ) | |
202 | { | |
203 | BOOST_QVM_STATIC_ASSERT(I>=0); | |
204 | BOOST_QVM_STATIC_ASSERT(I<dim); | |
205 | int const idx=qvm_detail::swizzle<SwizzleList,I>::value; | |
206 | BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim); | |
207 | return idx>=0? | |
208 | vec_traits<OriginalVector>::template read_element<qvm_detail::neg_zero<idx>::value>(reinterpret_cast<OriginalVector const &>(x)) : | |
209 | qvm_detail::const_value<this_vector,idx>::value(); | |
210 | } | |
211 | ||
212 | template <int I> | |
213 | static | |
214 | BOOST_QVM_INLINE_CRITICAL | |
215 | scalar_type & | |
216 | write_element( this_vector & x ) | |
217 | { | |
218 | BOOST_QVM_STATIC_ASSERT(I>=0); | |
219 | BOOST_QVM_STATIC_ASSERT(I<dim); | |
220 | int const idx=qvm_detail::swizzle<SwizzleList,I>::value; | |
221 | BOOST_QVM_STATIC_ASSERT(idx>=0); | |
222 | BOOST_QVM_STATIC_ASSERT(idx<vec_traits<OriginalVector>::dim); | |
223 | return vec_traits<OriginalVector>::template write_element<idx>(reinterpret_cast<OriginalVector &>(x)); | |
224 | } | |
225 | }; | |
226 | ||
227 | template <class SwizzleList> | |
228 | struct | |
229 | vec_traits<qvm_detail::sw01_<SwizzleList> > | |
230 | { | |
231 | typedef qvm_detail::sw01_<SwizzleList> this_vector; | |
232 | typedef int scalar_type; | |
233 | static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value; | |
234 | ||
235 | template <int I> | |
236 | static | |
237 | BOOST_QVM_INLINE_CRITICAL | |
238 | scalar_type | |
239 | read_element( this_vector const & ) | |
240 | { | |
241 | BOOST_QVM_STATIC_ASSERT(I>=0); | |
242 | BOOST_QVM_STATIC_ASSERT(I<dim); | |
243 | int const idx=qvm_detail::swizzle<SwizzleList,I>::value; | |
244 | BOOST_QVM_STATIC_ASSERT(idx<0); | |
245 | return qvm_detail::const_value<this_vector,idx>::value(); | |
246 | } | |
247 | }; | |
248 | ||
249 | template <class OriginalVector,class SwizzleList,int D> | |
250 | struct | |
251 | deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D> | |
252 | { | |
253 | typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type; | |
254 | }; | |
255 | ||
256 | template <class OriginalVector,class SwizzleList,int D> | |
257 | struct | |
258 | deduce_vec2<qvm_detail::sw_<OriginalVector,SwizzleList>,qvm_detail::sw_<OriginalVector,SwizzleList>,D> | |
259 | { | |
260 | typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type; | |
261 | }; | |
262 | } | |
263 | } | |
264 | ||
265 | #endif |