29 #ifndef VC_COMMON_SIMDMASKARRAY_H_ 
   30 #define VC_COMMON_SIMDMASKARRAY_H_ 
   32 #include <type_traits> 
   34 #include "simdarrayhelper.h" 
   36 #include "maskentry.h" 
   40 namespace Vc_VERSIONED_NAMESPACE
 
   45 template <
typename T, std::
size_t N, 
typename VectorType_>
 
   48     ((Common::nextPowerOfTwo(N) * (sizeof(VectorType_) / VectorType_::size()) - 1) & 127) +
 
   50     1) SimdMaskArray<T, N, VectorType_, N>
 
   53     using VectorType = VectorType_;
 
   54     using vector_type = VectorType;
 
   55     using mask_type = 
typename vector_type::Mask;
 
   56     using storage_type = mask_type;
 
   58     friend storage_type &internal_data(SimdMaskArray &m) { 
return m.data; }
 
   59     friend const storage_type &internal_data(
const SimdMaskArray &m) { 
return m.data; }
 
   61     static constexpr std::size_t size() { 
return N; }
 
   62     static constexpr std::size_t Size = size();
 
   64     static_assert(Size == mask_type::Size, 
"size mismatch");
 
   66     using vectorentry_type = 
typename mask_type::VectorEntryType;
 
   67     using vectorentry_reference = vectorentry_type &;
 
   68     using value_type = 
typename mask_type::EntryType;
 
   69     using Mask = mask_type;
 
   70     using VectorEntryType = vectorentry_type;
 
   71     using EntryType = value_type;
 
   72     using EntryReference = 
typename mask_type::EntryReference;
 
   73     using Vector = SimdArray<T, N, VectorType, N>;
 
   75     Vc_FREE_STORE_OPERATORS_ALIGNED(
alignof(mask_type))
 
   78     SimdMaskArray() = default;
 
   81     Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerOne one) : data(one) {}
 
   82     Vc_INTRINSIC 
explicit SimdMaskArray(VectorSpecialInitializerZero zero) : data(zero) {}
 
   83     Vc_INTRINSIC 
explicit SimdMaskArray(
bool b) : data(b) {}
 
   88     template <
typename U, 
typename V>
 
   89     Vc_INTRINSIC_L SimdMaskArray(
const SimdMaskArray<U, N, V> &x,
 
   90                                    enable_if<N == V::size()> = nullarg) Vc_INTRINSIC_R;
 
   91     template <typename U, typename V>
 
   92     Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
 
   93                                    enable_if<(N > V::size() && N <= 2 * V::size())> = nullarg)
 
   95     template <typename U, typename V>
 
   96     Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
 
   97                                    enable_if<(N > 2 * V::size() && N <= 4 * V::size())> = nullarg)
 
  101     template <typename M, 
std::
size_t Pieces, 
std::
size_t Index>
 
  102     Vc_INTRINSIC_L SimdMaskArray(
 
  103         Common::Segment<M, Pieces, Index> &&x,
 
  104         enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg) Vc_INTRINSIC_R;
 
  107     template <typename M>
 
  108     Vc_INTRINSIC_L SimdMaskArray(
 
  110         enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
 
  111                    Traits::simd_vector_size<M>::value == Size)> = nullarg) Vc_INTRINSIC_R;
 
  114     template <typename M,
 
  115               typename = enable_if<Traits::is_simd_mask<M>::value &&
 
  116                                    !Traits::isSimdMaskArray<M>::value && M::size() == N>>
 
  123     template <
typename Flags = DefaultLoadTag>
 
  124     Vc_INTRINSIC 
explicit SimdMaskArray(
const bool *mem, Flags f = Flags())
 
  129     Vc_INTRINSIC 
void load(
const bool *mem) { data.load(mem); }
 
  130     template <
typename Flags> Vc_INTRINSIC 
void load(
const bool *mem, Flags f)
 
  135     Vc_INTRINSIC 
void store(
bool *mem)
 const { data.store(mem); }
 
  136     template <
typename Flags> Vc_INTRINSIC 
void store(
bool *mem, Flags f)
 const 
  142     Vc_INTRINSIC Vc_PURE 
bool operator==(
const SimdMaskArray &rhs)
 const 
  144         return data == rhs.data;
 
  146     Vc_INTRINSIC Vc_PURE 
