MCKL
Monte Carlo Kernel Library
iterator.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/core/iterator.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_CORE_ITERATOR_HPP
33 #define MCKL_CORE_ITERATOR_HPP
34 
35 #include <mckl/internal/common.hpp>
36 
37 namespace mckl {
38 
43 template <typename Base>
45 {
46  public:
47  using difference_type = std::make_signed_t<
48  typename std::iterator_traits<Base>::difference_type>;
49  using value_type = typename std::iterator_traits<Base>::value_type;
50  using pointer = typename std::iterator_traits<Base>::pointer;
51  using reference = typename std::iterator_traits<Base>::reference;
52  using iterator_category =
53  typename std::iterator_traits<Base>::iterator_category;
54 
56  StepIterator() noexcept(std::is_nothrow_default_constructible<Base>::value)
57  : base_(Base()), step_(1)
58  {
59  }
60 
69  explicit StepIterator(Base base, difference_type step = 1) noexcept(
70  std::is_nothrow_copy_constructible<Base>::value)
71  : base_(base), step_(step)
72  {
73  }
74 
78  template <typename T>
79  StepIterator(const StepIterator<T> &other) noexcept(
80  std::is_nothrow_copy_constructible<Base>::value)
81  : base_(other.base()), step_(other.step())
82  {
83  }
84 
86  Base base() const { return base_; }
87 
89  difference_type step() const { return step_; }
90 
92  reference operator*() const { return *base_; }
93 
95  Base operator->() const { return base_; }
96 
101  template <typename IntType>
102  reference operator[](IntType n) const
103  {
104  return *((*this) + n);
105  }
106 
111  friend bool operator==(
112  const StepIterator &iter1, const StepIterator &iter2)
113  {
114  runtime_assert(iter1.step_ == iter2.step_,
115  "Compare two StepIterator objects with different steps");
116 
117  return iter1.base_ == iter2.base_;
118  }
119 
124  friend bool operator!=(
125  const StepIterator &iter1, const StepIterator &iter2)
126  {
127  runtime_assert(iter1.step_ == iter2.step_,
128  "Compare two StepIterator objects with different steps");
129 
130  return iter1.base_ != iter2.base_;
131  }
132 
137  friend bool operator<(const StepIterator &iter1, const StepIterator &iter2)
138  {
139  runtime_assert(iter1.step_ == iter2.step_,
140  "Compare two StepIterator objects with different steps");
141 
142  return iter1.base_ < iter2.base_;
143  }
144 
149  friend bool operator<=(
150  const StepIterator &iter1, const StepIterator &iter2)
151  {
152  runtime_assert(iter1.step_ == iter2.step_,
153  "Compare two StepIterator objects with different steps");
154 
155  return iter1.base_ <= iter2.base_;
156  }
157 
162  friend bool operator>(const StepIterator &iter1, const StepIterator &iter2)
163  {
164  runtime_assert(iter1.step_ == iter2.step_,
165  "Compare two StepIterator objects with different steps");
166 
167  return iter1.base_ > iter2.base_;
168  }
169 
174  friend bool operator>=(
175  const StepIterator &iter1, const StepIterator &iter2)
176  {
177  runtime_assert(iter1.step_ == iter2.step_,
178  "Compare two StepIterator objects with different steps");
179 
180  return iter1.base_ >= iter2.base_;
181  }
182 
189  {
190  using std::advance;
191 
192  advance(iter.base_, iter.step_);
193 
194  return iter;
195  }
196 
202  {
203  StepIterator ret(iter);
204  ++iter;
205 
206  return ret;
207  }
208 
215  {
216  using std::advance;
217 
218  advance(iter.base_, -iter.step_);
219 
220  return iter;
221  }
222 
228  {
229  StepIterator ret(iter);
230  --iter;
231 
232  return ret;
233  }
234 
240  template <typename IntType>
241  friend StepIterator operator+(const StepIterator &iter, IntType n)
242  {
243  using std::advance;
244 
245  StepIterator ret(iter);
246  advance(ret.base_, static_cast<difference_type>(n) * ret.step_);
247 
248  return ret;
249  }
250 
255  template <typename IntType>
256  friend StepIterator operator+(IntType n, const StepIterator &iter)
257  {
258  return iter + n;
259  }
260 
266  template <typename IntType>
267  friend StepIterator operator-(const StepIterator &iter, IntType n)
268  {
269  return iter + (-static_cast<difference_type>(n));
270  }
271 
276  template <typename IntType>
277  friend StepIterator &operator+=(StepIterator &iter, IntType n)
278  {
279  return iter = iter + n;
280  }
281 
286  template <typename IntType>
287  friend StepIterator &operator-=(StepIterator &iter, IntType n)
288  {
289  return iter = iter - n;
290  }
291 
298  const StepIterator &iter1, const StepIterator &iter2)
299  {
300  runtime_assert(iter1.step_ == iter2.step_,
301  "Subtract two StepIterator objects with different steps");
302 
303  using std::distance;
304 
305  return distance(iter2.base_, iter1.base_) / iter1.step_;
306  }
307 
308  private:
309  Base base_;
310  difference_type step_;
311 }; // class StepIterator
312 
313 template <typename T, bool = std::is_integral<T>::value>
314 class Range;
315 
324 template <typename IntType>
325 class Range<IntType, true>
326 {
327  public:
328  using size_type = std::size_t;
329  using iterator = IntType;
330 
332  Range() noexcept : begin_(0), end_(0), grainsize_(1) {}
333 
341  Range(iterator begin, iterator end, size_type grainsize = 1)
342  : begin_(begin), end_(end), grainsize_(grainsize)
343  {
344  runtime_assert(begin_ <= end_,
345  "**Range::Range** used with invalid pair of integers");
346  }
347 
349  Range(const Range &) = default;
350 
358  template <typename Split>
359  Range(Range &other, Split)
360  : begin_(other.begin_ + (other.end_ - other.begin_) / 2)
361  , end_(other.end_)
362  , grainsize_(other.grainsize_)
363  {
364  other.end_ = begin_;
365  }
366 
370  size_type size() const { return empty() ? 0 : end_ - begin_; }
371 
373  size_type grainsize() const { return grainsize_; }
374 
376  bool empty() const { return begin_ >= end_; }
377 
379  bool is_divisible() const { return grainsize_ <= size(); }
380 
382  iterator begin() const { return begin_; }
383 
385  iterator end() const { return end_; }
386 
387  private:
388  iterator begin_;
389  iterator end_;
390  size_type grainsize_;
391 }; // class Range
392 
401 template <typename Iterator>
402 class Range<Iterator, false>
403 {
404  public:
405  using size_type = std::size_t;
406  using iterator = Iterator;
407  using value_type = typename std::iterator_traits<iterator>::value_type;
408  using pointer = typename std::iterator_traits<iterator>::pointer;
409  using reference = typename std::iterator_traits<iterator>::reference;
410 
412  Range() : begin_(iterator()), end_(begin_), grainsize_(1) {}
413 
422  Range(iterator begin, iterator end, size_type grainsize = 1)
423  : begin_(begin), end_(end), grainsize_(grainsize)
424  {
425  using std::distance;
426 
427  runtime_assert(distance(begin_, end_) >= 0,
428  "**Range::Range** used with invalid pair of iterators");
429  }
430 
432  Range(const Range &) = default;
433 
444  template <typename Split>
445  Range(Range &other, Split)
446  : begin_(other.begin_), end_(other.end_), grainsize_(other.grainsize_)
447  {
448  using std::advance;
449  using std::distance;
450 
451  advance(begin_, distance(begin_, end_) / 2);
452  other.end_ = begin_;
453  }
454 
458  size_type size() const
459  {
460  using std::distance;
461 
462  return empty() ? 0 : static_cast<size_type>(distance(begin_, end_));
463  }
464 
466  size_type grainsize() const { return grainsize_; }
467 
469  bool empty() const
470  {
471  using std::distance;
472 
473  return distance(begin_, end_) <= 0;
474  }
475 
477  bool is_divisible() const { return grainsize_ <= size(); }
478 
480  iterator begin() const { return begin_; }
481 
483  iterator end() const { return end_; }
484 
490  {
491  runtime_assert<std::out_of_range>(
492  n < size(), "**Range::at** index out of range");
493 
494  return operator[](n);
495  }
496 
502  {
503  using std::advance;
504 
505  iterator iter = begin_;
506  advance(iter, n);
507 
508  return *iter;
509  }
510 
512  reference front() const { return *begin_; }
513 
517  reference back() const { return *(--end_); }
518 
519  private:
520  iterator begin_;
521  iterator end_;
522  size_type grainsize_;
523 }; // class Range
524 
525 } // namespace mckl
526 
527 #endif // MCKL_CORE_ITERATOR_HPP
typename std::iterator_traits< Base >::reference reference
Definition: iterator.hpp:51
Range(iterator begin, iterator end, size_type grainsize=1)
Construct a new range with a pair of iterators.
Definition: iterator.hpp:422
friend StepIterator & operator--(StepIterator &iter)
Prefix decrement: advance the base iterator by a distance of -iter.step()
Definition: iterator.hpp:214
reference at(size_type n) const
Access an element within the range with bound checking.
Definition: iterator.hpp:489
iterator end() const
The upper bound of the range.
Definition: iterator.hpp:385
typename std::iterator_traits< Base >::iterator_category iterator_category
Definition: iterator.hpp:53
size_type grainsize() const
Return the grain size.
Definition: iterator.hpp:466
Range(Range &other, Split)
Copy construct a new range which split the original.
Definition: iterator.hpp:359
StepIterator(const StepIterator< T > &other) noexcept(std::is_nothrow_copy_constructible< Base >::value)
Convert from compatible StepIterator.
Definition: iterator.hpp:79
Range(Range &other, Split)
Copy construct a new range which split the original.
Definition: iterator.hpp:445
difference_type step() const
Return the increment step size.
Definition: iterator.hpp:89
Base operator->() const
Member selection through the base iterator.
Definition: iterator.hpp:95
typename std::iterator_traits< iterator >::pointer pointer
Definition: iterator.hpp:408
friend bool operator>=(const StepIterator &iter1, const StepIterator &iter2)
Compare greater than relation or equality.
Definition: iterator.hpp:174
size_type size() const
Return the size of the range.
Definition: iterator.hpp:458
friend bool operator==(const StepIterator &iter1, const StepIterator &iter2)
Compare equality.
Definition: iterator.hpp:111
Range()
Default constructor.
Definition: iterator.hpp:412
reference front() const
Access the first element in the range.
Definition: iterator.hpp:512
size_type size() const
Return the size of the range.
Definition: iterator.hpp:370
STL namespace.
reference operator[](IntType n) const
Equivalent to *((*this) + n)
Definition: iterator.hpp:102
Range() noexcept
Default constructor.
Definition: iterator.hpp:332
typename std::iterator_traits< iterator >::value_type value_type
Definition: iterator.hpp:407
friend StepIterator operator+(const StepIterator &iter, IntType n)
Addition with integer: advance the base iterator by a distance of n * iter.step() ...
Definition: iterator.hpp:241
Base base() const
Return the underlying base iterator.
Definition: iterator.hpp:86
bool empty() const
If the range is empty, i.e., begin() >= end()
Definition: iterator.hpp:376
friend StepIterator operator++(StepIterator &iter, int)
Postfix increment.
Definition: iterator.hpp:201
bool empty() const
If the range is empty, i.e., distance(begin(), end()) <= 0
Definition: iterator.hpp:469
friend StepIterator & operator++(StepIterator &iter)
Prefix increment: advance the base iterator by a distance of iter.step()
Definition: iterator.hpp:188
friend StepIterator & operator-=(StepIterator &iter, IntType n)
Compound subtraction with integer.
Definition: iterator.hpp:287
friend StepIterator operator-(const StepIterator &iter, IntType n)
Subtraction with integer: advance the base iterator by a distance -n * iter.step() ...
Definition: iterator.hpp:267
reference operator[](size_type n) const
Access an element within the range.
Definition: iterator.hpp:501
iterator begin() const
The lower bound of the range.
Definition: iterator.hpp:382
iterator begin() const
The lower bound of the range.
Definition: iterator.hpp:480
friend StepIterator operator+(IntType n, const StepIterator &iter)
Addition with integer.
Definition: iterator.hpp:256
reference back() const
Access the last element in the range.
Definition: iterator.hpp:517
iterator end() const
The upper bound of the range.
Definition: iterator.hpp:483
bool is_divisible() const
If the range is divisible, i.e., grainsize() <= size()
Definition: iterator.hpp:379
StepIterator() noexcept(std::is_nothrow_default_constructible< Base >::value)
Default constructor.
Definition: iterator.hpp:56
friend bool operator>(const StepIterator &iter1, const StepIterator &iter2)
Compare greater than relation.
Definition: iterator.hpp:162
friend bool operator<(const StepIterator &iter1, const StepIterator &iter2)
Compare less than relation.
Definition: iterator.hpp:137
size_type grainsize() const
Return the grain size.
Definition: iterator.hpp:373
Definition: mcmc.hpp:40
friend bool operator!=(const StepIterator &iter1, const StepIterator &iter2)
Compare inequality.
Definition: iterator.hpp:124
std::make_signed_t< typename std::iterator_traits< Base >::difference_type > difference_type
Definition: iterator.hpp:48
Iterator adapter which increment the base iterator in multiple steps.
Definition: iterator.hpp:44
StepIterator(Base base, difference_type step=1) noexcept(std::is_nothrow_copy_constructible< Base >::value)
Convert from a base iterator.
Definition: iterator.hpp:69
friend difference_type operator-(const StepIterator &iter1, const StepIterator &iter2)
Difference between two iterators.
Definition: iterator.hpp:297
typename std::iterator_traits< iterator >::reference reference
Definition: iterator.hpp:409
friend StepIterator operator--(StepIterator &iter, int)
Postfix decrement.
Definition: iterator.hpp:227
typename std::iterator_traits< Base >::value_type value_type
Definition: iterator.hpp:49
Range(iterator begin, iterator end, size_type grainsize=1)
Construct a new range with a pair of integers.
Definition: iterator.hpp:341
friend bool operator<=(const StepIterator &iter1, const StepIterator &iter2)
Compare less than relation or equality.
Definition: iterator.hpp:149
reference operator*() const
Dereference the base iterator.
Definition: iterator.hpp:92
bool is_divisible() const
If the range is divisible, i.e., grainsize() <= size()
Definition: iterator.hpp:477
typename std::iterator_traits< Base >::pointer pointer
Definition: iterator.hpp:50
friend StepIterator & operator+=(StepIterator &iter, IntType n)
Compound addition with integer.
Definition: iterator.hpp:277
void runtime_assert(bool cond, const char *msg, bool soft=false)
Definition: assert.hpp:65