1 | /* Copyright (C) 2014 Povilas Kanapickas <povilas@radix.lt> |
2 | |
3 | Distributed under the Boost Software License, Version 1.0. |
4 | (See accompanying file LICENSE_1_0.txt or copy at |
5 | http://www.boost.org/LICENSE_1_0.txt) |
6 | */ |
7 | |
8 | #ifndef LIBSIMDPP_SIMD_TYPES_GENERIC_H |
9 | #define LIBSIMDPP_SIMD_TYPES_GENERIC_H |
10 | |
11 | #include <simdpp/setup_arch.h> |
12 | #include <simdpp/types.h> |
13 | #include <type_traits> |
14 | |
15 | namespace simdpp { |
16 | namespace SIMDPP_ARCH_NAMESPACE { |
17 | |
18 | // ----------------------------------------------------------------------------- |
19 | |
20 | /* |
21 | Note: the name of the expression vector type only identifies the target |
22 | type. In various cases we want to change the target type, thus the arbitrary |
23 | conversions have been added. |
24 | |
25 | Expression types are not meant to be used by the user, thus all constructors |
26 | are implicit. |
27 | */ |
28 | |
29 | // ----------------------------------------------------------------------------- |
30 | // float32 |
31 | |
32 | template<unsigned N, class E> |
33 | class float32 : public any_float32<N, float32<N,E>>{ |
34 | public: |
35 | static const unsigned type_tag = SIMDPP_TAG_FLOAT; |
36 | using expr_type = E; |
37 | E e; |
38 | |
39 | SIMDPP_INL float32(const E& a) : e(a) {} |
40 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
41 | float32(const any_vec<N*4,V<N2,E>>& a) : e(a.wrapped().e) {} |
42 | |
43 | SIMDPP_INL operator float32<N>() const { return eval(); } |
44 | SIMDPP_INL float32<N> eval() const |
45 | { return detail::expr_eval_wrapper<float32<N>, expr_type>::eval(e); } |
46 | }; |
47 | |
48 | template<unsigned N, class E> |
49 | class mask_float32 : public any_float32<N, mask_float32<N,E>> { |
50 | public: |
51 | static const unsigned type_tag = SIMDPP_TAG_MASK_FLOAT; |
52 | using expr_type = E; |
53 | E e; |
54 | |
55 | SIMDPP_INL mask_float32(const E& a) : e(a) {} |
56 | |
57 | SIMDPP_INL operator mask_float32<N>() const { return eval(); } |
58 | SIMDPP_INL operator float32<N>() const { return eval(); } |
59 | SIMDPP_INL mask_float32<N> eval() const |
60 | { return detail::expr_eval_wrapper<mask_float32<N>, expr_type>::eval(e); } |
61 | }; |
62 | |
63 | // ----------------------------------------------------------------------------- |
64 | // float64 |
65 | |
66 | template<unsigned N, class E> |
67 | class float64 : public any_float64<N, float64<N,E>> { |
68 | public: |
69 | static const unsigned type_tag = SIMDPP_TAG_FLOAT; |
70 | using expr_type = E; |
71 | E e; |
72 | |
73 | SIMDPP_INL float64(const E& a) : e(a) {} |
74 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
75 | float64(const any_vec<N*8,V<N2,E>>& a) : e(a.wrapped().e) {} |
76 | |
77 | SIMDPP_INL operator float64<N>() const { return eval(); } |
78 | SIMDPP_INL float64<N> eval() const |
79 | { return detail::expr_eval_wrapper<float64<N>, expr_type>::eval(e); } |
80 | }; |
81 | |
82 | template<unsigned N, class E> |
83 | class mask_float64 : public any_float64<N, mask_float64<N,E>> { |
84 | public: |
85 | static const unsigned type_tag = SIMDPP_TAG_MASK_FLOAT; |
86 | using expr_type = E; |
87 | E e; |
88 | |
89 | SIMDPP_INL mask_float64(const E& a) : e(a) {} |
90 | |
91 | SIMDPP_INL operator mask_float64<N>() const { return eval(); } |
92 | SIMDPP_INL operator float64<N>() const { return eval(); } |
93 | SIMDPP_INL mask_float64<N> eval() const |
94 | { return detail::expr_eval_wrapper<mask_float64<N>, expr_type>::eval(e); } |
95 | }; |
96 | |
97 | // ----------------------------------------------------------------------------- |
98 | // uint8<N> |
99 | template<unsigned N, class E> |
100 | class int8 : public any_int8<N, int8<N,E>> { |
101 | public: |
102 | static const unsigned type_tag = SIMDPP_TAG_INT; |
103 | using expr_type = E; |
104 | E e; |
105 | |
106 | SIMDPP_INL int8(const E& a) : e(a) {} |
107 | |
108 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
109 | int8(const any_vec<N,V<N2,E>>& a) : e(a.wrapped().e) {} |
110 | |
111 | SIMDPP_INL operator int8<N>() const { return eval(); } |
112 | SIMDPP_INL int8<N> eval() const |
113 | { return detail::expr_eval_wrapper<int8<N>, expr_type>::eval(e); } |
114 | }; |
115 | |
116 | |
117 | template<unsigned N, class E> |
118 | class uint8 : public any_int8<N, uint8<N,E>> { |
119 | public: |
120 | static const unsigned type_tag = SIMDPP_TAG_UINT; |
121 | using expr_type = E; |
122 | E e; |
123 | |
124 | SIMDPP_INL uint8(const E& a) : e(a) {} |
125 | |
126 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
127 | uint8(const any_vec<N,V<N2,E>>& a) : e(a.wrapped().e) {} |
128 | |
129 | SIMDPP_INL operator uint8<N>() const { return eval(); } |
130 | SIMDPP_INL uint8<N> eval() const |
131 | { return detail::expr_eval_wrapper<uint8<N>, expr_type>::eval(e); } |
132 | }; |
133 | |
134 | template<unsigned N, class E> |
135 | class mask_int8 : public any_int8<N, mask_int8<N,E>> { |
136 | public: |
137 | static const unsigned type_tag = SIMDPP_TAG_MASK_INT; |
138 | using expr_type = E; |
139 | E e; |
140 | |
141 | SIMDPP_INL mask_int8(const E& a) : e(a) {} |
142 | |
143 | SIMDPP_INL operator mask_int8<N>() const { return eval(); } |
144 | SIMDPP_INL operator uint8<N>() const { return eval(); } |
145 | SIMDPP_INL mask_int8<N> eval() const |
146 | { return detail::expr_eval_wrapper<mask_int8<N>, expr_type>::eval(e); } |
147 | }; |
148 | |
149 | // ----------------------------------------------------------------------------- |
150 | // uint16<N> |
151 | template<unsigned N, class E> |
152 | class int16 : public any_int16<N, int16<N,E>> { |
153 | public: |
154 | static const unsigned type_tag = SIMDPP_TAG_INT; |
155 | using expr_type = E; |
156 | E e; |
157 | |
158 | SIMDPP_INL int16(const E& a) : e(a) {} |
159 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
160 | int16(const any_vec<N*2,V<N2,E>>& a) : e(a.wrapped().e) {} |
161 | |
162 | SIMDPP_INL operator int16<N>() const { return eval(); } |
163 | SIMDPP_INL int16<N> eval() const |
164 | { return detail::expr_eval_wrapper<int16<N>, expr_type>::eval(e); } |
165 | }; |
166 | |
167 | |
168 | template<unsigned N, class E> |
169 | class uint16 : public any_int16<N, uint16<N,E>> { |
170 | public: |
171 | static const unsigned type_tag = SIMDPP_TAG_UINT; |
172 | using expr_type = E; |
173 | E e; |
174 | |
175 | SIMDPP_INL uint16(const E& a) : e(a) {} |
176 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
177 | uint16(const any_vec<N*2,V<N2,E>>& a) : e(a.wrapped().e) {} |
178 | |
179 | SIMDPP_INL operator uint16<N>() const { return eval(); } |
180 | SIMDPP_INL uint16<N> eval() const |
181 | { return detail::expr_eval_wrapper<uint16<N>, expr_type>::eval(e); } |
182 | }; |
183 | |
184 | template<unsigned N, class E> |
185 | class mask_int16 : public any_int16<N, mask_int16<N,E>> { |
186 | public: |
187 | static const unsigned type_tag = SIMDPP_TAG_MASK_INT; |
188 | using expr_type = E; |
189 | E e; |
190 | |
191 | SIMDPP_INL mask_int16(const E& a) : e(a) {} |
192 | |
193 | SIMDPP_INL operator mask_int16<N>() const { return eval(); } |
194 | SIMDPP_INL operator uint16<N>() const { return eval(); } |
195 | SIMDPP_INL mask_int16<N> eval() const |
196 | { return detail::expr_eval_wrapper<mask_int16<N>, expr_type>::eval(e); } |
197 | }; |
198 | |
199 | // ----------------------------------------------------------------------------- |
200 | // uint32<N> |
201 | template<unsigned N, class E> |
202 | class int32 : public any_int32<N, int32<N,E>> { |
203 | public: |
204 | static const unsigned type_tag = SIMDPP_TAG_INT; |
205 | using expr_type = E; |
206 | E e; |
207 | |
208 | SIMDPP_INL int32(const E& a) : e(a) {} |
209 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
210 | int32(const any_vec<N*4,V<N2,E>>& a) : e(a.wrapped().e) {} |
211 | |
212 | SIMDPP_INL operator int32<N>() const { return eval(); } |
213 | SIMDPP_INL int32<N> eval() const |
214 | { return detail::expr_eval_wrapper<int32<N>, expr_type>::eval(e); } |
215 | }; |
216 | |
217 | |
218 | template<unsigned N, class E> |
219 | class uint32 : public any_int32<N, uint32<N,E>> { |
220 | public: |
221 | static const unsigned type_tag = SIMDPP_TAG_UINT; |
222 | using expr_type = E; |
223 | E e; |
224 | |
225 | SIMDPP_INL uint32(const E& a) : e(a) {} |
226 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
227 | uint32(const any_vec<N*4,V<N2,E>>& a) : e(a.wrapped().e) {} |
228 | |
229 | SIMDPP_INL operator uint32<N>() const { return eval(); } |
230 | SIMDPP_INL uint32<N> eval() const |
231 | { return detail::expr_eval_wrapper<uint32<N>, expr_type>::eval(e); } |
232 | }; |
233 | |
234 | template<unsigned N, class E> |
235 | class mask_int32 : public any_int32<N, mask_int32<N,E>> { |
236 | public: |
237 | static const unsigned type_tag = SIMDPP_TAG_MASK_INT; |
238 | using expr_type = E; |
239 | E e; |
240 | |
241 | SIMDPP_INL mask_int32(const E& a) : e(a) {} |
242 | |
243 | SIMDPP_INL operator mask_int32<N>() const { return eval(); } |
244 | SIMDPP_INL operator uint32<N>() const { return eval(); } |
245 | SIMDPP_INL mask_int32<N> eval() const |
246 | { return detail::expr_eval_wrapper<mask_int32<N>, expr_type>::eval(e); } |
247 | }; |
248 | |
249 | // ----------------------------------------------------------------------------- |
250 | // int64<N> |
251 | |
252 | template<unsigned N, class E> |
253 | class int64 : public any_int64<N, int64<N,E>> { |
254 | public: |
255 | static const unsigned type_tag = SIMDPP_TAG_INT; |
256 | using expr_type = E; |
257 | E e; |
258 | |
259 | SIMDPP_INL int64(const E& a) : e(a) {} |
260 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
261 | int64(const any_vec<N*8,V<N2,E>>& a) : e(a.wrapped().e) {} |
262 | |
263 | SIMDPP_INL operator int64<N>() const { return eval(); } |
264 | SIMDPP_INL int64<N> eval() const |
265 | { return detail::expr_eval_wrapper<int64<N>, expr_type>::eval(e); } |
266 | }; |
267 | |
268 | |
269 | template<unsigned N, class E> |
270 | class uint64 : public any_int64<N, uint64<N,E>> { |
271 | public: |
272 | static const unsigned type_tag = SIMDPP_TAG_UINT; |
273 | using expr_type = E; |
274 | E e; |
275 | |
276 | SIMDPP_INL uint64(const E& a) : e(a) {} |
277 | template<template<unsigned, class> class V, unsigned N2> SIMDPP_INL |
278 | uint64(const any_vec<N*8,V<N2,E>>& a) : e(a.wrapped().e) {} |
279 | |
280 | SIMDPP_INL operator uint64<N>() const { return eval(); } |
281 | SIMDPP_INL uint64<N> eval() const |
282 | { return detail::expr_eval_wrapper<uint64<N>, expr_type>::eval(e); } |
283 | }; |
284 | |
285 | |
286 | template<unsigned N, class E> |
287 | class mask_int64 : public any_int64<N, mask_int64<N,E>> { |
288 | public: |
289 | static const unsigned type_tag = SIMDPP_TAG_MASK_INT; |
290 | using expr_type = E; |
291 | E e; |
292 | |
293 | SIMDPP_INL mask_int64(const E& a) : e(a) {} |
294 | |
295 | SIMDPP_INL operator mask_int64<N>() const { return eval(); } |
296 | SIMDPP_INL operator uint64<N>() const { return eval(); } |
297 | SIMDPP_INL mask_int64<N> eval() const |
298 | { return detail::expr_eval_wrapper<mask_int64<N>, expr_type>::eval(e); } |
299 | }; |
300 | |
301 | } // namespace SIMDPP_ARCH_NAMESPACE |
302 | } // namespace simdpp |
303 | |
304 | #endif |
305 | |
306 | |