bool operator!=(
const SimdMaskArray &rhs)
 const 
  148         return data != rhs.data;
 
  152     Vc_INTRINSIC Vc_PURE SimdMaskArray operator!()
 const 
  158     Vc_INTRINSIC SimdMaskArray &operator&=(
const SimdMaskArray &rhs)
 
  163     Vc_INTRINSIC SimdMaskArray &operator|=(
const SimdMaskArray &rhs)
 
  168     Vc_INTRINSIC SimdMaskArray &operator^=(
const SimdMaskArray &rhs)
 
  174     Vc_INTRINSIC Vc_PURE SimdMaskArray operator&(
const SimdMaskArray &rhs)
 const 
  176         return {data & rhs.data};
 
  178     Vc_INTRINSIC Vc_PURE SimdMaskArray operator|(
const SimdMaskArray &rhs)
 const 
  180         return {data | rhs.data};
 
  182     Vc_INTRINSIC Vc_PURE SimdMaskArray operator^(
const SimdMaskArray &rhs)
 const 
  184         return {data ^ rhs.data};
 
  187     Vc_INTRINSIC Vc_PURE SimdMaskArray operator&&(
const SimdMaskArray &rhs)
 const 
  189         return {data && rhs.data};
 
  191     Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(
const SimdMaskArray &rhs)
 const 
  193         return {data || rhs.data};
 
  196     Vc_INTRINSIC Vc_PURE 
bool isFull()
 const { 
return data.isFull(); }
 
  197     Vc_INTRINSIC Vc_PURE 
bool isNotEmpty()
 const { 
return data.isNotEmpty(); }
 
  198     Vc_INTRINSIC Vc_PURE 
bool isEmpty()
 const { 
return data.isEmpty(); }
 
  199     Vc_INTRINSIC Vc_PURE 
bool isMix()
 const { 
return data.isMix(); }
 
  201     Vc_INTRINSIC Vc_PURE 
int shiftMask()
 const { 
return data.shiftMask(); }
 
  203     Vc_INTRINSIC Vc_PURE 
int toInt()
 const { 
return data.toInt(); }
 
  205     Vc_INTRINSIC Vc_PURE EntryReference operator[](
size_t index)
 
  209     Vc_INTRINSIC Vc_PURE 
bool operator[](
size_t index)
 const { 
return data[index]; }
 
  211     Vc_INTRINSIC Vc_PURE 
int count()
 const { 
return data.count(); }
 
  218     Vc_INTRINSIC Vc_PURE 
int firstOne()
 const { 
return data.firstOne(); }
 
  220     template <
typename G> 
static Vc_INTRINSIC SimdMaskArray generate(
const G &gen)
 
  222         return {mask_type::generate(gen)};
 
  225     Vc_INTRINSIC Vc_PURE SimdMaskArray 
shifted(
int amount)
 const 
  227         return {data.shifted(amount)};
 
  231     template <
typename Op, 
typename... Args>
 
  232     static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
 
  240     Vc_INTRINSIC SimdMaskArray(mask_type &&x) : data(
std::move(x)) {}
 
  243     void setEntry(
size_t index, 
bool x) { data.setEntry(index, x); }
 
  249 template <
typename T, std::
size_t N, 
typename VectorType> constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::Size;
 
  250 template <
typename T, std::
size_t N, 
typename VectorType>
 
  253 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t>
 
  256     ((Common::nextPowerOfTwo(N) * (sizeof(VectorType) / VectorType::size()) - 1) & 127) +
 
  260     static constexpr std::size_t N0 = Common::nextPowerOfTwo(N - N / 2);
 
  262     using Split = Common::Split<N0>;
 
  265     using storage_type0 = SimdMaskArray<T, N0>;
 
  266     using storage_type1 = SimdMaskArray<T, N - N0>;
 
  267     static_assert(storage_type0::size() == N0, 
"");
 
  269     using vector_type = VectorType;
 
  271     friend storage_type0 &internal_data0(SimdMaskArray &m) { 
return m.data0; }
 
  272     friend storage_type1 &internal_data1(SimdMaskArray &m) { 
return m.data1; }
 
  273     friend const storage_type0 &internal_data0(
const SimdMaskArray &m) { 
return m.data0; }
 
  274     friend const storage_type1 &internal_data1(
const SimdMaskArray &m) { 
return m.data1; }
 
  276     using mask_type = SimdMaskArray;
 
  277     static constexpr std::size_t size() { 
return N; }
 
  278     static constexpr std::size_t Size = size();
 
  279     static constexpr std::size_t MemoryAlignment =
 
  283     static_assert(Size == mask_type::Size, 
"size mismatch");
 
  285     using vectorentry_type = 
