29 #ifndef VC_COMMON_SIMDARRAYHELPER_H_ 
   30 #define VC_COMMON_SIMDARRAYHELPER_H_ 
   34 namespace Vc_VERSIONED_NAMESPACE
 
   45 #define Vc_DEFINE_OPERATION(name_)                                                       \ 
   46     struct name_ : public tag {                                                          \ 
   47         template <typename V, typename... Args>                                          \ 
   48         Vc_INTRINSIC void operator()(V &v, Args &&... args)                              \ 
   50             v.name_(std::forward<Args>(args)...);                                        \ 
   53 Vc_DEFINE_OPERATION(gather);
 
   54 Vc_DEFINE_OPERATION(scatter);
 
   55 Vc_DEFINE_OPERATION(load);
 
   56 Vc_DEFINE_OPERATION(store);
 
   57 Vc_DEFINE_OPERATION(setZero);
 
   58 Vc_DEFINE_OPERATION(setZeroInverted);
 
   59 Vc_DEFINE_OPERATION(
assign);
 
   60 #undef Vc_DEFINE_OPERATION 
   61 #define Vc_DEFINE_OPERATION(name_, code_)                                                \ 
   62     struct name_ : public tag {                                                          \ 
   63         template <typename V> Vc_INTRINSIC void operator()(V &v) { code_; }              \ 
   65 Vc_DEFINE_OPERATION(increment, ++(v));
 
   66 Vc_DEFINE_OPERATION(decrement, --(v));
 
   67 Vc_DEFINE_OPERATION(random, v = V::Random());
 
   68 #undef Vc_DEFINE_OPERATION 
   69 #define Vc_DEFINE_OPERATION_FORWARD(name_)                                               \ 
   70     struct Forward_##name_ : public tag                                                  \ 
   72         template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \ 
   73         Vc_INTRINSIC void operator()(decltype(name_(std::declval<Args>()...)) &v,        \ 
   76             v = name_(std::forward<Args>(args)...);                                      \ 
   78         template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \ 
   79         Vc_INTRINSIC void operator()(std::nullptr_t, Args && ... args)                   \ 
   81             name_(std::forward<Args>(args)...);                                          \ 
   84 Vc_DEFINE_OPERATION_FORWARD(
abs);
 
   85 Vc_DEFINE_OPERATION_FORWARD(
asin);
 
   86 Vc_DEFINE_OPERATION_FORWARD(
atan);
 
   87 Vc_DEFINE_OPERATION_FORWARD(
atan2);
 
   88 Vc_DEFINE_OPERATION_FORWARD(
cos);
 
   89 Vc_DEFINE_OPERATION_FORWARD(
ceil);
 
   90 Vc_DEFINE_OPERATION_FORWARD(
copysign);
 
   91 Vc_DEFINE_OPERATION_FORWARD(
exp);
 
   92 Vc_DEFINE_OPERATION_FORWARD(
exponent);
 
   93 Vc_DEFINE_OPERATION_FORWARD(
fma);
 
   94 Vc_DEFINE_OPERATION_FORWARD(
floor);
 
   95 Vc_DEFINE_OPERATION_FORWARD(
frexp);
 
   96 Vc_DEFINE_OPERATION_FORWARD(
isfinite);
 
   97 Vc_DEFINE_OPERATION_FORWARD(
isinf);
 
   98 Vc_DEFINE_OPERATION_FORWARD(
isnan);
 
  100 Vc_DEFINE_OPERATION_FORWARD(
ldexp);
 
  101 Vc_DEFINE_OPERATION_FORWARD(
log);
 
  102 Vc_DEFINE_OPERATION_FORWARD(
log10);
 
  103 Vc_DEFINE_OPERATION_FORWARD(
log2);
 
  105 Vc_DEFINE_OPERATION_FORWARD(
round);
 
  106 Vc_DEFINE_OPERATION_FORWARD(
rsqrt);
 
  107 Vc_DEFINE_OPERATION_FORWARD(
sin);
 
  108 Vc_DEFINE_OPERATION_FORWARD(
sincos);
 
  109 Vc_DEFINE_OPERATION_FORWARD(
sqrt);
 
  110 Vc_DEFINE_OPERATION_FORWARD(
trunc);
 
  111 Vc_DEFINE_OPERATION_FORWARD(
min);
 
  112 Vc_DEFINE_OPERATION_FORWARD(
max);
 
  113 #undef Vc_DEFINE_OPERATION_FORWARD 
  114 template<
typename T> 
using is_operation = std::is_base_of<tag, T>;
 
  122 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_> 
struct Segment
 
  124     static_assert(Index_ < Pieces_, 
"You found a bug in Vc. Please report.");
 
  127     using type_decayed = 
typename std::decay<type>::type;
 
  128     static constexpr std::size_t Pieces = Pieces_;
 
  129     static constexpr std::size_t Index = Index_;
 
  130     using simd_array_type = SimdArray<
 
  131         typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
 
  132                                   typename type_decayed::EntryType, 
float>::type,
 
  133         type_decayed::size() / Pieces>;
 
  137     static constexpr std::size_t EntryOffset = Index * type_decayed::Size / Pieces;
 
  139     decltype(std::declval<type>()[0]) operator[](
size_t i) { 
return data[i + EntryOffset]; }
 
  140     decltype(std::declval<type>()[0]) operator[](
size_t i)
 const { 
return data[i + EntryOffset]; }
 
  142     simd_array_type asSimdArray()
 const 
  144         return simd_cast<simd_array_type, Index>(data);
 
  149 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
 
  150 struct Segment<T_ *, Pieces_, Index_> {
 
  151     static_assert(Index_ < Pieces_, 
"You found a bug in Vc. Please report.");
 
  154     using type_decayed = 
typename std::decay<T_>::type;
 
  155     static constexpr 
size_t Pieces = Pieces_;
 
  156     static constexpr 
size_t Index = Index_;
 
  157     using simd_array_type = SimdArray<
 
  158         typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
 
  159                                   typename type_decayed::VectorEntryType, 
float>::type,
 
  160         type_decayed::size() / Pieces> *;
 
  164     static constexpr std::size_t EntryOffset = Index * type_decayed::size() / Pieces;
 
  166     simd_array_type asSimdArray()
 const 
  168         return reinterpret_cast< 
  172                    typename std::remove_pointer<simd_array_type>::type
 
  174                    MayAlias<typename std::remove_pointer<simd_array_type>::type
> 
  193 template <
typename T, std::
size_t Offset> 
struct AddOffset
 
  195     constexpr AddOffset() = 
default;
 
  207 template <std::
size_t secondOffset> 
class Split
 
  209     static Vc_INTRINSIC AddOffset<VectorSpecialInitializerIndexesFromZero, secondOffset>
 
  210         hiImpl(VectorSpecialInitializerIndexesFromZero)
 
  214     template <std::
size_t Offset>
 
  216         AddOffset<VectorSpecialInitializerIndexesFromZero, Offset + secondOffset>
 
  217             hiImpl(AddOffset<VectorSpecialInitializerIndexesFromZero, Offset>)
 
  223     template <
typename U, std::size_t N, 
typename V, std::size_t M,
 
  224               typename = enable_if<N != M>>
 
  225     static Vc_INTRINSIC 
auto loImpl(
const SimdArray<U, N, V, M> &x)
 
  226         -> decltype(internal_data0(x))
 
  228         return internal_data0(x);
 
  230     template <
typename U, std::size_t N, 
typename V, std::size_t M,
 
  231               typename = enable_if<N != M>>
 
  232     static Vc_INTRINSIC 
auto hiImpl(
const SimdArray<U, N, V, M> &x)
 
  233         -> decltype(internal_data1(x))
 
  235         return internal_data1(x);
 
  237     template <
typename U, std::size_t N, 
typename V, std::size_t M,
 
  238               typename = enable_if<N != M>>
 
  239     static Vc_INTRINSIC 
auto loImpl(SimdArray<U, N, V, M> *x)
 
  240         -> decltype(&internal_data0(*x))
 
  242         return &internal_data0(*x);
 
  244     template <
typename U, std::size_t N, 
typename V, std::size_t M,
 
  245               typename = enable_if<N != M>>
 
  246     static Vc_INTRINSIC 
auto hiImpl(SimdArray<U, N, V, M> *x)
 
  247         -> decltype(&internal_data1(*x))
 
  249         return &internal_data1(*x);
 
  253     template <
typename U, std::
size_t N, 
typename V>
 
  254     static Vc_INTRINSIC Segment<V, 2, 0> loImpl(
const SimdArray<U, N, V, N> &x)
 
  256         return {internal_data(x)};
 
  258     template <
typename U, std::
size_t N, 
typename V>
 
  259     static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(
const SimdArray<U, N, V, N> &x)
 
  261         return {internal_data(x)};
 
  263     template <
typename U, std::
size_t N, 
typename V>
 
  264     static Vc_INTRINSIC Segment<V *, 2, 0> loImpl(SimdArray<U, N, V, N> *x)
 
  266         return {&internal_data(*x)};
 
  268     template <
typename U, std::
size_t N, 
typename V>
 
  269     static Vc_INTRINSIC Segment<V *, 2, 1> hiImpl(SimdArray<U, N, V, N> *x)
 
  271         return {&internal_data(*x)};
 
  275     template <
typename U, std::
size_t N, 
typename V, std::
size_t M>
 
  276     static Vc_INTRINSIC 
auto loImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data0(x))
 
  278         return internal_data0(x);
 
  280     template <
typename U, std::
size_t N, 
typename V, std::
size_t M>
 
  281     static Vc_INTRINSIC 
auto hiImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data1(x))
 
  283         return internal_data1(x);
 
  286     template <
typename U, std::
size_t N, 
typename V>
 
  287     static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 0> loImpl(
 
  288         const SimdMaskArray<U, N, V, N> &x)
 
  290         return {internal_data(x)};
 
  292     template <
typename U, std::
size_t N, 
typename V>
 
  293     static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 1> hiImpl(
 
  294         const SimdMaskArray<U, N, V, N> &x)
 
  296         return {internal_data(x)};
 
  300     template <
typename T>
 
  301     static constexpr 
bool is_vector_or_mask(){
 
  302         return (Traits::is_simd_vector<T>::value && !Traits::isSimdArray<T>::value) ||
 
  303                (Traits::is_simd_mask<T>::value && !Traits::isSimdMaskArray<T>::value);
 
  305     template <
typename V>
 
  306     static Vc_INTRINSIC Segment<V, 2, 0> loImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
 
  308         return {std::forward<V>(x)};
 
  310     template <
typename V>
 
  311     static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
 
  313         return {std::forward<V>(x)};
 
  317     template <
typename V, std::
size_t Pieces, std::
size_t Index>
 
  318     static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index> loImpl(
 
  319         const Segment<V, Pieces, Index> &x)
 
  323     template <
typename V, std::
size_t Pieces, std::
size_t Index>
 
  324     static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index + 1> hiImpl(
 
  325         const Segment<V, Pieces, Index> &x)
 
  334     template <
typename T, 
typename = decltype(loImpl(std::declval<T>()))>
 
  335     static std::true_type have_lo_impl(
int);
 
  336     template <
typename T> 
static std::false_type have_lo_impl(
float);
 
  337     template <
typename T> 
static constexpr 
bool have_lo_impl()
 
  339         return decltype(have_lo_impl<T>(1))::value;
 
  342     template <
typename T, 
typename = decltype(hiImpl(std::declval<T>()))>
 
  343     static std::true_type have_hi_impl(
int);
 
  344     template <
typename T> 
static std::false_type have_hi_impl(
float);
 
  345     template <
typename T> 
static constexpr 
bool have_hi_impl()
 
  347         return decltype(have_hi_impl<T>(1))::value;
 
  359     template <
typename U>
 
  360     static Vc_INTRINSIC 
const U *lo(Operations::gather, 
const U *ptr)
 
  364     template <
typename U>
 
  365     static Vc_INTRINSIC 
const U *hi(Operations::gather, 
const U *ptr)
 
  367         return ptr + secondOffset;
 
  369     template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
 
  370     static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>()))
 
  371         lo(Operations::gather, U &&x)
 
  373         return loImpl(std::forward<U>(x));
 
  375     template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
 
  376     static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>()))
 
  377         hi(Operations::gather, U &&x)
 
  379         return hiImpl(std::forward<U>(x));
 
  381     template <
