Vc  1.3.2-dev
SIMD Vector Classes for C++
iterators.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_ITERATORS_H_
29 #define VC_COMMON_ITERATORS_H_
30 
31 #include <array>
32 #include <iterator>
33 #ifdef Vc_MSVC
34 #include <intrin.h> // for _BitScanForward
35 #endif // Vc_MSVC
36 #include "where.h"
37 #include "elementreference.h"
38 #include "macros.h"
39 
40 namespace Vc_VERSIONED_NAMESPACE
41 {
42 namespace Common
43 {
44 
45 template<typename _V, typename Flags> class MemoryVector;
46 template<typename _V, typename Flags> class MemoryVectorIterator;
47 
48 template <typename V> class Iterator;
49 template <typename V, bool> class IteratorBase;
50 template <typename V> class IteratorBase<V, true>
51 {
52 public:
53  using iterator_category = std::input_iterator_tag;
54  using value_type = typename V::value_type;
55  using difference_type = int;
56  using reference = value_type;
57  Vc_ALWAYS_INLINE reference operator*() const { return v()[i()]; }
58  Vc_ALWAYS_INLINE reference operator[](difference_type i2) const { return v()[i2]; }
59 
60 private:
61  Vc_INTRINSIC V &v() const { return *static_cast<const Iterator<V> *>(this)->v; }
62  Vc_INTRINSIC difference_type i() const
63  {
64  return static_cast<const Iterator<V> *>(this)->i;
65  }
66 };
67 
68 template <typename V> class IteratorBase<V, false>
69 {
70 public:
71  using iterator_category = std::input_iterator_tag;
72  using value_type = typename V::value_type;
73  using difference_type = int;
74  using reference = Vc::Detail::ElementReference<V, IteratorBase>;
75  Vc_ALWAYS_INLINE reference operator*() const { return {*v(), i()}; }
76  Vc_ALWAYS_INLINE reference operator[](difference_type i2) const { return {*v(), i2}; }
77 
78 private:
79  Vc_INTRINSIC V *v() const { return static_cast<const Iterator<V> *>(this)->v; }
80  Vc_INTRINSIC difference_type i() const
81  {
82  return static_cast<const Iterator<V> *>(this)->i;
83  }
84 
85  friend reference;
86  static Vc_INTRINSIC value_type get(const V &o, int i)
87  {
88  return o[i];
89  }
90  template <typename T> static Vc_INTRINSIC void set(V &o, int i, T &&v)
91  {
92  o[i] = std::forward<T>(v);
93  }
94 };
95 
96 // class Iterator {{{
97 template <typename V> class Iterator : public IteratorBase<V, std::is_const<V>::value>
98 {
99  using Base = IteratorBase<V, std::is_const<V>::value>;
100  friend Base;
101 
102 public:
103  using typename Base::iterator_category;
104  using typename Base::value_type;
105  using typename Base::difference_type;
106  using pointer = const Iterator *;
107  using typename Base::reference;
108 
109  constexpr Iterator() = default;
110  constexpr Iterator(V &_v, difference_type _i) : v(&_v), i(_i) {}
111  // rely on implicit copy constructor/assignment
112 
113  Vc_ALWAYS_INLINE pointer operator->() const { return this; }
114  using Base::operator*;
115 
116  Vc_ALWAYS_INLINE Iterator &operator++() { ++i; return *this; }
117  Vc_ALWAYS_INLINE Iterator operator++(int) { Iterator tmp = *this; ++i; return tmp; }
118 
119  // bidirectional iteration is supported
120  Vc_ALWAYS_INLINE Iterator &operator--() { --i; return *this; }
121  Vc_ALWAYS_INLINE Iterator operator--(int) { Iterator tmp = *this; --i; return tmp; }
122 
123  // RandomAccessIterator:
124  using Base::operator[];
125  Vc_ALWAYS_INLINE Iterator &operator+=(difference_type d) { i += d; return *this; }
126  Vc_ALWAYS_INLINE Iterator &operator-=(difference_type d) { i -= d; return *this; }
127  Vc_ALWAYS_INLINE Iterator operator+(difference_type d) const { return {*v, i + d}; }
128  Vc_ALWAYS_INLINE Iterator operator-(difference_type d) const { return {*v, i - d}; }
129  Vc_ALWAYS_INLINE difference_type operator-(const Iterator &rhs) const { return i - rhs.i; }
130  friend Vc_ALWAYS_INLINE Iterator operator+(difference_type d, const Iterator &rhs)
131  {
132  return {*rhs.v, rhs.i + d};
133  }
134 
135  // InputIterator would not need to test v == rhs.v, but except for `reference` this
136  // class implements a complete RandomAccessIterator
137  Vc_ALWAYS_INLINE bool operator==(const Iterator<V> &rhs) const { return v == rhs.v && i == rhs.i; }
138  Vc_ALWAYS_INLINE bool operator!=(const Iterator<V> &rhs) const { return v == rhs.v && i != rhs.i; }
139  Vc_ALWAYS_INLINE bool operator< (const Iterator<V> &rhs) const { return v == rhs.v && i < rhs.i; }
140  Vc_ALWAYS_INLINE bool operator<=(const Iterator<V> &rhs) const { return v == rhs.v && i <= rhs.i; }
141  Vc_ALWAYS_INLINE bool operator> (const Iterator<V> &rhs) const { return v == rhs.v && i > rhs.i; }
142  Vc_ALWAYS_INLINE bool operator>=(const Iterator<V> &rhs) const { return v == rhs.v && i >= rhs.i; }
143 
144 private:
145  V *v = nullptr;
146  difference_type i = 0;
147 };/*}}}*/
148 
149 template <typename V> using ConstIterator = Iterator<const V>;
150 
151 #ifdef Vc_IMPL_MIC
152  class BitmaskIterator/*{{{*/
153  {
154  const int mask;
155  int bit;
156  public:
157  Vc_ALWAYS_INLINE BitmaskIterator(int m) : mask(m), bit(_mm_tzcnt_32(mask)) {}
158  Vc_ALWAYS_INLINE BitmaskIterator(const BitmaskIterator &) = default;
159  Vc_ALWAYS_INLINE BitmaskIterator(BitmaskIterator &&) = default;
160 
161  Vc_ALWAYS_INLINE size_t operator->() const { return bit; }
162  Vc_ALWAYS_INLINE size_t operator*() const { return bit; }
163 
164  Vc_ALWAYS_INLINE BitmaskIterator &operator++() {
165  bit = _mm_tzcnti_32(bit, mask);
166  return *this;
167  }
168  Vc_ALWAYS_INLINE BitmaskIterator operator++(int) {
169  BitmaskIterator tmp = *this;
170  bit = _mm_tzcnti_32(bit, mask);
171  return tmp;
172  }
173 
174  Vc_ALWAYS_INLINE bool operator==(const BitmaskIterator &rhs) const { return bit == rhs.bit; }
175  Vc_ALWAYS_INLINE bool operator!=(const BitmaskIterator &rhs) const { return bit != rhs.bit; }
176  };/*}}}*/
177 #else
178  class BitmaskIterator/*{{{*/
179  {
180 #ifdef Vc_MSVC
181  unsigned long mask;
182  unsigned long bit;
183 #else
184  size_t mask;
185  size_t bit;
186 #endif
187 
188  void nextBit()
189  {
190 #ifdef Vc_GNU_ASM
191  bit = __builtin_ctzl(mask);
192 #elif defined(Vc_MSVC)
193  _BitScanForward(&bit, mask);
194 #else
195 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
196 #endif
197  }
198  void resetLsb()
199  {
200  // 01100100 - 1 = 01100011
201  mask &= (mask - 1);
202  /*
203 #ifdef Vc_GNU_ASM
204  __asm__("btr %1,%0" : "+r"(mask) : "r"(bit));
205 #elif defined(_WIN64)
206  _bittestandreset64(&mask, bit);
207 #elif defined(_WIN32)
208  _bittestandreset(&mask, bit);
209 #else
210 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
211 #endif
212  */
213  }
214  public:
215  BitmaskIterator(decltype(mask) m) : mask(m) { nextBit(); }
216  BitmaskIterator(const BitmaskIterator &) = default;
217  BitmaskIterator(BitmaskIterator &&) = default;
218 
219  Vc_ALWAYS_INLINE size_t operator->() const { return bit; }
220  Vc_ALWAYS_INLINE size_t operator*() const { return bit; }
221 
222  Vc_ALWAYS_INLINE BitmaskIterator &operator++() { resetLsb(); nextBit(); return *this; }
223  Vc_ALWAYS_INLINE BitmaskIterator operator++(int) { BitmaskIterator tmp = *this; resetLsb(); nextBit(); return tmp; }
224 
225  Vc_ALWAYS_INLINE bool operator==(const BitmaskIterator &rhs) const { return mask == rhs.mask; }
226  Vc_ALWAYS_INLINE bool operator!=(const BitmaskIterator &rhs) const { return mask != rhs.mask; }
227  };/*}}}*/
228 #endif
229 
230 template <typename T>
231 Vc_ALWAYS_INLINE
232  enable_if<Traits::is_simd_vector<T>::value || Traits::is_simd_mask<T>::value,
233  Iterator<typename std::remove_reference<T>::type>>
234  begin(T &&x)
235 {
236  return {std::forward<T>(x), 0};
237 }
238 
239 template <typename T>
240 Vc_ALWAYS_INLINE
241  enable_if<Traits::is_simd_vector<T>::value || Traits::is_simd_mask<T>::value,
242  Iterator<typename std::remove_reference<T>::type>>
243  end(T &&x)
244 {
245  using TT = typename std::decay<T>::type;
246  return {std::forward<T>(x), int(TT::size())};
247 }
248 
249 template <typename T>
250 Vc_ALWAYS_INLINE enable_if<
251  Traits::is_simd_mask<T>::value || Traits::is_simd_vector<T>::value, ConstIterator<T>>
252 cbegin(const T &v)
253 {
254  return {v, 0};
255 }
256 
257 template <typename T>
258 Vc_ALWAYS_INLINE enable_if<
259  Traits::is_simd_mask<T>::value || Traits::is_simd_vector<T>::value, ConstIterator<T>>
260 cend(const T &v)
261 {
262  return {v, int(T::size())};
263 }
264 
265 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator begin(const WhereImpl::WhereMask<M> &w)
266 {
267  return w.mask.toInt();
268 }
269 
270 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator end(const WhereImpl::WhereMask<M> &)
271 {
272  return 0;
273 }
274 
275 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
276  makeIterator(T *mem, Flags)
277 {
278  return new(mem) MemoryVector<V, Flags>;
279 }
280 
281 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
282  makeIterator(const T *mem, Flags)
283 {
284  return new(const_cast<T *>(mem)) MemoryVector<const V, Flags>;
285 }
286 
287 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
288  makeIterator(MemoryVector<V, FlagsX> &mv, Flags)
289 {
290  return new(&mv) MemoryVector<V, Flags>;
291 }
292 
293 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
294  makeIterator(MemoryVector<const V, FlagsX> &mv, Flags)
295 {
296  return new(&mv) MemoryVector<const V, Flags>;
297 }
298 
299 } // namespace Common
300 
301 using Common::begin;
302 using Common::end;
303 using Common::cbegin;
304 using Common::cend;
305 using Common::makeIterator;
306 } // namespace Vc
307 
308 #endif // VC_COMMON_ITERATORS_H_
309 
310 // vim: foldmethod=marker
result_vector_type< L, R > operator-(L &&lhs, R &&rhs)
Applies - component-wise and concurrently.
Definition: simdarray.h:1611
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1642
result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
Definition: simdarray.h:1611
Helper class for the Memory::vector(size_t) class of functions.
Definition: iterators.h:45
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
Definition: simdarray.h:1642
result_vector_type< L, R > operator+(L &&lhs, R &&rhs)
Applies + component-wise and concurrently.
Definition: simdarray.h:1611
result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently.
Definition: simdarray.h:1642
result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.
Definition: simdarray.h:1642