Vc  1.0.0-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 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the names of contributing organizations nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 }}}*/
28 
29 #ifndef VC_COMMON_ITERATORS_H_
30 #define VC_COMMON_ITERATORS_H_
31 
32 #include <array>
33 #include <iterator>
34 #include "where.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 // class Iterator {{{
46 template <typename V>
47 class Iterator
48  : public std::iterator<std::bidirectional_iterator_tag, typename V::EntryType>
49  {
50  V &v;
51  size_t i;
52  public:
53  constexpr Iterator(V &_v, size_t _i) : v(_v), i(_i) {}
54  constexpr Iterator(const Iterator &) = default;
55  constexpr Iterator(Iterator &&) = default;
56 
57  Vc_ALWAYS_INLINE decltype(v[i]) operator->() { return v[i]; }
58  Vc_ALWAYS_INLINE decltype(v[i]) operator->() const { return v[i]; }
59 
60  Vc_ALWAYS_INLINE decltype(v[i]) operator*() { return v[i]; }
61  Vc_ALWAYS_INLINE decltype(v[i]) operator*() const { return v[i]; }
62 
63  Vc_ALWAYS_INLINE Iterator &operator++() { ++i; return *this; }
64  Vc_ALWAYS_INLINE Iterator operator++(int) { Iterator tmp = *this; ++i; return tmp; }
65 
66  Vc_ALWAYS_INLINE Iterator &operator--() { --i; return *this; }
67  Vc_ALWAYS_INLINE Iterator operator--(int) { Iterator tmp = *this; --i; return tmp; }
68 
69  // XXX: doesn't check &v == &rhs.v
70  Vc_ALWAYS_INLINE bool operator==(const Iterator<V> &rhs) const { return i == rhs.i; }
71  Vc_ALWAYS_INLINE bool operator!=(const Iterator<V> &rhs) const { return i != rhs.i; }
72  Vc_ALWAYS_INLINE bool operator< (const Iterator<V> &rhs) const { return i < rhs.i; }
73  Vc_ALWAYS_INLINE bool operator<=(const Iterator<V> &rhs) const { return i <= rhs.i; }
74  Vc_ALWAYS_INLINE bool operator> (const Iterator<V> &rhs) const { return i > rhs.i; }
75  Vc_ALWAYS_INLINE bool operator>=(const Iterator<V> &rhs) const { return i >= rhs.i; }
76  };/*}}}*/
77 
78  template<typename V> using ConstIterator = Iterator<const V>;
79 
80 #ifdef Vc_IMPL_MIC
81  class BitmaskIterator/*{{{*/
82  {
83  const int mask;
84  int bit;
85  public:
86  Vc_ALWAYS_INLINE BitmaskIterator(int m) : mask(m), bit(_mm_tzcnt_32(mask)) {}
87  Vc_ALWAYS_INLINE BitmaskIterator(const BitmaskIterator &) = default;
88  Vc_ALWAYS_INLINE BitmaskIterator(BitmaskIterator &&) = default;
89 
90  Vc_ALWAYS_INLINE size_t operator->() const { return bit; }
91  Vc_ALWAYS_INLINE size_t operator*() const { return bit; }
92 
93  Vc_ALWAYS_INLINE BitmaskIterator &operator++() {
94  bit = _mm_tzcnti_32(bit, mask);
95  return *this;
96  }
97  Vc_ALWAYS_INLINE BitmaskIterator operator++(int) {
98  BitmaskIterator tmp = *this;
99  bit = _mm_tzcnti_32(bit, mask);
100  return tmp;
101  }
102 
103  Vc_ALWAYS_INLINE bool operator==(const BitmaskIterator &rhs) const { return bit == rhs.bit; }
104  Vc_ALWAYS_INLINE bool operator!=(const BitmaskIterator &rhs) const { return bit != rhs.bit; }
105  };/*}}}*/
106 #else
107  class BitmaskIterator/*{{{*/
108  {
109  size_t mask;
110  size_t bit;
111 
112  void nextBit()
113  {
114 #ifdef Vc_GNU_ASM
115  bit = __builtin_ctzl(mask);
116 #elif defined(_WIN64)
117  _BitScanForward64(&bit, mask);
118 #elif defined(_WIN32)
119  _BitScanForward(&bit, mask);
120 #else
121 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
122 #endif
123  }
124  void resetLsb()
125  {
126  // 01100100 - 1 = 01100011
127  mask &= (mask - 1);
128  /*
129 #ifdef Vc_GNU_ASM
130  __asm__("btr %1,%0" : "+r"(mask) : "r"(bit));
131 #elif defined(_WIN64)
132  _bittestandreset64(&mask, bit);
133 #elif defined(_WIN32)
134  _bittestandreset(&mask, bit);
135 #else
136 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
137 #endif
138  */
139  }
140  public:
141  BitmaskIterator(size_t m) : mask(m) { nextBit(); }
142  BitmaskIterator(const BitmaskIterator &) = default;
143  BitmaskIterator(BitmaskIterator &&) = default;
144 
145  Vc_ALWAYS_INLINE size_t operator->() const { return bit; }
146  Vc_ALWAYS_INLINE size_t operator*() const { return bit; }
147 
148  Vc_ALWAYS_INLINE BitmaskIterator &operator++() { resetLsb(); nextBit(); return *this; }
149  Vc_ALWAYS_INLINE BitmaskIterator operator++(int) { BitmaskIterator tmp = *this; resetLsb(); nextBit(); return tmp; }
150 
151  Vc_ALWAYS_INLINE bool operator==(const BitmaskIterator &rhs) const { return mask == rhs.mask; }
152  Vc_ALWAYS_INLINE bool operator!=(const BitmaskIterator &rhs) const { return mask != rhs.mask; }
153  };/*}}}*/
154 #endif
155 
156 template<typename V> constexpr typename std::enable_if<Traits::is_simd_vector<V>::value, Iterator<V>>::type begin(V &v)
157 {
158  return { v, 0 };
159 }
160 
161 template<typename V> constexpr typename std::enable_if<Traits::is_simd_vector<V>::value, Iterator<V>>::type end(V &v)
162 {
163  return { v, V::Size };
164 }
165 
166 template<typename V> constexpr typename std::enable_if<Traits::is_simd_mask<V>::value || Traits::is_simd_vector<V>::value, ConstIterator<V>>::type begin(const V &v)
167 {
168  return { v, 0 };
169 }
170 
171 template<typename V> constexpr typename std::enable_if<Traits::is_simd_mask<V>::value || Traits::is_simd_vector<V>::value, ConstIterator<V>>::type end(const V &v)
172 {
173  return { v, V::Size };
174 }
175 
176 template<typename V> constexpr typename std::enable_if<Traits::is_simd_mask<V>::value || Traits::is_simd_vector<V>::value, ConstIterator<V>>::type cbegin(const V &v)
177 {
178  return { v, 0 };
179 }
180 
181 template<typename V> constexpr typename std::enable_if<Traits::is_simd_mask<V>::value || Traits::is_simd_vector<V>::value, ConstIterator<V>>::type cend(const V &v)
182 {
183  return { v, V::Size };
184 }
185 
186 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator begin(const WhereImpl::WhereMask<M> &w)
187 {
188  return w.mask.toInt();
189 }
190 
191 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator end(const WhereImpl::WhereMask<M> &)
192 {
193  return 0;
194 }
195 
196 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
197  makeIterator(T *mem, Flags)
198 {
199  return new(mem) MemoryVector<V, Flags>;
200 }
201 
202 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
203  makeIterator(const T *mem, Flags)
204 {
205  return new(const_cast<T *>(mem)) MemoryVector<const V, Flags>;
206 }
207 
208 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
209  makeIterator(MemoryVector<V, FlagsX> &mv, Flags)
210 {
211  return new(&mv) MemoryVector<V, Flags>;
212 }
213 
214 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
215  makeIterator(MemoryVector<const V, FlagsX> &mv, Flags)
216 {
217  return new(&mv) MemoryVector<const V, Flags>;
218 }
219 
220 } // namespace Common
221 
222 using Common::begin;
223 using Common::end;
224 using Common::makeIterator;
225 } // namespace Vc
226 
227 #endif // VC_COMMON_ITERATORS_H_
228 
229 // vim: foldmethod=marker
Helper class for the Memory::vector(size_t) class of functions.
Definition: iterators.h:42