Vc  1.4.1
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  class BitmaskIterator/*{{{*/
152  {
153 #ifdef Vc_MSVC
154  unsigned long mask;
155  unsigned long bit;
156 #else
157  size_t mask;
158  size_t bit;
159 #endif
160 
161  void nextBit()
162  {
163 #ifdef Vc_GNU_ASM
164  bit = __builtin_ctzl(mask);
165 #elif defined(Vc_MSVC)
166  _BitScanForward(&bit, mask);
167 #else
168 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
169 #endif
170  }
171  void resetLsb()
172  {
173  // 01100100 - 1 = 01100011
174  mask &= (mask - 1);
175  /*
176 #ifdef Vc_GNU_ASM
177  __asm__("btr %1,%0" : "+r"(mask) : "r"(bit));
178 #elif defined(_WIN64)
179  _bittestandreset64(&mask, bit);
180 #elif defined(_WIN32)
181  _bittestandreset(&mask, bit);
182 #else
183 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
184 #endif
185  */
186  }
187  public:
188  BitmaskIterator(decltype(mask) m) : mask(m) { nextBit(); }
189  BitmaskIterator(const BitmaskIterator &) = default;
190  BitmaskIterator(BitmaskIterator &&) = default;
191 
192  Vc_ALWAYS_INLINE size_t operator->() const { return bit; }
193  Vc_ALWAYS_INLINE size_t operator*() const { return bit; }
194 
195  Vc_ALWAYS_INLINE BitmaskIterator &operator++() { resetLsb(); nextBit(); return *this; }
196  Vc_ALWAYS_INLINE BitmaskIterator operator++(int) { BitmaskIterator tmp = *this; resetLsb(); nextBit(); return tmp; }
197 
198  Vc_ALWAYS_INLINE bool operator==(const BitmaskIterator &rhs) const { return mask == rhs.mask; }
199  Vc_ALWAYS_INLINE bool operator!=(const BitmaskIterator &rhs) const { return mask != rhs.mask; }
200  };/*}}}*/
201 
202 template <typename T>
203 Vc_ALWAYS_INLINE
204  enable_if<Traits::is_simd_vector<T>::value || Traits::is_simd_mask<T>::value,
205  Iterator<typename std::remove_reference<T>::type>>
206  begin(T &&x)
207 {
208  return {std::forward<T>(x), 0};
209 }
210 
211 template <typename T>
212 Vc_ALWAYS_INLINE
213  enable_if<Traits::is_simd_vector<T>::value || Traits::is_simd_mask<T>::value,
214  Iterator<typename std::remove_reference<T>::type>>
215  end(T &&x)
216 {
217  using TT = typename std::decay<T>::type;
218  return {std::forward<T>(x), int(TT::size())};
219 }
220 
221 template <typename T>
222 Vc_ALWAYS_INLINE enable_if<
224 cbegin(const T &v)
225 {
226  return {v, 0};
227 }
228 
229 template <typename T>
230 Vc_ALWAYS_INLINE enable_if<
232 cend(const T &v)
233 {
234  return {v, int(T::size())};
235 }
236 
237 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator begin(const WhereImpl::WhereMask<M> &w)
238 {
239  return w.mask.toInt();
240 }
241 
242 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator end(const WhereImpl::WhereMask<M> &)
243 {
244  return 0;
245 }
246 
247 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
248  makeIterator(T *mem, Flags)
249 {
250  return new(mem) MemoryVector<V, Flags>;
251 }
252 
253 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
254  makeIterator(const T *mem, Flags)
255 {
256  return new(const_cast<T *>(mem)) MemoryVector<const V, Flags>;
257 }
258 
259 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
260  makeIterator(MemoryVector<V, FlagsX> &mv, Flags)
261 {
262  return new(&mv) MemoryVector<V, Flags>;
263 }
264 
265 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
266  makeIterator(MemoryVector<const V, FlagsX> &mv, Flags)
267 {
268  return new(&mv) MemoryVector<const V, Flags>;
269 }
270 
271 } // namespace Common
272 
273 using Common::begin;
274 using Common::end;
275 using Common::cbegin;
276 using Common::cend;
277 using Common::makeIterator;
278 } // namespace Vc
279 
280 #endif // VC_COMMON_ITERATORS_H_
281 
282 // vim: foldmethod=marker
result_vector_type< L, R > operator-(L &&lhs, R &&rhs)
Applies - component-wise and concurrently.
Definition: simdarray.h:1721
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1752
result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
Definition: simdarray.h:1721
Identifies any SIMD vector type (independent of implementation or whether it&#39;s SimdArray<T, N>).
Definition: type_traits.h:128
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:1752
result_vector_type< L, R > operator+(L &&lhs, R &&rhs)
Applies + component-wise and concurrently.
Definition: simdarray.h:1721
result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently.
Definition: simdarray.h:1752
result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.
Definition: simdarray.h:1752
Identifies any SIMD mask type (independent of implementation or whether it&#39;s SimdMaskArray<T, N>).
Definition: type_traits.h:117