Vc  1.4.1
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 = 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 
224 private:
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 
237 public:
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 
285 private:
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 
294 template <typename T, std::size_t N, typename VectorType> constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::Size;
295 template <typename T, std::size_t N, typename VectorType>
297 
298 // generic SimdMaskArray {{{1
322 template <typename T, size_t N, typename V, size_t Wt>
323 class SimdMaskArray
324 {
325  static constexpr std::size_t N0 = Common::left_size<N>();
326 
327  using Split = Common::Split<N0>;
328 
329 public:
330  using storage_type0 = fixed_size_simd_mask<T, N0>;
331  using storage_type1 = fixed_size_simd_mask<T, N - N0>;
332  static_assert(storage_type0::size() == N0, "");
333 
334  using vector_type = fixed_size_simd<T, N>;
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 =
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 &&
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  {
441  }
443  Vc_INTRINSIC static fixed_size_simd_mask<T, N> One()
444  {
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 
550  Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator&(
551  const SimdMaskArray &rhs) const
552  {
553  return {data0 & rhs.data0, data1 & rhs.data1};
554  }
556  Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator|(
557  const SimdMaskArray &rhs) const
558  {
559  return {data0 | rhs.data0, data1 | rhs.data1};
560  }
562  Vc_INTRINSIC Vc_PURE fixed_size_simd_mask<T, N> operator^(
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 
596 private:
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 
618 public:
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 
694 private:
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 };
703 template <typename T, std::size_t N, typename V, std::size_t M>
704 constexpr std::size_t SimdMaskArray<T, N, V, M>::Size;
705 template <typename T, std::size_t N, typename V, std::size_t M>
706 constexpr 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
bool isNotEmpty() const
Returns a logical OR of all components.
The main vector class for expressing data parallelism.
Definition: fwddecl.h:53
bool EntryType
The EntryType of masks is always bool, independent of T.
Definition: mask.h:74
fixed_size_simd_mask< T, N > operator||(const SimdMaskArray &rhs) const
Returns the component-wise application of a logical OR to mask.
result_vector_type< L, R > operator|(L &&lhs, R &&rhs)
Applies | component-wise and concurrently.
Definition: simdarray.h:1722
result_vector_type< L, R > operator^(L &&lhs, R &&rhs)
Applies ^ component-wise and concurrently.
Definition: simdarray.h:1722
bool operator==(const SimdMaskArray &mask) const
Returns whether the two masks are equal in all components.
reference operator[](size_t index) noexcept
Return a smart reference to the boolean element at index index.
typename storage_type0::EntryType value_type
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).
fixed_size_simd_mask< T, N > operator &&(const SimdMaskArray &rhs) const
fixed_size_simd_mask< T, N > shifted(int amount) const
Returns a mask with components shifted by amount places.
void load(const bool *mem, Flags f)
Load N boolean values from the consecutive addresses starting at mem.
Definition: vector.h:248
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1752
SimdMaskArray & operator|=(const SimdMaskArray &rhs)
Modifies the mask using an OR operation with mask.
Identifies any possible SimdMaskArray<T, N> type (independent of const/volatile or reference) ...
Definition: type_traits.h:143
int toInt() const
Convert the boolean components of the mask into bits of an integer.
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: fwddecl.h:86
vectorentry_type VectorEntryType
void load(const bool *mem)
Load N boolean values from the consecutive addresses starting at mem.
bool operator!=(const SimdMaskArray &mask) const
Returns whether the two masks are different in at least one component.
static fixed_size_simd_mask< T, N > Zero()
Creates a new mask object initialized to zero/false.
SimdMaskArray & operator &=(const SimdMaskArray &rhs)
fixed_size_simd_mask< T, N > operator^(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary XOR to mask.
Vc::Detail::ElementReference< SimdMaskArray > EntryReference
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
Definition: simdarray.h:1752
typename VectorTraits< T, Abi >::VectorEntryType VectorEntryType
The VectorEntryType, in contrast to EntryType, reveals information about the SIMD implementation...
Definition: mask.h:88
static fixed_size_simd_mask< T, N > generate(const G &gen)
Generate a mask object from booleans returned from the function gen.
void store(bool *mem, Flags f) const
Store N boolean values to the consecutive addresses starting at mem.
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:1722
static fixed_size_simd_mask< T, N > One()
Creates a mask object initialized to one/true.
int firstOne() const
Returns the index of the first one in the mask.
int count() const
Returns how many components of the mask are true.
The main SIMD mask class.
Definition: fwddecl.h:52
fixed_size_simd_mask< T, N > operator!() const
Returns a mask with inverted components.
value_type operator[](size_t index) const noexcept
Return a copy of the boolean element at index index.
bool isEmpty() const
Returns true if components are false, false otherwise.
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
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
fixed_size_simd_mask< T, N > operator|(const SimdMaskArray &rhs) const
Returns the component-wise application of a binary OR to mask.
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 std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
Definition: vector.h:215
SimdMaskArray(bool b)
Broadcast constructor.
void store(bool *mem) const
Store N boolean values to the consecutive addresses starting at mem.
fixed_size_simd_mask< T, N > operator &(const SimdMaskArray &rhs) const
bool isMix() const
Returns !isFull() && !isEmpty().
bool isFull() const
Returns a logical AND of all components.