File indexing completed on 2025-01-31 10:25:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef VC_AVX_MASK_H_
0029 #define VC_AVX_MASK_H_
0030
0031 #include <array>
0032
0033 #include "intrinsics.h"
0034 #include "../common/storage.h"
0035 #include "../common/bitscanintrinsics.h"
0036 #include "../common/maskbool.h"
0037 #include "detail.h"
0038 #include "macros.h"
0039
0040 namespace Vc_VERSIONED_NAMESPACE
0041 {
0042 template <typename T> class Mask<T, VectorAbi::Avx>
0043 {
0044 public:
0045 using abi = VectorAbi::Avx;
0046
0047
0048
0049
0050 typedef bool EntryType;
0051 using value_type = EntryType;
0052
0053 using MaskBool = Common::MaskBool<sizeof(T)>;
0054
0055
0056
0057
0058 using VectorEntryType = MaskBool;
0059
0060
0061
0062
0063 using Vector = AVX2::Vector<T>;
0064
0065
0066 using VectorTypeF = AVX::FloatVectorType<typename AVX::VectorTypeHelper<T>::Type>;
0067
0068 using VectorTypeD = AVX::DoubleVectorType<VectorTypeF>;
0069
0070 using VectorTypeI = AVX::IntegerVectorType<VectorTypeF>;
0071
0072 private:
0073 typedef const VectorTypeF VArg;
0074 typedef const VectorTypeD VdArg;
0075 typedef const VectorTypeI ViArg;
0076
0077 public:
0078 static constexpr size_t Size = sizeof(VectorTypeF) / sizeof(T);
0079 static constexpr size_t MemoryAlignment = Size;
0080 static constexpr std::size_t size() { return Size; }
0081 Vc_FREE_STORE_OPERATORS_ALIGNED(alignof(VectorType));
0082
0083 private:
0084 typedef Common::Storage<T, Size> Storage;
0085
0086 public:
0087
0088
0089
0090
0091 using VectorType = typename Storage::VectorType;
0092
0093 using EntryReference = Vc::Detail::ElementReference<Mask>;
0094 using reference = EntryReference;
0095
0096
0097 #if defined Vc_MSVC && defined _WIN32
0098 typedef const Mask &AsArg;
0099 #else
0100 typedef const Mask AsArg;
0101 #endif
0102
0103 Vc_INTRINSIC Mask() {}
0104 Vc_INTRINSIC Mask(VArg x) : d(AVX::avx_cast<VectorType>(x)) {}
0105 Vc_INTRINSIC Mask(VdArg x) : d(AVX::avx_cast<VectorType>(x)) {}
0106 Vc_INTRINSIC Mask(ViArg x) : d(AVX::avx_cast<VectorType>(x)) {}
0107 Vc_INTRINSIC explicit Mask(VectorSpecialInitializerZero) : d(Detail::zero<VectorType>()) {}
0108 Vc_INTRINSIC explicit Mask(VectorSpecialInitializerOne) : d(Detail::allone<VectorType>()) {}
0109 Vc_INTRINSIC explicit Mask(bool b)
0110 : d(b ? Detail::allone<VectorType>() : Detail::zero<VectorType>())
0111 {
0112 }
0113 Vc_INTRINSIC static Mask Zero() { return Mask{Vc::Zero}; }
0114 Vc_INTRINSIC static Mask One() { return Mask{Vc::One}; }
0115
0116
0117 template <typename U>
0118 Vc_INTRINSIC Mask(
0119 U &&rhs, Common::enable_if_mask_converts_implicitly<Mask, T, U> = nullarg)
0120 : d(AVX::avx_cast<VectorType>(
0121 Detail::mask_cast<Traits::decay<U>::Size, Size, VectorTypeF>(
0122 rhs.dataI())))
0123 {
0124 }
0125
0126 #if Vc_IS_VERSION_1
0127
0128 template <typename U>
0129 Vc_DEPRECATED("use simd_cast instead of explicit type casting to convert between "
0130 "mask types") Vc_INTRINSIC
0131 explicit Mask(U &&rhs,
0132 Common::enable_if_mask_converts_explicitly<T, U> = nullarg);
0133 #endif
0134
0135 template<typename Flags = DefaultLoadTag> Vc_INTRINSIC explicit Mask(const bool *mem, Flags f = Flags()) { load(mem, f); }
0136
0137 template<typename Flags = DefaultLoadTag> Vc_INTRINSIC void load(const bool *mem, Flags = Flags());
0138
0139 template<typename Flags = DefaultLoadTag> Vc_INTRINSIC void store(bool *mem, Flags = Flags()) const;
0140
0141 Vc_INTRINSIC Mask &operator=(const Mask &) = default;
0142 Vc_INTRINSIC_L Mask &operator=(const std::array<bool, Size> &values) Vc_INTRINSIC_R;
0143 Vc_INTRINSIC_L operator std::array<bool, Size>() const Vc_INTRINSIC_R;
0144
0145
0146 Vc_INTRINSIC Vc_PURE bool operator==(const Mask &rhs) const
0147 { return Detail::movemask(d.v()) == Detail::movemask(rhs.d.v()); }
0148
0149 Vc_INTRINSIC Vc_PURE bool operator!=(const Mask &rhs) const
0150 { return !operator==(rhs); }
0151
0152 Vc_INTRINSIC Mask operator!() const
0153 {
0154 #ifdef Vc_GCC
0155 return ~dataI();
0156 #else
0157 return Detail::andnot_(dataF(), Detail::allone<VectorTypeF>());
0158 #endif
0159 }
0160
0161 Vc_INTRINSIC Mask &operator&=(const Mask &rhs) { d.v() = AVX::avx_cast<VectorType>(Detail::and_(data(), rhs.data())); return *this; }
0162 Vc_INTRINSIC Mask &operator|=(const Mask &rhs) { d.v() = AVX::avx_cast<VectorType>(Detail::or_ (data(), rhs.data())); return *this; }
0163 Vc_INTRINSIC Mask &operator^=(const Mask &rhs) { d.v() = AVX::avx_cast<VectorType>(Detail::xor_(data(), rhs.data())); return *this; }
0164
0165 Vc_INTRINSIC Vc_PURE Mask operator&(const Mask &rhs) const { return Detail::and_(data(), rhs.data()); }
0166 Vc_INTRINSIC Vc_PURE Mask operator|(const Mask &rhs) const { return Detail::or_(data(), rhs.data()); }
0167 Vc_INTRINSIC Vc_PURE Mask operator^(const Mask &rhs) const { return Detail::xor_(data(), rhs.data()); }
0168
0169 Vc_INTRINSIC Vc_PURE Mask operator&&(const Mask &rhs) const { return Detail::and_(data(), rhs.data()); }
0170 Vc_INTRINSIC Vc_PURE Mask operator||(const Mask &rhs) const { return Detail::or_(data(), rhs.data()); }
0171
0172
0173
0174 Vc_INTRINSIC_L bool isNotEmpty() const Vc_INTRINSIC_R;
0175 Vc_INTRINSIC_L bool isEmpty() const Vc_INTRINSIC_R;
0176 Vc_INTRINSIC_L bool isFull() const Vc_INTRINSIC_R;
0177 Vc_INTRINSIC_L bool isMix() const Vc_INTRINSIC_R;
0178
0179 Vc_INTRINSIC Vc_PURE int shiftMask() const { return Detail::movemask(dataI()); }
0180 Vc_INTRINSIC Vc_PURE int toInt() const { return Detail::mask_to_int<Size>(dataI()); }
0181
0182 Vc_INTRINSIC VectorType data () const { return d.v(); }
0183 Vc_INTRINSIC VectorTypeF dataF() const { return AVX::avx_cast<VectorTypeF>(d.v()); }
0184 Vc_INTRINSIC VectorTypeI dataI() const { return AVX::avx_cast<VectorTypeI>(d.v()); }
0185 Vc_INTRINSIC VectorTypeD dataD() const { return AVX::avx_cast<VectorTypeD>(d.v()); }
0186
0187 private:
0188 friend reference;
0189 static Vc_INTRINSIC Vc_PURE value_type get(const Mask &m, int i) noexcept
0190 {
0191 return m.toInt() & (1 << i);
0192 }
0193 template <typename U>
0194 static Vc_INTRINSIC void set(Mask &m, int i,
0195 U &&v) noexcept(noexcept(MaskBool(std::declval<U>())))
0196 {
0197 m.d.set(i, MaskBool(std::forward<U>(v)));
0198 }
0199
0200 public:
0201
0202
0203
0204
0205
0206
0207 Vc_ALWAYS_INLINE reference operator[](size_t index) noexcept
0208 {
0209 return {*this, int(index)};
0210 }
0211 Vc_ALWAYS_INLINE Vc_PURE value_type operator[](size_t index) const noexcept
0212 {
0213 return get(*this, index);
0214 }
0215
0216 Vc_INTRINSIC Vc_PURE int count() const { return Detail::popcnt16(toInt()); }
0217 Vc_INTRINSIC Vc_PURE int firstOne() const { return _bit_scan_forward(toInt()); }
0218
0219 template <typename G> static Vc_INTRINSIC_L Mask generate(G &&gen) Vc_INTRINSIC_R;
0220 Vc_INTRINSIC_L Vc_PURE_L Mask shifted(int amount) const Vc_INTRINSIC_R Vc_PURE_R;
0221
0222 private:
0223 #ifdef Vc_COMPILE_BENCHMARKS
0224 public:
0225 #endif
0226 Storage d;
0227 };
0228 template <typename T> constexpr size_t Mask<T, VectorAbi::Avx>::Size;
0229 template <typename T> constexpr size_t Mask<T, VectorAbi::Avx>::MemoryAlignment;
0230
0231 }
0232
0233 #include "mask.tcc"
0234
0235 #endif