28#ifndef VC_COMMON_SIMDMASKARRAY_H_ 
   29#define VC_COMMON_SIMDMASKARRAY_H_ 
   33#include "simdarrayhelper.h" 
   39namespace Vc_VERSIONED_NAMESPACE
 
   53template <
typename T, std::
size_t N, 
typename VectorType_>
 
   54class SimdMaskArray<T, N, VectorType_, N>
 
   57    using VectorType = VectorType_;
 
   58    using vector_type = VectorType;
 
   59    using mask_type = 
typename vector_type::Mask;
 
   60    using storage_type = mask_type;
 
   62    friend storage_type &internal_data(SimdMaskArray &m) { 
return m.data; }
 
   63    friend const storage_type &internal_data(
const SimdMaskArray &m) { 
return m.data; }
 
   65    static constexpr std::size_t size() { 
return N; }
 
   66    static constexpr std::size_t Size = size();
 
   67    static constexpr std::size_t 
MemoryAlignment = storage_type::MemoryAlignment;
 
   68    static_assert(Size == vector_type::Size, 
"size mismatch");
 
   70    using vectorentry_type = 
typename mask_type::VectorEntryType;
 
   71    using value_type = 
typename mask_type::EntryType;
 
   72    using Mask = mask_type;
 
   73    using VectorEntryType = vectorentry_type;
 
   74    using EntryType = value_type;
 
   75    using EntryReference = Vc::Detail::ElementReference<storage_type, SimdMaskArray>;
 
   76    using reference = EntryReference;
 
   77    using Vector = fixed_size_simd<T, N>;
 
   79    Vc_FREE_STORE_OPERATORS_ALIGNED(
alignof(mask_type));
 
   82    SimdMaskArray() = 
default;
 
   85    SimdMaskArray(
const SimdMaskArray &) = 
default;
 
   86    SimdMaskArray(SimdMaskArray &&) = 
default;
 
   87    SimdMaskArray &operator=(
const SimdMaskArray &) = 
default;
 
   88    SimdMaskArray &operator=(SimdMaskArray &&) = 
default;
 
   91    Vc_INTRINSIC 
explicit SimdMaskArray(VectorSpecialInitializerOne one) : data(one) {}
 
   92    Vc_INTRINSIC 
explicit SimdMaskArray(VectorSpecialInitializerZero zero) : data(zero) {}
 
   93    Vc_INTRINSIC 
explicit SimdMaskArray(
bool b) : data(b) {}
 
   94    Vc_INTRINSIC 
static SimdMaskArray 
Zero() { 
return {private_init, storage_type::Zero()}; }
 
   95    Vc_INTRINSIC 
static SimdMaskArray 
One() { 
return {private_init, storage_type::One()}; }
 
   98    template <
class U, 
class V, 
class = enable_if<N == V::Size>>
 
   99    Vc_INTRINSIC_L SimdMaskArray(
const SimdMaskArray<U, N, V> &x) Vc_INTRINSIC_R;
 
  100    template <
class U, 
class V, 
class = enable_if<(N > V::Size && N <= 2 * V::Size)>,
 
  102    Vc_INTRINSIC_L SimdMaskArray(
const SimdMaskArray<U, N, V> &x) Vc_INTRINSIC_R;
 
  103    template <
class U, 
class V, 
class = enable_if<(N > 2 * V::Size && N <= 4 * V::Size)>,
 
  104              class = U, 
class = U>
 
  105    Vc_INTRINSIC_L SimdMaskArray(
const SimdMaskArray<U, N, V> &x) Vc_INTRINSIC_R;
 
  108    template <
typename M, std::
size_t Pieces, std::
size_t Index>
 
  109    Vc_INTRINSIC_L SimdMaskArray(
 
  110        Common::Segment<M, Pieces, Index> &&x,
 
  111        enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg) Vc_INTRINSIC_R;
 
  114    template <
class M, 
class = enable_if<(Traits::is_simd_mask<M>::value &&
 
  115                                          !Traits::isSimdMaskArray<M>::value &&
 
  116                                          Traits::simd_vector_size<M>::value == Size)>>
 
  117    Vc_INTRINSIC_L SimdMaskArray(M k) Vc_INTRINSIC_R;
 
  120    template <
