diff --git a/libs/core/algorithms/CMakeLists.txt b/libs/core/algorithms/CMakeLists.txt index e54b4c1b1faa..6ec2269bcc13 100644 --- a/libs/core/algorithms/CMakeLists.txt +++ b/libs/core/algorithms/CMakeLists.txt @@ -54,7 +54,6 @@ set(algorithms_headers hpx/parallel/algorithms/fill.hpp hpx/parallel/algorithms/find.hpp hpx/parallel/algorithms/for_each.hpp - hpx/parallel/algorithms/for_each_index.hpp hpx/parallel/algorithms/for_loop.hpp hpx/parallel/algorithms/for_loop_induction.hpp hpx/parallel/algorithms/for_loop_reduction.hpp @@ -261,6 +260,10 @@ set(algorithms_compat_headers set(algorithms_sources handle_exception_termination_handler.cpp task_group.cpp) +if(HPX_TRACY_WITH_TRACY) + set(additional_dependencies hpx_tracy) +endif() + include(HPX_AddModule) add_hpx_module( core algorithms @@ -298,8 +301,8 @@ add_hpx_module( hpx_synchronization hpx_tag_invoke hpx_threading_base - hpx_tracing hpx_type_support hpx_util + ${additional_dependencies} CMAKE_SUBDIRS examples tests ) diff --git a/libs/core/algorithms/include/hpx/algorithms/traits/projected.hpp b/libs/core/algorithms/include/hpx/algorithms/traits/projected.hpp index 0ef3f4537429..ace187d3b495 100644 --- a/libs/core/algorithms/include/hpx/algorithms/traits/projected.hpp +++ b/libs/core/algorithms/include/hpx/algorithms/traits/projected.hpp @@ -20,7 +20,7 @@ namespace hpx::traits { /////////////////////////////////////////////////////////////////////////// - HPX_CXX_CORE_EXPORT template + template struct projected_iterator { using type = std::decay_t; @@ -28,7 +28,7 @@ namespace hpx::traits { // For segmented iterators, we consider the local_raw_iterator instead of // the given one. - HPX_CXX_CORE_EXPORT template + template struct projected_iterator>> { @@ -39,14 +39,14 @@ namespace hpx::traits { local_iterator>::local_raw_iterator; }; - HPX_CXX_CORE_EXPORT template + template struct projected_iterator::proxy_type>> { using type = typename std::decay_t::proxy_type; }; - HPX_CXX_CORE_EXPORT template + template using projected_iterator_t = typename projected_iterator::type; } // namespace hpx::traits @@ -55,18 +55,17 @@ namespace hpx::parallel::traits { /////////////////////////////////////////////////////////////////////////// namespace detail { - HPX_CXX_CORE_EXPORT template + template struct projected_result_of; - HPX_CXX_CORE_EXPORT template + template struct projected_result_of>> : hpx::util::invoke_result> { }; - HPX_CXX_CORE_EXPORT template + template struct projected_result_of_indirect : projected_result_of @@ -77,8 +76,7 @@ namespace hpx::parallel::traits { // This is being instantiated if a vector pack execution policy is used // with a zip_iterator. In this case the function object is invoked // with a tuple...> instead of just a tuple - HPX_CXX_CORE_EXPORT template + template struct projected_result_of_vector_pack_ : hpx::util::invoke_result + template struct projected_result_of_vector_pack; - HPX_CXX_CORE_EXPORT template + template struct projected_result_of_vector_pack> : projected_result_of_vector_pack_ + template struct projected_result_of : detail::projected_result_of, std::decay_t> { @@ -112,8 +108,7 @@ namespace hpx::parallel::traits { /////////////////////////////////////////////////////////////////////////// namespace detail { - HPX_CXX_CORE_EXPORT template + template struct is_projected : std::false_type { }; @@ -123,7 +118,7 @@ namespace hpx::parallel::traits { // void // clang-format off - HPX_CXX_CORE_EXPORT template + template struct is_projected && @@ -136,13 +131,12 @@ namespace hpx::parallel::traits { }; // clang-format on - HPX_CXX_CORE_EXPORT template + template struct is_projected_indirect : std::false_type { }; - HPX_CXX_CORE_EXPORT template + template struct is_projected_indirect> : detail::is_projected + template struct is_projected : detail::is_projected, hpx::traits::projected_iterator_t> { }; - HPX_CXX_CORE_EXPORT template + template inline constexpr bool is_projected_v = is_projected::value; /////////////////////////////////////////////////////////////////////////// - HPX_CXX_CORE_EXPORT template + template struct projected { using projector_type = std::decay_t; using iterator_type = hpx::traits::projected_iterator_t; }; - HPX_CXX_CORE_EXPORT template + template struct is_projected_indirect : detail::is_projected_indirect { }; - HPX_CXX_CORE_EXPORT template + template struct is_projected_zip_iterator : std::false_type { }; - HPX_CXX_CORE_EXPORT template + template struct is_projected_zip_iterator> : hpx::traits::is_zip_iterator @@ -190,19 +183,18 @@ namespace hpx::parallel::traits { /////////////////////////////////////////////////////////////////////////// namespace detail { - HPX_CXX_CORE_EXPORT template + template struct is_indirect_callable_impl : hpx::is_invocable { }; - HPX_CXX_CORE_EXPORT template + template struct is_indirect_callable : std::false_type { }; - HPX_CXX_CORE_EXPORT template + template struct is_indirect_callable, std::enable_if_t< hpx::util::all_of_v...> && @@ -218,8 +210,7 @@ namespace hpx::parallel::traits { // Vector pack execution policies used with zip-iterators require // special handling because zip_iterator<>::reference is not a real // reference type. - HPX_CXX_CORE_EXPORT template + template struct is_indirect_callable, std::enable_if_t< hpx::util::all_of_v...> && @@ -232,16 +223,14 @@ namespace hpx::parallel::traits { #endif } // namespace detail - HPX_CXX_CORE_EXPORT template + template struct is_indirect_callable : detail::is_indirect_callable, std::decay_t, hpx::util::pack...>> { }; - HPX_CXX_CORE_EXPORT template + template inline constexpr bool is_indirect_callable_v = is_indirect_callable::value; } // namespace hpx::parallel::traits diff --git a/libs/core/algorithms/include/hpx/algorithms/traits/projected_range.hpp b/libs/core/algorithms/include/hpx/algorithms/traits/projected_range.hpp index dc4550dce90a..04a7a25603c3 100644 --- a/libs/core/algorithms/include/hpx/algorithms/traits/projected_range.hpp +++ b/libs/core/algorithms/include/hpx/algorithms/traits/projected_range.hpp @@ -15,13 +15,12 @@ namespace hpx::parallel::traits { /////////////////////////////////////////////////////////////////////////// - HPX_CXX_CORE_EXPORT template + template struct projected_range_result_of { }; - HPX_CXX_CORE_EXPORT template + template struct projected_range_result_of>> : detail::projected_result_of, @@ -30,31 +29,29 @@ namespace hpx::parallel::traits { }; /////////////////////////////////////////////////////////////////////////// - HPX_CXX_CORE_EXPORT template + template struct is_projected_range : std::false_type { }; - HPX_CXX_CORE_EXPORT template + template struct is_projected_range>> : detail::is_projected, std::ranges::iterator_t> { }; - HPX_CXX_CORE_EXPORT template + template inline constexpr bool is_projected_range_v = is_projected_range::value; /////////////////////////////////////////////////////////////////////////// - HPX_CXX_CORE_EXPORT template + template struct projected_range { }; - HPX_CXX_CORE_EXPORT template + template struct projected_range>> { using projector_type = std::decay_t; diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/detail/is_sorted.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/detail/is_sorted.hpp index 67d40bd42356..a39fe1099ada 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/detail/is_sorted.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/detail/is_sorted.hpp @@ -13,8 +13,8 @@ namespace hpx::parallel::detail { - HPX_CXX_CORE_EXPORT template + template constexpr bool is_sorted_sequential( Iter first, Sent last, Compare&& comp, Proj&& proj = Proj()) { @@ -32,8 +32,8 @@ namespace hpx::parallel::detail { return sorted; } - HPX_CXX_CORE_EXPORT template + template constexpr Iter is_sorted_until_sequential( Iter first, Sent last, Compare&& comp, Proj&& proj = Proj()) { diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/is_partitioned.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/is_partitioned.hpp index 304bdad66b80..e9774e9dc2ff 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/is_partitioned.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/is_partitioned.hpp @@ -136,9 +136,16 @@ namespace hpx::parallel { //////////////////////////////////////////////////////////////////////////// // is_partitioned namespace detail { + enum class partition_status : std::uint8_t + { + is_partitioned = 0, + is_not_partitioned = 1, + mixed = 2, + cancelled = 3 + }; /// \cond NOINTERNAL - HPX_CXX_CORE_EXPORT template + template inline bool sequential_is_partitioned(std::vector&& res) { auto first = res.begin(); @@ -160,7 +167,7 @@ namespace hpx::parallel { return true; } - HPX_CXX_CORE_EXPORT template + template struct is_partitioned : public algorithm, bool> { @@ -184,18 +191,11 @@ namespace hpx::parallel { static decltype(auto) parallel(ExPolicy&& policy, Iter_ first, Sent_ last, Pred&& pred, Proj&& proj) { - using difference_type = - typename std::iterator_traits::difference_type; + using difference_type = hpx::traits::iter_difference_t; using result = util::detail::algorithm_result; constexpr bool has_scheduler_executor = hpx::execution_policy_has_scheduler_executor_v; - if constexpr (!has_scheduler_executor) - { - if (first == last) - return result::get(true); - } - difference_type count = hpx::parallel::detail::distance(first, last); @@ -208,36 +208,64 @@ namespace hpx::parallel { util::invoke_projected pred_projected( HPX_FORWARD(Pred, pred), HPX_FORWARD(Proj, proj)); util::cancellation_token<> tok; - using intermediate_result_t = std::uint8_t; + using intermediate_result_t = partition_status; auto f1 = [tok, pred_projected = HPX_MOVE(pred_projected)]( Iter_ part_begin, std::size_t part_count) mutable -> intermediate_result_t { bool fst_bool = HPX_INVOKE(pred_projected, *part_begin); if (part_count == 1) - return fst_bool; + return fst_bool ? partition_status::is_partitioned : + partition_status::is_not_partitioned; + + bool is_mixed = false; util::const_loop_n>(++part_begin, --part_count, tok, - [&fst_bool, &pred_projected, &tok]( + [&fst_bool, &is_mixed, &pred_projected, &tok]( Iter_ const& a) mutable -> void { if (fst_bool != hpx::invoke(pred_projected, *a)) { if (fst_bool) + { fst_bool = false; + is_mixed = true; + } else + { tok.cancel(); + } } }); - return fst_bool; + if (tok.was_cancelled()) + return partition_status::cancelled; + + return is_mixed ? + partition_status::mixed : + (fst_bool ? partition_status::is_partitioned : + partition_status::is_not_partitioned); }; auto f2 = [tok](auto&& results) -> bool { if (tok.was_cancelled()) return false; - return sequential_is_partitioned( - HPX_FORWARD(decltype(results), results)); + + auto it = std::find_if(hpx::util::begin(results), + hpx::util::end(results), [](partition_status x) { + return x != partition_status::is_partitioned; + }); + + if (it == hpx::util::end(results)) + return true; + + if (*it == partition_status::mixed) + ++it; + + return std::all_of( + it, hpx::util::end(results), [](partition_status x) { + return x == partition_status::is_not_partitioned; + }); }; return util::partitioner { private: - template + template // clang-format off requires ( - std::forward_iterator + std::forward_iterator && + hpx::parallel::traits::is_projected_v && + hpx::parallel::traits::is_indirect_callable_v< + hpx::execution::sequenced_policy, Pred, + hpx::parallel::traits::projected + > ) // clang-format on - friend bool tag_fallback_invoke( - hpx::is_partitioned_t, FwdIter first, FwdIter last, Pred pred) + friend bool tag_fallback_invoke(hpx::is_partitioned_t, FwdIter first, + FwdIter last, Pred pred, Proj proj = Proj()) { return hpx::parallel::detail::is_partitioned() .call(hpx::execution::seq, first, last, HPX_MOVE(pred), - hpx::identity_v); + HPX_MOVE(proj)); } - template + template // clang-format off requires ( hpx::is_execution_policy_v && - std::forward_iterator + std::forward_iterator && + hpx::parallel::traits::is_projected_v && + hpx::parallel::traits::is_indirect_callable_v< + hpx::execution::sequenced_policy, Pred, + hpx::parallel::traits::projected + > ) // clang-format on friend decltype(auto) tag_fallback_invoke(hpx::is_partitioned_t, - ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred) + ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred, + Proj proj = Proj()) { return hpx::parallel::detail::is_partitioned() .call(HPX_FORWARD(ExPolicy, policy), first, last, - HPX_MOVE(pred), hpx::identity_v); + HPX_MOVE(pred), HPX_MOVE(proj)); } } is_partitioned{}; } // namespace hpx diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/is_sorted.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/is_sorted.hpp index a607eb5f39b4..77f7a73de13e 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/is_sorted.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/is_sorted.hpp @@ -226,11 +226,11 @@ namespace hpx { #else #include -#include #include #include #include #include +#include #include #include #include @@ -255,7 +255,7 @@ namespace hpx::parallel { namespace detail { /// \cond NOINTERNAL - HPX_CXX_CORE_EXPORT template + template struct is_sorted : public algorithm, bool> { constexpr is_sorted() noexcept @@ -305,7 +305,7 @@ namespace hpx::parallel { -> intermediate_result_t { FwdIter_ trail = part_begin++; util::const_loop_n>(part_begin, - part_size - 1, + part_size - 1, tok, [&trail, &tok, &pred_projected]( FwdIter_ it) mutable -> void { if (hpx::invoke(pred_projected, *it, *trail++)) @@ -345,7 +345,7 @@ namespace hpx::parallel { namespace detail { /// \cond NOINTERNAL - HPX_CXX_CORE_EXPORT template + template struct is_sorted_until : public algorithm, FwdIter> { @@ -459,42 +459,49 @@ namespace hpx { : hpx::detail::tag_parallel_algorithm { private: - template + template // clang-format off requires ( std::forward_iterator && - hpx::is_invocable_v::value_type, - typename std::iterator_traits::value_type + hpx::parallel::traits::is_projected_v && + hpx::parallel::traits::is_indirect_callable_v< + hpx::execution::sequenced_policy, Pred, + hpx::parallel::traits::projected, + hpx::parallel::traits::projected > ) // clang-format on - friend bool tag_fallback_invoke( - hpx::is_sorted_t, FwdIter first, FwdIter last, Pred pred = Pred()) + friend bool tag_fallback_invoke(hpx::is_sorted_t, FwdIter first, + FwdIter last, Pred pred = Pred(), Proj proj = Proj()) { return hpx::parallel::detail::is_sorted().call( hpx::execution::seq, first, last, HPX_MOVE(pred), - hpx::identity_v); + HPX_MOVE(proj)); } template + typename Pred = hpx::parallel::detail::less, + typename Proj = hpx::identity> // clang-format off requires ( hpx::is_execution_policy_v && std::forward_iterator && - hpx::is_invocable_v::value_type, - typename std::iterator_traits::value_type + hpx::parallel::traits::is_projected_v && + hpx::parallel::traits::is_indirect_callable_v< + hpx::execution::sequenced_policy, Pred, + hpx::parallel::traits::projected, + hpx::parallel::traits::projected > ) // clang-format on friend decltype(auto) tag_fallback_invoke(hpx::is_sorted_t, - ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred()) + ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred(), + Proj proj = Proj()) { return hpx::parallel::detail::is_sorted().call( HPX_FORWARD(ExPolicy, policy), first, last, HPX_MOVE(pred), - hpx::identity_v); + HPX_MOVE(proj)); } } is_sorted{}; @@ -502,42 +509,49 @@ namespace hpx { : hpx::detail::tag_parallel_algorithm { private: - template + template // clang-format off requires ( std::forward_iterator && - hpx::is_invocable_v::value_type, - typename std::iterator_traits::value_type + hpx::parallel::traits::is_projected_v && + hpx::parallel::traits::is_indirect_callable_v< + hpx::execution::sequenced_policy, Pred, + hpx::parallel::traits::projected, + hpx::parallel::traits::projected > ) // clang-format on friend FwdIter tag_fallback_invoke(hpx::is_sorted_until_t, - FwdIter first, FwdIter last, Pred pred = Pred()) + FwdIter first, FwdIter last, Pred pred = Pred(), Proj proj = Proj()) { return hpx::parallel::detail::is_sorted_until() .call(hpx::execution::seq, first, last, HPX_MOVE(pred), - hpx::identity_v); + HPX_MOVE(proj)); } template + typename Pred = hpx::parallel::detail::less, + typename Proj = hpx::identity> // clang-format off requires ( hpx::is_execution_policy_v && std::forward_iterator && - hpx::is_invocable_v::value_type, - typename std::iterator_traits::value_type + hpx::parallel::traits::is_projected_v && + hpx::parallel::traits::is_indirect_callable_v< + hpx::execution::sequenced_policy, Pred, + hpx::parallel::traits::projected, + hpx::parallel::traits::projected > ) // clang-format on friend decltype(auto) tag_fallback_invoke(hpx::is_sorted_until_t, - ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred()) + ExPolicy&& policy, FwdIter first, FwdIter last, Pred pred = Pred(), + Proj proj = Proj()) { return hpx::parallel::detail::is_sorted_until() .call(HPX_FORWARD(ExPolicy, policy), first, last, - HPX_MOVE(pred), hpx::identity_v); + HPX_MOVE(pred), HPX_MOVE(proj)); } } is_sorted_until{}; } // namespace hpx diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp index c5201888dced..603e926141b4 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp @@ -388,7 +388,7 @@ namespace hpx { namespace hpx::parallel { - HPX_CXX_CORE_EXPORT template + template using minmax_element_result = hpx::parallel::util::min_max_result; /////////////////////////////////////////////////////////////////////////// @@ -396,8 +396,8 @@ namespace hpx::parallel { namespace detail { /// \cond NOINTERNAL - HPX_CXX_CORE_EXPORT template + template constexpr FwdIter sequential_min_element(ExPolicy&&, FwdIter it, std::size_t count, F const& f, Proj const& proj) { @@ -424,7 +424,7 @@ namespace hpx::parallel { } /////////////////////////////////////////////////////////////////////// - HPX_CXX_CORE_EXPORT template + template struct min_element : public algorithm, Iter> { // this has to be a member of the algorithm type as we access this @@ -548,8 +548,8 @@ namespace hpx::parallel { namespace detail { /// \cond NOINTERNAL - HPX_CXX_CORE_EXPORT template + template constexpr FwdIter sequential_max_element(ExPolicy&&, FwdIter it, std::size_t count, F const& f, Proj const& proj) { @@ -576,7 +576,7 @@ namespace hpx::parallel { } /////////////////////////////////////////////////////////////////////// - HPX_CXX_CORE_EXPORT template + template struct max_element : public algorithm, Iter> { // this has to be a member of the algorithm type as we access this @@ -700,8 +700,8 @@ namespace hpx::parallel { namespace detail { /// \cond NOINTERNAL - HPX_CXX_CORE_EXPORT template + template minmax_element_result sequential_minmax_element(ExPolicy&&, FwdIter it, std::size_t count, F const& f, Proj const& proj) { @@ -734,7 +734,7 @@ namespace hpx::parallel { return result; } - HPX_CXX_CORE_EXPORT template + template struct minmax_element : public algorithm, minmax_element_result> { @@ -882,7 +882,7 @@ namespace hpx::parallel { namespace hpx { - HPX_CXX_CORE_EXPORT template + template using minmax_element_result = hpx::parallel::util::min_max_result; /////////////////////////////////////////////////////////////////////////// diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/shift_left.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/shift_left.hpp index 913e632f64e8..97de954184a6 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/shift_left.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/shift_left.hpp @@ -277,9 +277,8 @@ namespace hpx { ) // clang-format on friend typename hpx::parallel::util::detail::algorithm_result::type - tag_fallback_invoke(shift_left_t, ExPolicy&& policy, FwdIter first, - FwdIter last, Size n) + FwdIter>::type tag_fallback_invoke(shift_left_t, ExPolicy&& policy, + FwdIter first, FwdIter last, Size n) { static_assert(std::forward_iterator, "Requires at least forward iterator."); diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/shift_right.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/shift_right.hpp index a32f2d0bf0de..d0f383dfe225 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/shift_right.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/shift_right.hpp @@ -322,9 +322,8 @@ namespace hpx { ) // clang-format on friend typename hpx::parallel::util::detail::algorithm_result::type - tag_fallback_invoke(shift_right_t, ExPolicy&& policy, FwdIter first, - FwdIter last, Size n) + FwdIter>::type tag_fallback_invoke(shift_right_t, ExPolicy&& policy, + FwdIter first, FwdIter last, Size n) { static_assert(std::forward_iterator, "Requires at least forward iterator."); diff --git a/libs/core/algorithms/include/hpx/parallel/container_algorithms/find.hpp b/libs/core/algorithms/include/hpx/parallel/container_algorithms/find.hpp index c473a876acf8..0d3f330ecfc2 100644 --- a/libs/core/algorithms/include/hpx/parallel/container_algorithms/find.hpp +++ b/libs/core/algorithms/include/hpx/parallel/container_algorithms/find.hpp @@ -2261,9 +2261,8 @@ namespace hpx::ranges { ) // clang-format on friend hpx::parallel::util::detail::algorithm_result_t> - tag_fallback_invoke(find_if_not_t, ExPolicy&& policy, Rng&& rng, - Pred pred, Proj proj = Proj()) + std::ranges::iterator_t> tag_fallback_invoke(find_if_not_t, + ExPolicy&& policy, Rng&& rng, Pred pred, Proj proj = Proj()) { using iterator_type = std::ranges::iterator_t; @@ -2472,10 +2471,9 @@ namespace hpx::ranges { ) // clang-format on friend hpx::parallel::util::detail::algorithm_result_t> - tag_fallback_invoke(find_first_of_t, ExPolicy&& policy, Rng1&& rng1, - Rng2&& rng2, Pred op = Pred(), Proj1 proj1 = Proj1(), - Proj2 proj2 = Proj2()) + std::ranges::iterator_t> tag_fallback_invoke(find_first_of_t, + ExPolicy&& policy, Rng1&& rng1, Rng2&& rng2, Pred op = Pred(), + Proj1 proj1 = Proj1(), Proj2 proj2 = Proj2()) { using iterator_type = std::ranges::iterator_t; diff --git a/libs/core/algorithms/include/hpx/parallel/container_algorithms/iota.hpp b/libs/core/algorithms/include/hpx/parallel/container_algorithms/iota.hpp index 0990a29060f6..0b38aff1cfcd 100644 --- a/libs/core/algorithms/include/hpx/parallel/container_algorithms/iota.hpp +++ b/libs/core/algorithms/include/hpx/parallel/container_algorithms/iota.hpp @@ -189,9 +189,8 @@ namespace hpx::ranges { ) // clang-format on friend hpx::parallel::util::detail::algorithm_result_t> - tag_fallback_invoke( - iota_t, ExPolicy&& policy, FwdIter first, Sent last, T value) + iota_result> tag_fallback_invoke(iota_t, + ExPolicy&& policy, FwdIter first, Sent last, T value) { auto dist = hpx::parallel::detail::distance(first, last); diff --git a/libs/core/algorithms/include/hpx/parallel/container_algorithms/is_partitioned.hpp b/libs/core/algorithms/include/hpx/parallel/container_algorithms/is_partitioned.hpp index 966d6c59a2e2..cbd3ffaa696d 100644 --- a/libs/core/algorithms/include/hpx/parallel/container_algorithms/is_partitioned.hpp +++ b/libs/core/algorithms/include/hpx/parallel/container_algorithms/is_partitioned.hpp @@ -297,9 +297,9 @@ namespace hpx::ranges { ) // clang-format on friend typename parallel::util::detail::algorithm_result::type - tag_fallback_invoke(hpx::ranges::is_partitioned_t, ExPolicy&& policy, - FwdIter first, Sent last, Pred pred, Proj proj = Proj()) + bool>::type tag_fallback_invoke(hpx::ranges::is_partitioned_t, + ExPolicy&& policy, FwdIter first, Sent last, Pred pred, + Proj proj = Proj()) { return hpx::parallel::detail::is_partitioned().call( HPX_FORWARD(ExPolicy, policy), first, last, HPX_MOVE(pred), @@ -318,15 +318,15 @@ namespace hpx::ranges { ) // clang-format on friend bool tag_fallback_invoke(hpx::ranges::is_partitioned_t, - Rng&& rng, Pred& pred, Proj proj = Proj()) + Rng&& rng, Pred pred, Proj proj = Proj()) { using iterator_type = typename hpx::traits::range_traits::iterator_type; return hpx::parallel::detail::is_partitioned() - .call(hpx::execution::seq, std::begin(rng), std::end(rng), - HPX_MOVE(pred), HPX_MOVE(proj)); + .call(hpx::execution::seq, hpx::util::begin(rng), + hpx::util::end(rng), HPX_MOVE(pred), HPX_MOVE(proj)); } template +#include +#include + +#include +#include +#include +#include + +void test_is_sorted_projection() +{ + using namespace hpx::execution; + using element = std::pair; + + std::vector sorted_c = {{10, 1}, {20, 3}, {30, 5}, {40, 8}}; + std::vector unsorted_c = {{10, 1}, {20, 5}, {30, 3}, {40, 8}}; + + auto proj = [](element const& p) { return p.second; }; + + HPX_TEST(hpx::is_sorted( + sorted_c.begin(), sorted_c.end(), std::less{}, proj)); + HPX_TEST(!hpx::is_sorted( + unsorted_c.begin(), unsorted_c.end(), std::less{}, proj)); + + HPX_TEST(hpx::is_sorted( + seq, sorted_c.begin(), sorted_c.end(), std::less{}, proj)); + HPX_TEST(!hpx::is_sorted( + seq, unsorted_c.begin(), unsorted_c.end(), std::less{}, proj)); + + HPX_TEST(hpx::is_sorted( + par, sorted_c.begin(), sorted_c.end(), std::less{}, proj)); + HPX_TEST(!hpx::is_sorted( + par, unsorted_c.begin(), unsorted_c.end(), std::less{}, proj)); + + HPX_TEST(hpx::is_sorted( + par(task), sorted_c.begin(), sorted_c.end(), std::less{}, proj) + .get()); + HPX_TEST(!hpx::is_sorted( + par(task), unsorted_c.begin(), unsorted_c.end(), std::less{}, proj) + .get()); + + HPX_TEST(hpx::is_sorted( + par, sorted_c.begin(), sorted_c.begin(), std::less{}, proj)); + HPX_TEST(hpx::is_sorted( + par, sorted_c.begin(), sorted_c.begin() + 1, std::less{}, proj)); +} + +void test_is_sorted_until_projection() +{ + using namespace hpx::execution; + using element = std::pair; + + std::vector c = {{10, 1}, {20, 3}, {30, 8}, {40, 5}, {50, 9}}; + + auto proj = [](element const& p) { return p.second; }; + + auto it_seq = + hpx::is_sorted_until(c.begin(), c.end(), std::less{}, proj); + HPX_TEST(it_seq != c.end()); + HPX_TEST_EQ(it_seq->second, 5); + + auto it_seq2 = + hpx::is_sorted_until(seq, c.begin(), c.end(), std::less{}, proj); + HPX_TEST(it_seq2 != c.end()); + HPX_TEST_EQ(it_seq2->second, 5); + + auto it_par = hpx::is_sorted_until( + hpx::execution::par, c.begin(), c.end(), std::less{}, proj); + HPX_TEST(it_par != c.end() && it_par->second == 5); + + auto it_task = + hpx::is_sorted_until(hpx::execution::par(hpx::execution::task), + c.begin(), c.end(), std::less{}, proj) + .get(); + HPX_TEST(it_task != c.end() && it_task->second == 5); + + std::vector fully_sorted = {{10, 1}, {20, 3}, {30, 5}}; + auto it_end = hpx::is_sorted_until( + par, fully_sorted.begin(), fully_sorted.end(), std::less{}, proj); + HPX_TEST(it_end == fully_sorted.end()); + + auto it_empty = hpx::is_sorted_until(par, fully_sorted.begin(), + fully_sorted.begin(), std::less{}, proj); + HPX_TEST(it_empty == fully_sorted.begin()); +} + +void test_is_partitioned_projection() +{ + using namespace hpx::execution; + using element = std::pair; + + std::vector partitioned_c = {{10, 2}, {20, 4}, {30, 1}, {40, 3}}; + std::vector not_partitioned_c = { + {10, 2}, {20, 1}, {30, 4}, {40, 3}}; + + auto proj = [](element const& p) { return p.second; }; + auto pred = [](int v) { return v % 2 == 0; }; + + HPX_TEST(hpx::is_partitioned( + partitioned_c.begin(), partitioned_c.end(), pred, proj)); + HPX_TEST(!hpx::is_partitioned( + not_partitioned_c.begin(), not_partitioned_c.end(), pred, proj)); + + HPX_TEST(hpx::is_partitioned( + seq, partitioned_c.begin(), partitioned_c.end(), pred, proj)); + HPX_TEST(!hpx::is_partitioned( + seq, not_partitioned_c.begin(), not_partitioned_c.end(), pred, proj)); + + HPX_TEST(hpx::is_partitioned( + par, partitioned_c.begin(), partitioned_c.end(), pred, proj)); + HPX_TEST(!hpx::is_partitioned( + par, not_partitioned_c.begin(), not_partitioned_c.end(), pred, proj)); + + HPX_TEST(hpx::is_partitioned( + par(task), partitioned_c.begin(), partitioned_c.end(), pred, proj) + .get()); + HPX_TEST(!hpx::is_partitioned(par(task), not_partitioned_c.begin(), + not_partitioned_c.end(), pred, proj) + .get()); + + HPX_TEST(hpx::is_partitioned( + par, partitioned_c.begin(), partitioned_c.begin(), pred, proj)); + HPX_TEST(hpx::is_partitioned( + par, partitioned_c.begin(), partitioned_c.begin() + 1, pred, proj)); +} + +int hpx_main(hpx::program_options::variables_map&) +{ + test_is_sorted_projection(); + test_is_sorted_until_projection(); + test_is_partitioned_projection(); + + return hpx::local::finalize(); +} + +int main(int argc, char* argv[]) +{ + std::vector const cfg = {"hpx.os_threads=all"}; + + hpx::local::init_params init_args; + init_args.cfg = cfg; + + HPX_TEST_EQ_MSG(hpx::local::init(hpx_main, argc, argv, init_args), 0, + "HPX main exited with non-zero status"); + + return hpx::util::report_errors(); +}