typename storage_type0::VectorEntryType;
 
  286     using vectorentry_reference = vectorentry_type &;
 
  287     using value_type = 
typename storage_type0::EntryType;
 
  288     using Mask = mask_type;
 
  289     using VectorEntryType = vectorentry_type;
 
  290     using EntryType = value_type;
 
  291     using EntryReference = 
typename std::conditional<
 
  292         std::is_same<
typename storage_type0::EntryReference,
 
  293                      typename storage_type1::EntryReference>::value,
 
  294         typename storage_type0::EntryReference, Common::MaskEntry<SimdMaskArray>>::type;
 
  295     using Vector = SimdArray<T, N, VectorType, VectorType::Size>;
 
  297     Vc_FREE_STORE_OPERATORS_ALIGNED(
alignof(mask_type))
 
  300     SimdMaskArray() = default;
 
  303     SimdMaskArray(const SimdMaskArray &) = default;
 
  304     SimdMaskArray(SimdMaskArray &&) = default;
 
  305     SimdMaskArray &operator=(const SimdMaskArray &) = default;
 
  306     SimdMaskArray &operator=(SimdMaskArray &&) = default;
 
  309     template <typename U, typename V>
 
  310     Vc_INTRINSIC SimdMaskArray(const SimdMaskArray<U, N, V> &rhs)
 
  311         : data0(Split::lo(rhs)), data1(Split::hi(rhs))
 
  316     template <
typename M, std::
size_t Pieces, std::
size_t Index>
 
  317     Vc_INTRINSIC SimdMaskArray(
 
  318         Common::Segment<M, Pieces, Index> &&rhs,
 
  319         enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg)
 
  320         : data0(Split::lo(rhs)), data1(Split::hi(rhs))
 
  325     template <
typename M>
 
  326     Vc_INTRINSIC SimdMaskArray(
 
  328         enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
 
  329                    Traits::simd_vector_size<M>::value == Size)> = nullarg)
 
  330         : data0(Split::lo(k)), data1(Split::hi(k))
 
  335     template <
typename M,
 
  336               typename = enable_if<Traits::is_simd_mask<M>::value &&
 
  337                                    !Traits::isSimdMaskArray<M>::value && M::size() == N>>
 
  343     Vc_INTRINSIC 
explicit SimdMaskArray(VectorSpecialInitializerOne one)
 
  344         : data0(one), data1(one)
 
  347     Vc_INTRINSIC 
explicit SimdMaskArray(VectorSpecialInitializerZero zero)
 
  348         : data0(zero), data1(zero)
 
  351     Vc_INTRINSIC 
explicit SimdMaskArray(
bool b) : data0(b), data1(b) {}
 
  356     template <
typename Flags = DefaultLoadTag>
 
  357     Vc_INTRINSIC 
explicit SimdMaskArray(
const bool *mem, Flags f = Flags())
 
  358         : data0(mem, f), data1(mem + storage_type0::size(), f)
 
  362     Vc_INTRINSIC 
void load(
const bool *mem)
 
  365         data1.load(mem + storage_type0::size());
 
  367     template <
typename Flags> Vc_INTRINSIC 
void load(
const bool *mem, Flags f)
 
  370         data1.load(mem + storage_type0::size(), f);
 
  373     Vc_INTRINSIC 
void store(
bool *mem)
 const 
  376         data1.store(mem + storage_type0::size());
 
  378     template <
typename Flags> Vc_INTRINSIC 
void store(
bool *mem, Flags f)
 const 
  381         data1.store(mem + storage_type0::size(), f);
 
  384     Vc_INTRINSIC Vc_PURE 
bool operator==(
const SimdMaskArray &rhs)
 const 
  386         return data0 == rhs.data0 && data1 == rhs.data1;
 
  388     Vc_INTRINSIC Vc_PURE 
