RAJA
RAJA provides a collection of platform portability abstractions for C++ HPC applications.
Iterators.hpp
Go to the documentation of this file.
1 
11 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
12 // Copyright (c) Lawrence Livermore National Security, LLC and other
13 // RAJA Project Developers. See top-level LICENSE and COPYRIGHT
14 // files for dates and other details. No copyright assignment is required
15 // to contribute to RAJA.
16 //
17 // SPDX-License-Identifier: (BSD-3-Clause)
18 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
19 
20 #ifndef RAJA_ITERATORS_HPP
21 #define RAJA_ITERATORS_HPP
22 
23 #include <iterator>
24 #include <limits>
25 #include <string>
26 #include <type_traits>
27 #include <typeinfo>
28 #include <utility>
29 
30 #include "RAJA/config.hpp"
32 #include "RAJA/util/macros.hpp"
33 #include "RAJA/util/types.hpp"
34 
35 namespace RAJA
36 {
37 namespace Iterators
38 {
39 
40 // Containers
41 
42 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
43 template<typename LType, typename RType>
44 std::string overflow_msg(LType lhs, RType rhs)
45 {
46  return "Iterator Overflow detected between operation of :\n\ttype : " +
47  (std::string) typeid(lhs).name() + " val : " + std::to_string(lhs) +
48  "\n\ttype : " + typeid(rhs).name() + " val : " + std::to_string(rhs) +
49  "\n";
50 }
51 
52 template<typename Type, typename DifferenceType>
53 RAJA_HOST_DEVICE bool is_addition_overflow(Type lhs, DifferenceType rhs)
54 {
55  if (std::is_unsigned<Type>::value)
56  {
57  if ((rhs > 0) && (lhs > std::numeric_limits<Type>::max() - rhs))
58  return true;
59  if ((rhs < 0) && (lhs < std::numeric_limits<Type>::min() - rhs))
60  return true;
61  }
62  return false;
63 }
64 
65 template<typename Type, typename DifferenceType>
66 RAJA_HOST_DEVICE bool is_subtraction_overflow(Type lhs,
67  DifferenceType rhs,
68  bool iterator_on_left = true)
69 {
70  if (iterator_on_left)
71  {
72 
73  if (std::is_unsigned<Type>::value)
74  {
75  if ((rhs > 0) && (lhs < std::numeric_limits<Type>::min() + rhs))
76  return true;
77  if ((rhs < 0) && (lhs > std::numeric_limits<Type>::max() + rhs))
78  return true;
79  }
80  }
81  else
82  { // Special case where operation is : value(lhs) - iterator(rhs).
83 
84  if (std::is_unsigned<DifferenceType>::value)
85  {
86  if ((lhs > 0) && (rhs < std::numeric_limits<DifferenceType>::min() + lhs))
87  return true;
88  if ((lhs < 0)) return true;
89  }
90  }
91  return false;
92 }
93 
94 template<typename Type, typename DifferenceType>
95 RAJA_HOST_DEVICE void check_is_addition_overflow(Type lhs, DifferenceType rhs)
96 {
97  if (is_addition_overflow(lhs, rhs))
98  throw std::runtime_error(overflow_msg(lhs, rhs));
99 }
100 
101 template<typename Type, typename DifferenceType>
102 RAJA_HOST_DEVICE void check_is_subtraction_overflow(Type lhs,
103  DifferenceType rhs)
104 {
105  if (is_subtraction_overflow(lhs, rhs))
106  throw std::runtime_error(overflow_msg(lhs, rhs));
107 }
108 #endif
109 
110 template<typename Type = Index_type,
111  typename DifferenceType = Type,
112  typename PointerType = Type*>
114 {
115 public:
116  using value_type = Type;
118  using difference_type = DifferenceType;
119  using pointer = PointerType;
121  using iterator_category = std::random_access_iterator_tag;
122 
123  constexpr numeric_iterator() noexcept = default;
124  constexpr numeric_iterator(const numeric_iterator&) noexcept = default;
125  constexpr numeric_iterator(numeric_iterator&&) noexcept = default;
126  numeric_iterator& operator=(const numeric_iterator&) noexcept = default;
127  numeric_iterator& operator=(numeric_iterator&&) noexcept = default;
128 
130  : val(rhs)
131  {}
132 
133  RAJA_HOST_DEVICE inline DifferenceType get_stride() const { return 1; }
134 
135  RAJA_HOST_DEVICE inline bool operator==(const numeric_iterator& rhs) const
136  {
137  return val == rhs.val;
138  }
139 
140  RAJA_HOST_DEVICE inline bool operator!=(const numeric_iterator& rhs) const
141  {
142  return val != rhs.val;
143  }
144 
145  RAJA_HOST_DEVICE inline bool operator>(const numeric_iterator& rhs) const
146  {
147  return val > rhs.val;
148  }
149 
150  RAJA_HOST_DEVICE inline bool operator<(const numeric_iterator& rhs) const
151  {
152  return val < rhs.val;
153  }
154 
155  RAJA_HOST_DEVICE inline bool operator>=(const numeric_iterator& rhs) const
156  {
157  return val >= rhs.val;
158  }
159 
160  RAJA_HOST_DEVICE inline bool operator<=(const numeric_iterator& rhs) const
161  {
162  return val <= rhs.val;
163  }
164 
166  {
167  ++val;
168  return *this;
169  }
170 
172  {
173  --val;
174  return *this;
175  }
176 
178  {
179  numeric_iterator tmp(*this);
180  ++val;
181  return tmp;
182  }
183 
185  {
186  numeric_iterator tmp(*this);
187  --val;
188  return tmp;
189  }
190 
192  const difference_type& rhs)
193  {
194 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
195  check_is_addition_overflow(val, rhs);
196 #endif
197  val += rhs;
198  return *this;
199  }
200 
202  const difference_type& rhs)
203  {
204 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
205  check_is_subtraction_overflow(val, rhs);
206 #endif
207  val -= rhs;
208  return *this;
209  }
210 
212  const numeric_iterator& rhs)
213  {
214  val += rhs.val;
215  return *this;
216  }
217 
219  const numeric_iterator& rhs)
220  {
221  val -= rhs.val;
222  return *this;
223  }
224 
226  const numeric_iterator& rhs) const
227  {
228  return val + rhs.val;
229  }
230 
232  const numeric_iterator& rhs) const
233  {
234  return val - rhs.val;
235  }
236 
238  const difference_type& rhs) const
239  {
240 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
241  check_is_addition_overflow(val, rhs);
242 #endif
243  return numeric_iterator(val + rhs);
244  }
245 
247  const difference_type& rhs) const
248  {
249 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
250  check_is_subtraction_overflow(val, rhs);
251 #endif
252  return numeric_iterator(val - rhs);
253  }
254 
256  difference_type lhs,
257  const numeric_iterator& rhs)
258  {
259 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
260  return is_addition_overflow(rhs.val, lhs)
261  ? throw std::runtime_error(overflow_msg(lhs, rhs.val))
262  : numeric_iterator(lhs + rhs.val);
263 #else
264  return numeric_iterator(lhs + rhs.val);
265 #endif
266  }
267 
269  difference_type lhs,
270  const numeric_iterator& rhs)
271  {
272 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
273  return is_subtraction_overflow(rhs.val, lhs, false)
274  ? throw std::runtime_error(overflow_msg(lhs, rhs.val))
275  : numeric_iterator(lhs - rhs.val);
276 #else
277  return numeric_iterator(lhs - rhs.val);
278 #endif
279  }
280 
282  {
283  return value_type(val);
284  }
285 
287  {
288  return value_type(val);
289  }
290 
292  {
293  return value_type(val + rhs);
294  }
295 
296 private:
297  stripped_value_type val = 0;
298 };
299 
300 template<typename Type = Index_type,
301  typename DifferenceType = Type,
302  typename PointerType = Type*>
304 {
305 public:
306  using value_type = Type;
308  using difference_type = DifferenceType;
309  using pointer = DifferenceType*;
310  using reference = DifferenceType&;
311  using iterator_category = std::random_access_iterator_tag;
312 
313  constexpr strided_numeric_iterator() noexcept = default;
315  default;
317  default;
319  const strided_numeric_iterator&) noexcept = default;
321  default;
322 
325  DifferenceType stride_ = DifferenceType(1))
326  : val(rhs),
327  stride(stride_)
328  {}
329 
330  RAJA_HOST_DEVICE inline DifferenceType get_stride() const { return stride; }
331 
333  {
334  val += stride;
335  return *this;
336  }
337 
339  {
340  val -= stride;
341  return *this;
342  }
343 
345  const difference_type& rhs)
346  {
347 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
348  check_is_addition_overflow(val, rhs * stride);
349 #endif
350  val += rhs * stride;
351  return *this;
352  }
353 
355  const difference_type& rhs)
356  {
357 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
358  check_is_subtraction_overflow(val, rhs * stride);
359 #endif
360  val -= rhs * stride;
361  return *this;
362  }
363 
365  const strided_numeric_iterator& rhs) const
366  {
367  return (static_cast<difference_type>(val) +
368  (static_cast<difference_type>(rhs.val))) /
369  stride;
370  }
371 
373  const strided_numeric_iterator& rhs) const
374  {
375  difference_type diff = (static_cast<difference_type>(val) -
376  (static_cast<difference_type>(rhs.val)));
377 
378  return (diff % stride != difference_type {0})
379  ? (difference_type {1} + diff / stride)
380  : diff / stride;
381  }
382 
384  const difference_type& rhs) const
385  {
386 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
387  check_is_addition_overflow(val, rhs * stride);
388 #endif
389  return strided_numeric_iterator(val + rhs * stride, stride);
390  }
391 
393  const difference_type& rhs) const
394  {
395 #if defined(RAJA_ENABLE_ITERATOR_OVERFLOW_DEBUG)
396  check_is_subtraction_overflow(val, rhs * stride);
397 #endif
398  return strided_numeric_iterator(val - rhs * stride, stride);
399  }
400 
401  // Specialized comparison to allow normal iteration to work on off-stride
402  // multiples by adjusting rhs to the nearest *higher* multiple of stride
404  const strided_numeric_iterator& rhs) const
405  {
406  return (val - rhs.val) / stride;
407  }
408 
410  const strided_numeric_iterator& rhs) const
411  {
412  return !((val - rhs.val) / stride);
413  }
414 
416  const strided_numeric_iterator& rhs) const
417  {
418  return val * stride > rhs.val * stride;
419  }
420 
422  const strided_numeric_iterator& rhs) const
423  {
424  return val * stride < rhs.val * stride;
425  }
426 
428  const strided_numeric_iterator& rhs) const
429  {
430  return val * stride >= rhs.val * stride;
431  }
432 
434  const strided_numeric_iterator& rhs) const
435  {
436  return val * stride <= rhs.val * stride;
437  }
438 
440  {
441  return value_type(val);
442  }
443 
445  {
446  return value_type(val);
447  }
448 
450  {
451  return value_type(val + rhs * stride);
452  }
453 
454 private:
455  stripped_value_type val = 0;
456  DifferenceType stride = 1;
457 };
458 
459 
460 } // namespace Iterators
461 
462 } // namespace RAJA
463 
464 #endif /* RAJA_ITERATORS_HPP */
RAJA header file for strongly-typed integer class.
Definition: Iterators.hpp:114
RAJA_HOST_DEVICE numeric_iterator & operator-=(const numeric_iterator &rhs)
Definition: Iterators.hpp:218
RAJA_HOST_DEVICE bool operator!=(const numeric_iterator &rhs) const
Definition: Iterators.hpp:140
RAJA_HOST_DEVICE stripped_value_type operator-(const numeric_iterator &rhs) const
Definition: Iterators.hpp:231
RAJA_HOST_DEVICE numeric_iterator & operator++()
Definition: Iterators.hpp:165
RAJA_HOST_DEVICE numeric_iterator operator-(const difference_type &rhs) const
Definition: Iterators.hpp:246
RAJA_HOST_DEVICE numeric_iterator & operator--()
Definition: Iterators.hpp:171
RAJA_HOST_DEVICE value_type operator->() const
Definition: Iterators.hpp:286
RAJA_HOST_DEVICE value_type operator*() const
Definition: Iterators.hpp:281
PointerType pointer
Definition: Iterators.hpp:119
constexpr RAJA_HOST_DEVICE value_type operator[](difference_type rhs) const
Definition: Iterators.hpp:291
RAJA_HOST_DEVICE constexpr friend numeric_iterator operator+(difference_type lhs, const numeric_iterator &rhs)
Definition: Iterators.hpp:255
RAJA_HOST_DEVICE numeric_iterator & operator+=(const difference_type &rhs)
Definition: Iterators.hpp:191
Type value_type
Definition: Iterators.hpp:116
strip_index_type_t< Type > stripped_value_type
Definition: Iterators.hpp:117
RAJA_HOST_DEVICE constexpr friend numeric_iterator operator-(difference_type lhs, const numeric_iterator &rhs)
Definition: Iterators.hpp:268
value_type & reference
Definition: Iterators.hpp:120
constexpr numeric_iterator() noexcept=default
RAJA_HOST_DEVICE numeric_iterator operator--(int)
Definition: Iterators.hpp:184
RAJA_HOST_DEVICE bool operator<(const numeric_iterator &rhs) const
Definition: Iterators.hpp:150
RAJA_HOST_DEVICE bool operator>(const numeric_iterator &rhs) const
Definition: Iterators.hpp:145
RAJA_HOST_DEVICE DifferenceType get_stride() const
Definition: Iterators.hpp:133
RAJA_HOST_DEVICE numeric_iterator operator++(int)
Definition: Iterators.hpp:177
RAJA_HOST_DEVICE numeric_iterator & operator+=(const numeric_iterator &rhs)
Definition: Iterators.hpp:211
RAJA_HOST_DEVICE bool operator==(const numeric_iterator &rhs) const
Definition: Iterators.hpp:135
DifferenceType difference_type
Definition: Iterators.hpp:118
std::random_access_iterator_tag iterator_category
Definition: Iterators.hpp:121
RAJA_HOST_DEVICE bool operator>=(const numeric_iterator &rhs) const
Definition: Iterators.hpp:155
RAJA_HOST_DEVICE numeric_iterator operator+(const difference_type &rhs) const
Definition: Iterators.hpp:237
RAJA_HOST_DEVICE bool operator<=(const numeric_iterator &rhs) const
Definition: Iterators.hpp:160
RAJA_HOST_DEVICE numeric_iterator & operator-=(const difference_type &rhs)
Definition: Iterators.hpp:201
RAJA_HOST_DEVICE stripped_value_type operator+(const numeric_iterator &rhs) const
Definition: Iterators.hpp:225
Definition: Iterators.hpp:304
strip_index_type_t< Type > stripped_value_type
Definition: Iterators.hpp:307
Type value_type
Definition: Iterators.hpp:306
RAJA_HOST_DEVICE strided_numeric_iterator & operator++()
Definition: Iterators.hpp:332
RAJA_HOST_DEVICE DifferenceType get_stride() const
Definition: Iterators.hpp:330
std::random_access_iterator_tag iterator_category
Definition: Iterators.hpp:311
RAJA_HOST_DEVICE bool operator<(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:421
RAJA_HOST_DEVICE strided_numeric_iterator operator+(const difference_type &rhs) const
Definition: Iterators.hpp:383
RAJA_HOST_DEVICE bool operator!=(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:403
RAJA_HOST_DEVICE bool operator==(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:409
RAJA_HOST_DEVICE bool operator>=(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:427
RAJA_HOST_DEVICE value_type operator->() const
Definition: Iterators.hpp:444
constexpr strided_numeric_iterator() noexcept=default
RAJA_HOST_DEVICE bool operator>(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:415
constexpr RAJA_HOST_DEVICE value_type operator[](difference_type rhs) const
Definition: Iterators.hpp:449
RAJA_HOST_DEVICE strided_numeric_iterator operator-(const difference_type &rhs) const
Definition: Iterators.hpp:392
DifferenceType * pointer
Definition: Iterators.hpp:309
RAJA_HOST_DEVICE difference_type operator+(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:364
DifferenceType & reference
Definition: Iterators.hpp:310
RAJA_HOST_DEVICE bool operator<=(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:433
RAJA_HOST_DEVICE strided_numeric_iterator & operator-=(const difference_type &rhs)
Definition: Iterators.hpp:354
RAJA_HOST_DEVICE value_type operator*() const
Definition: Iterators.hpp:439
RAJA_HOST_DEVICE strided_numeric_iterator & operator--()
Definition: Iterators.hpp:338
DifferenceType difference_type
Definition: Iterators.hpp:308
RAJA_HOST_DEVICE strided_numeric_iterator & operator+=(const difference_type &rhs)
Definition: Iterators.hpp:344
RAJA_HOST_DEVICE difference_type operator-(const strided_numeric_iterator &rhs) const
Definition: Iterators.hpp:372
Header file for common RAJA internal macro definitions.
#define RAJA_HOST_DEVICE
Definition: macros.hpp:65
Definition: AlignedRangeIndexSetBuilders.cpp:35
RAJA_HOST_DEVICE constexpr RAJA_INLINE Result min(Args... args)
Definition: foldl.hpp:161
std::ptrdiff_t Index_type
Definition: types.hpp:226
typename internal::StripIndexTypeT< FROM >::type strip_index_type_t
Strips a strongly typed index to its underlying type In the case of a non-strongly typed index,...
Definition: IndexValue.hpp:364
RAJA_HOST_DEVICE constexpr RAJA_INLINE Result max(Args... args)
Definition: foldl.hpp:155
Header file for RAJA type definitions.