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