class U, 
class A,
 
  121              class = enable_if<Vc::Mask<U, A>::Size == N &&
 
  122                                !detail::is_fixed_size_abi<A>::value>>
 
  125        return simd_cast<Vc::Mask<U, A>>(data);
 
  127    operator fixed_size_simd_mask<T, N> &()
 
  129        return static_cast<fixed_size_simd_mask<T, N> &
>(*this);
 
  131    operator const fixed_size_simd_mask<T, N> &() 
const 
  133        return static_cast<const fixed_size_simd_mask<T, N> &
>(*this);
 
  137    template <
typename Flags = DefaultLoadTag>
 
  138    Vc_INTRINSIC 
explicit SimdMaskArray(
const bool *mem, Flags f = Flags())
 
  143    Vc_INTRINSIC 
void load(
const bool *mem) { data.load(mem); }
 
  144    template <
typename Flags> Vc_INTRINSIC 
void load(
const bool *mem, Flags f)
 
  149    Vc_INTRINSIC 
void store(
bool *mem)
 const { data.store(mem); }
 
  150    template <
typename Flags> Vc_INTRINSIC 
void store(
bool *mem, Flags f)
 const 
  156    Vc_INTRINSIC Vc_PURE 
bool operator==(
const SimdMaskArray &rhs)
 const 
  158        return data == rhs.data;
 
  160    Vc_INTRINSIC Vc_PURE 
bool operator!=(
const SimdMaskArray &rhs)
 const 
  162        return data != rhs.data;
 
  166    Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator!()
 const 
  168        return {private_init, !data};
 
  172    Vc_INTRINSIC SimdMaskArray &operator&=(
const SimdMaskArray &rhs)
 
  177    Vc_INTRINSIC SimdMaskArray &operator|=(
const SimdMaskArray &rhs)
 
  182    Vc_INTRINSIC SimdMaskArray &operator^=(
const SimdMaskArray &rhs)
 
  188    Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator&(
 
  189        const SimdMaskArray &rhs)
 const 
  191        return {private_init, data & rhs.data};
 
  193    Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator|(
 
  194        const SimdMaskArray &rhs)
 const 
  196        return {private_init, data | rhs.data};
 
  198    Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator^(
 
  199        const SimdMaskArray &rhs)
 const 
  201        return {private_init, data ^ rhs.data};
 
  204    Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator&&(
 
  205        const SimdMaskArray &rhs)
 const 
  207        return {private_init, data && rhs.data};
 
  209    Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator||(
 
  210        const SimdMaskArray &rhs)
 const 
  212        return {private_init, data || rhs.data};
 
  215    Vc_INTRINSIC Vc_PURE 
bool isFull()
 const { 
return data.isFull(); }
 
  216    Vc_INTRINSIC Vc_PURE 
bool isNotEmpty()
 const { 
return data.isNotEmpty(); }
 
  217    Vc_INTRINSIC Vc_PURE 
bool isEmpty()
 const { 
return data.isEmpty(); }
 
  218    Vc_INTRINSIC Vc_PURE 
bool isMix()
 const { 
return data.isMix(); }
 
  220    Vc_INTRINSIC Vc_PURE 
int shiftMask()
 const { 
return data.shiftMask(); }
 
  222    Vc_INTRINSIC Vc_PURE 
int toInt()
 const { 
return data.toInt(); }
 
  226    static Vc_INTRINSIC value_type get(
const storage_type &k, 
int i) 
noexcept 
  230    template <
typename U>
 
  231    static Vc_INTRINSIC 
void set(storage_type &k, 
int i, U &&v) 
noexcept(
 
  232        noexcept(std::declval<storage_type &>()[0] = std::declval<U>()))
 
  234        k[i] = std::forward<U>(v);
 
  244    Vc_INTRINSIC Vc_PURE reference operator[](
size_t index) 
noexcept 
  246        return {data, int(index)};
 
  248    Vc_INTRINSIC Vc_PURE value_type operator[](
size_t index) 
const noexcept 
  253    Vc_INTRINSIC Vc_PURE 
int count()
 const { 
return data.count(); }
 
  260    Vc_INTRINSIC Vc_PURE 
