Loading...
Searching...
No Matches
iterator.hpp
1#pragma once
2
3#include <concepts>
4#include <cstddef>
5#include <type_traits>
6
7namespace tf {
8
27template <std::integral B, std::integral E, std::integral S>
28constexpr bool is_index_range_invalid(B beg, E end, S step) {
29 return ((step == 0 && beg != end) ||
30 (beg < end && step <= 0) || // positive range
31 (beg > end && step >= 0)); // negative range
32}
33
72template <std::integral B, std::integral E, std::integral S>
73constexpr size_t distance(B beg, E end, S step) {
74 return (end - beg + step + (step > 0 ? -1 : 1)) / step;
75}
76
77// ----------------------------------------------------------------------------
78// IndexRange
79// ----------------------------------------------------------------------------
80
116template <typename T>
118
119 static_assert(std::is_integral_v<T>, "index type must be integral");
120
121 public:
122
126 using index_type = T;
127
131 IndexRange() = default;
132
139 explicit IndexRange(T beg, T end, T step_size)
140 : _beg{beg}, _end{end}, _step_size{step_size} {}
141
145 T begin() const { return _beg; }
146
150 T end() const { return _end; }
151
155 T step_size() const { return _step_size; }
156
161 _beg = begin;
162 _end = end;
163 _step_size = step_size;
164 return *this;
165 }
166
170 IndexRange<T>& begin(T new_begin) { _beg = new_begin; return *this; }
171
175 IndexRange<T>& end(T new_end) { _end = new_end; return *this; }
176
180 IndexRange<T>& step_size(T new_step_size) { _step_size = new_step_size; return *this; }
181
194 size_t size() const { return distance(_beg, _end, _step_size); }
195
228 IndexRange unravel(size_t part_beg, size_t part_end) const {
229 return IndexRange(
230 static_cast<T>(part_beg) * _step_size + _beg,
231 static_cast<T>(part_end) * _step_size + _beg,
232 _step_size
233 );
234 }
235
236 private:
237
238 T _beg;
239 T _end;
240 T _step_size;
241
242};
243
244// ----------------------------------------------------------------------------
245
246
247
248
249
250} // end of namespace tf -----------------------------------------------------
IndexRange unravel(size_t part_beg, size_t part_end) const
maps a contiguous index partition back to the corresponding subrange
Definition iterator.hpp:228
size_t size() const
queries the number of elements in the range
Definition iterator.hpp:194
T end() const
queries the ending index of the range
Definition iterator.hpp:150
T begin() const
queries the starting index of the range
Definition iterator.hpp:145
T index_type
alias for the index type used in the range
Definition iterator.hpp:126
IndexRange< T > & end(T new_end)
updates the ending index of the range
Definition iterator.hpp:175
IndexRange< T > & reset(T begin, T end, T step_size)
updates the range with the new starting index, ending index, and step size
Definition iterator.hpp:160
IndexRange< T > & step_size(T new_step_size)
updates the step size of the range
Definition iterator.hpp:180
T step_size() const
queries the step size of the range
Definition iterator.hpp:155
IndexRange()=default
constructs an index range object without any initialization
IndexRange(T beg, T end, T step_size)
constructs an IndexRange object
Definition iterator.hpp:139
IndexRange< T > & begin(T new_begin)
updates the starting index of the range
Definition iterator.hpp:170
taskflow namespace
Definition small_vector.hpp:20
constexpr size_t distance(B beg, E end, S step)
calculates the number of iterations in the given index range
Definition iterator.hpp:73
constexpr bool is_index_range_invalid(B beg, E end, S step)
checks if the given index range is invalid
Definition iterator.hpp:28