Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:25:33

0001 /*  This file is part of the Vc library. {{{
0002 Copyright © 2009-2015 Matthias Kretz <kretz@kde.org>
0003 
0004 Redistribution and use in source and binary forms, with or without
0005 modification, are permitted provided that the following conditions are met:
0006     * Redistributions of source code must retain the above copyright
0007       notice, this list of conditions and the following disclaimer.
0008     * Redistributions in binary form must reproduce the above copyright
0009       notice, this list of conditions and the following disclaimer in the
0010       documentation and/or other materials provided with the distribution.
0011     * Neither the names of contributing organizations nor the
0012       names of its contributors may be used to endorse or promote products
0013       derived from this software without specific prior written permission.
0014 
0015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0016 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0017 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0018 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
0019 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0020 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0021 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0022 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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      * The \c EntryType of masks is always bool, independent of \c T.
0049      */
0050     typedef bool EntryType;
0051     using value_type = EntryType;
0052 
0053     using MaskBool = Common::MaskBool<sizeof(T)>;
0054     /**
0055      * The \c VectorEntryType, in contrast to \c EntryType, reveals information about the SIMD
0056      * implementation. This type is useful for the \c sizeof operator in generic functions.
0057      */
0058     using VectorEntryType = MaskBool;
0059 
0060     /**
0061      * The associated Vector<T> type.
0062      */
0063     using Vector = AVX2::Vector<T>;
0064 
0065     ///\internal
0066     using VectorTypeF = AVX::FloatVectorType<typename AVX::VectorTypeHelper<T>::Type>;
0067     ///\internal
0068     using VectorTypeD = AVX::DoubleVectorType<VectorTypeF>;
0069     ///\internal
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      * The \c VectorType reveals the implementation-specific internal type used for the
0089      * SIMD type.
0090      */
0091     using VectorType = typename Storage::VectorType;
0092 
0093     using EntryReference = Vc::Detail::ElementReference<Mask>;
0094     using reference = EntryReference;
0095 
0096         // abstracts the way Masks are passed to functions, it can easily be changed to const ref here
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         // implicit cast
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         // explicit cast, implemented via simd_cast (in avx/simd_cast_caller.h)
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         // specializations in mask.tcc
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         // no need for expression template optimizations because cmp(n)eq for floats are not bitwise
0173         // compares
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      * \note the returned object models the concept of a reference and
0203      * as such it can exist longer than the data it is referencing.
0204      * \note to avoid lifetime issues, we strongly advice not to store
0205      * any reference objects.
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 }  // namespace Vc
0232 
0233 #include "mask.tcc"
0234 
0235 #endif // VC_AVX_MASK_H_