ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
static_join.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/containers.hpp"
13#include "detray/definitions/detail/qualifiers.hpp"
14#include "detray/utils/ranges/ranges.hpp"
15#include "detray/utils/type_traits.hpp"
16
17// System include(s)
18#include <type_traits>
19
20namespace detray::ranges {
21
22namespace detail {
23
24template <detray::ranges::range T>
25 requires std::input_iterator<detray::detail::get_value_t<T>>
27
28}
29
44template <std::size_t I, std::input_iterator range_itr_t>
46 : public detray::ranges::view_interface<static_join_view<I, range_itr_t>> {
50 using iterator_t =
53 using value_t = std::iter_value_t<iterator_t>;
54
56 constexpr static_join_view() = default;
57
61 template <detray::ranges::range... ranges_t>
62 requires((sizeof...(ranges_t) > 1) ||
63 ((!std::same_as<static_join_view, ranges_t>) && ...))
64 DETRAY_HOST_DEVICE constexpr explicit static_join_view(ranges_t &&...ranges)
65 : m_begins{detray::ranges::begin(std::forward<ranges_t>(ranges))...},
66 m_ends{detray::ranges::end(std::forward<ranges_t>(ranges))...} {}
67
71 template <detray::ranges::range... ranges_t>
72 DETRAY_HOST_DEVICE constexpr explicit static_join_view(
73 const ranges_t &...ranges)
74 : m_begins{detray::ranges::cbegin(ranges)...},
75 m_ends{detray::ranges::cend(ranges)...} {}
76
78 DETRAY_HOST_DEVICE
79 constexpr auto begin() const -> iterator_t { return {m_begins, m_ends}; }
80
82 DETRAY_HOST_DEVICE
83 constexpr auto end() const -> iterator_t {
84 // Build a joined itr from the last value in the iterator collection
85 return {m_begins, m_ends, detray::detail::get<I - 1>(m_ends), I - 1};
86 }
87
90 DETRAY_HOST_DEVICE
91 constexpr auto data() const -> const value_t * {
92 return &(*(detray::detail::get<0>(m_begins())));
93 }
94
97 DETRAY_HOST_DEVICE
98 constexpr auto data() -> value_t * {
99 return &(*(detray::detail::get<0>(m_begins())));
100 }
101
103 DETRAY_HOST_DEVICE
104 constexpr auto size() const noexcept -> std::size_t {
105 std::size_t size{0};
106 for (std::size_t i{0}; i < I; ++i) {
107 const range_itr_t &begin = m_begins[i];
108 const range_itr_t &end = m_ends[i];
109 size += static_cast<std::size_t>(detray::ranges::distance(begin, end));
110 }
111 return size;
112 }
113
117};
118
119namespace views {
120
122template <std::size_t I, std::input_iterator range_itr_t>
123struct static_join : public ranges::static_join_view<I, range_itr_t> {
126
127 constexpr static_join() = default;
128
132 template <detray::ranges::range... ranges_t>
133 requires((sizeof...(ranges_t) > 1) ||
134 ((!std::same_as<static_join, ranges_t>) && ...))
135 DETRAY_HOST_DEVICE constexpr explicit static_join(ranges_t &&...ranges)
136 : base_type(std::forward<ranges_t>(ranges)...) {}
137};
138
139// deduction guides
140template <detray::ranges::range... ranges_t>
141DETRAY_HOST_DEVICE_DEDUCTION_GUIDE static_join(ranges_t &&...ranges)
142 -> static_join<sizeof...(ranges_t),
143 typename detray::ranges::iterator_t<detray::detail::first_t<
144 std::remove_reference_t<ranges_t>...>>>;
145
146} // namespace views
147
148namespace detail {
149
160template <detray::ranges::range iterator_coll_t>
161 requires std::input_iterator<detray::detail::get_value_t<iterator_coll_t>>
164 using iterator_t = detray::detail::get_value_t<iterator_coll_t>;
165
167 using difference_type = std::iter_difference_t<iterator_t>;
169 using value_type = std::iter_value_t<iterator_t>;
171 using pointer = typename std::iterator_traits<iterator_t>::pointer;
173 using reference = std::iter_reference_t<iterator_t>;
176 typename std::iterator_traits<iterator_t>::iterator_category;
177
179 constexpr static_join_iterator() = default;
180
184 DETRAY_HOST_DEVICE
185 constexpr static_join_iterator(const iterator_coll_t &begins,
186 const iterator_coll_t &ends)
187 : m_begins(&begins), m_ends(&ends), m_iter{(*m_begins)[0]} {}
188
194 DETRAY_HOST_DEVICE
195 constexpr static_join_iterator(const iterator_coll_t &begins,
196 const iterator_coll_t &ends,
197 iterator_t current, const std::size_t i)
198 : m_begins(&begins), m_ends(&ends), m_iter{current}, m_idx{i} {}
199
203 DETRAY_HOST_DEVICE constexpr auto operator++() -> static_join_iterator & {
204 ++m_iter;
205 // Switch to next range in the collection
206 if (constexpr std::size_t max_idx{
207 sizeof(iterator_coll_t) / sizeof(iterator_t) - 1u};
208 (m_iter == (*m_ends)[m_idx]) && (m_idx < max_idx)) {
209 ++m_idx;
210 m_iter = (*m_begins)[m_idx];
211 }
212 return *this;
213 }
214
217 DETRAY_HOST_DEVICE constexpr auto operator++(int) -> static_join_iterator {
218 auto tmp(*this);
219 ++(*this);
220 return tmp;
221 }
222
223
227 DETRAY_HOST_DEVICE constexpr auto operator--() -> static_join_iterator &
228 requires std::bidirectional_iterator<iterator_t>
229 {
230 if (m_iter != (*m_begins)[m_idx]) {
231 // Normal case
232 --m_iter;
233 } else if (m_idx > 0u) {
234 // Iterator has reached last valid position in this range during the
235 // previous decrement. Now go to the end of the previous range
236 --m_idx;
237 m_iter = detray::ranges::prev((*m_ends)[m_idx]);
238 }
239 return *this;
240 }
241
242
245 DETRAY_HOST_DEVICE constexpr auto operator--(int) -> static_join_iterator
246 requires std::bidirectional_iterator<iterator_t>
247 {
248 auto tmp(*this);
249 ++(*this);
250 return tmp;
251 }
252
254 DETRAY_HOST_DEVICE
255 constexpr auto operator*() const -> decltype(auto) { return *m_iter; }
256
260 DETRAY_HOST_DEVICE constexpr auto operator+=(const difference_type j)
262 requires std::random_access_iterator<iterator_t>
263 {
264 // walk through join to catch the switch between intermediate ranges
265 if (difference_type i{j}; i >= difference_type{0}) {
266 while (i--) {
267 ++(*this);
268 }
269 } else {
270 while (i++) {
271 --(*this);
272 }
273 }
274 return *this;
275 }
276
280 DETRAY_HOST_DEVICE constexpr auto operator-=(const difference_type j)
282 requires std::random_access_iterator<iterator_t>
283 {
284 m_iter += (-j);
285 return *this;
286 }
287
291 DETRAY_HOST_DEVICE constexpr decltype(auto) operator[](
292 const difference_type i) const
293 requires std::random_access_iterator<iterator_t>
294 {
295 difference_type offset{i - (m_iter - (*m_begins)[0])};
296 return *(*this + offset);
297 }
298
299 private:
301 DETRAY_HOST_DEVICE friend constexpr bool operator==(
302 const static_join_iterator &lhs, const static_join_iterator &rhs) {
303 return (lhs.m_iter == rhs.m_iter);
304 }
305
307 DETRAY_HOST_DEVICE friend constexpr auto operator<=>(
308 const static_join_iterator &lhs, const static_join_iterator &rhs)
309 requires std::random_access_iterator<iterator_t>
310 {
311#if defined(__apple_build_version__)
312 const auto l{lhs.m_iter};
313 const auto r{rhs.m_iter};
314 if (l < r || (l == r && l < r)) {
315 return std::strong_ordering::less;
316 }
317 if (l > r || (l == r && l > r)) {
318 return std::strong_ordering::greater;
319 }
320 return std::strong_ordering::equivalent;
321#else
322 return (lhs.m_iter <=> rhs.m_iter);
323#endif
324 }
325
327 DETRAY_HOST_DEVICE friend constexpr auto operator+(
328 const static_join_iterator &itr, const difference_type j)
330 requires std::random_access_iterator<iterator_t>
331 {
333 // walk through join to catch the switch between intermediate ranges
334 if (difference_type i{j}; i >= 0) {
335 while (i--) {
336 ++tmp;
337 }
338 } else {
339 while (i++) {
340 --tmp;
341 }
342 }
343 return tmp;
344 }
345
347 DETRAY_HOST_DEVICE friend constexpr auto operator+(
348 const difference_type j, const static_join_iterator &itr)
350 requires std::random_access_iterator<iterator_t>
351 {
352 return itr + j;
353 }
354
356 DETRAY_HOST_DEVICE friend constexpr auto operator-(
357 const static_join_iterator &itr, const difference_type j)
359 requires std::random_access_iterator<iterator_t>
360 {
361 return itr + (-j);
362 }
363
365 DETRAY_HOST_DEVICE friend constexpr auto operator-(
366 const static_join_iterator &lhs, const static_join_iterator &rhs)
368 requires std::random_access_iterator<iterator_t>
369 {
370 const static_join_iterator l{lhs};
371 const static_join_iterator r{rhs};
372
373 if (l.m_idx == r.m_idx) {
374 return l.m_iter - r.m_iter;
375 }
376 if (l.m_idx < r.m_idx) {
377 // Negative distance
378 difference_type diff{l.m_iter - (*l.m_ends)[l.m_idx]};
379 for (std::size_t i{l.m_idx + 1u}; i < r.m_idx; ++i) {
380 diff += (*l.m_begins)[i] - (*l.m_ends)[i];
381 }
382 diff += (*r.m_begins)[l.m_idx] - r.m_iter;
383 return diff;
384 } else {
385 // Positive distance
386 difference_type diff{l.m_iter - (*l.m_begins)[l.m_idx]};
387 for (std::size_t i{l.m_idx - 1u}; i > r.m_idx; --i) {
388 diff += (*l.m_ends)[i] - (*l.m_begins)[i];
389 }
390 diff += (*r.m_ends)[r.m_idx] - r.m_iter;
391 return diff;
392 }
393 }
394
396 const iterator_coll_t *m_begins{nullptr};
397 const iterator_coll_t *m_ends{nullptr};
399 iterator_t m_iter{};
401 std::size_t m_idx{0};
402};
403
404} // namespace detail
405
406} // namespace detray::ranges
Defines a detray 'view'.
Definition ranges.hpp:190
Range concept.
Definition ranges.hpp:97
Detray include(s).
Definition array_operators.hpp:18
std::array< value_t, kDIM > darray
Fixed-size array container.
Definition containers.hpp:30
Sequentially iterate through multiple ranges of the same type.
Definition static_join.hpp:162
constexpr static_join_iterator(const iterator_coll_t &begins, const iterator_coll_t &ends, iterator_t current, const std::size_t i)
Fully parametrized construction.
Definition static_join.hpp:195
constexpr auto operator-=(const difference_type j) -> static_join_iterator &
Retreat the joined iterator by j elements.
Definition static_join.hpp:280
constexpr auto operator+=(const difference_type j) -> static_join_iterator &
Advance the joined iterator by j elements.
Definition static_join.hpp:260
friend constexpr bool operator==(const static_join_iterator &lhs, const static_join_iterator &rhs)
Definition static_join.hpp:301
friend constexpr auto operator<=>(const static_join_iterator &lhs, const static_join_iterator &rhs)
Definition static_join.hpp:307
constexpr auto operator++() -> static_join_iterator &
Increment current iterator and check for switch between ranges.
Definition static_join.hpp:203
constexpr auto operator--(int) -> static_join_iterator
Retreat and return the iterator's previous position.
Definition static_join.hpp:245
typename std::iterator_traits< iterator_t >::pointer pointer
Pointer type associated with the underlying iterator.
Definition static_join.hpp:171
typename std::iterator_traits< iterator_t >::iterator_category iterator_category
Iterator category supported by the underlying iterators.
Definition static_join.hpp:175
constexpr auto operator--() -> static_join_iterator &
Decrement current iterator and check for switch between ranges.
Definition static_join.hpp:227
friend constexpr auto operator+(const difference_type j, const static_join_iterator &itr) -> static_join_iterator
Definition static_join.hpp:347
constexpr auto operator*() const -> decltype(auto)
Definition static_join.hpp:255
friend constexpr auto operator+(const static_join_iterator &itr, const difference_type j) -> static_join_iterator
Definition static_join.hpp:327
detray::detail::get_value_t< iterator_coll_t > iterator_t
Iterator type used within each input range.
Definition static_join.hpp:164
friend constexpr auto operator-(const static_join_iterator &lhs, const static_join_iterator &rhs) -> difference_type
Definition static_join.hpp:365
std::iter_difference_t< iterator_t > difference_type
Distance type of the underlying iterators.
Definition static_join.hpp:167
friend constexpr auto operator-(const static_join_iterator &itr, const difference_type j) -> static_join_iterator
Definition static_join.hpp:356
constexpr static_join_iterator()=default
Default constructor required by LegacyIterator trait.
constexpr auto operator++(int) -> static_join_iterator
Advance and return the iterator's previous position.
Definition static_join.hpp:217
std::iter_reference_t< iterator_t > reference
Reference type associated with the underlying iterator.
Definition static_join.hpp:173
std::iter_value_t< iterator_t > value_type
Element type yielded by dereferencing this iterator.
Definition static_join.hpp:169
constexpr static_join_iterator(const iterator_coll_t &begins, const iterator_coll_t &ends)
Construct from a collection of begins and ends positions.
Definition static_join.hpp:185
Range adaptor that joins different ranges of the same type (static).
Definition static_join.hpp:46
std::iter_value_t< iterator_t > value_t
Element type yielded by the joined view.
Definition static_join.hpp:53
constexpr auto begin() const -> iterator_t
Definition static_join.hpp:79
detray::ranges::detail::static_join_iterator< iterator_coll_t > iterator_t
Iterator that advances across the input ranges in order.
Definition static_join.hpp:50
constexpr auto data() -> value_t *
Definition static_join.hpp:98
constexpr static_join_view()=default
Default constructor.
darray< range_itr_t, I > iterator_coll_t
Begin/end iterator array for the fixed set of input ranges.
Definition static_join.hpp:48
constexpr static_join_view(const ranges_t &...ranges)
Construct from a pack of ranges - const.
Definition static_join.hpp:72
constexpr auto size() const noexcept -> std::size_t
Definition static_join.hpp:104
constexpr auto end() const -> iterator_t
Definition static_join.hpp:83
constexpr auto data() const -> const value_t *
Definition static_join.hpp:91
iterator_coll_t m_begins
Start and end position of the subranges.
Definition static_join.hpp:115
iterator_coll_t m_ends
End iterators of the input ranges.
Definition static_join.hpp:116
ranges::static_join_view< I, range_itr_t > base_type
Base implementation joining the fixed set of ranges.
Definition static_join.hpp:125