Skip to content

Commit 426ac05

Browse files
algorithms: expose Proj parameter in min/max/minmax, is_sorted, and is_partitioned CPOs
This commit expands projection support to several core parallel algorithms, bringing them into alignment with the std::ranges design and the hpx::ranges container algorithms. Key changes: - Exposed 'Proj' template parameter (defaulting to hpx::identity) in public CPOs for hpx::min_element, hpx::max_element, hpx::minmax_element, hpx::is_sorted, hpx::is_sorted_until, and hpx::is_partitioned. - Integrated hpx::parallel::traits::is_projected_v and hpx::parallel::traits::is_indirect_callable_v constraints for standard-compliant type validation. - Fixed a regression in element_type deduction in the parallel reduction path (sequential_minmax_element_ind) to correctly handle projected values. - Cleaned up source headers and removed non-ASCII characters to satisfy 'inspect' CI checks. - Added comprehensive regression tests for both parallel and container-based overloads of these algorithms.
1 parent 37c665c commit 426ac05

11 files changed

Lines changed: 838 additions & 74 deletions

File tree

libs/core/algorithms/include/hpx/parallel/algorithms/is_partitioned.hpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -255,33 +255,45 @@ namespace hpx {
255255
: hpx::detail::tag_parallel_algorithm<is_partitioned_t>
256256
{
257257
private:
258-
template <typename FwdIter, typename Pred>
258+
template <typename FwdIter, typename Pred,
259+
typename Proj = hpx::identity>
259260
// clang-format off
260261
requires (
261-
std::forward_iterator<FwdIter>
262+
std::forward_iterator<FwdIter> &&
263+
hpx::parallel::traits::is_projected_v<Proj, FwdIter> &&
264+
hpx::parallel::traits::is_indirect_callable_v<
265+
hpx::execution::sequenced_policy, Pred,
266+
hpx::parallel::traits::projected<Proj, FwdIter>
267+
>
262268
)
263269
// clang-format on
264-
friend bool tag_fallback_invoke(
265-
hpx::is_partitioned_t, FwdIter first, FwdIter last, Pred pred)
270+
friend bool tag_fallback_invoke(hpx::is_partitioned_t, FwdIter first,
271+
FwdIter last, Pred pred, Proj proj = Proj())
266272
{
267273
return hpx::parallel::detail::is_partitioned<FwdIter, FwdIter>()
268274
.call(hpx::execution::seq, first, last, HPX_MOVE(pred),
269-
hpx::identity_v);
275+
HPX_MOVE(proj));
270276
}
271277

272-
template <typename ExPolicy, typename FwdIter, typename Pred>
278+
template <typename ExPolicy, typename FwdIter, typename Pred,
279+
typename Proj = hpx::identity>
273280
// clang-format off
274281
requires (
275282
hpx::is_execution_policy_v<ExPolicy> &&
276-
std::forward_iterator<FwdIter>
283+
std::forward_iterator<FwdIter> &&
284+
hpx::parallel::traits::is_projected_v<Proj, FwdIter> &&
285+
hpx::parallel::traits::is_indirect_callable_v<ExPolicy, Pred,
286+
hpx::parallel::traits::projected<Proj, FwdIter>
287+
>
277288
)
278289
// clang-format on
279290
friend decltype(auto) tag_fallback_invoke(hpx::is_partitioned_t,
280-
ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred)
291+
ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred,
292+
Proj proj = Proj())
281293
{
282294
return hpx::parallel::detail::is_partitioned<FwdIter, FwdIter>()
283295
.call(HPX_FORWARD(ExPolicy, policy), first, last,
284-
HPX_MOVE(pred), hpx::identity_v);
296+
HPX_MOVE(pred), HPX_MOVE(proj));
285297
}
286298
} is_partitioned{};
287299
} // namespace hpx

