0.2.0
Loading...
Searching...
No Matches
CartesianProduct.hpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
15
16#pragma once
17
18#include <algorithm>
19#include <iostream>
20#include <iterator>
21#include <functional>
22#include <string>
23#include <type_traits>
24#include <utility>
25#include <vector>
26#include <numeric>
27
28namespace NAV
29{
30namespace CartesianProduct
31{
32
33namespace tuple_algos
34{
35
39template<class Tuple, class F, std::size_t... I>
40F for_each_impl(Tuple&& t, F&& f, std::index_sequence<I...> /* seq */)
41{
42 return (void)std::initializer_list<int>{ (std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))), 0)... }, f;
43}
44
49template<class F, class Tuple>
50constexpr decltype(auto) for_each(Tuple&& t, F&& f)
51{
52 return for_each_impl(std::forward<Tuple>(t), std::forward<F>(f),
53 std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
54}
55
60template<class Tuple, class F, std::size_t... Is>
61auto transform_impl(Tuple&& t, F&& f, std::index_sequence<Is...> /* seq */)
62 -> decltype(std::make_tuple(std::forward<F>(f)(std::get<Is>(std::forward<Tuple>(t)))...))
63{
64 return std::make_tuple(std::forward<F>(f)(std::get<Is>(std::forward<Tuple>(t)))...);
65}
66
67// Alternative implementation, which however does not compile with msvc
68//
69// @brief Transform implementation for tuples
70// @param[in] inputs Input tuple
71// @param[in] function Function to call
72// @return The transformed tuple
73// template<typename... Ts, typename Function, size_t... Is>
74// auto transform_impl(std::tuple<Ts...> const& inputs, Function function, std::index_sequence<Is...> /* seq */)
75// {
76// return std::tuple<std::result_of_t<Function(Ts)>...>{ function(std::get<Is>(inputs))... };
77// }
78
83template<typename... Ts, typename Function>
84auto transform(std::tuple<Ts...> const& inputs, Function function)
85{
86 return transform_impl(inputs, function, std::make_index_sequence<sizeof...(Ts)>{});
87}
88
93template<typename Tuple, typename Predicate>
94size_t find_if(Tuple&& tuple, Predicate pred)
95{
96 size_t index = std::tuple_size<std::decay_t<Tuple>>::value;
97 size_t currentIndex = 0;
98 bool found = false;
99 for_each(tuple, [&](auto&& value) {
100 if (!found && pred(value))
101 {
102 ++index = currentIndex;
103 found = true;
104 }
105 ++currentIndex;
106 });
107 return index;
108}
109
114template<typename Tuple, typename Predicate>
115bool any_of(Tuple&& tuple, Predicate pred)
116{
117 return find_if(tuple, pred) != std::tuple_size<std::decay_t<Tuple>>::value;
118}
119} // namespace tuple_algos
120
124template<typename... Ts>
125auto dereference(std::tuple<Ts...> const& tuple)
126{
127 return tuple_algos::transform(tuple, [](auto&& element) -> decltype(auto) { return *element; });
128}
129
131template<size_t I>
133{
138 template<typename... Iterators>
139 static void _(std::tuple<Iterators...>& iterators, std::tuple<Iterators...> const& beginIterators, std::tuple<Iterators...> const& endIterators)
140 {
141 auto& it = std::get<I>(iterators);
142 auto const begin = std::get<I>(beginIterators);
143 auto const end = std::get<I>(endIterators);
144
145 ++it;
146
147 if (it == end)
148 {
149 it = begin;
150 increment_iterator<I - 1>::_(iterators, beginIterators, endIterators);
151 }
152 }
153};
154
156template<>
158{
161 template<typename... Iterators>
162 static void _(std::tuple<Iterators...>& iterators, std::tuple<Iterators...> const& /* beginIterators */, std::tuple<Iterators...> const& /* endIterators */)
163 {
164 auto& it = std::get<0>(iterators);
165
166 ++it;
167 }
168};
169
174template<typename... Iterators>
175void next_combination(std::tuple<Iterators...>& iterators, std::tuple<Iterators...> const& beginIterators, std::tuple<Iterators...> const& endIterators)
176{
177 constexpr auto N = sizeof...(Iterators);
178 increment_iterator<N - 1>::_(iterators, beginIterators, endIterators);
179}
180
184template<typename Function, typename... Ts, size_t... Is>
185void callFunction(Function function, std::tuple<Ts...> const& tuple, std::index_sequence<Is...> /* seq */)
186{
187 function(std::get<Is>(tuple)...);
188}
189
190} // namespace CartesianProduct
191
195template<typename Function, typename... Ranges>
196void cartesian_product(Function function, Ranges const&... ranges)
197{
198 static_assert(sizeof...(Ranges) > 0, "There should be at least one range in cartesian_product.");
199 auto const hasEmptyRange = CartesianProduct::tuple_algos::any_of(std::forward_as_tuple(ranges...), [](auto&& range) { return range.size() == 0; });
200
201 if (!hasEmptyRange)
202 {
203 auto const beginIterators = std::make_tuple(begin(ranges)...);
204 auto const endIterators = std::make_tuple(end(ranges)...);
205
206 for (auto iterators = beginIterators; std::get<0>(iterators) != std::get<0>(endIterators); CartesianProduct::next_combination(iterators, beginIterators, endIterators))
207 {
208 std::apply(function, CartesianProduct::dereference(iterators));
209 }
210 }
211}
212
216template<typename SubList, size_t N, typename Function>
217void cartesian_product(Function function, std::array<SubList, N> list)
218{
219 std::apply([function](auto... xs) { cartesian_product(function, std::forward<decltype(xs)>(xs)...); }, list);
220}
221
226template<typename SubList, size_t N, typename Function>
227void cartesian_product_idx(Function function, std::array<SubList, N> list)
228{
229 std::array<std::vector<size_t>, N> indices;
230 for (size_t i = 0; i < list.size(); i++)
231 {
232 indices.at(i) = std::vector<size_t>(list.at(i).size());
233 std::iota(indices.at(i).begin(), indices.at(i).end(), 0);
234 }
235
236 std::apply([function](auto... xs) { cartesian_product(function, std::forward<decltype(xs)>(xs)...); }, indices);
237}
238
239} // namespace NAV
auto transform_impl(Tuple &&t, F &&f, std::index_sequence< Is... >) -> decltype(std::make_tuple(std::forward< F >(f)(std::get< Is >(std::forward< Tuple >(t)))...))
Transform implementation for tuples.
Definition CartesianProduct.hpp:61
auto transform(std::tuple< Ts... > const &inputs, Function function)
Transform algorithm for tuples.
Definition CartesianProduct.hpp:84
void cartesian_product(Function function, Ranges const &... ranges)
Calls a function on all combinations over ranges.
Definition CartesianProduct.hpp:196
F for_each_impl(Tuple &&t, F &&f, std::index_sequence< I... >)
For-each implementation for tuples.
Definition CartesianProduct.hpp:40
void callFunction(Function function, std::tuple< Ts... > const &tuple, std::index_sequence< Is... >)
Calls the function on the tuple.
Definition CartesianProduct.hpp:185
bool any_of(Tuple &&tuple, Predicate pred)
Any_of algorithm for tuples.
Definition CartesianProduct.hpp:115
void cartesian_product_idx(Function function, std::array< SubList, N > list)
Calls a function on all combinations over ranges defined in an array, e.g. std::array<std::vector>....
Definition CartesianProduct.hpp:227
constexpr decltype(auto) for_each(Tuple &&t, F &&f)
For-each algorithm for tuples.
Definition CartesianProduct.hpp:50
void next_combination(std::tuple< Iterators... > &iterators, std::tuple< Iterators... > const &beginIterators, std::tuple< Iterators... > const &endIterators)
Gets the next combination of the tuples of iterators.
Definition CartesianProduct.hpp:175
auto dereference(std::tuple< Ts... > const &tuple)
Dereference a tuple.
Definition CartesianProduct.hpp:125
size_t find_if(Tuple &&tuple, Predicate pred)
Find_if for tuples.
Definition CartesianProduct.hpp:94
@ I
Ionosphere phase delay.
static void _(std::tuple< Iterators... > &iterators, std::tuple< Iterators... > const &, std::tuple< Iterators... > const &)
Increments an iterator of tuples.
Definition CartesianProduct.hpp:162
Helper struct to increment an iterator.
Definition CartesianProduct.hpp:133
static void _(std::tuple< Iterators... > &iterators, std::tuple< Iterators... > const &beginIterators, std::tuple< Iterators... > const &endIterators)
Increments an iterator of tuples.
Definition CartesianProduct.hpp:139