int firstOne()
 const { 
return data.firstOne(); }
 
  262    template <
typename G>
 
  263    static Vc_INTRINSIC fixed_size_simd_mask<T, N> generate(
const G &gen)
 
  265        return {private_init, mask_type::generate(gen)};
 
  268    Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> 
shifted(
int amount)
 const 
  270        return {private_init, data.shifted(amount)};
 
  274    template <
typename Op, 
typename... Args>
 
  275    static Vc_INTRINSIC fixed_size_simd_mask<T, N> fromOperation(Op op, Args &&... args)
 
  277        fixed_size_simd_mask<T, N> r;
 
  278        Common::unpackArgumentsAuto(op, r.data, std::forward<Args>(args)...);
 
  283    Vc_INTRINSIC SimdMaskArray(private_init_t, mask_type &&x) : data(std::move(x)) {}
 
  289    alignas(
static_cast<std::size_t
>(
 
  290        Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * 
sizeof(VectorType_) /
 
  291                                 VectorType_::size()>::value)) storage_type data;
 
  294template <
typename T, std::
size_t N, 
typename VectorType> 
constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::Size;
 
  295template <
typename T, std::
size_t N, 
typename VectorType>
 
  296constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::MemoryAlignment;
 
  322template <
typename T, 
size_t N, 
typename V, 
size_t Wt>
 
  325    static constexpr std::size_t N0 = Common::left_size<N>();
 
  327    using Split = Common::Split<N0>;
 
  332    static_assert(storage_type0::size() == N0, 
"");
 
  344    static constexpr std::size_t 
size() { 
return N; }
 
  346    static constexpr std::size_t Size = size();
 
  349        storage_type0::MemoryAlignment > storage_type1::MemoryAlignment
 
  350            ? storage_type0::MemoryAlignment
 
  351            : storage_type1::MemoryAlignment;
 
  352    static_assert(Size == vector_type::Size, 
"size mismatch");
 
  384    template <
typename U, 
typename W>
 
  386        : data0(Split::lo(rhs)), data1(Split::hi(rhs))
 
  391    template <
typename M, std::
size_t Pieces, std::
size_t Index>
 
  393        Common::Segment<M, Pieces, Index> &&rhs,
 
  395        : data0(Split::lo(rhs)), data1(Split::hi(rhs))
 
  400    template <
class M, 
class = enable_if<(Traits::is_simd_mask<M>::value &&
 
  401                                          !Traits::isSimdMaskArray<M>::value &&
 
  402                                          Traits::simd_vector_size<M>::value == Size)>>
 
  403    Vc_INTRINSIC SimdMaskArray(M k) : data0(Split::lo(k)), data1(Split::hi(k))
 
  408    template <
class U, 
class A,
 
  409              class = enable_if<Vc::Mask<U, A>::Size == N &&
 
  410                                !detail::is_fixed_size_abi<A>::value>>
 
  413        return simd_cast<Vc::Mask<U, A>>(data0, data1);
 
  415    Vc_INTRINSIC 
operator fixed_size_simd_mask<T, N> &()
 
  417        return static_cast<fixed_size_simd_mask<T, N> &
>(*this);
 
  419    Vc_INTRINSIC 
operator const fixed_size_simd_mask<T, N> &() 
const 
  421        return static_cast<const fixed_size_simd_mask<T, N> &
>(*this);
 
  426        : data0(one), data1(one)
 
 
  431        : data0(zero), data1(zero)
 
 
  440        return {storage_type0::Zero(), storage_type1::Zero()};
 
 
  445        return {storage_type0::One(), storage_type1::One()};
 
 
  457    template <
typename Flags = DefaultLoadTag>
 
  468    Vc_INTRINSIC 
void load(
const bool *mem)
 
  471        data1.load(mem + storage_type0::size());
 
 
  480    template <
typename Flags> Vc_INTRINSIC 
void load(
const bool *mem, Flags f)
 
  483        data1.load(mem + storage_type0::size(), f);
 
 
  491    Vc_INTRINSIC 
void store(
bool *mem)
 const 
  494        data1.store(mem + storage_type0::size());
 
 
  503    template <
