TRIQS/itertools 2.0.0
C++ range library
Loading...
Searching...
No Matches
range.hpp
Go to the documentation of this file.
1// Copyright (c) 2024 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Thomas Hahn, Olivier Parcollet, Nils Wentzell, chuffa
16
21
22#ifndef _ITERTOOLS_RANGE_HPP
23#define _ITERTOOLS_RANGE_HPP
24
25#include "./product.hpp"
26
27#include <algorithm>
28#include <array>
29#include <cassert>
30#include <compare>
31#include <concepts>
32#include <iostream>
33#include <iterator>
34#include <stdexcept>
35#include <utility>
36
37namespace itertools {
38
43
64 class range {
65 // First value of the range.
66 long first_ = 0;
67
68 // Last value of the range (excluded).
69 long last_ = -1;
70
71 // Number of integers between two elements of the range.
72 long step_ = 1;
73
74 public:
80 struct all_t {};
81
83 static inline constexpr all_t all = {};
84
86 using index_t = long;
87
93 [[deprecated("range default construction deprecated. Use range::all for full range in slicing operation")]] range() = default;
94
101 range(std::integral auto first, std::integral auto last) noexcept : first_(first), last_(last) {}
102
112 range(std::integral auto first, std::integral auto last, std::integral auto step) : first_(first), last_(last), step_(step) {
113 if (step_ == 0) throw std::runtime_error("Step-size cannot be zero in construction of integer range");
114 }
115
120 explicit range(std::integral auto last) : range(0, last, 1) {}
121
123 [[nodiscard]] bool operator==(range const &) const = default;
124
126 [[nodiscard]] long first() const { return first_; }
127
129 [[nodiscard]] long last() const { return last_; }
130
132 [[nodiscard]] long step() const { return step_; }
133
135 [[nodiscard]] long size() const { return std::max(0l, (last_ + step_ - (step_ > 0 ? 1 : -1) - first_) / step_); }
136
145 [[nodiscard]] range operator+(long shift) const { return {first_ + shift, last_ + shift, step_}; }
146
154 friend inline std::ostream &operator<<(std::ostream &os, const range &rg) {
155 os << "range(" << rg.first() << "," << rg.last() << "," << rg.step() << ")";
156 return os;
157 }
158
162 long pos;
163
165 long step;
166
168 using value_type = long;
169
171 using iterator_category = std::random_access_iterator_tag;
172
175
177 using difference_type = std::ptrdiff_t;
178
180 using reference = value_type const &;
181
187 pos += step;
188 return *this;
189 }
190
196 const_iterator tmp = *this;
197 pos += step;
198 return tmp;
199 }
200
206 pos -= step;
207 return *this;
208 }
209
215 const_iterator tmp = *this;
216 pos -= step;
217 return tmp;
218 }
219
227 [[nodiscard]] std::strong_ordering operator<=>(const_iterator const &rhs) const noexcept {
228 return (step > 0 ? pos <=> rhs.pos : -pos <=> -rhs.pos);
229 }
230
237 [[nodiscard]] bool operator==(const_iterator const &other) const noexcept { return pos == other.pos; }
238
243 [[nodiscard]] long operator*() const noexcept { return pos; }
244
249 [[nodiscard]] long operator->() const noexcept { return operator*(); }
250
257 pos += n * step;
258 return *this;
259 }
260
266 [[nodiscard]] const_iterator operator+(difference_type n) const noexcept { return {.pos = pos + n * step, .step = step}; }
267
274 [[nodiscard]] friend const_iterator operator+(difference_type n, const_iterator it) noexcept { return it + n; }
275
282 pos -= n * step;
283 return *this;
284 }
285
291 [[nodiscard]] const_iterator operator-(difference_type n) const noexcept { return {.pos = pos - n * step, .step = step}; }
292
298 [[nodiscard]] difference_type operator-(const_iterator const &rhs) const noexcept { return (pos - rhs.pos) / step; }
299
305 [[nodiscard]] value_type operator[](difference_type n) const noexcept { return pos + n * step; }
306
307 }; // end struct const_iterator
308
310 using const_reverse_iterator = std::reverse_iterator<range::const_iterator>;
311
316 [[nodiscard]] const_iterator cbegin() const noexcept { return {.pos = first_, .step = step_}; }
317
319 [[nodiscard]] const_iterator begin() const noexcept { return {.pos = first_, .step = step_}; }
320
325 [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{end()}; }
326
328 [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
329
334 [[nodiscard]] const_iterator cend() const noexcept { return {.pos = first_ + step_ * size(), .step = step_}; }
335
337 [[nodiscard]] const_iterator end() const noexcept { return {.pos = first_ + step_ * size(), .step = step_}; }
338
343 [[nodiscard]] const_reverse_iterator crend() const noexcept { return const_reverse_iterator{begin()}; }
344
346 [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
347 };
348
372 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>> [[nodiscard]] auto product_range(Is... is) {
373 return product(range(is)...);
374 }
375
376 namespace detail {
377
378 // Helper function to create a product range of integer ranges from a tuple or an array.
379 template <typename T, size_t... Is> [[gnu::always_inline]] auto product_range_impl(T const &idxs, std::index_sequence<Is...>) {
380 return product_range(std::get<Is>(idxs)...);
381 }
382
383 } // namespace detail
384
394 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>>
395 [[nodiscard]] auto product_range(std::tuple<Is...> const &idx_tpl) {
396 return detail::product_range_impl(idx_tpl, std::make_index_sequence<sizeof...(Is)>{});
397 }
398
409 template <typename I, size_t N, typename EnableIf = std::enable_if_t<std::is_integral_v<I>, int>>
410 [[nodiscard]] auto product_range(std::array<I, N> const &idx_arr) {
411 return detail::product_range_impl(idx_arr, std::make_index_sequence<N>{});
412 }
413
429 template <typename F> void foreach (range const &rg, F && f) {
430 auto i = rg.first(), last = rg.last(), step = rg.step();
431 for (; i < last; i += step) std::forward<F>(f)(i);
432 }
433
435
436} // namespace itertools
437
438#endif // _ITERTOOLS_RANGE_HPP
A lazy range of integers that mimics a Python range.
Definition range.hpp:64
static constexpr all_t all
See range::all_t.
Definition range.hpp:83
long index_t
Integer type for backward compatibility.
Definition range.hpp:86
const_iterator cbegin() const noexcept
Beginning of the integer range.
Definition range.hpp:316
const_iterator cend() const noexcept
End of the range.
Definition range.hpp:334
const_reverse_iterator rbegin() const noexcept
The same as crbegin().
Definition range.hpp:328
const_reverse_iterator crbegin() const noexcept
Beginning of the integer range in reverse order.
Definition range.hpp:325
range(std::integral auto first, std::integral auto last) noexcept
Construct a range with a step size of 1 and a given first and last (excluded) value.
Definition range.hpp:101
range operator+(long shift) const
Shift the whole range by a given amount.
Definition range.hpp:145
friend std::ostream & operator<<(std::ostream &os, const range &rg)
Write the range details to std::ostream.
Definition range.hpp:154
bool operator==(range const &) const =default
Default equal-to operator.
range()=default
Default constructor.
range(std::integral auto first, std::integral auto last, std::integral auto step)
Construct a range with a given step size and a given first and last (excluded) value.
Definition range.hpp:112
long first() const
Get first value of the range.
Definition range.hpp:126
long last() const
Get last value of the range (excluded).
Definition range.hpp:129
const_iterator end() const noexcept
The same as cend().
Definition range.hpp:337
long step() const
Get step size between two elements of the range.
Definition range.hpp:132
std::reverse_iterator< range::const_iterator > const_reverse_iterator
Reverse const iterator type for itertools::range.
Definition range.hpp:310
range(std::integral auto last)
Construct a range with a step size of 1, a first value set to 0 and a given last value (excluded).
Definition range.hpp:120
long size() const
Get number of elements in the range.
Definition range.hpp:135
const_reverse_iterator crend() const noexcept
End of the range in reverse order.
Definition range.hpp:343
const_iterator begin() const noexcept
The same as cbegin().
Definition range.hpp:319
const_reverse_iterator rend() const noexcept
The same as crend().
Definition range.hpp:346
auto product_range(Is... is)
Create a cartesian product range of integer ranges from given integers.
Definition range.hpp:372
itertools::multiplied< Rs... > product(Rs &&...rgs)
Lazy-multiply a given number of ranges by forming their cartesian product.
Definition product.hpp:413
Provides a range adapting function for multiplying a given number of ranges/views (cartesian product)...
Denote a full range at compile-time.
Definition range.hpp:80
Const iterator type for itertools::range.
Definition range.hpp:160
const_iterator & operator++() noexcept
Pre-increment operator increments the current value by the step size.
Definition range.hpp:186
const_iterator & operator--() noexcept
Pre-decrement operator decrements the current value by the step size.
Definition range.hpp:205
std::random_access_iterator_tag iterator_category
Iterator category.
Definition range.hpp:171
const_iterator operator++(int) noexcept
Post-increment operator increments the current value by the step size.
Definition range.hpp:195
value_type * pointer
Pointer type.
Definition range.hpp:174
std::ptrdiff_t difference_type
Difference type.
Definition range.hpp:177
value_type operator[](difference_type n) const noexcept
Subscript operator.
Definition range.hpp:305
friend const_iterator operator+(difference_type n, const_iterator it) noexcept
Addition operator for an integer and an iterator.
Definition range.hpp:274
bool operator==(const_iterator const &other) const noexcept
Equal-to operator for two iterators.
Definition range.hpp:237
long operator*() const noexcept
Dereference operator.
Definition range.hpp:243
difference_type operator-(const_iterator const &rhs) const noexcept
Get the distance between two iterators.
Definition range.hpp:298
std::strong_ordering operator<=>(const_iterator const &rhs) const noexcept
Three-way comparison operator for two iterators.
Definition range.hpp:227
const_iterator & operator-=(difference_type n) noexcept
Subtraction assignment operator.
Definition range.hpp:281
const_iterator & operator+=(difference_type n) noexcept
Addition assignment operator.
Definition range.hpp:256
const_iterator operator+(difference_type n) const noexcept
Addition operator for an iterator and an integer.
Definition range.hpp:266
long operator->() const noexcept
Member access operator.
Definition range.hpp:249
value_type const & reference
Reference type.
Definition range.hpp:180
const_iterator operator--(int) noexcept
Post-decrement operator decrements the current value by the step size.
Definition range.hpp:214
const_iterator operator-(difference_type n) const noexcept
Subtraction operator for an iterator and an integer.
Definition range.hpp:291