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
22#ifndef _ITERTOOLS_RANGE_HPP
23#define _ITERTOOLS_RANGE_HPP
24
25#include "./product.hpp"
26
27#include <algorithm>
28#include <array>
29#include <iostream>
30#include <iterator>
31#include <stdexcept>
32#include <utility>
33
34namespace itertools {
35
80 class range {
81 // First value of the range.
82 long first_ = 0;
83
84 // Last value of the range (excluded).
85 long last_ = -1;
86
87 // Number of integers between two elements of the range.
88 long step_ = 1;
89
90 public:
96 struct all_t {};
97
99 static inline constexpr all_t all = {};
100
102 using index_t = long;
103
108 [[deprecated("range default construction deprecated. Use range::all for full range in slicing operation")]] range() = default;
109
116 range(long first, long last) noexcept : first_(first), last_(last) {}
117
127 range(long first, long last, long step) : first_(first), last_(last), step_(step) {
128 if (step_ == 0) throw std::runtime_error("Step-size cannot be zero in construction of integer range");
129 }
130
135 explicit range(long last) : range(0, last, 1) {}
136
138 [[nodiscard]] bool operator==(range const &) const = default;
139
141 [[nodiscard]] long first() const { return first_; }
142
144 [[nodiscard]] long last() const { return last_; }
145
147 [[nodiscard]] long step() const { return step_; }
148
150 [[nodiscard]] long size() const { return std::max(0l, (last_ + step_ - (step_ > 0 ? 1 : -1) - first_) / step_); }
151
161 [[nodiscard]] range operator+(long shift) const { return {first_ + shift, last_ + shift, step_}; }
162
170 friend inline std::ostream &operator<<(std::ostream &os, const range &rg) {
171 os << "range(" << rg.first() << "," << rg.last() << "," << rg.step() << ")";
172 return os;
173 }
174
178 long pos;
179
181 long last;
182
184 long step;
185
187 using value_type = long;
188
190 using iterator_category = std::forward_iterator_tag;
191
194
196 using difference_type = std::ptrdiff_t;
197
199 using reference = value_type const &;
200
206 pos += step;
207 return *this;
208 }
209
215 const_iterator c = *this;
216 pos += step;
217 return c;
218 }
219
225 [[nodiscard]] bool atEnd() const noexcept { return step > 0 ? pos >= last : pos <= last; }
226
233 [[nodiscard]] bool operator==(const_iterator const &other) const noexcept {
234 return (other.pos == this->pos) || (other.atEnd() && this->atEnd());
235 }
236
243 [[nodiscard]] bool operator!=(const_iterator const &other) const noexcept { return (!operator==(other)); }
244
249 [[nodiscard]] long operator*() const noexcept { return pos; }
250
255 [[nodiscard]] long operator->() const noexcept { return operator*(); }
256 };
257
262 [[nodiscard]] const_iterator cbegin() const noexcept { return {first_, last_, step_}; }
263
265 [[nodiscard]] const_iterator begin() const noexcept { return {first_, last_, step_}; }
266
271 [[nodiscard]] const_iterator cend() const noexcept { return {last_, last_, step_}; }
272
274 [[nodiscard]] const_iterator end() const noexcept { return {last_, last_, step_}; }
275 };
276
304 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>> [[nodiscard]] auto product_range(Is... is) {
305 return product(range(is)...);
306 }
307
308 namespace detail {
309
310 // Helper function to create a product range of integer ranges from a tuple or an array.
311 template <typename T, size_t... Is> [[gnu::always_inline]] auto product_range_impl(T const &idxs, std::index_sequence<Is...>) {
312 return product_range(std::get<Is>(idxs)...);
313 }
314
315 } // namespace detail
316
344 template <typename... Is, typename EnableIf = std::enable_if_t<(std::is_integral_v<Is> and ...), int>>
345 [[nodiscard]] auto product_range(std::tuple<Is...> const &idx_tpl) {
346 return detail::product_range_impl(idx_tpl, std::make_index_sequence<sizeof...(Is)>{});
347 }
348
377 template <typename I, size_t N, typename EnableIf = std::enable_if_t<std::is_integral_v<I>, int>>
378 [[nodiscard]] auto product_range(std::array<I, N> const &idx_arr) {
379 return detail::product_range_impl(idx_arr, std::make_index_sequence<N>{});
380 }
381
402 template <typename F> void foreach (range const &rg, F && f) {
403 auto i = rg.first(), last = rg.last(), step = rg.step();
404 for (; i < last; i += step) std::forward<F>(f)(i);
405 }
406
409} // namespace itertools
410
411#endif // _ITERTOOLS_RANGE_HPP
A lazy range of integers that mimics a Python range.
Definition range.hpp:80
static constexpr all_t all
See range::all_t.
Definition range.hpp:99
long index_t
Integer type for backward compatibility.
Definition range.hpp:102
range(long first, long last, long step)
Construct a range with a given step size and a given first and last (excluded) value.
Definition range.hpp:127
const_iterator cbegin() const noexcept
Beginning of the integer range.
Definition range.hpp:262
const_iterator cend() const noexcept
End of the range.
Definition range.hpp:271
range operator+(long shift) const
Shift the whole range by a given amount.
Definition range.hpp:161
friend std::ostream & operator<<(std::ostream &os, const range &rg)
Write the range details to std::ostream.
Definition range.hpp:170
bool operator==(range const &) const =default
Default equal-to operator.
range()=default
Default constructor.
long first() const
Get first value of the range.
Definition range.hpp:141
range(long first, long last) noexcept
Construct a range with a step size of 1 and a given first and last (excluded) value.
Definition range.hpp:116
long last() const
Get last value of the range (excluded).
Definition range.hpp:144
const_iterator end() const noexcept
The same as cend().
Definition range.hpp:274
range(long 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:135
long step() const
Get step size between two elements of the range.
Definition range.hpp:147
long size() const
Get number of elements in the range.
Definition range.hpp:150
const_iterator begin() const noexcept
The same as cbegin().
Definition range.hpp:265
auto product_range(Is... is)
Create a cartesian product range of integer ranges from given integers.
Definition range.hpp:304
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:96
Const iterator type for itertools::range.
Definition range.hpp:176
const_iterator & operator++() noexcept
Pre-increment operator increments the current value by the step size.
Definition range.hpp:205
std::forward_iterator_tag iterator_category
Iterator category.
Definition range.hpp:190
const_iterator operator++(int) noexcept
Post-increment operator increments the current value by the step size.
Definition range.hpp:214
value_type * pointer
Pointer type.
Definition range.hpp:193
bool atEnd() const noexcept
Has the iterator reached the end of the range?
Definition range.hpp:225
std::ptrdiff_t difference_type
Difference type.
Definition range.hpp:196
bool operator!=(const_iterator const &other) const noexcept
Not-equal-to operator for two iterators.
Definition range.hpp:243
bool operator==(const_iterator const &other) const noexcept
Equal-to operator for two iterators.
Definition range.hpp:233
long operator*() const noexcept
Dereference operator.
Definition range.hpp:249
long last
Last value of the range (excluded).
Definition range.hpp:181
long operator->() const noexcept
Member access operator.
Definition range.hpp:255
value_type const & reference
Reference type.
Definition range.hpp:199