Vc  1.2.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 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the names of contributing organizations nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 }}}*/
28 
29 #ifndef VC_COMMON_SIMDMASKARRAY_H_
30 #define VC_COMMON_SIMDMASKARRAY_H_
31 
32 #include <type_traits>
33 #include <array>
34 #include "simdarrayhelper.h"
35 #include "utility.h"
36 #include "maskentry.h"
37 
38 #include "macros.h"
39 
40 namespace Vc_VERSIONED_NAMESPACE
41 {
44 // atomic SimdMaskArray {{{1
54 template <typename T, std::size_t N, typename VectorType_>
55 class alignas(
57  ((Common::nextPowerOfTwo(N) * (sizeof(VectorType_) / VectorType_::size()) - 1) & 127) +
59  1) SimdMaskArray<T, N, VectorType_, N>
60 {
61 public:
62  using VectorType = VectorType_;
63  using vector_type = VectorType;
64  using mask_type = typename vector_type::Mask;
65  using storage_type = mask_type;
66 
67  friend storage_type &internal_data(SimdMaskArray &m) { return m.data; }
68  friend const storage_type &internal_data(const SimdMaskArray &m) { return m.data; }
69 
70  static constexpr std::size_t size() { return N; }
71  static constexpr std::size_t Size = size();
72  static constexpr std::size_t MemoryAlignment = storage_type::MemoryAlignment;
73  static_assert(Size == mask_type::Size, "size mismatch");
74 
75  using vectorentry_type = typename mask_type::VectorEntryType;
76  using vectorentry_reference = vectorentry_type &;
77  using value_type = typename mask_type::EntryType;
78  using Mask = mask_type;
79  using VectorEntryType = vectorentry_type;
80  using EntryType = value_type;
81  using EntryReference = typename mask_type::EntryReference;
82  using Vector = SimdArray<T, N, VectorType, N>;
83 
84  Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(mask_type));
85 
86  // zero init
87  SimdMaskArray() = default;
88 
89  // broadcasts
90  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerOne one) : data(one) {}
91  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerZero zero) : data(zero) {}
92  Vc_INTRINSIC explicit SimdMaskArray(bool b) : data(b) {}
93  Vc_INTRINSIC static SimdMaskArray Zero() { return {storage_type::Zero()}; }
94  Vc_INTRINSIC static SimdMaskArray One() { return {storage_type::One()}; }
95 
96  // conversion (casts)
97  template <typename U, typename V>
98  Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
99  enable_if<N == V::size()> = nullarg) Vc_INTRINSIC_R;
100  template <typename U, typename V>
101  Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
102  enable_if<(N > V::size() && N <= 2 * V::size())> = nullarg)
103  Vc_INTRINSIC_R;
104  template <typename U, typename V>
105  Vc_INTRINSIC_L SimdMaskArray(const SimdMaskArray<U, N, V> &x,
106  enable_if<(N > 2 * V::size() && N <= 4 * V::size())> = nullarg)
107  Vc_INTRINSIC_R;
108 
109  // conversion from any Segment object (could be SimdMaskArray or Mask<T>)
110  template <typename M, std::size_t Pieces, std::size_t Index>
111  Vc_INTRINSIC_L SimdMaskArray(
112  Common::Segment<M, Pieces, Index> &&x,
113  enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg) Vc_INTRINSIC_R;
114 
115  // conversion from Mask<T>
116  template <typename M>
117  Vc_INTRINSIC_L SimdMaskArray(
118  M k,
119  enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
120  Traits::simd_vector_size<M>::value == Size)> = nullarg) Vc_INTRINSIC_R;
121 
122  // implicit conversion to Mask<U, AnyAbi> for if Mask<U, AnyAbi>::size() == N
123  template <typename M,
124  typename = enable_if<Traits::is_simd_mask<M>::value &&
125  !Traits::isSimdMaskArray<M>::value && M::size() == N>>
126  operator M() const
127  {
128  return simd_cast<M>(*this);
129  }
130 
131  // load/store (from/to bool arrays)
132  template <typename Flags = DefaultLoadTag>
133  Vc_INTRINSIC explicit SimdMaskArray(const bool *mem, Flags f = Flags())
134  : data(mem, f)
135  {
136  }
137 
138  Vc_INTRINSIC void load(const bool *mem) { data.load(mem); }
139  template <typename Flags> Vc_INTRINSIC void load(const bool *mem, Flags f)
140  {
141  data.load(mem, f);
142  }
143 
144  Vc_INTRINSIC void store(bool *mem) const { data.store(mem); }
145  template <typename Flags> Vc_INTRINSIC void store(bool *mem, Flags f) const
146  {
147  data.store(mem, f);
148  }
149 
150  // compares
151  Vc_INTRINSIC Vc_PURE bool operator==(const SimdMaskArray &rhs) const
152  {
153  return data == rhs.data;
154  }
155  Vc_INTRINSIC Vc_PURE bool operator!=(const SimdMaskArray &rhs) const
156  {
157  return data != rhs.data;
158  }
159 
160  // inversion
161  Vc_INTRINSIC Vc_PURE SimdMaskArray operator!() const
162  {
163  return {!data};
164  }
165 
166  // binary operators
167  Vc_INTRINSIC SimdMaskArray &operator&=(const SimdMaskArray &rhs)
168  {
169  data &= rhs.data;
170  return *this;
171  }
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 
183  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&(const SimdMaskArray &rhs) const
184  {
185  return {data & rhs.data};
186  }
187  Vc_INTRINSIC Vc_PURE SimdMaskArray operator|(const SimdMaskArray &rhs) const
188  {
189  return {data | rhs.data};
190  }
191  Vc_INTRINSIC Vc_PURE SimdMaskArray operator^(const SimdMaskArray &rhs) const
192  {
193  return {data ^ rhs.data};
194  }
195 
196  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&&(const SimdMaskArray &rhs) const
197  {
198  return {data && rhs.data};
199  }
200  Vc_INTRINSIC Vc_PURE SimdMaskArray operator||(const SimdMaskArray &rhs) const
201  {
202  return {data || rhs.data};
203  }
204 
205  Vc_INTRINSIC Vc_PURE bool isFull() const { return data.isFull(); }
206  Vc_INTRINSIC Vc_PURE bool isNotEmpty() const { return data.isNotEmpty(); }
207  Vc_INTRINSIC Vc_PURE bool isEmpty() const { return data.isEmpty(); }
208  Vc_INTRINSIC Vc_PURE bool isMix() const { return data.isMix(); }
209 
210  Vc_INTRINSIC Vc_PURE int shiftMask() const { return data.shiftMask(); }
211 
212  Vc_INTRINSIC Vc_PURE int toInt() const { return data.toInt(); }
213 
214  Vc_INTRINSIC Vc_PURE EntryReference operator[](size_t index)
215  {
216  return data[index];
217  }
218  Vc_INTRINSIC Vc_PURE bool operator[](size_t index) const { return data[index]; }
219 
220  Vc_INTRINSIC Vc_PURE int count() const { return data.count(); }
221 
227  Vc_INTRINSIC Vc_PURE int firstOne() const { return data.firstOne(); }
228 
229  template <typename G> static Vc_INTRINSIC SimdMaskArray generate(const G &gen)
230  {
231  return {mask_type::generate(gen)};
232  }
233 
234  Vc_INTRINSIC Vc_PURE SimdMaskArray shifted(int amount) const
235  {
236  return {data.shifted(amount)};
237  }
238 
240  template <typename Op, typename... Args>
241  static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
242  {
243  SimdMaskArray r;
244  Common::unpackArgumentsAuto(op, r.data, std::forward<Args>(args)...);
245  return r;
246  }
247 
249  Vc_INTRINSIC SimdMaskArray(mask_type &&x) : data(std::move(x)) {}
250 
252  void setEntry(size_t index, bool x) { data.setEntry(index, x); }
253 
254 private:
255  storage_type data;
256 };
257 
258 template <typename T, std::size_t N, typename VectorType> constexpr std::size_t SimdMaskArray<T, N, VectorType, N>::Size;
259 template <typename T, std::size_t N, typename VectorType>
261 
262 // generic SimdArray {{{1
286 template <typename T, size_t N, typename V, size_t Wt>
287 class alignas(((Common::nextPowerOfTwo(N) * (sizeof(V) / V::size()) - 1) & 127) +
289  1) SimdMaskArray
290 {
291  static constexpr std::size_t N0 = Common::nextPowerOfTwo(N - N / 2);
292 
293  using Split = Common::Split<N0>;
294 
295 public:
296  using storage_type0 = SimdMaskArray<T, N0>;
297  using storage_type1 = SimdMaskArray<T, N - N0>;
298  static_assert(storage_type0::size() == N0, "");
299 
300  using vector_type = V;
301 
302  friend storage_type0 &internal_data0(SimdMaskArray &m) { return m.data0; }
303  friend storage_type1 &internal_data1(SimdMaskArray &m) { return m.data1; }
304  friend const storage_type0 &internal_data0(const SimdMaskArray &m) { return m.data0; }
305  friend const storage_type1 &internal_data1(const SimdMaskArray &m) { return m.data1; }
306 
308 
310  static constexpr std::size_t size() { return N; }
312  static constexpr std::size_t Size = size();
314  static constexpr std::size_t MemoryAlignment =
318  static_assert(Size == mask_type::Size, "size mismatch");
319 
321  using vectorentry_type = typename storage_type0::VectorEntryType;
323  using vectorentry_reference = vectorentry_type &;
325  using value_type = typename storage_type0::EntryType;
327  using MaskType = mask_type;
329  using VectorEntryType = vectorentry_type;
331  using EntryType = value_type;
333  using EntryReference = typename std::conditional<
334  std::is_same<typename storage_type0::EntryReference,
336  typename storage_type0::EntryReference, Common::MaskEntry<SimdMaskArray>>::type;
339 
340  Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(mask_type));
341 
342  // zero init
344  SimdMaskArray() = default;
345 
346  // default copy ctor/operator
347  SimdMaskArray(const SimdMaskArray &) = default;
348  SimdMaskArray(SimdMaskArray &&) = default;
349  SimdMaskArray &operator=(const SimdMaskArray &) = default;
350  SimdMaskArray &operator=(SimdMaskArray &&) = default;
351 
352  // implicit conversion from SimdMaskArray with same N
353  template <typename U, typename W>
354  Vc_INTRINSIC SimdMaskArray(const SimdMaskArray<U, N, W> &rhs)
355  : data0(Split::lo(rhs)), data1(Split::hi(rhs))
356  {
357  }
358 
359  // conversion from any Segment object (could be SimdMaskArray or Mask<T>)
360  template <typename M, std::size_t Pieces, std::size_t Index>
361  Vc_INTRINSIC SimdMaskArray(
362  Common::Segment<M, Pieces, Index> &&rhs,
363  enable_if<Traits::simd_vector_size<M>::value == Size * Pieces> = nullarg)
364  : data0(Split::lo(rhs)), data1(Split::hi(rhs))
365  {
366  }
367 
368  // conversion from Mask<T>
369  template <typename M>
370  Vc_INTRINSIC SimdMaskArray(
371  M k,
372  enable_if<(Traits::is_simd_mask<M>::value && !Traits::isSimdMaskArray<M>::value &&
373  Traits::simd_vector_size<M>::value == Size)> = nullarg)
374  : data0(Split::lo(k)), data1(Split::hi(k))
375  {
376  }
377 
378  // implicit conversion to Mask<U, AnyAbi> for if Mask<U, AnyAbi>::size() == N
379  template <typename M,
380  typename = enable_if<Traits::is_simd_mask<M>::value &&
381  !Traits::isSimdMaskArray<M>::value && M::size() == N>>
382  operator M() const
383  {
384  return simd_cast<M>(*this);
385  }
386 
388  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerOne one)
389  : data0(one), data1(one)
390  {
391  }
393  Vc_INTRINSIC explicit SimdMaskArray(VectorSpecialInitializerZero zero)
394  : data0(zero), data1(zero)
395  {
396  }
398  Vc_INTRINSIC explicit SimdMaskArray(bool b) : data0(b), data1(b) {}
399 
401  Vc_INTRINSIC static SimdMaskArray Zero() { return {storage_type0::Zero(), storage_type1::Zero()}; }
403  Vc_INTRINSIC static SimdMaskArray One() { return {storage_type0::One(), storage_type1::One()}; }
404 
407 
414  template <typename Flags = DefaultLoadTag>
415  Vc_INTRINSIC explicit SimdMaskArray(const bool *mem, Flags f = Flags())
416  : data0(mem, f), data1(mem + storage_type0::size(), f)
417  {
418  }
419 
425  Vc_INTRINSIC void load(const bool *mem)
426  {
427  data0.load(mem);
428  data1.load(mem + storage_type0::size());
429  }
430 
437  template <typename Flags> Vc_INTRINSIC void load(const bool *mem, Flags f)
438  {
439  data0.load(mem, f);
440  data1.load(mem + storage_type0::size(), f);
441  }
442 
448  Vc_INTRINSIC void store(bool *mem) const
449  {
450  data0.store(mem);
451  data1.store(mem + storage_type0::size());
452  }
453 
460  template <typename Flags> Vc_INTRINSIC void store(bool *mem, Flags f) const
461  {
462  data0.store(mem, f);
463  data1.store(mem + storage_type0::size(), f);
464  }
466 
468  Vc_INTRINSIC Vc_PURE bool operator==(const SimdMaskArray &mask) const
469  {
470  return data0 == mask.data0 && data1 == mask.data1;
471  }
473  Vc_INTRINSIC Vc_PURE bool operator!=(const SimdMaskArray &mask) const
474  {
475  return data0 != mask.data0 || data1 != mask.data1;
476  }
477 
479  Vc_INTRINSIC Vc_PURE SimdMaskArray operator!() const
480  {
481  return {!data0, !data1};
482  }
483 
485  Vc_INTRINSIC SimdMaskArray &operator&=(const SimdMaskArray &rhs)
486  {
487  data0 &= rhs.data0;
488  data1 &= rhs.data1;
489  return *this;
490  }
492  Vc_INTRINSIC SimdMaskArray &operator|=(const SimdMaskArray &rhs)
493  {
494  data0 |= rhs.data0;
495  data1 |= rhs.data1;
496  return *this;
497  }
499  Vc_INTRINSIC SimdMaskArray &operator^=(const SimdMaskArray &rhs)
500  {
501  data0 ^= rhs.data0;
502  data1 ^= rhs.data1;
503  return *this;
504  }
505 
507  Vc_INTRINSIC Vc_PURE SimdMaskArray operator&(const SimdMaskArray &rhs) const
508  {
509  return {data0 & rhs.data0, data1 & rhs.data1};
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  }
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 bool isFull() const { return data0.isFull() && data1.isFull(); }
536  Vc_INTRINSIC Vc_PURE bool isNotEmpty() const { return data0.isNotEmpty() || data1.isNotEmpty(); }
538  Vc_INTRINSIC Vc_PURE bool isEmpty() const { return data0.isEmpty() && data1.isEmpty(); }
540  Vc_INTRINSIC Vc_PURE bool isMix() const { return !isFull() && !isEmpty(); }
541 
543  Vc_INTRINSIC Vc_PURE int toInt() const
544  {
545  return data0.toInt() | (data1.toInt() << data0.size());
546  }
547 
548 private:
549  template <typename R>
550  R subscript_impl(
551  size_t index,
552  enable_if<std::is_same<R, typename storage_type0::EntryReference>::value> =
553  nullarg)
554  {
555  if (index < storage_type0::size()) {
556  return data0[index];
557  } else {
558  return data1[index - storage_type0::size()];
559  }
560  }
561  template <typename R>
562  R subscript_impl(
563  size_t index,
564  enable_if<!std::is_same<R, typename storage_type0::EntryReference>::value> =
565  nullarg)
566  {
567  return {*this, index};
568  }
569 
570 public:
572  void setEntry(size_t index, bool x)
573  {
574  if (index < data0.size()) {
575  data0.setEntry(index, x);
576  } else {
577  data1.setEntry(index - data0.size(), x);
578  }
579  }
580 
589  Vc_INTRINSIC Vc_PURE EntryReference operator[](size_t index) {
590  return subscript_impl<EntryReference>(index);
591  }
600  Vc_INTRINSIC Vc_PURE bool operator[](size_t index) const {
601  if (index < storage_type0::size()) {
602  return data0[index];
603  } else {
604  return data1[index - storage_type0::size()];
605  }
606  }
607 
609  Vc_INTRINSIC Vc_PURE int count() const { return data0.count() + data1.count(); }
610 
612  Vc_INTRINSIC Vc_PURE int firstOne() const {
613  if (data0.isEmpty()) {
614  return data1.firstOne() + storage_type0::size();
615  }
616  return data0.firstOne();
617  }
618 
620  template <typename G> static Vc_INTRINSIC SimdMaskArray generate(const G &gen)
621  {
622  return {storage_type0::generate(gen),
623  storage_type1::generate([&](std::size_t i) { return gen(i + N0); })};
624  }
625 
627  inline Vc_PURE SimdMaskArray shifted(int amount) const
628  {
629  if (Vc_IS_UNLIKELY(amount == 0)) {
630  return *this;
631  }
632  SimdMaskArray r{};
633  if (amount < 0) {
634  for (int i = 0; i < int(Size) + amount; ++i) {
635  r[i - amount] = operator[](i);
636  }
637  } else {
638  for (int i = 0; i < int(Size) - amount; ++i) {
639  r[i] = operator[](i + amount);
640  }
641  }
642  return r;
643  }
644 
646  template <typename Op, typename... Args>
647  static Vc_INTRINSIC SimdMaskArray fromOperation(Op op, Args &&... args)
648  {
649  SimdMaskArray r = {
650  storage_type0::fromOperation(op, Split::lo(args)...), // no forward here - it
651  // could move and thus
652  // break the next line
653  storage_type1::fromOperation(op, Split::hi(std::forward<Args>(args))...)};
654  return r;
655  }
656 
658  Vc_INTRINSIC SimdMaskArray(storage_type0 &&x, storage_type1 &&y)
659  : data0(std::move(x)), data1(std::move(y))
660  {
661  }
662 
663 private:
664  storage_type0 data0;
665  storage_type1 data1;
666 };
667 template <typename T, std::size_t N, typename V, std::size_t M>
668 constexpr std::size_t SimdMaskArray<T, N, V, M>::Size;
669 template <typename T, std::size_t N, typename V, std::size_t M>
670 constexpr std::size_t SimdMaskArray<T, N, V, M>::MemoryAlignment;
671 
674 
675 } // namespace Vc
676 
677 // XXX: this include should be in <Vc/vector.h>. But at least clang 3.4 then fails to compile the
678 // code. Not sure yet what is going on, but it looks a lot like a bug in clang.
679 #include "simd_cast_caller.tcc"
680 
#endif // VC_COMMON_SIMDMASKARRAY_H_
// vim: foldmethod=marker
Vc::SimdMaskArray::EntryReference
typename std::conditional< std::is_same< typename storage_type0::EntryReference, typename storage_type1::EntryReference >::value, typename storage_type0::EntryReference, Common::MaskEntry< SimdMaskArray >>::type EntryReference
The reference wrapper type used for accessing individual mask components.
Definition: simdmaskarray.h:333
Vc::operator|
result_vector_type< L, R > operator|(L &&lhs, R &&rhs)
Applies | component-wise and concurrently.
Definition: simdarray.h:1445
Vc::operator^
result_vector_type< L, R > operator^(L &&lhs, R &&rhs)
Applies ^ component-wise and concurrently.
Definition: simdarray.h:1445
std
Definition: vector.h:258
Vc::operator!=
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1475
Vc::SimdArray
Data-parallel arithmetic type with user-defined number of elements.
Definition: simdarray.h:506
Vc::Traits::simd_vector_size
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:172
Vc::simd_cast
enable_if< std::is_same< To, Traits::decay< From > >::value, To > simd_cast(From &&x)
Casts the argument x from type From to type To.
Definition: simd_cast.h:49
Vc::SimdMaskArray
Data-parallel mask type with user-defined number of boolean elements.
Definition: simdarrayfwd.h:126
Vc::operator==
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
Definition: simdarray.h:1475
Vc::operator&
result_vector_type< L, R > operator&(L &&lhs, R &&rhs)
Applies & component-wise and concurrently.
Definition: simdarray.h:1445
Vc::Zero
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
Definition: types.h:85
Vc::SimdizeDetail::shifted
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:993
Vc::One
constexpr VectorSpecialInitializerOne One
The special object Vc::One can be used to construct Vector and Mask objects initialized to one/true...
Definition: types.h:90
Vc::MemoryAlignment
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
Definition: vector.h:219