File indexing completed on 2025-01-30 10:25:46
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_COMMON_ITERATORS_H_
0029 #define VC_COMMON_ITERATORS_H_
0030
0031 #include <array>
0032 #include <iterator>
0033 #ifdef Vc_MSVC
0034 #include <intrin.h> // for _BitScanForward
0035 #endif
0036 #include "where.h"
0037 #include "elementreference.h"
0038 #include "macros.h"
0039
0040 namespace Vc_VERSIONED_NAMESPACE
0041 {
0042 namespace Common
0043 {
0044
0045 template<typename _V, typename Flags> class MemoryVector;
0046 template<typename _V, typename Flags> class MemoryVectorIterator;
0047
0048 template <typename V> class Iterator;
0049 template <typename V, bool> class IteratorBase;
0050 template <typename V> class IteratorBase<V, true>
0051 {
0052 public:
0053 using iterator_category = std::input_iterator_tag;
0054 using value_type = typename V::value_type;
0055 using difference_type = int;
0056 using reference = value_type;
0057 Vc_ALWAYS_INLINE reference operator*() const { return v()[i()]; }
0058 Vc_ALWAYS_INLINE reference operator[](difference_type i2) const { return v()[i2]; }
0059
0060 private:
0061 Vc_INTRINSIC V &v() const { return *static_cast<const Iterator<V> *>(this)->v; }
0062 Vc_INTRINSIC difference_type i() const
0063 {
0064 return static_cast<const Iterator<V> *>(this)->i;
0065 }
0066 };
0067
0068 template <typename V> class IteratorBase<V, false>
0069 {
0070 public:
0071 using iterator_category = std::input_iterator_tag;
0072 using value_type = typename V::value_type;
0073 using difference_type = int;
0074 using reference = Vc::Detail::ElementReference<V, IteratorBase>;
0075 Vc_ALWAYS_INLINE reference operator*() const { return {*v(), i()}; }
0076 Vc_ALWAYS_INLINE reference operator[](difference_type i2) const { return {*v(), i2}; }
0077
0078 private:
0079 Vc_INTRINSIC V *v() const { return static_cast<const Iterator<V> *>(this)->v; }
0080 Vc_INTRINSIC difference_type i() const
0081 {
0082 return static_cast<const Iterator<V> *>(this)->i;
0083 }
0084
0085 friend reference;
0086 static Vc_INTRINSIC value_type get(const V &o, int i)
0087 {
0088 return o[i];
0089 }
0090 template <typename T> static Vc_INTRINSIC void set(V &o, int i, T &&v)
0091 {
0092 o[i] = std::forward<T>(v);
0093 }
0094 };
0095
0096
0097 template <typename V> class Iterator : public IteratorBase<V, std::is_const<V>::value>
0098 {
0099 using Base = IteratorBase<V, std::is_const<V>::value>;
0100 friend Base;
0101
0102 public:
0103 using typename Base::iterator_category;
0104 using typename Base::value_type;
0105 using typename Base::difference_type;
0106 using pointer = const Iterator *;
0107 using typename Base::reference;
0108
0109 constexpr Iterator() = default;
0110 constexpr Iterator(V &_v, difference_type _i) : v(&_v), i(_i) {}
0111
0112
0113 Vc_ALWAYS_INLINE pointer operator->() const { return this; }
0114 using Base::operator*;
0115
0116 Vc_ALWAYS_INLINE Iterator &operator++() { ++i; return *this; }
0117 Vc_ALWAYS_INLINE Iterator operator++(int) { Iterator tmp = *this; ++i; return tmp; }
0118
0119
0120 Vc_ALWAYS_INLINE Iterator &operator--() { --i; return *this; }
0121 Vc_ALWAYS_INLINE Iterator operator--(int) { Iterator tmp = *this; --i; return tmp; }
0122
0123
0124 using Base::operator[];
0125 Vc_ALWAYS_INLINE Iterator &operator+=(difference_type d) { i += d; return *this; }
0126 Vc_ALWAYS_INLINE Iterator &operator-=(difference_type d) { i -= d; return *this; }
0127 Vc_ALWAYS_INLINE Iterator operator+(difference_type d) const { return {*v, i + d}; }
0128 Vc_ALWAYS_INLINE Iterator operator-(difference_type d) const { return {*v, i - d}; }
0129 Vc_ALWAYS_INLINE difference_type operator-(const Iterator &rhs) const { return i - rhs.i; }
0130 friend Vc_ALWAYS_INLINE Iterator operator+(difference_type d, const Iterator &rhs)
0131 {
0132 return {*rhs.v, rhs.i + d};
0133 }
0134
0135
0136
0137 Vc_ALWAYS_INLINE bool operator==(const Iterator<V> &rhs) const { return v == rhs.v && i == rhs.i; }
0138 Vc_ALWAYS_INLINE bool operator!=(const Iterator<V> &rhs) const { return v == rhs.v && i != rhs.i; }
0139 Vc_ALWAYS_INLINE bool operator< (const Iterator<V> &rhs) const { return v == rhs.v && i < rhs.i; }
0140 Vc_ALWAYS_INLINE bool operator<=(const Iterator<V> &rhs) const { return v == rhs.v && i <= rhs.i; }
0141 Vc_ALWAYS_INLINE bool operator> (const Iterator<V> &rhs) const { return v == rhs.v && i > rhs.i; }
0142 Vc_ALWAYS_INLINE bool operator>=(const Iterator<V> &rhs) const { return v == rhs.v && i >= rhs.i; }
0143
0144 private:
0145 V *v = nullptr;
0146 difference_type i = 0;
0147 };
0148
0149 template <typename V> using ConstIterator = Iterator<const V>;
0150
0151 class BitmaskIterator
0152 {
0153 #ifdef Vc_MSVC
0154 unsigned long mask;
0155 unsigned long bit;
0156 #else
0157 size_t mask;
0158 size_t bit;
0159 #endif
0160
0161 void nextBit()
0162 {
0163 #ifdef Vc_GNU_ASM
0164 bit = __builtin_ctzl(mask);
0165 #elif defined(Vc_MSVC)
0166 _BitScanForward(&bit, mask);
0167 #else
0168 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
0169 #endif
0170 }
0171 void resetLsb()
0172 {
0173
0174 mask &= (mask - 1);
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 }
0187 public:
0188 BitmaskIterator(decltype(mask) m) : mask(m) { nextBit(); }
0189 BitmaskIterator(const BitmaskIterator &) = default;
0190 BitmaskIterator(BitmaskIterator &&) = default;
0191
0192 Vc_ALWAYS_INLINE size_t operator->() const { return bit; }
0193 Vc_ALWAYS_INLINE size_t operator*() const { return bit; }
0194
0195 Vc_ALWAYS_INLINE BitmaskIterator &operator++() { resetLsb(); nextBit(); return *this; }
0196 Vc_ALWAYS_INLINE BitmaskIterator operator++(int) { BitmaskIterator tmp = *this; resetLsb(); nextBit(); return tmp; }
0197
0198 Vc_ALWAYS_INLINE bool operator==(const BitmaskIterator &rhs) const { return mask == rhs.mask; }
0199 Vc_ALWAYS_INLINE bool operator!=(const BitmaskIterator &rhs) const { return mask != rhs.mask; }
0200 };
0201
0202 template <typename T>
0203 Vc_ALWAYS_INLINE
0204 enable_if<Traits::is_simd_vector<T>::value || Traits::is_simd_mask<T>::value,
0205 Iterator<typename std::remove_reference<T>::type>>
0206 begin(T &&x)
0207 {
0208 return {std::forward<T>(x), 0};
0209 }
0210
0211 template <typename T>
0212 Vc_ALWAYS_INLINE
0213 enable_if<Traits::is_simd_vector<T>::value || Traits::is_simd_mask<T>::value,
0214 Iterator<typename std::remove_reference<T>::type>>
0215 end(T &&x)
0216 {
0217 using TT = typename std::decay<T>::type;
0218 return {std::forward<T>(x), int(TT::size())};
0219 }
0220
0221 template <typename T>
0222 Vc_ALWAYS_INLINE enable_if<
0223 Traits::is_simd_mask<T>::value || Traits::is_simd_vector<T>::value, ConstIterator<T>>
0224 cbegin(const T &v)
0225 {
0226 return {v, 0};
0227 }
0228
0229 template <typename T>
0230 Vc_ALWAYS_INLINE enable_if<
0231 Traits::is_simd_mask<T>::value || Traits::is_simd_vector<T>::value, ConstIterator<T>>
0232 cend(const T &v)
0233 {
0234 return {v, int(T::size())};
0235 }
0236
0237 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator begin(const WhereImpl::WhereMask<M> &w)
0238 {
0239 return w.mask.toInt();
0240 }
0241
0242 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator end(const WhereImpl::WhereMask<M> &)
0243 {
0244 return 0;
0245 }
0246
0247 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
0248 makeIterator(T *mem, Flags)
0249 {
0250 return new(mem) MemoryVector<V, Flags>;
0251 }
0252
0253 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
0254 makeIterator(const T *mem, Flags)
0255 {
0256 return new(const_cast<T *>(mem)) MemoryVector<const V, Flags>;
0257 }
0258
0259 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
0260 makeIterator(MemoryVector<V, FlagsX> &mv, Flags)
0261 {
0262 return new(&mv) MemoryVector<V, Flags>;
0263 }
0264
0265 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
0266 makeIterator(MemoryVector<const V, FlagsX> &mv, Flags)
0267 {
0268 return new(&mv) MemoryVector<const V, Flags>;
0269 }
0270
0271 }
0272
0273 using Common::begin;
0274 using Common::end;
0275 using Common::cbegin;
0276 using Common::cend;
0277 using Common::makeIterator;
0278 }
0279
0280 #endif
0281
0282