typename Flags> Vc_INTRINSIC 
void store(
bool *mem, Flags f)
 const 
  506        data1.store(mem + storage_type0::size(), f);
 
 
  513        return data0 == mask.data0 && data1 == mask.data1;
 
 
  518        return data0 != mask.data0 || data1 != mask.data1;
 
 
  524        return {!data0, !data1};
 
 
  553        return {data0 & rhs.data0, data1 & rhs.data1};
 
 
  559        return {data0 | rhs.data0, data1 | rhs.data1};
 
 
  565        return {data0 ^ rhs.data0, data1 ^ rhs.data1};
 
 
  572        return {data0 && rhs.data0, data1 && rhs.data1};
 
 
  578        return {data0 || rhs.data0, data1 || rhs.data1};
 
 
  582    Vc_INTRINSIC Vc_PURE 
bool isFull()
 const { 
return data0.isFull() && data1.isFull(); }
 
  584    Vc_INTRINSIC Vc_PURE 
bool isNotEmpty()
 const { 
return data0.isNotEmpty() || data1.isNotEmpty(); }
 
  586    Vc_INTRINSIC Vc_PURE 
bool isEmpty()
 const { 
return data0.isEmpty() && data1.isEmpty(); }
 
  588    Vc_INTRINSIC Vc_PURE 
bool isMix()
 const { 
return !isFull() && !isEmpty(); }
 
  591    Vc_INTRINSIC Vc_PURE 