bool operator!=(
const SimdMaskArray &rhs)
 const 
  390         return data0 != rhs.data0 || data1 != rhs.data1;
 
  393     Vc_INTRINSIC Vc_PURE SimdMaskArray operator!()
 const 
  395         return {!data0, !data1};
 
  398     Vc_INTRINSIC SimdMaskArray &operator&=(
const SimdMaskArray &rhs)
 
  404     Vc_INTRINSIC SimdMaskArray &operator|=(
const SimdMaskArray &rhs)
 
  410     Vc_INTRINSIC SimdMaskArray &operator^=(
const SimdMaskArray &rhs)
 
  417     Vc_INTRINSIC Vc_PURE SimdMaskArray operator&(
const SimdMaskArray &rhs)
 const 
  419         return {data0 & rhs.data0, data1 & rhs.data1};
 
  421     Vc_INTRINSIC Vc_PURE SimdMaskArray operator|(
const SimdMaskArray &rhs)
 const 
  423         return {data0 | rhs.data0, data1 | rhs.data1};
 
  425     Vc_INTRINSIC Vc_PURE SimdMaskArray operator^(
const SimdMaskArray &rhs)
 const 
  427         return {data0 ^ rhs.data0, data1 ^ rhs.data1};
 
  430     Vc_INTRINSIC Vc_PURE SimdMaskArray operator&&(
const SimdMaskArray &rhs)
 const 
  432         return {data0 && rhs.data0, data1 && rhs.data1};
 
  434     Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(
const SimdMaskArray &rhs)
 const 
  436         return {data0 || rhs.data0, data1 || rhs.data1};
 
  439     Vc_INTRINSIC Vc_PURE 
bool isFull()
 const { 
return data0.isFull() && data1.isFull(); }
 
  440     Vc_INTRINSIC Vc_PURE 
bool isNotEmpty()
 const { 
return data0.isNotEmpty() || data1.isNotEmpty(); }
 
  441     Vc_INTRINSIC Vc_PURE 
bool isEmpty()
 const { 
return data0.isEmpty() && data1.isEmpty(); }
 
  442     Vc_INTRINSIC Vc_PURE 
bool isMix()
 const { 
return !isFull() && !isEmpty(); }
 
  444     Vc_INTRINSIC Vc_PURE 
int toInt()
 const 
  446         return data0.toInt() | (data1.toInt() << data0.size());
 
  450     template <
typename R>
 
  453         enable_if<std::is_same<R, typename storage_type0::EntryReference>::value> =
 
  456         if (index < storage_type0::size()) {
 
  459             return data1[index - storage_type0::size()];
 
  462     template <
typename R>
 
  465         enable_if<!std::is_same<R, typename storage_type0::EntryReference>::value> =
 
  468         return {*
this, index};
 
  473     void setEntry(
size_t index, 
bool x)
 
  475         if (index < data0.size()) {
 
  476             data0.setEntry(index, x);
 
  478             data1.setEntry(index - data0.size(), x);
 
  482     Vc_INTRINSIC Vc_PURE EntryReference operator[](
size_t index) {
 
  483         return subscript_impl<EntryReference>(index);
 
  485     Vc_INTRINSIC Vc_PURE 
bool operator[](
size_t index)
 const {
 
  486         if (index < storage_type0::size()) {
 
  489             return data1[index - storage_type0::size()];
 
  493     Vc_INTRINSIC Vc_PURE 
int count()
 const { 
return data0.count() + data1.count(); }
 
  495     Vc_INTRINSIC Vc_PURE 
int firstOne()
 const {
 
  496         if (data0.isEmpty()) {
 
  497             return data1.firstOne() + storage_type0::size();
 
  499         return data0.firstOne();
 
  502     template <
typename G> 
static Vc_INTRINSIC SimdMaskArray generate(
const G &gen)
 
  504         return {storage_type0::generate(gen),
 
  505                 storage_type1::generate([&](std::size_t i) { 
return gen(i + N0); })};
 
  508     inline Vc_PURE SimdMaskArray 
shifted(
int amount)
 const 
  510         if (Vc_IS_UNLIKELY(amount == 0)) {
 
  515             for (
int i = 0; i < int(Size) + amount; ++i) {
 
  516                 r[i - amount] = operator[](i);
 
  519             for (
int i = 0; i < int(Size) - amount; ++i) {
 
  520                 r[i] = operator[](i + amount);
 
  527     template <
typename Op, 
typename... Args>
 
  528     static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
 
  531             storage_type0::fromOperation(op, Split::lo(args)...),  
 
  534             storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
 
  539     Vc_INTRINSIC SimdMaskArray(storage_type0 &&x, storage_type1 &&y)
 
  540         : data0(
std::move(x)), data1(
std::move(y))
 
  548 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t M> constexpr std::size_t SimdMaskArray<T, N, VectorType, M>::Size;
 
  549 template <
typename T, std::
size_t N, 
typename VectorType, std::
size_t M>