29 #ifndef VC_COMMON_SIMDARRAY_H_ 
   30 #define VC_COMMON_SIMDARRAY_H_ 
   34 #if defined Vc_DEBUG_SIMD_CAST || defined Vc_DEBUG_SORTED 
   40 #include "writemaskedvector.h" 
   41 #include "simdarrayhelper.h" 
   42 #include "simdmaskarray.h" 
   44 #include "interleave.h" 
   45 #include "indexsequence.h" 
   46 #include "transpose.h" 
   49 namespace Vc_VERSIONED_NAMESPACE
 
   54 template <
typename T> T Vc_INTRINSIC Vc_PURE product_helper_(
const T &l, 
const T &r) { 
return l * r; }
 
   55 template <
typename T> T Vc_INTRINSIC Vc_PURE sum_helper_(
const T &l, 
const T &r) { 
return l + r; }
 
   59 template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
   60 inline SimdArray<T, N, V, M> 
min(
const SimdArray<T, N, V, M> &x,
 
   61                                  const SimdArray<T, N, V, M> &y);
 
   62 template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
   63 inline SimdArray<T, N, V, M> 
max(
const SimdArray<T, N, V, M> &x,
 
   64                                  const SimdArray<T, N, V, M> &y);
 
   71 #define Vc_CURRENT_CLASS_NAME SimdArray 
   81 template <
typename T, std::
size_t N, 
typename VectorType_>
 
   84     ((Common::nextPowerOfTwo(N) * (sizeof(VectorType_) / VectorType_::size()) - 1) & 127) +
 
   86     1) SimdArray<T, N, VectorType_, N>
 
   88     static_assert(std::is_same<T, double>::value || std::is_same<T, float>::value ||
 
   89                       std::is_same<T, int32_t>::value ||
 
   90                       std::is_same<T, uint32_t>::value ||
 
   91                       std::is_same<T, int16_t>::value ||
 
   92                       std::is_same<T, uint16_t>::value,
 
   93                   "SimdArray<T, N> may only be used with T = { double, float, int32_t, uint32_t, " 
   94                   "int16_t, uint16_t }");
 
   97     using VectorType = VectorType_;
 
   98     using vector_type = VectorType;
 
   99     using storage_type = vector_type;
 
  100     using vectorentry_type = 
typename vector_type::VectorEntryType;
 
  101     using value_type = T;
 
  102     using mask_type = SimdMaskArray<T, N, vector_type>;
 
  103     using index_type = SimdArray<int, N>;
 
  104     static constexpr std::size_t size() { 
return N; }
 
  105     using Mask = mask_type;
 
  106     using MaskType = Mask;
 
  107     using MaskArgument = 
const MaskType &;
 
  108     using VectorEntryType = vectorentry_type;
 
  109     using EntryType = value_type;
 
  110     using IndexType = index_type;
 
  111     using AsArg = 
const SimdArray &;
 
  112     static constexpr std::size_t Size = size();
 
  116     Vc_INTRINSIC SimdArray() = 
default;
 
  119     Vc_INTRINSIC SimdArray(
const SimdArray &) = 
default;
 
  120     Vc_INTRINSIC SimdArray(SimdArray &&) = 
default;
 
  121     Vc_INTRINSIC SimdArray &operator=(
const SimdArray &) = 
default;
 
  124     Vc_INTRINSIC SimdArray(
const value_type &a) : data(a) {}
 
  125     Vc_INTRINSIC SimdArray(value_type &a) : data(a) {}
 
  126     Vc_INTRINSIC SimdArray(value_type &&a) : data(a) {}
 
  129         typename = enable_if<std::is_same<U, int>::value && !std::is_same<int, value_type>::value>>
 
  130     Vc_INTRINSIC SimdArray(U a)
 
  131         : SimdArray(static_cast<value_type>(a))
 
  136     template <
typename U, 
typename V>
 
  137     Vc_INTRINSIC SimdArray(
const SimdArray<U, N, V> &x, enable_if<N == V::size()> = nullarg)
 
  138         : data(
simd_cast<vector_type>(internal_data(x)))
 
  141     template <
typename U, 
typename V>
 
  142     Vc_INTRINSIC SimdArray(
const SimdArray<U, N, V> &x,
 
  143                             enable_if<(N > V::size() && N <= 2 * V::size())> = nullarg)
 
  144         : data(
simd_cast<vector_type>(internal_data(internal_data0(x)), internal_data(internal_data1(x))))
 
  147     template <
typename U, 
typename V>
 
  148     Vc_INTRINSIC SimdArray(
const SimdArray<U, N, V> &x,
 
  149                             enable_if<(N > 2 * V::size() && N <= 4 * V::size())> = nullarg)
 
  150         : data(
simd_cast<vector_type>(internal_data(internal_data0(internal_data0(x))),
 
  151                                       internal_data(internal_data1(internal_data0(x))),
 
  152                                       internal_data(internal_data0(internal_data1(x))),
 
  153                                       internal_data(internal_data1(internal_data1(x)))))
 
  157     template <
