rocPRIM
counting_iterator.hpp
1 // Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #ifndef ROCPRIM_ITERATOR_COUNTING_ITERATOR_HPP_
22 #define ROCPRIM_ITERATOR_COUNTING_ITERATOR_HPP_
23 
24 #include <iterator>
25 #include <iostream>
26 #include <cstddef>
27 #include <type_traits>
28 
29 #include "../config.hpp"
30 #include "../type_traits.hpp"
31 
34 
35 BEGIN_ROCPRIM_NAMESPACE
36 
47 template<
48  class Incrementable,
49  class Difference = std::ptrdiff_t
50 >
52 {
53 public:
55  using value_type = typename std::remove_const<Incrementable>::type;
59  using reference = value_type; // counting_iterator is not writable
62  using pointer = const value_type*; // counting_iterator is not writable
64  using difference_type = Difference;
66  using iterator_category = std::random_access_iterator_tag;
67 
68  static_assert(std::is_integral<value_type>::value, "Incrementable must be integral type");
69 
70 #ifndef DOXYGEN_SHOULD_SKIP_THIS
72 #endif
73 
74  ROCPRIM_HOST_DEVICE inline
75  counting_iterator() = default;
76 
79  ROCPRIM_HOST_DEVICE inline
80  ~counting_iterator() = default;
81 
85  ROCPRIM_HOST_DEVICE inline
86  explicit counting_iterator(const value_type value) : value_(value)
87  {
88  }
89 
90  #ifndef DOXYGEN_SHOULD_SKIP_THIS
91  ROCPRIM_HOST_DEVICE inline
92  counting_iterator& operator++()
93  {
94  value_++;
95  return *this;
96  }
97 
98  ROCPRIM_HOST_DEVICE inline
99  counting_iterator operator++(int)
100  {
101  counting_iterator old_ci = *this;
102  value_++;
103  return old_ci;
104  }
105 
106  ROCPRIM_HOST_DEVICE inline
107  counting_iterator& operator--()
108  {
109  value_--;
110  return *this;
111  }
112 
113  ROCPRIM_HOST_DEVICE inline
114  counting_iterator operator--(int)
115  {
116  counting_iterator old_ci = *this;
117  value_--;
118  return old_ci;
119  }
120 
121  ROCPRIM_HOST_DEVICE inline
122  value_type operator*() const
123  {
124  return value_;
125  }
126 
127  ROCPRIM_HOST_DEVICE inline
128  pointer operator->() const
129  {
130  return &value_;
131  }
132 
133  ROCPRIM_HOST_DEVICE inline
134  counting_iterator operator+(difference_type distance) const
135  {
136  return counting_iterator(value_ + static_cast<value_type>(distance));
137  }
138 
139  ROCPRIM_HOST_DEVICE inline
140  counting_iterator& operator+=(difference_type distance)
141  {
142  value_ += static_cast<value_type>(distance);
143  return *this;
144  }
145 
146  ROCPRIM_HOST_DEVICE inline
147  counting_iterator operator-(difference_type distance) const
148  {
149  return counting_iterator(value_ - static_cast<value_type>(distance));
150  }
151 
152  ROCPRIM_HOST_DEVICE inline
153  counting_iterator& operator-=(difference_type distance)
154  {
155  value_ -= static_cast<value_type>(distance);
156  return *this;
157  }
158 
159  ROCPRIM_HOST_DEVICE inline
160  difference_type operator-(counting_iterator other) const
161  {
162  return static_cast<difference_type>(value_ - other.value_);
163  }
164 
165  // counting_iterator is not writable, so we don't return reference,
166  // just something convertible to reference. That matches requirement
167  // of RandomAccessIterator concept
168  ROCPRIM_HOST_DEVICE inline
169  value_type operator[](difference_type distance) const
170  {
171  return value_ + static_cast<value_type>(distance);
172  }
173 
174  ROCPRIM_HOST_DEVICE inline
175  bool operator==(counting_iterator other) const
176  {
177  return this->equal_value(value_, other.value_);
178  }
179 
180  ROCPRIM_HOST_DEVICE inline
181  bool operator!=(counting_iterator other) const
182  {
183  return !(*this == other);
184  }
185 
186  ROCPRIM_HOST_DEVICE inline
187  bool operator<(counting_iterator other) const
188  {
189  return distance_to(other) > 0;
190  }
191 
192  ROCPRIM_HOST_DEVICE inline
193  bool operator<=(counting_iterator other) const
194  {
195  return distance_to(other) >= 0;
196  }
197 
198  ROCPRIM_HOST_DEVICE inline
199  bool operator>(counting_iterator other) const
200  {
201  return distance_to(other) < 0;
202  }
203 
204  ROCPRIM_HOST_DEVICE inline
205  bool operator>=(counting_iterator other) const
206  {
207  return distance_to(other) <= 0;
208  }
209 
210  friend std::ostream& operator<<(std::ostream& os, const counting_iterator& iter)
211  {
212  os << "[" << iter.value_ << "]";
213  return os;
214  }
215  #endif // DOXYGEN_SHOULD_SKIP_THIS
216 
217 private:
218  template<class T>
219  inline
220  bool equal_value(const T& x, const T& y) const
221  {
222  return (x == y);
223  }
224 
225  inline
226  difference_type distance_to(const counting_iterator& other) const
227  {
228  return difference_type(other.value_) - difference_type(value_);
229  }
230 
231  value_type value_;
232 };
233 
234 #ifndef DOXYGEN_SHOULD_SKIP_THIS
235 template<
236  class Incrementable,
237  class Difference
238 >
239 ROCPRIM_HOST_DEVICE inline
243 {
244  return iter + distance;
245 }
246 #endif // DOXYGEN_SHOULD_SKIP_THIS
247 
255 template<
256  class Incrementable,
257  class Difference = std::ptrdiff_t
258 >
259 ROCPRIM_HOST_DEVICE inline
261 make_counting_iterator(Incrementable value)
262 {
264 }
265 
266 END_ROCPRIM_NAMESPACE
267 
269 // end of group iteratormodule
270 
271 #endif // ROCPRIM_ITERATOR_COUNTING_ITERATOR_HPP_
std::random_access_iterator_tag iterator_category
The category of the iterator.
Definition: counting_iterator.hpp:66
ROCPRIM_HOST_DEVICE counting_iterator< Incrementable, Difference > make_counting_iterator(Incrementable value)
make_counting_iterator creates a counting_iterator with its initial value set to value.
Definition: counting_iterator.hpp:261
value_type reference
A reference type of the type iterated over (value_type).
Definition: counting_iterator.hpp:59
typename std::remove_const< Incrementable >::type value_type
The type of the value that can be obtained by dereferencing the iterator.
Definition: counting_iterator.hpp:55
const value_type * pointer
A pointer type of the type iterated over (value_type).
Definition: counting_iterator.hpp:62
ROCPRIM_HOST_DEVICE counting_iterator(const value_type value)
Creates counting_iterator and sets its initial value to value_.
Definition: counting_iterator.hpp:86
ROCPRIM_HOST_DEVICE ~counting_iterator()=default
Creates counting_iterator with its initial value initialized to its default value (usually 0)...
Difference difference_type
A type used for identify distance between iterators.
Definition: counting_iterator.hpp:64
A random-access input (read-only) iterator over a sequence of consecutive integer values...
Definition: counting_iterator.hpp:51