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)
235 op(r.data, Common::actual_value(op, std::forward<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>