Vc 1.4.5
SIMD Vector Classes for C++
 
Loading...
Searching...
No Matches
storage.h
1/* This file is part of the Vc library. {{{
2Copyright © 2010-2015 Matthias Kretz <kretz@kde.org>
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the names of contributing organizations nor the
12 names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
14
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26}}}*/
27
28#ifndef VC_COMMON_STORAGE_H_
29#define VC_COMMON_STORAGE_H_
30
31#include "aliasingentryhelper.h"
32#include "types.h"
33#include "maskbool.h"
34#ifdef Vc_IMPL_AVX
35#include "../avx/intrinsics.h"
36#endif
37#include "macros.h"
38
39namespace Vc_VERSIONED_NAMESPACE
40{
41namespace Detail
42{
43template <typename V> inline V zero();
44} // namespace Detail
45namespace Common
46{
47namespace Detail
48{
49#ifdef Vc_IMPL_AVX
50template <typename ValueType, size_t Size> struct IntrinsicType {
51 using type = typename std::conditional<
52 std::is_integral<ValueType>::value,
53 typename std::conditional<sizeof(ValueType) * Size == 16, __m128i, __m256i>::type,
54 typename std::conditional<
55 std::is_same<ValueType, double>::value,
56 typename std::conditional<sizeof(ValueType) * Size == 16, __m128d,
57 __m256d>::type,
58 typename std::conditional<sizeof(ValueType) * Size == 16, __m128,
59 __m256>::type>::type>::type;
60};
61#elif defined Vc_IMPL_SSE
62template <typename ValueType, size_t Size> struct IntrinsicType {
63 using type = typename std::conditional<
64 std::is_integral<ValueType>::value, __m128i,
65 typename std::conditional<std::is_same<ValueType, double>::value, __m128d,
66 __m128>::type>::type;
67};
68#else
69template <typename ValueType, size_t Size> struct IntrinsicType {
70 static_assert(Size == 1,
71 "IntrinsicType without SIMD target support may only have Size = 1");
72 using type = ValueType;
73};
74#endif
75template <typename ValueType, size_t Size, size_t Bytes = sizeof(ValueType) * Size>
76struct BuiltinType;
77#ifdef Vc_USE_BUILTIN_VECTOR_TYPES
78#define Vc_VECBUILTIN __attribute__((__vector_size__(16)))
79template <size_t Size> struct BuiltinType< double , Size, 16> { typedef double type Vc_VECBUILTIN; };
80template <size_t Size> struct BuiltinType< float , Size, 16> { typedef float type Vc_VECBUILTIN; };
81template <size_t Size> struct BuiltinType< long long, Size, 16> { typedef long long type Vc_VECBUILTIN; };
82template <size_t Size> struct BuiltinType<unsigned long long, Size, 16> { typedef unsigned long long type Vc_VECBUILTIN; };
83template <size_t Size> struct BuiltinType< long , Size, 16> { typedef long type Vc_VECBUILTIN; };
84template <size_t Size> struct BuiltinType<unsigned long , Size, 16> { typedef unsigned long type Vc_VECBUILTIN; };
85template <size_t Size> struct BuiltinType< int , Size, 16> { typedef int type Vc_VECBUILTIN; };
86template <size_t Size> struct BuiltinType<unsigned int , Size, 16> { typedef unsigned int type Vc_VECBUILTIN; };
87template <size_t Size> struct BuiltinType< short , Size, 16> { typedef short type Vc_VECBUILTIN; };
88template <size_t Size> struct BuiltinType<unsigned short , Size, 16> { typedef unsigned short type Vc_VECBUILTIN; };
89template <size_t Size> struct BuiltinType< char , Size, 16> { typedef char type Vc_VECBUILTIN; };
90template <size_t Size> struct BuiltinType<unsigned char , Size, 16> { typedef unsigned char type Vc_VECBUILTIN; };
91template <size_t Size> struct BuiltinType< signed char , Size, 16> { typedef signed char type Vc_VECBUILTIN; };
92template <size_t Size> struct BuiltinType< bool , Size, 16> { typedef unsigned char type Vc_VECBUILTIN; };
93#undef Vc_VECBUILTIN
94#define Vc_VECBUILTIN __attribute__((__vector_size__(32)))
95template <size_t Size> struct BuiltinType< double , Size, 32> { typedef double type Vc_VECBUILTIN; };
96template <size_t Size> struct BuiltinType< float , Size, 32> { typedef float type Vc_VECBUILTIN; };
97template <size_t Size> struct BuiltinType< long long, Size, 32> { typedef long long type Vc_VECBUILTIN; };
98template <size_t Size> struct BuiltinType<unsigned long long, Size, 32> { typedef unsigned long long type Vc_VECBUILTIN; };
99template <size_t Size> struct BuiltinType< long , Size, 32> { typedef long type Vc_VECBUILTIN; };
100template <size_t Size> struct BuiltinType<unsigned long , Size, 32> { typedef unsigned long type Vc_VECBUILTIN; };
101template <size_t Size> struct BuiltinType< int , Size, 32> { typedef int type Vc_VECBUILTIN; };
102template <size_t Size> struct BuiltinType<unsigned int , Size, 32> { typedef unsigned int type Vc_VECBUILTIN; };
103template <size_t Size> struct BuiltinType< short , Size, 32> { typedef short type Vc_VECBUILTIN; };
104template <size_t Size> struct BuiltinType<unsigned short , Size, 32> { typedef unsigned short type Vc_VECBUILTIN; };
105template <size_t Size> struct BuiltinType< char , Size, 32> { typedef char type Vc_VECBUILTIN; };
106template <size_t Size> struct BuiltinType<unsigned char , Size, 32> { typedef unsigned char type Vc_VECBUILTIN; };
107template <size_t Size> struct BuiltinType< signed char , Size, 32> { typedef signed char type Vc_VECBUILTIN; };
108template <size_t Size> struct BuiltinType< bool , Size, 32> { typedef unsigned char type Vc_VECBUILTIN; };
109#undef Vc_VECBUILTIN
110#endif
111} // namespace Detail
112
113template <typename ValueType, size_t Size>
114using IntrinsicType = typename Detail::IntrinsicType<ValueType, Size>::type;
115
116template <typename ValueType, size_t Size>
117using BuiltinType = typename Detail::BuiltinType<ValueType, Size>::type;
118
119namespace AliasStrategy
120{
121struct Union {};
122struct MayAlias {};
123struct VectorBuiltin {};
124struct UnionMembers {};
125} // namespace AliasStrategy
126
127using DefaultStrategy =
128#if defined Vc_USE_BUILTIN_VECTOR_TYPES
129 AliasStrategy::VectorBuiltin;
130#elif defined Vc_MSVC
131 AliasStrategy::UnionMembers;
132#elif defined Vc_ICC
133 AliasStrategy::Union;
134#elif defined __GNUC__
135 AliasStrategy::MayAlias;
136#else
137 AliasStrategy::Union;
138#endif
139
140template <typename ValueType, size_t Size, typename Strategy = DefaultStrategy>
141class Storage;
142
143// GCC 6 forbids `EntryType m[]` altogether
144template <typename ValueType, size_t Size>
145class Storage<ValueType, Size, AliasStrategy::Union>
146{
147 static_assert(std::is_fundamental<ValueType>::value &&
148 std::is_arithmetic<ValueType>::value,
149 "Only works for fundamental arithmetic types.");
150
151public:
152 using VectorType = IntrinsicType<ValueType, Size>;
153 using EntryType = ValueType;
154
155 union Alias {
156 Vc_INTRINSIC Alias(VectorType vv) : v(vv) {}
157 VectorType v;
158 EntryType m[Size];
159 };
160
161 Vc_INTRINSIC Storage() : data(Vc::Detail::zero<VectorType>()) {}
162 Vc_INTRINSIC Storage(const VectorType &x) : data(x) { assertCorrectAlignment(&data); }
163 template <typename U>
164 Vc_INTRINSIC explicit Storage(const U &x,
165 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
166 : data(reinterpret_cast<VectorType>(x))
167 {
168 assertCorrectAlignment(&data);
169 }
170
171 Vc_INTRINSIC Storage(const Storage &) = default;
172 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
173
174 Vc_INTRINSIC operator const VectorType &() const { return data; }
175 Vc_INTRINSIC Vc_PURE VectorType &v() { return data; }
176 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return data; }
177 Vc_INTRINSIC Vc_PURE EntryType m(size_t i) const { return Alias(data).m[i]; }
178 Vc_INTRINSIC void set(size_t i, EntryType x)
179 {
180 Alias a(data);
181 a.m[i] = x;
182 data = a.v;
183 }
184
185private:
186 VectorType data;
187};
188
189template <typename ValueType, size_t Size>
190class Storage<ValueType, Size, AliasStrategy::MayAlias>
191{
192 static_assert(std::is_fundamental<ValueType>::value &&
193 std::is_arithmetic<ValueType>::value,
194 "Only works for fundamental arithmetic types.");
195
196public:
197 using VectorType = IntrinsicType<ValueType, Size>;
198 using EntryType = ValueType;
199
200 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
201 Vc_INTRINSIC Storage(const VectorType &x) : data(x)
202 {
203 assertCorrectAlignment(&data);
204 }
205 template <typename U>
206 Vc_INTRINSIC explicit Storage(const U &x,
207 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
208 : data(reinterpret_cast<const VectorType &>(x))
209 {
210 assertCorrectAlignment(&data);
211 }
212 Vc_INTRINSIC Storage &operator=(const VectorType &x)
213 {
214 data = x;
215 return *this;
216 }
217
218 Vc_INTRINSIC Storage(const Storage &) = default;
219 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
220
221 Vc_INTRINSIC operator const VectorType &() const { return v(); }
222 Vc_INTRINSIC Vc_PURE VectorType &v() { return data; }
223 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return data; }
224
225 Vc_INTRINSIC Vc_PURE EntryType m(size_t i) const
226 {
227 return aliasing_cast<EntryType>(&data)[i];
228 }
229 Vc_INTRINSIC void set(size_t i, EntryType x)
230 {
231 aliasing_cast<EntryType>(&data)[i] = x;
232 }
233
234private:
235 VectorType data;
236};
237
238template <typename ValueType, size_t Size>
239class Storage<ValueType, Size, AliasStrategy::VectorBuiltin>
240{
241 static_assert(std::is_fundamental<ValueType>::value &&
242 std::is_arithmetic<ValueType>::value,
243 "Only works for fundamental arithmetic types.");
244
245 using Builtin = BuiltinType<ValueType, Size>;
246
247public:
248 using VectorType =
249#ifdef Vc_TEMPLATES_DROP_ATTRIBUTES
250 MayAlias<IntrinsicType<ValueType, Size>>;
251#else
252 IntrinsicType<ValueType, Size>;
253#endif
254 using EntryType = ValueType;
255
256 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
257 Vc_INTRINSIC Storage(const Storage &) = default;
258 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
259
260 Vc_INTRINSIC Storage(const VectorType &x)
261 : data(aliasing_cast<Builtin>(x))
262 {
263 assertCorrectAlignment(&data);
264 }
265 template <typename U>
266 Vc_INTRINSIC explicit Storage(const U &x,
267 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
268 : data(aliasing_cast<Builtin>(x))
269 {
270 assertCorrectAlignment(&data);
271 }
272 Vc_INTRINSIC Storage &operator=(const VectorType &x)
273 {
274 data = aliasing_cast<Builtin>(x);
275 return *this;
276 }
277
278 Vc_INTRINSIC operator const VectorType &() const { return v(); }
279 Vc_INTRINSIC Vc_PURE VectorType &v() { return reinterpret_cast<VectorType &>(data); }
280 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return reinterpret_cast<const VectorType &>(data); }
281
282 Vc_INTRINSIC Vc_PURE EntryType m(size_t i) const { return data[i]; }
283 Vc_INTRINSIC void set(size_t i, EntryType x) { data[i] = x; }
284
285 Vc_INTRINSIC Builtin &builtin() { return data; }
286 Vc_INTRINSIC const Builtin &builtin() const { return data; }
287
288private:
289 Builtin data;
290};
291
292template <typename ValueType, size_t Size>
293class Storage<ValueType, Size, AliasStrategy::UnionMembers>
294{
295 static_assert(std::is_fundamental<ValueType>::value &&
296 std::is_arithmetic<ValueType>::value,
297 "Only works for fundamental arithmetic types.");
298
299public:
300 using VectorType = IntrinsicType<ValueType, Size>;
301 using EntryType = ValueType;
302
303 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
304 Vc_INTRINSIC Storage(const VectorType &x) : data(x)
305 {
306 assertCorrectAlignment(&data);
307 }
308 template <typename U>
309 Vc_INTRINSIC explicit Storage(const U &x,
310 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
311 : data(reinterpret_cast<const VectorType &>(x))
312 {
313 assertCorrectAlignment(&data);
314 }
315 Vc_INTRINSIC Storage &operator=(const VectorType &x)
316 {
317 data = x;
318 return *this;
319 }
320
321 Vc_INTRINSIC Storage(const Storage &) = default;
322 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
323
324 Vc_INTRINSIC Vc_PURE VectorType &v() { return data; }
325 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return data; }
326
327 Vc_INTRINSIC_L Vc_PURE_L EntryType m(size_t i) const Vc_INTRINSIC_R Vc_PURE_R;
328 Vc_INTRINSIC void set(size_t i, EntryType x) { ref(i) = x; }
329
330private:
331 Vc_INTRINSIC_L Vc_PURE_L EntryType &ref(size_t i) Vc_INTRINSIC_R Vc_PURE_R;
332 VectorType data;
333};
334
335#ifdef Vc_MSVC
336template <> Vc_INTRINSIC Vc_PURE double Storage< double, 2, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128d_f64[i]; }
337template <> Vc_INTRINSIC Vc_PURE float Storage< float , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128_f32[i]; }
338template <> Vc_INTRINSIC Vc_PURE signed int Storage< signed int , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i32[i]; }
339template <> Vc_INTRINSIC Vc_PURE signed short Storage< signed short , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i16[i]; }
340template <> Vc_INTRINSIC Vc_PURE signed char Storage< signed char ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i8[i]; }
341template <> Vc_INTRINSIC Vc_PURE unsigned int Storage<unsigned int , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u32[i]; }
342template <> Vc_INTRINSIC Vc_PURE unsigned short Storage<unsigned short , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u16[i]; }
343template <> Vc_INTRINSIC Vc_PURE unsigned char Storage<unsigned char ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u8[i]; }
344
345template <> Vc_INTRINSIC Vc_PURE double &Storage< double, 2, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128d_f64[i]; }
346template <> Vc_INTRINSIC Vc_PURE float &Storage< float , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128_f32[i]; }
347template <> Vc_INTRINSIC Vc_PURE signed int &Storage< signed int , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_i32[i]; }
348template <> Vc_INTRINSIC Vc_PURE signed short &Storage< signed short , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_i16[i]; }
349template <> Vc_INTRINSIC Vc_PURE signed char &Storage< signed char ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return reinterpret_cast<signed char &>(data.m128i_i8[i]); }
350template <> Vc_INTRINSIC Vc_PURE unsigned int &Storage<unsigned int , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u32[i]; }
351template <> Vc_INTRINSIC Vc_PURE unsigned short &Storage<unsigned short , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u16[i]; }
352template <> Vc_INTRINSIC Vc_PURE unsigned char &Storage<unsigned char ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u8[i]; }
353
354#ifdef Vc_IMPL_AVX
355template <> Vc_INTRINSIC Vc_PURE double Storage< double, 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256d_f64[i]; }
356template <> Vc_INTRINSIC Vc_PURE float Storage< float , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256_f32[i]; }
357template <> Vc_INTRINSIC Vc_PURE signed int Storage< signed int , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i32[i]; }
358template <> Vc_INTRINSIC Vc_PURE signed short Storage< signed short ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i16[i]; }
359template <> Vc_INTRINSIC Vc_PURE signed char Storage< signed char ,32, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i8[i]; }
360template <> Vc_INTRINSIC Vc_PURE unsigned int Storage<unsigned int , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u32[i]; }
361template <> Vc_INTRINSIC Vc_PURE unsigned short Storage<unsigned short ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u16[i]; }
362template <> Vc_INTRINSIC Vc_PURE unsigned char Storage<unsigned char ,32, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u8[i]; }
363
364template <> Vc_INTRINSIC Vc_PURE double &Storage< double, 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256d_f64[i]; }
365template <> Vc_INTRINSIC Vc_PURE float &Storage< float , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256_f32[i]; }
366template <> Vc_INTRINSIC Vc_PURE signed int &Storage< signed int , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_i32[i]; }
367template <> Vc_INTRINSIC Vc_PURE signed short &Storage< signed short ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_i16[i]; }
368template <> Vc_INTRINSIC Vc_PURE signed char &Storage< signed char ,32, AliasStrategy::UnionMembers>::ref(size_t i) { return reinterpret_cast<signed char &>(data.m256i_i8[i]); }
369template <> Vc_INTRINSIC Vc_PURE unsigned int &Storage<unsigned int , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u32[i]; }
370template <> Vc_INTRINSIC Vc_PURE unsigned short &Storage<unsigned short ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u16[i]; }
371template <> Vc_INTRINSIC Vc_PURE unsigned char &Storage<unsigned char ,32, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u8[i]; }
372#endif
373#endif // Vc_MSVC
374
375template <typename VectorType, typename EntryType>
376using VectorMemoryUnion = Storage<EntryType, sizeof(VectorType) / sizeof(EntryType)>;
377
378} // namespace Common
379} // namespace Vc
380
381#endif // VC_COMMON_STORAGE_H_
Vector Classes Namespace.
Definition dox.h:585