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_;
67
68 // Last value of the range (excluded).
69 long last_;
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
94 range(std::integral auto first, std::integral auto last) noexcept : first_(first), last_(last) {}
95
105 range(std::integral auto first, std::integral auto last, std::integral auto step) : first_(first), last_(last), step_(step) {
106 if (step_ == 0) throw std::runtime_error("Step-size cannot be zero in construction of integer range");
107 }
108
113 explicit range(std::integral auto last) : range(0, last, 1) {}
114
116 [[nodiscard]] bool operator==(range const &) const = default;
117
119 [[nodiscard]] long first() const { return first_; }
120
122 [[nodiscard]] long last() const { return last_; }
123
125 [[nodiscard]] long step() const { return step_; }
126
128 [[nodiscard]] long size() const { return std::max(0l, (last_ + step_ - (step_ > 0 ? 1 : -1) - first_) / step_); }
129
138 [[nodiscard]] range operator+(long shift) const { return {first_ + shift, last_ + shift, step_}; }
139
147 friend inline std::ostream &operator<<(std::ostream &os, const range &rg) {
148 os << "range(" << rg.first() << "," << rg.last() << "," << rg.step() << ")";
149 return os;
150 }
151
155 long pos;
156
158 long step;
159
161 using value_type = long;
162
164 using iterator_category = std::random_access_iterator_tag;
165
168
170 using difference_type = std::ptrdiff_t;
171
173 using reference = value_type const &;
174
180 pos += step;
181 return *this;
182 }
183
189 const_iterator tmp = *this;
190 pos += step;
191 return tmp;
192 }
193
199 pos -= step;
200 return *this;
201 }
202
208 const_iterator tmp = *this;
209 pos -= step;
210 return tmp;
211 }
212
220 [[nodiscard]] std::strong_ordering operator<=>(const_iterator const &rhs) const noexcept {
221 return (step > 0 ? pos <=> rhs.pos : -pos <=> -rhs.pos);
222 }
223
230 [[nodiscard]] bool operator==(const_iterator const &other) const noexcept { return pos == other.pos; }
231
236 [[nodiscard]] long operator*() const noexcept { return pos; }
237
242 [[nodiscard]] long operator->() const noexcept { return operator*(); }
243
250 pos += n * step;
251 return *this;
252 }
253
259 [[nodiscard]] const_iterator operator+(difference_type n) const noexcept { return {.pos = pos + n * step, .step = step}; }
260
267 [[nodiscard]] friend const_iterator operator+(difference_type n, const_iterator it) noexcept { return it + n; }
268
275 pos -= n * step;
276 return *this;
277 }
278
284 [[nodiscard]] const_iterator operator-(difference_type n) const noexcept { return {.pos = pos - n * step, .step = step}; }
285
291 [[nodiscard]] difference_type operator-(const_iterator const &rhs) const noexcept { return (pos - rhs.pos) / step; }
292
298 [[nodiscard]] value_type operator[](difference_type n) const noexcept { return pos + n * step; }
299
300 }; // end struct const_iterator
301
303 using const_reverse_iterator = std::reverse_iterator<range::const_iterator>;
304
309 [[nodiscard]] const_iterator cbegin() const noexcept { return {.pos = first_, .step = step_}; }
310
312 [[nodiscard]] const_iterator begin() const noexcept { return {.pos = first_, .step = step_}; }
313
318 [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{end()}; }
319
321 [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
322
327 [[nodiscard]] const_iterator cend() const noexcept { return {.pos = first_ + step_ * size(), .step = step_}; }
328
330 [[nodiscard]] const_iterator end() const noexcept { return {.pos = first_ + step_ * size(), .step = step_}; }
331
336 [[nodiscard]] const_reverse_iterator crend() const noexcept { return const_reverse_iterator{begin()}; }
337
339 [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
340 };
341
365 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>> [[nodiscard]] auto product_range(Is... is) {
366 return product(range(is)...);
367 }
368
369 namespace detail {
370
371 // Helper function to create a product range of integer ranges from a tuple or an array.
372 template <typename T, size_t... Is> [[gnu::always_inline]] auto product_range_impl(T const &idxs, std::index_sequence<Is...>) {
373 return product_range(std::get<Is>(idxs)...);
374 }
375
376 } // namespace detail
377
387 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>>
388 [[nodiscard]] auto product_range(std::tuple<Is...> const &idx_tpl) {
389 return detail::product_range_impl(idx_tpl, std::make_index_sequence<sizeof...(Is)>{});
390 }
391
402 template <typename I, size_t N, typename EnableIf = std::enable_if_t<std::is_integral_v<I>, int>>
403 [[nodiscard]] auto product_range(std::array<I, N> const &idx_arr) {
404 return detail::product_range_impl(idx_arr, std::make_index_sequence<N>{});
405 }
406
422 template <typename F> void foreach (range const &rg, F && f) {
423 auto i = rg.first(), last = rg.last(), step = rg.step();
424 for (; i < last; i += step) std::forward<F>(f)(i);
425 }
426
428
429} // namespace itertools
430
431#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:309
const_iterator cend() const noexcept
End of the range.
Definition range.hpp:327
const_reverse_iterator rbegin() const noexcept
The same as crbegin().
Definition range.hpp:321
const_reverse_iterator crbegin() const noexcept
Beginning of the integer range in reverse order.
Definition range.hpp:318
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:94
range operator+(long shift) const
Shift the whole range by a given amount.
Definition range.hpp:138
friend std::ostream & operator<<(std::ostream &os, const range &rg)
Write the range details to std::ostream.
Definition range.hpp:147
bool operator==(range const &) const =default
Default equal-to operator.
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:105
long first() const
Get first value of the range.
Definition range.hpp:119
long last() const
Get last value of the range (excluded).
Definition range.hpp:122
const_iterator end() const noexcept
The same as cend().
Definition range.hpp:330
long step() const
Get step size between two elements of the range.
Definition range.hpp:125
std::reverse_iterator< range::const_iterator > const_reverse_iterator
Reverse const iterator type for itertools::range.
Definition range.hpp:303
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:113
long size() const
Get number of elements in the range.
Definition range.hpp:128
const_reverse_iterator crend() const noexcept
End of the range in reverse order.
Definition range.hpp:336
const_iterator begin() const noexcept
The same as cbegin().
Definition range.hpp:312
const_reverse_iterator rend() const noexcept
The same as crend().
Definition range.hpp:339
auto product_range(Is... is)
Create a cartesian product range of integer ranges from given integers.
Definition range.hpp:365
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:153
const_iterator & operator++() noexcept
Pre-increment operator increments the current value by the step size.
Definition range.hpp:179
const_iterator & operator--() noexcept
Pre-decrement operator decrements the current value by the step size.
Definition range.hpp:198
std::random_access_iterator_tag iterator_category
Iterator category.
Definition range.hpp:164
const_iterator operator++(int) noexcept
Post-increment operator increments the current value by the step size.
Definition range.hpp:188
value_type * pointer
Pointer type.
Definition range.hpp:167
std::ptrdiff_t difference_type
Difference type.
Definition range.hpp:170
value_type operator[](difference_type n) const noexcept
Subscript operator.
Definition range.hpp:298
friend const_iterator operator+(difference_type n, const_iterator it) noexcept
Addition operator for an integer and an iterator.
Definition range.hpp:267
bool operator==(const_iterator const &other) const noexcept
Equal-to operator for two iterators.
Definition range.hpp:230
long operator*() const noexcept
Dereference operator.
Definition range.hpp:236
difference_type operator-(const_iterator const &rhs) const noexcept
Get the distance between two iterators.
Definition range.hpp:291
std::strong_ordering operator<=>(const_iterator const &rhs) const noexcept
Three-way comparison operator for two iterators.
Definition range.hpp:220
const_iterator & operator-=(difference_type n) noexcept
Subtraction assignment operator.
Definition range.hpp:274
const_iterator & operator+=(difference_type n) noexcept
Addition assignment operator.
Definition range.hpp:249
const_iterator operator+(difference_type n) const noexcept
Addition operator for an iterator and an integer.
Definition range.hpp:259
long operator->() const noexcept
Member access operator.
Definition range.hpp:242
value_type const & reference
Reference type.
Definition range.hpp:173
const_iterator operator--(int) noexcept
Post-decrement operator decrements the current value by the step size.
Definition range.hpp:207
const_iterator operator-(difference_type n) const noexcept
Subtraction operator for an iterator and an integer.
Definition range.hpp:284