11 template <
typename W,
typename LeafOp,
typename SelectOp,
typename ForwardIterator>
12 inline auto search_aux(
const execution::parallel_policy<W>& policy,
15 ForwardIterator first,
16 ForwardIterator last) {
17 if constexpr (ori::is_global_ptr_v<ForwardIterator>) {
26 std::size_t d = std::distance(first, last);
28 if (d <= policy.cutoff_count) {
29 auto [css, its] = checkout_global_iterators(d, first);
30 auto first_ = std::get<0>(its);
34 auto [ret, found_its_] = leaf_op(first_, std::next(first_, d));
35 auto found_its = std::apply([&](
auto&&... its_) {
36 return std::make_tuple((first + std::distance(first_, its_))...);
38 return std::make_tuple(ret, found_its);
41 auto mid = std::next(first, d / 2);
44 [=] {
return search_aux(policy, leaf_op, select_op, first, mid); },
45 [=] {
return search_aux(policy, leaf_op, select_op, mid, last); });
47 return select_op(r1, r2);
87 template <
typename ExecutionPolicy,
typename ForwardIterator,
typename Compare>
88 inline ForwardIterator
min_element(
const ExecutionPolicy& policy,
89 ForwardIterator first,
92 if (std::distance(first, last) <= 1) {
96 using value_type =
typename std::iterator_traits<ForwardIterator>::value_type;
98 auto leaf_op = [=](
const auto& f,
const auto& l) {
100 if constexpr (std::is_trivially_copyable_v<value_type>) {
101 return std::make_tuple(*it, std::make_tuple(it));
103 return std::make_tuple(std::monostate{}, std::make_tuple(it));
107 auto select_op = [=](
const auto& l,
const auto& r) {
108 auto [val_l, its_l] = l;
109 auto [val_r, its_r] = r;
110 if constexpr (std::is_trivially_copyable_v<value_type>) {
111 return comp(val_r, val_l) ? r : l;
115 auto [css, its] = internal::checkout_global_iterators(1, it_l, it_r);
116 auto [it_l_, it_r_] = its;
117 return comp(*it_r_, *it_l_) ? r : l;
121 auto [val, its] = internal::search_aux(policy, leaf_op, select_op, first, last);
150 template <
typename ExecutionPolicy,
typename ForwardIterator>
152 ForwardIterator first,
153 ForwardIterator last) {
154 return min_element(policy, first, last, std::less<>{});
190 template <
typename ExecutionPolicy,
typename ForwardIterator,
typename Compare>
192 ForwardIterator first,
193 ForwardIterator last,
195 if (std::distance(first, last) <= 1) {
199 using value_type =
typename std::iterator_traits<ForwardIterator>::value_type;
201 auto leaf_op = [=](
const auto& f,
const auto& l) {
203 if constexpr (std::is_trivially_copyable_v<value_type>) {
204 return std::make_tuple(*it, std::make_tuple(it));
206 return std::make_tuple(std::monostate{}, std::make_tuple(it));
210 auto select_op = [=](
const auto& l,
const auto& r) {
211 auto [val_l, its_l] = l;
212 auto [val_r, its_r] = r;
213 if constexpr (std::is_trivially_copyable_v<value_type>) {
214 return comp(val_l, val_r) ? r : l;
218 auto [css, its] = internal::checkout_global_iterators(1, it_l, it_r);
219 auto [it_l_, it_r_] = its;
220 return comp(*it_l_, *it_r_) ? r : l;
224 auto [val, its] = internal::search_aux(policy, leaf_op, select_op, first, last);
253 template <
typename ExecutionPolicy,
typename ForwardIterator>
255 ForwardIterator first,
256 ForwardIterator last) {
257 return max_element(policy, first, last, std::less<>{});
295 template <
typename ExecutionPolicy,
typename ForwardIterator,
typename Compare>
296 inline std::pair<ForwardIterator, ForwardIterator>
298 ForwardIterator first,
299 ForwardIterator last,
301 if (std::distance(first, last) <= 1) {
302 return std::make_pair(first, first);
305 using value_type =
typename std::iterator_traits<ForwardIterator>::value_type;
307 auto leaf_op = [=](
const auto& f,
const auto& l) {
309 if constexpr (std::is_trivially_copyable_v<value_type>) {
310 return std::make_tuple(
311 std::make_pair(*min_it, *max_it), std::make_tuple(min_it, max_it));
313 return std::make_tuple(
314 std::monostate{}, std::make_tuple(min_it, max_it));
318 auto select_op = [=](
const auto& l,
const auto& r) {
319 auto [vals_l, its_l] = l;
320 auto [vals_r, its_r] = r;
321 auto [min_it_l, max_it_l] = its_l;
322 auto [min_it_r, max_it_r] = its_r;
324 if constexpr (std::is_trivially_copyable_v<value_type>) {
325 auto [min_val_l, max_val_l] = vals_l;
326 auto [min_val_r, max_val_r] = vals_r;
328 decltype(min_val_l) min_val = min_val_l;
329 decltype(min_it_l) min_it = min_it_l;
330 if (comp(min_val_r, min_val_l)) {
335 decltype(max_val_l) max_val = max_val_l;
336 decltype(max_it_l) max_it = max_it_l;
337 if (comp(max_val_l, max_val_r)) {
342 return std::make_tuple(
343 std::make_pair(min_val, max_val), std::make_tuple(min_it, max_it));
346 auto [css, its] = internal::checkout_global_iterators(
347 1, min_it_l, max_it_l, min_it_r, max_it_r);
348 auto [min_it_l_, max_it_l_, min_it_r_, max_it_r_] = its;
350 auto min_it = comp(*min_it_r_, *min_it_l_) ? min_it_r : min_it_l;
351 auto max_it = comp(*max_it_l_, *max_it_r_) ? max_it_r : max_it_l;
352 return std::make_tuple(
353 std::monostate{}, std::make_tuple(min_it, max_it));
357 auto [vals, its] = internal::search_aux(policy, leaf_op, select_op, first, last);
358 auto [min_it, max_it] = its;
359 return std::make_pair(min_it, max_it);
387 template <
typename ExecutionPolicy,
typename ForwardIterator>
388 inline std::pair<ForwardIterator, ForwardIterator>
390 ForwardIterator first,
391 ForwardIterator last) {
395 ITYR_TEST_CASE(
"[ityr::pattern::parallel_search] min, max, minmax_element") {
400 ori::global_ptr<long> p = ori::malloc_coll<long>(n);
404 execution::parallel_policy(100),
405 count_iterator<long>(0), count_iterator<long>(n), p,
406 [=](
long i) {
return (3 * i + 5) % 13; });
409 long max_pos = n / 3;
410 long max_pos_dummy = n / 3 * 2;
411 p[max_pos].put(max_val);
412 p[max_pos_dummy].put(max_val);
415 long min_pos = n / 4;
416 long min_pos_dummy = n - 1;
417 p[min_pos].put(min_val);
418 p[min_pos_dummy].put(min_val);
420 auto max_it =
max_element(execution::parallel_policy(100), p, p + n);
424 auto min_it =
min_element(execution::parallel_policy(100), p, p + n);
428 auto [min_it2, max_it2] =
minmax_element(execution::parallel_policy(100), p, p + n);
#define ITYR_CHECK(cond)
Definition: util.hpp:48
constexpr read_t read
Read-only checkout mode.
Definition: checkout_span.hpp:19
void fini()
Definition: ito.hpp:45
auto root_exec(Fn &&fn, Args &&... args)
Definition: ito.hpp:50
void init(MPI_Comm comm=MPI_COMM_WORLD)
Definition: ito.hpp:41
void fini()
Definition: ori.hpp:49
void init(MPI_Comm comm=MPI_COMM_WORLD)
Definition: ori.hpp:45
void free_coll(global_ptr< T > ptr)
Definition: ori.hpp:70
Definition: allocator.hpp:16
ForwardIterator max_element(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, Compare comp)
Search for the maximum element in a range.
Definition: parallel_search.hpp:191
std::pair< ForwardIterator, ForwardIterator > minmax_element(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, Compare comp)
Search for the minimum and maximum element in a range.
Definition: parallel_search.hpp:297
auto parallel_invoke(Args &&... args)
Fork parallel tasks and join them.
Definition: parallel_invoke.hpp:238
ForwardIteratorD transform(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d, UnaryOp unary_op)
Transform elements in a given range and store them in another range.
Definition: parallel_loop.hpp:583
ForwardIterator min_element(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, Compare comp)
Search for the minimum element in a range.
Definition: parallel_search.hpp:88
ForwardIterator min_element(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last)
Search for the minimum element in a range.
Definition: parallel_search.hpp:151
ForwardIterator max_element(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last)
Search for the maximum element in a range.
Definition: parallel_search.hpp:254
std::pair< ForwardIterator, ForwardIterator > minmax_element(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last)
Search for the minimum and maximum element in a range.
Definition: parallel_search.hpp:389