File indexing completed on 2026-05-27 07:24:05
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/containers.hpp"
0013 #include "detray/definitions/detail/qualifiers.hpp"
0014 #include "detray/utils/ranges/ranges.hpp"
0015 #include "detray/utils/type_traits.hpp"
0016
0017
0018 #include <type_traits>
0019
0020 namespace detray::ranges {
0021
0022 namespace detail {
0023
0024 template <detray::ranges::range T>
0025 requires std::input_iterator<detray::detail::get_value_t<T>>
0026 struct static_join_iterator;
0027
0028 }
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 template <std::size_t I, std::input_iterator range_itr_t>
0045 struct static_join_view
0046 : public detray::ranges::view_interface<static_join_view<I, range_itr_t>> {
0047 using iterator_coll_t = darray<range_itr_t, I>;
0048 using iterator_t =
0049 detray::ranges::detail::static_join_iterator<iterator_coll_t>;
0050 using value_t = std::iter_value_t<iterator_t>;
0051
0052
0053 constexpr static_join_view() = default;
0054
0055
0056 template <detray::ranges::range... ranges_t>
0057 requires((sizeof...(ranges_t) > 1) ||
0058 ((!std::same_as<static_join_view, ranges_t>) && ...))
0059 DETRAY_HOST_DEVICE constexpr explicit static_join_view(ranges_t &&...ranges)
0060 : m_begins{detray::ranges::begin(std::forward<ranges_t>(ranges))...},
0061 m_ends{detray::ranges::end(std::forward<ranges_t>(ranges))...} {}
0062
0063
0064 template <detray::ranges::range... ranges_t>
0065 DETRAY_HOST_DEVICE constexpr explicit static_join_view(
0066 const ranges_t &...ranges)
0067 : m_begins{detray::ranges::cbegin(ranges)...},
0068 m_ends{detray::ranges::cend(ranges)...} {}
0069
0070
0071 DETRAY_HOST_DEVICE
0072 constexpr auto begin() const -> iterator_t { return {m_begins, m_ends}; }
0073
0074
0075 DETRAY_HOST_DEVICE
0076 constexpr auto end() const -> iterator_t {
0077
0078 return {m_begins, m_ends, detray::detail::get<I - 1>(m_ends), I - 1};
0079 }
0080
0081
0082
0083 DETRAY_HOST_DEVICE
0084 constexpr auto data() const -> const value_t * {
0085 return &(*(detray::detail::get<0>(m_begins())));
0086 }
0087
0088
0089
0090 DETRAY_HOST_DEVICE
0091 constexpr auto data() -> value_t * {
0092 return &(*(detray::detail::get<0>(m_begins())));
0093 }
0094
0095
0096 DETRAY_HOST_DEVICE
0097 constexpr auto size() const noexcept -> std::size_t {
0098 std::size_t size{0};
0099 for (std::size_t i{0}; i < I; ++i) {
0100 const range_itr_t &begin = m_begins[i];
0101 const range_itr_t &end = m_ends[i];
0102 size += static_cast<std::size_t>(detray::ranges::distance(begin, end));
0103 }
0104 return size;
0105 }
0106
0107
0108 iterator_coll_t m_begins{};
0109 iterator_coll_t m_ends{};
0110 };
0111
0112 namespace views {
0113
0114
0115 template <std::size_t I, std::input_iterator range_itr_t>
0116 struct static_join : public ranges::static_join_view<I, range_itr_t> {
0117 using base_type = ranges::static_join_view<I, range_itr_t>;
0118
0119 constexpr static_join() = default;
0120
0121 template <detray::ranges::range... ranges_t>
0122 requires((sizeof...(ranges_t) > 1) ||
0123 ((!std::same_as<static_join, ranges_t>) && ...))
0124 DETRAY_HOST_DEVICE constexpr explicit static_join(ranges_t &&...ranges)
0125 : base_type(std::forward<ranges_t>(ranges)...) {}
0126 };
0127
0128
0129 template <detray::ranges::range... ranges_t>
0130 DETRAY_HOST_DEVICE static_join(ranges_t &&...ranges)
0131 -> static_join<sizeof...(ranges_t),
0132 typename detray::ranges::iterator_t<detray::detail::first_t<
0133 std::remove_reference_t<ranges_t>...>>>;
0134
0135 }
0136
0137 namespace detail {
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 template <detray::ranges::range iterator_coll_t>
0150 requires std::input_iterator<detray::detail::get_value_t<iterator_coll_t>>
0151 struct static_join_iterator {
0152 using iterator_t = detray::detail::get_value_t<iterator_coll_t>;
0153
0154 using difference_type = std::iter_difference_t<iterator_t>;
0155 using value_type = std::iter_value_t<iterator_t>;
0156 using pointer = typename std::iterator_traits<iterator_t>::pointer;
0157 using reference = std::iter_reference_t<iterator_t>;
0158 using iterator_category =
0159 typename std::iterator_traits<iterator_t>::iterator_category;
0160
0161
0162 constexpr static_join_iterator() = default;
0163
0164
0165 DETRAY_HOST_DEVICE
0166 constexpr static_join_iterator(const iterator_coll_t &begins,
0167 const iterator_coll_t &ends)
0168 : m_begins(&begins), m_ends(&ends), m_iter{(*m_begins)[0]} {}
0169
0170
0171 DETRAY_HOST_DEVICE
0172 constexpr static_join_iterator(const iterator_coll_t &begins,
0173 const iterator_coll_t &ends,
0174 iterator_t current, const std::size_t i)
0175 : m_begins(&begins), m_ends(&ends), m_iter{current}, m_idx{i} {}
0176
0177
0178
0179 DETRAY_HOST_DEVICE constexpr auto operator++() -> static_join_iterator & {
0180 ++m_iter;
0181
0182 if (constexpr std::size_t max_idx{
0183 sizeof(iterator_coll_t) / sizeof(iterator_t) - 1u};
0184 (m_iter == (*m_ends)[m_idx]) && (m_idx < max_idx)) {
0185 ++m_idx;
0186 m_iter = (*m_begins)[m_idx];
0187 }
0188 return *this;
0189 }
0190
0191 DETRAY_HOST_DEVICE constexpr auto operator++(int) -> static_join_iterator {
0192 auto tmp(*this);
0193 ++(*this);
0194 return tmp;
0195 }
0196
0197
0198
0199
0200 DETRAY_HOST_DEVICE constexpr auto operator--() -> static_join_iterator &
0201 requires std::bidirectional_iterator<iterator_t>
0202 {
0203 if (m_iter != (*m_begins)[m_idx]) {
0204
0205 --m_iter;
0206 } else if (m_idx > 0u) {
0207
0208
0209 --m_idx;
0210 m_iter = detray::ranges::prev((*m_ends)[m_idx]);
0211 }
0212 return *this;
0213 }
0214
0215
0216 DETRAY_HOST_DEVICE constexpr auto operator--(int) -> static_join_iterator
0217 requires std::bidirectional_iterator<iterator_t>
0218 {
0219 auto tmp(*this);
0220 ++(*this);
0221 return tmp;
0222 }
0223
0224
0225 DETRAY_HOST_DEVICE
0226 constexpr auto operator*() const -> decltype(auto) { return *m_iter; }
0227
0228
0229 DETRAY_HOST_DEVICE constexpr auto operator+=(const difference_type j)
0230 -> static_join_iterator &
0231 requires std::random_access_iterator<iterator_t>
0232 {
0233
0234 if (difference_type i{j}; i >= difference_type{0}) {
0235 while (i--) {
0236 ++(*this);
0237 }
0238 } else {
0239 while (i++) {
0240 --(*this);
0241 }
0242 }
0243 return *this;
0244 }
0245
0246
0247 DETRAY_HOST_DEVICE constexpr auto operator-=(const difference_type j)
0248 -> static_join_iterator &
0249 requires std::random_access_iterator<iterator_t>
0250 {
0251 m_iter += (-j);
0252 return *this;
0253 }
0254
0255
0256 DETRAY_HOST_DEVICE constexpr decltype(auto) operator[](
0257 const difference_type i) const
0258 requires std::random_access_iterator<iterator_t>
0259 {
0260 difference_type offset{i - (m_iter - (*m_begins)[0])};
0261 return *(*this + offset);
0262 }
0263
0264 private:
0265
0266 DETRAY_HOST_DEVICE friend constexpr bool operator==(
0267 const static_join_iterator &lhs, const static_join_iterator &rhs) {
0268 return (lhs.m_iter == rhs.m_iter);
0269 }
0270
0271
0272 DETRAY_HOST_DEVICE friend constexpr auto operator<=>(
0273 const static_join_iterator &lhs, const static_join_iterator &rhs)
0274 requires std::random_access_iterator<iterator_t>
0275 {
0276 #if defined(__apple_build_version__)
0277 const auto l{lhs.m_iter};
0278 const auto r{rhs.m_iter};
0279 if (l < r || (l == r && l < r)) {
0280 return std::strong_ordering::less;
0281 }
0282 if (l > r || (l == r && l > r)) {
0283 return std::strong_ordering::greater;
0284 }
0285 return std::strong_ordering::equivalent;
0286 #else
0287 return (lhs.m_iter <=> rhs.m_iter);
0288 #endif
0289 }
0290
0291
0292 DETRAY_HOST_DEVICE friend constexpr auto operator+(
0293 const static_join_iterator &itr, const difference_type j)
0294 -> static_join_iterator
0295 requires std::random_access_iterator<iterator_t>
0296 {
0297 static_join_iterator<iterator_coll_t> tmp(itr);
0298
0299 if (difference_type i{j}; i >= 0) {
0300 while (i--) {
0301 ++tmp;
0302 }
0303 } else {
0304 while (i++) {
0305 --tmp;
0306 }
0307 }
0308 return tmp;
0309 }
0310
0311
0312 DETRAY_HOST_DEVICE friend constexpr auto operator+(
0313 const difference_type j, const static_join_iterator &itr)
0314 -> static_join_iterator
0315 requires std::random_access_iterator<iterator_t>
0316 {
0317 return itr + j;
0318 }
0319
0320
0321 DETRAY_HOST_DEVICE friend constexpr auto operator-(
0322 const static_join_iterator &itr, const difference_type j)
0323 -> static_join_iterator
0324 requires std::random_access_iterator<iterator_t>
0325 {
0326 return itr + (-j);
0327 }
0328
0329
0330 DETRAY_HOST_DEVICE friend constexpr auto operator-(
0331 const static_join_iterator &lhs, const static_join_iterator &rhs)
0332 -> difference_type
0333 requires std::random_access_iterator<iterator_t>
0334 {
0335 const static_join_iterator l{lhs};
0336 const static_join_iterator r{rhs};
0337
0338 if (l.m_idx == r.m_idx) {
0339 return l.m_iter - r.m_iter;
0340 }
0341 if (l.m_idx < r.m_idx) {
0342
0343 difference_type diff{l.m_iter - (*l.m_ends)[l.m_idx]};
0344 for (std::size_t i{l.m_idx + 1u}; i < r.m_idx; ++i) {
0345 diff += (*l.m_begins)[i] - (*l.m_ends)[i];
0346 }
0347 diff += (*r.m_begins)[l.m_idx] - r.m_iter;
0348 return diff;
0349 } else {
0350
0351 difference_type diff{l.m_iter - (*l.m_begins)[l.m_idx]};
0352 for (std::size_t i{l.m_idx - 1u}; i > r.m_idx; --i) {
0353 diff += (*l.m_ends)[i] - (*l.m_begins)[i];
0354 }
0355 diff += (*r.m_ends)[r.m_idx] - r.m_iter;
0356 return diff;
0357 }
0358 }
0359
0360
0361 const iterator_coll_t *m_begins{nullptr};
0362 const iterator_coll_t *m_ends{nullptr};
0363
0364 iterator_t m_iter{};
0365
0366 std::size_t m_idx{0};
0367 };
0368
0369 }
0370
0371 }