TRIQS/itertools 1.3.0
C++ range library
Loading...
Searching...
No Matches
product.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_PRODUCT_HPP
23#define _ITERTOOLS_PRODUCT_HPP
24
25#include "./iterator_facade.hpp"
26#include "./sentinel.hpp"
27
28#include <cstddef>
29#include <iterator>
30#include <tuple>
31#include <utility>
32
33namespace itertools {
34
55 template <typename EndIters, typename... Iters>
56 struct prod_iter : iterator_facade<prod_iter<EndIters, Iters...>, std::tuple<typename std::iterator_traits<Iters>::value_type...>> {
58 std::tuple<Iters...> its_begin;
59
61 EndIters its_end;
62
64 std::tuple<Iters...> its = its_begin;
65
67 static constexpr long Rank = sizeof...(Iters);
68
70 prod_iter() = default;
71
78 prod_iter(std::tuple<Iters...> its_begin, EndIters its_end) : its_begin(std::move(its_begin)), its_end(std::move(its_end)) {}
79
80 private:
81 // Helper function to recursively increment the current iterators.
82 template <int N> void _increment() {
83 // increment Nth iterator
84 ++std::get<N>(its);
85 // recursively increment previous iterators if necessary
86 if constexpr (N > 0) {
87 // if Nth iterator is at its end, reset it to its begin iterator and increment N-1st iterator
88 if (std::get<N>(its) == std::get<N>(its_end)) {
89 std::get<N>(its) = std::get<N>(its_begin);
90 _increment<N - 1>();
91 }
92 }
93 }
94
95 public:
97 void increment() { _increment<Rank - 1>(); }
98
105 [[nodiscard]] bool operator==(prod_iter const &other) const { return its == other.its; }
106
116 template <typename SentinelIter> [[nodiscard]] bool operator==(sentinel_t<SentinelIter> const &s) const { return (s.it == std::get<0>(its)); }
117
118 private:
119 // Helper function to dereference all original iterators.
120 template <size_t... Is> [[gnu::always_inline]] [[nodiscard]] auto tuple_map_impl(std::index_sequence<Is...>) const {
121 return std::tuple<decltype(*std::get<Is>(its))...>(*std::get<Is>(its)...);
122 }
123
124 public:
129 [[nodiscard]] decltype(auto) dereference() const { return tuple_map_impl(std::index_sequence_for<Iters...>{}); }
130 };
131
140 template <typename... Rs> struct multiplied {
142 std::tuple<Rs...> tu;
143
145 using iterator = prod_iter<std::tuple<decltype(std::end(std::declval<Rs &>()))...>, decltype(std::begin(std::declval<Rs &>()))...>;
146
148 using const_iterator = prod_iter<std::tuple<decltype(std::cend(std::declval<Rs &>()))...>, decltype(std::cbegin(std::declval<Rs &>()))...>;
149
156 template <typename... Us> multiplied(Us &&...rgs) : tu{std::forward<Us>(rgs)...} {}
157
159 [[nodiscard]] bool operator==(multiplied const &) const = default;
160
161 private:
162 // Helper function to create a itertools::prod_iter representing the beginning of the product range.
163 template <size_t... Is> [[gnu::always_inline]] auto _begin(std::index_sequence<Is...>) {
164 return iterator{std::make_tuple(std::begin(std::get<Is>(tu))...), std::make_tuple(std::end(std::get<Is>(tu))...)};
165 }
166
167 // Const version of _begin(std::index_sequence<Is...>).
168 template <size_t... Is> [[gnu::always_inline]] auto _cbegin(std::index_sequence<Is...>) const {
169 return const_iterator{std::make_tuple(std::cbegin(std::get<Is>(tu))...), std::make_tuple(std::cend(std::get<Is>(tu))...)};
170 }
171
172 public:
177 [[nodiscard]] iterator begin() noexcept { return _begin(std::index_sequence_for<Rs...>{}); }
178
180 [[nodiscard]] const_iterator cbegin() const noexcept { return _cbegin(std::index_sequence_for<Rs...>{}); }
181
183 [[nodiscard]] const_iterator begin() const noexcept { return cbegin(); }
184
189 [[nodiscard]] auto end() noexcept { return make_sentinel(std::end(std::get<0>(tu))); }
190
192 [[nodiscard]] auto cend() const noexcept { return make_sentinel(std::cend(std::get<0>(tu))); }
193
195 [[nodiscard]] auto end() const noexcept { return cend(); }
196 };
197
198 // Class template argument deduction guide.
199 template <typename... Rs> multiplied(Rs &&...) -> multiplied<std::decay_t<Rs>...>;
200
240 template <typename... Rs> [[nodiscard]] itertools::multiplied<Rs...> product(Rs &&...rgs) { return {std::forward<Rs>(rgs)...}; }
241
242 namespace detail {
243
244 // Helper function to create a product range from a container of ranges.
245 template <typename C, size_t... Is> [[gnu::always_inline]] [[nodiscard]] auto make_product_impl(C &cont, std::index_sequence<Is...>) {
246 return product(cont[Is]...);
247 }
248
249 } // namespace detail
250
259 template <typename R, size_t N> [[nodiscard]] auto make_product(std::array<R, N> &arr) {
260 return detail::make_product_impl(arr, std::make_index_sequence<N>{});
261 }
262
264 template <typename R, size_t N> [[nodiscard]] auto make_product(std::array<R, N> const &arr) {
265 return detail::make_product_impl(arr, std::make_index_sequence<N>{});
266 }
267
270} // namespace itertools
271
272#endif // _ITERTOOLS_PRODUCT_HPP
auto make_product(std::array< R, N > &arr)
Create a cartesian product range from an array of ranges.
Definition product.hpp:259
itertools::multiplied< Rs... > product(Rs &&...rgs)
Lazy-multiply a given number of ranges by forming their cartesian product.
Definition product.hpp:240
sentinel_t< Iter > make_sentinel(Iter it)
Create an itertools::sentinel_t from an iterator using template type deduction.
Definition sentinel.hpp:50
Provides a CRTP base class for various iterator types in itertools.
Provides a generic sentinel type for various iterator types in itertools.
Represents a cartesian product of ranges.
Definition product.hpp:140
std::tuple< Rs... > tu
Tuple containing the original ranges.
Definition product.hpp:142
multiplied(Us &&...rgs)
Constructs a cartesian product (multiplied) range from the given ranges.
Definition product.hpp:156
const_iterator cbegin() const noexcept
Const version of begin().
Definition product.hpp:180
auto end() noexcept
End of the product range.
Definition product.hpp:189
bool operator==(multiplied const &) const =default
Default equal-to operator.
auto cend() const noexcept
Const version of end().
Definition product.hpp:192
iterator begin() noexcept
Beginning of the product range.
Definition product.hpp:177
auto end() const noexcept
Const overload of end().
Definition product.hpp:195
prod_iter< std::tuple< decltype(std::cend(std::declval< Rs & >()))... >, decltype(std::cbegin(std::declval< Rs & >()))... > const_iterator
Const iterator type the product range.
Definition product.hpp:148
const_iterator begin() const noexcept
Const overload of begin().
Definition product.hpp:183
Iterator for a itertools::multiplied (cartesian product) range.
Definition product.hpp:56
std::tuple< Iters... > its
Tuple containing the current iterators of the original ranges.
Definition product.hpp:64
bool operator==(sentinel_t< SentinelIter > const &s) const
Equal-to operator for a itertools::prod_iter and an itertools::sentinel_t.
Definition product.hpp:116
static constexpr long Rank
Number of original ranges.
Definition product.hpp:67
std::tuple< Iters... > its_begin
Tuple containing the begin iterators of the original ranges.
Definition product.hpp:58
EndIters its_end
Tuple containing the end iterators of the original ranges.
Definition product.hpp:61
prod_iter(std::tuple< Iters... > its_begin, EndIters its_end)
Construct a product iterator from given begin iterators and end iterators.
Definition product.hpp:78
prod_iter()=default
Default constructor.
void increment()
Increment the iterator by incrementing the current iterators starting with the iterator of the last r...
Definition product.hpp:97
bool operator==(prod_iter const &other) const
Equal-to operator for two itertools::prod_iter objects.
Definition product.hpp:105
decltype(auto) dereference() const
Dereference the iterator.
Definition product.hpp:129
Generic sentinel type that can be used to mark the end of a range.
Definition sentinel.hpp:38
Iter it
End iterator of some range.
Definition sentinel.hpp:40