int toInt()
 const 
  593        return data0.toInt() | (data1.toInt() << data0.size());
 
 
  598    static Vc_INTRINSIC value_type get(
const SimdMaskArray &o, 
int i) 
noexcept 
  600        if (i < 
int(o.data0.size())) {
 
  603            return o.data1[i - o.data0.size()];
 
  606    template <
typename U>
 
  607    static Vc_INTRINSIC 
void set(SimdMaskArray &o, 
int i, U &&v) 
noexcept(
 
  608        noexcept(std::declval<storage_type0 &>()[0] = std::declval<U>()) &&
 
  609        noexcept(std::declval<storage_type1 &>()[0] = std::declval<U>()))
 
  611        if (i < 
int(o.data0.size())) {
 
  612            o.data0[i] = std::forward<U>(v);
 
  614            o.data1[i - o.data0.size()] = std::forward<U>(v);
 
  627    Vc_INTRINSIC Vc_PURE reference 
operator[](
size_t index) 
noexcept 
  629        return {*
this, int(index)};
 
 
  641        return get(*
this, index);
 
 
  645    Vc_INTRINSIC Vc_PURE 
int count()
 const { 
return data0.count() + data1.count(); }
 
  649        if (data0.isEmpty()) {
 
  650            return data1.firstOne() + storage_type0::size();
 
  652        return data0.firstOne();
 
 
  656    template <
typename G>
 
  659        return {storage_type0::generate(gen),
 
  660                storage_type1::generate([&](std::size_t i) { 
return gen(i + N0); })};
 
 
  666        if (Vc_IS_UNLIKELY(amount == 0)) {
 
  669        return generate([&](
unsigned i) {
 
  671            const unsigned j = i + amount;
 
  672            return j < size() ? get(*
this, j) : 
false;
 
 
  677    template <
typename Op, 
typename... Args>
 
  681            storage_type0::fromOperation(op, Split::lo(args)...),  
 
  684            storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
 
  689    Vc_INTRINSIC SimdMaskArray(storage_type0 &&x, storage_type1 &&y)
 
  690        : data0(std::move(x)), data1(std::move(y))
 
  698    alignas(
static_cast<std::size_t
>(
 
  699        Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * 
sizeof(V) /
 
  700                                 V::size()>::value)) storage_type0 data0;
 
 
  703template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
  704constexpr std::size_t SimdMaskArray<T, N, V, M>::Size;
 
  705template <
typename T, std::
size_t N, 
typename V, std::
size_t M>
 
  706constexpr std::size_t SimdMaskArray<T, N, V, M>::MemoryAlignment;
 
  715#include "simd_cast_caller.tcc" 
The main SIMD mask class.
 
typename VectorTraits< T, Abi >::VectorEntryType VectorEntryType
The VectorEntryType, in contrast to EntryType, reveals information about the SIMD implementation.
 
bool EntryType
The EntryType of masks is always bool, independent of T.
 
Data-parallel mask type with user-defined number of boolean elements.
 
fixed_size_simd_mask< T, N > operator&(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary AND to mask.
 
SimdMaskArray(bool b)
Broadcast constructor.
 
void store(bool *mem) const
Store N boolean values to the consecutive addresses starting at mem.
 
int count() const
Returns how many components of the mask are true.
 
typename storage_type0::EntryType value_type
The EntryType of masks is always bool, independent of T.
 
SimdMaskArray & operator|=(const SimdMaskArray &rhs)
Modifies the mask using an OR operation with mask.
 
static fixed_size_simd_mask< T, N > Zero()
Creates a new mask object initialized to zero/false.
 
bool isMix() const
Returns !isFull() && !isEmpty().
 
fixed_size_simd_mask< T, N > operator^(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary XOR to mask.
 
bool isNotEmpty() const
Returns a logical OR of all components.
 
static fixed_size_simd_mask< T, N > One()
Creates a mask object initialized to one/true.
 
vectorentry_type VectorEntryType
The VectorEntryType, in contrast to EntryType, reveals information about the SIMD implementation.
 
bool operator!=(const SimdMaskArray &mask) const
Returns whether the two masks are different in at least one component.
 
void load(const bool *mem)
Load N boolean values from the consecutive addresses starting at mem.
 
SimdMaskArray(const bool *mem, Flags f=Flags())
Load N boolean values from the consecutive addresses starting at mem.
 
static constexpr std::size_t size()
Returns the number of boolean components (  ) in a mask of this type.
 
fixed_size_simd_mask< T, N > operator&&(const SimdMaskArray &rhs) const
Returns the component-wise application of a logical AND to mask.
 
value_type operator[](size_t index) const noexcept
Return a copy of the boolean element at index index.
 
SimdMaskArray(VectorSpecialInitializerOne one)
Initialize the new mask object to one (true).
 
Vc::Detail::ElementReference< SimdMaskArray > EntryReference
The reference wrapper type used for accessing individual mask components.
 
fixed_size_simd_mask< T, N > operator||(const SimdMaskArray &rhs) const
Returns the component-wise application of a logical OR to mask.
 
SimdMaskArray & operator^=(const SimdMaskArray &rhs)
Modifies the mask using an XOR operation with mask.
 
int toInt() const
Convert the boolean components of the mask into bits of an integer.
 
static fixed_size_simd_mask< T, N > generate(const G &gen)
Generate a mask object from booleans returned from the function gen.
 
fixed_size_simd_mask< T, N > operator!() const
Returns a mask with inverted components.
 
void store(bool *mem, Flags f) const
Store N boolean values to the consecutive addresses starting at mem.
 
void load(const bool *mem, Flags f)
Load N boolean values from the consecutive addresses starting at mem.
 
fixed_size_simd_mask< T, N > shifted(int amount) const
Returns a mask with components shifted by amount places.
 
SimdMaskArray()=default
Construct a zero-initialized vector object.
 
bool isEmpty() const
Returns true if components are false, false otherwise.
 
int firstOne() const
Returns the index of the first one in the mask.
 
bool isFull() const
Returns a logical AND of all components.
 
reference operator[](size_t index) noexcept
Return a smart reference to the boolean element at index index.
 
bool operator==(const SimdMaskArray &mask) const
Returns whether the two masks are equal in all components.
 
value_type EntryType
The EntryType of masks is always bool, independent of T.
 
SimdMaskArray & operator&=(const SimdMaskArray &rhs)
Modifies the mask using an AND operation with mask.
 
SimdMaskArray(VectorSpecialInitializerZero zero)
Zero-initialize the new mask object (false).
 
fixed_size_simd_mask< T, N > operator|(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary OR to mask.
 
The main vector class for expressing data parallelism.
 
Adapter< S, T, N > shifted(const Adapter< S, T, N > &a, int shift)
Returns a new vectorized object where each entry is shifted by shift.
 
constexpr VectorSpecialInitializerOne One
The special object Vc::One can be used to construct Vector and Mask objects initialized to one/true.
 
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
 
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
 
The value member will either be the number of SIMD vector entries or 0 if T is not a SIMD type.