29 #ifndef VC_COMMON_STORAGE_H_ 
   30 #define VC_COMMON_STORAGE_H_ 
   32 #include "aliasingentryhelper.h" 
   34 #include "maskentry.h" 
   36 #include "../avx/intrinsics.h" 
   40 namespace Vc_VERSIONED_NAMESPACE
 
   47 template <
typename ValueType, 
size_t Size> 
struct IntrinsicType {
 
   48     using type = 
typename std::conditional<
 
   49         std::is_integral<ValueType>::value,
 
   50         typename std::conditional<sizeof(ValueType) * Size == 16, __m128i, __m256i>::type,
 
   51         typename std::conditional<
 
   52             std::is_same<ValueType, double>::value,
 
   53             typename std::conditional<
sizeof(ValueType) * Size == 16, __m128d,
 
   55             typename std::conditional<
sizeof(ValueType) * Size == 16, __m128,
 
   56                                       __m256>::type>::type>::type;
 
   58 #elif defined Vc_IMPL_SSE 
   59 template <
typename ValueType, 
size_t Size> 
struct IntrinsicType {
 
   60     using type = 
typename std::conditional<
 
   61         std::is_integral<ValueType>::value, __m128i,
 
   62         typename std::conditional<std::is_same<ValueType, double>::value, __m128d,
 
   65 #elif defined Vc_IMPL_MIC 
   66 template <
typename ValueType, 
size_t Size> 
struct IntrinsicType {
 
   67     using type = 
typename std::conditional<
 
   68         std::is_integral<ValueType>::value, __m512i,
 
   69         typename std::conditional<std::is_same<ValueType, double>::value, __m512d,
 
   73 template <
typename ValueType, 
size_t Size> 
struct IntrinsicType {
 
   74     static_assert(Size == 1,
 
   75                   "IntrinsicType without SIMD target support may only have Size = 1");
 
   76     using type = ValueType;
 
   79 template <
typename ValueType, 
size_t Size, 
size_t Bytes = sizeof(ValueType) * Size>
 
   83     typedef ValueType type;
 
   85 #ifdef Vc_USE_BUILTIN_VECTOR_TYPES 
   86 #define Vc_VECBUILTIN __attribute__((__vector_size__(16))) 
   87 template <
size_t Size> 
struct BuiltinType<         double   , Size, 16> { 
typedef          double    type Vc_VECBUILTIN; };
 
   88 template <
size_t Size> 
struct BuiltinType<         float    , Size, 16> { 
typedef          float     type Vc_VECBUILTIN; };
 
   89 template <
size_t Size> 
struct BuiltinType<         long long, Size, 16> { 
typedef          long long type Vc_VECBUILTIN; };
 
   90 template <
size_t Size> 
struct BuiltinType<unsigned long long, Size, 16> { 
typedef unsigned long long type Vc_VECBUILTIN; };
 
   91 template <
size_t Size> 
struct BuiltinType<         long     , Size, 16> { 
typedef          long      type Vc_VECBUILTIN; };
 
   92 template <
size_t Size> 
struct BuiltinType<unsigned long     , Size, 16> { 
typedef unsigned long      type Vc_VECBUILTIN; };
 
   93 template <
size_t Size> 
struct BuiltinType<         int      , Size, 16> { 
typedef          int       type Vc_VECBUILTIN; };
 
   94 template <
size_t Size> 
struct BuiltinType<unsigned int      , Size, 16> { 
typedef unsigned int       type Vc_VECBUILTIN; };
 
   95 template <
size_t Size> 
struct BuiltinType<         short    , Size, 16> { 
typedef          short     type Vc_VECBUILTIN; };
 
   96 template <
size_t Size> 
struct BuiltinType<unsigned short    , Size, 16> { 
typedef unsigned short     type Vc_VECBUILTIN; };
 
   97 template <
size_t Size> 
struct BuiltinType<         char     , Size, 16> { 
typedef          char      type Vc_VECBUILTIN; };
 
   98 template <
size_t Size> 
struct BuiltinType<unsigned char     , Size, 16> { 
typedef unsigned char      type Vc_VECBUILTIN; };
 
   99 template <
size_t Size> 
struct BuiltinType<  signed char     , Size, 16> { 
typedef   signed 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; };
 
