Vc  1.3.0
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:
221  Vc_INTRINSIC Vc_PURE reference operator[](size_t index) noexcept
222  {
223  return {data, int(index)};
224  }
225  Vc_INTRINSIC Vc_PURE value_type operator[](size_t index) const noexcept
226  {
227  return data[index];
228  }
229 
230  Vc_INTRINSIC Vc_PURE int count() const { return data.count(); }
231 
237  Vc_INTRINSIC Vc_PURE int firstOne() const { return data.firstOne(); }
238 
239  template <typename G> static Vc_INTRINSIC SimdMaskArray generate(const G &gen)
240  {
241  return {mask_type::generate(gen)};
242  }
243 
244  Vc_INTRINSIC Vc_PURE SimdMaskArray shifted(int amount) const
245  {
246  return {data.shifted(amount)};
247  }
248 
250  template <typename Op, typename... Args>
251  static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
252  {
253  SimdMaskArray r;
254  Common::unpackArgumentsAuto(op, r.data, std::forward<Args>(args)...);
255  return r;
256  }
257 
259  Vc_INTRINSIC SimdMaskArray(mask_type &&x) : data(std::move(x)) {}
260 
261 private:
262  // The alignas attribute attached to the class declaration above is ignored by ICC
263  // 17.0.0 (at least). So just move the alignas attribute down here where it works for
264  // all compilers.
265  alignas(static_cast<std::size_t>(
266  Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * sizeof(VectorType_) /
267  VectorType_::size()>::value)) storage_type data;
268 };
269 
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>
273 
274 // generic SimdArray {{{1
298 template <typename T, size_t N, typename V, size_t Wt>
299 class SimdMaskArray
300 {
301  static constexpr std::size_t N0 = Common::left_size<N>();
302 
303  using Split = Common::Split<N0>;
304 
305 public:
306  using storage_type0 = SimdMaskArray<T, N0>;
307  using storage_type1 = SimdMaskArray<T, N - N0>;
308  static_assert(storage_type0::size() == N0, "");
309 
310  using vector_type = SimdArray<T, N>;
311 
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; }
316 
317  using mask_type = SimdMaskArray;
318 
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");
329 
331  using vectorentry_type = typename storage_type0::VectorEntryType;
332 
338  using VectorEntryType = vectorentry_type;
342  using EntryReference = Vc::Detail::ElementReference<SimdMaskArray>;
343  using reference = EntryReference;
346 
347  Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(mask_type));
348 
349  // zero init
351  SimdMaskArray() = default;
352 
353  // default copy ctor/operator
354  SimdMaskArray(const SimdMaskArray &) = default;
355  SimdMaskArray(SimdMaskArray &&) = default;
356  SimdMaskArray &operator=(const SimdMaskArray &) = default;
357  SimdMaskArray &operator=(SimdMaskArray &&) = default;
358 
359  // implicit conversion from SimdMaskArray with same N
360  template <typename U, typename W>
361  Vc_INTRINSIC SimdMaskArray(const SimdMaskArray<U, N, W> &rhs)
362  : data0(Split::lo(rhs)), data1(Split::hi(rhs))
363  {
364  }
365 
366  // conversion from any Segment object (could be SimdMaskArray or Mask<T>)
367  template <typename M, std::size_t Pieces, std::size_t Index>
368  Vc_INTRINSIC SimdMaskArray(
369  Common::Segment<M, Pieces, Index> &&rhs,
370  enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg)
371  : data0(Split::lo(rhs)), data1(Split::hi(rhs))
372  {
373  }
374 
375  // conversion from Mask<T>
376  template <typename M>
377  Vc_INTRINSIC SimdMaskArray(
378  M k,
380  Traits::simd_vector_size<M>::value == Size)> = nullarg)
381  : data0(Split::lo(k)), data1(Split::hi(k))
382  {
383  }
384 
385  // implicit conversion to Mask<U, AnyAbi> for if Mask<U, AnyAbi>::size() == N
386  template <typename U, typename A, typename = enable_if<Vc::Mask<U, A>::Size == N>>
387  operator Vc::Mask<U, A>() const
388  {
389  return simd_cast<Vc::Mask<U, A>>(data0, data1);
390  }
391 
393  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerOne one)
394  : data0(one), data1(one)
395  {
396  }
398  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerZero zero)
399  : data0(zero), data1(zero)
400  {
401  }
403  Vc_INTRINSIC explicit SimdMaskArray(bool b) : data0(b), data1(b) {}
404 
406  Vc_INTRINSIC static SimdMaskArray Zero() { return {storage_type0::Zero(), storage_type1::Zero()}; }
408  Vc_INTRINSIC static SimdMaskArray One() { return {storage_type0::One(), storage_type1::One()}; }
409 
412 
419  template <typename Flags = DefaultLoadTag>
420  Vc_INTRINSIC explicit SimdMaskArray(const bool *mem, Flags f = Flags())
421  : data0(mem, f), data1(mem + storage_type0::size(), f)
422  {
423  }
424 
430  Vc_INTRINSIC void load(const bool *mem)
431  {
432  data0.load(mem);
433  data1.load(mem + storage_type0::size());
434  }
435 
442  template <typename Flags> Vc_INTRINSIC void load(const bool *mem, Flags f)
443  {
444  data0.load(mem, f);
445  data1.load(mem + storage_type0::size(), f);
446  }
447 
453  Vc_INTRINSIC void store(bool *mem) const
454  {
455  data0.store(mem);
456  data1.store(mem + storage_type0::size());
457  }
458 
465  template <typename Flags> Vc_INTRINSIC void store(bool *mem, Flags f) const
466  {
467  data0.store(mem, f);
468  data1.store(mem + storage_type0::size(), f);
469  }
471 
473  Vc_INTRINSIC Vc_PURE bool operator==(const SimdMaskArray &mask) const
474  {
475  return data0 == mask.data0 && data1 == mask.data1;
476  }
478  Vc_INTRINSIC Vc_PURE bool operator!=(const SimdMaskArray &mask) const
479  {
480  return data0 != mask.data0 || data1 != mask.data1;
481  }
482 
484  Vc_INTRINSIC Vc_PURE SimdMaskArray operator!() const
485  {
486  return {!data0, !data1};
487  }
488 
490  Vc_INTRINSIC SimdMaskArray &operator&=(const SimdMaskArray &rhs)
491  {
492  data0 &= rhs.data0;
493  data1 &= rhs.data1;
494  return *this;
495  }
497  Vc_INTRINSIC SimdMaskArray &operator|=(const SimdMaskArray &rhs)
498  {
499  data0 |= rhs.data0;
500  data1 |= rhs.data1;
501  return *this;
502  }
504  Vc_INTRINSIC SimdMaskArray &operator^=(const SimdMaskArray &rhs)
505  {
506  data0 ^= rhs.data0;
507  data1 ^= rhs.data1;
508  return *this;
509  }
510 
512  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&(const SimdMaskArray &rhs) const
513  {
514  return {data0 & rhs.data0, data1 & rhs.data1};
515  }
517  Vc_INTRINSIC Vc_PURE SimdMaskArray operator|(const SimdMaskArray &rhs) const
518  {
519  return {data0 | rhs.data0, data1 | rhs.data1};
520  }
522  Vc_INTRINSIC Vc_PURE SimdMaskArray operator^(const SimdMaskArray &rhs) const
523  {
524  return {data0 ^ rhs.data0, data1 ^ rhs.data1};
525  }
526 
528  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&&(const SimdMaskArray &rhs) const
529  {
530  return {data0 && rhs.data0, data1 && rhs.data1};
531  }
533  Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(const SimdMaskArray &rhs) const
534  {
535  return {data0 || rhs.data0, data1 || rhs.data1};
536  }
537 
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(); }
546 
548  Vc_INTRINSIC Vc_PURE int toInt() const
549  {
550  return data0.toInt() | (data1.toInt() << data0.size());
551  }
552 
553 private:
554  friend reference;
555  static Vc_INTRINSIC value_type get(const SimdMaskArray &o, int i) noexcept
556  {
557  if (i < int(o.data0.size())) {
558  return o.data0[i];
559  } else {
560  return o.data1[i - o.data0.size()];
561  }
562  }
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>()))
567  {
568  if (i < int(o.data0.size())) {
569  o.data0[i] = std::forward<U>(v);
570  } else {
571  o.data1[i - o.data0.size()] = std::forward<U>(v);
572  }
573  }
574 
575 public:
584  Vc_INTRINSIC Vc_PURE reference operator[](size_t index) noexcept
585  {
586  return {*this, int(index)};
587  }
596  Vc_INTRINSIC Vc_PURE value_type operator[](size_t index) const noexcept
597  {
598  return get(*this, index);
599  }
600 
602  Vc_INTRINSIC Vc_PURE int count() const { return data0.count() + data1.count(); }
603 
605  Vc_INTRINSIC Vc_PURE int firstOne() const {
606  if (data0.isEmpty()) {
607  return data1.firstOne() + storage_type0::size();
608  }
609  return data0.firstOne();
610  }
611 
613  template <typename G> static Vc_INTRINSIC SimdMaskArray generate(const G &gen)
614  {
615  return {storage_type0::generate(gen),
616  storage_type1::generate([&](std::size_t i) { return gen(i + N0); })};
617  }
618 
620  inline Vc_PURE SimdMaskArray shifted(int amount) const
621  {
622  if (Vc_IS_UNLIKELY(amount == 0)) {
623  return *this;
624  }
625  return generate([&](unsigned i) {
626  // modulo arithmetic of unsigned makes the check for j >= 0 unnecessary
627  const unsigned j = i + amount;
628  return j < size() ? get(*this, j) : false;
629  });
630  }
631 
633  template <typename Op, typename... Args>
634  static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
635  {
636  SimdMaskArray r = {
637  storage_type0::fromOperation(op, Split::lo(args)...), // no forward here - it
638  // could move and thus
639  // break the next line
640  storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
641  return r;
642  }
643 
645  Vc_INTRINSIC SimdMaskArray(storage_type0 &&x, storage_type1 &&y)
646  : data0(std::move(x)), data1(std::move(y))
647  {
648  }
649 
650 private:
651  // The alignas attribute attached to the class declaration above is ignored by ICC
652  // 17.0.0 (at least). So just move the alignas attribute down here where it works for
653  // all compilers.
654  alignas(static_cast<std::size_t>(
655  Common::BoundedAlignment<Common::NextPowerOfTwo<N>::value * sizeof(V) /
656  V::size()>::value)) storage_type0 data0;
657  storage_type1 data1;
658 };
659 template <typename T, std::size_t N, typename V, std::size_t M>
660 constexpr std::size_t SimdMaskArray<T, N, V, M>::Size;
661 template <typename T, std::size_t N, typename V, std::size_t M>
662 constexpr std::size_t SimdMaskArray<T, N, V, M>::MemoryAlignment;
663 
666 
667 } // namespace Vc
668 
669 // XXX: this include should be in <Vc/vector.h>. But at least clang 3.4 then fails to compile the
670 // code. Not sure yet what is going on, but it looks a lot like a bug in clang.
671 #include "simd_cast_caller.tcc"
672 
673 #endif // VC_COMMON_SIMDMASKARRAY_H_
674 
675 // 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.
result_vector_type< L, R > operator|(L &&lhs, R &&rhs)
Applies | component-wise and concurrently.
Definition: simdarray.h:1604
result_vector_type< L, R > operator^(L &&lhs, R &&rhs)
Applies ^ component-wise and concurrently.
Definition: simdarray.h:1604
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:1634
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) ...
Definition: type_traits.h:148
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:559
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:1634
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:1604
The main SIMD mask class.
Definition: mask.h:41
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...
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.
Identifies any SIMD mask type (independent of implementation or whether it&#39;s SimdMaskArray<T, N>).
Definition: type_traits.h:122
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.