Vc 1.4.5
SIMD Vector Classes for C++
 
Loading...
Searching...
No Matches
iterators.h
1/* This file is part of the Vc library. {{{
2Copyright © 2013-2015 Matthias Kretz <kretz@kde.org>
3
4Redistribution and use in source and binary forms, with or without
5modification, 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
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22ON 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
24SOFTWARE, 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
40namespace Vc_VERSIONED_NAMESPACE
41{
42namespace Common
43{
44
45template<typename _V, typename Flags> class MemoryVector;
46template<typename _V, typename Flags> class MemoryVectorIterator;
47
48template <typename V> class Iterator;
49template <typename V, bool> class IteratorBase;
50template <typename V> class IteratorBase<V, true>
51{
52public:
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
60private:
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
68template <typename V> class IteratorBase<V, false>
69{
70public:
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
78private:
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 {{{
97template <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
102public:
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
144private:
145 V *v = nullptr;
146 difference_type i = 0;
147};/*}}}*/
148
149template <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
202template <typename T>
203Vc_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
211template <typename T>
212Vc_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
221template <typename T>
222Vc_ALWAYS_INLINE enable_if<
223 Traits::is_simd_mask<T>::value || Traits::is_simd_vector<T>::value, ConstIterator<T>>
224cbegin(const T &v)
225{
226 return {v, 0};
227}
228
229template <typename T>
230Vc_ALWAYS_INLINE enable_if<
231 Traits::is_simd_mask<T>::value || Traits::is_simd_vector<T>::value, ConstIterator<T>>
232cend(const T &v)
233{
234 return {v, int(T::size())};
235}
236
237template<typename M> Vc_ALWAYS_INLINE BitmaskIterator begin(const WhereImpl::WhereMask<M> &w)
238{
239 return w.mask.toInt();
240}
241
242template<typename M> Vc_ALWAYS_INLINE BitmaskIterator end(const WhereImpl::WhereMask<M> &)
243{
244 return 0;
245}
246
247template<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
253template<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
259template<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
265template<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
273using Common::begin;
274using Common::end;
275using Common::cbegin;
276using Common::cend;
277using Common::makeIterator;
278} // namespace Vc
279
280#endif // VC_COMMON_ITERATORS_H_
281
282// vim: foldmethod=marker