typename U>
 
  382     static Vc_INTRINSIC 
const U *lo(Operations::scatter, 
const U *ptr)
 
  386     template <
typename U>
 
  387     static Vc_INTRINSIC 
const U *hi(Operations::scatter, 
const U *ptr)
 
  389         return ptr + secondOffset;
 
  404     template <
typename U>
 
  405     static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>())) lo(U &&x)
 
  407         return loImpl(std::forward<U>(x));
 
  409     template <
typename U>
 
  410     static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>())) hi(U &&x)
 
  412         return hiImpl(std::forward<U>(x));
 
  415     template <
typename U>
 
  416     static Vc_ALWAYS_INLINE enable_if<!have_lo_impl<U>(), U> lo(U &&x)
 
  418         return std::forward<U>(x);
 
  420     template <
typename U>
 
  421     static Vc_ALWAYS_INLINE enable_if<!have_hi_impl<U>(), U> hi(U &&x)
 
  423         return std::forward<U>(x);
 
  429 template <
typename Op, 
typename U, std::
size_t M, 
typename V>
 
  430 static Vc_INTRINSIC 
const V &actual_value(Op, 
const SimdArray<U, M, V, M> &x)
 
  432   return internal_data(x);
 
  434 template <
typename Op, 
typename U, std::
size_t M, 
typename V>
 
  435 static Vc_INTRINSIC V *actual_value(Op, SimdArray<U, M, V, M> *x)
 
  437   return &internal_data(*x);
 
  439 template <
