From ac384694e9e57ed8974d70e9599deeefff2c7c28 Mon Sep 17 00:00:00 2001 From: harith-hacky03 Date: Sun, 27 Apr 2025 20:28:54 +0530 Subject: [PATCH 1/2] Fix extrema algorithm semantics and add semantic tests for min_element, max_element, and minmax_element Signed-off-by: harith-hacky03 From 9755e1a92f6c778c297c074b2ee597aea52032fb Mon Sep 17 00:00:00 2001 From: harith-hacky03 Date: Sun, 27 Apr 2025 20:31:26 +0530 Subject: [PATCH 2/2] Fix extrema algorithm semantics and add semantic tests for min_element, max_element, and minmax_element Signed-off-by: harith-hacky03 --- .../hpx/parallel/algorithms/minmax.hpp | 52 +++++++++++-------- .../tests/unit/algorithms/max_element.cpp | 3 ++ .../tests/unit/algorithms/min_element.cpp | 3 ++ .../tests/unit/algorithms/minmax_element.cpp | 3 ++ 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp index 04b73961902c..19b0f25f7a62 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/minmax.hpp @@ -706,33 +706,41 @@ namespace hpx::parallel { minmax_element_result sequential_minmax_element(ExPolicy&&, FwdIter it, std::size_t count, F const& f, Proj const& proj) { - minmax_element_result result = {it, it}; + HPX_ASSERT(count != 0); - if (count == 0 || count == 1) - return result; + if (count == 1) + return minmax_element_result{it, it}; using element_type = hpx::traits::proxy_value_t< typename std::iterator_traits::value_type>; - element_type min_value = HPX_INVOKE(proj, *it); - element_type max_value = min_value; - util::loop_n>( - ++it, count - 1, [&](FwdIter const& curr) -> void { - element_type curr_value = HPX_INVOKE(proj, *curr); - if (HPX_INVOKE(f, curr_value, min_value)) - { - result.min = curr; - min_value = curr_value; - } + auto min = it; + auto max = it; + ++it; - if (!HPX_INVOKE(f, curr_value, max_value)) - { - result.max = curr; - max_value = HPX_MOVE(curr_value); - } - }); + element_type min_value = HPX_INVOKE(proj, *min); + element_type max_value = HPX_INVOKE(proj, *max); + + for (std::size_t i = 1; i < count; ++i, ++it) + { + element_type curr_value = HPX_INVOKE(proj, *it); + + // Update min if curr_value < min_value + if (HPX_INVOKE(f, curr_value, min_value)) + { + min = it; + min_value = curr_value; + } + + // Update max if min_value <= curr_value (not curr_value < min_value) + if (!HPX_INVOKE(f, curr_value, max_value)) + { + max = it; + max_value = curr_value; + } + } - return result; + return minmax_element_result{min, max}; } template @@ -771,7 +779,7 @@ namespace hpx::parallel { element_type curr_max_value = HPX_INVOKE(proj, *curr->max); - if (!HPX_INVOKE(f, curr_max_value, max_value)) + if (HPX_INVOKE(f, curr_max_value, max_value)) { result.max = curr->max; max_value = HPX_MOVE(curr_max_value); @@ -813,7 +821,7 @@ namespace hpx::parallel { min_value = curr_value; } - if (!HPX_INVOKE(f, curr_value, max_value)) + if (HPX_INVOKE(f, curr_value, max_value)) { max = curr; max_value = HPX_MOVE(curr_value); diff --git a/libs/core/algorithms/tests/unit/algorithms/max_element.cpp b/libs/core/algorithms/tests/unit/algorithms/max_element.cpp index ea32980a7deb..6522f6da5e94 100644 --- a/libs/core/algorithms/tests/unit/algorithms/max_element.cpp +++ b/libs/core/algorithms/tests/unit/algorithms/max_element.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -125,6 +126,8 @@ void max_element_test() { test_max_element(); test_max_element(); + test_max_element_semantics(); + test_max_element_semantics(); } /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/core/algorithms/tests/unit/algorithms/min_element.cpp b/libs/core/algorithms/tests/unit/algorithms/min_element.cpp index 88f2c6d395c4..8ba29d601fa9 100644 --- a/libs/core/algorithms/tests/unit/algorithms/min_element.cpp +++ b/libs/core/algorithms/tests/unit/algorithms/min_element.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -126,6 +127,8 @@ void min_element_test() { test_min_element(); test_min_element(); + test_min_element_semantics(); + test_min_element_semantics(); } /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/core/algorithms/tests/unit/algorithms/minmax_element.cpp b/libs/core/algorithms/tests/unit/algorithms/minmax_element.cpp index f4cd68ad6a63..76f7c0357a56 100644 --- a/libs/core/algorithms/tests/unit/algorithms/minmax_element.cpp +++ b/libs/core/algorithms/tests/unit/algorithms/minmax_element.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -139,6 +140,8 @@ void minmax_element_test() { test_minmax_element(); test_minmax_element(); + test_minmax_element_semantics(); + test_minmax_element_semantics(); } ///////////////////////////////////////////////////////////////////////////////