ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
cartesian_product.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
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
9#pragma once
10
11// Project include(s)
12#include "detray/definitions/detail/qualifiers.hpp"
13#include "detray/utils/ranges/ranges.hpp"
14#include "detray/utils/tuple.hpp"
15
16// System include(s)
17#include <tuple> // < needed for structured binding of iterator values
18
19namespace detray::ranges {
20
21namespace detail {
22
23template <std::input_iterator... T>
25
26}
27
34template <detray::ranges::range... range_ts>
36 cartesian_product_view<range_ts...>> {
41 detray::ranges::iterator_t<range_ts>...>;
43 using value_type =
45
47 constexpr cartesian_product_view() = default;
48
52 template <detray::ranges::range... deduced_range_ts>
53 requires((sizeof...(deduced_range_ts) > 1) ||
54 ((!std::same_as<cartesian_product_view, deduced_range_ts>) && ...))
55 DETRAY_HOST_DEVICE constexpr explicit cartesian_product_view(
56 deduced_range_ts... ranges)
57 : m_begins(detray::ranges::begin(ranges)...),
58 m_ends(detray::ranges::end(ranges)...) {}
59
61 DETRAY_HOST_DEVICE
62 constexpr auto begin() const -> iterator_t { return {m_begins, m_ends}; }
63
65 DETRAY_HOST_DEVICE
66 constexpr auto end() const -> iterator_t { return {m_ends, m_ends}; }
67
70 DETRAY_HOST_DEVICE
71 constexpr auto data() const { return &(*(detray::get<0>(m_begins()))); }
72
75 DETRAY_HOST_DEVICE
76 constexpr auto data() { return &(*(detray::get<0>(m_begins()))); }
77
82 template <int I = static_cast<int>(sizeof...(range_ts)) - 1>
83 DETRAY_HOST_DEVICE constexpr auto size(std::size_t s = 1u) const noexcept
84 -> std::size_t {
85 decltype(auto) begin = detray::get<I>(m_begins);
86 decltype(auto) end = detray::get<I>(m_ends);
87
88 s *= static_cast<std::size_t>(detray::ranges::distance(begin, end));
89
90 if constexpr (I > 0) {
91 return size<I - 1>(s);
92 } else {
93 return s;
94 }
95 }
96
97 private:
99 iterator_coll_t m_begins{};
100 iterator_coll_t m_ends{};
101};
102
103namespace views {
104
106template <detray::ranges::range... range_ts>
107struct cartesian_product : public ranges::cartesian_product_view<range_ts...> {
110
111 constexpr cartesian_product() = default;
112
116 template <detray::ranges::range... deduced_range_ts>
117 requires((sizeof...(deduced_range_ts) > 1) ||
118 ((!std::same_as<cartesian_product, deduced_range_ts>) && ...))
119 DETRAY_HOST_DEVICE constexpr explicit cartesian_product(
120 deduced_range_ts &&...ranges)
121 : base_type(std::forward<deduced_range_ts>(ranges)...) {}
122};
123
124// deduction guides
125template <detray::ranges::range... ranges_ts>
126DETRAY_HOST_DEVICE_DEDUCTION_GUIDE cartesian_product(ranges_ts &&...ranges)
127 -> cartesian_product<ranges_ts...>;
128
129} // namespace views
130
131namespace detail {
132
134template <std::input_iterator... iterator_ts>
137 using difference_type = std::ptrdiff_t;
139 using value_type = std::tuple<std::iter_reference_t<iterator_ts>...>;
144 // TODO: Adapt to the weakest iterator category in pack
146 using iterator_category = detray::ranges::bidirectional_iterator_tag;
147
149 constexpr cartesian_product_iterator() = default;
150
154 DETRAY_HOST_DEVICE
157 : m_begins(begins), m_ends(ends), m_itrs(begins) {}
158
163 DETRAY_HOST_DEVICE constexpr bool operator==(
164 const cartesian_product_iterator &rhs) const {
165 return (detray::get<0>(m_itrs) == detray::get<0>(rhs.m_itrs));
166 }
167
171 DETRAY_HOST_DEVICE constexpr auto operator++()
173 unroll_increment();
174 return *this;
175 }
176
179 DETRAY_HOST_DEVICE constexpr auto operator++(int)
181 auto tmp(*this);
182 ++(*this);
183 return tmp;
184 }
185
186
190 DETRAY_HOST_DEVICE constexpr auto operator--()
192 unroll_decrement();
193 return *this;
194 }
195
198 DETRAY_HOST_DEVICE constexpr auto operator--(int)
200 auto tmp(*this);
201 ++(*this);
202 return tmp;
203 }
204
205
207 DETRAY_HOST_DEVICE
208 constexpr decltype(auto) operator*() const {
209 return unroll_values(
210 std::make_integer_sequence<std::size_t, sizeof...(iterator_ts)>{});
211 }
212
213 private:
218 template <int I = static_cast<int>(sizeof...(iterator_ts)) - 1>
219 DETRAY_HOST_DEVICE constexpr void unroll_increment() {
220 auto &itr = detray::get<I>(m_itrs);
221 ++itr;
222 if constexpr (I > 0) {
223 if (itr == detray::get<I>(m_ends)) {
224 itr = detray::get<I>(m_begins);
225 unroll_increment<I - 1>();
226 }
227 }
228 }
229
234 template <int I = static_cast<int>(sizeof...(iterator_ts)) - 1>
235 DETRAY_HOST_DEVICE constexpr void unroll_decrement() {
236 auto &itr = detray::get<I>(m_itrs);
237
238 if constexpr (I > 0) {
239 if (itr == detray::get<I>(m_begins)) {
240 itr = detray::ranges::prev(detray::get<I>(m_ends));
241 unroll_decrement<I - 1>();
242 }
243 }
244 --itr;
245 }
246
249 template <std::size_t... I>
250 DETRAY_HOST_DEVICE constexpr auto unroll_values(
251 std::index_sequence<I...> /*seq*/) const {
252 return std::tuple<std::iter_reference_t<iterator_ts>...>(
253 *detray::get<I>(m_itrs)...);
254 }
255
257 dtuple<iterator_ts...> m_begins;
258 dtuple<iterator_ts...> m_ends;
260 dtuple<iterator_ts...> m_itrs;
261};
262
263} // namespace detail
264
265} // namespace detray::ranges
Defines a detray 'view'.
Definition ranges.hpp:190
Range concept.
Definition ranges.hpp:97
constexpr double T
Magnetic field, native unit (eV*s)/(e*m²).
Definition Units.hpp:168
Detray include(s).
Definition array_operators.hpp:18
const auto & get(const detray::tuple< Ts... > &t) noexcept
Get a tuple element by index from a const tuple.
Definition tuple.hpp:152
detray::tuple< types... > dtuple
Tuple type used by detray storage and dispatch.
Definition containers.hpp:46
Range adaptor that generates a cartesian product from the given input ranges.
Definition cartesian_product.hpp:36
constexpr cartesian_product_view()=default
Default constructor.
dtuple< detray::ranges::iterator_t< range_ts >... > iterator_coll_t
Tuple of the begin or end iterator for each input range.
Definition cartesian_product.hpp:38
dtuple< std::iter_reference_t< detray::ranges::iterator_t< range_ts > >... > value_type
Tuple of references to the current element of each input range.
Definition cartesian_product.hpp:43
constexpr auto begin() const -> iterator_t
Definition cartesian_product.hpp:62
constexpr auto data()
Definition cartesian_product.hpp:76
constexpr auto end() const -> iterator_t
Definition cartesian_product.hpp:66
detray::ranges::detail::cartesian_product_iterator< detray::ranges::iterator_t< range_ts >... > iterator_t
Iterator that advances through the Cartesian product.
Definition cartesian_product.hpp:40
constexpr auto data() const
Definition cartesian_product.hpp:71
constexpr auto size(std::size_t s=1u) const noexcept -> std::size_t
Definition cartesian_product.hpp:83
Iterator implementation for the cartesian product view.
Definition cartesian_product.hpp:135
constexpr bool operator==(const cartesian_product_iterator &rhs) const
Definition cartesian_product.hpp:163
detray::ranges::bidirectional_iterator_tag iterator_category
Definition cartesian_product.hpp:146
std::tuple< std::iter_reference_t< iterator_ts >... > value_type
Definition cartesian_product.hpp:139
constexpr auto operator++() -> cartesian_product_iterator &
Increment iterators.
Definition cartesian_product.hpp:171
constexpr auto operator--() -> cartesian_product_iterator &
Decrement iterators.
Definition cartesian_product.hpp:190
constexpr auto operator++(int) -> cartesian_product_iterator
Advance to the next product element and return the previous iterator.
Definition cartesian_product.hpp:179
constexpr cartesian_product_iterator()=default
Default constructor required by LegacyIterator trait.
constexpr cartesian_product_iterator(dtuple< iterator_ts... > begins, dtuple< iterator_ts... > ends)
Construct from a collection of begins and ends positions.
Definition cartesian_product.hpp:155
constexpr auto operator--(int) -> cartesian_product_iterator
Move to the previous product element and return the previous iterator.
Definition cartesian_product.hpp:198
ranges::cartesian_product_view< range_ts... > base_type
Base Cartesian-product view.
Definition cartesian_product.hpp:109