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
54 template <
typename T, std::
size_t N,
typename VectorType_>
57 ((Common::nextPowerOfTwo(N) * (sizeof(VectorType_) / VectorType_::size()) - 1) & 127) +
59 1) SimdMaskArray<T, N, VectorType_, N>
62 using VectorType = VectorType_;
63 using vector_type = VectorType;
64 using mask_type =
typename vector_type::Mask;
65 using storage_type = mask_type;
67 friend storage_type &internal_data(SimdMaskArray &m) {
return m.data; }
68 friend const storage_type &internal_data(
const SimdMaskArray &m) {
return m.data; }
70 static constexpr std::size_t size() {
return N; }
71 static constexpr std::size_t Size = size();
73 static_assert(Size == mask_type::Size,
"size mismatch");
75 using vectorentry_type =
typename mask_type::VectorEntryType;
76 using vectorentry_reference = vectorentry_type &;
77 using value_type =
typename mask_type::EntryType;
78 using Mask = mask_type;
79 using VectorEntryType = vectorentry_type;
80 using EntryType = value_type;
81 using EntryReference =
typename mask_type::EntryReference;
82 using Vector = SimdArray<T, N, VectorType, N>;
84 Vc_FREE_STORE_OPERATORS_ALIGNED(
alignof(mask_type));
87 SimdMaskArray() =
default;
90 Vc_INTRINSIC
explicit SimdMaskArray(VectorSpecialInitializerOne one) : data(one) {}
91 Vc_INTRINSIC
explicit SimdMaskArray(VectorSpecialInitializerZero zero) : data(zero) {}
92 Vc_INTRINSIC
explicit SimdMaskArray(
bool b) : data(b) {}
97 template <
typename U,
typename V>
98 Vc_INTRINSIC_L SimdMaskArray(
const SimdMaskArray<U, N, V> &x,
99 enable_if<N == V::size()> = nullarg) Vc_INTRINSIC_R;
100 template <typename U, typename V>
101 Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
102 enable_if<(N > V::size() && N <= 2 * V::size())> = nullarg)
104 template <typename U, typename V>
105 Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
106 enable_if<(N > 2 * V::size() && N <= 4 * V::size())> = nullarg)
110 template <typename M,
std::
size_t Pieces,
std::
size_t Index>
111 Vc_INTRINSIC_L SimdMaskArray(
112 Common::Segment<M, Pieces, Index> &&x,
113 enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg) Vc_INTRINSIC_R;
116 template <typename M>
117 Vc_INTRINSIC_L SimdMaskArray(
119 enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
120 Traits::simd_vector_size<M>::value == Size)> = nullarg) Vc_INTRINSIC_R;
123 template <typename M,
124 typename = enable_if<Traits::is_simd_mask<M>::value &&
125 !Traits::isSimdMaskArray<M>::value && M::size() == N>>
132 template <
typename Flags = DefaultLoadTag>
133 Vc_INTRINSIC
explicit SimdMaskArray(
const bool *mem, Flags f = Flags())
138 Vc_INTRINSIC
void load(
const bool *mem) { data.load(mem); }
139 template <
typename Flags> Vc_INTRINSIC
void load(
const bool *mem, Flags f)
144 Vc_INTRINSIC
void store(
bool *mem)
const { data.store(mem); }
145 template <
typename Flags> Vc_INTRINSIC
void store(
bool *mem, Flags f)
const
151 Vc_INTRINSIC Vc_PURE
bool operator==(
const SimdMaskArray &rhs)
const
153 return data == rhs.data;
155 Vc_INTRINSIC Vc_PURE
bool operator!=(
const SimdMaskArray &rhs)
const
157 return data != rhs.data;
161 Vc_INTRINSIC Vc_PURE SimdMaskArray operator!()
const
167 Vc_INTRINSIC SimdMaskArray &operator&=(
const SimdMaskArray &rhs)
172 Vc_INTRINSIC SimdMaskArray &operator|=(
const SimdMaskArray &rhs)
177 Vc_INTRINSIC SimdMaskArray &operator^=(
const SimdMaskArray &rhs)
183 Vc_INTRINSIC Vc_PURE SimdMaskArray
operator&(
const SimdMaskArray &rhs)
const
185 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 SimdMaskArray operator&&(
const SimdMaskArray &rhs)
const
198 return {data && rhs.data};
200 Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(
const SimdMaskArray &rhs)
const
202 return {data || rhs.data};
205 Vc_INTRINSIC Vc_PURE
bool isFull()
const {
return data.isFull(); }
206 Vc_INTRINSIC Vc_PURE
bool isNotEmpty()
const {
return data.isNotEmpty(); }
207 Vc_INTRINSIC Vc_PURE
bool isEmpty()
const {
return data.isEmpty(); }
208 Vc_INTRINSIC Vc_PURE
bool isMix()
const {
return data.isMix(); }
210 Vc_INTRINSIC Vc_PURE
int shiftMask()
const {
return data.shiftMask(); }
212 Vc_INTRINSIC Vc_PURE
int toInt()
const {
return data.toInt(); }
214 Vc_INTRINSIC Vc_PURE EntryReference operator[](
size_t index)
218 Vc_INTRINSIC Vc_PURE
bool operator[](
size_t index)
const {
return data[index]; }
220 Vc_INTRINSIC Vc_PURE
int count()
const {
return data.count(); }
227 Vc_INTRINSIC Vc_PURE
int firstOne()
const {
return data.firstOne(); }
229 template <
typename G>
static Vc_INTRINSIC SimdMaskArray generate(
const G &gen)
231 return {mask_type::generate(gen)};
234 Vc_INTRINSIC Vc_PURE SimdMaskArray
shifted(
int amount)
const
236 return {data.shifted(amount)};
240 template <
typename Op,
typename... Args>
241 static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
244 Common::unpackArgumentsAuto(op, r.data, std::forward<Args>(args)...);
249 Vc_INTRINSIC SimdMaskArray(mask_type &&x) : data(
std::move(x)) {}
252 void setEntry(
size_t index,
bool x) { data.setEntry(index, x); }
258 template <
typename T, std::
size_t N,
typename VectorType> constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::Size;
259 template <
typename T, std::
size_t N,
typename VectorType>
286 template <
typename T,
size_t N,
typename V,
size_t Wt>
287 class alignas(((Common::nextPowerOfTwo(N) * (sizeof(V) / V::size()) - 1) & 127) +
291 static constexpr std::size_t N0 = Common::nextPowerOfTwo(N - N / 2);
293 using Split = Common::Split<N0>;
296 using storage_type0 = SimdMaskArray<T, N0>;
297 using storage_type1 = SimdMaskArray<T, N - N0>;
298 static_assert(storage_type0::size() == N0,
"");
300 using vector_type = V;
302 friend storage_type0 &internal_data0(SimdMaskArray &m) {
return m.data0; }
303 friend storage_type1 &internal_data1(SimdMaskArray &m) {
return m.data1; }
304 friend const storage_type0 &internal_data0(
const SimdMaskArray &m) {
return m.data0; }
305 friend const storage_type1 &internal_data1(
const SimdMaskArray &m) {
return m.data1; }
310 static constexpr std::size_t size() {
return N; }
312 static constexpr std::size_t Size = size();
314 static constexpr std::size_t MemoryAlignment =
318 static_assert(Size == mask_type::Size,
"size mismatch");
321 using vectorentry_type =
typename storage_type0::VectorEntryType;
323 using vectorentry_reference = vectorentry_type &;
325 using value_type =
typename storage_type0::EntryType;
327 using MaskType = mask_type;
329 using VectorEntryType = vectorentry_type;
331 using EntryType = value_type;
336 typename storage_type0::EntryReference, Common::MaskEntry<SimdMaskArray>>::type;
340 Vc_FREE_STORE_OPERATORS_ALIGNED(
alignof(
mask_type));
353 template <
typename U,
typename W>
355 : data0(Split::lo(rhs)), data1(Split::hi(rhs))
360 template <
typename M, std::
size_t Pieces, std::
size_t Index>
362 Common::Segment<M, Pieces, Index> &&rhs,
364 : data0(Split::lo(rhs)), data1(Split::hi(rhs))
369 template <
typename M>
370 Vc_INTRINSIC SimdMaskArray(
372 enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
373 Traits::simd_vector_size<M>::value == Size)> = nullarg)
374 : data0(Split::lo(k)), data1(Split::hi(k))
379 template <
typename M,
380 typename = enable_if<Traits::is_simd_mask<M>::value &&
381 !Traits::isSimdMaskArray<M>::value && M::size() == N>>
388 Vc_INTRINSIC
explicit SimdMaskArray(VectorSpecialInitializerOne one)
389 : data0(one), data1(one)
393 Vc_INTRINSIC
explicit SimdMaskArray(VectorSpecialInitializerZero zero)
394 : data0(zero), data1(zero)
414 template <
typename Flags = DefaultLoadTag>
415 Vc_INTRINSIC
explicit SimdMaskArray(
const bool *mem, Flags f = Flags())
416 : data0(mem, f), data1(mem + storage_type0::size(), f)
425 Vc_INTRINSIC
void load(
const bool *mem)
428 data1.load(mem + storage_type0::size());
437 template <
typename Flags> Vc_INTRINSIC
void load(
const bool *mem, Flags f)
440 data1.load(mem + storage_type0::size(), f);
448 Vc_INTRINSIC
void store(
bool *mem)
const
451 data1.store(mem + storage_type0::size());
460 template <
typename Flags> Vc_INTRINSIC
void store(
bool *mem, Flags f)
const
463 data1.store(mem + storage_type0::size(), f);
468 Vc_INTRINSIC Vc_PURE
bool operator==(
const SimdMaskArray &mask)
const
470 return data0 == mask.data0 && data1 == mask.data1;
475 return data0 != mask.data0 || data1 != mask.data1;
481 return {!data0, !data1};
509 return {data0 & rhs.data0, data1 & rhs.data1};
512 Vc_INTRINSIC Vc_PURE SimdMaskArray
operator|(
const SimdMaskArray &rhs)
const
514 return {data0 | rhs.data0, data1 | rhs.data1};
517 Vc_INTRINSIC Vc_PURE SimdMaskArray
operator^(
const SimdMaskArray &rhs)
const
519 return {data0 ^ rhs.data0, data1 ^ rhs.data1};
525 return {data0 && rhs.data0, data1 && rhs.data1};
528 Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(
const SimdMaskArray &rhs)
const
530 return {data0 || rhs.data0, data1 || rhs.data1};
534 Vc_INTRINSIC Vc_PURE
bool isFull()
const {
return data0.isFull() && data1.isFull(); }
536 Vc_INTRINSIC Vc_PURE
bool isNotEmpty()
const {
return data0.isNotEmpty() || data1.isNotEmpty(); }
538 Vc_INTRINSIC Vc_PURE
bool isEmpty()
const {
return data0.isEmpty() && data1.isEmpty(); }
540 Vc_INTRINSIC Vc_PURE
bool isMix()
const {
return !isFull() && !isEmpty(); }
543 Vc_INTRINSIC Vc_PURE
int toInt()
const
545 return data0.toInt() | (data1.toInt() << data0.size());
549 template <
typename R>
552 enable_if<std::is_same<R, typename storage_type0::EntryReference>::value> =
555 if (index < storage_type0::size()) {
558 return data1[index - storage_type0::size()];
561 template <
typename R>
564 enable_if<!std::is_same<R, typename storage_type0::EntryReference>::value> =
567 return {*
this, index};
572 void setEntry(
size_t index,
bool x)
574 if (index < data0.size()) {
575 data0.setEntry(index, x);
577 data1.setEntry(index - data0.size(), x);
589 Vc_INTRINSIC Vc_PURE EntryReference operator[](
size_t index) {
590 return subscript_impl<EntryReference>(index);
600 Vc_INTRINSIC Vc_PURE
bool operator[](
size_t index)
const {
601 if (index < storage_type0::size()) {
604 return data1[index - storage_type0::size()];
609 Vc_INTRINSIC Vc_PURE
int count()
const {
return data0.count() + data1.count(); }
612 Vc_INTRINSIC Vc_PURE
int firstOne()
const {
613 if (data0.isEmpty()) {
614 return data1.firstOne() + storage_type0::size();
616 return data0.firstOne();
620 template <
typename G>
static Vc_INTRINSIC
SimdMaskArray generate(
const G &gen)
622 return {storage_type0::generate(gen),
623 storage_type1::generate([&](std::size_t i) {
return gen(i + N0); })};
629 if (Vc_IS_UNLIKELY(amount == 0)) {
634 for (
int i = 0; i < int(Size) + amount; ++i) {
635 r[i - amount] = operator[](i);
638 for (
int i = 0; i < int(Size) - amount; ++i) {
639 r[i] = operator[](i + amount);
646 template <
typename Op,
typename... Args>
647 static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
650 storage_type0::fromOperation(op, Split::lo(args)...),
653 storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
658 Vc_INTRINSIC SimdMaskArray(storage_type0 &&x, storage_type1 &&y)
659 : data0(
std::move(x)), data1(
std::move(y))
667 template <
typename T, std::
size_t N,
typename V, std::
size_t M>
668 constexpr std::size_t SimdMaskArray<T, N, V, M>::Size;
669 template <
typename T, std::
size_t N,
typename V, std::
size_t M>
679 #include "simd_cast_caller.tcc"
#endif // VC_COMMON_SIMDMASKARRAY_H_