|
12 | 12 | #include <hpx/config.hpp> |
13 | 13 | #include <hpx/modules/coroutines.hpp> |
14 | 14 | #include <hpx/modules/execution.hpp> |
| 15 | +#include <hpx/modules/functional.hpp> |
15 | 16 | #include <hpx/modules/tag_invoke.hpp> |
16 | 17 | #include <hpx/parallel/algorithms/detail/dispatch.hpp> |
17 | 18 | #include <hpx/parallel/algorithms/detail/distance.hpp> |
|
31 | 32 | namespace hpx::parallel::detail { |
32 | 33 | /// \cond NOINTERNAL |
33 | 34 |
|
| 35 | + /////////////////////////////////////////////////////////////////////////// |
| 36 | + // sequential_search dispatch tag |
| 37 | + HPX_CXX_CORE_EXPORT template <typename ExPolicy> |
| 38 | + struct sequential_search_t final |
| 39 | + : hpx::functional::detail::tag_fallback<sequential_search_t<ExPolicy>> |
| 40 | + { |
| 41 | + private: |
| 42 | + // Partitioned path: called from search::parallel() f1 for each chunk. |
| 43 | + // Checks each starting position in [base_idx, base_idx+part_size) for a |
| 44 | + // needle match; cancels tok at the first match position found. |
| 45 | + template <typename Iter1, typename Iter2, typename Token, typename Pred, |
| 46 | + typename Proj1, typename Proj2> |
| 47 | + friend inline constexpr void tag_fallback_invoke( |
| 48 | + sequential_search_t<ExPolicy>, Iter1 it, Iter2 s_first, |
| 49 | + std::size_t base_idx, std::size_t part_size, std::size_t diff, |
| 50 | + std::size_t count, Token& tok, Pred&& op, Proj1&& proj1, |
| 51 | + Proj2&& proj2) |
| 52 | + { |
| 53 | + using reference = typename std::iterator_traits<Iter1>::reference; |
| 54 | + Iter1 curr = it; |
| 55 | + util::loop_idx_n<ExPolicy>(base_idx, it, part_size, tok, |
| 56 | + [diff, count, s_first, &tok, &curr, op = HPX_FORWARD(Pred, op), |
| 57 | + proj1 = HPX_FORWARD(Proj1, proj1), |
| 58 | + proj2 = HPX_FORWARD(Proj2, proj2)]( |
| 59 | + reference v, std::size_t i) mutable -> void { |
| 60 | + ++curr; |
| 61 | + if (HPX_INVOKE(op, HPX_INVOKE(proj1, v), |
| 62 | + HPX_INVOKE(proj2, *s_first))) |
| 63 | + { |
| 64 | + std::size_t local_count = 1; |
| 65 | + Iter2 needle = s_first; |
| 66 | + Iter1 mid = curr; |
| 67 | + // clang-format off |
| 68 | + for (std::size_t len = 0; |
| 69 | + local_count != diff && len != count; |
| 70 | + ++local_count, ++len, ++mid) |
| 71 | + // clang-format on |
| 72 | + { |
| 73 | + if (!HPX_INVOKE(op, HPX_INVOKE(proj1, *mid), |
| 74 | + HPX_INVOKE(proj2, *++needle))) |
| 75 | + break; |
| 76 | + } |
| 77 | + if (local_count == diff) |
| 78 | + tok.cancel(i); |
| 79 | + } |
| 80 | + }); |
| 81 | + } |
| 82 | + }; |
| 83 | + |
| 84 | + /////////////////////////////////////////////////////////////////////////// |
| 85 | + // sequential_search_n dispatch tag |
| 86 | + HPX_CXX_CORE_EXPORT template <typename ExPolicy> |
| 87 | + struct sequential_search_n_t final |
| 88 | + : hpx::functional::detail::tag_fallback<sequential_search_n_t<ExPolicy>> |
| 89 | + { |
| 90 | + private: |
| 91 | + // Partitioned path: called from search_n::parallel() f1 for each chunk. |
| 92 | + // Checks each starting position in [base_idx, base_idx+part_size) for |
| 93 | + // count consecutive elements equal to value_proj. |
| 94 | + template <typename Iter, typename Size, typename V, typename Token, |
| 95 | + typename Pred, typename Proj> |
| 96 | + friend inline constexpr void tag_fallback_invoke( |
| 97 | + sequential_search_n_t<ExPolicy>, Iter it, std::size_t base_idx, |
| 98 | + std::size_t part_size, std::ptrdiff_t max_start, Size count, |
| 99 | + V const& value_proj, Token& tok, Pred&& pred, Proj&& proj) |
| 100 | + { |
| 101 | + using difference_type = |
| 102 | + typename std::iterator_traits<Iter>::difference_type; |
| 103 | + using reference = typename std::iterator_traits<Iter>::reference; |
| 104 | + std::size_t idx = 0; |
| 105 | + util::loop_idx_n<ExPolicy>(base_idx, it, part_size, tok, |
| 106 | + [max_start, count, it, &value_proj, &tok, &idx, |
| 107 | + pred = HPX_FORWARD(Pred, pred), |
| 108 | + proj = HPX_FORWARD(Proj, proj)]( |
| 109 | + reference, std::size_t abs_idx) mutable -> void { |
| 110 | + if (static_cast<difference_type>(abs_idx) >= max_start) |
| 111 | + return; |
| 112 | + Iter start = it; |
| 113 | + std::advance(start, static_cast<difference_type>(idx)); |
| 114 | + ++idx; |
| 115 | + Iter curr = start; |
| 116 | + Size matched = 0; |
| 117 | + while (matched < count && |
| 118 | + HPX_INVOKE(pred, HPX_INVOKE(proj, *curr), value_proj)) |
| 119 | + { |
| 120 | + ++curr; |
| 121 | + ++matched; |
| 122 | + } |
| 123 | + if (matched == count) |
| 124 | + tok.cancel(abs_idx); |
| 125 | + }); |
| 126 | + } |
| 127 | + }; |
| 128 | + |
34 | 129 | /////////////////////////////////////////////////////////////////////////// |
35 | 130 | // search |
36 | 131 | HPX_CXX_CORE_EXPORT template <typename FwdIter, typename Sent> |
@@ -69,7 +164,6 @@ namespace hpx::parallel::detail { |
69 | 164 | Sent last, FwdIter2 s_first, Sent2 s_last, Pred&& op, Proj1&& proj1, |
70 | 165 | Proj2&& proj2) |
71 | 166 | { |
72 | | - using reference = typename std::iterator_traits<FwdIter>::reference; |
73 | 167 | using difference_type = |
74 | 168 | typename std::iterator_traits<FwdIter>::difference_type; |
75 | 169 | using s_difference_type = |
@@ -130,38 +224,10 @@ namespace hpx::parallel::detail { |
130 | 224 | proj2 = HPX_FORWARD(Proj2, proj2)](FwdIter it, |
131 | 225 | std::size_t part_size, |
132 | 226 | std::size_t base_idx) mutable -> void { |
133 | | - FwdIter curr = it; |
134 | | - |
135 | | - hpx::parallel::util::loop_idx_n<policy_type>(base_idx, it, |
136 | | - part_size, tok, |
137 | | - [diff, count, s_first, &tok, &curr, |
138 | | - op = HPX_FORWARD(Pred, op), |
139 | | - proj1 = HPX_FORWARD(Proj1, proj1), |
140 | | - proj2 = HPX_FORWARD(Proj2, proj2)]( |
141 | | - reference v, std::size_t i) -> void { |
142 | | - ++curr; |
143 | | - if (HPX_INVOKE(op, HPX_INVOKE(proj1, v), |
144 | | - HPX_INVOKE(proj2, *s_first))) |
145 | | - { |
146 | | - difference_type local_count = 1; |
147 | | - FwdIter2 needle = s_first; |
148 | | - FwdIter mid = curr; |
149 | | - |
150 | | - // clang-format off |
151 | | - for (difference_type len = 0; |
152 | | - local_count != diff && len != count; |
153 | | - ++local_count, ++len, ++mid) |
154 | | - // clang-format on |
155 | | - { |
156 | | - if (!HPX_INVOKE(op, HPX_INVOKE(proj1, *mid), |
157 | | - HPX_INVOKE(proj2, *++needle))) |
158 | | - break; |
159 | | - } |
160 | | - |
161 | | - if (local_count == diff) |
162 | | - tok.cancel(i); |
163 | | - } |
164 | | - }); |
| 227 | + sequential_search_t<policy_type>{}(it, s_first, base_idx, |
| 228 | + part_size, static_cast<std::size_t>(diff), |
| 229 | + static_cast<std::size_t>(count), tok, HPX_FORWARD(Pred, op), |
| 230 | + HPX_FORWARD(Proj1, proj1), HPX_FORWARD(Proj2, proj2)); |
165 | 231 | }; |
166 | 232 |
|
167 | 233 | auto f2 = [=](auto&&... data) mutable -> FwdIter { |
@@ -278,33 +344,14 @@ namespace hpx::parallel::detail { |
278 | 344 | hpx::parallel::util::cancellation_token<difference_type> tok( |
279 | 345 | max_start); |
280 | 346 |
|
281 | | - auto f1 = [first, max_start, count, value_proj, |
| 347 | + auto f1 = [max_start, count, value_proj, |
282 | 348 | pred = HPX_FORWARD(Pred, pred), |
283 | 349 | proj = HPX_FORWARD(Proj, proj), |
284 | 350 | tok](FwdIter it, std::size_t part_size, |
285 | 351 | std::size_t base_idx) mutable -> void { |
286 | | - util::loop_idx_n<policy_type>(base_idx, it, part_size, tok, |
287 | | - [=, &tok](auto&&, std::size_t idx) mutable -> void { |
288 | | - difference_type start_idx = |
289 | | - static_cast<difference_type>(idx); |
290 | | - if (start_idx >= max_start) |
291 | | - return; |
292 | | - |
293 | | - FwdIter start = first; |
294 | | - std::advance(start, start_idx); |
295 | | - |
296 | | - FwdIter curr = start; |
297 | | - Size matched = 0; |
298 | | - |
299 | | - while (matched < count && pred(proj(*curr), value_proj)) |
300 | | - { |
301 | | - ++curr; |
302 | | - ++matched; |
303 | | - } |
304 | | - |
305 | | - if (matched == count) |
306 | | - tok.cancel(start_idx); |
307 | | - }); |
| 352 | + sequential_search_n_t<policy_type>{}(it, base_idx, part_size, |
| 353 | + static_cast<std::ptrdiff_t>(max_start), count, value_proj, |
| 354 | + tok, HPX_FORWARD(Pred, pred), HPX_FORWARD(Proj, proj)); |
308 | 355 | }; |
309 | 356 |
|
310 | 357 | auto f2 = [first, last, max_start, tok]( |
|
0 commit comments