typename Op, 
typename T, 
size_t Pieces, 
size_t Index>
 
  440 static Vc_INTRINSIC 
typename Segment<T, Pieces, Index>::simd_array_type actual_value(
 
  441     Op, Segment<T, Pieces, Index> &&seg)
 
  443     return seg.asSimdArray();
 
  446 template <
typename Op, 
typename U, std::
size_t M, 
typename V>
 
  447 static Vc_INTRINSIC 
const typename V::Mask &actual_value(Op, 
const SimdMaskArray<U, M, V, M> &x)
 
  449   return internal_data(x);
 
  451 template <
typename Op, 
typename U, std::
size_t M, 
typename V>
 
  452 static Vc_INTRINSIC 
typename V::Mask *actual_value(Op, SimdMaskArray<U, M, V, M> *x)
 
  454   return &internal_data(*x);
 
  476 template <
typename Op, 
typename Arg>
 
  477 decltype(actual_value(std::declval<Op &>(), std::declval<Arg>())) conditionalUnpack(
 
  478     std::true_type, Op op, Arg &&arg)
 
  480     return actual_value(op, std::forward<Arg>(arg));
 
  483 template <
typename Op, 
typename Arg> Arg conditionalUnpack(std::false_type, Op, Arg &&arg)
 
  485     return std::forward<Arg>(arg);
 
  489 template <