  119 template <
typename ValueType, 
size_t Size>
 
  120 using IntrinsicType = 
typename Detail::IntrinsicType<ValueType, Size>::type;
 
  122 template <
typename ValueType, 
size_t Size>
 
  123 using BuiltinType = 
typename Detail::BuiltinType<ValueType, Size>::type;
 
  125 namespace AliasStrategy
 
  129 struct VectorBuiltin {};
 
  130 struct UnionMembers {};
 
  133 using DefaultStrategy =
 
  134 #if defined Vc_USE_BUILTIN_VECTOR_TYPES 
  135     AliasStrategy::VectorBuiltin;
 
  136 #elif defined Vc_MSVC 
  137     AliasStrategy::UnionMembers;
 
  139     AliasStrategy::Union;
 
  140 #elif defined __GNUC__ 
  141     AliasStrategy::MayAlias;
 
  143     AliasStrategy::Union;
 
  146 template <
typename ValueType, 
size_t Size, 
typename Strategy = DefaultStrategy>
 
  149 template <
typename ValueType, 
size_t Size>
 
  150 class Storage<ValueType, Size, AliasStrategy::Union>
 
  152     static_assert(std::is_fundamental<ValueType>::value &&
 
  153                       std::is_arithmetic<ValueType>::value,
 
  154                   "Only works for fundamental arithmetic types.");
 
  157     using VectorType = IntrinsicType<ValueType, Size>;
 
  158     using EntryType = ValueType;
 
  160     Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data.v); }
 
  161     Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
 
  163         assertCorrectAlignment(&data.v);
 
  165     Vc_INTRINSIC Storage &operator=(
const VectorType &x)
 
  171     Vc_INTRINSIC Storage(
const Storage &) = 
default;
 
  172     Vc_INTRINSIC Storage &operator=(
const Storage &) = 
default;
 
  174     Vc_INTRINSIC Vc_PURE VectorType &v() { 
return data.v; }
 
  175     Vc_INTRINSIC Vc_PURE 
const VectorType &v()
 const { 
return data.v; }
 
  177     Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
 const { 
return data.m[i]; }
 
  178     Vc_INTRINSIC 
void set(
size_t i, EntryType x) { data.m[i] = x; }
 
  179     Vc_INTRINSIC Vc_PURE EntryType &ref(
size_t i) { 
return data.m[i]; }
 
