Vc 1.4.5
SIMD Vector Classes for C++
 
Loading...
Searching...
No Matches
simdmaskarray.h
1/* This file is part of the Vc library. {{{
2Copyright © 2013-2015 Matthias Kretz <kretz@kde.org>
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the names of contributing organizations nor the
12 names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
14
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26}}}*/
27
28#ifndef VC_COMMON_SIMDMASKARRAY_H_
29#define VC_COMMON_SIMDMASKARRAY_H_
30
31#include <type_traits>
32#include <array>
33#include "simdarrayhelper.h"
34#include "utility.h"
35#include "maskbool.h"
36
37#include "macros.h"
38
39namespace Vc_VERSIONED_NAMESPACE
40{
43// atomic SimdMaskArray {{{1
53template <typename T, std::size_t N, typename VectorType_>
54class SimdMaskArray<T, N, VectorType_, N>
55{
56public:
57 using VectorType = VectorType_;
58 using vector_type = VectorType;
59 using mask_type = typename vector_type::Mask;
60 using storage_type = mask_type;
61
62 friend storage_type &internal_data(SimdMaskArray &m) { return m.data; }
63 friend const storage_type &internal_data(const SimdMaskArray &m) { return m.data; }
64
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");
69
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>;
78
79 Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(mask_type));
80
81 // zero init
82 SimdMaskArray() = default;
83
84 // default copy ctor/operator
85 SimdMaskArray(const SimdMaskArray &) = default;
86 SimdMaskArray(SimdMaskArray &&) = default;
87 SimdMaskArray &operator=(const SimdMaskArray &) = default;
88 SimdMaskArray &operator=(SimdMaskArray &&) = default;
89
90 // broadcasts
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()}; }
96
97 // conversion (casts); implemented in simd_cast_caller.tcc
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)>,
101 class = U>
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;
106
107 // conversion from any Segment object (could be SimdMaskArray or Mask<T>)
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;
112
113 // conversion from Mask<T>
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;
118
119 // implicit conversion to Mask<U, AnyAbi> for if Mask<U, AnyAbi>::size() == N
120 template <class U, class A,
121 class = enable_if<Vc::Mask<U, A>::Size == N &&
122 !detail::is_fixed_size_abi<A>::value>>
123 operator Vc::Mask<U, A>() const
124 {
125 return simd_cast<Vc::Mask<U, A>>(data);
126 }
127 operator fixed_size_simd_mask<T, N> &()
128 {
129 return static_cast<fixed_size_simd_mask<T, N> &>(*this);
130 }
131 operator const fixed_size_simd_mask<T, N> &() const
132 {
133 return static_cast<const fixed_size_simd_mask<T, N> &>(*this);
134 }
135
136 // load/store (from/to bool arrays)
137 template <typename Flags = DefaultLoadTag>
138 Vc_INTRINSIC explicit SimdMaskArray(const bool *mem, Flags f = Flags())
139 : data(mem, f)
140 {
141 }
142
143 Vc_INTRINSIC void load(const bool *mem) { data.load(mem); }
144 template <typename Flags> Vc_INTRINSIC void load(const bool *mem, Flags f)
145 {
146 data.load(mem, f);
147 }
148
149 Vc_INTRINSIC void store(bool *mem) const { data.store(mem); }
150 template <typename Flags> Vc_INTRINSIC void store(bool *mem, Flags f) const
151 {
152 data.store(mem, f);
153 }
154
155 // compares
156 Vc_INTRINSIC Vc_PURE bool operator==(const SimdMaskArray &rhs) const
157 {
158 return data == rhs.data;
159 }
160 Vc_INTRINSIC Vc_PURE bool operator!=(const SimdMaskArray &rhs) const
161 {
162 return data != rhs.data;
163 }
164
165 // inversion
166 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator!() const
167 {
168 return {private_init, !data};
169 }
170
171 // binary operators
172 Vc_INTRINSIC SimdMaskArray &operator&=(const SimdMaskArray &rhs)
173 {
174 data &= rhs.data;
175 return *this;
176 }
177 Vc_INTRINSIC SimdMaskArray &operator|=(const SimdMaskArray &rhs)
178 {
179 data |= rhs.data;
180 return *this;
181 }
182 Vc_INTRINSIC SimdMaskArray &operator^=(const SimdMaskArray &rhs)
183 {
184 data ^= rhs.data;
185 return *this;
186 }
187
188 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator&(
189 const SimdMaskArray &rhs) const
190 {
191 return {private_init, data & rhs.data};
192 }
193 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator|(
194 const SimdMaskArray &rhs) const
195 {
196 return {private_init, data | rhs.data};
197 }
198 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator^(
199 const SimdMaskArray &rhs) const
200 {
201 return {private_init, data ^ rhs.data};
202 }
203
204 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator&&(
205 const SimdMaskArray &rhs) const
206 {
207 return {private_init, data && rhs.data};
208 }
209 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator||(
210 const SimdMaskArray &rhs) const
211 {
212 return {private_init, data || rhs.data};
213 }
214
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(); }
219
220 Vc_INTRINSIC Vc_PURE int shiftMask() const { return data.shiftMask(); }
221
222 Vc_INTRINSIC Vc_PURE int toInt() const { return data.toInt(); }
223
224private:
225 friend reference;
226 static Vc_INTRINSIC value_type get(const storage_type &k, int i) noexcept
227 {
228 return k[i];
229 }
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>()))
233 {
234 k[i] = std::forward<U>(v);
235 }
236
237public:
244 Vc_INTRINSIC Vc_PURE reference operator[](size_t index) noexcept
245 {
246 return {data, int(index)};
247 }
248 Vc_INTRINSIC Vc_PURE value_type operator[](size_t index) const noexcept
249 {
250 return data[index];
251 }
252
253 Vc_INTRINSIC Vc_PURE int count() const { return data.count(); }
254
260 Vc_INTRINSIC Vc_PURE int firstOne() const { return data.firstOne(); }
261
262 template <typename G>
263 static Vc_INTRINSIC fixed_size_simd_mask<T, N> generate(const G &gen)
264 {
265 return {private_init, mask_type::generate(gen)};
266 }
267
268 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> shifted(int amount) const
269 {
270 return {private_init, data.shifted(amount)};
271 }
272
274 template <typename Op, typename... Args>
275 static Vc_INTRINSIC fixed_size_simd_mask<T, N> fromOperation(Op op, Args &&... args)
276 {
277 fixed_size_simd_mask<T, N> r;
278 Common::unpackArgumentsAuto(op, r.data, std::forward<Args>(args)...);
279 return r;
280 }
281
283 Vc_INTRINSIC SimdMaskArray(private_init_t, mask_type &&x) : data(std::move(x)) {}
284
285private:
286 // The alignas attribute attached to the class declaration above is ignored by ICC
287 // 17.0.0 (at least). So just move the alignas attribute down here where it works for
288 // all compilers.
289 alignas(static_cast<std::size_t>(
290 Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * sizeof(VectorType_) /
291 VectorType_::size()>::value)) storage_type data;
292};
293
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;
297
298// generic SimdMaskArray {{{1
322template <typename T, size_t N, typename V, size_t Wt>
324{
325 static constexpr std::size_t N0 = Common::left_size<N>();
326
327 using Split = Common::Split<N0>;
328
329public:
331 using storage_type1 = fixed_size_simd_mask<T, N - N0>;
332 static_assert(storage_type0::size() == N0, "");
333
335
336 friend storage_type0 &internal_data0(SimdMaskArray &m) { return m.data0; }
337 friend storage_type1 &internal_data1(SimdMaskArray &m) { return m.data1; }
338 friend const storage_type0 &internal_data0(const SimdMaskArray &m) { return m.data0; }
339 friend const storage_type1 &internal_data1(const SimdMaskArray &m) { return m.data1; }
340
341 using mask_type = SimdMaskArray;
342
344 static constexpr std::size_t size() { return N; }
346 static constexpr std::size_t Size = size();
348 static constexpr std::size_t MemoryAlignment =
349 storage_type0::MemoryAlignment > storage_type1::MemoryAlignment
350 ? storage_type0::MemoryAlignment
351 : storage_type1::MemoryAlignment;
352 static_assert(Size == vector_type::Size, "size mismatch");
353
355 using vectorentry_type = typename storage_type0::VectorEntryType;
356
362 using VectorEntryType = vectorentry_type;
366 using EntryReference = Vc::Detail::ElementReference<SimdMaskArray>;
367 using reference = EntryReference;
370
371 Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(mask_type));
372
373 // zero init
375 SimdMaskArray() = default;
376
377 // default copy ctor/operator
378 SimdMaskArray(const SimdMaskArray &) = default;
379 SimdMaskArray(SimdMaskArray &&) = default;
380 SimdMaskArray &operator=(const SimdMaskArray &) = default;
381 SimdMaskArray &operator=(SimdMaskArray &&) = default;
382
383 // implicit conversion from SimdMaskArray with same N
384 template <typename U, typename W>
385 Vc_INTRINSIC SimdMaskArray(const SimdMaskArray<U, N, W> &rhs)
386 : data0(Split::lo(rhs)), data1(Split::hi(rhs))
387 {
388 }
389
390 // conversion from any Segment object (could be SimdMaskArray or Mask<T>)
391 template <typename M, std::size_t Pieces, std::size_t Index>
392 Vc_INTRINSIC SimdMaskArray(
393 Common::Segment<M, Pieces, Index> &&rhs,
394 enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg)
395 : data0(Split::lo(rhs)), data1(Split::hi(rhs))
396 {
397 }
398
399 // conversion from Mask<T>
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))
404 {
405 }
406
407 // implicit conversion to Mask<U, AnyAbi> for if Mask<U, AnyAbi>::size() == N
408 template <class U, class A,
409 class = enable_if<Vc::Mask<U, A>::Size == N &&
410 !detail::is_fixed_size_abi<A>::value>>
411 operator Vc::Mask<U, A>() const
412 {
413 return simd_cast<Vc::Mask<U, A>>(data0, data1);
414 }
415 Vc_INTRINSIC operator fixed_size_simd_mask<T, N> &()
416 {
417 return static_cast<fixed_size_simd_mask<T, N> &>(*this);
418 }
419 Vc_INTRINSIC operator const fixed_size_simd_mask<T, N> &() const
420 {
421 return static_cast<const fixed_size_simd_mask<T, N> &>(*this);
422 }
423
425 Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerOne one)
426 : data0(one), data1(one)
427 {
428 }
430 Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerZero zero)
431 : data0(zero), data1(zero)
432 {
433 }
435 Vc_INTRINSIC explicit SimdMaskArray(bool b) : data0(b), data1(b) {}
436
438 Vc_INTRINSIC static fixed_size_simd_mask<T, N> Zero()
439 {
440 return {storage_type0::Zero(), storage_type1::Zero()};
441 }
443 Vc_INTRINSIC static fixed_size_simd_mask<T, N> One()
444 {
445 return {storage_type0::One(), storage_type1::One()};
446 }
447
450
457 template <typename Flags = DefaultLoadTag>
458 Vc_INTRINSIC explicit SimdMaskArray(const bool *mem, Flags f = Flags())
459 : data0(mem, f), data1(mem + storage_type0::size(), f)
460 {
461 }
462
468 Vc_INTRINSIC void load(const bool *mem)
469 {
470 data0.load(mem);
471 data1.load(mem + storage_type0::size());
472 }
473
480 template <typename Flags> Vc_INTRINSIC void load(const bool *mem, Flags f)
481 {
482 data0.load(mem, f);
483 data1.load(mem + storage_type0::size(), f);
484 }
485
491 Vc_INTRINSIC void store(bool *mem) const
492 {
493 data0.store(mem);
494 data1.store(mem + storage_type0::size());
495 }
496
503 template <typename Flags> Vc_INTRINSIC void store(bool *mem, Flags f) const
504 {
505 data0.store(mem, f);
506 data1.store(mem + storage_type0::size(), f);
507 }
509
511 Vc_INTRINSIC Vc_PURE bool operator==(const SimdMaskArray &mask) const
512 {
513 return data0 == mask.data0 && data1 == mask.data1;
514 }
516 Vc_INTRINSIC Vc_PURE bool operator!=(const SimdMaskArray &mask) const
517 {
518 return data0 != mask.data0 || data1 != mask.data1;
519 }
520
522 Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator!() const
523 {
524 return {!data0, !data1};
525 }
526
528 Vc_INTRINSIC SimdMaskArray &operator&=(const SimdMaskArray &rhs)
529 {
530 data0 &= rhs.data0;
531 data1 &= rhs.data1;
532 return *this;
533 }
535 Vc_INTRINSIC SimdMaskArray &operator|=(const SimdMaskArray &rhs)
536 {
537 data0 |= rhs.data0;
538 data1 |= rhs.data1;
539 return *this;
540 }
542 Vc_INTRINSIC SimdMaskArray &operator^=(const SimdMaskArray &rhs)
543 {
544 data0 ^= rhs.data0;
545 data1 ^= rhs.data1;
546 return *this;
547 }
548
551 const SimdMaskArray &rhs) const
552 {
553 return {data0 & rhs.data0, data1 & rhs.data1};
554 }
557 const SimdMaskArray &rhs) const
558 {
559 return {data0 | rhs.data0, data1 | rhs.data1};
560 }
563 const SimdMaskArray &rhs) const
564 {
565 return {data0 ^ rhs.data0, data1 ^ rhs.data1};
566 }
567
570 const SimdMaskArray &rhs) const
571 {
572 return {data0 && rhs.data0, data1 && rhs.data1};
573 }
576 const SimdMaskArray &rhs) const
577 {
578 return {data0 || rhs.data0, data1 || rhs.data1};
579 }
580
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(); }
589
591 Vc_INTRINSIC Vc_PURE int toInt() const
592 {
593 return data0.toInt() | (data1.toInt() << data0.size());
594 }
595
596private:
597 friend reference;
598 static Vc_INTRINSIC value_type get(const SimdMaskArray &o, int i) noexcept
599 {
600 if (i < int(o.data0.size())) {
601 return o.data0[i];
602 } else {
603 return o.data1[i - o.data0.size()];
604 }
605 }
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>()))
610 {
611 if (i < int(o.data0.size())) {
612 o.data0[i] = std::forward<U>(v);
613 } else {
614 o.data1[i - o.data0.size()] = std::forward<U>(v);
615 }
616 }
617
618public:
627 Vc_INTRINSIC Vc_PURE reference operator[](size_t index) noexcept
628 {
629 return {*this, int(index)};
630 }
639 Vc_INTRINSIC Vc_PURE value_type operator[](size_t index) const noexcept
640 {
641 return get(*this, index);
642 }
643
645 Vc_INTRINSIC Vc_PURE int count() const { return data0.count() + data1.count(); }
646
648 Vc_INTRINSIC Vc_PURE int firstOne() const {
649 if (data0.isEmpty()) {
650 return data1.firstOne() + storage_type0::size();
651 }
652 return data0.firstOne();
653 }
654
656 template <typename G>
657 static Vc_INTRINSIC fixed_size_simd_mask<T, N> generate(const G &gen)
658 {
659 return {storage_type0::generate(gen),
660 storage_type1::generate([&](std::size_t i) { return gen(i + N0); })};
661 }
662
664 inline Vc_PURE fixed_size_simd_mask<T, N> shifted(int amount) const
665 {
666 if (Vc_IS_UNLIKELY(amount == 0)) {
667 return *this;
668 }
669 return generate([&](unsigned i) {
670 // modulo arithmetic of unsigned makes the check for j >= 0 unnecessary
671 const unsigned j = i + amount;
672 return j < size() ? get(*this, j) : false;
673 });
674 }
675
677 template <typename Op, typename... Args>
678 static Vc_INTRINSIC fixed_size_simd_mask<T, N> fromOperation(Op op, Args &&... args)
679 {
681 storage_type0::fromOperation(op, Split::lo(args)...), // no forward here - it
682 // could move and thus
683 // break the next line
684 storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
685 return r;
686 }
687
689 Vc_INTRINSIC SimdMaskArray(storage_type0 &&x, storage_type1 &&y)
690 : data0(std::move(x)), data1(std::move(y))
691 {
692 }
693
694private:
695 // The alignas attribute attached to the class declaration above is ignored by ICC
696 // 17.0.0 (at least). So just move the alignas attribute down here where it works for
697 // all compilers.
698 alignas(static_cast<std::size_t>(
699 Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * sizeof(V) /
700 V::size()>::value)) storage_type0 data0;
701 storage_type1 data1;
702};
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;
707
710
711} // namespace Vc
712
713// XXX: this include should be in <Vc/vector.h>. But at least clang 3.4 then fails to compile the
714// code. Not sure yet what is going on, but it looks a lot like a bug in clang.
715#include "simd_cast_caller.tcc"
716
717#endif // VC_COMMON_SIMDMASKARRAY_H_
718
719// vim: foldmethod=marker
The main SIMD mask class.
Definition mask.h:42
typename VectorTraits< T, Abi >::VectorEntryType VectorEntryType
The VectorEntryType, in contrast to EntryType, reveals information about the SIMD implementation.
Definition mask.h:88
bool EntryType
The EntryType of masks is always bool, independent of T.
Definition mask.h:74
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.
Definition vector.h:126
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.
Definition simdize.h:1069
constexpr VectorSpecialInitializerOne One
The special object Vc::One can be used to construct Vector and Mask objects initialized to one/true.
Definition types.h:86
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
Definition types.h:81
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
Definition vector.h:215
The value member will either be the number of SIMD vector entries or 0 if T is not a SIMD type.