Vc  1.1.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 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 #ifdef Vc_MSVC
110  unsigned long mask;
111  unsigned long bit;
112 #else
113  size_t mask;
114  size_t bit;
115 #endif
116 
117  void nextBit()
118  {
119 #ifdef Vc_GNU_ASM
120  bit = __builtin_ctzl(mask);
121 #elif defined(Vc_MSVC)
122  _BitScanForward(&bit, mask);
123 #else
124 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
125 #endif
126  }
127  void resetLsb()
128  {
129  // 01100100 - 1 = 01100011
130  mask &= (mask - 1);
131  /*
132 #ifdef Vc_GNU_ASM
133  __asm__("btr %1,%0" : "+r"(mask) : "r"(bit));
134 #elif defined(_WIN64)
135  _bittestandreset64(&mask, bit);
136 #elif defined(_WIN32)
137  _bittestandreset(&mask, bit);
138 #else
139 #error "Not implemented yet. Please contact vc-devel@compeng.uni-frankfurt.de"
140 #endif
141  */
142  }
143  public:
144  BitmaskIterator(decltype(mask) m) : mask(m) { nextBit(); }
145  BitmaskIterator(const BitmaskIterator &) = default;
146  BitmaskIterator(BitmaskIterator &&) = default;
147 
148  Vc_ALWAYS_INLINE size_t operator->() const { return bit; }
149  Vc_ALWAYS_INLINE size_t operator*() const { return bit; }
150 
151  Vc_ALWAYS_INLINE BitmaskIterator &operator++() { resetLsb(); nextBit(); return *this; }
152  Vc_ALWAYS_INLINE BitmaskIterator operator++(int) { BitmaskIterator tmp = *this; resetLsb(); nextBit(); return tmp; }
153 
154  Vc_ALWAYS_INLINE bool operator==(const BitmaskIterator &rhs) const { return mask == rhs.mask; }
155  Vc_ALWAYS_INLINE bool operator!=(const BitmaskIterator &rhs) const { return mask != rhs.mask; }
156  };/*}}}*/
157 #endif
158 
159 template<typename V> constexpr typename std::enable_if<Traits::is_simd_vector<V>::value, Iterator<V>>::type begin(V &v)
160 {
161  return { v, 0 };
162 }
163 
164 template<typename V> constexpr typename std::enable_if<Traits::is_simd_vector<V>::value, Iterator<V>>::type end(V &v)
165 {
166  return { v, V::Size };
167 }
168 
169 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)
170 {
171  return { v, 0 };
172 }
173 
174 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)
175 {
176  return { v, V::Size };
177 }
178 
179 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)
180 {
181  return { v, 0 };
182 }
183 
184 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)
185 {
186  return { v, V::Size };
187 }
188 
189 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator begin(const WhereImpl::WhereMask<M> &w)
190 {
191  return w.mask.toInt();
192 }
193 
194 template<typename M> Vc_ALWAYS_INLINE BitmaskIterator end(const WhereImpl::WhereMask<M> &)
195 {
196  return 0;
197 }
198 
199 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
200  makeIterator(T *mem, Flags)
201 {
202  return new(mem) MemoryVector<V, Flags>;
203 }
204 
205 template<typename V, typename Flags, typename T> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
206  makeIterator(const T *mem, Flags)
207 {
208  return new(const_cast<T *>(mem)) MemoryVector<const V, Flags>;
209 }
210 
211 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<V, Flags>
212  makeIterator(MemoryVector<V, FlagsX> &mv, Flags)
213 {
214  return new(&mv) MemoryVector<V, Flags>;
215 }
216 
217 template<typename V, typename Flags, typename FlagsX> Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>
218  makeIterator(MemoryVector<const V, FlagsX> &mv, Flags)
219 {
220  return new(&mv) MemoryVector<const V, Flags>;
221 }
222 
223 } // namespace Common
224 
225 using Common::begin;
226 using Common::end;
227 using Common::makeIterator;
228 } // namespace Vc
229 
230 #endif // VC_COMMON_ITERATORS_H_
231 
232 // vim: foldmethod=marker
Helper class for the Memory::vector(size_t) class of functions.
Definition: iterators.h:42