  182     union VectorScalarUnion {
 
  183         Vc_INTRINSIC VectorScalarUnion() : v() {}
 
  184         Vc_INTRINSIC VectorScalarUnion(VectorType vv) : v(vv) {}
 
  187 #pragma GCC diagnostic push 
  188 #pragma GCC diagnostic ignored "-Wpedantic" 
  192 #pragma GCC diagnostic pop 
  197 template <
typename ValueType, 
size_t Size>
 
  198 class Storage<ValueType, Size, AliasStrategy::MayAlias>
 
  200     static_assert(std::is_fundamental<ValueType>::value &&
 
  201                       std::is_arithmetic<ValueType>::value,
 
  202                   "Only works for fundamental arithmetic types.");
 
  205     using VectorType = IntrinsicType<ValueType, Size>;
 
  206     using EntryType = ValueType;
 
  208     Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
 
  209     Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
 
  211         assertCorrectAlignment(&data);
 
  213     Vc_INTRINSIC Storage &operator=(
const VectorType &x)
 
  219     Vc_INTRINSIC Storage(
const Storage &) = 
default;
 
  220     Vc_INTRINSIC Storage &operator=(
const Storage &) = 
default;
 
  222     Vc_INTRINSIC Vc_PURE VectorType &v() { 
return data; }
 
  223     Vc_INTRINSIC Vc_PURE 
const VectorType &v()
 const { 
return data; }
 
  225     Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
 const 
  227         return reinterpret_cast<const MayAlias<EntryType> *
>(&data)[i];
 
  229     Vc_INTRINSIC 
void set(
size_t i, EntryType x)
 
  231         reinterpret_cast<MayAlias<EntryType> *
>(&data)[i] = x;
 
  233     Vc_INTRINSIC Vc_PURE MayAlias<EntryType> &ref(
size_t i)
 
  235         return reinterpret_cast<MayAlias<EntryType> *
>(&data)[i];
 
  242 template <
typename ValueType, 
size_t Size>
 
  243 class Storage<ValueType, Size, AliasStrategy::VectorBuiltin>
 
  245     static_assert(std::is_fundamental<ValueType>::value &&
 
  246                       std::is_arithmetic<ValueType>::value,
 
  247                   "Only works for fundamental arithmetic types.");
 
  249     using Builtin = BuiltinType<ValueType, Size>;
 
  252     using VectorType = IntrinsicType<ValueType, Size>;
 
  253     using EntryType = ValueType;
 
  255     Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
 
  256     Vc_INTRINSIC Storage(
const VectorType &x)
 
  257         : data(reinterpret_cast<const MayAlias<Builtin> &>(x))
 
  259         assertCorrectAlignment(&data);
 
  261     Vc_INTRINSIC Storage &operator=(
const VectorType &x)
 
  263         data = 
reinterpret_cast<const MayAlias<Builtin> &
>(x);
 
  267     Vc_INTRINSIC Storage(
const Storage &) = 
default;
 
  268     Vc_INTRINSIC Storage &operator=(
const Storage &) = 
default;
 
  270     Vc_INTRINSIC Vc_PURE VectorType &v() { 
return reinterpret_cast<VectorType &
>(data); }
 
  271     Vc_INTRINSIC Vc_PURE 
const VectorType &v()
 const { 
return reinterpret_cast<const VectorType &
>(data); }
 
  273     Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
 const { 
return data[i]; }
 
  274     Vc_INTRINSIC 
void set(
size_t i, EntryType x) { data[i] = x; }
 
  275     Vc_INTRINSIC Vc_PURE MayAlias<EntryType> &ref(
size_t i)
 
  277         return reinterpret_cast<MayAlias<EntryType> *
>(&data)[i];
 
  280     Vc_INTRINSIC Builtin &builtin() { 
return data; }
 
  281     Vc_INTRINSIC 
const Builtin &builtin()
 const { 
return data; }
 
  287 template <
typename ValueType, 
size_t Size>
 
  288 class Storage<ValueType, Size, AliasStrategy::UnionMembers>
 
  290     static_assert(std::is_fundamental<ValueType>::value &&
 
  291                       std::is_arithmetic<ValueType>::value,
 
  292                   "Only works for fundamental arithmetic types.");
 
  295     using VectorType = IntrinsicType<ValueType, Size>;
 
  296     using EntryType = ValueType;
 
  298     Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
 
  299     Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
 
  301         assertCorrectAlignment(&data);
 
  303     Vc_INTRINSIC Storage &operator=(
const VectorType &x)
 
  309     Vc_INTRINSIC Storage(
const Storage &) = 
default;
 
  310     Vc_INTRINSIC Storage &operator=(
const Storage &) = 
default;
 
  312     Vc_INTRINSIC Vc_PURE VectorType &v() { 
return data; }
 
  313     Vc_INTRINSIC Vc_PURE 
const VectorType &v()
 const { 
return data; }
 
  315     Vc_INTRINSIC_L Vc_PURE_L EntryType m(
size_t i) 
const Vc_INTRINSIC_R Vc_PURE_R;
 
  316     Vc_INTRINSIC_L Vc_PURE_L EntryType &ref(
size_t i) Vc_INTRINSIC_R Vc_PURE_R;
 
  317     Vc_INTRINSIC 
void set(
size_t i, EntryType x) { ref(i) = x; }
 
  324 template <> Vc_INTRINSIC Vc_PURE          
double Storage<         double, 2, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128d_f64[i]; }
 
  325 template <> Vc_INTRINSIC Vc_PURE          
float  Storage<         float , 4, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128_f32[i]; }
 
  326 template <> Vc_INTRINSIC Vc_PURE   
signed int    Storage<  signed int   , 4, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128i_i32[i]; }
 
  327 template <> Vc_INTRINSIC Vc_PURE   
signed short  Storage<  signed short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128i_i16[i]; }
 
  328 template <> Vc_INTRINSIC Vc_PURE   
signed char   Storage<  signed char  ,16, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128i_i8[i]; }
 
  329 template <> Vc_INTRINSIC Vc_PURE 
