Distributed Ranges
Loading...
Searching...
No Matches
segments_tools.hpp
1// SPDX-FileCopyrightText: Intel Corporation
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#pragma once
6
7#include <dr/concepts/concepts.hpp>
8#include <dr/detail/enumerate.hpp>
9#include <dr/detail/ranges_shim.hpp>
10#include <dr/detail/remote_subrange.hpp>
11#include <dr/detail/view_detectors.hpp>
12
13namespace dr {
14
15namespace __detail {
16
17// Take all elements up to and including segment `segment_id` at index
18// `local_id`
19template <typename R>
20auto take_segments(R &&segments, std::size_t last_seg, std::size_t local_id) {
21 auto remainder = local_id;
22
23 auto take_partial = [=](auto &&v) {
24 auto &&[i, segment] = v;
25 if (i == last_seg) {
26 auto first = rng::begin(segment);
27 auto last = rng::begin(segment);
28 rng::advance(last, remainder);
29 return dr::remote_subrange(first, last, dr::ranges::rank(segment));
30 } else {
31 return dr::remote_subrange(segment);
32 }
33 };
34
35 return enumerate(segments) | rng::views::take(last_seg + 1) |
36 rng::views::transform(std::move(take_partial));
37}
38
39// Take the first n elements
40template <typename R> auto take_segments(R &&segments, std::size_t n) {
41 std::size_t last_seg = 0;
42 std::size_t remainder = n;
43
44 for (auto &&seg : segments) {
45 if (seg.size() >= remainder) {
46 break;
47 }
48 remainder -= seg.size();
49 last_seg++;
50 }
51
52 return take_segments(std::forward<R>(segments), last_seg, remainder);
53}
54
55// Drop all elements up to segment `segment_id` and index `local_id`
56template <typename R>
57auto drop_segments(R &&segments, std::size_t first_seg, std::size_t local_id) {
58 auto remainder = local_id;
59
60 auto drop_partial = [=](auto &&v) {
61 auto &&[i, segment] = v;
62 if (i == first_seg) {
63 auto first = rng::begin(segment);
64 rng::advance(first, remainder);
65 auto last = rng::end(segment);
66 return dr::remote_subrange(first, last, dr::ranges::rank(segment));
67 } else {
68 return dr::remote_subrange(segment);
69 }
70 };
71
72 return enumerate(segments) | rng::views::drop(first_seg) |
73 rng::views::transform(std::move(drop_partial));
74}
75
76// Drop the first n elements
77template <typename R> auto drop_segments(R &&segments, std::size_t n) {
78 std::size_t first_seg = 0;
79 std::size_t remainder = n;
80
81 for (auto &&seg : segments) {
82 if (seg.size() > remainder) {
83 break;
84 }
85 remainder -= seg.size();
86 first_seg++;
87 }
88
89 return drop_segments(std::forward<R>(segments), first_seg, remainder);
90}
91
92} // namespace __detail
93
94} // namespace dr
95
96namespace DR_RANGES_NAMESPACE {
97
98// A standard library range adaptor does not change the rank of a
99// remote range, so we can simply return the rank of the base view.
100template <rng::range V>
102auto rank_(V &&v) {
103 return dr::ranges::rank(std::forward<V>(v).base());
104}
105
106template <rng::range V>
107 requires(dr::is_ref_view_v<std::remove_cvref_t<V>> &&
109auto segments_(V &&v) {
110 return dr::ranges::segments(v.base());
111}
112
113template <rng::range V>
114 requires(dr::is_take_view_v<std::remove_cvref_t<V>> &&
116auto segments_(V &&v) {
117 return dr::__detail::take_segments(dr::ranges::segments(v.base()), v.size());
118}
119
120template <rng::range V>
121 requires(dr::is_drop_view_v<std::remove_cvref_t<V>> &&
123auto segments_(V &&v) {
124 return dr::__detail::drop_segments(dr::ranges::segments(v.base()),
125 v.base().size() - v.size());
126}
127
128template <rng::range V>
129 requires(dr::is_subrange_view_v<std::remove_cvref_t<V>> &&
131auto segments_(V &&v) {
132 auto first = rng::begin(v);
133 auto last = rng::end(v);
134 auto size = rng::distance(first, last);
135
136 return dr::__detail::take_segments(dr::ranges::segments(first), size);
137}
138
139} // namespace DR_RANGES_NAMESPACE
Definition: remote_subrange.hpp:15
Definition: concepts.hpp:31
Definition: concepts.hpp:20
Definition: concepts.hpp:16