typename V, std::
size_t Pieces, std::
size_t Index>
 
  158     Vc_INTRINSIC SimdArray(Common::Segment<V, Pieces, Index> &&x)
 
  159         : data(
simd_cast<vector_type, Index>(x.data))
 
  163     Vc_INTRINSIC SimdArray(
const std::initializer_list<value_type> &init)
 
  166 #if defined Vc_CXX14 && 0  // doesn't compile yet 
  167         static_assert(init.size() == size(), 
"The initializer_list argument to " 
  168                                              "SimdArray<T, N> must contain exactly N " 
  171         Vc_ASSERT(init.size() == size());
 
  178         typename = enable_if<Traits::is_simd_vector<V>::value && !Traits::isSimdArray<V>::value>>
 
  179     explicit Vc_INTRINSIC SimdArray(
const V &x)
 
  186     template <
typename V,
 
  187               typename = enable_if<
 
  189                   std::is_convertible<T, typename V::EntryType>::value && V::size() == N>>
 
  190     Vc_INTRINSIC 
operator V()
 const 
  195 #include "gatherinterface.h" 
  198     template <
typename... Args,
 
  199               typename = enable_if<!Traits::is_cast_arguments<Args...>::value &&
 
  200                                    !Traits::is_gather_signature<Args...>::value &&
 
  201                                    !Traits::is_initializer_list<Args...>::value>>
 
  202     explicit Vc_INTRINSIC SimdArray(Args &&... args)
 
  203         : data(
std::forward<Args>(args)...)
 
  207     template <std::
size_t Offset>
 
  208     explicit Vc_INTRINSIC SimdArray(
 
  209         Common::AddOffset<VectorSpecialInitializerIndexesFromZero, Offset>)
 
  212         data += value_type(Offset);
 
  215     Vc_INTRINSIC 
void setZero() { data.setZero(); }
 
  216     Vc_INTRINSIC 
void setZero(mask_type k) { data.setZero(internal_data(k)); }
 
  217     Vc_INTRINSIC 
void setZeroInverted() { data.setZeroInverted(); }
 
  218     Vc_INTRINSIC 
void setZeroInverted(mask_type k) { data.setZeroInverted(internal_data(k)); }
 
  220     Vc_INTRINSIC 
void setQnan() { data.setQnan(); }
 
  221     Vc_INTRINSIC 
void setQnan(mask_type m) { data.setQnan(internal_data(m)); }
 
  224     template <
typename Op, 
typename... Args>
 
  225     static Vc_INTRINSIC SimdArray fromOperation(Op op, Args &&... args)
 
  232     template <
typename Op, 
typename... Args>
 
  233     static Vc_INTRINSIC 
void callOperation(Op op, Args &&... args)
 
  238     static Vc_INTRINSIC SimdArray 
Zero()
 
  242     static Vc_INTRINSIC SimdArray 
One()
 
  250     static Vc_INTRINSIC SimdArray Random()
 
  252         return fromOperation(Common::Operations::random());
 
  255     template <
typename... Args> Vc_INTRINSIC 
void load(Args &&... args)
 
  257         data.load(std::forward<Args>(args)...);
 
  260     template <
typename... Args> Vc_INTRINSIC 
void store(Args &&... args)
 const 
  262         data.store(std::forward<Args>(args)...);
 
  265     Vc_INTRINSIC mask_type operator!()
 const 
  270     Vc_INTRINSIC SimdArray operator-()
 const 
  276     Vc_INTRINSIC SimdArray operator+()
 const { 
return *
this; }
 
  278     Vc_INTRINSIC SimdArray operator~()
 const 
  283     template <
typename U,
 
  284               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  285     Vc_INTRINSIC Vc_CONST SimdArray 
operator<<(U x)
 const 
  289     template <
typename U,
 
  290               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  291     Vc_INTRINSIC SimdArray &operator<<=(U x)
 
  296     template <
typename U,
 
  297               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  298     Vc_INTRINSIC Vc_CONST SimdArray operator>>(U x)
 const 
  302     template <
typename U,
 
  303               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  304     Vc_INTRINSIC SimdArray &operator>>=(U x)
 
  310 #define Vc_BINARY_OPERATOR_(op)                                                          \ 
  311     Vc_INTRINSIC Vc_CONST SimdArray operator op(const SimdArray &rhs) const              \ 
  313         return {data op rhs.data};                                                       \ 
  315     Vc_INTRINSIC SimdArray &operator op##=(const SimdArray &rhs)                         \ 
  317         data op## = rhs.data;                                                            \ 
  320     Vc_ALL_ARITHMETICS(Vc_BINARY_OPERATOR_)
 
  321     Vc_ALL_BINARY(Vc_BINARY_OPERATOR_)
 
  322     Vc_ALL_SHIFTS(Vc_BINARY_OPERATOR_)
 
  323 #undef Vc_BINARY_OPERATOR_ 
  325 #define Vc_COMPARES(op)                                                                  \ 
  326     Vc_INTRINSIC mask_type operator op(const SimdArray &rhs) const                       \ 
  328         return {data op rhs.data};                                                       \ 
  330     Vc_ALL_COMPARES(Vc_COMPARES)
 
  334     Vc_INTRINSIC Vc_DEPRECATED(
"use isnegative(x) instead") MaskType isNegative()
 const 
  336         return {isnegative(data)};
 
  339     Vc_INTRINSIC decltype(std::declval<vector_type &>()[0]) operator[](
std::
size_t i)
 
  343     Vc_INTRINSIC value_type operator[](std::size_t i)
 const { 
return data[i]; }
 
  345     Vc_INTRINSIC Common::WriteMaskedVector<SimdArray, mask_type> operator()(
const mask_type &k)
 
  350     Vc_INTRINSIC 
void assign(
const SimdArray &v, 
const mask_type &k)
 
  352         data.assign(v.data, internal_data(k));
 
  356 #define Vc_REDUCTION_FUNCTION_(name_)                                                    \ 
  357     Vc_INTRINSIC Vc_PURE value_type name_() const { return data.name_(); }               \ 
  358     Vc_INTRINSIC Vc_PURE value_type name_(mask_type mask) const                          \ 
  360         return data.name_(internal_data(mask));                                          \ 
  362     Vc_REDUCTION_FUNCTION_(min)
 
  363     Vc_REDUCTION_FUNCTION_(max)
 
  364     Vc_REDUCTION_FUNCTION_(product)
 
  365     Vc_REDUCTION_FUNCTION_(sum)
 
  366 #undef Vc_REDUCTION_FUNCTION_ 
  367     Vc_INTRINSIC Vc_PURE SimdArray partialSum()
 const { 
return data.partialSum(); }
 
  369     Vc_INTRINSIC 
void fusedMultiplyAdd(
const SimdArray &factor, 
const SimdArray &summand)
 
  371         data.fusedMultiplyAdd(internal_data(factor), internal_data(summand));
 
  374     template <
typename F> Vc_INTRINSIC SimdArray apply(F &&f)
 const 
  376         return {data.apply(std::forward<F>(f))};
 
  378     template <
typename F> Vc_INTRINSIC SimdArray apply(F &&f, 
const mask_type &k)
 const 
  380         return {data.apply(std::forward<F>(f), k)};
 
  383     Vc_INTRINSIC SimdArray 
shifted(
int amount)
 const 
  385         return {data.shifted(amount)};
 
  388     template <std::
size_t NN>
 
  389     Vc_INTRINSIC SimdArray 
shifted(
int amount, 
const SimdArray<value_type, NN> &shiftIn)
 
  392         return {data.shifted(amount, simd_cast<VectorType>(shiftIn))};
 
  395     Vc_INTRINSIC SimdArray rotated(
int amount)
 const 
  397         return {data.rotated(amount)};
 
  401     Vc_INTRINSIC Vc_DEPRECATED(
"use exponent(x) instead") SimdArray exponent()
 const 
  403         return {exponent(data)};
 
  406     Vc_INTRINSIC SimdArray interleaveLow(SimdArray x)
 const 
  408         return {data.interleaveLow(x.data)};
 
  410     Vc_INTRINSIC SimdArray interleaveHigh(SimdArray x)
 const 
  412         return {data.interleaveHigh(x.data)};
 
  415     Vc_INTRINSIC SimdArray reversed()
 const 
  417         return {data.reversed()};
 
  420     Vc_INTRINSIC SimdArray sorted()
 const 
  422         return {data.sorted()};
 
  425     template <
typename G> 
static Vc_INTRINSIC SimdArray generate(
const G &gen)
 
  427         return {VectorType::generate(gen)};
 
  430     Vc_INTRINSIC Vc_DEPRECATED(
"use copysign(x, y) instead") SimdArray
 
  431         copySign(const SimdArray &reference)
 const 
  436     friend VectorType &internal_data<>(SimdArray &x);
 
  437     friend const VectorType &internal_data<>(
const SimdArray &x);
 
  440     Vc_INTRINSIC SimdArray(VectorType &&x) : data(
std::move(x)) {}
 
  444 template <
typename T, std::
size_t N, 
typename VectorType> constexpr std::size_t SimdArray<T, N, VectorType, N>::Size;
 
  445 template <
typename T, std::
size_t N, 
typename VectorType>
 
  447 template <
typename T, std::
size_t N, 
typename VectorType>
 
  448 Vc_INTRINSIC VectorType &internal_data(SimdArray<T, N, VectorType, N> &x)
 
  452 template <
typename T, std::
size_t N, 
typename VectorType>
 
  453 Vc_INTRINSIC 
const VectorType &internal_data(
const SimdArray<T, N, VectorType, N> &x)
 
  459 template <
typename T, std::
size_t N, 
typename VectorType>
 
  460 template <
typename MT, 
typename IT>
 
  461 inline void SimdArray<T, N, VectorType, N>::gatherImplementation(
const MT *mem,
 
  464     data.gather(mem, std::forward<IT>(indexes));
 
  466 template <
typename T, std::
size_t N, 
typename VectorType>
 
  467 template <
typename MT, 
typename IT>
 
  468 inline void SimdArray<T, N, VectorType, N>::gatherImplementation(
const MT *mem,
 
  472     data.gather(mem, std::forward<IT>(indexes), mask);
 
  480 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t>
 
  483     ((Common::nextPowerOfTwo(N) * (sizeof(VectorType) / VectorType::size()) - 1) & 127) +
 
  487     static_assert(std::is_same<T,   double>::value ||
 
  488                   std::is_same<T,    float>::value ||
 
  489                   std::is_same<T,  int32_t>::value ||
 
  490                   std::is_same<T, uint32_t>::value ||
 
  491                   std::is_same<T,  int16_t>::value ||
 
  492                   std::is_same<T, uint16_t>::value, 
"SimdArray<T, N> may only be used with T = { double, float, int32_t, uint32_t, int16_t, uint16_t }");
 
  495         std::is_same<
typename VectorType::EntryType,
 
  496                      typename VectorType::VectorEntryType>::value ||
 
  498             (N % VectorType::size() == 0),
 
  499         "SimdArray<(un)signed short, N> on MIC only works correctly for N = k * " 
  500         "MIC::(u)short_v::size(), i.e. k * 16.");
 
  502     using my_traits = SimdArrayTraits<T, N>;
 
  503     static constexpr std::size_t N0 = my_traits::N0;
 
  504     static constexpr std::size_t N1 = my_traits::N1;
 
  505     using Split = Common::Split<N0>;
 
  506     template <
typename U, std::
size_t K> 
using CArray = U[K];
 
  511     static_assert(storage_type0::size() == N0, 
"");
 
  513     using vector_type = VectorType;
 
  514     using vectorentry_type = 
typename storage_type0::vectorentry_type;
 
  515     typedef vectorentry_type alias_type Vc_MAY_ALIAS;
 
  516     using value_type = T;
 
  517     using mask_type = SimdMaskArray<T, N, vector_type>;
 
  519     static constexpr std::size_t size() { 
return N; }
 
  520     using Mask = mask_type;
 
  521     using MaskType = Mask;
 
  522     using MaskArgument = 
const MaskType &;
 
  523     using VectorEntryType = vectorentry_type;
 
  524     using EntryType = value_type;
 
  526     using AsArg = 
const SimdArray &;
 
  527     static constexpr std::size_t Size = size();
 
  528     static constexpr std::size_t MemoryAlignment =
 
  536     SimdArray() = 
default;
 
  539     SimdArray(
const SimdArray &) = 
default;
 
  540     SimdArray(SimdArray &&) = 
default;
 
  541     SimdArray &operator=(
const SimdArray &) = 
default;
 
  544     Vc_INTRINSIC SimdArray(value_type a) : data0(a), data1(a) {}
 
  547         typename = enable_if<std::is_same<U, int>::value && !std::is_same<int, value_type>::value>>
 
  549         : SimdArray(static_cast<value_type>(a))
 
  554     template <
typename U,
 
  556               typename = enable_if<Traits::is_load_store_flag<Flags>::value>>
 
  557     explicit Vc_INTRINSIC SimdArray(
const U *mem, Flags f = Flags())
 
  558         : data0(mem, f), data1(mem + storage_type0::size(), f)
 
  567     template <
typename U, std::size_t Extent, 
typename Flags = 
DefaultLoadTag,
 
  568               typename = enable_if<Traits::is_load_store_flag<Flags>::value>>
 
  569     explicit Vc_INTRINSIC SimdArray(CArray<U, Extent> &mem, Flags f = Flags())
 
  570         : data0(&mem[0], f), data1(&mem[storage_type0::size()], f)
 
  576     template <
typename U, std::size_t Extent, 
typename Flags = 
DefaultLoadTag,
 
  577               typename = enable_if<Traits::is_load_store_flag<Flags>::value>>
 
  578     explicit Vc_INTRINSIC SimdArray(
const CArray<U, Extent> &mem, Flags f = Flags())
 
  579         : data0(&mem[0], f), data1(&mem[storage_type0::size()], f)
 
  584     Vc_INTRINSIC SimdArray(
const std::initializer_list<value_type> &init)
 
  588 #if defined Vc_CXX14 && 0  // doesn't compile yet 
  589         static_assert(init.size() == size(), 
"The initializer_list argument to " 
  590                                              "SimdArray<T, N> must contain exactly N " 
  593         Vc_ASSERT(init.size() == size());
 
  597 #include "gatherinterface.h" 
  600     template <
typename... Args,
 
  601               typename = enable_if<!Traits::is_cast_arguments<Args...>::value &&
 
  602                                    !Traits::is_initializer_list<Args...>::value &&
 
  603                                    !Traits::is_gather_signature<Args...>::value &&
 
  604                                    !Traits::is_load_arguments<Args...>::value>>
 
  605     explicit Vc_INTRINSIC SimdArray(Args &&... args)
 
  606         : data0(Split::lo(args)...)  
 
  608         , data1(Split::hi(std::forward<Args>(args))...)
 
  613     template <
typename V>
 
  614     Vc_INTRINSIC 
explicit SimdArray(
 
  617                    !(std::is_convertible<Traits::entry_type_of<V>, T>::value &&
 
  619         : data0(Split::lo(x)), data1(Split::hi(x))
 
  624     template <
typename V>
 
  625     Vc_INTRINSIC SimdArray(
 
  628                    std::is_convertible<Traits::entry_type_of<V>, T>::value)> = nullarg)
 
  629         : data0(Split::lo(x)), data1(Split::hi(x))
 
  635     template <
typename V,
 
  636               typename = enable_if<
 
  638                   std::is_convertible<T, typename V::EntryType>::value && V::size() == N>>
 
  646     Vc_INTRINSIC 
void setZero()
 
  651     Vc_INTRINSIC 
void setZero(
const mask_type &k)
 
  653         data0.setZero(Split::lo(k));
 
  654         data1.setZero(Split::hi(k));
 
  656     Vc_INTRINSIC 
void setZeroInverted()
 
  658         data0.setZeroInverted();
 
  659         data1.setZeroInverted();
 
  661     Vc_INTRINSIC 
void setZeroInverted(
const mask_type &k)
 
  663         data0.setZeroInverted(Split::lo(k));
 
  664         data1.setZeroInverted(Split::hi(k));
 
  668     Vc_INTRINSIC 
void setQnan() {
 
  672     Vc_INTRINSIC 
void setQnan(
const mask_type &m) {
 
  673         data0.setQnan(Split::lo(m));
 
  674         data1.setQnan(Split::hi(m));
 
  678     template <
typename Op, 
typename... Args>
 
  679     static Vc_INTRINSIC SimdArray fromOperation(Op op, Args &&... args)
 
  682             storage_type0::fromOperation(op, Split::lo(args)...),  
 
  685             storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
 
  690     template <
typename Op, 
typename... Args>
 
  691     static Vc_INTRINSIC 
void callOperation(Op op, Args &&... args)
 
  693         storage_type0::callOperation(op, Split::lo(args)...);
 
  694         storage_type1::callOperation(op, Split::hi(std::forward<Args>(args))...);
 
  698     static Vc_INTRINSIC SimdArray 
Zero()
 
  704     static Vc_INTRINSIC SimdArray 
One()
 
  716     static Vc_INTRINSIC SimdArray Random()
 
  718         return fromOperation(Common::Operations::random());
 
  721     template <
typename U, 
typename... Args> Vc_INTRINSIC 
void load(
const U *mem, Args &&... args)
 
  723         data0.load(mem, Split::lo(args)...);  
 
  725         data1.load(mem + storage_type0::size(), Split::hi(std::forward<Args>(args))...);
 
  728     template <
typename U, 
typename... Args> Vc_INTRINSIC 
void store(U *mem, Args &&... args)
 const 
  730         data0.store(mem, Split::lo(args)...);  
 
  732         data1.store(mem + storage_type0::size(), Split::hi(std::forward<Args>(args))...);
 
  735     Vc_INTRINSIC mask_type operator!()
 const 
  737         return {!data0, !data1};
 
  740     Vc_INTRINSIC SimdArray operator-()
 const 
  742         return {-data0, -data1};
 
  746     Vc_INTRINSIC SimdArray operator+()
 const { 
return *
this; }
 
  748     Vc_INTRINSIC SimdArray operator~()
 const 
  750         return {~data0, ~data1};
 
  754     template <
typename U,
 
  755               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  756     Vc_INTRINSIC Vc_CONST SimdArray 
operator<<(U x)
 const 
  758         return {data0 << x, data1 << x};
 
  760     template <
typename U,
 
  761               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  762     Vc_INTRINSIC SimdArray &operator<<=(U x)
 
  768     template <
typename U,
 
  769               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  770     Vc_INTRINSIC Vc_CONST SimdArray operator>>(U x)
 const 
  772         return {data0 >> x, data1 >> x};
 
  774     template <
typename U,
 
  775               typename = enable_if<std::is_integral<T>::value && std::is_integral<U>::value>>
 
  776     Vc_INTRINSIC SimdArray &operator>>=(U x)
 
  784 #define Vc_BINARY_OPERATOR_(op)                                                          \ 
  785     Vc_INTRINSIC Vc_CONST SimdArray operator op(const SimdArray &rhs) const              \ 
  787         return {data0 op rhs.data0, data1 op rhs.data1};                                 \ 
  789     Vc_INTRINSIC SimdArray &operator op##=(const SimdArray &rhs)                         \ 
  791         data0 op## = rhs.data0;                                                          \ 
  792         data1 op## = rhs.data1;                                                          \ 
  795     Vc_ALL_ARITHMETICS(Vc_BINARY_OPERATOR_)
 
  796     Vc_ALL_BINARY(Vc_BINARY_OPERATOR_)
 
  797     Vc_ALL_SHIFTS(Vc_BINARY_OPERATOR_)
 
  798 #undef Vc_BINARY_OPERATOR_ 
  800 #define Vc_COMPARES(op)                                                                  \ 
  801     Vc_INTRINSIC mask_type operator op(const SimdArray &rhs) const                       \ 
  803         return {data0 op rhs.data0, data1 op rhs.data1};                                 \ 
  805     Vc_ALL_COMPARES(Vc_COMPARES)
 
  809     Vc_INTRINSIC MaskType isNegative()
 const 
  811         return {isnegative(data0), isnegative(data1)};
 
  815     Vc_INTRINSIC value_type operator[](std::size_t i)
 const 
  817         const auto tmp = 
reinterpret_cast<const alias_type *
>(
this);
 
  821     Vc_INTRINSIC alias_type &operator[](std::size_t i)
 
  823         auto tmp = 
reinterpret_cast<alias_type *
>(
this);
 
  827     Vc_INTRINSIC Common::WriteMaskedVector<SimdArray, mask_type> operator()(
const mask_type &k) 
 
  832     Vc_INTRINSIC 
void assign(
const SimdArray &v, 
const mask_type &k) 
 
  834         data0.assign(v.data0, internal_data0(k));
 
  835         data1.assign(v.data1, internal_data1(k));
 
  839 #define Vc_REDUCTION_FUNCTION_(name_, binary_fun_, scalar_fun_)                          \ 
  840     template <typename ForSfinae = void>                                                 \ 
  841     Vc_INTRINSIC enable_if<std::is_same<ForSfinae, void>::value &&                       \ 
  842                                storage_type0::size() == storage_type1::size(),           \ 
  846         return binary_fun_(data0, data1).name_();                                        \ 
  849     template <typename ForSfinae = void>                                                 \ 
  850     Vc_INTRINSIC enable_if<std::is_same<ForSfinae, void>::value &&                       \ 
  851                                storage_type0::size() != storage_type1::size(),           \ 
  855         return scalar_fun_(data0.name_(), data1.name_());                                \ 
  858     Vc_INTRINSIC value_type name_(const mask_type &mask) const                           \ 
  860         if (Vc_IS_UNLIKELY(Split::lo(mask).isEmpty())) {                                 \ 
  861             return data1.name_(Split::hi(mask));                                         \ 
  862         } else if (Vc_IS_UNLIKELY(Split::hi(mask).isEmpty())) {                          \ 
  863             return data0.name_(Split::lo(mask));                                         \ 
  865             return scalar_fun_(data0.name_(Split::lo(mask)),                             \ 
  866                                data1.name_(Split::hi(mask)));                            \ 
  869     Vc_REDUCTION_FUNCTION_(min, 
Vc::min, std::min)
 
  870     Vc_REDUCTION_FUNCTION_(max, 
Vc::max, 
std::max)
 
  871     Vc_REDUCTION_FUNCTION_(product, internal::product_helper_, internal::product_helper_)
 
  872     Vc_REDUCTION_FUNCTION_(sum, internal::sum_helper_, internal::sum_helper_)
 
  873 #undef Vc_REDUCTION_FUNCTION_ 
  874     Vc_INTRINSIC Vc_PURE SimdArray partialSum() const 
 
  876         auto ps0 = data0.partialSum();
 
  878         tmp[0] += ps0[data0.size() - 1];
 
  879         return {std::move(ps0), tmp.partialSum()};
 
  882     void fusedMultiplyAdd(
const SimdArray &factor, 
const SimdArray &summand) 
 
  884         data0.fusedMultiplyAdd(Split::lo(factor), Split::lo(summand));
 
  885         data1.fusedMultiplyAdd(Split::hi(factor), Split::hi(summand));
 
  889     template <
typename F> Vc_INTRINSIC SimdArray apply(F &&f)
 const 
  891         return {data0.apply(f), data1.apply(f)};
 
  893     template <
typename F> Vc_INTRINSIC SimdArray apply(F &&f, 
const mask_type &k)
 const 
  895         return {data0.apply(f, Split::lo(k)), data1.apply(f, Split::hi(k))};
 
  899     inline SimdArray 
shifted(
int amount)
 const 
  901         constexpr 
int SSize = Size;
 
  902         constexpr 
int SSize0 = storage_type0::Size;
 
  903         constexpr 
int SSize1 = storage_type1::Size;
 
  908             if (amount > -SSize0) {
 
  909                 return {data0.shifted(amount), data1.shifted(amount, data0)};
 
  911             if (amount == -SSize0) {
 
  914             if (amount < -SSize0) {
 
  920             if (amount >= SSize) {
 
  922             } 
else if (amount >= SSize0) {
 
  926             } 
else if (amount >= SSize1) {
 
  929                 return {data0.shifted(amount, data1), data1.shifted(amount)};
 
  934     template <std::
size_t NN>
 
  936         !(std::is_same<storage_type0, storage_type1>::value &&  
 
  939         shifted(
int amount, 
const SimdArray<value_type, NN> &shiftIn) 
const 
  941         constexpr 
int SSize = Size;
 
  943             return SimdArray::generate([&](
int i) -> value_type {
 
  946                     return operator[](i);
 
  947                 } 
else if (i >= -SSize) {
 
  948                     return shiftIn[i + SSize];
 
  953         return SimdArray::generate([&](
int i) -> value_type {
 
  956                 return operator[](i);
 
  957             } 
else if (i < 2 * SSize) {
 
  958                 return shiftIn[i - SSize];
 
  964     template <std::
size_t NN>
 
  966         enable_if<(std::is_same<storage_type0, storage_type1>::value &&  
 
  969             shifted(
int amount, 
const SimdArray<value_type, NN> &shiftIn) 
const 
  971         constexpr 
int SSize = Size;
 
  973             if (amount > -static_cast<int>(storage_type0::Size)) {
 
  974                 return {data0.shifted(amount, internal_data1(shiftIn)),
 
  975                         data1.shifted(amount, data0)};
 
  977             if (amount == -static_cast<int>(storage_type0::Size)) {
 
  978                 return {storage_type0(internal_data1(shiftIn)), storage_type1(data0)};
 
  980             if (amount > -SSize) {
 
  982                     internal_data1(shiftIn)
 
  983                         .shifted(amount + static_cast<int>(storage_type0::Size), internal_data0(shiftIn)),
 
  984                     data0.shifted(amount + static_cast<int>(storage_type0::Size), internal_data1(shiftIn))};
 
  986             if (amount == -SSize) {
 
  989             if (amount > -2 * SSize) {
 
  990                 return shiftIn.shifted(amount + SSize);
 
  996         if (amount < static_cast<int>(storage_type0::Size)) {
 
  997             return {data0.shifted(amount, data1),
 
  998                     data1.shifted(amount, internal_data0(shiftIn))};
 
 1000         if (amount == static_cast<int>(storage_type0::Size)) {
 
 1001             return {storage_type0(data1), storage_type1(internal_data0(shiftIn))};
 
 1003         if (amount < SSize) {
 
 1004             return {data1.shifted(amount - static_cast<int>(storage_type0::Size), internal_data0(shiftIn)),
 
 1005                     internal_data0(shiftIn)
 
 1006                         .shifted(amount - static_cast<int>(storage_type0::Size), internal_data1(shiftIn))};
 
 1008         if (amount == SSize) {
 
 1011         if (amount < 2 * SSize) {
 
 1012             return shiftIn.shifted(amount - SSize);
 
 1018     Vc_INTRINSIC SimdArray rotated(
int amount)
 const 
 1020         amount %= int(size());
 
 1023         } 
else if (amount < 0) {
 
 1027         auto &&d0cvtd = 
simd_cast<storage_type1>(data0);
 
 1028         auto &&d1cvtd = 
simd_cast<storage_type0>(data1);
 
 1029         constexpr 
int size0 = storage_type0::size();
 
 1030         constexpr 
int size1 = storage_type1::size();
 
 1032         if (amount == size0 && std::is_same<storage_type0, storage_type1>::value) {
 
 1033             return {std::move(d1cvtd), std::move(d0cvtd)};
 
 1034         } 
else if (amount < size1) {
 
 1035             return {data0.shifted(amount, d1cvtd), data1.shifted(amount, d0cvtd)};
 
 1036         } 
else if (amount == size1) {
 
 1037             return {data0.shifted(amount, d1cvtd), std::move(d0cvtd)};
 
 1038         } 
else if (
int(size()) - amount < size1) {
 
 1039             return {data0.shifted(amount - 
int(size()), d1cvtd.shifted(size1 - size0)),
 
 1040                     data1.shifted(amount - 
int(size()), data0.shifted(size0 - size1))};
 
 1041         } 
else if (
int(size()) - amount == size1) {
 
 1042             return {data0.shifted(-size1, d1cvtd.shifted(size1 - size0)),
 
 1043                     simd_cast<storage_type1>(data0.shifted(size0 - size1))};
 
 1044         } 
else if (amount <= size0) {
 
 1045             return {data0.shifted(size1, d1cvtd).shifted(amount - size1, data0),
 
 1046                     simd_cast<storage_type1>(data0.shifted(amount - size1))};
 
 1048             return {data0.shifted(size1, d1cvtd).shifted(amount - size1, data0),
 
 1049                     simd_cast<storage_type1>(data0.shifted(amount - size1, d1cvtd))};
 
 1055     Vc_INTRINSIC Vc_DEPRECATED(
"use exponent(x) instead") SimdArray exponent()
 const 
 1057         return {exponent(data0), exponent(data1)};
 
 1061     Vc_INTRINSIC SimdArray interleaveLow(
const SimdArray &x)
 const 
 1064         return {data0.interleaveLow(x.data0),
 
 1065                 simd_cast<storage_type1>(data0.interleaveHigh(x.data0))};
 
 1067     Vc_INTRINSIC SimdArray interleaveHigh(
const SimdArray &x)
 const 
 1069         return interleaveHighImpl(
 
 1071             std::integral_constant<bool, storage_type0::Size == storage_type1::Size>());
 
 1075     Vc_INTRINSIC SimdArray interleaveHighImpl(
const SimdArray &x, std::true_type)
 const 
 1077         return {data1.interleaveLow(x.data1), data1.interleaveHigh(x.data1)};
 
 1079     inline SimdArray interleaveHighImpl(
const SimdArray &x, std::false_type)
 const 
 1081         return {data0.interleaveHigh(x.data0)
 
 1082                     .shifted(storage_type1::Size,
 
 1083                              simd_cast<storage_type0>(data1.interleaveLow(x.data1))),
 
 1084                 data1.interleaveHigh(x.data1)};
 
 1088     inline SimdArray reversed() const 
 
 1090         if (std::is_same<storage_type0, storage_type1>::value) {
 
 1091             return {
simd_cast<storage_type0>(data1).reversed(),
 
 1092                     simd_cast<storage_type1>(data0).reversed()};
 
 1094             return {data0.shifted(storage_type1::Size, data1).reversed(),
 
 1095                     simd_cast<storage_type1>(data0.reversed().shifted(
 
 1096                         storage_type0::Size - storage_type1::Size))};
 
 1099     inline SimdArray sorted() const  
 
 1102             std::integral_constant<bool, storage_type0::Size == storage_type1::Size>());
 
 1105     Vc_INTRINSIC SimdArray sortedImpl(std::true_type)
 const 
 1107 #ifdef Vc_DEBUG_SORTED 
 1108         std::cerr << 
"-- " << data0 << data1 << 
'\n';
 
 1110         const auto a = data0.sorted();
 
 1111         const auto b = data1.sorted().reversed();
 
 1112         const auto lo = 
Vc::min(a, b);
 
 1113         const auto hi = 
Vc::max(a, b);
 
 1114         return {lo.sorted(), hi.sorted()};
 
 1117     Vc_INTRINSIC SimdArray sortedImpl(std::false_type)
 const 
 1119         using SortableArray = SimdArray<value_type, Common::nextPowerOfTwo(size())>;
 
 1120         auto sortable = 
simd_cast<SortableArray>(*this);
 
 1121         for (std::size_t i = Size; i < SortableArray::Size; ++i) {
 
 1122             using limits = std::numeric_limits<value_type>;
 
 1123             if (limits::has_infinity) {
 
 1124                 sortable[i] = limits::infinity();
 
 1126                 sortable[i] = std::numeric_limits<value_type>::max();
 
 1129         return simd_cast<SimdArray>(sortable.sorted());
 
 1158     template <
typename G> 
static Vc_INTRINSIC SimdArray generate(
const G &gen) 
 
 1160         auto tmp = storage_type0::generate(gen);  
 
 1165         return {std::move(tmp),
 
 1166                 storage_type1::generate([&](std::size_t i) { 
return gen(i + N0); })};
 
 1169     Vc_INTRINSIC Vc_DEPRECATED(
"use copysign(x, y) instead") SimdArray
 
 1170         copySign(const SimdArray &reference)
 const 
 1177     friend storage_type0 &internal_data0<>(SimdArray &x);
 
 1178     friend storage_type1 &internal_data1<>(SimdArray &x);
 
 1179     friend const storage_type0 &internal_data0<>(
const SimdArray &x);
 
 1180     friend const storage_type1 &internal_data1<>(
const SimdArray &x);
 
 1183     Vc_INTRINSIC SimdArray(storage_type0 &&x, storage_type1 &&y) 
 
 1184         : data0(
std::move(x)), data1(
std::move(y))
 
 1188     storage_type0 data0;
 
 1189     storage_type1 data1;
 
 1191 #undef Vc_CURRENT_CLASS_NAME 
 1192 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t M> constexpr std::size_t SimdArray<T, N, VectorType, M>::Size;
 
 1193 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t M>
 
 1197 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t M>
 
 1198 template <
typename MT, 
typename IT>
 
 1199 inline void SimdArray<T, N, VectorType, M>::gatherImplementation(
const MT *mem,
 
 1202     data0.gather(mem, Split::lo(Common::Operations::gather(),
 
 1205     data1.gather(mem, Split::hi(Common::Operations::gather(), std::forward<IT>(indexes)));
 
 1207 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t M>
 
 1208 template <
typename MT, 
typename IT>
 
 1209 inline void SimdArray<T, N, VectorType, M>::gatherImplementation(
const MT *mem,
 
 1210                                                                  IT &&indexes, MaskArgument mask)
 
 1212     data0.gather(mem, Split::lo(Common::Operations::gather(), indexes),
 
 1215     data1.gather(mem, Split::hi(Common::Operations::gather(), std::forward<IT>(indexes)),
 
 1220 template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
 1221 Vc_INTRINSIC 
typename SimdArrayTraits<T, N>::storage_type0 &internal_data0(
 
 1222     SimdArray<T, N, V, M> &x)
 
 1226 template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
 1227 Vc_INTRINSIC 
typename SimdArrayTraits<T, N>::storage_type1 &internal_data1(
 
 1228     SimdArray<T, N, V, M> &x)
 
 1232 template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
 1233 Vc_INTRINSIC 
const typename SimdArrayTraits<T, N>::storage_type0 &internal_data0(
 
 1234     const SimdArray<T, N, V, M> &x)
 
 1238 template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
 1239 Vc_INTRINSIC 
const typename SimdArrayTraits<T, N>::storage_type1 &internal_data1(
 
 1240     const SimdArray<T, N, V, M> &x)
 
 1246 namespace result_vector_type_internal
 
 1248 template <
typename T>
 
 1249 using type = 
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
 
 1251 template <
typename T>
 
 1252 using is_integer_larger_than_int = std::integral_constant<
 
 1253     bool, std::is_integral<T>::value &&(
sizeof(T) > 
sizeof(
int) ||
 
 1254                                         std::is_same<T, long>::value ||
 
 1255                                         std::is_same<T, unsigned long>::value)>;
 
 1258     typename L, 
typename R, std::size_t N = Traits::isSimdArray<L>::value
 
 1259                                                 ? Traits::simd_vector_size<L>::value
 
 1260                                                 : Traits::simd_vector_size<R>::value,
 
 1261     bool = (Traits::isSimdArray<L>::value ||
 
 1262             Traits::isSimdArray<R>::value)  
 
 1264            !std::is_same<type<L>, type<R>>::value  
 
 1267            ((std::is_arithmetic<type<L>>::value &&
 
 1268              !is_integer_larger_than_int<type<L>>::value) ||
 
 1269             (std::is_arithmetic<type<R>>::value &&
 
 1270              !is_integer_larger_than_int<
 
 1273             (Traits::is_simd_vector<L>::value && !Traits::isSimdArray<L>::value) ||
 
 1274             (Traits::is_simd_vector<R>::value &&
 
 1275              !Traits::isSimdArray<R>::value)  
 
 1276             ) > 
struct evaluate;
 
 1278 template <
typename L, 
typename R, std::
size_t N> 
struct evaluate<L, R, N, true>
 
 1281     using LScalar = Traits::entry_type_of<L>;
 
 1282     using RScalar = Traits::entry_type_of<R>;
 
 1284     template <
bool B, 
typename True, 
typename False>
 
 1285     using conditional = 
typename std::conditional<B, True, False>::type;
 
 1298     using type = SimdArray<
 
 1299         conditional<(std::is_integral<LScalar>::value &&std::is_integral<RScalar>::value &&
 
 1300                      sizeof(LScalar) < 
sizeof(
int) &&
 
 1301                      sizeof(RScalar) < 
sizeof(
int)),
 
 1302                     conditional<(
sizeof(LScalar) == 
sizeof(RScalar)),
 
 1303                                 conditional<std::is_unsigned<LScalar>::value, LScalar, RScalar>,
 
 1304                                 conditional<(sizeof(LScalar) > 
sizeof(RScalar)), LScalar, RScalar>>,
 
 1305                     decltype(std::declval<LScalar>() + std::declval<RScalar>())>,
 
 1311 template <
typename L, 
typename R>
 
 1312 using result_vector_type = 
typename result_vector_type_internal::evaluate<L, R>::type;
 
 1317     "result_vector_type does not work");
 
 1319 #define Vc_BINARY_OPERATORS_(op_)                                                        \ 
 1320     template <typename L, typename R>                                                    \ 
 1321     Vc_INTRINSIC result_vector_type<L, R> operator op_(L &&lhs, R &&rhs)                 \ 
 1323         using Return = result_vector_type<L, R>;                                         \ 
 1324         return Return(std::forward<L>(lhs)) op_ Return(std::forward<R>(rhs));            \ 
 1326 Vc_ALL_ARITHMETICS(Vc_BINARY_OPERATORS_)
 
 1327 Vc_ALL_BINARY(Vc_BINARY_OPERATORS_)
 
 1328 #undef Vc_BINARY_OPERATORS_ 
 1329 #define Vc_BINARY_OPERATORS_(op_)                                                        \ 
 1330     template <typename L, typename R>                                                    \ 
 1331     Vc_INTRINSIC typename result_vector_type<L, R>::mask_type operator op_(L &&lhs,      \ 
 1334         using Promote = result_vector_type<L, R>;                                        \ 
 1335         return Promote(std::forward<L>(lhs)) op_ Promote(std::forward<R>(rhs));          \ 
 1337 Vc_ALL_COMPARES(Vc_BINARY_OPERATORS_)
 
 1338 #undef Vc_BINARY_OPERATORS_ 
 1341 #define Vc_FORWARD_UNARY_OPERATOR(name_)                                                 \ 
 1342     template <typename T, std::size_t N, typename V, std::size_t M>                      \ 
 1343     inline SimdArray<T, N, V, M> name_(const SimdArray<T, N, V, M> &x)                   \ 
 1345         return SimdArray<T, N, V, M>::fromOperation(                                     \ 
 1346             Common::Operations::Forward_##name_(), x);                                   \ 
 1349 #define Vc_FORWARD_UNARY_BOOL_OPERATOR(name_)                                            \ 
 1350     template <typename T, std::size_t N, typename V, std::size_t M>                      \ 
 1351     inline SimdMaskArray<T, N, V, M> name_(const SimdArray<T, N, V, M> &x)               \ 
 1353         return SimdMaskArray<T, N, V, M>::fromOperation(                                 \ 
 1354             Common::Operations::Forward_##name_(), x);                                   \ 
 1357 #define Vc_FORWARD_BINARY_OPERATOR(name_)                                                \ 
 1358     template <typename T, std::size_t N, typename V, std::size_t M>                      \ 
 1359     inline SimdArray<T, N, V, M> name_(const SimdArray<T, N, V, M> &x,                   \ 
 1360                                        const SimdArray<T, N, V, M> &y)                   \ 
 1362         return SimdArray<T, N, V, M>::fromOperation(                                     \ 
 1363             Common::Operations::Forward_##name_(), x, y);                                \ 
 1366 Vc_FORWARD_UNARY_OPERATOR(abs)
 
 1367 Vc_FORWARD_UNARY_OPERATOR(asin)
 
 1368 Vc_FORWARD_UNARY_OPERATOR(atan)
 
 1369 Vc_FORWARD_BINARY_OPERATOR(atan2)
 
 1370 Vc_FORWARD_UNARY_OPERATOR(ceil)
 
 1371 Vc_FORWARD_BINARY_OPERATOR(copysign)
 
 1372 Vc_FORWARD_UNARY_OPERATOR(cos)
 
 1373 Vc_FORWARD_UNARY_OPERATOR(exp)
 
 1374 Vc_FORWARD_UNARY_OPERATOR(exponent)
 
 1375 Vc_FORWARD_UNARY_OPERATOR(floor)
 
 1376 template <typename T, 
std::
size_t N>
 
 1377 SimdArray<T, N> fma(const SimdArray<T, N> &a, const SimdArray<T, N> &b, const SimdArray<T, N> &c)
 
 1379     return SimdArray<T, N>::fromOperation(Common::Operations::Forward_fma(), a, b, c);
 
 1381 Vc_FORWARD_UNARY_BOOL_OPERATOR(isfinite)
 
 1382 Vc_FORWARD_UNARY_BOOL_OPERATOR(isinf)
 
 1383 Vc_FORWARD_UNARY_BOOL_OPERATOR(isnan)
 
 1384 Vc_FORWARD_UNARY_BOOL_OPERATOR(isnegative)
 
 1385 template <typename T, 
std::
size_t N>
 
 1386 SimdArray<T, N> frexp(const SimdArray<T, N> &x, SimdArray<
int, N> *e)
 
 1388     return SimdArray<T, N>::fromOperation(Common::Operations::Forward_frexp(), x, e);
 
 1390 template <
typename T, std::
size_t N>
 
 1391 SimdArray<T, N> 
ldexp(
const SimdArray<T, N> &x, 
const SimdArray<int, N> &e)
 
 1393     return SimdArray<T, N>::fromOperation(Common::Operations::Forward_ldexp(), x, e);
 
 1395 Vc_FORWARD_UNARY_OPERATOR(log)
 
 1396 Vc_FORWARD_UNARY_OPERATOR(log10)
 
 1397 Vc_FORWARD_UNARY_OPERATOR(log2)
 
 1398 Vc_FORWARD_UNARY_OPERATOR(reciprocal)
 
 1399 Vc_FORWARD_UNARY_OPERATOR(round)
 
 1400 Vc_FORWARD_UNARY_OPERATOR(rsqrt)
 
 1401 Vc_FORWARD_UNARY_OPERATOR(sin)
 
 1402 template <typename T, 
std::
size_t N>
 
 1403 void sincos(const SimdArray<T, N> &x, SimdArray<T, N> *sin, SimdArray<T, N> *cos)
 
 1405     SimdArray<T, N>::callOperation(Common::Operations::Forward_sincos(), x, sin, cos);
 
 1407 Vc_FORWARD_UNARY_OPERATOR(sqrt)
 
 1408 Vc_FORWARD_UNARY_OPERATOR(trunc)
 
 1409 Vc_FORWARD_BINARY_OPERATOR(min)
 
 1410 Vc_FORWARD_BINARY_OPERATOR(max)
 
 1411 #undef Vc_FORWARD_UNARY_OPERATOR 
 1412 #undef Vc_FORWARD_UNARY_BOOL_OPERATOR 
 1413 #undef Vc_FORWARD_BINARY_OPERATOR 
 1420 template <
typename Return, std::size_t N, 
typename T, 
typename... From>
 
 1421 Vc_INTRINSIC Vc_CONST enable_if<
sizeof...(From) != 0, Return>
 
 1422 simd_cast_impl_smaller_input(
const From &... xs, 
const T &last)
 
 1425     for (
size_t i = 0; i < N; ++i) {
 
 1426         r[i + N * 
sizeof...(From)] = static_cast<typename Return::EntryType>(last[i]);
 
 1430 template <
typename Return, std::
size_t N, 
typename T>
 
 1431 Vc_INTRINSIC Vc_CONST Return simd_cast_impl_smaller_input(
const T &last)
 
 1433     Return r = Return();
 
 1434     for (
size_t i = 0; i < N; ++i) {
 
 1435         r[i] = 
static_cast<typename Return::EntryType
>(last[i]);
 
 1439 template <
typename Return, std::size_t N, 
typename T, 
typename... From>
 
 1440 Vc_INTRINSIC Vc_CONST enable_if<
sizeof...(From) != 0, Return> simd_cast_impl_larger_input(
 
 1441     const From &... xs, 
const T &last)
 
 1444     for (
size_t i = N * 
sizeof...(From); i < Return::Size; ++i) {
 
 1445         r[i] = 
static_cast<typename Return::EntryType
>(last[i - N * 
sizeof...(From)]);
 
 1449 template <
typename Return, std::
size_t N, 
typename T>
 
 1450 Vc_INTRINSIC Vc_CONST Return simd_cast_impl_larger_input(
const T &last)
 
 1452     Return r = Return();
 
 1453     for (
size_t i = 0; i < Return::size(); ++i) {
 
 1454         r[i] = 
static_cast<typename Return::EntryType
>(last[i]);
 
 1460 template <
typename Return, 
typename T, 
typename... From>
 
 1461 Vc_INTRINSIC_L Vc_CONST_L Return
 
 1462     simd_cast_without_last(
const From &... xs, 
const T &) Vc_INTRINSIC_R Vc_CONST_R;
 
 1465 template <typename... Ts> struct are_all_types_equal;
 
 1466 template <typename T>
 
 1467 struct are_all_types_equal<T> : public 
std::integral_constant<
bool, true>
 
 1470 template <
typename T0, 
typename T1, 
typename... Ts>
 
 1471 struct are_all_types_equal<T0, T1, Ts...>
 
 1472     : 
public std::integral_constant<
 
 1473           bool, std::is_same<T0, T1>::value && are_all_types_equal<T1, Ts...>::value>
 
 1497 template <
typename Return, 
typename... Ts>
 
 1498 Vc_INTRINSIC Vc_CONST Return
 
 1499     simd_cast_interleaved_argument_order(
const Ts &... a, 
const Ts &... b);
 
 1503 template <
typename Return, std::size_t offset, 
typename From, 
typename... Froms>
 
 1504 Vc_INTRINSIC Vc_CONST
 
 1505     enable_if<(are_all_types_equal<From, Froms...>::value && offset == 0), Return>
 
 1506         simd_cast_with_offset(
const From &x, 
const Froms &... xs);
 
 1508 template <
typename Return, std::
size_t offset, 
typename From>
 
 1509 Vc_INTRINSIC Vc_CONST
 
 1510     enable_if<(From::Size > offset && offset > 0 && offset % Return::Size == 0), Return>
 
 1511         simd_cast_with_offset(
const From &x);
 
 1513 template <
typename Return, std::
size_t offset, 
typename From>
 
 1514 Vc_INTRINSIC Vc_CONST
 
 1515     enable_if<(From::Size > offset && offset > 0 && offset % Return::Size != 0 &&
 
 1516                ((Traits::isSimdArray<Return>::value &&
 
 1517                  !Traits::isAtomicSimdArray<Return>::value) ||
 
 1518                 (Traits::isSimdMaskArray<Return>::value &&
 
 1519                  !Traits::isAtomicSimdMaskArray<Return>::value))),
 
 1521         simd_cast_with_offset(
const From &x);
 
 1523 template <
typename Return, std::
size_t offset, 
typename From>
 
 1524 Vc_INTRINSIC Vc_CONST
 
 1525     enable_if<(From::Size > offset && offset > 0 && offset % Return::Size != 0 &&
 
 1526                ((Traits::isSimdArray<Return>::value &&
 
 1527                  Traits::isAtomicSimdArray<Return>::value) ||
 
 1528                 (Traits::isSimdMaskArray<Return>::value &&
 
 1529                  Traits::isAtomicSimdMaskArray<Return>::value))),
 
 1531         simd_cast_with_offset(
const From &x);
 
 1533 template <
typename Return, std::size_t offset, 
typename From, 
typename... Froms>
 
 1534 Vc_INTRINSIC Vc_CONST enable_if<
 
 1535     (are_all_types_equal<From, Froms...>::value && From::Size <= offset), Return>
 
 1536     simd_cast_with_offset(
const From &, 
const Froms &... xs)
 
 1538     return simd_cast_with_offset<Return, offset - From::Size>(xs...);
 
 1542 template <
typename Return, std::
size_t offset, 
typename From>
 
 1543 Vc_INTRINSIC Vc_CONST enable_if<(From::Size <= offset), Return> simd_cast_with_offset(
 
 1550 template <
typename T, 
typename... Ts> 
struct first_type_of_impl
 
 1554 template <
typename... Ts> 
using first_type_of = 
typename first_type_of_impl<Ts...>::type;
 
 1557 template <
typename Return, 
typename From>
 
 1558 Vc_INTRINSIC Vc_CONST Return simd_cast_drop_arguments(From x);
 
 1559 template <
typename Return, 
typename... Froms>
 
 1560 Vc_INTRINSIC Vc_CONST
 
 1561     enable_if<(are_all_types_equal<Froms...>::value &&
 
 1562                sizeof...(Froms) * first_type_of<Froms...>::Size < Return::Size),
 
 1564         simd_cast_drop_arguments(Froms... xs, first_type_of<Froms...> x);
 
 1568 template <
typename Return, 
typename From, 
typename... Froms>
 
 1569 Vc_INTRINSIC Vc_CONST enable_if<
 
 1570     (are_all_types_equal<From, Froms...>::value &&
 
 1571      (1 + 
sizeof...(Froms)) * From::Size >= Return::Size && 
sizeof...(Froms) != 0),
 
 1573 simd_cast_drop_arguments(Froms... xs, From x, From);
 
 1574 template <
typename Return, 
typename From>
 
 1575 Vc_INTRINSIC Vc_CONST
 
 1576     enable_if<(are_all_types_equal<From>::value && From::Size >= Return::Size), Return>
 
 1577     simd_cast_drop_arguments(From x, From);
 
 1581 #ifdef Vc_DEBUG_SIMD_CAST 
 1582 void debugDoNothing(
const std::initializer_list<void *> &) {}
 
 1583 template <
typename T0, 
typename... Ts>
 
 1584 inline void vc_debug_(
const char *prefix, 
const char *suffix, 
const T0 &arg0,
 
 1587     std::cerr << prefix << arg0;
 
 1588     debugDoNothing({&(std::cerr << 
", " << args)...});
 
 1589     std::cerr << suffix;
 
 1592 template <
typename T0, 
typename... Ts>
 
 1593 Vc_INTRINSIC 
void vc_debug_(
const char *, 
const char *, 
const T0 &, 
const Ts &...)
 
 1600 #define Vc_SIMDARRAY_CASTS(SimdArrayType_, trait_name_)                                  \ 
 1601     template <typename Return, typename From, typename... Froms>                         \ 
 1602     Vc_INTRINSIC Vc_CONST enable_if<(Traits::isAtomic##SimdArrayType_<Return>::value &&  \ 
 1603                                      !Traits::is##SimdArrayType_<From>::value &&         \ 
 1604                                      Traits::is_simd_##trait_name_<From>::value &&       \ 
 1605                                      From::Size * sizeof...(Froms) < Return::Size &&     \ 
 1606                                      are_all_types_equal<From, Froms...>::value),        \ 
 1608     simd_cast(From x, Froms... xs)                                                       \ 
 1610         vc_debug_("simd_cast{1}(", ")\n", x, xs...);                                     \ 
 1611         return {simd_cast<typename Return::storage_type>(x, xs...)};                     \ 
 1613     template <typename Return, typename From, typename... Froms>                         \ 
 1614     Vc_INTRINSIC Vc_CONST enable_if<(Traits::isAtomic##SimdArrayType_<Return>::value &&  \ 
 1615                                      !Traits::is##SimdArrayType_<From>::value &&         \ 
 1616                                      Traits::is_simd_##trait_name_<From>::value &&       \ 
 1617                                      From::Size * sizeof...(Froms) >= Return::Size &&    \ 
 1618                                      are_all_types_equal<From, Froms...>::value),        \ 
 1620     simd_cast(From x, Froms... xs)                                                       \ 
 1622         vc_debug_("simd_cast{2}(", ")\n", x, xs...);                                     \ 
 1623         return {simd_cast_without_last<Return, From, Froms...>(x, xs...)};               \ 
 1625     template <typename Return, typename From, typename... Froms>                         \ 
 1626     Vc_INTRINSIC Vc_CONST enable_if<(Traits::is##SimdArrayType_<Return>::value &&        \ 
 1627                                      !Traits::isAtomic##SimdArrayType_<Return>::value && \ 
 1628                                      !Traits::is##SimdArrayType_<From>::value &&         \ 
 1629                                      Traits::is_simd_##trait_name_<From>::value &&       \ 
 1630                                      Common::left_size(Return::Size) <                   \ 
 1631                                          From::Size * (1 + sizeof...(Froms)) &&          \ 
 1632                                      are_all_types_equal<From, Froms...>::value),        \ 
 1634     simd_cast(From x, Froms... xs)                                                       \ 
 1636         vc_debug_("simd_cast{3}(", ")\n", x, xs...);                                     \ 
 1637         using R0 = typename Return::storage_type0;                                       \ 
 1638         using R1 = typename Return::storage_type1;                                       \ 
 1639         return {simd_cast_drop_arguments<R0, Froms...>(x, xs...),                        \ 
 1640                 simd_cast_with_offset<R1, R0::Size>(x, xs...)};                          \ 
 1642     template <typename Return, typename From, typename... Froms>                         \ 
 1643     Vc_INTRINSIC Vc_CONST enable_if<(Traits::is##SimdArrayType_<Return>::value &&        \ 
 1644                                      !Traits::isAtomic##SimdArrayType_<Return>::value && \ 
 1645                                      !Traits::is##SimdArrayType_<From>::value &&         \ 
 1646                                      Traits::is_simd_##trait_name_<From>::value &&       \ 
 1647                                      Common::left_size(Return::Size) >=                  \ 
 1648                                          From::Size * (1 + sizeof...(Froms)) &&          \ 
 1649                                      are_all_types_equal<From, Froms...>::value),        \ 
 1651     simd_cast(From x, Froms... xs)                                                       \ 
 1653         vc_debug_("simd_cast{4}(", ")\n", x, xs...);                                     \ 
 1654         using R0 = typename Return::storage_type0;                                       \ 
 1655         using R1 = typename Return::storage_type1;                                       \ 
 1656         return {simd_cast<R0>(x, xs...), R1::Zero()};                                    \ 
 1658 Vc_SIMDARRAY_CASTS(SimdArray, 
vector)
 
 1659 Vc_SIMDARRAY_CASTS(SimdMaskArray, mask)
 
 1660 #undef Vc_SIMDARRAY_CASTS 
 1663 #define Vc_SIMDARRAY_CASTS(SimdArrayType_, trait_name_)                                  \ 
 1665     template <typename Return, int offset, typename From>                                \ 
 1666     Vc_INTRINSIC Vc_CONST enable_if<(Traits::isAtomic##SimdArrayType_<Return>::value &&  \ 
 1667                                      !Traits::is##SimdArrayType_<From>::value &&         \ 
 1668                                      Traits::is_simd_##trait_name_<From>::value),        \ 
 1672         vc_debug_("simd_cast{offset, atomic}(", ")\n", offset, x);                       \ 
 1673         return {simd_cast<typename Return::storage_type, offset>(x)};                    \ 
 1676     template <typename Return, int offset, typename From>                                \ 
 1677     Vc_INTRINSIC Vc_CONST enable_if<                                                     \ 
 1678         (Traits::is##SimdArrayType_<Return>::value &&                                    \ 
 1679          !Traits::isAtomic##SimdArrayType_<Return>::value &&                             \ 
 1680          !Traits::is##SimdArrayType_<From>::value &&                                     \ 
 1681          Traits::is_simd_##trait_name_<From>::value &&                                   \ 
 1682          Return::Size * offset + Common::left_size(Return::Size) < From::Size),          \ 
 1686         vc_debug_("simd_cast{offset, split Return}(", ")\n", offset, x);                 \ 
 1687         using R0 = typename Return::storage_type0;                                       \ 
 1688         constexpr int entries_offset = offset * Return::Size;                            \ 
 1689         constexpr int entries_offset_right = entries_offset + R0::Size;                  \ 
 1691             simd_cast_with_offset<typename Return::storage_type0, entries_offset>(x),    \ 
 1692             simd_cast_with_offset<typename Return::storage_type1, entries_offset_right>( \ 
 1697     template <typename Return, int offset, typename From>                                \ 
 1698     Vc_INTRINSIC Vc_CONST enable_if<                                                     \ 
 1699         (Traits::is##SimdArrayType_<Return>::value &&                                    \ 
 1700          !Traits::isAtomic##SimdArrayType_<Return>::value &&                             \ 
 1701          !Traits::is##SimdArrayType_<From>::value &&                                     \ 
 1702          Traits::is_simd_##trait_name_<From>::value &&                                   \ 
 1703          Return::Size * offset + Common::left_size(Return::Size) >= From::Size),         \ 
 1707         vc_debug_("simd_cast{offset, R1::Zero}(", ")\n", offset, x);                     \ 
 1708         using R0 = typename Return::storage_type0;                                       \ 
 1709         using R1 = typename Return::storage_type1;                                       \ 
 1710         constexpr int entries_offset = offset * Return::Size;                            \ 
 1711         return {simd_cast_with_offset<R0, entries_offset>(x), R1::Zero()};               \ 
 1713 Vc_SIMDARRAY_CASTS(SimdArray, 
vector)
 
 1714 Vc_SIMDARRAY_CASTS(SimdMaskArray, mask)
 
 1715 #undef Vc_SIMDARRAY_CASTS 
 1718 #define Vc_SIMDARRAY_CASTS(SimdArrayType_)                                               \ 
 1720     template <typename Return, typename T, std::size_t N, typename V, typename... From>  \ 
 1721     Vc_INTRINSIC Vc_CONST                                                                \ 
 1722         enable_if<(are_all_types_equal<SimdArrayType_<T, N, V, N>, From...>::value &&    \ 
 1723                    (sizeof...(From) == 0 || N * sizeof...(From) < Return::Size) &&       \ 
 1724                    !std::is_same<Return, SimdArrayType_<T, N, V, N>>::value),            \ 
 1726         simd_cast(const SimdArrayType_<T, N, V, N> &x0, const From &... xs)              \ 
 1728         vc_debug_("simd_cast{indivisible}(", ")\n", x0, xs...);                          \ 
 1729         return simd_cast<Return>(internal_data(x0), internal_data(xs)...);               \ 
 1732     template <typename Return, typename T, std::size_t N, typename V, typename... From>  \ 
 1733     Vc_INTRINSIC Vc_CONST                                                                \ 
 1734         enable_if<(are_all_types_equal<SimdArrayType_<T, N, V, N>, From...>::value &&    \ 
 1735                    (sizeof...(From) > 0 && (N * sizeof...(From) >= Return::Size)) &&     \ 
 1736                    !std::is_same<Return, SimdArrayType_<T, N, V, N>>::value),            \ 
 1738         simd_cast(const SimdArrayType_<T, N, V, N> &x0, const From &... xs)              \ 
 1740         vc_debug_("simd_cast{indivisible2}(", ")\n", x0, xs...);                         \ 
 1741         return simd_cast_without_last<Return,                                            \ 
 1742                                       typename SimdArrayType_<T, N, V, N>::storage_type, \ 
 1743                                       typename From::storage_type...>(                   \ 
 1744             internal_data(x0), internal_data(xs)...);                                    \ 
 1747     template <typename Return, typename T, std::size_t N, typename V, std::size_t M,     \ 
 1749     Vc_INTRINSIC Vc_CONST enable_if<                                                     \ 
 1750         (N != M && are_all_types_equal<SimdArrayType_<T, N, V, M>, From...>::value &&    \ 
 1751          N * sizeof...(From) < Return::Size && ((N - 1) & N) == 0),                      \ 
 1753     simd_cast(const SimdArrayType_<T, N, V, M> &x0, const From &... xs)                  \ 
 1755         vc_debug_("simd_cast{bisectable}(", ")\n", x0, xs...);                           \ 
 1756         return simd_cast_interleaved_argument_order<                                     \ 
 1757             Return, typename SimdArrayType_<T, N, V, M>::storage_type0,                  \ 
 1758             typename From::storage_type0...>(internal_data0(x0), internal_data0(xs)...,  \ 
 1759                                              internal_data1(x0), internal_data1(xs)...); \ 
 1763     template <typename Return, typename T, std::size_t N, typename V, std::size_t M,     \ 
 1765     Vc_INTRINSIC Vc_CONST enable_if<                                                     \ 
 1766         (N != M && are_all_types_equal<SimdArrayType_<T, N, V, M>, From...>::value &&    \ 
 1767          N * sizeof...(From) >= Return::Size && ((N - 1) & N) == 0),                     \ 
 1769     simd_cast(const SimdArrayType_<T, N, V, M> &x0, const From &... xs)                  \ 
 1771         vc_debug_("simd_cast{bisectable2}(", ")\n", x0, xs...);                          \ 
 1772         return simd_cast_without_last<Return, SimdArrayType_<T, N, V, M>, From...>(      \ 
 1776     template <typename Return, typename T, std::size_t N, typename V, std::size_t M,     \ 
 1778     Vc_INTRINSIC Vc_CONST enable_if<                                                     \ 
 1779         (N != M && are_all_types_equal<SimdArrayType_<T, N, V, M>, From...>::value &&    \ 
 1780          N * (1 + sizeof...(From)) <= Return::Size && ((N - 1) & N) != 0),               \ 
 1782     simd_cast(const SimdArrayType_<T, N, V, M> &x0, const From &... xs)                  \ 
 1784         vc_debug_("simd_cast{remaining}(", ")\n", x0, xs...);                            \ 
 1785         return simd_cast_impl_smaller_input<Return, N, SimdArrayType_<T, N, V, M>,       \ 
 1786                                             From...>(x0, xs...);                         \ 
 1789     template <typename Return, typename T, std::size_t N, typename V, std::size_t M,     \ 
 1791     Vc_INTRINSIC Vc_CONST enable_if<                                                     \ 
 1792         (N != M && are_all_types_equal<SimdArrayType_<T, N, V, M>, From...>::value &&    \ 
 1793          N * (1 + sizeof...(From)) > Return::Size && ((N - 1) & N) != 0),                \ 
 1795     simd_cast(const SimdArrayType_<T, N, V, M> &x0, const From &... xs)                  \ 
 1797         vc_debug_("simd_cast{remaining2}(", ")\n", x0, xs...);                           \ 
 1798         return simd_cast_impl_larger_input<Return, N, SimdArrayType_<T, N, V, M>,        \ 
 1799                                            From...>(x0, xs...);                          \ 
 1802     template <typename Return, typename T, std::size_t N, typename V, std::size_t M>     \ 
 1803     Vc_INTRINSIC Vc_CONST                                                                \ 
 1804         enable_if<(N != M && N >= 2 * Return::Size && ((N - 1) & N) == 0), Return>       \ 
 1805         simd_cast(const SimdArrayType_<T, N, V, M> &x)                                   \ 
 1807         vc_debug_("simd_cast{single bisectable}(", ")\n", x);                            \ 
 1808         return simd_cast<Return>(internal_data0(x));                                     \ 
 1810     template <typename Return, typename T, std::size_t N, typename V, std::size_t M>     \ 
 1811     Vc_INTRINSIC Vc_CONST enable_if<(N != M && N > Return::Size &&                       \ 
 1812                                      N < 2 * Return::Size && ((N - 1) & N) == 0),        \ 
 1814     simd_cast(const SimdArrayType_<T, N, V, M> &x)                                       \ 
 1816         vc_debug_("simd_cast{single bisectable2}(", ")\n", x);                           \ 
 1817         return simd_cast<Return>(internal_data0(x), internal_data1(x));                  \ 
 1819 Vc_SIMDARRAY_CASTS(SimdArray)
 
 1820 Vc_SIMDARRAY_CASTS(SimdMaskArray)
 
 1821 #undef Vc_SIMDARRAY_CASTS 
 1824 #define Vc_SIMDARRAY_CASTS(SimdArrayType_)                                               \ 
 1826     template <typename Return, int offset, typename T, std::size_t N, typename V,        \ 
 1828     Vc_INTRINSIC Vc_CONST enable_if<(offset == 0), Return> simd_cast(                    \ 
 1829         const SimdArrayType_<T, N, V, M> &x)                                             \ 
 1831         vc_debug_("simd_cast{offset == 0}(", ")\n", offset, x);                          \ 
 1832         return simd_cast<Return>(x);                                                     \ 
 1835     template <typename Return, int offset, typename T, std::size_t N, typename V>        \ 
 1836     Vc_INTRINSIC Vc_CONST enable_if<(offset != 0), Return> simd_cast(                    \ 
 1837         const SimdArrayType_<T, N, V, N> &x)                                             \ 
 1839         vc_debug_("simd_cast{offset, forward}(", ")\n", offset, x);                      \ 
 1840         return simd_cast<Return, offset>(internal_data(x));                              \ 
 1843     template <typename Return, int offset, typename T, std::size_t N, typename V,        \ 
 1845     Vc_INTRINSIC Vc_CONST                                                                \ 
 1846         enable_if<(N != M && offset * Return::Size >= Common::left_size(N) &&            \ 
 1847                    offset != 0 && Common::left_size(N) % Return::Size == 0),             \ 
 1849         simd_cast(const SimdArrayType_<T, N, V, M> &x)                                   \ 
 1851         vc_debug_("simd_cast{offset, right}(", ")\n", offset, x);                        \ 
 1852         return simd_cast<Return, offset - Common::left_size(N) / Return::Size>(          \ 
 1853             internal_data1(x));                                                          \ 
 1857     template <typename Return, int offset, typename T, std::size_t N, typename V,        \ 
 1859     Vc_INTRINSIC Vc_CONST                                                                \ 
 1860         enable_if<(N != M && offset * Return::Size >= Common::left_size(N) &&            \ 
 1861                    offset != 0 && Common::left_size(N) % Return::Size != 0),             \ 
 1863         simd_cast(const SimdArrayType_<T, N, V, M> &x)                                   \ 
 1865         vc_debug_("simd_cast{offset, right, nofit}(", ")\n", offset, x);                 \ 
 1866         return simd_cast_with_offset<Return,                                             \ 
 1867                                      offset * Return::Size - Common::left_size(N)>(      \ 
 1868             internal_data1(x));                                                          \ 
 1871     template <typename Return, int offset, typename T, std::size_t N, typename V,        \ 
 1873     Vc_INTRINSIC Vc_CONST                                                                \ 
 1874         enable_if<(N != M &&          \ 
 1875                    offset != 0 && (offset + 1) * Return::Size <= Common::left_size(N)),  \ 
 1877         simd_cast(const SimdArrayType_<T, N, V, M> &x)                                   \ 
 1879         vc_debug_("simd_cast{offset, left}(", ")\n", offset, x);                         \ 
 1880         return simd_cast<Return, offset>(internal_data0(x));                             \ 
 1883     template <typename Return, int offset, typename T, std::size_t N, typename V,        \ 
 1885     Vc_INTRINSIC Vc_CONST                                                                \ 
 1886         enable_if<(N != M && (offset * Return::Size < Common::left_size(N)) &&           \ 
 1887                    offset != 0 && (offset + 1) * Return::Size > Common::left_size(N)),   \ 
 1889         simd_cast(const SimdArrayType_<T, N, V, M> &x)                                   \ 
 1891         vc_debug_("simd_cast{offset, copy scalars}(", ")\n", offset, x);                 \ 
 1892         using R = typename Return::EntryType;                                            \ 
 1893         Return r = Return::Zero();                                                       \ 
 1894         for (std::size_t i = offset * Return::Size;                                      \ 
 1895              i < std::min(N, (offset + 1) * Return::Size); ++i) {                        \ 
 1896             r[i - offset * Return::Size] = static_cast<R>(x[i]);                         \ 
 1900 Vc_SIMDARRAY_CASTS(SimdArray)
 
 1901 Vc_SIMDARRAY_CASTS(SimdMaskArray)
 
 1902 #undef Vc_SIMDARRAY_CASTS 
 1904 template <
typename Return, 
typename From>
 
 1905 Vc_INTRINSIC Vc_CONST Return simd_cast_drop_arguments(From x)
 
 1909 template <
typename Return, 
typename... Froms>
 
 1910 Vc_INTRINSIC Vc_CONST
 
 1911     enable_if<(are_all_types_equal<Froms...>::value &&
 
 1912                sizeof...(Froms) * first_type_of<Froms...>::Size < Return::Size),
 
 1914         simd_cast_drop_arguments(Froms... xs, first_type_of<Froms...> x)
 
 1921 template <
typename Return, 
typename From, 
typename... Froms>
 
 1922 Vc_INTRINSIC Vc_CONST enable_if<
 
 1923     (are_all_types_equal<From, Froms...>::value &&
 
 1924      (1 + 
sizeof...(Froms)) * From::Size >= Return::Size && 
sizeof...(Froms) != 0),
 
 1926 simd_cast_drop_arguments(Froms... xs, From x, From)
 
 1928     return simd_cast_drop_arguments<Return, Froms...>(xs..., x);
 
 1930 template <
typename Return, 
typename From>
 
 1931 Vc_INTRINSIC Vc_CONST
 
 1932     enable_if<(are_all_types_equal<From>::value && From::Size >= Return::Size), Return>
 
 1933     simd_cast_drop_arguments(From x, From)
 
 1935     return simd_cast_drop_arguments<Return>(x);
 
 1939     template <
typename Return, std::
size_t offset, 
typename From>
 
 1940     Vc_INTRINSIC Vc_CONST
 
 1941     enable_if<(From::Size > offset && offset > 0 && offset % Return::Size == 0),
 
 1942               Return> simd_cast_with_offset(
const From &x)
 
 1944     return simd_cast<Return, offset / Return::Size>(x);
 
 1946 template <
typename Return, std::
size_t offset, 
typename From>
 
 1947 Vc_INTRINSIC Vc_CONST
 
 1948     enable_if<(From::Size > offset && offset > 0 && offset % Return::Size != 0 &&
 
 1949                ((Traits::isSimdArray<Return>::value &&
 
 1950                  !Traits::isAtomicSimdArray<Return>::value) ||
 
 1951                 (Traits::isSimdMaskArray<Return>::value &&
 
 1952                  !Traits::isAtomicSimdMaskArray<Return>::value))),
 
 1954         simd_cast_with_offset(
const From &x)
 
 1956     using R0 = 
typename Return::storage_type0;
 
 1957     using R1 = 
typename Return::storage_type1;
 
 1958     return {simd_cast_with_offset<R0, offset>(x),
 
 1959             simd_cast_with_offset<R1, offset + R0::Size>(x)};
 
 1961 template <
typename Return, std::
size_t offset, 
typename From>
 
 1962 Vc_INTRINSIC Vc_CONST
 
 1963     enable_if<(From::Size > offset && offset > 0 && offset % Return::Size != 0 &&
 
 1964                ((Traits::isSimdArray<Return>::value &&
 
 1965                  Traits::isAtomicSimdArray<Return>::value) ||
 
 1966                 (Traits::isSimdMaskArray<Return>::value &&
 
 1967                  Traits::isAtomicSimdMaskArray<Return>::value))),
 
 1969         simd_cast_with_offset(
const From &x)
 
 1971     return simd_cast<Return, offset / Return::Size>(x.shifted(offset % Return::Size));
 
 1973 template <
typename Return, std::size_t offset, 
typename From, 
typename... Froms>
 
 1974 Vc_INTRINSIC Vc_CONST
 
 1975     enable_if<(are_all_types_equal<From, Froms...>::value && offset == 0), Return>
 
 1976         simd_cast_with_offset(
const From &x, 
const Froms &... xs)
 
 1982 template <
typename Return, 
typename T, 
typename... From>
 
 1983 Vc_INTRINSIC Vc_CONST Return simd_cast_without_last(
const From &... xs, 
const T &)
 
 1991 template <std::size_t I, 
typename T0, 
typename... Ts>
 
 1992 Vc_INTRINSIC Vc_CONST enable_if<(I == 0), T0> extract_interleaved(
const T0 &a0,
 
 2000 template <std::size_t I, 
typename T0, 
typename... Ts>
 
 2001 Vc_INTRINSIC Vc_CONST enable_if<(I == 1), T0> extract_interleaved(
const T0 &,
 
 2009 template <std::size_t I, 
typename T0, 
typename... Ts>
 
 2010 Vc_INTRINSIC Vc_CONST enable_if<(I > 1), T0> extract_interleaved(
const T0 &,
 
 2015     return extract_interleaved<I - 2, Ts...>(a..., b...);
 
 2019 template <
typename Return, 
typename... Ts, std::size_t... Indexes>
 
 2020 Vc_INTRINSIC Vc_CONST Return
 
 2021     simd_cast_interleaved_argument_order_1(index_sequence<Indexes...>, 
const Ts &... a,
 
 2024     return simd_cast<Return>(extract_interleaved<Indexes, Ts...>(a..., b...)...);
 
 2028 template <
typename Return, 
typename... Ts>
 
 2029 Vc_INTRINSIC Vc_CONST Return
 
 2030     simd_cast_interleaved_argument_order(
const Ts &... a, 
const Ts &... b)
 
 2032     using seq = make_index_sequence<
sizeof...(Ts)*2>;
 
 2033     return simd_cast_interleaved_argument_order_1<Return, Ts...>(seq(), a..., b...);
 
 2037 #define Vc_CONDITIONAL_ASSIGN(name_, op_)                                                \ 
 2038     template <Operator O, typename T, std::size_t N, typename V, size_t VN, typename M,  \ 
 2040     Vc_INTRINSIC enable_if<O == Operator::name_, void> conditional_assign(               \ 
 2041         SimdArray<T, N, V, VN> &lhs, M &&mask, U &&rhs)                                  \ 
 2043         lhs(mask) op_ rhs;                                                               \ 
 2045 Vc_CONDITIONAL_ASSIGN(          Assign,  =)
 
 2046 Vc_CONDITIONAL_ASSIGN(      PlusAssign, +=)
 
 2047 Vc_CONDITIONAL_ASSIGN(     MinusAssign, -=)
 
 2048 Vc_CONDITIONAL_ASSIGN(  MultiplyAssign, *=)
 
 2049 Vc_CONDITIONAL_ASSIGN(    DivideAssign, /=)
 
 2050 Vc_CONDITIONAL_ASSIGN( RemainderAssign, %=)
 
 2051 Vc_CONDITIONAL_ASSIGN(       XorAssign, ^=)
 
 2052 Vc_CONDITIONAL_ASSIGN(       AndAssign, &=)
 
 2053 Vc_CONDITIONAL_ASSIGN(        OrAssign, |=)
 
 2054 Vc_CONDITIONAL_ASSIGN( LeftShiftAssign,<<=)
 
 2055 Vc_CONDITIONAL_ASSIGN(RightShiftAssign,>>=)
 
 2056 #undef Vc_CONDITIONAL_ASSIGN 
 2058 #define Vc_CONDITIONAL_ASSIGN(name_, expr_)                                              \ 
 2059     template <Operator O, typename T, std::size_t N, typename V, size_t VN, typename M>  \ 
 2060     Vc_INTRINSIC enable_if<O == Operator::name_, SimdArray<T, N, V, VN>>                 \ 
 2061     conditional_assign(SimdArray<T, N, V, VN> &lhs, M &&mask)                            \ 
 2065 Vc_CONDITIONAL_ASSIGN(PostIncrement, lhs(mask)++)
 
 2066 Vc_CONDITIONAL_ASSIGN( PreIncrement, ++lhs(mask))
 
 2067 Vc_CONDITIONAL_ASSIGN(PostDecrement, lhs(mask)--)
 
 2068 Vc_CONDITIONAL_ASSIGN( PreDecrement, --lhs(mask))
 
 2069 #undef Vc_CONDITIONAL_ASSIGN 
 2073     template <
int L, 
typename T, std::
size_t N, 
typename V>
 
 2074     inline enable_if<L == 4, void> transpose_impl(
 
 2075         SimdArray<T, N, V, N> * Vc_RESTRICT r[],
 
 2076         const TransposeProxy<SimdArray<T, N, V, N>, SimdArray<T, N, V, N>,
 
 2077                              SimdArray<T, N, V, N>, SimdArray<T, N, V, N>> &proxy)
 
 2079         V *Vc_RESTRICT r2[L] = {&internal_data(*r[0]), &internal_data(*r[1]),
 
 2080                                 &internal_data(*r[2]), &internal_data(*r[3])};
 
 2082             &r2[0], TransposeProxy<V, V, V, V>{internal_data(std::get<0>(proxy.in)),
 
 2083                                                internal_data(std::get<1>(proxy.in)),
 
 2084                                                internal_data(std::get<2>(proxy.in)),
 
 2085                                                internal_data(std::get<3>(proxy.in))});
 
 2087     template <
int L, 
typename T, 
typename V>
 
 2088     inline enable_if<(L == 2), void> transpose_impl(
 
 2089         SimdArray<T, 4, V, 1> *Vc_RESTRICT r[],
 
 2090         const TransposeProxy<SimdArray<T, 2, V, 1>, SimdArray<T, 2, V, 1>,
 
 2091                              SimdArray<T, 2, V, 1>, SimdArray<T, 2, V, 1>> &proxy)
 
 2095         internal_data0(internal_data0(lo)) = internal_data0(std::get<0>(proxy.in));
 
 2096         internal_data1(internal_data0(lo)) = internal_data0(std::get<1>(proxy.in));
 
 2097         internal_data0(internal_data1(lo)) = internal_data0(std::get<2>(proxy.in));
 
 2098         internal_data1(internal_data1(lo)) = internal_data0(std::get<3>(proxy.in));
 
 2099         internal_data0(internal_data0(hi)) = internal_data1(std::get<0>(proxy.in));
 
 2100         internal_data1(internal_data0(hi)) = internal_data1(std::get<1>(proxy.in));
 
 2101         internal_data0(internal_data1(hi)) = internal_data1(std::get<2>(proxy.in));
 
 2102         internal_data1(internal_data1(hi)) = internal_data1(std::get<3>(proxy.in));
 
 2104     template <
int L, 
typename T, std::
size_t N, 
typename V>
 
 2105     inline enable_if<(L == 4 && N > 1), 
void> transpose_impl(
 
 2106         SimdArray<T, N, V, 1> *Vc_RESTRICT r[],
 
 2107         const TransposeProxy<SimdArray<T, N, V, 1>, SimdArray<T, N, V, 1>,
 
 2108                              SimdArray<T, N, V, 1>, SimdArray<T, N, V, 1>> &proxy)
 
 2110         SimdArray<T, N, V, 1> *Vc_RESTRICT r0[L / 2] = {r[0], r[1]};
 
 2111         SimdArray<T, N, V, 1> *Vc_RESTRICT r1[L / 2] = {r[2], r[3]};
 
 2112         using H = SimdArray<T, 2>;
 
 2114             &r0[0], TransposeProxy<H, H, H, H>{internal_data0(std::get<0>(proxy.in)),
 
 2115                                                internal_data0(std::get<1>(proxy.in)),
 
 2116                                                internal_data0(std::get<2>(proxy.in)),
 
 2117                                                internal_data0(std::get<3>(proxy.in))});
 
 2119             &r1[0], TransposeProxy<H, H, H, H>{internal_data1(std::get<0>(proxy.in)),
 
 2120                                                internal_data1(std::get<1>(proxy.in)),
 
 2121                                                internal_data1(std::get<2>(proxy.in)),
 
 2122                                                internal_data1(std::get<3>(proxy.in))});
 
 2174 template <
typename T, 
size_t N, 
typename V, 
size_t VN>
 
 2175 struct numeric_limits<
Vc::SimdArray<T, N, V, VN>> : 
public numeric_limits<T> {
 
 2180     static Vc_ALWAYS_INLINE Vc_CONST R max() noexcept { 
return numeric_limits<T>::max(); }
 
 2181     static Vc_ALWAYS_INLINE Vc_CONST R 
min() noexcept { 
return numeric_limits<T>::min(); }
 
 2182     static Vc_ALWAYS_INLINE Vc_CONST R lowest() noexcept
 
 2184         return numeric_limits<T>::lowest();
 
 2186     static Vc_ALWAYS_INLINE Vc_CONST R epsilon() noexcept
 
 2188         return numeric_limits<T>::epsilon();
 
 2190     static Vc_ALWAYS_INLINE Vc_CONST R round_error() noexcept
 
 2192         return numeric_limits<T>::round_error();
 
 2194     static Vc_ALWAYS_INLINE Vc_CONST R infinity() noexcept
 
 2196         return numeric_limits<T>::infinity();
 
 2198     static Vc_ALWAYS_INLINE Vc_CONST R quiet_NaN() noexcept
 
 2200         return numeric_limits<T>::quiet_NaN();
 
 2202     static Vc_ALWAYS_INLINE Vc_CONST R signaling_NaN() noexcept
 
 2204         return numeric_limits<T>::signaling_NaN();
 
 2206     static Vc_ALWAYS_INLINE Vc_CONST R denorm_min() noexcept
 
 2208         return numeric_limits<T>::denorm_min();