unsigned int    Storage<unsigned int   , 4, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128i_u32[i]; }
 
  330 template <> Vc_INTRINSIC Vc_PURE 
unsigned short  Storage<unsigned short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128i_u16[i]; }
 
  331 template <> Vc_INTRINSIC Vc_PURE 
unsigned char   Storage<unsigned char  ,16, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m128i_u8[i]; }
 
  333 template <> Vc_INTRINSIC Vc_PURE          
double &Storage<         double, 2, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128d_f64[i]; }
 
  334 template <> Vc_INTRINSIC Vc_PURE          
float  &Storage<         float , 4, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128_f32[i]; }
 
  335 template <> Vc_INTRINSIC Vc_PURE   
signed int    &Storage<  signed int   , 4, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128i_i32[i]; }
 
  336 template <> Vc_INTRINSIC Vc_PURE   
signed short  &Storage<  signed short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128i_i16[i]; }
 
  337 template <> Vc_INTRINSIC Vc_PURE   
signed char   &Storage<  signed char  ,16, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128i_i8[i]; }
 
  338 template <> Vc_INTRINSIC Vc_PURE 
unsigned int    &Storage<unsigned int   , 4, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128i_u32[i]; }
 
  339 template <> Vc_INTRINSIC Vc_PURE 
unsigned short  &Storage<unsigned short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128i_u16[i]; }
 
  340 template <> Vc_INTRINSIC Vc_PURE 
unsigned char   &Storage<unsigned char  ,16, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m128i_u8[i]; }
 
  343 template <> Vc_INTRINSIC Vc_PURE          
double Storage<         double, 4, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256d_f64[i]; }
 
  344 template <> Vc_INTRINSIC Vc_PURE          
float  Storage<         float , 8, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256_f32[i]; }
 
  345 template <> Vc_INTRINSIC Vc_PURE   
signed int    Storage<  signed int   , 8, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256i_i32[i]; }
 
  346 template <> Vc_INTRINSIC Vc_PURE   
signed short  Storage<  signed short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256i_i16[i]; }
 
  347 template <> Vc_INTRINSIC Vc_PURE   
signed char   Storage<  signed char  ,32, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256i_i8[i]; }
 
  348 template <> Vc_INTRINSIC Vc_PURE 
unsigned int    Storage<unsigned int   , 8, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256i_u32[i]; }
 
  349 template <> Vc_INTRINSIC Vc_PURE 
unsigned short  Storage<unsigned short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256i_u16[i]; }
 
  350 template <> Vc_INTRINSIC Vc_PURE 
unsigned char   Storage<unsigned char  ,32, AliasStrategy::UnionMembers>::m(
size_t i)
 const { 
return data.m256i_u8[i]; }
 
  352 template <> Vc_INTRINSIC Vc_PURE          
double &Storage<         double, 4, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256d_f64[i]; }
 
  353 template <> Vc_INTRINSIC Vc_PURE          
float  &Storage<         float , 8, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256_f32[i]; }
 
  354 template <> Vc_INTRINSIC Vc_PURE   
signed int    &Storage<  signed int   , 8, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256i_i32[i]; }
 
  355 template <> Vc_INTRINSIC Vc_PURE   
signed short  &Storage<  signed short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256i_i16[i]; }
 
  356 template <> Vc_INTRINSIC Vc_PURE   
signed char   &Storage<  signed char  ,32, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256i_i8[i]; }
 
  357 template <> Vc_INTRINSIC Vc_PURE 
unsigned int    &Storage<unsigned int   , 8, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256i_u32[i]; }
 
  358 template <> Vc_INTRINSIC Vc_PURE 
unsigned short  &Storage<unsigned short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256i_u16[i]; }
 
  359 template <> Vc_INTRINSIC Vc_PURE 
unsigned char   &Storage<unsigned char  ,32, AliasStrategy::UnionMembers>::ref(
size_t i) { 
return data.m256i_u8[i]; }
 
  363 template <
typename VectorType, 
typename EntryType>
 
  364 using VectorMemoryUnion = Storage<EntryType, 
sizeof(VectorType) / 
sizeof(EntryType)>;
 
  369 #endif // VC_COMMON_STORAGE_H_