Vc  1.3.2-dev
SIMD Vector Classes for C++
simdmaskarray.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2013-2015 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, 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 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON 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
24 SOFTWARE, 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 
39 namespace Vc_VERSIONED_NAMESPACE
40 {
43 // atomic SimdMaskArray {{{1
53 template <typename T, std::size_t N, typename VectorType_>
54 class SimdMaskArray<T, N, VectorType_, N>
55 {
56 public:
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 = SimdArray<T, N, VectorType, N>;
78 
79  Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(mask_type));
80 
81  // zero init
82  SimdMaskArray() = default;
83 
84  // broadcasts
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) {}
88  Vc_INTRINSIC static SimdMaskArray Zero() { return {storage_type::Zero()}; }
89  Vc_INTRINSIC static SimdMaskArray One() { return {storage_type::One()}; }
90 
91  // conversion (casts)
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)
98  Vc_INTRINSIC_R;
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)
102  Vc_INTRINSIC_R;
103 
104  // conversion from any Segment object (could be SimdMaskArray or Mask<T>)
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;
109 
110  // conversion from Mask<T>
111  template <typename M>
112  Vc_INTRINSIC_L SimdMaskArray(
113  M k,
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;
116 
117  // implicit conversion to Mask<U, AnyAbi> for if Mask<U, AnyAbi>::size() == N
118  template <typename U, typename A, typename = enable_if<Vc::Mask<U, A>::Size == N>>
119  operator Vc::Mask<U, A>() const
120  {
121  return simd_cast<Vc::Mask<U, A>>(data);
122  }
123 
124  // load/store (from/to bool arrays)
125  template <typename Flags = DefaultLoadTag>
126  Vc_INTRINSIC explicit SimdMaskArray(const bool *mem, Flags f = Flags())
127  : data(mem, f)
128  {
129  }
130 
131  Vc_INTRINSIC void load(const bool *mem) { data.load(mem); }
132  template <typename Flags> Vc_INTRINSIC void load(const bool *mem, Flags f)
133  {
134  data.load(mem, f);
135  }
136 
137  Vc_INTRINSIC void store(bool *mem) const { data.store(mem); }
138  template <typename Flags> Vc_INTRINSIC void store(bool *mem, Flags f) const
139  {
140  data.store(mem, f);
141  }
142 
143  // compares
144  Vc_INTRINSIC Vc_PURE bool operator==(const SimdMaskArray &rhs) const
145  {
146  return data == rhs.data;
147  }
148  Vc_INTRINSIC Vc_PURE bool operator!=(const SimdMaskArray &rhs) const
149  {
150  return data != rhs.data;
151  }
152 
153  // inversion
154  Vc_INTRINSIC Vc_PURE SimdMaskArray operator!() const
155  {
156  return {!data};
157  }
158 
159  // binary operators
160  Vc_INTRINSIC SimdMaskArray &operator&=(const SimdMaskArray &rhs)
161  {
162  data &= rhs.data;
163  return *this;
164  }
165  Vc_INTRINSIC SimdMaskArray &operator|=(const SimdMaskArray &rhs)
166  {
167  data |= rhs.data;
168  return *this;
169  }
170  Vc_INTRINSIC SimdMaskArray &operator^=(const SimdMaskArray &rhs)
171  {
172  data ^= rhs.data;
173  return *this;
174  }
175 
176  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&(const SimdMaskArray &rhs) const
177  {
178  return {data & rhs.data};
179  }
180  Vc_INTRINSIC Vc_PURE SimdMaskArray operator|(const SimdMaskArray &rhs) const
181  {
182  return {data | rhs.data};
183  }
184  Vc_INTRINSIC Vc_PURE SimdMaskArray operator^(const SimdMaskArray &rhs) const
185  {
186  return {data ^ rhs.data};
187  }
188 
189  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&&(const SimdMaskArray &rhs) const
190  {
191  return {data && rhs.data};
192  }
193  Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(const SimdMaskArray &rhs) const
194  {
195  return {data || rhs.data};
196  }
197 
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(); }
202 
203  Vc_INTRINSIC Vc_PURE int shiftMask() const { return data.shiftMask(); }
204 
205  Vc_INTRINSIC Vc_PURE int toInt() const { return data.toInt(); }
206 
207 private:
208  friend reference;
209  static Vc_INTRINSIC value_type get(const storage_type &k, int i) noexcept
210  {
211  return k[i];
212  }
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>()))
216  {
217  k[i] = std::forward<U>(v);
218  }
219 
220 public:
227  Vc_INTRINSIC Vc_PURE reference operator[](size_t index) noexcept
228  {
229  return {data, int(index)};
230  }
231  Vc_INTRINSIC Vc_PURE value_type operator[](size_t index) const noexcept
232  {
233  return data[index];
234  }
235 
236  Vc_INTRINSIC Vc_PURE int count() const { return data.count(); }
237 
243  Vc_INTRINSIC Vc_PURE int firstOne() const { return data.firstOne(); }
244 
245  template <typename G> static Vc_INTRINSIC SimdMaskArray generate(const G &gen)
246  {
247  return {mask_type::generate(gen)};
248  }
249 
250  Vc_INTRINSIC Vc_PURE SimdMaskArray shifted(int amount) const
251  {
252  return {data.shifted(amount)};
253  }
254 
256  template <typename Op, typename... Args>
257  static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
258  {
259  SimdMaskArray r;
260  Common::unpackArgumentsAuto(op, r.data, std::forward<Args>(args)...);
261  return r;
262  }
263 
265  Vc_INTRINSIC SimdMaskArray(mask_type &&x) : data(std::move(x)) {}
266 
267 private:
268  // The alignas attribute attached to the class declaration above is ignored by ICC
269  // 17.0.0 (at least). So just move the alignas attribute down here where it works for
270  // all compilers.
271  alignas(static_cast<std::size_t>(
272  Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * sizeof(VectorType_) /
273  VectorType_::size()>::value)) storage_type data;
274 };
275 
276 template <typename T, std::size_t N, typename VectorType> constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::Size;
277 template <typename T, std::size_t N, typename VectorType>
279 
280 // generic SimdArray {{{1
304 template <typename T, size_t N, typename V, size_t Wt>
305 class SimdMaskArray
306 {
307  static constexpr std::size_t N0 = Common::left_size<N>();
308 
309  using Split = Common::Split<N0>;
310 
311 public:
312  using storage_type0 = SimdMaskArray<T, N0>;
313  using storage_type1 = SimdMaskArray<T, N - N0>;
314  static_assert(storage_type0::size() == N0, "");
315 
316  using vector_type = SimdArray<T, N>;
317 
318  friend storage_type0 &internal_data0(SimdMaskArray &m) { return m.data0; }
319  friend storage_type1 &internal_data1(SimdMaskArray &m) { return m.data1; }
320  friend const storage_type0 &internal_data0(const SimdMaskArray &m) { return m.data0; }
321  friend const storage_type1 &internal_data1(const SimdMaskArray &m) { return m.data1; }
322 
323  using mask_type = SimdMaskArray;
324 
326  static constexpr std::size_t size() { return N; }
328  static constexpr std::size_t Size = size();
330  static constexpr std::size_t MemoryAlignment =
334  static_assert(Size == vector_type::Size, "size mismatch");
335 
337  using vectorentry_type = typename storage_type0::VectorEntryType;
338 
344  using VectorEntryType = vectorentry_type;
348  using EntryReference = Vc::Detail::ElementReference<SimdMaskArray>;
349  using reference = EntryReference;
352 
353  Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(mask_type));
354 
355  // zero init
357  SimdMaskArray() = default;
358 
359  // default copy ctor/operator
360  SimdMaskArray(const SimdMaskArray &) = default;
361  SimdMaskArray(SimdMaskArray &&) = default;
362  SimdMaskArray &operator=(const SimdMaskArray &) = default;
363  SimdMaskArray &operator=(SimdMaskArray &&) = default;
364 
365  // implicit conversion from SimdMaskArray with same N
366  template <typename U, typename W>
367  Vc_INTRINSIC SimdMaskArray(const SimdMaskArray<U, N, W> &rhs)
368  : data0(Split::lo(rhs)), data1(Split::hi(rhs))
369  {
370  }
371 
372  // conversion from any Segment object (could be SimdMaskArray or Mask<T>)
373  template <typename M, std::size_t Pieces, std::size_t Index>
374  Vc_INTRINSIC SimdMaskArray(
375  Common::Segment<M, Pieces, Index> &&rhs,
376  enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg)
377  : data0(Split::lo(rhs)), data1(Split::hi(rhs))
378  {
379  }
380 
381  // conversion from Mask<T>
382  template <typename M>
383  Vc_INTRINSIC SimdMaskArray(
384  M k,
385  enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
386  Traits::simd_vector_size<M>::value == Size)> = nullarg)
387  : data0(Split::lo(k)), data1(Split::hi(k))
388  {
389  }
390 
391  // implicit conversion to Mask<U, AnyAbi> for if Mask<U, AnyAbi>::size() == N
392  template <typename U, typename A, typename = enable_if<Vc::Mask<U, A>::Size == N>>
393  operator Vc::Mask<U, A>() const
394  {
395  return simd_cast<Vc::Mask<U, A>>(data0, data1);
396  }
397 
399  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerOne one)
400  : data0(one), data1(one)
401  {
402  }
404  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerZero zero)
405  : data0(zero), data1(zero)
406  {
407  }
409  Vc_INTRINSIC explicit SimdMaskArray(bool b) : data0(b), data1(b) {}
410 
412  Vc_INTRINSIC static SimdMaskArray Zero() { return {storage_type0::Zero(), storage_type1::Zero()}; }
414  Vc_INTRINSIC static SimdMaskArray One() { return {storage_type0::One(), storage_type1::One()}; }
415 
418 
425  template <typename Flags = DefaultLoadTag>
426  Vc_INTRINSIC explicit SimdMaskArray(const bool *mem, Flags f = Flags())
427  : data0(mem, f), data1(mem + storage_type0::size(), f)
428  {
429  }
430 
436  Vc_INTRINSIC void load(const bool *mem)
437  {
438  data0.load(mem);
439  data1.load(mem + storage_type0::size());
440  }
441 
448  template <typename Flags> Vc_INTRINSIC void load(const bool *mem, Flags f)
449  {
450  data0.load(mem, f);
451  data1.load(mem + storage_type0::size(), f);
452  }
453 
459  Vc_INTRINSIC void store(bool *mem) const
460  {
461  data0.store(mem);
462  data1.store(mem + storage_type0::size());
463  }
464 
471  template <typename Flags> Vc_INTRINSIC void store(bool *mem, Flags f) const
472  {
473  data0.store(mem, f);
474  data1.store(mem + storage_type0::size(), f);
475  }
477 
479  Vc_INTRINSIC Vc_PURE bool operator==(const SimdMaskArray &mask) const
480  {
481  return data0 == mask.data0 && data1 == mask.data1;
482  }
484  Vc_INTRINSIC Vc_PURE bool operator!=(const SimdMaskArray &mask) const
485  {
486  return data0 != mask.data0 || data1 != mask.data1;
487  }
488 
490  Vc_INTRINSIC Vc_PURE SimdMaskArray operator!() const
491  {
492  return {!data0, !data1};
493  }
494 
496  Vc_INTRINSIC SimdMaskArray &operator&=(const SimdMaskArray &rhs)
497  {
498  data0 &= rhs.data0;
499  data1 &= rhs.data1;
500  return *this;
501  }
503  Vc_INTRINSIC SimdMaskArray &operator|=(const SimdMaskArray &rhs)
504  {
505  data0 |= rhs.data0;
506  data1 |= rhs.data1;
507  return *this;
508  }
510  Vc_INTRINSIC SimdMaskArray &operator^=(const SimdMaskArray &rhs)
511  {
512  data0 ^= rhs.data0;
513  data1 ^= rhs.data1;
514  return *this;
515  }
516 
518  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&(const SimdMaskArray &rhs) const
519  {
520  return {data0 & rhs.data0, data1 & rhs.data1};
521  }
523  Vc_INTRINSIC Vc_PURE SimdMaskArray operator|(const SimdMaskArray &rhs) const
524  {
525  return {data0 | rhs.data0, data1 | rhs.data1};
526  }
528  Vc_INTRINSIC Vc_PURE SimdMaskArray operator^(const SimdMaskArray &rhs) const
529  {
530  return {data0 ^ rhs.data0, data1 ^ rhs.data1};
531  }
532 
534  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&&(const SimdMaskArray &rhs) const
535  {
536  return {data0 && rhs.data0, data1 && rhs.data1};
537  }
539  Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(const SimdMaskArray &rhs) const
540  {
541  return {data0 || rhs.data0, data1 || rhs.data1};
542  }
543 
545  Vc_INTRINSIC Vc_PURE bool isFull() const { return data0.isFull() && data1.isFull(); }
547  Vc_INTRINSIC Vc_PURE bool isNotEmpty() const { return data0.isNotEmpty() || data1.isNotEmpty(); }
549  Vc_INTRINSIC Vc_PURE bool isEmpty() const { return data0.isEmpty() && data1.isEmpty(); }
551  Vc_INTRINSIC Vc_PURE bool isMix() const { return !isFull() && !isEmpty(); }
552 
554  Vc_INTRINSIC Vc_PURE int toInt() const
555  {
556  return data0.toInt() | (data1.toInt() << data0.size());
557  }
558 
559 private:
560  friend reference;
561  static Vc_INTRINSIC value_type get(const SimdMaskArray &o, int i) noexcept
562  {
563  if (i < int(o.data0.size())) {
564  return o.data0[i];
565  } else {
566  return o.data1[i - o.data0.size()];
567  }
568  }
569  template <typename U>
570  static Vc_INTRINSIC void set(SimdMaskArray &o, int i, U &&v) noexcept(
571  noexcept(std::declval<storage_type0 &>()[0] = std::declval<U>()) &&
572  noexcept(std::declval<storage_type1 &>()[0] = std::declval<U>()))
573  {
574  if (i < int(o.data0.size())) {
575  o.data0[i] = std::forward<U>(v);
576  } else {
577  o.data1[i - o.data0.size()] = std::forward<U>(v);
578  }
579  }
580 
581 public:
590  Vc_INTRINSIC Vc_PURE reference operator[](size_t index) noexcept
591  {
592  return {*this, int(index)};
593  }
602  Vc_INTRINSIC Vc_PURE value_type operator[](size_t index) const noexcept
603  {
604  return get(*this, index);
605  }
606 
608  Vc_INTRINSIC Vc_PURE int count() const { return data0.count() + data1.count(); }
609 
611  Vc_INTRINSIC Vc_PURE int firstOne() const {
612  if (data0.isEmpty()) {
613  return data1.firstOne() + storage_type0::size();
614  }
615  return data0.firstOne();
616  }
617 
619  template <typename G> static Vc_INTRINSIC SimdMaskArray generate(const G &gen)
620  {
621  return {storage_type0::generate(gen),
622  storage_type1::generate([&](std::size_t i) { return gen(i + N0); })};
623  }
624 
626  inline Vc_PURE SimdMaskArray shifted(int amount) const
627  {
628  if (Vc_IS_UNLIKELY(amount == 0)) {
629  return *this;
630  }
631  return generate([&](unsigned i) {
632  // modulo arithmetic of unsigned makes the check for j >= 0 unnecessary
633  const unsigned j = i + amount;
634  return j < size() ? get(*this, j) : false;
635  });
636  }
637 
639  template <typename Op, typename... Args>
640  static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
641  {
642  SimdMaskArray r = {
643  storage_type0::fromOperation(op, Split::lo(args)...), // no forward here - it
644  // could move and thus
645  // break the next line
646  storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
647  return r;
648  }
649 
651  Vc_INTRINSIC SimdMaskArray(storage_type0 &&x, storage_type1 &&y)
652  : data0(std::move(x)), data1(std::move(y))
653  {
654  }
655 
656 private:
657  // The alignas attribute attached to the class declaration above is ignored by ICC
658  // 17.0.0 (at least). So just move the alignas attribute down here where it works for
659  // all compilers.
660  alignas(static_cast<std::size_t>(
661  Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * sizeof(V) /
662  V::size()>::value)) storage_type0 data0;
663  storage_type1 data1;
664 };
665 template <typename T, std::size_t N, typename V, std::size_t M>
666 constexpr std::size_t SimdMaskArray<T, N, V, M>::Size;
667 template <typename T, std::size_t N, typename V, std::size_t M>
668 constexpr std::size_t SimdMaskArray<T, N, V, M>::MemoryAlignment;
669 
672 
673 } // namespace Vc
674 
675 // XXX: this include should be in <Vc/vector.h>. But at least clang 3.4 then fails to compile the
676 // code. Not sure yet what is going on, but it looks a lot like a bug in clang.
677 #include "simd_cast_caller.tcc"
678 
679 #endif // VC_COMMON_SIMDMASKARRAY_H_
680 
681 // vim: foldmethod=marker
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.
value_type operator[](size_t index) const noexcept
Return a copy of the boolean element at index index.
result_vector_type< L, R > operator|(L &&lhs, R &&rhs)
Applies | component-wise and concurrently.
Definition: simdarray.h:1612
result_vector_type< L, R > operator^(L &&lhs, R &&rhs)
Applies ^ component-wise and concurrently.
Definition: simdarray.h:1612
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.
Definition: vector.h:257
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1642
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.
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.
Definition: simdarray.h:565
The value member will either be the number of SIMD vector entries or 0 if T is not a SIMD type...
Definition: type_traits.h:171
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.
Definition: simdarrayfwd.h:121
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.
Definition: simdarray.h:1642
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.
Definition: simdarray.h:1612
The main SIMD mask class.
Definition: mask.h:41
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...
Definition: types.h:84
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
int count() const
Returns how many components of the mask are true.
Vector Classes Namespace.
Definition: cpuid.h:32
constexpr VectorSpecialInitializerOne One
The special object Vc::One can be used to construct Vector and Mask objects initialized to one/true...
Definition: types.h:89
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...
Definition: vector.h:218
SimdMaskArray(bool b)
Broadcast constructor.
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.