-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathamp_iterators.h
300 lines (252 loc) · 9.99 KB
/
amp_iterators.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*----------------------------------------------------------------------------
* Copyright (c) Microsoft Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
* MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing
* permissions and limitations under the License.
*---------------------------------------------------------------------------
*
* C++ AMP standard algorithms library.
*
* This file contains the iterator classes for C++ AMP containers
*---------------------------------------------------------------------------*/
#pragma once
#include <amp.h>
#include <iterator>
#include <type_traits>
#include <xx_amp_stl_algorithms_impl.h>
namespace amp_stl_algorithms
{
using namespace concurrency;
//----------------------------------------------------------------------------
// array_view_iterator
//
// Provides a local iterator for an array_view. Iterators are only comparable
// for the same array_view (copies of the array_view are shallow, and are OK,
// i.e., iterators obtained from different copies are comparable).
// The behavior is undefined on comparing iterators obtained from different
// array_views.
//
// Note: only array_view<T, 1> is supported, since only array_view<T, 1> could
// ensure the linear continuous storage.
//----------------------------------------------------------------------------
// TODO: array_view_iterator<value_type> should freely be usable as
// array_view_iterator<const value_type>. This currently does not work
// properly at several places and needs to be fixed.
namespace _details
{
template <typename value_type>
struct array_view_iterator_helper;
}
template <typename value_type>
class array_view_iterator : public std::iterator<std::random_access_iterator_tag, typename value_type, int>
{
template <typename value_type>
friend struct _details::array_view_iterator_helper;
template <typename value_type>
friend array_view_iterator<value_type> begin(const concurrency::array_view<value_type>& arr) restrict(cpu,amp);
template <typename value_type>
friend array_view_iterator<value_type> end(const concurrency::array_view<value_type>& arr) restrict(cpu,amp);
public:
~array_view_iterator() restrict(cpu,amp)
{
}
array_view_iterator(const array_view_iterator& other) restrict(cpu,amp)
: m_base_view(other.m_base_view),
m_position(other.m_position)
{
}
// TODO: Should be able to copy construct a const array_view iterator from a non-const array_view iterator
array_view_iterator() restrict(cpu,amp)
: m_base_view(_details::empty_array_view_factory<value_type>::create())
{
}
array_view_iterator& operator=(const array_view_iterator& iter) restrict(cpu,amp)
{
if (this != &iter)
{
m_base_view = iter.m_base_view;
m_position = iter.m_position;
}
return *this;
}
// TODO: Should be able to assign a non-const array_view iterator to a const array_view iterator
// Prefix
array_view_iterator& operator ++() restrict(cpu,amp)
{
m_position++;
return *this;
}
// Postfix
array_view_iterator operator ++(int) restrict(cpu,amp)
{
auto temp = *this;
m_position++;
return temp;
}
// Prefix
array_view_iterator& operator --() restrict(cpu,amp)
{
m_position--;
return *this;
}
// Postfix
array_view_iterator operator --(int) restrict(cpu,amp)
{
auto temp = *this;
m_position--;
return temp;
}
bool operator==(const array_view_iterator& rhs) const restrict(cpu,amp)
{
return (m_position == rhs.m_position);
}
bool operator!=(const array_view_iterator& other) const restrict(cpu,amp)
{
return !(*this == other);
}
reference operator*() const restrict(cpu,amp)
{
return *deref();
}
reference operator->() const restrict(cpu,amp)
{
return *deref();
}
array_view_iterator operator+(difference_type delta) const restrict(cpu,amp)
{
auto temp = *this;
temp.m_position += delta;
return temp;
}
array_view_iterator operator-(difference_type delta) const restrict(cpu,amp)
{
return this->operator+(-delta);
}
difference_type operator-(const array_view_iterator& other) const restrict(cpu,amp)
{
return (m_position - other.m_position);
}
friend array_view_iterator operator+(difference_type delta, const array_view_iterator&) restrict(cpu,amp);
friend array_view_iterator operator-(difference_type delta, const array_view_iterator&) restrict(cpu,amp);
bool operator < (const array_view_iterator& rhs) const restrict(cpu,amp)
{
return (m_position < rhs.m_position);
}
bool operator > (const array_view_iterator& rhs) const restrict(cpu,amp)
{
return rhs < *this;
}
bool operator <= (const array_view_iterator& rhs) const restrict(cpu,amp)
{
return (m_position <= rhs.m_position);
}
bool operator >= (const array_view_iterator& rhs) const restrict(cpu,amp)
{
return rhs <= *this;
}
array_view_iterator& operator+=(difference_type delta) restrict(cpu,amp)
{
m_position += delta;
return *this;
}
array_view_iterator& operator-=(difference_type delta) restrict(cpu,amp)
{
return this->operator+=(-delta);
}
value_type& operator[](difference_type idx) const restrict(cpu,amp)
{
return *(*this + idx);
}
private:
// TODO: Should be able to construct a const array_view_iterator from a non-const array_view
array_view_iterator(const array_view<value_type>& arr_view, difference_type position) restrict(cpu,amp)
: m_base_view(arr_view),
m_position(position)
{
}
value_type * deref() const restrict(cpu,amp)
{
return &m_base_view[m_position];
}
array_view<value_type> m_base_view;
difference_type m_position;
};
namespace _details
{
template<typename value_type>
struct array_view_iterator_helper
{
static const array_view<value_type> & get_base_array_view(const array_view_iterator<value_type> & iter)
{
return iter.m_base_view;
}
};
}
// Friends of array_view_iterator
template <typename value_type>
array_view_iterator<value_type> operator+(typename array_view_iterator<value_type>::difference_type delta, const array_view_iterator<value_type>& iter) restrict(cpu,amp)
{
return iter+delta;
}
template <typename value_type>
array_view_iterator<value_type> operator-(typename array_view_iterator<value_type>::difference_type delta, const array_view_iterator<value_type>& iter) restrict(cpu,amp)
{
return iter-delta;
}
// end of array_view_iterator
//----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
// iterator_traits
//
// Provides typedefs that programmers could use to define iterators. e.g.,
//
// iterator_traits<array_view<float,2>>::const_iterator_type myAvIter;
//
// In future release, this should be offered as member typedefs of the
// respective classes.
//
///////////////////////////////////////////////////////////////////////////////
template <typename array_type>
class iterator_traits
{
iterator_traits()
{
static_assert(false, "This class must be specialized");
}
};
template <typename value_type>
class iterator_traits<concurrency::array_view<value_type>>
{
public:
typedef array_view_iterator<value_type> iterator_type;
typedef array_view_iterator<const value_type> const_iterator_type;
};
template <typename value_type>
class iterator_traits<concurrency::array_view<const value_type>>
{
public:
typedef array_view_iterator<const value_type> const_iterator_type;
};
//----------------------------------------------------------------------------
// begin and end iterators for array views
//----------------------------------------------------------------------------
template <typename value_type>
array_view_iterator<value_type> begin(const concurrency::array_view<value_type>& arr) restrict(cpu,amp)
{
return array_view_iterator<value_type>(arr, 0);
}
template <typename value_type>
array_view_iterator<value_type> end(const concurrency::array_view<value_type>& arr) restrict(cpu,amp)
{
return array_view_iterator<value_type>(arr, arr.get_extent().size());
}
} // amp_stl_algorithms