libs/core/algorithms/include/hpx/parallel/algorithms/is_sorted.hpp

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -459,85 +459,97 @@ namespace hpx {
459459
: hpx::detail::tag_parallel_algorithm<is_sorted_t>
460460
{
461461
private:
462-
template <typename FwdIter, typename Pred = hpx::parallel::detail::less>
462+
template <typename FwdIter, typename Pred = hpx::parallel::detail::less,
463+
typename Proj = hpx::identity>
463464
// clang-format off
464465
requires (
465466
std::forward_iterator<FwdIter> &&
466-
hpx::is_invocable_v<Pred,
467-
typename std::iterator_traits<FwdIter>::value_type,
468-
typename std::iterator_traits<FwdIter>::value_type
467+
hpx::parallel::traits::is_projected_v<Proj, FwdIter> &&
468+
hpx::parallel::traits::is_indirect_callable_v<
469+
hpx::execution::sequenced_policy, Pred,
470+
hpx::parallel::traits::projected<Proj, FwdIter>,
471+
hpx::parallel::traits::projected<Proj, FwdIter>
469472
>
470473
)
471474
// clang-format on
472-
friend bool tag_fallback_invoke(
473-
hpx::is_sorted_t, FwdIter first, FwdIter last, Pred pred = Pred())
475+
friend bool tag_fallback_invoke(hpx::is_sorted_t, FwdIter first,
476+
FwdIter last, Pred pred = Pred(), Proj proj = Proj())
474477
{
475478
return hpx::parallel::detail::is_sorted<FwdIter, FwdIter>().call(
476479
hpx::execution::seq, first, last, HPX_MOVE(pred),
477-
hpx::identity_v);
480+
HPX_MOVE(proj));
478481
}
479482

480483
template <typename ExPolicy, typename FwdIter,
481-
typename Pred = hpx::parallel::detail::less>
484+
typename Pred = hpx::parallel::detail::less,
485+
typename Proj = hpx::identity>
482486
// clang-format off
483487
requires (
484488
hpx::is_execution_policy_v<ExPolicy> &&
485489
std::forward_iterator<FwdIter> &&
486-
hpx::is_invocable_v<Pred,
487-
typename std::iterator_traits<FwdIter>::value_type,
488-
typename std::iterator_traits<FwdIter>::value_type
490+
hpx::parallel::traits::is_projected_v<Proj, FwdIter> &&
491+
hpx::parallel::traits::is_indirect_callable_v<ExPolicy, Pred,
492+
hpx::parallel::traits::projected<Proj, FwdIter>,
493+
hpx::parallel::traits::projected<Proj, FwdIter>
489494
>
490495
)
491496
// clang-format on
492497
friend decltype(auto) tag_fallback_invoke(hpx::is_sorted_t,
493-
ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred())
498+
ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred(),
499+
Proj proj = Proj())
494500
{
495501
return hpx::parallel::detail::is_sorted<FwdIter, FwdIter>().call(
496502
HPX_FORWARD(ExPolicy, policy), first, last, HPX_MOVE(pred),
497-
hpx::identity_v);
503+
HPX_MOVE(proj));
498504
}
499505
} is_sorted{};
500506

501507
HPX_CXX_CORE_EXPORT inline constexpr struct is_sorted_until_t final
502508
: hpx::detail::tag_parallel_algorithm<is_sorted_until_t>
503509
{
504510
private:
505-
template <typename FwdIter, typename Pred = hpx::parallel::detail::less>
511+
template <typename FwdIter, typename Pred = hpx::parallel::detail::less,
512+
typename Proj = hpx::identity>
506513
// clang-format off
507514
requires (
508515
std::forward_iterator<FwdIter> &&
509-
hpx::is_invocable_v<Pred,
510-
typename std::iterator_traits<FwdIter>::value_type,
511-
typename std::iterator_traits<FwdIter>::value_type
516+
hpx::parallel::traits::is_projected_v<Proj, FwdIter> &&
517+
hpx::parallel::traits::is_indirect_callable_v<
518+
hpx::execution::sequenced_policy, Pred,
519+
hpx::parallel::traits::projected<Proj, FwdIter>,
520+
hpx::parallel::traits::projected<Proj, FwdIter>
512521
>
513522
)
514523
// clang-format on
515524
friend FwdIter tag_fallback_invoke(hpx::is_sorted_until_t,
516-
FwdIter first, FwdIter last, Pred pred = Pred())
525+
FwdIter first, FwdIter last, Pred pred = Pred(), Proj proj = Proj())
517526
{
518527
return hpx::parallel::detail::is_sorted_until<FwdIter, FwdIter>()
519528
.call(hpx::execution::seq, first, last, HPX_MOVE(pred),
520-
hpx::identity_v);
529+
HPX_MOVE(proj));
521530
}
522531

523532
template <typename ExPolicy, typename FwdIter,
524-
typename Pred = hpx::parallel::detail::less>
533+
typename Pred = hpx::parallel::detail::less,
534+
typename Proj = hpx::identity>
525535
// clang-format off
526536
requires (
527537
hpx::is_execution_policy_v<ExPolicy> &&
528538
std::forward_iterator<FwdIter> &&
529-
hpx::is_invocable_v<Pred,
530-
typename std::iterator_traits<FwdIter>::value_type,
531-
typename std::iterator_traits<FwdIter>::value_type
539+
hpx::parallel::traits::is_projected_v<Proj, FwdIter> &&
540+
hpx::parallel::traits::is_indirect_callable_v<ExPolicy, Pred,
541+
hpx::parallel::traits::projected<Proj, FwdIter>,
542+
hpx::parallel::traits::projected<Proj, FwdIter>
532543
>
533544
)
534545
// clang-format on
535546
friend decltype(auto) tag_fallback_invoke(hpx::is_sorted_until_t,
536-
ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred())
547+
ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred(),
548+
Proj proj = Proj())
537549
{
538550
return hpx::parallel::detail::is_sorted_until<FwdIter, FwdIter>()
539551
.call(HPX_FORWARD(ExPolicy, policy), first, last,
540-
HPX_MOVE(pred), hpx::identity_v);
552+
HPX_MOVE(pred), HPX_MOVE(proj));
541553
}
542554
} is_sorted_until{};
543555
} // namespace hpx

0 commit comments

Comments
 (0)