28 #ifndef VC_COMMON_STORAGE_H_
29 #define VC_COMMON_STORAGE_H_
31 #include "aliasingentryhelper.h"
35 #include "../avx/intrinsics.h"
39 namespace Vc_VERSIONED_NAMESPACE
43 template <
typename V>
inline V zero();
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,
58 typename std::conditional<
sizeof(ValueType) * Size == 16, __m128,
59 __m256>::type>::type>::type;
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,
68 #elif defined Vc_IMPL_MIC
69 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
70 using type =
typename std::conditional<
71 std::is_integral<ValueType>::value, __m512i,
72 typename std::conditional<std::is_same<ValueType, double>::value, __m512d,
76 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
77 static_assert(Size == 1,
78 "IntrinsicType without SIMD target support may only have Size = 1");
79 using type = ValueType;
82 template <
typename ValueType,
size_t Size,
size_t Bytes = sizeof(ValueType) * Size>
84 #ifdef Vc_USE_BUILTIN_VECTOR_TYPES
85 #define Vc_VECBUILTIN __attribute__((__vector_size__(16)))
86 template <
size_t Size>
struct BuiltinType< double , Size, 16> {
typedef double type Vc_VECBUILTIN; };
87 template <
size_t Size>
struct BuiltinType< float , Size, 16> {
typedef float type Vc_VECBUILTIN; };
88 template <
size_t Size>
struct BuiltinType< long long, Size, 16> {
typedef long long type Vc_VECBUILTIN; };
89 template <
size_t Size>
struct BuiltinType<unsigned long long, Size, 16> {
typedef unsigned long long type Vc_VECBUILTIN; };
90 template <
size_t Size>
struct BuiltinType< long , Size, 16> {
typedef long type Vc_VECBUILTIN; };
91 template <
size_t Size>
struct BuiltinType<unsigned long , Size, 16> {
typedef unsigned long type Vc_VECBUILTIN; };
92 template <
size_t Size>
struct BuiltinType< int , Size, 16> {
typedef int type Vc_VECBUILTIN; };
93 template <
size_t Size>
struct BuiltinType<unsigned int , Size, 16> {
typedef unsigned int type Vc_VECBUILTIN; };
94 template <
size_t Size>
struct BuiltinType< short , Size, 16> {
typedef short type Vc_VECBUILTIN; };
95 template <
size_t Size>
struct BuiltinType<unsigned short , Size, 16> {
typedef unsigned short type Vc_VECBUILTIN; };
96 template <
size_t Size>
struct BuiltinType< char , Size, 16> {
typedef char type Vc_VECBUILTIN; };
97 template <
size_t Size>
struct BuiltinType<unsigned char , Size, 16> {
typedef unsigned char type Vc_VECBUILTIN; };
98 template <
size_t Size>
struct BuiltinType< signed char , Size, 16> {
typedef signed char type Vc_VECBUILTIN; };
99 template <
size_t Size>
struct BuiltinType< bool , Size, 16> {
typedef unsigned char type Vc_VECBUILTIN; };
101 #define Vc_VECBUILTIN __attribute__((__vector_size__(32)))
102 template <
size_t Size>
struct BuiltinType< double , Size, 32> {
typedef double type Vc_VECBUILTIN; };
103 template <
size_t Size>
struct BuiltinType< float , Size, 32> {
typedef float type Vc_VECBUILTIN; };
104 template <
size_t Size>
struct BuiltinType< long long, Size, 32> {
typedef long long type Vc_VECBUILTIN; };
105 template <
size_t Size>
struct BuiltinType<unsigned long long, Size, 32> {
typedef unsigned long long type Vc_VECBUILTIN; };
106 template <
size_t Size>
struct BuiltinType< long , Size, 32> {
typedef long type Vc_VECBUILTIN; };
107 template <
size_t Size>
struct BuiltinType<unsigned long , Size, 32> {
typedef unsigned long type Vc_VECBUILTIN; };
108 template <
size_t Size>
struct BuiltinType< int , Size, 32> {
typedef int type Vc_VECBUILTIN; };
109 template <
size_t Size>
struct BuiltinType<unsigned int , Size, 32> {
typedef unsigned int type Vc_VECBUILTIN; };
110 template <
size_t Size>
struct BuiltinType< short , Size, 32> {
typedef short type Vc_VECBUILTIN; };
111 template <
size_t Size>
struct BuiltinType<unsigned short , Size, 32> {
typedef unsigned short type Vc_VECBUILTIN; };
112 template <
size_t Size>
struct BuiltinType< char , Size, 32> {
typedef char type Vc_VECBUILTIN; };
113 template <
size_t Size>
struct BuiltinType<unsigned char , Size, 32> {
typedef unsigned char type Vc_VECBUILTIN; };
114 template <
size_t Size>
struct BuiltinType< signed char , Size, 32> {
typedef signed char type Vc_VECBUILTIN; };
115 template <
size_t Size>
struct BuiltinType< bool , Size, 32> {
typedef unsigned char type Vc_VECBUILTIN; };
120 template <
typename ValueType,
size_t Size>
121 using IntrinsicType =
typename Detail::IntrinsicType<ValueType, Size>::type;
123 template <
typename ValueType,
size_t Size>
124 using BuiltinType =
typename Detail::BuiltinType<ValueType, Size>::type;
126 namespace AliasStrategy
130 struct VectorBuiltin {};
131 struct UnionMembers {};
134 using DefaultStrategy =
135 #if defined Vc_USE_BUILTIN_VECTOR_TYPES
136 AliasStrategy::VectorBuiltin;
137 #elif defined Vc_MSVC
138 AliasStrategy::UnionMembers;
140 AliasStrategy::Union;
141 #elif defined __GNUC__
142 AliasStrategy::MayAlias;
144 AliasStrategy::Union;
147 template <
typename ValueType,
size_t Size,
typename Strategy = DefaultStrategy>
151 template <
typename ValueType,
size_t Size>
152 class Storage<ValueType, Size, AliasStrategy::Union>
154 static_assert(std::is_fundamental<ValueType>::value &&
155 std::is_arithmetic<ValueType>::value,
156 "Only works for fundamental arithmetic types.");
159 using VectorType = IntrinsicType<ValueType, Size>;
160 using EntryType = ValueType;
163 Vc_INTRINSIC Alias(VectorType vv) : v(vv) {}
168 Vc_INTRINSIC Storage() : data(
Vc::Detail::zero<VectorType>()) {}
169 Vc_INTRINSIC Storage(
const VectorType &x) : data(x) { assertCorrectAlignment(&data); }
170 template <
typename U>
171 Vc_INTRINSIC
explicit Storage(
const U &x,
172 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
173 : data(reinterpret_cast<VectorType>(x))
175 assertCorrectAlignment(&data);
178 Vc_INTRINSIC Storage(
const Storage &) =
default;
179 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
181 Vc_INTRINSIC
operator const VectorType &()
const {
return data; }
182 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data; }
183 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data; }
184 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const {
return Alias(data).m[i]; }
185 Vc_INTRINSIC
void set(
size_t i, EntryType x)
196 template <
typename ValueType,
size_t Size>
197 class Storage<ValueType, Size, AliasStrategy::MayAlias>
199 static_assert(std::is_fundamental<ValueType>::value &&
200 std::is_arithmetic<ValueType>::value,
201 "Only works for fundamental arithmetic types.");
204 using VectorType = IntrinsicType<ValueType, Size>;
205 using EntryType = ValueType;
207 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
208 Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
210 assertCorrectAlignment(&data);
212 template <
typename U>
213 Vc_INTRINSIC
explicit Storage(
const U &x,
214 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
215 : data(reinterpret_cast<const VectorType &>(x))
217 assertCorrectAlignment(&data);
219 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
225 Vc_INTRINSIC Storage(
const Storage &) =
default;
226 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
228 Vc_INTRINSIC
operator const VectorType &()
const {
return v(); }
229 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data; }
230 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data; }
232 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const
234 return reinterpret_cast<const MayAlias<EntryType> *
>(&data)[i];
236 Vc_INTRINSIC
void set(
size_t i, EntryType x)
238 reinterpret_cast<MayAlias<EntryType> *
>(&data)[i] = x;
245 template <
typename ValueType,
size_t Size>
246 class Storage<ValueType, Size, AliasStrategy::VectorBuiltin>
248 static_assert(std::is_fundamental<ValueType>::value &&
249 std::is_arithmetic<ValueType>::value,
250 "Only works for fundamental arithmetic types.");
252 using Builtin = BuiltinType<ValueType, Size>;
256 #ifdef Vc_TEMPLATES_DROP_ATTRIBUTES
257 MayAlias<IntrinsicType<ValueType, Size>>;
259 IntrinsicType<ValueType, Size>;
261 using EntryType = ValueType;
263 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
264 Vc_INTRINSIC Storage(
const VectorType &x)
265 : data(reinterpret_cast<const MayAlias<Builtin> &>(x))
267 assertCorrectAlignment(&data);
269 template <
typename U>
270 Vc_INTRINSIC
explicit Storage(
const U &x,
271 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
272 : data(reinterpret_cast<const MayAlias<Builtin> &>(x))
274 assertCorrectAlignment(&data);
276 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
278 data =
reinterpret_cast<const MayAlias<Builtin> &
>(x);
282 Vc_INTRINSIC Storage(
const Storage &) =
default;
283 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
285 Vc_INTRINSIC
operator const VectorType &()
const {
return v(); }
286 Vc_INTRINSIC Vc_PURE VectorType &v() {
return reinterpret_cast<VectorType &
>(data); }
287 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return reinterpret_cast<const VectorType &
>(data); }
289 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const {
return data[i]; }
290 Vc_INTRINSIC
void set(
size_t i, EntryType x) { data[i] = x; }
292 Vc_INTRINSIC Builtin &builtin() {
return data; }
293 Vc_INTRINSIC
const Builtin &builtin()
const {
return data; }
299 template <
typename ValueType,
size_t Size>
300 class Storage<ValueType, Size, AliasStrategy::UnionMembers>
302 static_assert(std::is_fundamental<ValueType>::value &&
303 std::is_arithmetic<ValueType>::value,
304 "Only works for fundamental arithmetic types.");
307 using VectorType = IntrinsicType<ValueType, Size>;
308 using EntryType = ValueType;
310 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
311 Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
313 assertCorrectAlignment(&data);
315 template <
typename U>
316 Vc_INTRINSIC
explicit Storage(
const U &x,
317 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
318 : data(reinterpret_cast<const VectorType &>(x))
320 assertCorrectAlignment(&data);
322 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
328 Vc_INTRINSIC Storage(
const Storage &) =
default;
329 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
331 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data; }
332 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data; }
334 Vc_INTRINSIC_L Vc_PURE_L EntryType m(
size_t i)
const Vc_INTRINSIC_R Vc_PURE_R;
335 Vc_INTRINSIC
void set(
size_t i, EntryType x) { ref(i) = x; }
338 Vc_INTRINSIC_L Vc_PURE_L EntryType &ref(
size_t i) Vc_INTRINSIC_R Vc_PURE_R;
343 template <> Vc_INTRINSIC Vc_PURE
double Storage< double, 2, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128d_f64[i]; }
344 template <> Vc_INTRINSIC Vc_PURE
float Storage< float , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128_f32[i]; }
345 template <> Vc_INTRINSIC Vc_PURE
signed int Storage< signed int , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i32[i]; }
346 template <> Vc_INTRINSIC Vc_PURE
signed short Storage< signed short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i16[i]; }
347 template <> Vc_INTRINSIC Vc_PURE
signed char Storage< signed char ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i8[i]; }
348 template <> Vc_INTRINSIC Vc_PURE
unsigned int Storage<unsigned int , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u32[i]; }
349 template <> Vc_INTRINSIC Vc_PURE
unsigned short Storage<unsigned short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u16[i]; }
350 template <> Vc_INTRINSIC Vc_PURE
unsigned char Storage<unsigned char ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u8[i]; }
352 template <> Vc_INTRINSIC Vc_PURE
double &Storage< double, 2, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128d_f64[i]; }
353 template <> Vc_INTRINSIC Vc_PURE
float &Storage< float , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128_f32[i]; }
354 template <> Vc_INTRINSIC Vc_PURE
signed int &Storage< signed int , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_i32[i]; }
355 template <> Vc_INTRINSIC Vc_PURE
signed short &Storage< signed short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_i16[i]; }
356 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]); }
357 template <> Vc_INTRINSIC Vc_PURE
unsigned int &Storage<unsigned int , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u32[i]; }
358 template <> Vc_INTRINSIC Vc_PURE
unsigned short &Storage<unsigned short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u16[i]; }
359 template <> Vc_INTRINSIC Vc_PURE
unsigned char &Storage<unsigned char ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u8[i]; }
362 template <> Vc_INTRINSIC Vc_PURE
double Storage< double, 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256d_f64[i]; }
363 template <> Vc_INTRINSIC Vc_PURE
float Storage< float , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256_f32[i]; }
364 template <> Vc_INTRINSIC Vc_PURE
signed int Storage< signed int , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i32[i]; }
365 template <> Vc_INTRINSIC Vc_PURE
signed short Storage< signed short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i16[i]; }
366 template <> Vc_INTRINSIC Vc_PURE
signed char Storage< signed char ,32, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i8[i]; }
367 template <> Vc_INTRINSIC Vc_PURE
unsigned int Storage<unsigned int , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u32[i]; }
368 template <> Vc_INTRINSIC Vc_PURE
unsigned short Storage<unsigned short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u16[i]; }
369 template <> Vc_INTRINSIC Vc_PURE
unsigned char Storage<unsigned char ,32, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u8[i]; }
371 template <> Vc_INTRINSIC Vc_PURE
double &Storage< double, 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256d_f64[i]; }
372 template <> Vc_INTRINSIC Vc_PURE
float &Storage< float , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256_f32[i]; }
373 template <> Vc_INTRINSIC Vc_PURE
signed int &Storage< signed int , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_i32[i]; }
374 template <> Vc_INTRINSIC Vc_PURE
signed short &Storage< signed short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_i16[i]; }
375 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]); }
376 template <> Vc_INTRINSIC Vc_PURE
unsigned int &Storage<unsigned int , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u32[i]; }
377 template <> Vc_INTRINSIC Vc_PURE
unsigned short &Storage<unsigned short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u16[i]; }
378 template <> Vc_INTRINSIC Vc_PURE
unsigned char &Storage<unsigned char ,32, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u8[i]; }
382 template <
typename VectorType,
typename EntryType>
383 using VectorMemoryUnion = Storage<EntryType,
sizeof(VectorType) /
sizeof(EntryType)>;
388 #endif // VC_COMMON_STORAGE_H_
Vector Classes Namespace.