size_t A, 
size_t B>
 
  490 struct selectorType : 
public std::integral_constant<bool, !((A & (1 << B)) != 0)> {
 
  494 template <size_t I, typename Op, typename R, typename... Args, size_t... Indexes>
 
  495 Vc_INTRINSIC decltype(std::declval<Op &>()(std::declval<R &>(),
 
  496                                            conditionalUnpack(selectorType<I, Indexes>(),
 
  497                                                              std::declval<Op &>(),
 
  498                                                              std::declval<Args>())...))
 
  499 unpackArgumentsAutoImpl(int, index_sequence<Indexes...>, Op op, R &&r, Args &&... args)
 
  501     op(std::forward<R>(r),
 
  502        conditionalUnpack(selectorType<I, Indexes>(), op, std::forward<Args>(args))...);
 
  506 template <size_t I, typename Op, typename R, typename... Args, size_t... Indexes>
 
  507 Vc_INTRINSIC enable_if<(I <= (1 << sizeof...(Args))), void> unpackArgumentsAutoImpl(
 
  508     float, index_sequence<Indexes...> is, Op op, R &&r, Args &&... args)
 
  515         I < (1 << sizeof...(Args)) - (std::is_same<R, std::nullptr_t>::value ? 1 : 0),
 
  516         "Vc or compiler bug. Please report. Failed to find a combination of "
 
  517         "actual_value(arg) transformations that allows calling Op.");
 
  518     unpackArgumentsAutoImpl<I + 1, Op, R, Args...>(int(), is, op, std::forward<R>(r),
 
  519                                                    std::forward<Args>(args)...);
 
  523 template <size_t, typename... Ts> struct IccWorkaround {
 
  526 template <typename... Ts> struct IccWorkaround<2, Ts...> {
 
  527     using type = typename std::remove_pointer<typename std::decay<
 
  528         typename std::tuple_element<1, std::tuple<Ts...>>::type>::type>::type;
 
  533 template <typename Op, typename R, typename... Args>
 
  534 Vc_INTRINSIC void unpackArgumentsAuto(Op op, R &&r, Args &&... args)
 
  540     const int recursionStart =
 
  542             typename IccWorkaround<sizeof...(Args), Args...>::type>::value &&
 
  543                 (std::is_same<Op, Common::Operations::Forward_frexp>::value ||
 
  544                  std::is_same<Op, Common::Operations::Forward_ldexp>::value)
 
  548     const int recursionStart = 0;
 
  550     unpackArgumentsAutoImpl<recursionStart>(
 
  551         int(), make_index_sequence<sizeof...(Args)>(), op, std::forward<R>(r),
 
  552         std::forward<Args>(args)...);
 
SimdArray< T, N, V, M > ceil(const SimdArray< T, N, V, M > &x)
Applies the std:: ceil function component-wise and concurrently. 
Vc::Vector< T > frexp(const Vc::Vector< T > &x, Vc::SimdArray< int, size()> *e)
Convert floating-point number to fractional and integral components. 
Vc::Vector< T > log2(const Vc::Vector< T > &v)
Vc::Vector< T > exp(const Vc::Vector< T > &v)
SimdArray< T, N, V, M > floor(const SimdArray< T, N, V, M > &x)
Applies the std:: floor function component-wise and concurrently. 
Vc::Vector< T > sin(const Vc::Vector< T > &v)
Vc::Vector< T > cos(const Vc::Vector< T > &v)
Vc::Vector< T > min(const Vc::Vector< T > &x, const Vc::Vector< T > &y)
Vc::Vector< T > reciprocal(const Vc::Vector< T > &v)
Returns the reciprocal of v. 
Vc::Vector< T > ldexp(Vc::Vector< T > x, Vc::SimdArray< int, size()> e)
Multiply floating-point number by integral power of 2. 
Vc::Vector< T > abs(const Vc::Vector< T > &v)
Returns the absolute value of v. 
Vc::Vector< T > max(const Vc::Vector< T > &x, const Vc::Vector< T > &y)
Vc::Vector< T > log(const Vc::Vector< T > &v)
Vc::Vector< T > fma(Vc::Vector< T > a, Vc::Vector< T > b, Vc::Vector< T > c)
Multiplies a with b and then adds c, without rounding between the multiplication and the addition...
enable_if< std::is_same< To, Traits::decay< From > >::value, To > simd_cast(From &&x)
Casts the argument x from type From to type To. 
Vc::Vector< T > round(const Vc::Vector< T > &v)
Returns the closest integer to v; 0.5 is rounded to even. 
Vc::Vector< T > rsqrt(const Vc::Vector< T > &v)
Returns the reciprocal square root of v. 
SimdMaskArray< T, N, V, M > isnegative(const SimdArray< T, N, V, M > &x)
Applies the std:: isnegative function component-wise and concurrently. 
Vc::Vector< T > log10(const Vc::Vector< T > &v)
SimdArray< T, N, V, M > trunc(const SimdArray< T, N, V, M > &x)
Applies the std:: trunc function component-wise and concurrently. 
SimdArray< T, N, V, M > exponent(const SimdArray< T, N, V, M > &x)
Applies the std:: exponent function component-wise and concurrently. 
Vc::Vector< T > atan2(const Vc::Vector< T > &y, const Vc::Vector< T > &x)
Calculates the angle given the lengths of the opposite and adjacent legs in a right triangle...
SimdArray< T, N, V, M > copysign(const SimdArray< T, N, V, M > &x, const SimdArray< T, N, V, M > &y)
Applies the std:: copysign function component-wise and concurrently. 
Vc::Vector< T > atan(const Vc::Vector< T > &v)
Vc::Vector< T > asin(const Vc::Vector< T > &v)
void assign(Adapter< S, T, N > &a, size_t i, const S &x)
Assigns one scalar object x to a SIMD slot at offset i in the simdized object a. 
Vc::Mask< T > isfinite(const Vc::Vector< T > &x)
Vc::Mask< T > isnan(const Vc::Vector< T > &x)
#define Vc_GCC
This macro is defined to a number identifying the GCC version if the current translation unit is comp...
void sincos(const SimdArray< T, N > &x, SimdArray< T, N > *sin, SimdArray< T, N > *cos)
Determines sine and cosine concurrently and component-wise on x. 
Vc::Vector< T > sqrt(const Vc::Vector< T > &v)
Returns the square root of v. 
SimdMaskArray< T, N, V, M > isinf(const SimdArray< T, N, V, M > &x)
Applies the std:: isinf function component-wise and concurrently.