28 #ifndef VC_COMMON_SIMDMASKARRAY_H_ 29 #define VC_COMMON_SIMDMASKARRAY_H_ 31 #include <type_traits> 33 #include "simdarrayhelper.h" 39 namespace Vc_VERSIONED_NAMESPACE
53 template <
typename T, std::
size_t N,
typename VectorType_>
54 class 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();
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 = SimdArray<T, N, VectorType, N>;
79 Vc_FREE_STORE_OPERATORS_ALIGNED(
alignof(mask_type));
82 SimdMaskArray() =
default;
85 Vc_INTRINSIC
explicit SimdMaskArray(VectorSpecialInitializerOne one) : data(one) {}
86 Vc_INTRINSIC
explicit SimdMaskArray(VectorSpecialInitializerZero zero) : data(zero) {}
87 Vc_INTRINSIC
explicit SimdMaskArray(
bool b) : data(b) {}
92 template <
typename U,
typename V>
93 Vc_INTRINSIC_L SimdMaskArray(
const SimdMaskArray<U, N, V> &x,
94 enable_if<N == V::Size> = nullarg) Vc_INTRINSIC_R;
95 template <typename U, typename V>
96 Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
97 enable_if<(N > V::Size && N <= 2 * V::Size)> = nullarg)
99 template <typename U, typename V>
100 Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
101 enable_if<(N > 2 * V::Size && N <= 4 * V::Size)> = nullarg)
105 template <typename M,
std::
size_t Pieces,
std::
size_t Index>
106 Vc_INTRINSIC_L SimdMaskArray(
107 Common::Segment<M, Pieces, Index> &&x,
108 enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg) Vc_INTRINSIC_R;
111 template <typename M>
112 Vc_INTRINSIC_L SimdMaskArray(
114 enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
115 Traits::simd_vector_size<M>::value == Size)> = nullarg) Vc_INTRINSIC_R;
118 template <typename U, typename A, typename = enable_if<
Vc::Mask<U, A>::Size == N>>
119 operator
Vc::Mask<U, A>()
const 125 template <
typename Flags = DefaultLoadTag>
126 Vc_INTRINSIC
explicit SimdMaskArray(
const bool *mem, Flags f = Flags())
131 Vc_INTRINSIC
void load(
const bool *mem) { data.load(mem); }
132 template <
typename Flags> Vc_INTRINSIC
void load(
const bool *mem, Flags f)
137 Vc_INTRINSIC
void store(
bool *mem)
const { data.store(mem); }
138 template <
typename Flags> Vc_INTRINSIC
void store(
bool *mem, Flags f)
const 144 Vc_INTRINSIC Vc_PURE
bool operator==(
const SimdMaskArray &rhs)
const 146 return data == rhs.data;
148 Vc_INTRINSIC Vc_PURE
bool operator!=(
const SimdMaskArray &rhs)
const 150 return data != rhs.data;
154 Vc_INTRINSIC Vc_PURE SimdMaskArray operator!()
const 160 Vc_INTRINSIC SimdMaskArray &operator&=(
const SimdMaskArray &rhs)
165 Vc_INTRINSIC SimdMaskArray &operator|=(
const SimdMaskArray &rhs)
170 Vc_INTRINSIC SimdMaskArray &operator^=(
const SimdMaskArray &rhs)
176 Vc_INTRINSIC Vc_PURE SimdMaskArray
operator&(
const SimdMaskArray &rhs)
const 178 return {data & rhs.data};
180 Vc_INTRINSIC Vc_PURE SimdMaskArray
operator|(
const SimdMaskArray &rhs)
const 182 return {data | rhs.data};
184 Vc_INTRINSIC Vc_PURE SimdMaskArray
operator^(
const SimdMaskArray &rhs)
const 186 return {data ^ rhs.data};
189 Vc_INTRINSIC Vc_PURE SimdMaskArray operator&&(
const SimdMaskArray &rhs)
const 191 return {data && rhs.data};
193 Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(
const SimdMaskArray &rhs)
const 195 return {data || rhs.data};
198 Vc_INTRINSIC Vc_PURE
bool isFull()
const {
return data.isFull(); }
199 Vc_INTRINSIC Vc_PURE
bool isNotEmpty()
const {
return data.isNotEmpty(); }
200 Vc_INTRINSIC Vc_PURE
bool isEmpty()
const {
return data.isEmpty(); }
201 Vc_INTRINSIC Vc_PURE
bool isMix()
const {
return data.isMix(); }
203 Vc_INTRINSIC Vc_PURE
int shiftMask()
const {
return data.shiftMask(); }
205 Vc_INTRINSIC Vc_PURE
int toInt()
const {
return data.toInt(); }
209 static Vc_INTRINSIC value_type
get(
const storage_type &k,
int i) noexcept
213 template <
typename U>
214 static Vc_INTRINSIC
void set(storage_type &k,
int i, U &&v) noexcept(
215 noexcept(std::declval<storage_type &>()[0] = std::declval<U>()))
217 k[i] = std::forward<U>(v);
221 Vc_INTRINSIC Vc_PURE reference operator[](
size_t index) noexcept
223 return {data, int(index)};
225 Vc_INTRINSIC Vc_PURE value_type operator[](
size_t index)
const noexcept
230 Vc_INTRINSIC Vc_PURE
int count()
const {
return data.count(); }
237 Vc_INTRINSIC Vc_PURE
int firstOne()
const {
return data.firstOne(); }
239 template <
typename G>
static Vc_INTRINSIC SimdMaskArray generate(
const G &gen)
241 return {mask_type::generate(gen)};
244 Vc_INTRINSIC Vc_PURE SimdMaskArray
shifted(
int amount)
const 246 return {data.shifted(amount)};
250 template <
typename Op,
typename... Args>
251 static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
254 Common::unpackArgumentsAuto(op, r.data, std::forward<Args>(args)...);
259 Vc_INTRINSIC SimdMaskArray(mask_type &&x) : data(
std::move(x)) {}
265 alignas(
static_cast<std::size_t
>(
266 Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value *
sizeof(VectorType_) /
267 VectorType_::size()>::value)) storage_type data;
270 template <
typename T, std::
size_t N,
typename VectorType> constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::Size;
271 template <
typename T, std::
size_t N,
typename VectorType>
298 template <
typename T,
size_t N,
typename V,
size_t Wt>
301 static constexpr std::size_t N0 = Common::left_size<N>();
303 using Split = Common::Split<N0>;
306 using storage_type0 = SimdMaskArray<T, N0>;
307 using storage_type1 = SimdMaskArray<T, N - N0>;
308 static_assert(storage_type0::size() == N0,
"");
310 using vector_type = SimdArray<T, N>;
312 friend storage_type0 &internal_data0(SimdMaskArray &m) {
return m.data0; }
313 friend storage_type1 &internal_data1(SimdMaskArray &m) {
return m.data1; }
314 friend const storage_type0 &internal_data0(
const SimdMaskArray &m) {
return m.data0; }
315 friend const storage_type1 &internal_data1(
const SimdMaskArray &m) {
return m.data1; }
317 using mask_type = SimdMaskArray;
320 static constexpr std::size_t
size() {
return N; }
322 static constexpr std::size_t Size = size();
324 static constexpr std::size_t MemoryAlignment =
328 static_assert(Size == vector_type::Size,
"size mismatch");
360 template <
typename U,
typename W>
362 : data0(Split::lo(rhs)), data1(Split::hi(rhs))
367 template <
typename M, std::
size_t Pieces, std::
size_t Index>
369 Common::Segment<M, Pieces, Index> &&rhs,
371 : data0(Split::lo(rhs)), data1(Split::hi(rhs))
376 template <
typename M>
381 : data0(Split::lo(k)), data1(Split::hi(k))
386 template <typename U, typename A, typename = enable_if<Vc::Mask<U, A>::Size == N>>
394 : data0(one), data1(one)
399 : data0(zero), data1(zero)
419 template <
typename Flags = DefaultLoadTag>
430 Vc_INTRINSIC
void load(
const bool *mem)
433 data1.load(mem + storage_type0::size());
442 template <
typename Flags> Vc_INTRINSIC
void load(
const bool *mem, Flags f)
445 data1.load(mem + storage_type0::size(), f);
453 Vc_INTRINSIC
void store(
bool *mem)
const 456 data1.store(mem + storage_type0::size());
465 template <
typename Flags> Vc_INTRINSIC
void store(
bool *mem, Flags f)
const 468 data1.store(mem + storage_type0::size(), f);
475 return data0 == mask.data0 && data1 == mask.data1;
480 return data0 != mask.data0 || data1 != mask.data1;
486 return {!data0, !data1};
514 return {data0 & rhs.data0, data1 & rhs.data1};
519 return {data0 | rhs.data0, data1 | rhs.data1};
524 return {data0 ^ rhs.data0, data1 ^ rhs.data1};
530 return {data0 && rhs.data0, data1 && rhs.data1};
535 return {data0 || rhs.data0, data1 || rhs.data1};
539 Vc_INTRINSIC Vc_PURE
bool isFull()
const {
return data0.isFull() && data1.isFull(); }
541 Vc_INTRINSIC Vc_PURE
bool isNotEmpty()
const {
return data0.isNotEmpty() || data1.isNotEmpty(); }
543 Vc_INTRINSIC Vc_PURE
bool isEmpty()
const {
return data0.isEmpty() && data1.isEmpty(); }
545 Vc_INTRINSIC Vc_PURE
bool isMix()
const {
return !isFull() && !isEmpty(); }
548 Vc_INTRINSIC Vc_PURE
int toInt()
const 550 return data0.toInt() | (data1.toInt() << data0.size());
557 if (i <
int(o.data0.size())) {
560 return o.data1[i - o.data0.size()];
563 template <
typename U>
564 static Vc_INTRINSIC
void set(
SimdMaskArray &o,
int i, U &&v) noexcept(
565 noexcept(std::declval<storage_type0 &>()[0] = std::declval<U>()) &&
566 noexcept(std::declval<storage_type1 &>()[0] = std::declval<U>()))
568 if (i <
int(o.data0.size())) {
569 o.data0[i] = std::forward<U>(v);
571 o.data1[i - o.data0.size()] = std::forward<U>(v);
584 Vc_INTRINSIC Vc_PURE reference
operator[](
size_t index) noexcept
586 return {*
this, int(index)};
598 return get(*
this, index);
602 Vc_INTRINSIC Vc_PURE
int count()
const {
return data0.count() + data1.count(); }
606 if (data0.isEmpty()) {
607 return data1.firstOne() + storage_type0::size();
609 return data0.firstOne();
615 return {storage_type0::generate(gen),
616 storage_type1::generate([&](std::size_t i) {
return gen(i + N0); })};
622 if (Vc_IS_UNLIKELY(amount == 0)) {
625 return generate([&](
unsigned i) {
627 const unsigned j = i + amount;
628 return j < size() ?
get(*
this, j) :
false;
633 template <
typename Op,
typename... Args>
634 static Vc_INTRINSIC
SimdMaskArray fromOperation(Op op, Args &&... args)
637 storage_type0::fromOperation(op, Split::lo(args)...),
640 storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
646 : data0(std::move(x)), data1(std::move(y))
654 alignas(
static_cast<std::size_t
>(
655 Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value *
sizeof(V) /
659 template <
typename T, std::
size_t N,
typename V, std::
size_t M>
661 template <
typename T, std::
size_t N,
typename V, std::
size_t M>
671 #include "simd_cast_caller.tcc" 673 #endif // VC_COMMON_SIMDMASKARRAY_H_ bool operator!=(const SimdMaskArray &mask) const
Returns whether the two masks are different in at least one component.
bool isNotEmpty() const
Returns a logical OR of all components.
result_vector_type< L, R > operator|(L &&lhs, R &&rhs)
Applies | component-wise and concurrently.
result_vector_type< L, R > operator^(L &&lhs, R &&rhs)
Applies ^ component-wise and concurrently.
static SimdMaskArray One()
Creates a mask object initialized to one/true.
SimdMaskArray shifted(int amount) const
Returns a mask with components shifted by amount places.
reference operator[](size_t index) noexcept
Return a smart reference to the boolean element at index index.
typename storage_type0::EntryType value_type
The EntryType of masks is always bool, independent of T.
SimdMaskArray(const bool *mem, Flags f=Flags())
Load N boolean values from the consecutive addresses starting at mem.
SimdMaskArray(VectorSpecialInitializerZero zero)
Zero-initialize the new mask object (false).
int firstOne() const
Returns the index of the first one in the mask.
SimdMaskArray operator^(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary XOR to mask.
void load(const bool *mem, Flags f)
Load N boolean values from the consecutive addresses starting at mem.
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
SimdMaskArray & operator|=(const SimdMaskArray &rhs)
Modifies the mask using an OR operation with mask.
static SimdMaskArray Zero()
Creates a new mask object initialized to zero/false.
Identifies any possible SimdMaskArray<T, N> type (independent of const/volatile or reference) ...
bool isEmpty() const
Returns true if components are false, false otherwise.
SimdMaskArray operator&&(const SimdMaskArray &rhs) const
Returns the component-wise application of a logical AND to mask.
Data-parallel arithmetic type with user-defined number of elements.
The value member will either be the number of SIMD vector entries or 0 if T is not a SIMD type...
static constexpr std::size_t size()
Returns the number of boolean components ( ) in a mask of this type.
SimdMaskArray(VectorSpecialInitializerOne one)
Initialize the new mask object to one (true).
Data-parallel mask type with user-defined number of boolean elements.
SimdMaskArray & operator&=(const SimdMaskArray &rhs)
Modifies the mask using an AND operation with mask.
vectorentry_type VectorEntryType
The VectorEntryType, in contrast to EntryType, reveals information about the SIMD implementation...
SimdMaskArray operator!() const
Returns a mask with inverted components.
void load(const bool *mem)
Load N boolean values from the consecutive addresses starting at mem.
SimdMaskArray operator|(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary OR to mask.
SimdMaskArray operator||(const SimdMaskArray &rhs) const
Returns the component-wise application of a logical OR to mask.
void store(bool *mem, Flags f) const
Store N boolean values to the consecutive addresses starting at mem.
Vc::Detail::ElementReference< SimdMaskArray > EntryReference
The reference wrapper type used for accessing individual mask components.
value_type EntryType
The EntryType of masks is always bool, independent of T.
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
int toInt() const
Convert the boolean components of the mask into bits of an integer.
SimdMaskArray & operator^=(const SimdMaskArray &rhs)
Modifies the mask using an XOR operation with mask.
result_vector_type< L, R > operator&(L &&lhs, R &&rhs)
Applies & component-wise and concurrently.
The main SIMD mask class.
value_type operator[](size_t index) const noexcept
Return a copy of the boolean element at index index.
bool isFull() const
Returns a logical AND of all components.
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
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.
int count() const
Returns how many components of the mask are true.
Vector Classes Namespace.
constexpr VectorSpecialInitializerOne One
The special object Vc::One can be used to construct Vector and Mask objects initialized to one/true...
void store(bool *mem) const
Store N boolean values to the consecutive addresses starting at mem.
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
SimdMaskArray(bool b)
Broadcast constructor.
Identifies any SIMD mask type (independent of implementation or whether it's SimdMaskArray<T, N>).
bool operator==(const SimdMaskArray &mask) const
Returns whether the two masks are equal in all components.
SimdMaskArray operator&(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary AND to mask.
bool isMix() const
Returns !isFull() && !isEmpty().
static SimdMaskArray generate(const G &gen)
Generate a mask object from booleans returned from the function gen.