Vc  1.4.2
SIMD Vector Classes for C++
storage.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2010-2015 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, 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 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON 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
24 SOFTWARE, 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 
39 namespace Vc_VERSIONED_NAMESPACE
40 {
41 namespace Detail
42 {
43 template <typename V> inline V zero();
44 } // namespace Detail
45 namespace Common
46 {
47 namespace Detail
48 {
49 #ifdef Vc_IMPL_AVX
50 template <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
62 template <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
69 template <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
75 template <typename ValueType, size_t Size, size_t Bytes = sizeof(ValueType) * Size>
76 struct BuiltinType;
77 #ifdef Vc_USE_BUILTIN_VECTOR_TYPES
78 #define Vc_VECBUILTIN __attribute__((__vector_size__(16)))
79 template <size_t Size> struct BuiltinType< double , Size, 16> { typedef double type Vc_VECBUILTIN; };
80 template <size_t Size> struct BuiltinType< float , Size, 16> { typedef float type Vc_VECBUILTIN; };
81 template <size_t Size> struct BuiltinType< long long, Size, 16> { typedef long long type Vc_VECBUILTIN; };
82 template <size_t Size> struct BuiltinType<unsigned long long, Size, 16> { typedef unsigned long long type Vc_VECBUILTIN; };
83 template <size_t Size> struct BuiltinType< long , Size, 16> { typedef long type Vc_VECBUILTIN; };
84 template <size_t Size> struct BuiltinType<unsigned long , Size, 16> { typedef unsigned long type Vc_VECBUILTIN; };
85 template <size_t Size> struct BuiltinType< int , Size, 16> { typedef int type Vc_VECBUILTIN; };
86 template <size_t Size> struct BuiltinType<unsigned int , Size, 16> { typedef unsigned int type Vc_VECBUILTIN; };
87 template <size_t Size> struct BuiltinType< short , Size, 16> { typedef short type Vc_VECBUILTIN; };
88 template <size_t Size> struct BuiltinType<unsigned short , Size, 16> { typedef unsigned short type Vc_VECBUILTIN; };
89 template <size_t Size> struct BuiltinType< char , Size, 16> { typedef char type Vc_VECBUILTIN; };
90 template <size_t Size> struct BuiltinType<unsigned char , Size, 16> { typedef unsigned char type Vc_VECBUILTIN; };
91 template <size_t Size> struct BuiltinType< signed char , Size, 16> { typedef signed char type Vc_VECBUILTIN; };
92 template <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)))
95 template <size_t Size> struct BuiltinType< double , Size, 32> { typedef double type Vc_VECBUILTIN; };
96 template <size_t Size> struct BuiltinType< float , Size, 32> { typedef float type Vc_VECBUILTIN; };
97 template <size_t Size> struct BuiltinType< long long, Size, 32> { typedef long long type Vc_VECBUILTIN; };
98 template <size_t Size> struct BuiltinType<unsigned long long, Size, 32> { typedef unsigned long long type Vc_VECBUILTIN; };
99 template <size_t Size> struct BuiltinType< long , Size, 32> { typedef long type Vc_VECBUILTIN; };
100 template <size_t Size> struct BuiltinType<unsigned long , Size, 32> { typedef unsigned long type Vc_VECBUILTIN; };
101 template <size_t Size> struct BuiltinType< int , Size, 32> { typedef int type Vc_VECBUILTIN; };
102 template <size_t Size> struct BuiltinType<unsigned int , Size, 32> { typedef unsigned int type Vc_VECBUILTIN; };
103 template <size_t Size> struct BuiltinType< short , Size, 32> { typedef short type Vc_VECBUILTIN; };
104 template <size_t Size> struct BuiltinType<unsigned short , Size, 32> { typedef unsigned short type Vc_VECBUILTIN; };
105 template <size_t Size> struct BuiltinType< char , Size, 32> { typedef char type Vc_VECBUILTIN; };
106 template <size_t Size> struct BuiltinType<unsigned char , Size, 32> { typedef unsigned char type Vc_VECBUILTIN; };
107 template <size_t Size> struct BuiltinType< signed char , Size, 32> { typedef signed char type Vc_VECBUILTIN; };
108 template <size_t Size> struct BuiltinType< bool , Size, 32> { typedef unsigned char type Vc_VECBUILTIN; };
109 #undef Vc_VECBUILTIN
110 #endif
111 } // namespace Detail
112 
113 template <typename ValueType, size_t Size>
114 using IntrinsicType = typename Detail::IntrinsicType<ValueType, Size>::type;
115 
116 template <typename ValueType, size_t Size>
117 using BuiltinType = typename Detail::BuiltinType<ValueType, Size>::type;
118 
119 namespace AliasStrategy
120 {
121 struct Union {};
122 struct MayAlias {};
123 struct VectorBuiltin {};
124 struct UnionMembers {};
125 } // namespace AliasStrategy
126 
127 using 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 
140 template <typename ValueType, size_t Size, typename Strategy = DefaultStrategy>
141 class Storage;
142 
143 // GCC 6 forbids `EntryType m[]` altogether
144 template <typename ValueType, size_t Size>
145 class 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 
151 public:
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 
185 private:
186  VectorType data;
187 };
188 
189 template <typename ValueType, size_t Size>
190 class 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 
196 public:
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 
234 private:
235  VectorType data;
236 };
237 
238 template <typename ValueType, size_t Size>
239 class 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 
247 public:
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 
288 private:
289  Builtin data;
290 };
291 
292 template <typename ValueType, size_t Size>
293 class 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 
299 public:
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 
330 private:
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
336 template <> Vc_INTRINSIC Vc_PURE double Storage< double, 2, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128d_f64[i]; }
337 template <> Vc_INTRINSIC Vc_PURE float Storage< float , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128_f32[i]; }
338 template <> Vc_INTRINSIC Vc_PURE signed int Storage< signed int , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i32[i]; }
339 template <> Vc_INTRINSIC Vc_PURE signed short Storage< signed short , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i16[i]; }
340 template <> Vc_INTRINSIC Vc_PURE signed char Storage< signed char ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i8[i]; }
341 template <> Vc_INTRINSIC Vc_PURE unsigned int Storage<unsigned int , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u32[i]; }
342 template <> Vc_INTRINSIC Vc_PURE unsigned short Storage<unsigned short , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u16[i]; }
343 template <> Vc_INTRINSIC Vc_PURE unsigned char Storage<unsigned char ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u8[i]; }
344 
345 template <> Vc_INTRINSIC Vc_PURE double &Storage< double, 2, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128d_f64[i]; }
346 template <> Vc_INTRINSIC Vc_PURE float &Storage< float , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128_f32[i]; }
347 template <> Vc_INTRINSIC Vc_PURE signed int &Storage< signed int , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_i32[i]; }
348 template <> Vc_INTRINSIC Vc_PURE signed short &Storage< signed short , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_i16[i]; }
349 template <> 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]); }
350 template <> Vc_INTRINSIC Vc_PURE unsigned int &Storage<unsigned int , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u32[i]; }
351 template <> Vc_INTRINSIC Vc_PURE unsigned short &Storage<unsigned short , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u16[i]; }
352 template <> 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
355 template <> Vc_INTRINSIC Vc_PURE double Storage< double, 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256d_f64[i]; }
356 template <> Vc_INTRINSIC Vc_PURE float Storage< float , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256_f32[i]; }
357 template <> Vc_INTRINSIC Vc_PURE signed int Storage< signed int , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i32[i]; }
358 template <> Vc_INTRINSIC Vc_PURE signed short Storage< signed short ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i16[i]; }
359 template <> Vc_INTRINSIC Vc_PURE signed char Storage< signed char ,32, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i8[i]; }
360 template <> Vc_INTRINSIC Vc_PURE unsigned int Storage<unsigned int , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u32[i]; }
361 template <> Vc_INTRINSIC Vc_PURE unsigned short Storage<unsigned short ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u16[i]; }
362 template <> Vc_INTRINSIC Vc_PURE unsigned char Storage<unsigned char ,32, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u8[i]; }
363 
364 template <> Vc_INTRINSIC Vc_PURE double &Storage< double, 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256d_f64[i]; }
365 template <> Vc_INTRINSIC Vc_PURE float &Storage< float , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256_f32[i]; }
366 template <> Vc_INTRINSIC Vc_PURE signed int &Storage< signed int , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_i32[i]; }
367 template <> Vc_INTRINSIC Vc_PURE signed short &Storage< signed short ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_i16[i]; }
368 template <> 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]); }
369 template <> Vc_INTRINSIC Vc_PURE unsigned int &Storage<unsigned int , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u32[i]; }
370 template <> Vc_INTRINSIC Vc_PURE unsigned short &Storage<unsigned short ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u16[i]; }
371 template <> 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 
375 template <typename VectorType, typename EntryType>
376 using VectorMemoryUnion = Storage<EntryType, sizeof(VectorType) / sizeof(EntryType)>;
377 
378 } // namespace Common
379 } // namespace Vc
380 
381 #endif // VC_COMMON_STORAGE_H_
Vc
Vector Classes Namespace.
Definition: dox.h:586