Volume Cartographer 2.27.0
Iteration.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <cmath>
6#include <cstddef>
7#include <iostream>
8#include <type_traits>
9
10namespace volcart
11{
12
23template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
25{
26private:
27 template <typename ItT>
29 {
30 private:
32 ItT value_{0};
34 ItT maxValue_{1};
36 ItT step_{1};
37
38 public:
40 using difference_type = std::size_t;
41 using value_type = ItT;
42 using pointer = value_type*;
43 using reference = value_type const&;
44 using iterator_category = std::input_iterator_tag;
48 explicit CountingIterator(ItT value, ItT maxValue, ItT step)
49 : value_{value}, maxValue_{maxValue}, step_{step}
50 {
51 }
52
54 reference operator*() const { return value_; }
55
57 bool operator==(const CountingIterator& other) const
58 {
59 return value_ == other.value_;
60 }
61
63 bool operator!=(const CountingIterator& other) const
64 {
65 return !(*this == other);
66 }
67
70 {
71 // Stop iterating at the max value
72 if (value_ < maxValue_) {
73 value_ = std::min(value_ + step_, maxValue_);
74 }
75 return *this;
76 }
77 };
78
79public:
84
86 RangeIterable(T start, T end, T step)
87 : start_{start}, end_{end}, step_{step}
88 {
89 if (step <= 0) {
90 throw std::invalid_argument("step size cannot be zero or negative");
91 }
92 }
93
95 iterator begin() const { return iterator{start_, end_, step_}; }
97 iterator end() const { return iterator{end_, end_, step_}; }
100 {
101 return const_iterator{start_, end_, step_};
102 }
104 const_iterator cend() const { return const_iterator{end_, end_, step_}; }
105
107 template <typename Q = T>
108 std::enable_if_t<std::is_floating_point<Q>::value, std::size_t> size() const
109 {
110 return static_cast<std::size_t>(std::ceil((end_ - start_) / step_));
111 }
112
114 template <typename Q = T>
115 std::enable_if_t<std::is_integral<Q>::value, std::size_t> size() const
116 {
117 return static_cast<std::size_t>((end_ - start_) / step_);
118 }
119
120private:
121 T start_{0};
122 T end_{0};
123 T step_{1};
124};
125
127template <typename T>
128std::ostream& operator<<(std::ostream& os, const RangeIterable<T>& it)
129{
130 for (const auto& v : it) {
131 if (v != *it.begin()) {
132 os << " ";
133 }
134 os << v;
135 }
136 return os;
137}
138
147template <typename T>
148auto range(T stop)
149{
150 return RangeIterable<T>(0, stop, 1);
151}
152
161template <typename T0, typename T1>
162auto range(T0 start, T1 stop)
163{
164 return RangeIterable<T0>(start, stop, 1);
165}
166
177template <typename T0, typename T1, typename T2>
178auto range(T0 start, T1 stop, T2 step)
179{
180 return RangeIterable<T0>(start, stop, step);
181}
182
193template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
195{
196private:
197 template <typename ItT>
199 {
200 private:
202 ItT v_{0};
204 ItT vMax_{1};
206 ItT u_{0};
208 ItT uStart_{0};
210 ItT uMax_{1};
212 ItT step_{1};
213
214 public:
216 using difference_type = std::size_t;
217 using value_type = std::pair<ItT const&, ItT const&>;
218 using pointer = value_type*;
219 using reference = value_type;
220 using iterator_category = std::input_iterator_tag;
224 explicit Counting2DIterator(ItT v, ItT vMax, ItT u, ItT uMax, ItT step)
225 : v_{v}, vMax_{vMax}, u_{u}, uStart_{u}, uMax_{uMax}, step_{step}
226 {
227 }
228
230 reference operator*() const { return {v_, u_}; }
231
233 bool operator==(const Counting2DIterator& other) const
234 {
235 return u_ == other.u_ and v_ == other.v_;
236 }
237
239 bool operator!=(const Counting2DIterator& other) const
240 {
241 return !(*this == other);
242 }
243
246 {
247 if (u_ < uMax_) {
248 u_ = std::min(u_ + step_, uMax_);
249 }
250
251 if (u_ == uMax_ and v_ < vMax_) {
252 v_ = std::min(v_ + step_, vMax_);
253
254 if (v_ < vMax_) {
255 u_ = uStart_;
256 }
257 }
258
259 return *this;
260 }
261 };
262
263public:
268
270 Range2DIterable(T vStart, T vEnd, T uStart, T uEnd, T step)
271 : vStart_{vStart}
272 , vEnd_{vEnd}
273 , uStart_{uStart}
274 , uEnd_{uEnd}
275 , step_{step}
276 {
277 if (step <= 0) {
278 throw std::invalid_argument("step size cannot be zero or negative");
279 }
280 }
281
284 {
286 }
288 iterator end() const { return iterator{vEnd_, vEnd_, uEnd_, uEnd_, step_}; }
291 {
293 }
296 {
298 }
299
301 template <typename Q = T>
302 std::enable_if_t<std::is_floating_point<Q>::value, std::size_t> size() const
303 {
304 auto vLen =
305 static_cast<std::size_t>(std::ceil((vEnd_ - vStart_) / step_));
306 return static_cast<std::size_t>(std::ceil((uEnd_ - uStart_) / step_)) *
307 vLen;
308 }
309
311 template <typename Q = T>
312 std::enable_if_t<std::is_integral<Q>::value, std::size_t> size() const
313 {
314 auto vLen = static_cast<std::size_t>((vEnd_ - vStart_) / step_);
315 return static_cast<std::size_t>((uEnd_ - uStart_) / step_) * vLen;
316 }
317
318private:
322 T vEnd_{0};
326 T uEnd_{0};
328 T step_{1};
329};
330
340template <typename T0, typename T1>
341auto range2D(T0 vStop, T1 uStop)
342{
343 return Range2DIterable<T0>(0, vStop, 0, uStop, 1);
344}
345
357template <typename T0, typename T1, typename T2, typename T3>
358auto range2D(T0 vStart, T1 vStop, T2 uStart, T3 uStop)
359{
360 return Range2DIterable<T0>(vStart, vStop, uStart, uStop, 1);
361}
362
375template <typename T0, typename T1, typename T2, typename T3, typename T4>
376auto range2D(T0 vStart, T1 vStop, T2 uStart, T3 uStop, T4 step)
377{
378 return Range2DIterable<T0>(vStart, vStop, uStart, uStop, step);
379}
380
381// Predeclarations
382template <class Iterable>
383class EnumerateIterable;
384
385template <class Iterable>
386inline auto enumerate(Iterable&& it);
387
388template <typename... Args>
389inline EnumerateIterable<std::vector<std::common_type_t<Args...>>> enumerate(
390 Args&&... args);
391
400template <class Iterable>
402{
403private:
405 template <class T>
407 {
408 private:
409 std::size_t idx_;
410 T it_;
411
412 public:
414 using difference_type = std::size_t;
415 using value_type =
416 std::pair<std::size_t, decltype(*std::declval<T&>())&>;
417 using pointer = value_type*;
418 using reference = value_type;
419 using iterator_category = std::input_iterator_tag;
423 explicit EnumerateIterator(std::size_t idx, T&& it)
424 : idx_{idx}, it_{std::move(it)}
425 {
426 }
427
429 value_type operator*() const { return {idx_, *it_}; }
430
432 bool operator==(const EnumerateIterator& other) const
433 {
434 return it_ == other.it_;
435 }
436
438 bool operator!=(const EnumerateIterator& other) const
439 {
440 return !(*this == other);
441 }
442
445 {
446 ++idx_;
447 ++it_;
448 return *this;
449 }
450 };
451
452 using IteratorType = decltype(std::begin(std::declval<Iterable>()));
453
454 EnumerateIterable(Iterable&& container)
455 : container_{std::forward<Iterable>(container)}
456 {
457 }
458
459 template <typename... Args>
460 EnumerateIterable(Args&&... args) : container_{std::forward<Args>(args)...}
461 {
462 }
463
464 friend auto enumerate<Iterable>(Iterable&& it);
465
466 template <typename... Args>
467 friend EnumerateIterable<std::vector<std::common_type_t<Args...>>>
468 enumerate(Args&&... args);
469
470public:
471 using iterator = EnumerateIterator<IteratorType>;
472 using const_iterator = EnumerateIterator<const IteratorType>;
473
475 iterator begin() const { return iterator{0, std::begin(container_)}; }
476
478 iterator end() const { return iterator{0, std::end(container_)}; }
479
482 {
483 return const_iterator{0, std::begin(container_)};
484 }
485
488 {
489 return const_iterator{0, std::end(container_)};
490 }
491
492private:
493 Iterable container_;
494};
495
526template <class Iterable>
527inline auto enumerate(Iterable&& it)
528{
529 return EnumerateIterable<Iterable>(std::forward<Iterable>(it));
530}
531
548template <typename... Args>
549inline EnumerateIterable<std::vector<std::common_type_t<Args...>>> enumerate(
550 Args&&... args)
551{
552 using Type = std::common_type_t<Args...>;
553 using Iterable = std::vector<Type>;
554 return EnumerateIterable<Iterable>(std::forward<Args>(args)...);
555}
556
557} // namespace volcart
bool operator==(const EnumerateIterator &other) const
Definition: Iteration.hpp:432
EnumerateIterator(std::size_t idx, T &&it)
Definition: Iteration.hpp:423
bool operator!=(const EnumerateIterator &other) const
Definition: Iteration.hpp:438
friend auto enumerate(Iterable &&it)
Wrap an Iterable into a new one whose iterators return an [index, value] pair.
Definition: Iteration.hpp:527
iterator begin() const
Definition: Iteration.hpp:475
iterator end() const
Definition: Iteration.hpp:478
const_iterator cbegin() const
Definition: Iteration.hpp:481
const_iterator cend() const
Definition: Iteration.hpp:487
bool operator!=(const Counting2DIterator &other) const
Definition: Iteration.hpp:239
Counting2DIterator(ItT v, ItT vMax, ItT u, ItT uMax, ItT step)
Definition: Iteration.hpp:224
bool operator==(const Counting2DIterator &other) const
Definition: Iteration.hpp:233
Provides an iterable range of 2D number pairs with optional step size.
Definition: Iteration.hpp:195
iterator begin() const
Definition: Iteration.hpp:283
std::enable_if_t< std::is_integral< Q >::value, std::size_t > size() const
Definition: Iteration.hpp:312
iterator end() const
Definition: Iteration.hpp:288
Range2DIterable(T vStart, T vEnd, T uStart, T uEnd, T step)
Definition: Iteration.hpp:270
const_iterator cbegin() const
Definition: Iteration.hpp:290
const_iterator cend() const
Definition: Iteration.hpp:295
std::enable_if_t< std::is_floating_point< Q >::value, std::size_t > size() const
Definition: Iteration.hpp:302
bool operator!=(const CountingIterator &other) const
Definition: Iteration.hpp:63
CountingIterator(ItT value, ItT maxValue, ItT step)
Definition: Iteration.hpp:48
bool operator==(const CountingIterator &other) const
Definition: Iteration.hpp:57
Provides an iterable range of numbers with optional step size.
Definition: Iteration.hpp:25
iterator begin() const
Definition: Iteration.hpp:95
std::enable_if_t< std::is_floating_point< Q >::value, std::size_t > size() const
Definition: Iteration.hpp:108
const_iterator cbegin() const
Definition: Iteration.hpp:99
std::enable_if_t< std::is_integral< Q >::value, std::size_t > size() const
Definition: Iteration.hpp:115
const_iterator cend() const
Definition: Iteration.hpp:104
RangeIterable(T start, T end, T step)
Definition: Iteration.hpp:86
iterator end() const
Definition: Iteration.hpp:97
auto range(T stop)
Definition: Iteration.hpp:148
auto enumerate(Iterable &&it)
Wrap an Iterable into a new one whose iterators return an [index, value] pair.
Definition: Iteration.hpp:527
auto range2D(T0 vStop, T1 uStop)
Definition: Iteration.hpp:341
Type
Implemented Volume Landmark types.
Volume Cartographer library
std::ostream & operator<<(std::ostream &os, const RangeIterable< T > &it)
Definition: Iteration.hpp:128