TRIQS/itertools 1.3.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
83 class range {
84 // First value of the range.
85 long first_ = 0;
86
87 // Last value of the range (excluded).
88 long last_ = -1;
89
90 // Number of integers between two elements of the range.
91 long step_ = 1;
92
93 public:
99 struct all_t {};
100
102 static inline constexpr all_t all = {};
103
105 using index_t = long;
106
111 [[deprecated("range default construction deprecated. Use range::all for full range in slicing operation")]] range() = default;
112
119 range(std::integral auto first, std::integral auto last) noexcept : first_(first), last_(last) {}
120
130 range(std::integral auto first, std::integral auto last, std::integral auto step) : first_(first), last_(last), step_(step) {
131 if (step_ == 0) throw std::runtime_error("Step-size cannot be zero in construction of integer range");
132 }
133
138 explicit range(std::integral auto last) : range(0, last, 1) {}
139
141 [[nodiscard]] bool operator==(range const &) const = default;
142
144 [[nodiscard]] long first() const { return first_; }
145
147 [[nodiscard]] long last() const { return last_; }
148
150 [[nodiscard]] long step() const { return step_; }
151
153 [[nodiscard]] long size() const { return std::max(0l, (last_ + step_ - (step_ > 0 ? 1 : -1) - first_) / step_); }
154
163 [[nodiscard]] range operator+(long shift) const { return {first_ + shift, last_ + shift, step_}; }
164
172 friend inline std::ostream &operator<<(std::ostream &os, const range &rg) {
173 os << "range(" << rg.first() << "," << rg.last() << "," << rg.step() << ")";
174 return os;
175 }
176
180 long pos;
181
183 long step;
184
186 using value_type = long;
187
189 using iterator_category = std::random_access_iterator_tag;
190
193
195 using difference_type = std::ptrdiff_t;
196
198 using reference = value_type const &;
199
205 pos += step;
206 return *this;
207 }
208
214 const_iterator tmp = *this;
215 pos += step;
216 return tmp;
217 }
218
224 pos -= step;
225 return *this;
226 }
227
233 const_iterator tmp = *this;
234 pos -= step;
235 return tmp;
236 }
237
245 [[nodiscard]] std::strong_ordering operator<=>(const_iterator const &rhs) const noexcept {
246 return (step > 0 ? pos <=> rhs.pos : -pos <=> -rhs.pos);
247 }
248
255 [[nodiscard]] bool operator==(const_iterator const &other) const noexcept { return pos == other.pos; }
256
261 [[nodiscard]] long operator*() const noexcept { return pos; }
262
267 [[nodiscard]] long operator->() const noexcept { return operator*(); }
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
292 [[nodiscard]] friend const_iterator operator+(difference_type n, const_iterator it) noexcept { return it + n; }
293
300 pos -= n * step;
301 return *this;
302 }
303
309 [[nodiscard]] const_iterator operator-(difference_type n) const noexcept { return {.pos = pos - n * step, .step = step}; }
310
316 [[nodiscard]] difference_type operator-(const_iterator const &rhs) const noexcept { return (pos - rhs.pos) / step; }
317
323 [[nodiscard]] value_type operator[](difference_type n) const noexcept { return pos + n * step; }
324
325 }; // end struct const_iterator
326
328 using const_reverse_iterator = std::reverse_iterator<range::const_iterator>;
329
334 [[nodiscard]] const_iterator cbegin() const noexcept { return {.pos = first_, .step = step_}; }
335
337 [[nodiscard]] const_iterator begin() const noexcept { return {.pos = first_, .step = step_}; }
338
343 [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{end()}; }
344
346 [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
347
352 [[nodiscard]] const_iterator cend() const noexcept { return {.pos = first_ + step_ * size(), .step = step_}; }
353
355 [[nodiscard]] const_iterator end() const noexcept { return {.pos = first_ + step_ * size(), .step = step_}; }
356
361 [[nodiscard]] const_reverse_iterator crend() const noexcept { return const_reverse_iterator{begin()}; }
362
364 [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
365 };
366
394 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>> [[nodiscard]] auto product_range(Is... is) {
395 return product(range(is)...);
396 }
397
398 namespace detail {
399
400 // Helper function to create a product range of integer ranges from a tuple or an array.
401 template <typename T, size_t... Is> [[gnu::always_inline]] auto product_range_impl(T const &idxs, std::index_sequence<Is...>) {
402 return product_range(std::get<Is>(idxs)...);
403 }
404
405 } // namespace detail
406
434 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>>
435 [[nodiscard]] auto product_range(std::tuple<Is...> const &idx_tpl) {
436 return detail::product_range_impl(idx_tpl, std::make_index_sequence<sizeof...(Is)>{});
437 }
438
467 template <typename I, size_t N, typename EnableIf = std::enable_if_t<std::is_integral_v<I>, int>>
468 [[nodiscard]] auto product_range(std::array<I, N> const &idx_arr) {
469 return detail::product_range_impl(idx_arr, std::make_index_sequence<N>{});
470 }
471
492 template <typename F> void foreach (range const &rg, F && f) {
493 auto i = rg.first(), last = rg.last(), step = rg.step();
494 for (; i < last; i += step) std::forward<F>(f)(i);
495 }
496
498
499} // namespace itertools
500
501#endif // _ITERTOOLS_RANGE_HPP
A lazy range of integers that mimics a Python range.
Definition range.hpp:83
static constexpr all_t all
See range::all_t.
Definition range.hpp:102
long index_t
Integer type for backward compatibility.
Definition range.hpp:105
const_iterator cbegin() const noexcept
Beginning of the integer range.
Definition range.hpp:334
const_iterator cend() const noexcept
End of the range.
Definition range.hpp:352
const_reverse_iterator rbegin() const noexcept
The same as crbegin().
Definition range.hpp:346
const_reverse_iterator crbegin() const noexcept
Beginning of the integer range in reverse order.
Definition range.hpp:343
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:119
range operator+(long shift) const
Shift the whole range by a given amount.
Definition range.hpp:163
friend std::ostream & operator<<(std::ostream &os, const range &rg)
Write the range details to std::ostream.
Definition range.hpp:172
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:130
long first() const
Get first value of the range.
Definition range.hpp:144
long last() const
Get last value of the range (excluded).
Definition range.hpp:147
const_iterator end() const noexcept
The same as cend().
Definition range.hpp:355
long step() const
Get step size between two elements of the range.
Definition range.hpp:150
std::reverse_iterator< range::const_iterator > const_reverse_iterator
Reverse const iterator type for itertools::range.
Definition range.hpp:328
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:138
long size() const
Get number of elements in the range.
Definition range.hpp:153
const_reverse_iterator crend() const noexcept
End of the range in reverse order.
Definition range.hpp:361
const_iterator begin() const noexcept
The same as cbegin().
Definition range.hpp:337
const_reverse_iterator rend() const noexcept
The same as crend().
Definition range.hpp:364
auto product_range(Is... is)
Create a cartesian product range of integer ranges from given integers.
Definition range.hpp:394
itertools::multiplied< Rs... > product(Rs &&...rgs)
Lazy-multiply a given number of ranges by forming their cartesian product.
Definition product.hpp:240
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:99
Const iterator type for itertools::range.
Definition range.hpp:178
const_iterator & operator++() noexcept
Pre-increment operator increments the current value by the step size.
Definition range.hpp:204
const_iterator & operator--() noexcept
Pre-decrement operator decrements the current value by the step size.
Definition range.hpp:223
std::random_access_iterator_tag iterator_category
Iterator category.
Definition range.hpp:189
const_iterator operator++(int) noexcept
Post-increment operator increments the current value by the step size.
Definition range.hpp:213
value_type * pointer
Pointer type.
Definition range.hpp:192
std::ptrdiff_t difference_type
Difference type.
Definition range.hpp:195
value_type operator[](difference_type n) const noexcept
Subscript operator.
Definition range.hpp:323
friend const_iterator operator+(difference_type n, const_iterator it) noexcept
Addition operator for an integer and an iterator.
Definition range.hpp:292
bool operator==(const_iterator const &other) const noexcept
Equal-to operator for two iterators.
Definition range.hpp:255
long operator*() const noexcept
Dereference operator.
Definition range.hpp:261
difference_type operator-(const_iterator const &rhs) const noexcept
Get the distance between two iterators.
Definition range.hpp:316
std::strong_ordering operator<=>(const_iterator const &rhs) const noexcept
Three-way comparison operator for two iterators.
Definition range.hpp:245
const_iterator & operator-=(difference_type n) noexcept
Subtraction assignment operator.
Definition range.hpp:299
const_iterator & operator+=(difference_type n) noexcept
Addition assignment operator.
Definition range.hpp:274
const_iterator operator+(difference_type n) const noexcept
Addition operator for an iterator and an integer.
Definition range.hpp:284
long operator->() const noexcept
Member access operator.
Definition range.hpp:267
value_type const & reference
Reference type.
Definition range.hpp:198
const_iterator operator--(int) noexcept
Post-decrement operator decrements the current value by the step size.
Definition range.hpp:232
const_iterator operator-(difference_type n) const noexcept
Subtraction operator for an iterator and an integer.
Definition range.hpp:309