diff --git a/.github/workflows/windows_debug_vs2026_modules.yml b/.github/workflows/windows_debug_vs2026_modules.yml new file mode 100644 index 000000000000..e1655a07f916 --- /dev/null +++ b/.github/workflows/windows_debug_vs2026_modules.yml @@ -0,0 +1,68 @@ +# Copyright (c) 2020 Mikael Simberg +# Copyright (c) 2024-2026 The STE||AR Group +# +# SPDX-License-Identifier: BSL-1.0 +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +name: Windows CI (Debug, VS2026 toolset, C++20 Modules) + +on: [pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: windows-2025-vs2026 + + steps: + - uses: actions/checkout@v6 + - uses: lukka/get-cmake@v4.3.2 + + - name: Install dependencies + run: | + md C:\projects + $client = new-object System.Net.WebClient + $client.DownloadFile("https://rostam.cct.lsu.edu/download/builder/vcpkg-export-hpx-dependencies-2026.7z","C:\projects\vcpkg-export-hpx-dependencies.7z") + 7z x C:\projects\vcpkg-export-hpx-dependencies.7z -y -oC:\projects\vcpkg + - name: Configure + shell: bash + run: | + cmake . -Bbuild -G'Visual Studio 18 2026' \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_TOOLCHAIN_FILE='C:/projects/vcpkg/scripts/buildsystems/vcpkg.cmake' \ + -DHPX_WITH_FETCH_ASIO=ON \ + -DHPX_WITH_ASIO_TAG=asio-1-38-0 \ + -DHPX_WITH_EXAMPLES=OFF \ + -DHPX_WITH_TESTS=OFF \ + -DHPX_WITH_TESTS_EXAMPLES=OFF \ + -DHPX_WITH_DEPRECATION_WARNINGS=OFF \ + -DHPX_WITH_TESTS_MAX_THREADS_PER_LOCALITY=2 \ + -DHPX_COROUTINES_WITH_SWAP_CONTEXT_EMULATION=ON \ + -DHPX_WITH_VERIFY_LOCKS=ON \ + -DHPX_WITH_VERIFY_LOCKS_BACKTRACE=ON \ + -DHPX_WITH_CHECK_MODULE_DEPENDENCIES=ON \ + -DHPX_WITH_CXX_MODULES=ON \ + -DHPX_WITH_DATAPAR=ON \ + -DHPX_WITH_DATAPAR_BACKEND=EMULATE + - name: Build + shell: bash + run: | + cmake --build build --config Debug --target ALL_BUILD \ + -- -maxcpucount:2 -verbosity:minimal -nologo + - name: Install + shell: bash + run: | + cmake --install build --config Debug +# - name: Test +# run: | +# $exclude_regex = & "$env:GITHUB_WORKSPACE/.github/ci-scripts/generate_ctest_exclude_regex.ps1" ` +# "$env:GITHUB_WORKSPACE/.github/workflows/tests.examples.targets" +# cd build +# ctest ` +# --output-on-failure ` +# --build-config Debug ` +# --tests-regex tests.examples ` +# --exclude-regex $exclude_regex diff --git a/CMakeLists.txt b/CMakeLists.txt index 71e939a056fa..31e3aab1b07d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -293,17 +293,19 @@ if(HPX_WITH_DOCUMENTATION) endif() if(WIN32) - set(HPX_WITH_PSEUDO_DEPENDENCIES - OFF - CACHE INTERNAL "" FORCE - ) + set(HPX_WITH_PSEUDO_DEPENDENCIES_DEFAULT OFF) else() - set(HPX_WITH_PSEUDO_DEPENDENCIES - ON - CACHE INTERNAL "" FORCE - ) + set(HPX_WITH_PSEUDO_DEPENDENCIES_DEFAULT ON) endif() +hpx_option( + HPX_WITH_PSEUDO_DEPENDENCIES + BOOL + "Turn compiler warnings into errors (default: ${HPX_WITH_PSEUDO_DEPENDENCIES_DEFAULT})" + ${HPX_WITH_PSEUDO_DEPENDENCIES_DEFAULT} + ADVANCED +) + hpx_option( HPX_WITH_UNITY_BUILD BOOL "Enable unity build for certain build targets (default OFF)" OFF ADVANCED diff --git a/cmake/HPX_SetupAsio.cmake b/cmake/HPX_SetupAsio.cmake index d04b0f92dd77..42461b1acd91 100644 --- a/cmake/HPX_SetupAsio.cmake +++ b/cmake/HPX_SetupAsio.cmake @@ -46,8 +46,20 @@ elseif(NOT TARGET Asio::asio AND NOT HPX_FIND_PACKAGE) set(Asio_ROOT ${asio_SOURCE_DIR}) add_library(asio INTERFACE) + + # convert ASIO tag into CMake version + string(REGEX REPLACE "asio-([0-9]+)-([0-9]+)-([0-9]+)" "\\1.\\2.\\3" VERSION + "${HPX_WITH_ASIO_TAG}" + ) + + # starting v1.37.0 ASIO has changed its directory structure + set(asio_base_directory ${Asio_ROOT}/asio/include) + if(VERSION VERSION_GREATER "1.36.0") + set(asio_base_directory ${Asio_ROOT}/include) + endif() + target_include_directories( - asio SYSTEM INTERFACE $ + asio SYSTEM INTERFACE $ $ ) @@ -58,7 +70,7 @@ elseif(NOT TARGET Asio::asio AND NOT HPX_FIND_PACKAGE) ) install( - DIRECTORY ${Asio_ROOT}/asio/include/ + DIRECTORY ${asio_base_directory}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT core FILES_MATCHING diff --git a/cmake/HPX_SetupTarget.cmake b/cmake/HPX_SetupTarget.cmake index aee04abbbbd1..d21c6f4c2f70 100644 --- a/cmake/HPX_SetupTarget.cmake +++ b/cmake/HPX_SetupTarget.cmake @@ -264,23 +264,23 @@ function(hpx_setup_target target) target_compile_definitions( ${target} PRIVATE HPX_HAVE_FORCE_NO_CXX_MODULES ) - - # If modules are enabled, Clang emits DWARF v5, which requires using lld - # instead of ld. - if((NOT MSVC) - AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - AND (NOT (CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")) - ) - get_target_property(_type ${target} TYPE) - if((_type STREQUAL "SHARED_LIBRARY") OR (_type STREQUAL "EXECUTABLE")) - target_link_options(${target} PRIVATE "-fuse-ld=lld") - endif() - endif() endif() set_target_properties(${target} PROPERTIES CXX_SCAN_FOR_MODULES OFF) endif() + # Newer Clang emits DWARF v5, which requires using lld instead of ld. + if(HPX_WITH_CXX_MODULES + AND (NOT MSVC) + AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + AND (NOT (CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")) + ) + get_target_property(_type ${target} TYPE) + if((_type STREQUAL "SHARED_LIBRARY") OR (_type STREQUAL "EXECUTABLE")) + target_link_options(${target} PRIVATE "-fuse-ld=lld") + endif() + endif() + get_target_property(target_EXCLUDE_FROM_ALL ${target} EXCLUDE_FROM_ALL) if(target_EXPORT AND NOT target_EXCLUDE_FROM_ALL) diff --git a/components/component_storage/CMakeLists.txt b/components/component_storage/CMakeLists.txt index 80ca969a9fac..5a4040b6f8bb 100644 --- a/components/component_storage/CMakeLists.txt +++ b/components/component_storage/CMakeLists.txt @@ -50,5 +50,15 @@ add_hpx_pseudo_dependencies( components.component_storage component_storage_component ) +# MSVC V1951 and V1952 exposes ICE compiling this in C++20 module mode +if(HPX_WITH_CXX_MODULES + AND (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + AND ((MSVC_VERSION EQUAL 1951) OR (MSVC_VERSION EQUAL 1952)) +) + target_compile_definitions( + component_storage_component PRIVATE HPX_HAVE_FORCE_NO_CXX_MODULES + ) +endif() + add_subdirectory(tests) add_subdirectory(examples) diff --git a/components/component_storage/include/hpx/components/component_storage/server/migrate_from_storage.hpp b/components/component_storage/include/hpx/components/component_storage/server/migrate_from_storage.hpp index e876035c40bb..c2a8ec5d0421 100644 --- a/components/component_storage/include/hpx/components/component_storage/server/migrate_from_storage.hpp +++ b/components/component_storage/include/hpx/components/component_storage/server/migrate_from_storage.hpp @@ -11,8 +11,7 @@ #include #include #include -#include -#include +#include #include #include diff --git a/components/component_storage/src/server/component_storage_server.cpp b/components/component_storage/src/server/component_storage_server.cpp index 1371f46e9e6c..789928cde27a 100644 --- a/components/component_storage/src/server/component_storage_server.cpp +++ b/components/component_storage/src/server/component_storage_server.cpp @@ -5,9 +5,10 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include -#include #include -#include +#include + +#include #include diff --git a/components/containers/partitioned_vector/CMakeLists.txt b/components/containers/partitioned_vector/CMakeLists.txt index 88dc3a0eb227..0125ceed538b 100644 --- a/components/containers/partitioned_vector/CMakeLists.txt +++ b/components/containers/partitioned_vector/CMakeLists.txt @@ -63,5 +63,15 @@ add_hpx_pseudo_dependencies( components.containers.partitioned_vector partitioned_vector_component ) +# MSVC V1951 and V1952 exposes ICE compiling this in C++20 module mode +if(HPX_WITH_CXX_MODULES + AND (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + AND ((MSVC_VERSION EQUAL 1951) OR (MSVC_VERSION EQUAL 1952)) +) + target_compile_definitions( + partitioned_vector_component PRIVATE HPX_HAVE_FORCE_NO_CXX_MODULES + ) +endif() + add_subdirectory(tests) add_subdirectory(examples) diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/coarray/coarray.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/coarray/coarray.hpp index a2648b1f5801..b8f1741f2119 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/coarray/coarray.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/coarray/coarray.hpp @@ -10,10 +10,11 @@ #pragma once #include +#include +#include + #include #include -#include -#include #include #include diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp index 0489db6d80ea..d4666bcf44cd 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp index d90bb837349d..b1015c6d6e71 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/components/containers/partitioned_vector/tests/unit/partitioned_vector_subview.cpp b/components/containers/partitioned_vector/tests/unit/partitioned_vector_subview.cpp index 719254f2342c..25569c116d3e 100644 --- a/components/containers/partitioned_vector/tests/unit/partitioned_vector_subview.cpp +++ b/components/containers/partitioned_vector/tests/unit/partitioned_vector_subview.cpp @@ -7,13 +7,15 @@ #include #if !defined(HPX_COMPUTE_DEVICE_CODE) #include -#include -#include #include +#include +#include + #include #include -#include -#include + +#include +#include #include #include diff --git a/components/containers/partitioned_vector/tests/unit/partitioned_vector_view.cpp b/components/containers/partitioned_vector/tests/unit/partitioned_vector_view.cpp index eca7307427a4..dac70842ef3c 100644 --- a/components/containers/partitioned_vector/tests/unit/partitioned_vector_view.cpp +++ b/components/containers/partitioned_vector/tests/unit/partitioned_vector_view.cpp @@ -7,14 +7,16 @@ #include #if !defined(HPX_COMPUTE_DEVICE_CODE) #include -#include -#include #include -#include -#include #include +#include #include -#include + +#include +#include + +#include +#include #include #include diff --git a/components/containers/partitioned_vector/tests/unit/partitioned_vector_view_iterator.cpp b/components/containers/partitioned_vector/tests/unit/partitioned_vector_view_iterator.cpp index 56fd139dc693..5166c3969947 100644 --- a/components/containers/partitioned_vector/tests/unit/partitioned_vector_view_iterator.cpp +++ b/components/containers/partitioned_vector/tests/unit/partitioned_vector_view_iterator.cpp @@ -8,10 +8,11 @@ #if !defined(HPX_COMPUTE_DEVICE_CODE) #include #include +#include +#include + #include #include -#include -#include #include #include diff --git a/components/containers/unordered/CMakeLists.txt b/components/containers/unordered/CMakeLists.txt index a48f323d9758..f2839aa37560 100644 --- a/components/containers/unordered/CMakeLists.txt +++ b/components/containers/unordered/CMakeLists.txt @@ -37,5 +37,15 @@ add_hpx_component( add_hpx_pseudo_dependencies(components.containers.unordered unordered_component) +# MSVC V1951 and V1952 exposes ICE compiling this in C++20 module mode +if(HPX_WITH_CXX_MODULES + AND (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + AND ((MSVC_VERSION EQUAL 1951) OR (MSVC_VERSION EQUAL 1952)) +) + target_compile_definitions( + unordered_component PRIVATE HPX_HAVE_FORCE_NO_CXX_MODULES + ) +endif() + add_subdirectory(tests) add_subdirectory(examples) diff --git a/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp b/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp index 2b3c019ad844..24f298bb1955 100644 --- a/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp +++ b/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp @@ -17,9 +17,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/components/iostreams/CMakeLists.txt b/components/iostreams/CMakeLists.txt index 008f5dba210a..8aab92a552d0 100644 --- a/components/iostreams/CMakeLists.txt +++ b/components/iostreams/CMakeLists.txt @@ -50,5 +50,15 @@ target_compile_definitions( add_hpx_pseudo_dependencies(components.iostreams iostreams_component) +# MSVC V1951 and V1952 exposes ICE compiling this in C++20 module mode +if(HPX_WITH_CXX_MODULES + AND (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + AND ((MSVC_VERSION EQUAL 1951) OR (MSVC_VERSION EQUAL 1952)) +) + target_compile_definitions( + iostreams_component PRIVATE HPX_HAVE_FORCE_NO_CXX_MODULES + ) +endif() + add_subdirectory(tests) add_subdirectory(examples) diff --git a/components/iostreams/src/server/output_stream.cpp b/components/iostreams/src/server/output_stream.cpp index 29bd20e4b307..cd389fadf1c6 100644 --- a/components/iostreams/src/server/output_stream.cpp +++ b/components/iostreams/src/server/output_stream.cpp @@ -9,9 +9,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/components/iostreams/src/standard_streams.cpp b/components/iostreams/src/standard_streams.cpp index 179128074193..ef3f4a9afcee 100644 --- a/components/iostreams/src/standard_streams.cpp +++ b/components/iostreams/src/standard_streams.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include diff --git a/components/process/CMakeLists.txt b/components/process/CMakeLists.txt index 3ecd0c21195c..73ed40f70868 100644 --- a/components/process/CMakeLists.txt +++ b/components/process/CMakeLists.txt @@ -138,5 +138,15 @@ target_compile_definitions(process_component PRIVATE HPX_PROCESS_EXPORTS) add_hpx_pseudo_dependencies(components.process process_component) +# MSVC V1951 and V1952 exposes ICE compiling this in C++20 module mode +if(HPX_WITH_CXX_MODULES + AND (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + AND ((MSVC_VERSION EQUAL 1951) OR (MSVC_VERSION EQUAL 1952)) +) + target_compile_definitions( + process_component PRIVATE HPX_HAVE_FORCE_NO_CXX_MODULES + ) +endif() + add_subdirectory(tests) add_subdirectory(examples) diff --git a/docs/sphinx/manual/writing_distributed_hpx_applications.rst b/docs/sphinx/manual/writing_distributed_hpx_applications.rst index 04267cf74fb6..76d111f0fb10 100644 --- a/docs/sphinx/manual/writing_distributed_hpx_applications.rst +++ b/docs/sphinx/manual/writing_distributed_hpx_applications.rst @@ -897,7 +897,7 @@ An example of how to use the ``partitioned_vector`` container with distribution policies would be:: #include - #include + #include // The following code generates all necessary boiler plate to enable the // remote creation of 'partitioned_vector' segments diff --git a/examples/quickstart/CMakeLists.txt b/examples/quickstart/CMakeLists.txt index b9d560677d64..83fdcdf6f4ff 100644 --- a/examples/quickstart/CMakeLists.txt +++ b/examples/quickstart/CMakeLists.txt @@ -192,7 +192,16 @@ foreach(example_program ${example_programs}) endforeach() if(HPX_WITH_CXX_MODULES AND MSVC) - foreach(example customize_async enumerate_threads mutex_docs) + foreach( + example + customize_async + component_ctors + component_in_executable + component_with_executor + custom_serialization + enumerate_threads + mutex_docs + ) target_compile_definitions(${example} PRIVATE HPX_HAVE_FORCE_NO_CXX_MODULES) endforeach() endif() diff --git a/libs/core/algorithms/include/hpx/parallel/algorithms/detail/transfer.hpp b/libs/core/algorithms/include/hpx/parallel/algorithms/detail/transfer.hpp index 56fc2f398b99..4038ea572d4c 100644 --- a/libs/core/algorithms/include/hpx/parallel/algorithms/detail/transfer.hpp +++ b/libs/core/algorithms/include/hpx/parallel/algorithms/detail/transfer.hpp @@ -59,10 +59,10 @@ namespace hpx::parallel { #if !defined(HPX_COMPUTE_DEVICE_CODE) // forward declare segmented version - HPX_CXX_CORE_EXPORT template - typename util::detail::algorithm_result>::type + template + util::detail::algorithm_result_t> transfer_(ExPolicy&& policy, FwdIter1 first, Sent1 last, FwdIter2 dest, std::true_type); #endif @@ -130,7 +130,7 @@ namespace hpx::parallel { return transfer_(HPX_FORWARD(ExPolicy, policy), first, last, dest, std::false_type()); #else - typedef hpx::traits::is_segmented_iterator is_segmented; + using is_segmented = hpx::traits::is_segmented_iterator; return transfer_(HPX_FORWARD(ExPolicy, policy), first, last, dest, is_segmented()); diff --git a/libs/core/algorithms/tests/regressions/scan_different_inits.cpp b/libs/core/algorithms/tests/regressions/scan_different_inits.cpp index 47b5a949361d..a8fccc5c9dc4 100644 --- a/libs/core/algorithms/tests/regressions/scan_different_inits.cpp +++ b/libs/core/algorithms/tests/regressions/scan_different_inits.cpp @@ -99,26 +99,19 @@ void test_one(std::vector a) auto fun_conv = [](int foo) { return foo - 3; }; auto policy = hpx::execution::par; - Iter f_inc_add = + [[maybe_unused]] Iter f_inc_add = hpx::inclusive_scan(policy, a.begin(), a.end(), b.begin(), fun_add, 10); - Iter f_inc_mult = hpx::inclusive_scan( + [[maybe_unused]] Iter f_inc_mult = hpx::inclusive_scan( policy, a.begin(), a.end(), c.begin(), fun_mult, 10); - Iter f_exc_add = + [[maybe_unused]] Iter f_exc_add = hpx::exclusive_scan(policy, a.begin(), a.end(), d.begin(), 10, fun_add); - Iter f_exc_mult = hpx::exclusive_scan( + [[maybe_unused]] Iter f_exc_mult = hpx::exclusive_scan( policy, a.begin(), a.end(), e.begin(), 10, fun_mult); - Iter f_transform_inc = hpx::transform_inclusive_scan( + [[maybe_unused]] Iter f_transform_inc = hpx::transform_inclusive_scan( policy, a.begin(), a.end(), f.begin(), fun_add, fun_conv, 10); - Iter f_transform_exc = hpx::transform_exclusive_scan( + [[maybe_unused]] Iter f_transform_exc = hpx::transform_exclusive_scan( policy, a.begin(), a.end(), g.begin(), 10, fun_add, fun_conv); - HPX_UNUSED(f_inc_add); - HPX_UNUSED(f_inc_mult); - HPX_UNUSED(f_exc_add); - HPX_UNUSED(f_exc_mult); - HPX_UNUSED(f_transform_inc); - HPX_UNUSED(f_transform_exc); - hpx::parallel::detail::sequential_inclusive_scan( a.begin(), a.end(), b_ans.begin(), 10, fun_add); hpx::parallel::detail::sequential_inclusive_scan( diff --git a/libs/core/algorithms/tests/regressions/scan_shortlength.cpp b/libs/core/algorithms/tests/regressions/scan_shortlength.cpp index 30e90eceba64..19246100865f 100644 --- a/libs/core/algorithms/tests/regressions/scan_shortlength.cpp +++ b/libs/core/algorithms/tests/regressions/scan_shortlength.cpp @@ -75,17 +75,13 @@ void test_one(std::vector a) std::vector b(n), c(n), d(n); std::vector b_ans(n), c_ans(n), d_ans(n); - auto p_copy_if = hpx::ranges::copy_if(par, a.begin(), a.end(), b.begin(), - [](int bar) { return bar % 2 == 1; }); - auto p_remove_copy_if = hpx::remove_copy_if(par, a.begin(), a.end(), - c.begin(), [](int bar) { return bar % 2 != 1; }); - auto p_remove_copy = + [[maybe_unused]] auto p_copy_if = hpx::ranges::copy_if(par, a.begin(), + a.end(), b.begin(), [](int bar) { return bar % 2 == 1; }); + [[maybe_unused]] auto p_remove_copy_if = hpx::remove_copy_if(par, a.begin(), + a.end(), c.begin(), [](int bar) { return bar % 2 != 1; }); + [[maybe_unused]] auto p_remove_copy = hpx::remove_copy(par, a.begin(), a.end(), d.begin(), 0); - HPX_UNUSED(p_copy_if); - HPX_UNUSED(p_remove_copy_if); - HPX_UNUSED(p_remove_copy); - std::copy_if(a.begin(), a.end(), b_ans.begin(), [](int bar) { return bar % 2 == 1; }); std::remove_copy_if(a.begin(), a.end(), c_ans.begin(), diff --git a/libs/core/execution/include/hpx/execution/algorithms/detail/sync_wait_domain.hpp b/libs/core/execution/include/hpx/execution/algorithms/detail/sync_wait_domain.hpp index ed204f206dd7..410731ba7527 100644 --- a/libs/core/execution/include/hpx/execution/algorithms/detail/sync_wait_domain.hpp +++ b/libs/core/execution/include/hpx/execution/algorithms/detail/sync_wait_domain.hpp @@ -74,7 +74,7 @@ namespace hpx::execution::experimental::detail { inline constexpr bool sync_wait_can_query_attrs_completion_scheduler_v = false; - HPX_CXX_CORE_EXPORT template + template inline constexpr bool sync_wait_can_query_attrs_completion_scheduler_v< Sender, std::enable_if_t< @@ -89,7 +89,7 @@ namespace hpx::execution::experimental::detail { .get_scheduler())>; }; - HPX_CXX_CORE_EXPORT template + template struct sync_wait_rcv_scheduler_impl::value>> @@ -100,7 +100,7 @@ namespace hpx::execution::experimental::detail { HPX_CXX_CORE_EXPORT template using sync_wait_rcv_scheduler_t = - typename sync_wait_rcv_scheduler_impl::type; + sync_wait_rcv_scheduler_impl::type; // Receiver env: exposes a stdexec run_loop scheduler via the standard // get_scheduler / get_delegation_scheduler queries so dependent senders @@ -188,7 +188,7 @@ namespace hpx::execution::experimental::detail { HPX_CXX_CORE_EXPORT template struct first_alternative; - HPX_CXX_CORE_EXPORT template + template struct first_alternative> { using type = T; diff --git a/libs/core/execution/tests/unit/executor_parameters_partition_hooks.cpp b/libs/core/execution/tests/unit/executor_parameters_partition_hooks.cpp index 95db2245b7ed..e5846e77764d 100644 --- a/libs/core/execution/tests/unit/executor_parameters_partition_hooks.cpp +++ b/libs/core/execution/tests/unit/executor_parameters_partition_hooks.cpp @@ -102,8 +102,7 @@ void test_mark_partition_async() hpx::execution::par(hpx::execution::task).with(std::ref(params)); auto f = hpx::merge(policy, left.begin(), left.end(), right.begin(), right.end(), out.begin()); - auto result_iter = f.get(); - HPX_UNUSED(result_iter); + [[maybe_unused]] auto result_iter = f.get(); HPX_TEST(std::is_sorted(out.begin(), out.end())); HPX_TEST_LT(std::size_t(0), params.num_chunks_); diff --git a/libs/core/executors/include/hpx/executors/parallel_executor.hpp b/libs/core/executors/include/hpx/executors/parallel_executor.hpp index 2c8820ba093f..324ca5cfe5b1 100644 --- a/libs/core/executors/include/hpx/executors/parallel_executor.hpp +++ b/libs/core/executors/include/hpx/executors/parallel_executor.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2019-2020 ETH Zurich -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2019 Agustin Berge // // SPDX-License-Identifier: BSL-1.0 @@ -10,9 +10,6 @@ #include #include -#include -#include -#include #include #include #include @@ -26,13 +23,16 @@ #include #include +#include +#include +#include + #include #include #include #include #include #include -#include namespace hpx::parallel::execution::detail { diff --git a/libs/core/executors/include/hpx/executors/parallel_scheduler.hpp b/libs/core/executors/include/hpx/executors/parallel_scheduler.hpp index 86b7937bbe5c..442d500ca68d 100644 --- a/libs/core/executors/include/hpx/executors/parallel_scheduler.hpp +++ b/libs/core/executors/include/hpx/executors/parallel_scheduler.hpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -228,7 +227,7 @@ namespace hpx::execution::experimental { { using type = concrete_proxy; }; - using proxy_t = typename proxy_for_tuple::type; + using proxy_t = proxy_for_tuple::type; // ---- Inline proxy storage ------------------------------------ // Eliminates the second heap allocation that make_unique @@ -866,7 +865,7 @@ namespace hpx::execution::experimental { { } - friend parallel_scheduler get_parallel_scheduler(); + friend HPX_CORE_EXPORT parallel_scheduler get_parallel_scheduler(); std::shared_ptr backend_; }; diff --git a/libs/core/lock_registration/include/hpx/lock_registration/detail/register_locks.hpp b/libs/core/lock_registration/include/hpx/lock_registration/detail/register_locks.hpp index 2eba748efab7..1289155a7dcf 100644 --- a/libs/core/lock_registration/include/hpx/lock_registration/detail/register_locks.hpp +++ b/libs/core/lock_registration/include/hpx/lock_registration/detail/register_locks.hpp @@ -38,7 +38,7 @@ namespace hpx::util { namespace detail { - HPX_CXX_CORE_EXPORT struct HPX_CORE_EXPORT lock_data + struct HPX_CORE_EXPORT lock_data { explicit lock_data(std::size_t trace_depth); lock_data(register_lock_data* data, std::size_t trace_depth); @@ -187,7 +187,7 @@ namespace hpx::util { bool owns_registration_; }; - HPX_CXX_CORE_EXPORT template + template struct ignore_while_checking && !detail::has_owns_lock_v>> @@ -251,44 +251,39 @@ namespace hpx::util { constexpr ignore_all_while_checking() noexcept {} }; - HPX_CXX_CORE_EXPORT constexpr inline bool register_lock( + HPX_CXX_CORE_EXPORT constexpr bool register_lock( void const*, util::register_lock_data* = nullptr) noexcept { return true; } - HPX_CXX_CORE_EXPORT constexpr inline bool unregister_lock( - void const*) noexcept + HPX_CXX_CORE_EXPORT constexpr bool unregister_lock(void const*) noexcept { return true; } - HPX_CXX_CORE_EXPORT constexpr inline void verify_no_locks() noexcept {} - HPX_CXX_CORE_EXPORT constexpr inline void force_error_on_lock() noexcept {} - HPX_CXX_CORE_EXPORT constexpr inline void enable_lock_detection() noexcept - { - } - HPX_CXX_CORE_EXPORT constexpr inline void disable_lock_detection() noexcept - { - } - HPX_CXX_CORE_EXPORT constexpr inline void trace_depth_lock_detection( + HPX_CXX_CORE_EXPORT constexpr void verify_no_locks() noexcept {} + HPX_CXX_CORE_EXPORT constexpr void force_error_on_lock() noexcept {} + HPX_CXX_CORE_EXPORT constexpr void enable_lock_detection() noexcept {} + HPX_CXX_CORE_EXPORT constexpr void disable_lock_detection() noexcept {} + HPX_CXX_CORE_EXPORT constexpr void trace_depth_lock_detection( std::size_t /*value*/) noexcept { } - HPX_CXX_CORE_EXPORT constexpr inline bool ignore_lock( + HPX_CXX_CORE_EXPORT constexpr bool ignore_lock( void const* /*lock*/) noexcept { return true; } - HPX_CXX_CORE_EXPORT constexpr inline bool reset_ignored( + HPX_CXX_CORE_EXPORT constexpr bool reset_ignored( void const* /*lock*/) noexcept { return true; } - HPX_CXX_CORE_EXPORT constexpr inline bool ignore_all_locks() noexcept + HPX_CXX_CORE_EXPORT constexpr bool ignore_all_locks() noexcept { return true; } - HPX_CXX_CORE_EXPORT constexpr inline bool reset_ignored_all() noexcept + HPX_CXX_CORE_EXPORT constexpr bool reset_ignored_all() noexcept { return true; } @@ -297,13 +292,13 @@ namespace hpx::util { { }; - HPX_CXX_CORE_EXPORT constexpr inline held_locks_data* + HPX_CXX_CORE_EXPORT constexpr held_locks_data* get_held_locks_data() noexcept { return nullptr; } - HPX_CXX_CORE_EXPORT constexpr inline void set_held_locks_data( + HPX_CXX_CORE_EXPORT constexpr void set_held_locks_data( held_locks_data*) noexcept { } diff --git a/libs/core/type_support/include/hpx/type_support/is_replaceable.hpp b/libs/core/type_support/include/hpx/type_support/is_replaceable.hpp index 418f2a710020..4064766bf44e 100644 --- a/libs/core/type_support/include/hpx/type_support/is_replaceable.hpp +++ b/libs/core/type_support/include/hpx/type_support/is_replaceable.hpp @@ -39,12 +39,12 @@ namespace hpx::experimental { { }; - HPX_CXX_CORE_EXPORT template + template struct is_replaceable : std::false_type { }; - HPX_CXX_CORE_EXPORT template + template struct is_replaceable : std::false_type { }; diff --git a/libs/full/actions/include/hpx/actions/post_helper.hpp b/libs/full/actions/include/hpx/actions/post_helper.hpp index 51613dd5b47d..c5b9d105a70b 100644 --- a/libs/full/actions/include/hpx/actions/post_helper.hpp +++ b/libs/full/actions/include/hpx/actions/post_helper.hpp @@ -102,7 +102,7 @@ namespace hpx::detail { } /////////////////////////////////////////////////////////////////////////// - HPX_CXX_EXPORT template + template struct post_helper { template @@ -151,7 +151,7 @@ namespace hpx::detail { }; /////////////////////////////////////////////////////////////////////////// - HPX_CXX_EXPORT template + template struct post_helper { // If local and to be directly executed, just call the function diff --git a/libs/full/actions_base/include/hpx/actions_base/component_action.hpp b/libs/full/actions_base/include/hpx/actions_base/component_action.hpp index 8c9245ba9c37..b2acfd4432b9 100644 --- a/libs/full/actions_base/include/hpx/actions_base/component_action.hpp +++ b/libs/full/actions_base/include/hpx/actions_base/component_action.hpp @@ -72,9 +72,8 @@ namespace hpx::actions { } // namespace detail /////////////////////////////////////////////////////////////////////////// - // Specialized generic non-const component action types allowing to hold - // a different number of arguments - /////////////////////////////////////////////////////////////////////////// + // Specialized generic non-const component action types allowing to hold an + // arbitrary number of arguments template struct action @@ -104,13 +103,12 @@ namespace hpx::actions { }; /////////////////////////////////////////////////////////////////////////// - // Specialized generic const component action types allowing to hold a - // different number of arguments - /////////////////////////////////////////////////////////////////////////// + // Specialized generic const component action types allowing to hold an + // arbitrary number of arguments template struct action - : basic_action, Derived>> { @@ -127,18 +125,17 @@ namespace hpx::actions { static R invoke(naming::address_type lva, naming::component_type comptype, Ts&&... vs) { - basic_action::increment_invocation_count(); - return detail::component_invoke( + return detail::component_invoke( lva, comptype, F, HPX_FORWARD(Ts, vs)...); } }; /////////////////////////////////////////////////////////////////////////// // Specialized generic non-const noexcept component action types allowing - // to hold a different number of arguments - /////////////////////////////////////////////////////////////////////////// + // to hold an arbitrary number of arguments template struct action @@ -169,11 +166,11 @@ namespace hpx::actions { /////////////////////////////////////////////////////////////////////////// // Specialized generic const noexcept component action types allowing to - // hold a different number of arguments + // hold an arbitrary number of arguments template struct action - : basic_action, Derived>> @@ -191,10 +188,10 @@ namespace hpx::actions { static R invoke(naming::address_type lva, naming::component_type comptype, Ts&&... vs) { - basic_action::increment_invocation_count(); - return detail::component_invoke( + return detail::component_invoke( lva, comptype, F, HPX_FORWARD(Ts, vs)...); } }; diff --git a/libs/full/checkpoint/include/hpx/checkpoint/checkpoint.hpp b/libs/full/checkpoint/include/hpx/checkpoint/checkpoint.hpp index b752a322e598..667387c56a45 100644 --- a/libs/full/checkpoint/include/hpx/checkpoint/checkpoint.hpp +++ b/libs/full/checkpoint/include/hpx/checkpoint/checkpoint.hpp @@ -23,8 +23,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/libs/full/collectives/include/hpx/collectives/detail/latch.hpp b/libs/full/collectives/include/hpx/collectives/detail/latch.hpp index a8cb6f92c51a..e89823b6ba23 100644 --- a/libs/full/collectives/include/hpx/collectives/detail/latch.hpp +++ b/libs/full/collectives/include/hpx/collectives/detail/latch.hpp @@ -12,10 +12,10 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/libs/full/collectives/src/create_communicator.cpp b/libs/full/collectives/src/create_communicator.cpp index ea67309e9d1b..dfbe8e5db9d7 100644 --- a/libs/full/collectives/src/create_communicator.cpp +++ b/libs/full/collectives/src/create_communicator.cpp @@ -20,9 +20,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/libs/full/collectives/src/latch.cpp b/libs/full/collectives/src/latch.cpp index c3bcc52e1d09..0ace576663ee 100644 --- a/libs/full/collectives/src/latch.cpp +++ b/libs/full/collectives/src/latch.cpp @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include diff --git a/libs/full/compute/include/hpx/compute/host/distributed_target.hpp b/libs/full/compute/include/hpx/compute/host/distributed_target.hpp index 3820e3e9c32d..654d04b3574d 100644 --- a/libs/full/compute/include/hpx/compute/host/distributed_target.hpp +++ b/libs/full/compute/include/hpx/compute/host/distributed_target.hpp @@ -14,9 +14,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/libs/full/compute/src/get_host_targets.cpp b/libs/full/compute/src/get_host_targets.cpp index 23f9da2fae5a..a076f0a8506d 100644 --- a/libs/full/compute/src/get_host_targets.cpp +++ b/libs/full/compute/src/get_host_targets.cpp @@ -14,10 +14,10 @@ #include #include #include +#include #include #include #include -#include #include diff --git a/libs/full/include/include/hpx/include/applier.hpp b/libs/full/include/include/hpx/include/applier.hpp index 51fcde4f1d22..6af893f1ba44 100644 --- a/libs/full/include/include/hpx/include/applier.hpp +++ b/libs/full/include/include/hpx/include/applier.hpp @@ -10,4 +10,4 @@ #include #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/client.hpp b/libs/full/include/include/hpx/include/client.hpp index 9f3097d895bc..d6baad0d3dae 100644 --- a/libs/full/include/include/hpx/include/client.hpp +++ b/libs/full/include/include/hpx/include/client.hpp @@ -10,4 +10,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/components.hpp b/libs/full/include/include/hpx/include/components.hpp index ffb1ae5f058a..84158c43dfe4 100644 --- a/libs/full/include/include/hpx/include/components.hpp +++ b/libs/full/include/include/hpx/include/components.hpp @@ -16,8 +16,4 @@ #include #include #include - -#include -#include -#include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_adjacent_difference.hpp b/libs/full/include/include/hpx/include/parallel_adjacent_difference.hpp index f8f69c55e980..4ce4c7fc5349 100644 --- a/libs/full/include/include/hpx/include/parallel_adjacent_difference.hpp +++ b/libs/full/include/include/hpx/include/parallel_adjacent_difference.hpp @@ -8,5 +8,4 @@ #include #include - -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_adjacent_find.hpp b/libs/full/include/include/hpx/include/parallel_adjacent_find.hpp index 7e9c3841ac99..d96bd0512c17 100644 --- a/libs/full/include/include/hpx/include/parallel_adjacent_find.hpp +++ b/libs/full/include/include/hpx/include/parallel_adjacent_find.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_all_any_none_of.hpp b/libs/full/include/include/hpx/include/parallel_all_any_none_of.hpp index 15b2b7c025da..d96bd0512c17 100644 --- a/libs/full/include/include/hpx/include/parallel_all_any_none_of.hpp +++ b/libs/full/include/include/hpx/include/parallel_all_any_none_of.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_copy.hpp b/libs/full/include/include/hpx/include/parallel_copy.hpp index ab47416c6cba..70ebd807ac85 100644 --- a/libs/full/include/include/hpx/include/parallel_copy.hpp +++ b/libs/full/include/include/hpx/include/parallel_copy.hpp @@ -8,4 +8,4 @@ #pragma once #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_count.hpp b/libs/full/include/include/hpx/include/parallel_count.hpp index 97ba1f763cda..6210ef02ddc3 100644 --- a/libs/full/include/include/hpx/include/parallel_count.hpp +++ b/libs/full/include/include/hpx/include/parallel_count.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_execution.hpp b/libs/full/include/include/hpx/include/parallel_execution.hpp index cab868bc4e64..f941dfd52804 100644 --- a/libs/full/include/include/hpx/include/parallel_execution.hpp +++ b/libs/full/include/include/hpx/include/parallel_execution.hpp @@ -8,4 +8,3 @@ #include #include -#include diff --git a/libs/full/include/include/hpx/include/parallel_executor_information.hpp b/libs/full/include/include/hpx/include/parallel_executor_information.hpp index 5e0a0ed376e2..00d7332c6fc9 100644 --- a/libs/full/include/include/hpx/include/parallel_executor_information.hpp +++ b/libs/full/include/include/hpx/include/parallel_executor_information.hpp @@ -7,5 +7,4 @@ #pragma once #include - #include diff --git a/libs/full/include/include/hpx/include/parallel_fill.hpp b/libs/full/include/include/hpx/include/parallel_fill.hpp index dd63e8a1fc1a..d96bd0512c17 100644 --- a/libs/full/include/include/hpx/include/parallel_fill.hpp +++ b/libs/full/include/include/hpx/include/parallel_fill.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_find.hpp b/libs/full/include/include/hpx/include/parallel_find.hpp index 0cd5b2b9e0f4..d96bd0512c17 100644 --- a/libs/full/include/include/hpx/include/parallel_find.hpp +++ b/libs/full/include/include/hpx/include/parallel_find.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_for_each.hpp b/libs/full/include/include/hpx/include/parallel_for_each.hpp index dc1644843942..70ebd807ac85 100644 --- a/libs/full/include/include/hpx/include/parallel_for_each.hpp +++ b/libs/full/include/include/hpx/include/parallel_for_each.hpp @@ -8,4 +8,4 @@ #pragma once #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_generate.hpp b/libs/full/include/include/hpx/include/parallel_generate.hpp index e09267c5a4e9..2b12b06aa803 100644 --- a/libs/full/include/include/hpx/include/parallel_generate.hpp +++ b/libs/full/include/include/hpx/include/parallel_generate.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_is_partitioned.hpp b/libs/full/include/include/hpx/include/parallel_is_partitioned.hpp index 28b827b96e66..f3276b48fba9 100644 --- a/libs/full/include/include/hpx/include/parallel_is_partitioned.hpp +++ b/libs/full/include/include/hpx/include/parallel_is_partitioned.hpp @@ -7,4 +7,4 @@ #pragma once #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_is_sorted.hpp b/libs/full/include/include/hpx/include/parallel_is_sorted.hpp index 9e43c8646236..f3276b48fba9 100644 --- a/libs/full/include/include/hpx/include/parallel_is_sorted.hpp +++ b/libs/full/include/include/hpx/include/parallel_is_sorted.hpp @@ -7,4 +7,4 @@ #pragma once #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_minmax.hpp b/libs/full/include/include/hpx/include/parallel_minmax.hpp index b3fece645488..2b12b06aa803 100644 --- a/libs/full/include/include/hpx/include/parallel_minmax.hpp +++ b/libs/full/include/include/hpx/include/parallel_minmax.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_reduce.hpp b/libs/full/include/include/hpx/include/parallel_reduce.hpp index 3d3e706c6e93..d96bd0512c17 100644 --- a/libs/full/include/include/hpx/include/parallel_reduce.hpp +++ b/libs/full/include/include/hpx/include/parallel_reduce.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_replace.hpp b/libs/full/include/include/hpx/include/parallel_replace.hpp index 42fa09f011f0..a239ce8aa1e7 100644 --- a/libs/full/include/include/hpx/include/parallel_replace.hpp +++ b/libs/full/include/include/hpx/include/parallel_replace.hpp @@ -8,5 +8,4 @@ #pragma once #include -#include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_scan.hpp b/libs/full/include/include/hpx/include/parallel_scan.hpp index e7db28f766a2..7a9413133ce8 100644 --- a/libs/full/include/include/hpx/include/parallel_scan.hpp +++ b/libs/full/include/include/hpx/include/parallel_scan.hpp @@ -8,5 +8,4 @@ #include #include -#include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_transform.hpp b/libs/full/include/include/hpx/include/parallel_transform.hpp index 6c494e5c0b59..d96bd0512c17 100644 --- a/libs/full/include/include/hpx/include/parallel_transform.hpp +++ b/libs/full/include/include/hpx/include/parallel_transform.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_transform_reduce.hpp b/libs/full/include/include/hpx/include/parallel_transform_reduce.hpp index fce2a333b176..d96bd0512c17 100644 --- a/libs/full/include/include/hpx/include/parallel_transform_reduce.hpp +++ b/libs/full/include/include/hpx/include/parallel_transform_reduce.hpp @@ -9,4 +9,4 @@ #include #include -#include +#include diff --git a/libs/full/include/include/hpx/include/parallel_transform_scan.hpp b/libs/full/include/include/hpx/include/parallel_transform_scan.hpp index 4d9d89077c1a..7a9413133ce8 100644 --- a/libs/full/include/include/hpx/include/parallel_transform_scan.hpp +++ b/libs/full/include/include/hpx/include/parallel_transform_scan.hpp @@ -8,5 +8,4 @@ #include #include -#include -#include +#include diff --git a/libs/full/include/include/hpx/include/runtime.hpp b/libs/full/include/include/hpx/include/runtime.hpp index 71dead2c9073..648cf65208c4 100644 --- a/libs/full/include/include/hpx/include/runtime.hpp +++ b/libs/full/include/include/hpx/include/runtime.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2012 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -18,4 +18,3 @@ #include #include #include -#include diff --git a/libs/full/include/include/hpx/runtime.hpp b/libs/full/include/include/hpx/runtime.hpp index bcd35890131f..857ca4e7e37a 100644 --- a/libs/full/include/include/hpx/runtime.hpp +++ b/libs/full/include/include/hpx/runtime.hpp @@ -6,5 +6,5 @@ #pragma once +#include #include -#include diff --git a/libs/full/init_runtime/src/hpx_init.cpp b/libs/full/init_runtime/src/hpx_init.cpp index 0cf242beb0bf..58ed3661930c 100644 --- a/libs/full/init_runtime/src/hpx_init.cpp +++ b/libs/full/init_runtime/src/hpx_init.cpp @@ -55,9 +55,7 @@ #include #endif #include -#include -#include -#include +#include #endif #if defined(HPX_HAVE_LOGGING) #include diff --git a/libs/full/init_runtime/src/pre_main.cpp b/libs/full/init_runtime/src/pre_main.cpp index 09a028c803ae..2a96e0da3941 100644 --- a/libs/full/init_runtime/src/pre_main.cpp +++ b/libs/full/init_runtime/src/pre_main.cpp @@ -22,11 +22,8 @@ #include #include #include +#include #include -#include -#include -#include -#include #include diff --git a/libs/full/parcelset/tests/regressions/very_big_tchunk.cpp b/libs/full/parcelset/tests/regressions/very_big_tchunk.cpp index ee71c1bd2223..7a8271d02eed 100644 --- a/libs/full/parcelset/tests/regressions/very_big_tchunk.cpp +++ b/libs/full/parcelset/tests/regressions/very_big_tchunk.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include class Data { diff --git a/libs/full/runtime_components/include/hpx/runtime_components/macros.hpp b/libs/full/runtime_components/include/hpx/runtime_components/macros.hpp index fb677cb36ad5..bd066cd1eba6 100644 --- a/libs/full/runtime_components/include/hpx/runtime_components/macros.hpp +++ b/libs/full/runtime_components/include/hpx/runtime_components/macros.hpp @@ -11,6 +11,7 @@ #include #include +#include #if !defined(HPX_COMPUTE_DEVICE_CODE) diff --git a/libs/full/runtime_distributed/CMakeLists.txt b/libs/full/runtime_distributed/CMakeLists.txt index 914e1887ee0a..5bab6b53528b 100644 --- a/libs/full/runtime_distributed/CMakeLists.txt +++ b/libs/full/runtime_distributed/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 The STE||AR-Group +# Copyright (c) 2019-2026 The STE||AR-Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -59,6 +59,7 @@ include(HPX_AddModule) add_hpx_module( full runtime_distributed GLOBAL_HEADER_GEN ON + GLOBAL_HEADER_MODULE_GEN ON SOURCES ${runtime_distributed_sources} HEADERS ${runtime_distributed_headers} COMPAT_HEADERS ${runtime_distributed_compat_headers} diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed.hpp index 2eaae63cbadd..aa712e43509e 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2023 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -41,7 +41,7 @@ namespace hpx { /// The \a runtime class encapsulates the HPX runtime system in a simple to /// use way. It makes sure all required parts of the HPX runtime system are /// properly initialized. - class HPX_EXPORT runtime_distributed : public runtime + HPX_CXX_EXPORT class HPX_EXPORT runtime_distributed : public runtime { public: /// Construct a new HPX runtime instance diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier.hpp index 35912b949a27..69071cba660a 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2007-2008 Anshul Tandon -// Copyright (c) 2007-2012 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -9,29 +9,33 @@ #pragma once #include -#include // this needs to go first - #include #include #include #include #include +#include // this needs to go first + #include #include #include #include -namespace hpx { namespace applier { +namespace hpx::applier { + /// The \a applier class is used to decide whether a particular action /// has to be issued on a local or a remote resource. If the target /// component is local a new \a thread will be created, if the target is /// remote a parcel will be sent. - class HPX_EXPORT applier + HPX_CXX_EXPORT class HPX_EXPORT applier { public: - HPX_NON_COPYABLE(applier); + applier(applier const&) = delete; + applier(applier&&) = delete; + applier& operator=(applier const&) = delete; + applier& operator=(applier&&) = delete; public: // constructor @@ -153,6 +157,6 @@ namespace hpx { namespace applier { threads::threadmanager* thread_manager_; hpx::id_type runtime_support_id_; }; -}} // namespace hpx::applier +} // namespace hpx::applier #include diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier_fwd.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier_fwd.hpp index fe57ee9647b3..881f924e9f69 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier_fwd.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/applier_fwd.hpp @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2014 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -13,22 +13,24 @@ #include namespace hpx { + /// \namespace applier /// /// The namespace \a applier contains all definitions needed for the /// class \a hpx#applier#applier and its related functionality. This /// namespace is part of the HPX core module. namespace applier { - class HPX_EXPORT applier; + + HPX_CXX_EXPORT class HPX_EXPORT applier; /// The function \a get_applier returns a reference to the (thread /// specific) applier instance. - HPX_EXPORT applier& get_applier(); + HPX_CXX_EXPORT HPX_EXPORT applier& get_applier(); /// The function \a get_applier returns a pointer to the (thread /// specific) applier instance. The returned pointer is NULL if the /// current thread is not known to HPX or if the runtime system is not /// active. - HPX_EXPORT applier* get_applier_ptr(); + HPX_CXX_EXPORT HPX_EXPORT applier* get_applier_ptr(); } // namespace applier } // namespace hpx diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/big_boot_barrier.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/big_boot_barrier.hpp index 48e4b62ae397..91ca51b448e6 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/big_boot_barrier.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/big_boot_barrier.hpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2011 Bryce Lelbach -// Copyright (c) 2007-2017 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -32,14 +32,17 @@ #include -namespace hpx { namespace agas { +namespace hpx::agas { - struct notification_header; + HPX_CXX_EXPORT struct notification_header; - struct HPX_EXPORT big_boot_barrier + HPX_CXX_EXPORT struct HPX_EXPORT big_boot_barrier { public: - HPX_NON_COPYABLE(big_boot_barrier); + big_boot_barrier(big_boot_barrier const&) = delete; + big_boot_barrier(big_boot_barrier&&) = delete; + big_boot_barrier& operator=(big_boot_barrier const&) = delete; + big_boot_barrier& operator=(big_boot_barrier&&) = delete; private: parcelset::parcelport* pp; @@ -130,15 +133,14 @@ namespace hpx { namespace agas { parcelset::endpoints_type const& endpoints); }; - HPX_EXPORT void create_big_boot_barrier(parcelset::parcelport* pp_, - parcelset::endpoints_type const& endpoints_, + HPX_CXX_EXPORT HPX_EXPORT void create_big_boot_barrier( + parcelset::parcelport* pp_, parcelset::endpoints_type const& endpoints_, util::runtime_configuration const& ini_); - HPX_EXPORT void destroy_big_boot_barrier(); + HPX_CXX_EXPORT HPX_EXPORT void destroy_big_boot_barrier(); - HPX_EXPORT big_boot_barrier& get_big_boot_barrier(); - -}} // namespace hpx::agas + HPX_CXX_EXPORT HPX_EXPORT big_boot_barrier& get_big_boot_barrier(); +} // namespace hpx::agas #include diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/copy_component.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/copy_component.hpp index 6e77954dec83..22c478d4e078 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/copy_component.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/copy_component.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -40,13 +40,9 @@ namespace hpx::components { /// \note The new component instance is created on the locality of the /// component instance which is to be copied. /// - template -#if defined(DOXYGEN) - future -#else - std::enable_if_t, future> -#endif - copy(hpx::id_type const& to_copy) + HPX_CXX_EXPORT template + requires(traits::is_component_v) + future copy(hpx::id_type const& to_copy) { using action_type = server::copy_component_action_here; return hpx::detail::async_colocated(to_copy, to_copy); @@ -69,13 +65,10 @@ namespace hpx::components { /// \returns A future representing the global id of the newly (copied) /// component instance. /// - template -#if defined(DOXYGEN) - future -#else - std::enable_if_t, future> -#endif - copy(hpx::id_type const& to_copy, hpx::id_type const& target_locality) + HPX_CXX_EXPORT template + requires(traits::is_component_v) + future copy( + hpx::id_type const& to_copy, hpx::id_type const& target_locality) { using action_type = server::copy_component_action; return hpx::detail::async_colocated( @@ -106,7 +99,7 @@ namespace hpx::components { /// new component instance is created on the locality of the /// component instance which is to be copied. /// - template + HPX_CXX_EXPORT template Derived copy(client_base const& to_copy, hpx::id_type const& target_locality = hpx::invalid_id) { diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_all_localities.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_all_localities.hpp index ecc7514e182f..3e65de032d92 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_all_localities.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_all_localities.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -47,7 +47,8 @@ namespace hpx { /// otherwise. /// /// \see \a hpx::find_all_localities(), \a hpx::find_locality() - HPX_EXPORT hpx::id_type find_root_locality(error_code& ec = throws); + HPX_CXX_EXPORT HPX_EXPORT hpx::id_type find_root_locality( + error_code& ec = throws); /////////////////////////////////////////////////////////////////////////// /// \brief Return the list of global ids representing all localities @@ -76,7 +77,7 @@ namespace hpx { /// from an HPX-thread. It will return an empty vector otherwise. /// /// \see \a hpx::find_here(), \a hpx::find_locality() - HPX_EXPORT std::vector find_all_localities( + HPX_CXX_EXPORT HPX_EXPORT std::vector find_all_localities( error_code& ec = throws); /// \brief Return the list of locality ids of remote localities supporting @@ -107,6 +108,6 @@ namespace hpx { /// from an HPX-thread. It will return an empty vector otherwise. /// /// \see \a hpx::find_here(), \a hpx::find_locality() - HPX_EXPORT std::vector find_remote_localities( + HPX_CXX_EXPORT HPX_EXPORT std::vector find_remote_localities( error_code& ec = throws); } // namespace hpx diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_here.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_here.hpp index 0e6a1b2363b6..47d24f1ab1de 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_here.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_here.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -34,7 +34,7 @@ namespace hpx { /// /// \note As long as \a ec is not pre-initialized to \a hpx::throws this /// function doesn't throw but returns the result code using the - /// parameter \a ec. Otherwise it throws an instance of + /// parameter \a ec. Otherwise, it throws an instance of /// hpx::exception. /// /// \note This function will return meaningful results only if called @@ -42,5 +42,5 @@ namespace hpx { /// otherwise. /// /// \see \a hpx::find_all_localities(), \a hpx::find_locality() - HPX_EXPORT hpx::id_type find_here(error_code& ec = throws); + HPX_CXX_EXPORT HPX_EXPORT hpx::id_type find_here(error_code& ec = throws); } // namespace hpx diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_localities.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_localities.hpp index bbfe5f63d536..8a084977228a 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_localities.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/find_localities.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2020 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -55,7 +55,7 @@ namespace hpx { /// from an HPX-thread. It will return an empty vector otherwise. /// /// \see \a hpx::find_here(), \a hpx::find_locality() - HPX_EXPORT std::vector find_all_localities( + HPX_CXX_EXPORT HPX_EXPORT std::vector find_all_localities( components::component_type type, error_code& ec = throws); /// \brief Return the list of locality ids of remote localities supporting @@ -89,7 +89,7 @@ namespace hpx { /// from an HPX-thread. It will return an empty vector otherwise. /// /// \see \a hpx::find_here(), \a hpx::find_locality() - HPX_EXPORT std::vector find_remote_localities( + HPX_CXX_EXPORT HPX_EXPORT std::vector find_remote_localities( components::component_type type, error_code& ec = throws); /////////////////////////////////////////////////////////////////////////// @@ -127,6 +127,6 @@ namespace hpx { /// otherwise. /// /// \see \a hpx::find_here(), \a hpx::find_all_localities() - HPX_EXPORT hpx::id_type find_locality( + HPX_CXX_EXPORT HPX_EXPORT hpx::id_type find_locality( components::component_type type, error_code& ec = throws); } // namespace hpx diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_locality_name.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_locality_name.hpp index a84401f1caba..f04c271040c6 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_locality_name.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_locality_name.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -32,5 +32,6 @@ namespace hpx { /// and may be different for different parcel ports. /// /// \see \a std::string get_locality_name() - HPX_EXPORT future get_locality_name(hpx::id_type const& id); + HPX_CXX_EXPORT HPX_EXPORT future get_locality_name( + hpx::id_type const& id); } // namespace hpx diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_num_localities.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_num_localities.hpp index ebe7d8aefcaa..e72f427c2795 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_num_localities.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/get_num_localities.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -35,7 +35,7 @@ namespace hpx { /// from an HPX-thread. It will return 0 otherwise. /// /// \see \a hpx::find_all_localities, \a hpx::get_num_localities - HPX_EXPORT hpx::future get_num_localities( + HPX_CXX_EXPORT HPX_EXPORT hpx::future get_num_localities( components::component_type t); /// \brief Synchronously return the number of localities which are @@ -55,6 +55,7 @@ namespace hpx { /// from an HPX-thread. It will return 0 otherwise. /// /// \see \a hpx::find_all_localities, \a hpx::get_num_localities - HPX_EXPORT std::uint32_t get_num_localities(launch::sync_policy, - components::component_type t, error_code& ec = throws); + HPX_CXX_EXPORT HPX_EXPORT std::uint32_t get_num_localities( + launch::sync_policy, components::component_type t, + error_code& ec = throws); } // namespace hpx diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/migrate_component.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/migrate_component.hpp index 63810d0de7b5..9835736d3aad 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/migrate_component.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/migrate_component.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -9,6 +9,7 @@ #pragma once #include + #if !defined(HPX_COMPUTE_DEVICE_CODE) #include #include @@ -23,7 +24,7 @@ #include -namespace hpx { namespace components { +namespace hpx::components { /// Migrate the given component to the specified target locality /// @@ -45,15 +46,10 @@ namespace hpx { namespace components { /// \returns A future representing the global id of the migrated /// component instance. This should be the same as \a migrate_to. /// - template -#if defined(DOXYGEN) - future -#else - std::enable_if_t && - traits::is_distribution_policy_v, - future> -#endif - migrate(hpx::id_type const& to_migrate, + HPX_CXX_EXPORT template + requires(traits::is_component_v && + traits::is_distribution_policy_v) + future migrate(hpx::id_type const& to_migrate, [[maybe_unused]] DistPolicy const& policy) { #if defined(HPX_HAVE_NETWORKING) @@ -86,14 +82,10 @@ namespace hpx { namespace components { /// \returns A future representing the global id of the migrated /// component instance. This should be the same as \a migrate_to. /// - template -#if defined(DOXYGEN) - Derived -#else - std::enable_if_t, Derived> -#endif - migrate(client_base const& to_migrate, + requires(traits::is_distribution_policy_v) + Derived migrate(client_base const& to_migrate, DistPolicy const& policy) { using component_type = @@ -103,14 +95,10 @@ namespace hpx { namespace components { /// \cond NODETAIL // overload to be used for polymorphic objects - template -#if defined(DOXYGEN) - Derived -#else - std::enable_if_t, Derived> -#endif - migrate(client_base const& to_migrate, + HPX_CXX_EXPORT template + requires(traits::is_distribution_policy_v) + Derived migrate(client_base const& to_migrate, DistPolicy const& policy) { return Derived(migrate(to_migrate.get_id(), policy)); @@ -134,13 +122,10 @@ namespace hpx { namespace components { /// \returns A future representing the global id of the migrated /// component instance. This should be the same as \a migrate_to. /// - template -#if defined(DOXYGEN) - future -#else - std::enable_if_t, future> -#endif - migrate(hpx::id_type const& to_migrate, hpx::id_type const& target_locality) + HPX_CXX_EXPORT template + requires(traits::is_component_v) + future migrate( + hpx::id_type const& to_migrate, hpx::id_type const& target_locality) { return migrate(to_migrate, hpx::target(target_locality)); } @@ -163,7 +148,7 @@ namespace hpx { namespace components { /// \returns A client side representation of representing of the migrated /// component instance. This should be the same as \a migrate_to. /// - template + HPX_CXX_EXPORT template Derived migrate(client_base const& to_migrate, hpx::id_type const& target_locality) { @@ -175,8 +160,8 @@ namespace hpx { namespace components { /// \cond NODETAIL // overload to be used for polymorphic objects - template + HPX_CXX_EXPORT template Derived migrate(client_base const& to_migrate, hpx::id_type const& target_locality) { @@ -184,5 +169,6 @@ namespace hpx { namespace components { migrate(to_migrate.get_id(), target_locality)); } /// \endcond -}} // namespace hpx::components +} // namespace hpx::components + #endif diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_fwd.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_fwd.hpp index 620f3afff37f..301d484fde1f 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_fwd.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_fwd.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2018 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -14,6 +14,7 @@ #include #include #include + #include #include #include @@ -24,18 +25,14 @@ namespace hpx { - class HPX_EXPORT runtime_distributed; + HPX_CXX_EXPORT class HPX_EXPORT runtime_distributed; - HPX_EXPORT runtime_distributed& get_runtime_distributed(); - HPX_EXPORT runtime_distributed*& get_runtime_distributed_ptr(); + HPX_CXX_EXPORT HPX_EXPORT runtime_distributed& get_runtime_distributed(); + HPX_CXX_EXPORT HPX_EXPORT runtime_distributed*& + get_runtime_distributed_ptr(); /// The function \a get_locality returns a reference to the locality prefix - HPX_EXPORT naming::gid_type const& get_locality(); - - /// \cond NOINTERNAL - namespace util { - struct binary_filter; - } // namespace util + HPX_CXX_EXPORT HPX_EXPORT naming::gid_type const& get_locality(); /// \endcond /////////////////////////////////////////////////////////////////////////// @@ -54,7 +51,8 @@ namespace hpx { /// \note The active counters are those which have been specified on /// the command line while executing the application (see command /// line option \--hpx:print-counter) - HPX_EXPORT void start_active_counters(error_code& ec = throws); + HPX_CXX_EXPORT HPX_EXPORT void start_active_counters( + error_code& ec = throws); /// \brief Resets all active performance counters. /// @@ -70,7 +68,8 @@ namespace hpx { /// \note The active counters are those which have been specified on /// the command line while executing the application (see command /// line option \--hpx:print-counter) - HPX_EXPORT void reset_active_counters(error_code& ec = throws); + HPX_CXX_EXPORT HPX_EXPORT void reset_active_counters( + error_code& ec = throws); /// \brief Re-initialize all active performance counters. /// @@ -88,7 +87,7 @@ namespace hpx { /// \note The active counters are those which have been specified on /// the command line while executing the application (see command /// line option \--hpx:print-counter) - HPX_EXPORT void reinit_active_counters( + HPX_CXX_EXPORT HPX_EXPORT void reinit_active_counters( bool reset = true, error_code& ec = throws); /// \brief Stop all active performance counters. @@ -105,7 +104,8 @@ namespace hpx { /// \note The active counters are those which have been specified on /// the command line while executing the application (see command /// line option \--hpx:print-counter) - HPX_EXPORT void stop_active_counters(error_code& ec = throws); + HPX_CXX_EXPORT HPX_EXPORT void stop_active_counters( + error_code& ec = throws); /// \brief Evaluate and output all active performance counters, optionally /// naming the point in code marked by this function. @@ -130,7 +130,7 @@ namespace hpx { /// \note The active counters are those which have been specified on /// the command line while executing the application (see command /// line option \--hpx:print-counter) - HPX_EXPORT void evaluate_active_counters(bool reset = false, + HPX_CXX_EXPORT HPX_EXPORT void evaluate_active_counters(bool reset = false, char const* description = nullptr, error_code& ec = throws); /////////////////////////////////////////////////////////////////////////// @@ -148,8 +148,8 @@ namespace hpx { /// function doesn't throw but returns the result code using the /// parameter \a ec. Otherwise it throws an instance of /// hpx::exception. - HPX_EXPORT serialization::binary_filter* create_binary_filter( - char const* binary_filter_type, bool compress, + HPX_CXX_EXPORT HPX_EXPORT serialization::binary_filter* + create_binary_filter(char const* binary_filter_type, bool compress, serialization::binary_filter* next_filter = nullptr, error_code& ec = throws); } // namespace hpx diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp index 686995b94ed9..47aa53879878 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2024 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -15,15 +15,16 @@ #include #include -namespace hpx { namespace components { +namespace hpx::components { /////////////////////////////////////////////////////////////////////////// /// The \a runtime_support class is the client side representation of a /// \a server#runtime_support component - class HPX_EXPORT runtime_support : public stubs::runtime_support + HPX_CXX_EXPORT class HPX_EXPORT runtime_support + : public stubs::runtime_support { private: - typedef stubs::runtime_support base_type; + using base_type = stubs::runtime_support; public: /// Create a client side representation for the existing @@ -151,15 +152,17 @@ namespace hpx { namespace components { private: hpx::id_type gid_; }; -}} // namespace hpx::components +} // namespace hpx::components /////////////////////////////////////////////////////////////////////////////// // initialize runtime interface function wrappers namespace hpx::agas { - struct runtime_components_init_interface_functions& + + HPX_CXX_EXPORT struct runtime_components_init_interface_functions& runtime_components_init(); } namespace hpx::components { - struct counter_interface_functions& counter_init(); + + HPX_CXX_EXPORT struct counter_interface_functions& counter_init(); } // namespace hpx::components diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/copy_component.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/copy_component.hpp index ebacd11ff6bc..a6b25bf2f4a2 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/copy_component.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/copy_component.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -12,6 +12,7 @@ #include #include #include + #include #include @@ -21,6 +22,7 @@ namespace hpx::components::server { /////////////////////////////////////////////////////////////////////////// /// \brief Copy given component to the specified target locality namespace detail { + // If we know that the new component has to be created local to the old // one, we can avoid doing serialization. template @@ -61,7 +63,7 @@ namespace hpx::components::server { } // namespace detail /////////////////////////////////////////////////////////////////////////// - template + HPX_CXX_EXPORT template hpx::id_type copy_component_here(hpx::id_type const& to_copy) { std::shared_ptr sp = @@ -69,7 +71,7 @@ namespace hpx::components::server { return detail::copy_component_here_postproc(HPX_MOVE(sp)); } - template + HPX_CXX_EXPORT template future copy_component( hpx::id_type const& to_copy, hpx::id_type const& target_locality) { @@ -81,7 +83,7 @@ namespace hpx::components::server { }); } - template + HPX_CXX_EXPORT template struct copy_component_action_here : ::hpx::actions::action, @@ -89,7 +91,7 @@ namespace hpx::components::server { { }; - template + HPX_CXX_EXPORT template struct copy_component_action : ::hpx::actions::action (*)( hpx::id_type const&, hpx::id_type const&), diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/migrate_component.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/migrate_component.hpp index 5c7f19860a50..f58fedf5f3de 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/migrate_component.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/migrate_component.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2023 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -12,6 +12,7 @@ #include #include #include + #include #include @@ -158,7 +159,7 @@ namespace hpx::components::server { } } // namespace detail - template + HPX_CXX_EXPORT template future migrate_component(id_type const& to_migrate, naming::address const& addr, DistPolicy const& policy) { @@ -189,7 +190,7 @@ namespace hpx::components::server { ptr, to_migrate, policy); } - template + HPX_CXX_EXPORT template struct migrate_component_action : ::hpx::actions::action (*)(id_type const&, naming::address const&, DistPolicy const&), @@ -203,7 +204,7 @@ namespace hpx::components::server { // // This is executed on the locality responsible for managing the address // resolution for the given object. - template + HPX_CXX_EXPORT template future trigger_migrate_component(id_type const& to_migrate, DistPolicy const& policy, hpx::id_type const& id, naming::address const& addr) @@ -262,7 +263,7 @@ namespace hpx::components::server { }); } - template + HPX_CXX_EXPORT template struct trigger_migrate_component_action : ::hpx::actions::action (*)(id_type const&, DistPolicy const&, hpx::id_type const&, @@ -277,7 +278,7 @@ namespace hpx::components::server { // // This is executed on the locality where the object to migrate is // currently located. - template + HPX_CXX_EXPORT template future perform_migrate_component( id_type const& to_migrate, DistPolicy const& policy) { @@ -346,7 +347,7 @@ namespace hpx::components::server { .then(launch::sync, HPX_MOVE(start_migration_op)); } - template + HPX_CXX_EXPORT template struct perform_migrate_component_action : ::hpx::actions::action (*)( id_type const&, DistPolicy const&), diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp index 250b9fa5599c..2e386bfd68b8 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // Copyright (c) 2011-2017 Thomas Heller // @@ -48,7 +48,7 @@ namespace hpx::components::server { /////////////////////////////////////////////////////////////////////////// - class runtime_support + HPX_CXX_EXPORT class runtime_support { private: using plugin_map_mutex_type = hpx::spinlock; @@ -611,7 +611,7 @@ HPX_REGISTER_ACTION_DECLARATION( namespace hpx::components::server { - template + HPX_CXX_EXPORT template struct create_component_action : ::hpx::actions::action, @@ -627,7 +627,7 @@ namespace hpx::components::server { { }; - template + HPX_CXX_EXPORT template struct create_component_direct_action : ::hpx::actions::direct_action + HPX_CXX_EXPORT template struct bulk_create_component_action : ::hpx::actions::action ( runtime_support::*)(std::size_t, Ts...), @@ -664,7 +664,7 @@ namespace hpx::components::server { { }; - template + HPX_CXX_EXPORT template struct bulk_create_component_direct_action : ::hpx::actions::direct_action ( runtime_support::*)( @@ -686,7 +686,7 @@ namespace hpx::components::server { }; /////////////////////////////////////////////////////////////////////////// - template + HPX_CXX_EXPORT template struct copy_create_component_action : ::hpx::actions::action const&, bool), @@ -694,7 +694,8 @@ namespace hpx::components::server { copy_create_component_action> { }; - template + + HPX_CXX_EXPORT template struct migrate_component_here_action : ::hpx::actions::action const&, @@ -707,21 +708,24 @@ namespace hpx::components::server { /////////////////////////////////////////////////////////////////////////// // Termination detection does not make this locality black +namespace hpx::traits { + #if !defined(HPX_COMPUTE_DEVICE_CODE) && defined(HPX_HAVE_NETWORKING) -template <> -struct hpx::traits::action_does_termination_detection< - hpx::components::server::runtime_support::dijkstra_termination_action> -{ - static constexpr bool call() noexcept + template <> + struct action_does_termination_detection< + hpx::components::server::runtime_support::dijkstra_termination_action> { - return true; - } -}; + static constexpr bool call() noexcept + { + return true; + } + }; #endif -// runtime_support is a (hand-rolled) component -template <> -struct hpx::traits::is_component - : std::true_type -{ -}; + // runtime_support is a (hand-rolled) component + template <> + struct is_component + : std::true_type + { + }; +} // namespace hpx::traits diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp index 0245feb77fce..e74fc68704bb 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2024 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -31,7 +31,7 @@ namespace hpx::components::stubs { /////////////////////////////////////////////////////////////////////////// // The \a runtime_support class is the client side representation of a // \a server#runtime_support component - struct HPX_EXPORT runtime_support + HPX_CXX_EXPORT struct HPX_EXPORT runtime_support { /////////////////////////////////////////////////////////////////////// /// Create a new component \a type using the runtime_support with the diff --git a/libs/full/runtime_distributed/src/applier.cpp b/libs/full/runtime_distributed/src/applier.cpp index b905f2f4a041..789ffef585ac 100644 --- a/libs/full/runtime_distributed/src/applier.cpp +++ b/libs/full/runtime_distributed/src/applier.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2007-2008 Anshul Tandon -// Copyright (c) 2007-2017 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -31,7 +31,7 @@ #include #include -namespace hpx { namespace applier { +namespace hpx::applier { applier::applier() #if defined(HPX_HAVE_NETWORKING) @@ -182,4 +182,4 @@ namespace hpx { namespace applier { { return &hpx::get_runtime_distributed().get_applier(); } -}} // namespace hpx::applier +} // namespace hpx::applier diff --git a/libs/full/runtime_distributed/src/big_boot_barrier.cpp b/libs/full/runtime_distributed/src/big_boot_barrier.cpp index 5ee8b35ad00e..8a482f9e1ede 100644 --- a/libs/full/runtime_distributed/src/big_boot_barrier.cpp +++ b/libs/full/runtime_distributed/src/big_boot_barrier.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011 Bryce Lelbach & Katelyn Kufahl -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2015 Anton Bikineev // // SPDX-License-Identifier: BSL-1.0 diff --git a/libs/full/runtime_distributed/src/get_locality_name.cpp b/libs/full/runtime_distributed/src/get_locality_name.cpp index fa526a70dfc2..473de9e33596 100644 --- a/libs/full/runtime_distributed/src/get_locality_name.cpp +++ b/libs/full/runtime_distributed/src/get_locality_name.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/libs/full/runtime_distributed/src/locality_interface.cpp b/libs/full/runtime_distributed/src/locality_interface.cpp index 98236ba38204..c33b6b94e7ba 100644 --- a/libs/full/runtime_distributed/src/locality_interface.cpp +++ b/libs/full/runtime_distributed/src/locality_interface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Hartmut Kaiser +// Copyright (c) 2021-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,6 +13,7 @@ #include #include #include + #include #include @@ -134,7 +135,7 @@ namespace hpx::parcelset { } // namespace detail::impl // initialize locality interface function pointers in parcelset modules - HPX_CXX_EXPORT struct HPX_EXPORT locality_interface_functions + struct HPX_EXPORT locality_interface_functions { locality_interface_functions() { diff --git a/libs/full/runtime_distributed/src/runtime_distributed.cpp b/libs/full/runtime_distributed/src/runtime_distributed.cpp index c6333267402b..385b68b3172b 100644 --- a/libs/full/runtime_distributed/src/runtime_distributed.cpp +++ b/libs/full/runtime_distributed/src/runtime_distributed.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 diff --git a/libs/full/runtime_distributed/src/runtime_support.cpp b/libs/full/runtime_distributed/src/runtime_support.cpp index f0a8a18f312a..ed9e60eb4862 100644 --- a/libs/full/runtime_distributed/src/runtime_support.cpp +++ b/libs/full/runtime_distributed/src/runtime_support.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2024 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/libs/full/runtime_distributed/src/server/runtime_support_server.cpp b/libs/full/runtime_distributed/src/server/runtime_support_server.cpp index 5b911357ce64..7de7ac6015f0 100644 --- a/libs/full/runtime_distributed/src/server/runtime_support_server.cpp +++ b/libs/full/runtime_distributed/src/server/runtime_support_server.cpp @@ -115,12 +115,14 @@ HPX_DEFINE_GET_COMPONENT_TYPE_STATIC(hpx::components::server::runtime_support, to_int(hpx::components::component_enum_type::runtime_support)) namespace hpx { + // helper function to stop evaluating counters during shutdown void stop_evaluating_counters(bool terminate = false); } // namespace hpx /////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace components { namespace server { +namespace hpx::components::server { + /////////////////////////////////////////////////////////////////////////// runtime_support::runtime_support(hpx::util::runtime_configuration& cfg) : stop_called_(false) @@ -184,7 +186,7 @@ namespace hpx { namespace components { namespace server { #endif std::abort(); } -}}} // namespace hpx::components::server +} // namespace hpx::components::server /////////////////////////////////////////////////////////////////////////////// namespace hpx { namespace components { namespace server { diff --git a/libs/full/runtime_distributed/src/stubs/runtime_support_stubs.cpp b/libs/full/runtime_distributed/src/stubs/runtime_support_stubs.cpp index 31194727737f..0e1e5396af4e 100644 --- a/libs/full/runtime_distributed/src/stubs/runtime_support_stubs.cpp +++ b/libs/full/runtime_distributed/src/stubs/runtime_support_stubs.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -18,6 +18,7 @@ #include #include #include + #include #include diff --git a/libs/full/segmented_algorithms/CMakeLists.txt b/libs/full/segmented_algorithms/CMakeLists.txt index 74565fdbc323..15799ecf2b98 100644 --- a/libs/full/segmented_algorithms/CMakeLists.txt +++ b/libs/full/segmented_algorithms/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019 The STE||AR-Group +# Copyright (c) 2019-2026 The STE||AR-Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -52,6 +52,8 @@ set(segmented_algorithms_compat_headers include(HPX_AddModule) add_hpx_module( full segmented_algorithms + GLOBAL_HEADER_GEN ON + GLOBAL_HEADER_MODULE_GEN ON HEADERS ${segmented_algorithms_headers} COMPAT_HEADERS ${segmented_algorithms_compat_headers} DEPENDENCIES hpx_core diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithm.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithm.hpp index cc9041ca09af..ede530bd8931 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithm.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithm.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2019 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -8,27 +8,4 @@ #include #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_difference.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_difference.hpp index f482431e33df..903fe0da7ada 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_difference.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_difference.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 Ajai V George // Copyright (c) 2021 Karame M.Shokooh -// Copyright (c) 2024-2025 Hartmut Kaiser +// Copyright (c) 2024-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -25,94 +25,68 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_adjacent_difference - namespace detail { - - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - hpx::parallel::util::detail::algorithm_result_t - segmented_adjacent_difference(Algo&& algo, ExPolicy const& policy, - FwdIter1 first, FwdIter1 last, FwdIter2 dest, Op&& op, - std::true_type) - { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; - using result = - hpx::parallel::util::detail::algorithm_result; + /// \cond NOINTERNAL + + // sequential remote implementation + template + hpx::parallel::util::detail::algorithm_result_t + segmented_adjacent_difference(Algo&& algo, ExPolicy const& policy, + FwdIter1 first, FwdIter1 last, FwdIter2 dest, Op&& op, std::true_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; + + using result = + hpx::parallel::util::detail::algorithm_result; - FwdIter2 end_dest = dest, curr; - std::advance(end_dest, std::distance(first, last)); + FwdIter2 end_dest = dest, curr; + std::advance(end_dest, std::distance(first, last)); - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - local_iterator_type2 out = dispatch(traits2::get_id(sdest), - algo, policy, std::true_type(), beg, end, ldest, op); - dest = traits2::compose(sdest, out); - } + local_iterator_type2 out = dispatch(traits2::get_id(sdest), + algo, policy, std::true_type(), beg, end, ldest, op); + dest = traits2::compose(sdest, out); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + local_iterator_type2 out = traits2::local(dest); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); - local_iterator_type2 out = traits2::local(dest); - if (beg != end) - { - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, op); - } - - // handle all full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - curr = traits2::compose(sdest, ldest); - if (beg != end) - { - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, op); - - FwdIter1 beginning = traits1::compose(sit, beg); - if (beginning != last) - { - if (curr != end_dest) - { - *curr = HPX_INVOKE( - op, *beginning, *std::prev(beginning)); - } - } - } - } + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, op); + } - // handle the beginning of the last partition + // handle all full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); curr = traits2::compose(sdest, ldest); if (beg != end) @@ -130,88 +104,95 @@ namespace hpx::parallel { } } } - dest = traits2::compose(sdest, out); } - return result::get(HPX_MOVE(dest)); + + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + curr = traits2::compose(sdest, ldest); + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, op); + + FwdIter1 beginning = traits1::compose(sit, beg); + if (beginning != last) + { + if (curr != end_dest) + { + *curr = + HPX_INVOKE(op, *beginning, *std::prev(beginning)); + } + } + } + dest = traits2::compose(sdest, out); } + return result::get(HPX_MOVE(dest)); + } - // parallel remote implementation - template - hpx::parallel::util::detail::algorithm_result_t - segmented_adjacent_difference(Algo&& algo, ExPolicy const& policy, - FwdIter1 first, FwdIter1 last, FwdIter2 dest, Op&& op, - std::false_type) - { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; + // parallel remote implementation + template + hpx::parallel::util::detail::algorithm_result_t + segmented_adjacent_difference(Algo&& algo, ExPolicy const& policy, + FwdIter1 first, FwdIter1 last, FwdIter2 dest, Op&& op, std::false_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; - using result = - hpx::parallel::util::detail::algorithm_result; + using result = + hpx::parallel::util::detail::algorithm_result; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); - using segment_type = std::vector>; - segment_type segments; + using segment_type = std::vector>; + segment_type segments; - auto size = std::distance(sit, send); - segments.reserve(size); + auto size = std::distance(sit, send); + segments.reserve(size); - std::vector between_segments; - between_segments.reserve(size); + std::vector between_segments; + between_segments.reserve(size); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, op)); - } + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, op)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, op)); - } - - // handle all full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - between_segments.push_back(traits1::compose(sit, beg)); - segments.push_back( - dispatch_async(traits2::get_id(sdest), algo, policy, - forced_seq(), beg, end, ldest, op)); - } - } + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, op)); + } - // handle the beginning of the last partition + // handle all full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); if (beg != end) { @@ -221,36 +202,47 @@ namespace hpx::parallel { } } - return result::get(dataflow( - [=](segment_type&& r) -> FwdIter2 { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - auto ft = r.back().get(); - auto odest = traits2::compose(sdest, ft); - auto start = between_segments.begin(); - while (start != between_segments.end()) - { - FwdIter2 curr = dest; - std::advance(curr, std::distance(first, *start)); - *curr = HPX_INVOKE(op, *(*start), *std::prev(*start)); - start = std::next(start); - } - return odest; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + between_segments.push_back(traits1::compose(sit, beg)); + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, op)); + } } - /// \endcond - } // namespace detail -} // namespace hpx::parallel + + return result::get(dataflow( + [=](segment_type&& r) -> FwdIter2 { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + auto ft = r.back().get(); + auto odest = traits2::compose(sdest, ft); + auto start = between_segments.begin(); + while (start != between_segments.end()) + { + FwdIter2 curr = dest; + std::advance(curr, std::distance(first, *start)); + *curr = HPX_INVOKE(op, *(*start), *std::prev(*start)); + start = std::next(start); + } + return odest; + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -283,7 +275,7 @@ namespace hpx::segmented { HPX_FORWARD(Op, op), is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_find.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_find.hpp index 5c72fbc1bd28..b2853089221f 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_find.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/adjacent_find.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2017 Ajai V George -// Copyright (c) 2025 Hartmut Kaiser +// Copyright (c) 2025-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -25,259 +25,254 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_adjacent_find - namespace detail { - - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static util::detail::algorithm_result_t - segmented_adjacent_find(Algo&& algo, ExPolicy const& policy, - FwdIter first, FwdIter last, Pred&& pred, Proj&& proj, - std::true_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + /// \cond NOINTERNAL + + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_adjacent_find( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, + Pred&& pred, Proj&& proj, std::true_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + + using result = util::detail::algorithm_result; - segment_iterator1 sit = traits::segment(first); - segment_iterator1 send = traits::segment(last); + segment_iterator1 sit = traits::segment(first); + segment_iterator1 send = traits::segment(last); - FwdIter output = last; + FwdIter output = last; - util::invoke_projected pred_projected{pred, proj}; + util::invoke_projected pred_projected{pred, proj}; - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - local_iterator_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, pred, proj); - output = traits::compose(sit, out); - } + local_iterator_type out = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, pred, proj); + output = traits::compose(sit, out); } - else + } + else + { + bool found = false; + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + local_iterator_type out = traits::local(last); + if (beg != end) { - bool found = false; - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - local_iterator_type out = traits::local(last); - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, pred, proj); - if (out != end) - { - found = true; - output = traits::compose(sit, out); - } - } - FwdIter ending = traits::compose(sit, std::prev(end)); - if (!found && - HPX_INVOKE(pred_projected, *ending, *std::next(ending))) + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, pred, proj); + if (out != end) { found = true; - output = traits::compose(sit, std::prev(end)); + output = traits::compose(sit, out); } + } + FwdIter ending = traits::compose(sit, std::prev(end)); + if (!found && + HPX_INVOKE(pred_projected, *ending, *std::next(ending))) + { + found = true; + output = traits::compose(sit, std::prev(end)); + } - // handle all the full partitions - if (!found) + // handle all the full partitions + if (!found) + { + for (++sit; sit != send; ++sit) { - for (++sit; sit != send; ++sit) + beg = traits::begin(sit); + end = traits::end(sit); + if (beg != end) { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, pred, proj); - if (out != end) - { - found = true; - output = traits::compose(sit, out); - break; - } - } - ending = traits::compose(sit, std::prev(end)); - if (HPX_INVOKE( - pred_projected, *ending, *std::next(ending)) && - !found) + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, pred, proj); + if (out != end) { found = true; - output = traits::compose(sit, std::prev(end)); + output = traits::compose(sit, out); break; } } + ending = traits::compose(sit, std::prev(end)); + if (HPX_INVOKE( + pred_projected, *ending, *std::next(ending)) && + !found) + { + found = true; + output = traits::compose(sit, std::prev(end)); + break; + } } + } - // handle the beginning of the last partition - beg = traits::begin(sit); - end = traits::local(last); - if (beg != end && !found) + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end && !found) + { + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, pred, proj); + if (out != end) { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, pred, proj); - if (out != end) - { - output = traits::compose(sit, out); - } + output = traits::compose(sit, out); } } - return result::get(HPX_MOVE(output)); } + return result::get(HPX_MOVE(output)); + } - // parallel remote implementation - template - static util::detail::algorithm_result_t - segmented_adjacent_find(Algo&& algo, ExPolicy const& policy, - FwdIter first, FwdIter last, Pred&& pred, Proj&& proj, - std::false_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_adjacent_find( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, + Pred&& pred, Proj&& proj, std::false_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + using result = util::detail::algorithm_result; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - segment_iterator1 sit = traits::segment(first); - segment_iterator1 send = traits::segment(last); + segment_iterator1 sit = traits::segment(first); + segment_iterator1 send = traits::segment(last); - using segment_type = std::vector>; - segment_type segments; - segments.reserve(std::distance(sit, send)); + using segment_type = std::vector>; + segment_type segments; + segments.reserve(std::distance(sit, send)); - std::vector between_segments; - between_segments.reserve(std::distance(sit, send)); + std::vector between_segments; + between_segments.reserve(std::distance(sit, send)); - util::invoke_projected pred_projected{pred, proj}; + util::invoke_projected pred_projected{pred, proj}; - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, HPX_FORWARD(Pred, pred), - HPX_FORWARD(Proj, proj)), - [sit, end, last]( - local_iterator_type const& out) -> FwdIter { - if (out != end) - return traits::compose(sit, out); - return last; - })); - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy, + forced_seq(), beg, end, HPX_FORWARD(Pred, pred), + HPX_FORWARD(Proj, proj)), + [sit, end, last]( + local_iterator_type const& out) -> FwdIter { + if (out != end) + return traits::compose(sit, out); + return last; + })); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, pred, proj), - [sit, end, last]( - local_iterator_type const& out) -> FwdIter { - if (out != end) - return traits::compose(sit, out); - return last; - })); - } - - // handle all the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - between_segments.push_back(traits::compose(sit, beg)); - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, pred, proj), - [sit, end, last]( - local_iterator_type const& out) -> FwdIter { - if (out != end) - return traits::compose(sit, out); - return last; - })); - } - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy, + forced_seq(), beg, end, pred, proj), + [sit, end, last]( + local_iterator_type const& out) -> FwdIter { + if (out != end) + return traits::compose(sit, out); + return last; + })); + } - // handle the beginning of the last partition + // handle all the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { between_segments.push_back(traits::compose(sit, beg)); segments.push_back(hpx::make_future( dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, HPX_FORWARD(Pred, pred), - HPX_FORWARD(Proj, proj)), + forced_seq(), beg, end, pred, proj), [sit, end, last]( local_iterator_type const& out) -> FwdIter { if (out != end) return traits::compose(sit, out); - else - return last; + return last; })); } } - return result::get(dataflow( - [=](segment_type&& r) mutable -> FwdIter { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - std::vector res = hpx::unwrap(HPX_MOVE(r)); - auto it = res.begin(); - int i = 0; - while (it != res.end()) + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + between_segments.push_back(traits::compose(sit, beg)); + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy, + forced_seq(), beg, end, HPX_FORWARD(Pred, pred), + HPX_FORWARD(Proj, proj)), + [sit, end, last]( + local_iterator_type const& out) -> FwdIter { + if (out != end) + return traits::compose(sit, out); + else + return last; + })); + } + } + + return result::get(dataflow( + [=](segment_type&& r) mutable -> FwdIter { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + std::vector res = hpx::unwrap(HPX_MOVE(r)); + auto it = res.begin(); + int i = 0; + while (it != res.end()) + { + if (*it != last) + return *it; + if (HPX_INVOKE(pred_projected, + *std::prev(between_segments[i]), + *(between_segments[i]))) { - if (*it != last) - return *it; - if (HPX_INVOKE(pred_projected, - *std::prev(between_segments[i]), - *(between_segments[i]))) - { - return std::prev(between_segments[i]); - } - ++it; - i += 1; + return std::prev(between_segments[i]); } - return res.back(); - }, - HPX_MOVE(segments))); - } - /// \endcond - } // namespace detail -} // namespace hpx::parallel + ++it; + i += 1; + } + return res.back(); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) InIter tag_invoke( @@ -301,7 +296,7 @@ namespace hpx::segmented { hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp index 9c573adab7ea..f57a09aef2bd 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2017 Ajai V George -// Copyright (c) 2024-2025 Hartmut Kaiser +// Copyright (c) 2024-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -10,6 +10,7 @@ #include #include #include + #include #include @@ -20,136 +21,125 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_all_any_none - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static util::detail::algorithm_result_t - segmented_none_of(Algo&& algo, ExPolicy const& policy, FwdIter first, - FwdIter last, F&& f, Proj&& proj, std::true_type) + + /// \cond NOINTERNAL + + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_none_of( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, F&& f, + Proj&& proj, std::true_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; + + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); + bool output = false; + if (sit == send) { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; - - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); - bool output = false; - if (sit == send) + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - - if (beg != end) - { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); - // handle all of the full partitions - for (++sit; sit != send && output; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - - if (beg != end) - { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } - } + if (beg != end) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send && output; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); - if (beg != end && output) + end = traits::end(sit); + + if (beg != end) { output = dispatch(traits::get_id(sit), algo, policy, std::true_type(), beg, end, f, proj); } } - return result::get(HPX_MOVE(output)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end && output) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } } - // parallel remote implementation - template - static util::detail::algorithm_result_t - segmented_none_of(Algo&& algo, ExPolicy const& policy, FwdIter first, - FwdIter last, F&& f, Proj&& proj, std::false_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + return result::get(HPX_MOVE(output)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_none_of( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, F&& f, + Proj&& proj, std::false_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, f, proj)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -157,148 +147,148 @@ namespace hpx::parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) -> bool { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - std::vector res = hpx::unwrap(HPX_MOVE(r)); - auto it = res.begin(); - while (it != res.end()) - { - if (*it == false) - return false; - it++; - } - return true; - }, - HPX_MOVE(segments))); - } - - /////////////////////////////////////////////////////////////////////// - // sequential remote implementation - template - static util::detail::algorithm_result_t - segmented_any_of(Algo&& algo, ExPolicy const& policy, FwdIter first, - FwdIter last, F&& f, Proj&& proj, std::true_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; - - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); - bool output = false; - if (sit == send) + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); + } - if (beg != end) + return result::get(dataflow( + [=](std::vector>&& r) -> bool { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + std::vector res = hpx::unwrap(HPX_MOVE(r)); + auto it = res.begin(); + while (it != res.end()) { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); + if (*it == false) + return false; + it++; } + return true; + }, + HPX_MOVE(segments))); + } - // handle all of the full partitions - for (++sit; sit != send && !output; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - - if (beg != end) - { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } - } + /////////////////////////////////////////////////////////////////////// + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_any_of( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, F&& f, + Proj&& proj, std::true_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; + + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); + bool output = false; + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); - // handle the beginning of the last partition + if (beg != end) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } + + // handle all of the full partitions + for (++sit; sit != send && !output; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); - if (beg != end && !output) + end = traits::end(sit); + + if (beg != end) { output = dispatch(traits::get_id(sit), algo, policy, std::true_type(), beg, end, f, proj); } } - return result::get(HPX_MOVE(output)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end && !output) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } } - // parallel remote implementation - template - static util::detail::algorithm_result_t - segmented_any_of(Algo&& algo, ExPolicy const& policy, FwdIter first, - FwdIter last, F&& f, Proj&& proj, std::false_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + return result::get(HPX_MOVE(output)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_any_of( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, F&& f, + Proj&& proj, std::false_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, f, proj)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -306,148 +296,148 @@ namespace hpx::parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) -> bool { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - std::vector res = hpx::unwrap(HPX_MOVE(r)); - auto it = res.begin(); - while (it != res.end()) - { - if (*it == true) - return true; - it++; - } - return false; - }, - HPX_MOVE(segments))); - } - - /////////////////////////////////////////////////////////////////////// - // sequential remote implementation - template - static util::detail::algorithm_result_t - segmented_all_of(Algo&& algo, ExPolicy const& policy, FwdIter first, - FwdIter last, F&& f, Proj&& proj, std::true_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; - - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); - bool output = false; - if (sit == send) + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); + } - if (beg != end) + return result::get(dataflow( + [=](std::vector>&& r) -> bool { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + std::vector res = hpx::unwrap(HPX_MOVE(r)); + auto it = res.begin(); + while (it != res.end()) { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); + if (*it == true) + return true; + it++; } + return false; + }, + HPX_MOVE(segments))); + } - // handle all of the full partitions - for (++sit; sit != send && output; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - - if (beg != end) - { - output = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } - } + /////////////////////////////////////////////////////////////////////// + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_all_of( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, F&& f, + Proj&& proj, std::true_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; + + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); + bool output = false; + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + + if (beg != end) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send && output; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); - if (beg != end && output) + end = traits::end(sit); + + if (beg != end) { output = dispatch(traits::get_id(sit), algo, policy, std::true_type(), beg, end, f, proj); } } - return result::get(HPX_MOVE(output)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end && output) + { + output = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } } - // parallel remote implementation - template - static util::detail::algorithm_result_t - segmented_all_of(Algo&& algo, ExPolicy const& policy, FwdIter first, - FwdIter last, F&& f, Proj&& proj, std::false_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + return result::get(HPX_MOVE(output)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_all_of( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, F&& f, + Proj&& proj, std::false_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, f, proj)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -455,32 +445,41 @@ namespace hpx::parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) -> bool { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - std::vector res = hpx::unwrap(HPX_MOVE(r)); - auto it = res.begin(); - while (it != res.end()) - { - if (*it == false) - return false; - it++; - } - return true; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); + } } - /// \endcond - } // namespace detail -} // namespace hpx::parallel + + return result::get(dataflow( + [=](std::vector>&& r) -> bool { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + std::vector res = hpx::unwrap(HPX_MOVE(r)); + auto it = res.begin(); + while (it != res.end()) + { + if (*it == false) + return false; + it++; + } + return true; + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) bool tag_invoke(hpx::none_of_t, InIter first, InIter last, F&& f) @@ -493,7 +492,7 @@ namespace hpx::segmented { HPX_FORWARD(F, f), hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) @@ -510,7 +509,7 @@ namespace hpx::segmented { first, last, HPX_FORWARD(F, f), hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) bool tag_invoke(hpx::any_of_t, InIter first, InIter last, F&& f) @@ -523,7 +522,7 @@ namespace hpx::segmented { HPX_FORWARD(F, f), hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) @@ -540,7 +539,7 @@ namespace hpx::segmented { first, last, HPX_FORWARD(F, f), hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) bool tag_invoke(hpx::all_of_t, InIter first, InIter last, F&& f) @@ -553,7 +552,7 @@ namespace hpx::segmented { HPX_FORWARD(F, f), hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/copy.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/copy.hpp index b4d89979189a..09f91d439824 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/copy.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/copy.hpp @@ -10,7 +10,9 @@ #include #include #include + #include +#include #include #include @@ -22,84 +24,69 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_copy - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static util::detail::algorithm_result_t> - segmented_copy(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, OutIter dest, std::true_type) - { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; - using result = util::detail::algorithm_result>; + /// \cond NOINTERNAL - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_copy(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, OutIter dest, std::true_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; - if (sit == send) - { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - util::in_out_result - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest); - last = traits1::compose(send, out.in); - dest = traits2::compose(sdest, out.out); - } - } - else + using result = util::detail::algorithm_result>; + + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + if (sit == send) + { + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); util::in_out_result - out{beg, ldest}; - if (beg != end) - { out = dispatch(traits2::get_id(sdest), algo, policy, std::true_type(), beg, end, ldest); - } - - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - out = util::in_out_result{beg, ldest}; - if (beg != end) - { - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest); - } - } + last = traits1::compose(send, out.in); + dest = traits2::compose(sdest, out.out); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + util::in_out_result out{ + beg, ldest}; + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); out = util::in_out_result{beg, ldest}; @@ -108,103 +95,98 @@ namespace hpx::parallel { out = dispatch(traits2::get_id(sdest), algo, policy, std::true_type(), beg, end, ldest); } - last = traits1::compose(send, out.in); - dest = traits2::compose(sdest, out.out); } - return result::get(util::in_out_result{ - HPX_MOVE(last), HPX_MOVE(dest)}); + + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + out = + util::in_out_result{ + beg, ldest}; + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest); + } + last = traits1::compose(send, out.in); + dest = traits2::compose(sdest, out.out); } + return result::get(util::in_out_result{ + HPX_MOVE(last), HPX_MOVE(dest)}); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_copy(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, OutIter dest, std::false_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; + + using result = util::detail::algorithm_result>; + + using forced_seq = std::integral_constant>; - // parallel remote implementation - template - static util::detail::algorithm_result_t> - segmented_copy(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, OutIter dest, std::false_type) + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + using segment_type = std::vector>>; + segment_type segments; + segments.reserve(std::distance(sit, send)); + + if (sit == send) { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; - - using result = util::detail::algorithm_result>; - - using forced_seq = std::integral_constant>; - - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); - - using segment_type = - std::vector>>; - segment_type segments; - segments.reserve(std::distance(sit, send)); - - if (sit == send) + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest)); - } - else - { - segments.push_back(hpx::make_ready_future( - util::in_out_result{beg, ldest})); - } + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest)); } else { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest)); - } - else - { - segments.push_back(hpx::make_ready_future( - util::in_out_result{beg, ldest})); - } - - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - segments.push_back( - dispatch_async(traits2::get_id(sdest), algo, policy, - forced_seq(), beg, end, ldest)); - } - else - { - segments.push_back(hpx::make_ready_future( - util::in_out_result{beg, ldest})); - } - } + segments.push_back(hpx::make_ready_future( + util::in_out_result{beg, ldest})); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) + { + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest)); + } + else + { + segments.push_back(hpx::make_ready_future( + util::in_out_result{beg, ldest})); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); if (beg != end) { @@ -219,23 +201,38 @@ namespace hpx::parallel { } } - return result::get(dataflow( - [=](segment_type&& r) -> util::in_out_result { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - auto ft = r.back().get(); - auto olast = traits1::compose(send, ft.in); - auto odest = traits2::compose(sdest, ft.out); - return util::in_out_result{olast, odest}; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest)); + } + else + { + segments.push_back(hpx::make_ready_future( + util::in_out_result{beg, ldest})); + } } - } // namespace detail + return result::get(dataflow( + [=](segment_type&& r) -> util::in_out_result { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + auto ft = r.back().get(); + auto olast = traits1::compose(send, ft.in); + auto odest = traits2::compose(sdest, ft.out); + return util::in_out_result{olast, odest}; + }, + HPX_MOVE(segments))); + } /// \endcond -} // namespace hpx::parallel +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { @@ -244,7 +241,7 @@ namespace hpx::segmented { // segmented copy - tag_invoke overloads // no-policy (sequential) overload - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -274,7 +271,8 @@ namespace hpx::segmented { } // execution-policy overload - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -310,5 +308,4 @@ namespace hpx::segmented { typename iterator_traits2::local_iterator>>(), HPX_FORWARD(ExPolicy, policy), first, last, dest, is_seq{})); } - } // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/count.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/count.hpp index f5f25e9c2509..295d84c67fc9 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/count.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/count.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -9,6 +9,7 @@ #include #include #include + #include #include @@ -20,70 +21,60 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { + /////////////////////////////////////////////////////////////////////////// // segmented_count - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result::difference_type>::type - segmented_count(Algo&& algo, ExPolicy const& policy, SegIterB first, - SegIterE last, T const& value, Proj&& proj, std::true_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef typename std::iterator_traits::difference_type - value_type; - typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + /// \cond NOINTERNAL - value_type overall_result = value_type(); + // sequential remote implementation + template + util::detail::algorithm_result_t::difference_type> + segmented_count(Algo&& algo, ExPolicy const& policy, SegIterB first, + SegIterE last, T const& value, Proj&& proj, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef + typename std::iterator_traits::difference_type value_type; + typedef util::detail::algorithm_result result; - if (sit == send) + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); + + value_type overall_result = value_type(); + + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - overall_result = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, value, proj); - } + overall_result = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, value, proj); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - overall_result += dispatch(traits::get_id(sit), algo, - policy, std::true_type(), beg, end, value, proj); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - overall_result += dispatch(traits::get_id(sit), algo, - policy, std::true_type(), beg, end, value, proj); - } - } + overall_result += dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, value, proj); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { overall_result += dispatch(traits::get_id(sit), algo, @@ -91,72 +82,71 @@ namespace hpx { namespace parallel { } } - return result::get(HPX_MOVE(overall_result)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + overall_result += dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, value, proj); + } } - // parallel remote implementation - template - static typename util::detail::algorithm_result::difference_type>::type - segmented_count(Algo&& algo, ExPolicy const& policy, SegIterB first, - SegIterE last, T const& value, Proj&& proj, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; + return result::get(HPX_MOVE(overall_result)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t::difference_type> + segmented_count(Algo&& algo, ExPolicy const& policy, SegIterB first, + SegIterE last, T const& value, Proj&& proj, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; - typedef std::integral_constant> - forced_seq; + typedef std::integral_constant> + forced_seq; - typedef typename std::iterator_traits::difference_type - value_type; - typedef util::detail::algorithm_result result; + typedef + typename std::iterator_traits::difference_type value_type; + typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(detail::distance(sit, send)); + std::vector> segments; + segments.reserve(detail::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, value, proj)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, value, proj)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, value, proj)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, value, proj)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, value, proj)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -164,185 +154,188 @@ namespace hpx { namespace parallel { } } - return result::get( - dataflow(hpx::unwrapping([=](std::vector&& r) { - return detail::accumulate(r.begin(), r.end(), value_type()); - }), - segments)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, value, proj)); + } } - /// \endcond - } // namespace detail - /////////////////////////////////////////////////////////////////////////// - // segmented_count_if - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result::difference_type>::type - segmented_count_if(Algo&& algo, ExPolicy const& policy, SegIterB first, - SegIterE last, F&& f, Proj&& proj, std::true_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef typename std::iterator_traits::difference_type - value_type; - typedef util::detail::algorithm_result result; + return result::get( + dataflow(hpx::unwrapping([=](std::vector&& r) { + return detail::accumulate(r.begin(), r.end(), value_type()); + }), + segments)); + } + /// \endcond + + /////////////////////////////////////////////////////////////////////// + /// \cond NOINTERNAL + + // sequential remote implementation + template + util::detail::algorithm_result_t::difference_type> + segmented_count_if(Algo&& algo, ExPolicy const& policy, SegIterB first, + SegIterE last, F&& f, Proj&& proj, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef + typename std::iterator_traits::difference_type value_type; + typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - value_type overall_result = value_type(); + value_type overall_result = value_type(); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - overall_result = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, HPX_FORWARD(F, f), - HPX_FORWARD(Proj, proj)); - } + overall_result = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, HPX_FORWARD(F, f), + HPX_FORWARD(Proj, proj)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - overall_result += dispatch(traits::get_id(sit), algo, - policy, std::true_type(), beg, end, f, proj); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - overall_result += dispatch(traits::get_id(sit), algo, - policy, std::true_type(), beg, end, f, proj); - } - } + overall_result += dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { overall_result += dispatch(traits::get_id(sit), algo, - policy, std::true_type(), beg, end, HPX_FORWARD(F, f), - HPX_FORWARD(Proj, proj)); + policy, std::true_type(), beg, end, f, proj); } } - return result::get(HPX_MOVE(overall_result)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + overall_result += dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, HPX_FORWARD(F, f), + HPX_FORWARD(Proj, proj)); + } } - // parallel remote implementation - template - static typename util::detail::algorithm_result::difference_type>::type - segmented_count_if(Algo&& algo, ExPolicy const& policy, SegIterB first, - SegIterE last, F&& f, Proj&& proj, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; + return result::get(HPX_MOVE(overall_result)); + } - typedef std::integral_constant> - forced_seq; + // parallel remote implementation + template + util::detail::algorithm_result_t::difference_type> + segmented_count_if(Algo&& algo, ExPolicy const& policy, SegIterB first, + SegIterE last, F&& f, Proj&& proj, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + + typedef std::integral_constant> + forced_seq; - typedef typename std::iterator_traits::difference_type - value_type; - typedef util::detail::algorithm_result result; + typedef + typename std::iterator_traits::difference_type value_type; + typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(detail::distance(sit, send)); + std::vector> segments; + segments.reserve(detail::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, HPX_FORWARD(F, f), - HPX_FORWARD(Proj, proj))); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, HPX_FORWARD(F, f), + HPX_FORWARD(Proj, proj))); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } - - // handle all the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, f, proj)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); + } - // handle the beginning of the last partition + // handle all the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, HPX_FORWARD(F, f), - HPX_FORWARD(Proj, proj))); + policy, forced_seq(), beg, end, f, proj)); } } - return result::get(dataflow( - [=](std::vector>&& r) -> value_type { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - return detail::accumulate(r.begin(), r.end(), value_type(), - [](value_type const& val, - shared_future& curr) { - return val + curr.get(); - }); - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, HPX_FORWARD(F, f), + HPX_FORWARD(Proj, proj))); + } } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + + return result::get(dataflow( + [=](std::vector>&& r) -> value_type { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + return detail::accumulate(r.begin(), r.end(), value_type(), + [](value_type const& val, shared_future& curr) { + return val + curr.get(); + }); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) typename std::iterator_traits::difference_type tag_invoke( @@ -365,12 +358,12 @@ namespace hpx { namespace segmented { std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename hpx::parallel::util::detail::algorithm_result::difference_type>::type + hpx::parallel::util::detail::algorithm_result_t::difference_type> tag_invoke(hpx::count_t, ExPolicy&& policy, SegIter first, SegIter last, T const& value) { @@ -394,7 +387,7 @@ namespace hpx { namespace segmented { is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) typename std::iterator_traits::difference_type tag_invoke( @@ -417,12 +410,12 @@ namespace hpx { namespace segmented { hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename hpx::parallel::util::detail::algorithm_result::difference_type>::type + hpx::parallel::util::detail::algorithm_result_t::difference_type> tag_invoke( hpx::count_if_t, ExPolicy&& policy, SegIter first, SegIter last, F&& f) { @@ -445,4 +438,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f), hpx::identity_v, is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/dispatch.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/dispatch.hpp index 7408bb633b8d..ed7122e95beb 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/dispatch.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/dispatch.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2024 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2021 Giannis Gonidelis // // SPDX-License-Identifier: BSL-1.0 @@ -297,9 +297,8 @@ namespace hpx::parallel::detail { id_type const& id, Algo&& algo, ExPolicy policy, IsSeq, Args&&... args) { using algo_type = std::decay_t; - using result_type = - typename parallel::util::detail::algorithm_result::type; + using result_type = parallel::util::detail::algorithm_result_t; algorithm_invoker_action...)> diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/is_partitioned.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/is_partitioned.hpp index bf475867aae9..1eef64798342 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/is_partitioned.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/is_partitioned.hpp @@ -16,6 +16,7 @@ #include namespace hpx::parallel::detail { + struct local_result { bool local_res; // local is_partitioned result @@ -27,7 +28,7 @@ namespace hpx::parallel::detail { struct seg_is_partitioned : algorithm, local_result> { - seg_is_partitioned() + constexpr seg_is_partitioned() noexcept : algorithm, local_result>("is_partitioned") { } diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/reduce.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/reduce.hpp index 9a2436e2ac94..76e6eeef5e8a 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/reduce.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/reduce.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2017 Ajai V George -// Copyright (c) 2022-2024 Hartmut Kaiser +// Copyright (c) 2022-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -11,6 +11,7 @@ #include #include #include + #include #include @@ -38,8 +39,8 @@ namespace hpx::parallel::detail { } template - static typename util::detail::algorithm_result::type - parallel(ExPolicy&& policy, FwdIter first, FwdIter last, Reduce&& r) + static util::detail::algorithm_result_t parallel( + ExPolicy&& policy, FwdIter first, FwdIter last, Reduce&& r) { return util::partitioner::call( HPX_FORWARD(ExPolicy, policy), first, @@ -76,8 +77,8 @@ namespace hpx::parallel::detail { template - static typename util::detail::algorithm_result::type - parallel(ExPolicy&& policy, FwdIter first, FwdIter last, Reduce&& r, + static util::detail::algorithm_result_t parallel( + ExPolicy&& policy, FwdIter first, FwdIter last, Reduce&& r, Convert&& conv) { return util::partitioner::call( @@ -107,7 +108,7 @@ namespace hpx::parallel::detail { struct seg_transform_reduce_binary : algorithm, T> { - seg_transform_reduce_binary() + constexpr seg_transform_reduce_binary() noexcept : algorithm("transform_reduce_binary") { } @@ -123,9 +124,9 @@ namespace hpx::parallel::detail { template - static typename util::detail::algorithm_result::type - parallel(ExPolicy&& policy, FwdIter1 first1, FwdIter1 last1, - FwdIter2 first2, Reduce&& r, Convert&& conv) + static util::detail::algorithm_result_t parallel( + ExPolicy&& policy, FwdIter1 first1, FwdIter1 last1, FwdIter2 first2, + Reduce&& r, Convert&& conv) { using zip_iterator = hpx::util::zip_iterator; diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/scan.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/scan.hpp index 4e5469af87b4..ec8a826832c7 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/scan.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/scan.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2016 Minh-Khanh Do -// Copyright (c) 2020-2025 Hartmut Kaiser +// Copyright (c) 2020-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -32,251 +32,217 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented scan - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // returns the last value of the scan - // used to compute the next init value - template - T sequential_segmented_scan_T( - InIter first, InIter last, Op&& op, Conv&& conv) - { - T ret = T(); - if (first != last) - { - ret = HPX_INVOKE(conv, *first); - for (++first; first != last; ++first) - { - ret = hpx::invoke(op, ret, hpx::invoke(conv, *first)); - } - } - return ret; - } - - // does a scan and returns last value of the scan - template - struct segmented_scan_T : algorithm, Value> - { - using T = Value; - - segmented_scan_T() - : algorithm, Value>("segmented_scan_T") - { - } - - template - static T sequential( - ExPolicy&&, InIter first, InIter last, Op&& op, Conv&& conv) - { - return sequential_segmented_scan_T( - first, last, HPX_FORWARD(Op, op), HPX_FORWARD(Conv, conv)); - } - template - static typename util::detail::algorithm_result::type - parallel(ExPolicy&& policy, FwdIter first, FwdIter last, Op&& op, - Conv&& conv) - { - using execution_policy_type = std::decay_t; - return util::partitioner::call( - HPX_FORWARD(ExPolicy, policy), first, - std::distance(first, last), - [op, conv](FwdIter part_begin, - std::size_t part_size) mutable -> T { - T ret = hpx::invoke(conv, *part_begin); - if (part_size > 1) - { - // MSVC complains if 'op' is captured by reference - util::const_loop_n( - part_begin + 1, part_size - 1, - [&ret, op, conv]( - FwdIter const& curr) mutable -> void { - ret = hpx::invoke( - op, ret, hpx::invoke(conv, *curr)); - }); - } - return ret; - }, - hpx::unwrapping([op](auto&& results) mutable -> T { - T ret = *results.begin(); - if (results.size() > 1) - { - // MSVC complains if 'op' is captured by reference - util::const_loop_n( - results.begin() + 1, results.size() - 1, - [&ret, op]( - typename std::vector::iterator const& - curr) mutable { - ret = hpx::invoke(op, ret, *curr); - }); - } - return ret; - })); - } - }; + /// \cond NOINTERNAL - // do the scan (exclusive/inclusive) - // does not return anything - template - struct segmented_scan_void : algorithm> + // returns the last value of the scan used to compute the next init value + template + T sequential_segmented_scan_t( + InIter first, InIter last, Op&& op, Conv&& conv) + { + T ret = T(); + if (first != last) { - segmented_scan_void() - : algorithm>("segmented_scan_void") + ret = HPX_INVOKE(conv, *first); + for (++first; first != last; ++first) { + ret = hpx::invoke(op, ret, hpx::invoke(conv, *first)); } + } + return ret; + } - template - static hpx::util::unused_type sequential(ExPolicy&& policy, - InIter first, InIter last, OutIter dest, T&& init, Op&& op, - Conv&& conv) - { - Algo().sequential(HPX_FORWARD(ExPolicy, policy), first, last, - dest, HPX_FORWARD(T, init), HPX_FORWARD(Op, op), - HPX_FORWARD(Conv, conv)); - - return hpx::util::unused; - } - - template - static typename util::detail::algorithm_result::type - parallel(ExPolicy&& policy, InIter first, InIter last, OutIter dest, - T&& init, Op&& op, Conv&& conv) - { - using result_type = - typename util::detail::algorithm_result::type; + // does a scan and returns last value of the scan + template + struct segmented_scan_t : algorithm, Value> + { + using T = Value; - if (first == last) - return util::detail::algorithm_result::get(); + constexpr segmented_scan_t() noexcept + : algorithm, Value>("segmented_scan_t") + { + } - return hpx::util::void_guard(), - Algo().parallel(HPX_FORWARD(ExPolicy, policy), first, - last, dest, HPX_FORWARD(T, init), - HPX_FORWARD(Op, op), HPX_FORWARD(Conv, conv)); - } - }; + template + static T sequential( + ExPolicy&&, InIter first, InIter last, Op&& op, Conv&& conv) + { + return sequential_segmented_scan_t( + first, last, HPX_FORWARD(Op, op), HPX_FORWARD(Conv, conv)); + } - template - static bool is_segmented_the_same( - SegIter, SegIter, OutIter, std::false_type) + template + static util::detail::algorithm_result_t parallel( + ExPolicy&& policy, FwdIter first, FwdIter last, Op&& op, + Conv&& conv) + { + using execution_policy_type = std::decay_t; + return util::partitioner::call( + HPX_FORWARD(ExPolicy, policy), first, + std::distance(first, last), + [op, conv]( + FwdIter part_begin, std::size_t part_size) mutable -> T { + T ret = hpx::invoke(conv, *part_begin); + if (part_size > 1) + { + // MSVC complains if 'op' is captured by reference + util::const_loop_n( + part_begin + 1, part_size - 1, + [&ret, op, conv]( + FwdIter const& curr) mutable -> void { + ret = hpx::invoke( + op, ret, hpx::invoke(conv, *curr)); + }); + } + return ret; + }, + hpx::unwrapping([op](auto&& results) mutable -> T { + T ret = *results.begin(); + if (results.size() > 1) + { + // MSVC complains if 'op' is captured by reference + util::const_loop_n( + results.begin() + 1, results.size() - 1, + [&ret, op](typename std::vector::iterator const& + curr) mutable { + ret = hpx::invoke(op, ret, *curr); + }); + } + return ret; + })); + } + }; + + // do the scan (exclusive/inclusive) + // does not return anything + template + struct segmented_scan_void : algorithm> + { + constexpr segmented_scan_void() noexcept + : algorithm>("segmented_scan_void") { - return false; } - // check if two segmented iterators are partitioned the same - // partition size and id should be the same - template - static bool is_segmented_the_same( - SegIter first, SegIter last, OutIter dest, std::true_type) + template + static hpx::util::unused_type sequential(ExPolicy&& policy, + InIter first, InIter last, OutIter dest, T&& init, Op&& op, + Conv&& conv) { - using traits_in = hpx::traits::segmented_iterator_traits; - using segment_iterator_in = typename traits_in::segment_iterator; - using local_iterator_type_in = typename traits_in::local_iterator; + Algo().sequential(HPX_FORWARD(ExPolicy, policy), first, last, dest, + HPX_FORWARD(T, init), HPX_FORWARD(Op, op), + HPX_FORWARD(Conv, conv)); - using traits_out = hpx::traits::segmented_iterator_traits; - using segment_iterator_out = typename traits_out::segment_iterator; - using local_iterator_type_out = typename traits_out::local_iterator; + return hpx::util::unused; + } - segment_iterator_in sit_in = traits_in::segment(first); - segment_iterator_in send_in = traits_in::segment(last); + template + static util::detail::algorithm_result_t parallel( + ExPolicy&& policy, InIter first, InIter last, OutIter dest, + T&& init, Op&& op, Conv&& conv) + { + using result_type = util::detail::algorithm_result_t; - segment_iterator_out sit_out = traits_out::segment(dest); + if (first == last) + return util::detail::algorithm_result::get(); - using hpx::naming::get_locality_from_id; + return hpx::util::void_guard(), + Algo().parallel(HPX_FORWARD(ExPolicy, policy), first, last, + dest, HPX_FORWARD(T, init), HPX_FORWARD(Op, op), + HPX_FORWARD(Conv, conv)); + } + }; - if (sit_in == send_in) - { - // all elements on the same partition - local_iterator_type_in beg_in = traits_in::local(first); - local_iterator_type_in end_in = traits_in::local(last); + template + static bool is_segmented_the_same( + SegIter, SegIter, OutIter, std::false_type) + { + return false; + } - local_iterator_type_out beg_out = traits_out::local(dest); - local_iterator_type_out end_out = traits_out::end(sit_out); + // check if two segmented iterators are partitioned the same + // partition size and id should be the same + template + static bool is_segmented_the_same( + SegIter first, SegIter last, OutIter dest, std::true_type) + { + using traits_in = hpx::traits::segmented_iterator_traits; + using segment_iterator_in = typename traits_in::segment_iterator; + using local_iterator_type_in = typename traits_in::local_iterator; - if (beg_in != end_in) - { - id_type const in_id = - get_locality_from_id(traits_in::get_id(sit_in)); - id_type const out_id = - get_locality_from_id(traits_out::get_id(sit_out)); + using traits_out = hpx::traits::segmented_iterator_traits; + using segment_iterator_out = typename traits_out::segment_iterator; + using local_iterator_type_out = typename traits_out::local_iterator; - if (in_id != out_id) - return false; + segment_iterator_in sit_in = traits_in::segment(first); + segment_iterator_in send_in = traits_in::segment(last); - std::size_t const in_dist = std::distance(beg_in, end_in); - std::size_t const out_dist = - std::distance(beg_out, end_out); + segment_iterator_out sit_out = traits_out::segment(dest); - if (out_dist < in_dist) - return false; - } - } - else - { - // handle the remaining part of the first partition - local_iterator_type_in beg_in = traits_in::local(first); - local_iterator_type_in end_in = traits_in::end(sit_in); + using hpx::naming::get_locality_from_id; - local_iterator_type_out beg_out = traits_out::local(dest); - local_iterator_type_out end_out = traits_out::end(sit_out); + if (sit_in == send_in) + { + // all elements on the same partition + local_iterator_type_in beg_in = traits_in::local(first); + local_iterator_type_in end_in = traits_in::local(last); - if (beg_in != end_in) - { - id_type const in_id = - get_locality_from_id(traits_in::get_id(sit_in)); - id_type const out_id = - get_locality_from_id(traits_out::get_id(sit_out)); + local_iterator_type_out beg_out = traits_out::local(dest); + local_iterator_type_out end_out = traits_out::end(sit_out); - if (in_id != out_id) - return false; + if (beg_in != end_in) + { + id_type const in_id = + get_locality_from_id(traits_in::get_id(sit_in)); + id_type const out_id = + get_locality_from_id(traits_out::get_id(sit_out)); - std::size_t const in_dist = std::distance(beg_in, end_in); - std::size_t const out_dist = - std::distance(beg_out, end_out); + if (in_id != out_id) + return false; - if (in_dist != out_dist) - return false; - } + std::size_t const in_dist = std::distance(beg_in, end_in); + std::size_t const out_dist = std::distance(beg_out, end_out); - // handle all partitions - for (++sit_in, ++sit_out; sit_in != send_in; - ++sit_in, ++sit_out) - { - beg_in = traits_in::begin(sit_in); - end_in = traits_in::end(sit_in); + if (out_dist < in_dist) + return false; + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type_in beg_in = traits_in::local(first); + local_iterator_type_in end_in = traits_in::end(sit_in); - beg_out = traits_out::begin(sit_out); - end_out = traits_out::end(sit_out); + local_iterator_type_out beg_out = traits_out::local(dest); + local_iterator_type_out end_out = traits_out::end(sit_out); - if (beg_in != end_in) - { - id_type in_id = - get_locality_from_id(traits_in::get_id(sit_in)); - id_type out_id = - get_locality_from_id(traits_out::get_id(sit_out)); + if (beg_in != end_in) + { + id_type const in_id = + get_locality_from_id(traits_in::get_id(sit_in)); + id_type const out_id = + get_locality_from_id(traits_out::get_id(sit_out)); - if (in_id != out_id) - return false; + if (in_id != out_id) + return false; - std::size_t const in_dist = - std::distance(beg_in, end_in); - std::size_t const out_dist = - std::distance(beg_out, end_out); + std::size_t const in_dist = std::distance(beg_in, end_in); + std::size_t const out_dist = std::distance(beg_out, end_out); - if (in_dist != out_dist) - return false; - } - } + if (in_dist != out_dist) + return false; + } - // handle the last partition + // handle all partitions + for (++sit_in, ++sit_out; sit_in != send_in; ++sit_in, ++sit_out) + { beg_in = traits_in::begin(sit_in); end_in = traits_in::end(sit_in); @@ -285,9 +251,9 @@ namespace hpx::parallel { if (beg_in != end_in) { - id_type const in_id = + id_type in_id = get_locality_from_id(traits_in::get_id(sit_in)); - id_type const out_id = + id_type out_id = get_locality_from_id(traits_out::get_id(sit_out)); if (in_id != out_id) @@ -301,101 +267,111 @@ namespace hpx::parallel { return false; } } - return true; - } - /////////////////////////////////////////////////////////////////////// - // sequential implementation + // handle the last partition + beg_in = traits_in::begin(sit_in); + end_in = traits_in::end(sit_in); - // sequential segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_scan_seq(ExPolicy const& policy, SegIter first, SegIter last, - OutIter dest, Conv&& conv, T const& init, Op&& op, std::true_type) - { - using result = util::detail::algorithm_result; + beg_out = traits_out::begin(sit_out); + end_out = traits_out::end(sit_out); - if (first == last) - return result::get(HPX_MOVE(dest)); + if (beg_in != end_in) + { + id_type const in_id = + get_locality_from_id(traits_in::get_id(sit_in)); + id_type const out_id = + get_locality_from_id(traits_out::get_id(sit_out)); + + if (in_id != out_id) + return false; + + std::size_t const in_dist = std::distance(beg_in, end_in); + std::size_t const out_dist = std::distance(beg_out, end_out); + + if (in_dist != out_dist) + return false; + } + } + return true; + } + + /////////////////////////////////////////////////////////////////////// + // sequential implementation + + // sequential segmented OutIter implementation + template + static util::detail::algorithm_result_t + segmented_scan_seq(ExPolicy const& policy, SegIter first, SegIter last, + OutIter dest, Conv&& conv, T const& init, Op&& op, std::true_type) + { + using result = util::detail::algorithm_result; + + if (first == last) + return result::get(HPX_MOVE(dest)); - using traits_in = hpx::traits::segmented_iterator_traits; - using segment_iterator_in = typename traits_in::segment_iterator; - using local_iterator_type_in = typename traits_in::local_iterator; + using traits_in = hpx::traits::segmented_iterator_traits; + using segment_iterator_in = typename traits_in::segment_iterator; + using local_iterator_type_in = typename traits_in::local_iterator; - using traits_out = hpx::traits::segmented_iterator_traits; - using segment_iterator_out = typename traits_out::segment_iterator; - using local_iterator_type_out = typename traits_out::local_iterator; + using traits_out = hpx::traits::segmented_iterator_traits; + using segment_iterator_out = typename traits_out::segment_iterator; + using local_iterator_type_out = typename traits_out::local_iterator; - using local_iterator_in_tuple = - hpx::tuple; + using local_iterator_in_tuple = + hpx::tuple; - segment_iterator_in sit_in = traits_in::segment(first); - segment_iterator_in send_in = traits_in::segment(last); + segment_iterator_in sit_in = traits_in::segment(first); + segment_iterator_in send_in = traits_in::segment(last); - segment_iterator_out sit_out = traits_out::segment(dest); + segment_iterator_out sit_out = traits_out::segment(dest); - std::vector results; - std::vector in_iters; - std::vector out_segs; - std::vector out_iters; + std::vector results; + std::vector in_iters; + std::vector out_segs; + std::vector out_iters; - // 1. Step: scan on each partition, push last T of scan into results - if (sit_in == send_in) + // 1. Step: scan on each partition, push last T of scan into results + if (sit_in == send_in) + { + // all elements on the same partition + local_iterator_type_in beg = traits_in::local(first); + local_iterator_type_in end = traits_in::local(last); + if (beg != end) { - // all elements on the same partition - local_iterator_type_in beg = traits_in::local(first); - local_iterator_type_in end = traits_in::local(last); - if (beg != end) - { - results.push_back(dispatch(traits_in::get_id(sit_in), - segmented_scan_T(), policy, std::true_type(), beg, - end, op, conv)); - in_iters.push_back(hpx::make_tuple(beg, end)); - out_segs.push_back(sit_out); - out_iters.push_back(traits_out::local(dest)); - } + results.push_back( + dispatch(traits_in::get_id(sit_in), segmented_scan_t(), + policy, std::true_type(), beg, end, op, conv)); + in_iters.push_back(hpx::make_tuple(beg, end)); + out_segs.push_back(sit_out); + out_iters.push_back(traits_out::local(dest)); } - else - { - // handle the remaining part of the first partition - local_iterator_type_in beg = traits_in::local(first); - local_iterator_type_in end = traits_in::end(sit_in); - - if (beg != end) - { - results.push_back(dispatch(traits_in::get_id(sit_in), - segmented_scan_T(), policy, std::true_type(), beg, - end, op, conv)); - in_iters.push_back(hpx::make_tuple(beg, end)); - out_segs.push_back(sit_out); - out_iters.push_back(traits_out::local(dest)); - } + } + else + { + // handle the remaining part of the first partition + local_iterator_type_in beg = traits_in::local(first); + local_iterator_type_in end = traits_in::end(sit_in); - // handle all partitions - for (++sit_in, ++sit_out; sit_in != send_in; - ++sit_in, ++sit_out) - { - beg = traits_in::begin(sit_in); - end = traits_in::end(sit_in); - if (beg != end) - { - results.push_back(dispatch(traits_in::get_id(sit_in), - segmented_scan_T(), policy, std::true_type(), - beg, end, op, conv)); - in_iters.push_back(hpx::make_tuple(beg, end)); - out_segs.push_back(sit_out); - out_iters.push_back(traits_out::begin(sit_out)); - } - } + if (beg != end) + { + results.push_back( + dispatch(traits_in::get_id(sit_in), segmented_scan_t(), + policy, std::true_type(), beg, end, op, conv)); + in_iters.push_back(hpx::make_tuple(beg, end)); + out_segs.push_back(sit_out); + out_iters.push_back(traits_out::local(dest)); + } - // handle the beginning of the last partition + // handle all partitions + for (++sit_in, ++sit_out; sit_in != send_in; ++sit_in, ++sit_out) + { beg = traits_in::begin(sit_in); - end = traits_in::local(last); + end = traits_in::end(sit_in); if (beg != end) { results.push_back(dispatch(traits_in::get_id(sit_in), - segmented_scan_T(), policy, std::true_type(), beg, + segmented_scan_t(), policy, std::true_type(), beg, end, op, conv)); in_iters.push_back(hpx::make_tuple(beg, end)); out_segs.push_back(sit_out); @@ -403,93 +379,96 @@ namespace hpx::parallel { } } - // first init value is the given init value - T last_value = init; - for (std::size_t i = 0; i < results.size(); ++i) + // handle the beginning of the last partition + beg = traits_in::begin(sit_in); + end = traits_in::local(last); + if (beg != end) { - using hpx::get; - local_iterator_type_out out = out_iters[i]; - - // 2. Step: use the init values to dispatch final scan for each - // segment - dispatch(traits_out::get_id(out_segs[i]), - segmented_scan_void(), policy, std::true_type(), - get<0>(in_iters[i]), get<1>(in_iters[i]), out, conv, - last_value, op); - - // 3. Step: compute new init values for the next segment - last_value = op(last_value, results[i]); + results.push_back( + dispatch(traits_in::get_id(sit_in), segmented_scan_t(), + policy, std::true_type(), beg, end, op, conv)); + in_iters.push_back(hpx::make_tuple(beg, end)); + out_segs.push_back(sit_out); + out_iters.push_back(traits_out::begin(sit_out)); } - - OutIter final_dest = dest; - std::advance(final_dest, std::distance(first, last)); - - return result::get(HPX_MOVE(final_dest)); } - // sequential non segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_scan_seq_non(ExPolicy const& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, F1&& f1, - F2&& f2) + // first init value is the given init value + T last_value = init; + for (std::size_t i = 0; i < results.size(); ++i) { - using result = util::detail::algorithm_result; + using hpx::get; + local_iterator_type_out out = out_iters[i]; + + // 2. Step: use the init values to dispatch final scan for each + // segment + dispatch(traits_out::get_id(out_segs[i]), + segmented_scan_void(), policy, std::true_type(), + get<0>(in_iters[i]), get<1>(in_iters[i]), out, conv, last_value, + op); + + // 3. Step: compute new init values for the next segment + last_value = op(last_value, results[i]); + } - if (first == last) - return result::get(HPX_MOVE(dest)); + OutIter final_dest = dest; + std::advance(final_dest, std::distance(first, last)); + + return result::get(HPX_MOVE(final_dest)); + } + + // sequential non segmented OutIter implementation + template + static util::detail::algorithm_result_t + segmented_scan_seq_non(ExPolicy const& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, F1&& f1, F2&& f2) + { + using result = util::detail::algorithm_result; + + if (first == last) + return result::get(HPX_MOVE(dest)); - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - using vector_type = std::vector; + using vector_type = std::vector; - std::vector results; + std::vector results; - // scan on each partition, push whole result vector into results - if (sit == send) + // scan on each partition, push whole result vector into results + if (sit == send) + { + // all elements on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - results.push_back(dispatch(traits::get_id(sit), Algo(), - policy, std::true_type(), beg, end, op)); - } + results.push_back(dispatch(traits::get_id(sit), Algo(), policy, + std::true_type(), beg, end, op)); } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - - if (beg != end) - { - results.push_back(dispatch(traits::get_id(sit), Algo(), - policy, std::true_type(), beg, end, op)); - } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); - // handle all partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - results.push_back(dispatch(traits::get_id(sit), Algo(), - policy, std::true_type(), beg, end, op)); - } - } + if (beg != end) + { + results.push_back(dispatch(traits::get_id(sit), Algo(), policy, + std::true_type(), beg, end, op)); + } - // handle the beginning of the last partition + // handle all partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { results.push_back(dispatch(traits::get_id(sit), Algo(), @@ -497,275 +476,270 @@ namespace hpx::parallel { } } - // merge results with given merge algorithm f1 - // update init value with function f2 - T last_value = init; - for (auto res : results) + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) { - dest = f1(res.begin(), res.end(), dest, last_value, op); + results.push_back(dispatch(traits::get_id(sit), Algo(), policy, + std::true_type(), beg, end, op)); + } + } + + // merge results with given merge algorithm f1 + // update init value with function f2 + T last_value = init; + for (auto res : results) + { + dest = f1(res.begin(), res.end(), dest, last_value, op); #if defined(HPX_GCC_VERSION) && HPX_GCC_VERSION >= 100000 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Warray-bounds" #endif - last_value = f2(res, last_value); + last_value = f2(res, last_value); #if defined(HPX_GCC_VERSION) && HPX_GCC_VERSION >= 100000 #pragma GCC diagnostic pop #endif - } - return result::get(HPX_MOVE(dest)); } + return result::get(HPX_MOVE(dest)); + } + + /////////////////////////////////////////////////////////////////////// + // parallel implementation + + // parallel segmented OutIter implementation + template + static util::detail::algorithm_result_t + segmented_scan_par(ExPolicy const& policy, SegIter first, SegIter last, + OutIter dest, Conv&& conv, T const& init, Op&& op, std::true_type) + { + using result = util::detail::algorithm_result; + + if (first == last) + return result::get(HPX_MOVE(dest)); - /////////////////////////////////////////////////////////////////////// - // parallel implementation - - // parallel segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_scan_par(ExPolicy const& policy, SegIter first, SegIter last, - OutIter dest, Conv&& conv, T const& init, Op&& op, std::true_type) - { - using result = util::detail::algorithm_result; - - if (first == last) - return result::get(HPX_MOVE(dest)); - - using traits_in = hpx::traits::segmented_iterator_traits; - using segment_iterator_in = typename traits_in::segment_iterator; - using local_iterator_type_in = typename traits_in::local_iterator; + using traits_in = hpx::traits::segmented_iterator_traits; + using segment_iterator_in = typename traits_in::segment_iterator; + using local_iterator_type_in = typename traits_in::local_iterator; - using traits_out = hpx::traits::segmented_iterator_traits; - using segment_iterator_out = typename traits_out::segment_iterator; - using local_iterator_type_out = typename traits_out::local_iterator; + using traits_out = hpx::traits::segmented_iterator_traits; + using segment_iterator_out = typename traits_out::segment_iterator; + using local_iterator_type_out = typename traits_out::local_iterator; - using difference_type = typename std::iterator_traits< - segment_iterator_in>::difference_type; + using difference_type = + typename std::iterator_traits::difference_type; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - using local_iterator_in_tuple = - hpx::tuple; + using local_iterator_in_tuple = + hpx::tuple; - segment_iterator_in sit_in = traits_in::segment(first); - segment_iterator_in send_in = traits_in::segment(last); + segment_iterator_in sit_in = traits_in::segment(first); + segment_iterator_in send_in = traits_in::segment(last); - segment_iterator_out sit_out = traits_out::segment(dest); + segment_iterator_out sit_out = traits_out::segment(dest); - difference_type count = std::distance(sit_in, send_in); + difference_type count = std::distance(sit_in, send_in); - std::vector> results; - std::vector in_iters; - std::vector out_segs; - std::vector out_iters; + std::vector> results; + std::vector in_iters; + std::vector out_segs; + std::vector out_iters; - results.reserve(count); - in_iters.reserve(count); - out_iters.reserve(count); + results.reserve(count); + in_iters.reserve(count); + out_iters.reserve(count); - // 1. Step: scan on each partition, push last T of scan into results - if (sit_in == send_in) + // 1. Step: scan on each partition, push last T of scan into results + if (sit_in == send_in) + { + // all elements on the same partition + local_iterator_type_in beg = traits_in::local(first); + local_iterator_type_in end = traits_in::local(last); + if (beg != end) { - // all elements on the same partition - local_iterator_type_in beg = traits_in::local(first); - local_iterator_type_in end = traits_in::local(last); - if (beg != end) - { - in_iters.push_back(hpx::make_tuple(beg, end)); - out_segs.push_back(sit_out); - out_iters.push_back(traits_out::local(dest)); - results.push_back(dispatch_async(traits_in::get_id(sit_in), - segmented_scan_T(), policy, forced_seq(), beg, end, - op, conv)); - } + in_iters.push_back(hpx::make_tuple(beg, end)); + out_segs.push_back(sit_out); + out_iters.push_back(traits_out::local(dest)); + results.push_back(dispatch_async(traits_in::get_id(sit_in), + segmented_scan_t(), policy, forced_seq(), beg, end, op, + conv)); } - else - { - // handle the remaining part of the first partition - local_iterator_type_in beg = traits_in::local(first); - local_iterator_type_in end = traits_in::end(sit_in); - - if (beg != end) - { - in_iters.push_back(hpx::make_tuple(beg, end)); - out_segs.push_back(sit_out); - out_iters.push_back(traits_out::local(dest)); - results.push_back(dispatch_async(traits_in::get_id(sit_in), - segmented_scan_T(), policy, forced_seq(), beg, end, - op, conv)); - } + } + else + { + // handle the remaining part of the first partition + local_iterator_type_in beg = traits_in::local(first); + local_iterator_type_in end = traits_in::end(sit_in); - // handle all partitions - for (++sit_in, ++sit_out; sit_in != send_in; - ++sit_in, ++sit_out) - { - beg = traits_in::begin(sit_in); - end = traits_in::end(sit_in); - if (beg != end) - { - in_iters.push_back(hpx::make_tuple(beg, end)); - out_segs.push_back(sit_out); - out_iters.push_back(traits_out::begin(sit_out)); - results.push_back(dispatch_async( - traits_in::get_id(sit_in), segmented_scan_T(), - policy, forced_seq(), beg, end, op, conv)); - } - } + if (beg != end) + { + in_iters.push_back(hpx::make_tuple(beg, end)); + out_segs.push_back(sit_out); + out_iters.push_back(traits_out::local(dest)); + results.push_back(dispatch_async(traits_in::get_id(sit_in), + segmented_scan_t(), policy, forced_seq(), beg, end, op, + conv)); + } - // handle the beginning of the last partition + // handle all partitions + for (++sit_in, ++sit_out; sit_in != send_in; ++sit_in, ++sit_out) + { beg = traits_in::begin(sit_in); - end = traits_in::local(last); + end = traits_in::end(sit_in); if (beg != end) { in_iters.push_back(hpx::make_tuple(beg, end)); out_segs.push_back(sit_out); out_iters.push_back(traits_out::begin(sit_out)); results.push_back(dispatch_async(traits_in::get_id(sit_in), - segmented_scan_T(), policy, forced_seq(), beg, end, + segmented_scan_t(), policy, forced_seq(), beg, end, op, conv)); } } - std::vector> workitems; - workitems.reserve(results.size() + 1); - - std::vector> finalitems; - finalitems.reserve(results.size()); - - // first init value is the given init value - workitems.push_back(make_ready_future(init)); + // handle the beginning of the last partition + beg = traits_in::begin(sit_in); + end = traits_in::local(last); + if (beg != end) + { + in_iters.push_back(hpx::make_tuple(beg, end)); + out_segs.push_back(sit_out); + out_iters.push_back(traits_out::begin(sit_out)); + results.push_back(dispatch_async(traits_in::get_id(sit_in), + segmented_scan_t(), policy, forced_seq(), beg, end, op, + conv)); + } + } - using op_type = std::decay_t; - using conv_type = std::decay_t; - auto op_ptr = std::make_shared(HPX_FORWARD(Op, op)); - auto conv_ptr = - std::make_shared(HPX_FORWARD(Conv, conv)); + std::vector> workitems; + workitems.reserve(results.size() + 1); - std::size_t i = 0; + std::vector> finalitems; + finalitems.reserve(results.size()); - for (auto const& res : results) - { - using hpx::get; - segment_iterator_out out_it = out_segs[i]; - local_iterator_type_out out = out_iters[i]; - local_iterator_in_tuple in_tuple = in_iters[i]; - - // 2. Step: use the init values to dispatch final scan for each - // segment performed as soon as the init values are ready - // wait for 1. step of current partition to prevent race condition - // when used in place - finalitems.push_back(hpx::dataflow(policy.executor(), - hpx::unwrapping([=](T last_value, T) mutable -> void { - dispatch(traits_out::get_id(out_it), - segmented_scan_void(), hpx::execution::seq, - std::true_type(), get<0>(in_tuple), - get<1>(in_tuple), out, *conv_ptr, last_value, - *op_ptr); - }), - workitems.back(), res)); - - // 3. Step: compute new init value for the next segment - // performed as soon as the needed results are ready - workitems.push_back(hpx::dataflow(policy.executor(), - hpx::unwrapping([=](T lhs, T rhs) { - return hpx::invoke(*op_ptr, lhs, rhs); - }), - workitems.back(), res)); - ++i; - } + // first init value is the given init value + workitems.push_back(make_ready_future(init)); - OutIter final_dest = dest; - std::advance(final_dest, std::distance(first, last)); + using op_type = std::decay_t; + using conv_type = std::decay_t; + auto op_ptr = std::make_shared(HPX_FORWARD(Op, op)); + auto conv_ptr = std::make_shared(HPX_FORWARD(Conv, conv)); - // wait for all tasks to finish - return result::get(hpx::dataflow( - [final_dest](std::vector>&&, - std::vector>&&, - std::vector>&&) mutable -> OutIter { - return final_dest; - }, - HPX_MOVE(results), HPX_MOVE(workitems), HPX_MOVE(finalitems))); - } + std::size_t i = 0; - // parallel non-segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_scan_par_non(ExPolicy const& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, F1&& f1, - F2&& f2) + for (auto const& res : results) { - using result = util::detail::algorithm_result; + using hpx::get; + segment_iterator_out out_it = out_segs[i]; + local_iterator_type_out out = out_iters[i]; + local_iterator_in_tuple in_tuple = in_iters[i]; + + // 2. Step: use the init values to dispatch final scan for each + // segment performed as soon as the init values are ready wait for + // 1. step of current partition to prevent race condition when used + // in place + finalitems.push_back(hpx::dataflow(policy.executor(), + hpx::unwrapping([=](T last_value, T) mutable -> void { + dispatch(traits_out::get_id(out_it), + segmented_scan_void(), hpx::execution::seq, + std::true_type(), get<0>(in_tuple), get<1>(in_tuple), + out, *conv_ptr, last_value, *op_ptr); + }), + workitems.back(), res)); + + // 3. Step: compute new init value for the next segment + // performed as soon as the needed results are ready + workitems.push_back(hpx::dataflow(policy.executor(), + hpx::unwrapping([=](T lhs, T rhs) { + return hpx::invoke(*op_ptr, lhs, rhs); + }), + workitems.back(), res)); + ++i; + } - if (first == last) - return result::get(HPX_MOVE(dest)); + OutIter final_dest = dest; + std::advance(final_dest, std::distance(first, last)); + + // wait for all tasks to finish + return result::get(hpx::dataflow( + [final_dest](std::vector>&&, + std::vector>&&, + std::vector>&&) mutable -> OutIter { + return final_dest; + }, + HPX_MOVE(results), HPX_MOVE(workitems), HPX_MOVE(finalitems))); + } + + // parallel non-segmented OutIter implementation + template + static typename util::detail::algorithm_result::type + segmented_scan_par_non(ExPolicy const& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, F1&& f1, F2&& f2) + { + using result = util::detail::algorithm_result; + + if (first == last) + return result::get(HPX_MOVE(dest)); - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using difference_type = typename std::iterator_traits< - segment_iterator>::difference_type; + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using difference_type = + typename std::iterator_traits::difference_type; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - difference_type count = std::distance(sit, send); + difference_type count = std::distance(sit, send); - using vector_type = std::vector; - std::vector> results; - results.reserve(count); + using vector_type = std::vector; + std::vector> results; + results.reserve(count); - std::vector segment_sizes; - segment_sizes.reserve(count); + std::vector segment_sizes; + segment_sizes.reserve(count); - OutIter final_dest = dest; - std::advance(final_dest, std::distance(first, last)); + OutIter final_dest = dest; + std::advance(final_dest, std::distance(first, last)); - // scan on each partition, push whole result vector into results - if (sit == send) + // scan on each partition, push whole result vector into results + if (sit == send) + { + // all elements on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - results.push_back(dispatch_async(traits::get_id(sit), - Algo(), policy, forced_seq(), beg, end, op)); - segment_sizes.push_back(std::distance(beg, end)); - } + results.push_back(dispatch_async(traits::get_id(sit), Algo(), + policy, forced_seq(), beg, end, op)); + segment_sizes.push_back(std::distance(beg, end)); } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - - if (beg != end) - { - results.push_back(dispatch_async(traits::get_id(sit), - Algo(), policy, forced_seq(), beg, end, op)); - segment_sizes.push_back(std::distance(beg, end)); - } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); - // handle all partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - results.push_back(dispatch_async(traits::get_id(sit), - Algo(), policy, forced_seq(), beg, end, op)); - segment_sizes.push_back(std::distance(beg, end)); - } - } + if (beg != end) + { + results.push_back(dispatch_async(traits::get_id(sit), Algo(), + policy, forced_seq(), beg, end, op)); + segment_sizes.push_back(std::distance(beg, end)); + } - // handle the beginning of the last partition + // handle all partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { results.push_back(dispatch_async(traits::get_id(sit), @@ -774,55 +748,65 @@ namespace hpx::parallel { } } - std::vector> workitems; - workitems.reserve(results.size() + 1); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + results.push_back(dispatch_async(traits::get_id(sit), Algo(), + policy, forced_seq(), beg, end, op)); + segment_sizes.push_back(std::distance(beg, end)); + } + } - std::vector> finalitems; - finalitems.reserve(results.size()); + std::vector> workitems; + workitems.reserve(results.size() + 1); - workitems.push_back(make_ready_future(init)); + std::vector> finalitems; + finalitems.reserve(results.size()); - using op_type = std::decay_t; - using f1_type = std::decay_t; - using f2_type = std::decay_t; - auto op_ptr = std::make_shared(HPX_FORWARD(Op, op)); - auto f1_ptr = std::make_shared(HPX_FORWARD(F1, f1)); - auto f2_ptr = std::make_shared(HPX_FORWARD(F2, f2)); + workitems.push_back(make_ready_future(init)); - std::size_t segment_index = 0; + using op_type = std::decay_t; + using f1_type = std::decay_t; + using f2_type = std::decay_t; + auto op_ptr = std::make_shared(HPX_FORWARD(Op, op)); + auto f1_ptr = std::make_shared(HPX_FORWARD(F1, f1)); + auto f2_ptr = std::make_shared(HPX_FORWARD(F2, f2)); - for (auto const& res : results) - { - // collect all results with updated init values - finalitems.push_back(hpx::dataflow(policy.executor(), - hpx::unwrapping([=](T last_value, vector_type r) mutable { - // merge function - hpx::invoke(*f1_ptr, r.begin(), r.end(), dest, - last_value, *op_ptr); - }), - workitems.back(), res)); - - std::advance(dest, segment_sizes[segment_index++]); - - // propagate results from left to right - // new init value is most right value combined with old init - workitems.push_back(hpx::dataflow(policy.executor(), - hpx::unwrapping([=](T last_value, vector_type v) { - return hpx::invoke(*op_ptr, last_value, - hpx::invoke(*f2_ptr, HPX_MOVE(v))); - }), - workitems.back(), res)); - } + std::size_t segment_index = 0; - // wait for all tasks to finish - return result::get(hpx::dataflow( - [final_dest](std::vector>&&, - std::vector>&&, - std::vector>&&) mutable -> OutIter { - return final_dest; - }, - HPX_MOVE(results), HPX_MOVE(workitems), HPX_MOVE(finalitems))); + for (auto const& res : results) + { + // collect all results with updated init values + finalitems.push_back(hpx::dataflow(policy.executor(), + hpx::unwrapping([=](T last_value, vector_type r) mutable { + // merge function + hpx::invoke( + *f1_ptr, r.begin(), r.end(), dest, last_value, *op_ptr); + }), + workitems.back(), res)); + + std::advance(dest, segment_sizes[segment_index++]); + + // propagate results from left to right + // new init value is most right value combined with old init + workitems.push_back(hpx::dataflow(policy.executor(), + hpx::unwrapping([=](T last_value, vector_type v) { + return hpx::invoke( + *op_ptr, last_value, hpx::invoke(*f2_ptr, HPX_MOVE(v))); + }), + workitems.back(), res)); } - /// \endcond - } // namespace detail -} // namespace hpx::parallel + + // wait for all tasks to finish + return result::get(hpx::dataflow( + [final_dest](std::vector>&&, + std::vector>&&, + std::vector>&&) mutable -> OutIter { + return final_dest; + }, + HPX_MOVE(results), HPX_MOVE(workitems), HPX_MOVE(finalitems))); + } + /// \endcond +} // namespace hpx::parallel::detail diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/transfer.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/transfer.hpp index 077626159267..d788e166e981 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/transfer.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/detail/transfer.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2024 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -11,6 +11,7 @@ #include #include #include + #include #include @@ -21,63 +22,74 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented transfer - namespace detail { - - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transfer(Algo&& algo, ExPolicy const& policy, std::true_type, - SegIter first, SegIter last, SegOutIter dest) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using output_traits = - hpx::traits::segmented_iterator_traits; - using segment_output_iterator = - typename output_traits::segment_iterator; - using local_output_iterator_type = - typename output_traits::local_iterator; + /// \cond NOINTERNAL + + // sequential remote implementation + template + static util::detail::algorithm_result_t> + segmented_transfer(Algo&& algo, ExPolicy const& policy, std::true_type, + SegIter first, SegIter last, SegOutIter dest) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + + using output_traits = + hpx::traits::segmented_iterator_traits; + using segment_output_iterator = + typename output_traits::segment_iterator; + using local_output_iterator_type = + typename output_traits::local_iterator; - using local_iterator_pair = util::in_out_result; + using local_iterator_pair = util::in_out_result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - segment_output_iterator sdest = traits::segment(dest); + segment_output_iterator sdest = traits::segment(dest); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); + local_iterator_pair p = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, traits::local(dest)); - if (beg != end) - { - local_iterator_pair p = - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, traits::local(dest)); + dest = output_traits::compose(sdest, p.out); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + local_output_iterator_type out = traits::local(dest); - dest = output_traits::compose(sdest, p.out); - } + if (beg != end) + { + local_iterator_pair p = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, out); + out = p.out; } - else + + // handle all full partitions + for ((void) ++sit, ++sdest; sit != send; (void) ++sit, ++sdest) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - local_output_iterator_type out = traits::local(dest); + beg = traits::begin(sit); + end = traits::end(sit); + out = traits::begin(sdest); if (beg != end) { @@ -85,178 +97,162 @@ namespace hpx::parallel { policy, std::true_type(), beg, end, out); out = p.out; } + } - // handle all full partitions - for ((void) ++sit, ++sdest; sit != send; (void) ++sit, ++sdest) - { - beg = traits::begin(sit); - end = traits::end(sit); - out = traits::begin(sdest); - - if (beg != end) - { - local_iterator_pair p = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, out); - out = p.out; - } - } + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + local_iterator_pair p = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, traits::begin(sdest)); + out = p.out; + } - // handle the beginning of the last partition - beg = traits::begin(sit); - end = traits::local(last); - if (beg != end) - { - local_iterator_pair p = - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, traits::begin(sdest)); - out = p.out; - } + dest = output_traits::compose(sdest, out); + } - dest = output_traits::compose(sdest, out); - } + using result_type = util::in_out_result; - using result_type = util::in_out_result; + return util::detail::algorithm_result::get( + result_type{last, dest}); + } - return util::detail::algorithm_result::get( - result_type{last, dest}); - } + // parallel remote implementation + template + static util::detail::algorithm_result_t> + segmented_transfer(Algo&& algo, ExPolicy const& policy, std::false_type, + SegIter first, SegIter last, SegOutIter dest) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; - // parallel remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transfer(Algo&& algo, ExPolicy const& policy, std::false_type, - SegIter first, SegIter last, SegOutIter dest) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; + using output_traits = + hpx::traits::segmented_iterator_traits; + using segment_output_iterator = + typename output_traits::segment_iterator; + using local_output_iterator_type = + typename output_traits::local_iterator; - using output_traits = - hpx::traits::segmented_iterator_traits; - using segment_output_iterator = - typename output_traits::segment_iterator; - using local_output_iterator_type = - typename output_traits::local_iterator; + using local_iterator_pair = util::in_out_result; - using local_iterator_pair = util::in_out_result; + using forced_seq = + std::integral_constant>; - using forced_seq = - std::integral_constant>; + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_output_iterator sdest = traits::segment(dest); - segment_output_iterator sdest = traits::segment(dest); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); - if (sit == send) + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, traits::local(dest))); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + local_output_iterator_type out = traits::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, traits::local(dest))); - } + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, out)); } - else + + // handle all full partitions + for ((void) ++sit, ++sdest; sit != send; (void) ++sit, ++sdest) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - local_output_iterator_type out = traits::local(dest); + beg = traits::begin(sit); + end = traits::end(sit); + out = traits::begin(sdest); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, policy, forced_seq(), beg, end, out)); } + } - // handle all full partitions - for ((void) ++sit, ++sdest; sit != send; (void) ++sit, ++sdest) - { - beg = traits::begin(sit); - end = traits::end(sit); - out = traits::begin(sdest); - - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, out)); - } - } - - // handle the beginning of the last partition - beg = traits::begin(sit); - end = traits::local(last); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, traits::begin(sdest))); - } + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, traits::begin(sdest))); } - - // NOLINTNEXTLINE(bugprone-use-after-move) - HPX_ASSERT(!segments.empty()); - - return util::detail::algorithm_result>:: - get(hpx::dataflow( - [=](std::vector>&& r) - -> util::in_out_result { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - local_iterator_pair p = r.back().get(); - using result_type = - util::in_out_result; - - return result_type{output_traits::compose(sdest, p.in), - output_traits::compose(sdest, p.out)}; - }, - HPX_MOVE(segments))); } - /////////////////////////////////////////////////////////////////////// - // segmented implementation - template - typename util::detail::algorithm_result>::type - transfer_(ExPolicy&& policy, FwdIter1 first, Sent1 last, FwdIter2 dest, - std::true_type) + // NOLINTNEXTLINE(bugprone-use-after-move) + HPX_ASSERT(!segments.empty()); + + return util::detail::algorithm_result>:: + get(hpx::dataflow( + [=](std::vector>&& r) + -> util::in_out_result { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + local_iterator_pair p = r.back().get(); + using result_type = + util::in_out_result; + + return result_type{output_traits::compose(sdest, p.in), + output_traits::compose(sdest, p.out)}; + }, + HPX_MOVE(segments))); + } + + /////////////////////////////////////////////////////////////////////// + // segmented implementation + HPX_CXX_EXPORT template + util::detail::algorithm_result_t> + transfer_(ExPolicy&& policy, FwdIter1 first, Sent1 last, FwdIter2 dest, + std::true_type) + { + if (first == last) { - if (first == last) - { - using result_type = util::in_out_result; + using result_type = util::in_out_result; - return util::detail::algorithm_result::get(result_type{last, dest}); - } - - using is_seq = hpx::is_sequenced_execution_policy; - return segmented_transfer(Algo(), HPX_FORWARD(ExPolicy, policy), - is_seq(), first, last, dest); + return util::detail::algorithm_result::get( + result_type{last, dest}); } - // forward declare the non-segmented version of this algorithm - template - typename util::detail::algorithm_result>::type - transfer_(ExPolicy&& policy, FwdIter1 first, Sent1 last, FwdIter2 dest, - std::false_type); - - /// \endcond - } // namespace detail -} // namespace hpx::parallel + using is_seq = hpx::is_sequenced_execution_policy; + return segmented_transfer( + Algo(), HPX_FORWARD(ExPolicy, policy), is_seq(), first, last, dest); + } + + // forward declare the non-segmented version of this algorithm + template + util::detail::algorithm_result_t> + transfer_(ExPolicy&& policy, FwdIter1 first, Sent1 last, FwdIter2 dest, + std::false_type); + + /// \endcond +} // namespace hpx::parallel::detail diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/equal.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/equal.hpp index 8f6c3f4250fd..ae28f96f9b90 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/equal.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/equal.hpp @@ -9,6 +9,7 @@ #include #include #include + #include #include @@ -20,191 +21,186 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { + /////////////////////////////////////////////////////////////////////////// // segmented_equal - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result::type - segmented_equal(Algo&& algo, ExPolicy const& policy, SegIter1 first1, - SegIter1 last1, SegIter2 first2, Pred&& pred, std::true_type) - { - // Traits for Vector A - typedef hpx::traits::segmented_iterator_traits traits1; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - // Traits for Vector B - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; + /// \cond NOINTERNAL - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_equal( + Algo&& algo, ExPolicy const& policy, SegIter1 first1, SegIter1 last1, + SegIter2 first2, Pred&& pred, std::true_type) + { + // Traits for Vector A + typedef hpx::traits::segmented_iterator_traits traits1; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; - using result = util::detail::algorithm_result; + // Traits for Vector B + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; - bool overall_result = true; + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); - if (sit1 == send1) + using result = util::detail::algorithm_result; + + bool overall_result = true; + + if (sit1 == send1) + { + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); + if (beg1 != end1) { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); - if (beg1 != end1) - { - overall_result &= dispatch(traits1::get_id(sit1), algo, - policy, std::true_type(), beg1, end1, beg2, - HPX_FORWARD(Pred, pred)); - } + overall_result &= dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, + HPX_FORWARD(Pred, pred)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); + if (beg1 != end1) { - // handle the remaining part of the first partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); - if (beg1 != end1) - { - overall_result = dispatch(traits1::get_id(sit1), algo, - policy, std::true_type(), beg1, end1, beg2, pred); - } + overall_result = dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, pred); + } - // handle all of the full partitions - for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) - { - if (!overall_result) - break; - - beg1 = traits1::begin(sit1); - end1 = traits1::end(sit1); - beg2 = traits2::begin(sit2); - - if (beg1 != end1) - { - overall_result &= dispatch(traits1::get_id(sit1), algo, - policy, std::true_type(), beg1, end1, beg2, pred); - } - } + // handle all of the full partitions + for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) + { + if (!overall_result) + break; - // handle the beginning of the last partition beg1 = traits1::begin(sit1); - end1 = traits1::local(last1); + end1 = traits1::end(sit1); beg2 = traits2::begin(sit2); + if (beg1 != end1) { overall_result &= dispatch(traits1::get_id(sit1), algo, - policy, std::true_type(), beg1, end1, beg2, - HPX_FORWARD(Pred, pred)); + policy, std::true_type(), beg1, end1, beg2, pred); } } - return result::get(HPX_MOVE(overall_result)); + // handle the beginning of the last partition + beg1 = traits1::begin(sit1); + end1 = traits1::local(last1); + beg2 = traits2::begin(sit2); + if (beg1 != end1) + { + overall_result &= dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, + HPX_FORWARD(Pred, pred)); + } } - // parallel remote implementation - template - static typename util::detail::algorithm_result::type - segmented_equal(Algo&& algo, ExPolicy const& policy, SegIter1 first1, - SegIter1 last1, SegIter2 first2, Pred&& pred, std::false_type) - { - // Traits for Vector A - typedef hpx::traits::segmented_iterator_traits traits1; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; + return result::get(HPX_MOVE(overall_result)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_equal( + Algo&& algo, ExPolicy const& policy, SegIter1 first1, SegIter1 last1, + SegIter2 first2, Pred&& pred, std::false_type) + { + // Traits for Vector A + typedef hpx::traits::segmented_iterator_traits traits1; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; - // Traits for Vector B - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; + // Traits for Vector B + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; - typedef std::integral_constant> - forced_seq; + typedef std::integral_constant> + forced_seq; - using result = util::detail::algorithm_result; + using result = util::detail::algorithm_result; - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); - std::vector> segments; - segments.reserve(detail::distance(sit1, send1)); + std::vector> segments; + segments.reserve(detail::distance(sit1, send1)); - if (sit1 == send1) + if (sit1 == send1) + { + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); + if (beg1 != end1) { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, - HPX_FORWARD(Pred, pred))); - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, + HPX_FORWARD(Pred, pred))); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); + if (beg1 != end1) { - // handle the remaining part of the first partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, pred)); - } - - // handle all of the full partitions - for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) - { - beg1 = traits1::begin(sit1); - end1 = traits1::end(sit1); - beg2 = traits2::begin(sit2); - if (beg1 != end1) - { - segments.push_back( - dispatch_async(traits1::get_id(sit1), algo, policy, - forced_seq(), beg1, end1, beg2, pred)); - } - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, pred)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) + { beg1 = traits1::begin(sit1); - end1 = traits1::local(last1); + end1 = traits1::end(sit1); beg2 = traits2::begin(sit2); if (beg1 != end1) { segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, - HPX_FORWARD(Pred, pred))); + algo, policy, forced_seq(), beg1, end1, beg2, pred)); } } - return result::get( - dataflow(hpx::unwrapping([=](std::vector&& r) { - return std::all_of( - r.begin(), r.end(), [](bool v) { return v; }); - }), - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg1 = traits1::begin(sit1); + end1 = traits1::local(last1); + beg2 = traits2::begin(sit2); + if (beg1 != end1) + { + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, + HPX_FORWARD(Pred, pred))); + } } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + + return result::get(dataflow(hpx::unwrapping([=](std::vector&& r) { + return std::all_of(r.begin(), r.end(), [](bool v) { return v; }); + }), + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { - template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -227,8 +223,8 @@ namespace hpx::segmented { first2, HPX_FORWARD(Pred, pred), std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/exclusive_scan.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/exclusive_scan.hpp index c69768e3052d..b1439ba32156 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/exclusive_scan.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/exclusive_scan.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2016 Minh-Khanh Do -// Copyright (c) 2020-2025 Hartmut Kaiser +// Copyright (c) 2020-2026 Hartmut Kaiser // Copyright (c) 2021 Akhil J Nair // // SPDX-License-Identifier: BSL-1.0 @@ -14,6 +14,7 @@ #include #include + #include #include @@ -22,219 +23,212 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { + /////////////////////////////////////////////////////////////////////////// // segmented exclusive_scan - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - struct merge_exclusive_scan + /// \cond NOINTERNAL + + struct merge_exclusive_scan + { + // adds init to each element except for the first one + template + OutIter operator()( + InIter first, InIter last, OutIter dest, T init, Op&& op) { - // adds init to each element except for the first one - template - OutIter operator()( - InIter first, InIter last, OutIter dest, T init, Op&& op) + *dest = init; + for (++first, ++dest; first != last; (void) ++first, ++dest) { - *dest = init; - for (++first, ++dest; first != last; (void) ++first, ++dest) - { - *dest = op(init, *first); - } - return dest; + *dest = op(init, *first); } - }; - - /////////////////////////////////////////////////////////////////////// - // do exclusive scan returns result as vector - // first element of result vector is last T of scan - // (can be used to transfer to the next partition) - // - // first element can be used because it will be - // overwritten by the last T of the previous partition - template - struct segmented_exclusive_scan_vector - : public detail::algorithm, - Value> - { - typedef Value vector_type; + return dest; + } + }; + + /////////////////////////////////////////////////////////////////////// + // do exclusive scan returns result as vector + // first element of result vector is last T of scan + // (can be used to transfer to the next partition) + // + // first element can be used because it will be + // overwritten by the last T of the previous partition + template + struct segmented_exclusive_scan_vector + : detail::algorithm, Value> + { + typedef Value vector_type; - segmented_exclusive_scan_vector() - : segmented_exclusive_scan_vector::algorithm( - "segmented_exclusive_scan_vector") - { - } + constexpr segmented_exclusive_scan_vector() noexcept + : segmented_exclusive_scan_vector::algorithm( + "segmented_exclusive_scan_vector") + { + } - template - static vector_type sequential( - ExPolicy&& policy, InIter first, InIter last, Op&& op) - { - vector_type result(std::distance(first, last)); - - // use first element to save the last T of scan - if (result.size() != 0) - { - exclusive_scan().sequential( - HPX_FORWARD(ExPolicy, policy), first + 1, last, - result.begin() + 1, *first, op); - result[0] = op(result.back(), *(last - 1)); - } - return result; - } + template + static vector_type sequential( + ExPolicy&& policy, InIter first, InIter last, Op&& op) + { + vector_type result(std::distance(first, last)); - template - static typename util::detail::algorithm_result::type - parallel( - ExPolicy&& /* policy */, FwdIter first, FwdIter last, Op&& op) + // use first element to save the last T of scan + if (result.size() != 0) { - using result = - util::detail::algorithm_result; - - vector_type res(std::distance(first, last)); - - // use first element to save last T of scan - return result::get(hpx::dataflow( - [=](vector_type r) { - exclusive_scan() - .parallel(hpx::execution::par, first + 1, last, - r.begin() + 1, *first, op); - r[0] = op(r.back(), *(last - 1)); - return r; - }, - HPX_MOVE(res))); + exclusive_scan().sequential( + HPX_FORWARD(ExPolicy, policy), first + 1, last, + result.begin() + 1, *first, op); + result[0] = op(result.back(), *(last - 1)); } - }; - - /////////////////////////////////////////////////////////////////////// - // sequential implementation - - // sequential segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_exclusive_scan_seq(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::true_type, - Conv&& conv) - { - using traits_out = hpx::traits::segmented_iterator_traits; - return segmented_scan_seq>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, - HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), - std::true_type()); + return result; } - // sequential non segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_exclusive_scan_seq(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::false_type, - Conv&& /* conv */) + template + static util::detail::algorithm_result_t parallel( + ExPolicy&& /* policy */, FwdIter first, FwdIter last, Op&& op) { - using vector_type = std::vector; - return segmented_scan_seq_non< - segmented_exclusive_scan_vector>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), merge_exclusive_scan(), - // new init value is first element from - // segmented_exclusive_scan_vector + last init value - [op](vector_type v, T val) { return op(v.front(), val); }); + using result = + util::detail::algorithm_result; + + vector_type res(std::distance(first, last)); + + // use first element to save last T of scan + return result::get(hpx::dataflow( + [=](vector_type r) { + exclusive_scan().parallel( + hpx::execution::par, first + 1, last, r.begin() + 1, + *first, op); + r[0] = op(r.back(), *(last - 1)); + return r; + }, + HPX_MOVE(res))); } + }; - /////////////////////////////////////////////////////////////////////// - // parallel implementation + /////////////////////////////////////////////////////////////////////// + // sequential implementation - // parallel segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_exclusive_scan_par(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::true_type, - Conv&& conv) - { - using traits_out = hpx::traits::segmented_iterator_traits; - return segmented_scan_par>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, - HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), - std::true_type()); - } + // sequential segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_exclusive_scan_seq(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) + { + using traits_out = hpx::traits::segmented_iterator_traits; + return segmented_scan_seq< + transform_exclusive_scan>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, + HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), + std::true_type()); + } - // parallel non-segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_exclusive_scan_par(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::false_type, - Conv&& /* conv */) - { - using vector_type = std::vector; - return segmented_scan_par_non< - segmented_exclusive_scan_vector>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), merge_exclusive_scan(), - // last T of scan is on the front - // see segmented_exclusive_scan_vector - [](vector_type v) { return v.front(); }); - } + // sequential non segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_exclusive_scan_seq(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::false_type, + Conv&& /* conv */) + { + using vector_type = std::vector; + return segmented_scan_seq_non< + segmented_exclusive_scan_vector>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, init, + HPX_FORWARD(Op, op), merge_exclusive_scan(), + // new init value is first element from + // segmented_exclusive_scan_vector + last init value + [op](vector_type v, T val) { return op(v.front(), val); }); + } - /////////////////////////////////////////////////////////////////////// - // sequential remote implementation - template - static typename util::detail::algorithm_result::type - segmented_exclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, - OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) - { - using is_out_seg = typename hpx::traits::segmented_iterator_traits< - OutIter>::is_segmented_iterator; + /////////////////////////////////////////////////////////////////////// + // parallel implementation - // check if OutIter is segmented in the same way as SegIter - if (is_segmented_the_same(first, last, dest, is_out_seg())) - { - return segmented_exclusive_scan_seq( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), is_out_seg(), HPX_FORWARD(Conv, conv)); - } + // parallel segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_exclusive_scan_par(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) + { + using traits_out = hpx::traits::segmented_iterator_traits; + return segmented_scan_par< + transform_exclusive_scan>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, + HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), + std::true_type()); + } + // parallel non-segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_exclusive_scan_par(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::false_type, + Conv&& /* conv */) + { + using vector_type = std::vector; + return segmented_scan_par_non< + segmented_exclusive_scan_vector>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, init, + HPX_FORWARD(Op, op), merge_exclusive_scan(), + // last T of scan is on the front + // see segmented_exclusive_scan_vector + [](vector_type v) { return v.front(); }); + } + + /////////////////////////////////////////////////////////////////////// + // sequential remote implementation + template + util::detail::algorithm_result_t + segmented_exclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) + { + using is_out_seg = typename hpx::traits::segmented_iterator_traits< + OutIter>::is_segmented_iterator; + + // check if OutIter is segmented in the same way as SegIter + if (is_segmented_the_same(first, last, dest, is_out_seg())) + { return segmented_exclusive_scan_seq(HPX_FORWARD(ExPolicy, policy), - first, last, dest, init, HPX_FORWARD(Op, op), std::false_type(), + first, last, dest, init, HPX_FORWARD(Op, op), is_out_seg(), HPX_FORWARD(Conv, conv)); } - /////////////////////////////////////////////////////////////////////// - // parallel remote implementation - template - static typename util::detail::algorithm_result::type - segmented_exclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, - OutIter dest, T const& init, Op&& op, std::false_type, Conv&& conv) - { - using is_out_seg = typename hpx::traits::segmented_iterator_traits< - OutIter>::is_segmented_iterator; + return segmented_exclusive_scan_seq(HPX_FORWARD(ExPolicy, policy), + first, last, dest, init, HPX_FORWARD(Op, op), std::false_type(), + HPX_FORWARD(Conv, conv)); + } - if (is_segmented_the_same(first, last, dest, is_out_seg())) - { - return segmented_exclusive_scan_par( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), is_out_seg(), HPX_FORWARD(Conv, conv)); - } + /////////////////////////////////////////////////////////////////////// + // parallel remote implementation + template + util::detail::algorithm_result_t + segmented_exclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::false_type, Conv&& conv) + { + using is_out_seg = typename hpx::traits::segmented_iterator_traits< + OutIter>::is_segmented_iterator; + if (is_segmented_the_same(first, last, dest, is_out_seg())) + { return segmented_exclusive_scan_par(HPX_FORWARD(ExPolicy, policy), - first, last, dest, init, HPX_FORWARD(Op, op), std::false_type(), + first, last, dest, init, HPX_FORWARD(Op, op), is_out_seg(), HPX_FORWARD(Conv, conv)); } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + + return segmented_exclusive_scan_par(HPX_FORWARD(ExPolicy, policy), + first, last, dest, init, HPX_FORWARD(Op, op), std::false_type(), + HPX_FORWARD(Conv, conv)); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template > requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -261,8 +255,8 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), std::true_type{}, hpx::identity_v); } - template > + HPX_CXX_EXPORT template > requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -271,9 +265,9 @@ namespace hpx { namespace segmented { hpx::is_invocable_v::value_type, typename std::iterator_traits::value_type>) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::exclusive_scan_t, ExPolicy&& policy, FwdIter1 first, - FwdIter1 last, FwdIter2 dest, T init, Op&& op = Op()) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::exclusive_scan_t, ExPolicy&& policy, FwdIter1 first, FwdIter1 last, + FwdIter2 dest, T init, Op&& op = Op()) { static_assert(std::forward_iterator, "Requires at least forward iterator."); @@ -291,4 +285,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, dest, HPX_MOVE(init), HPX_FORWARD(Op, op), is_seq(), hpx::identity_v); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/fill.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/fill.hpp index 0feaba025012..edc2cc90e0fc 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/fill.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/fill.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2016 Minh-Khanh Do -// Copyright (c) 2024-2025 Hartmut Kaiser +// Copyright (c) 2024-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -10,49 +10,48 @@ #include #include #include + #include #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_fill - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - template - struct fill_function + /// \cond NOINTERNAL + + template + struct fill_function + { + fill_function(T val = T()) + : value_(val) { - fill_function(T val = T()) - : value_(val) - { - } - - T value_; - - void operator()(T& val) const - { - val = value_; - } - - template - void serialize(Archive& ar, unsigned /* version */) - { - // clang-format off + } + + T value_; + + void operator()(T& val) const + { + val = value_; + } + + template + void serialize(Archive& ar, unsigned /* version */) + { + // clang-format off ar & value_; - // clang-format on - } - }; - } // namespace detail + // clang-format on + } + }; /// \endcond -}} // namespace hpx::parallel +} // namespace hpx::parallel::detail -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) SegIter tag_invoke(hpx::fill_t, SegIter first, SegIter last, T const& value) @@ -76,7 +75,7 @@ namespace hpx { namespace segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && std::is_integral_v) @@ -103,12 +102,11 @@ namespace hpx { namespace segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - static typename hpx::parallel::util::detail::algorithm_result::type + hpx::parallel::util::detail::algorithm_result_t tag_invoke(hpx::fill_t, ExPolicy&& policy, SegIter first, SegIter last, T const& value) { @@ -136,13 +134,13 @@ namespace hpx { namespace segmented { hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && std::is_integral_v) - static typename hpx::parallel::util::detail::algorithm_result::type + hpx::parallel::util::detail::algorithm_result_t tag_invoke(hpx::fill_n_t, ExPolicy&& policy, SegIter first, Size count, T const& value) { @@ -170,4 +168,4 @@ namespace hpx { namespace segmented { hpx::parallel::detail::fill_function(value), hpx::identity_v, is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/find.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/find.hpp index d17a79d27b8b..08e82619bf6a 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/find.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/find.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2017 Ajai V George -// Copyright (c) 2024-2025 Hartmut Kaiser +// Copyright (c) 2024-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -10,6 +10,7 @@ #include #include #include + #include #include @@ -21,172 +22,150 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_find - namespace detail { - template - inline typename util::detail::algorithm_result::type - segmented_find(Algo&& algo, ExPolicy&& policy, FwdIter first, - FwdIter last, U&& f_or_val, std::true_type) + template + util::detail::algorithm_result_t segmented_find( + Algo&& algo, ExPolicy&& policy, FwdIter first, FwdIter last, + U&& f_or_val, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef util::detail::algorithm_result result; + + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); + FwdIter output = last; + if (sit == send) { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; - - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); - FwdIter output = last; - if (sit == send) + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - local_iterator_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f_or_val); - output = traits::compose(send, out); - } + local_iterator_type out = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, f_or_val); + output = traits::compose(send, out); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + local_iterator_type out = traits::local(last); + bool found = false; + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - local_iterator_type out = traits::local(last); - bool found = false; - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f_or_val); - if (out != end) - found = true; - } - if (!found) - { - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - out = traits::begin(send); - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f_or_val); - if (out != end) - { - found = true; - break; - } - } - } - } - if (!found) + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f_or_val); + if (out != end) + found = true; + } + if (!found) + { + // handle all of the full partitions + for (++sit; sit != send; ++sit) { - // handle the beginning of the last partition beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); + out = traits::begin(send); if (beg != end) { out = dispatch(traits::get_id(sit), algo, policy, std::true_type(), beg, end, f_or_val); if (out != end) + { found = true; + break; + } } } - if (found) - output = traits::compose(sit, out); } - return result::get(HPX_MOVE(output)); + if (!found) + { + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f_or_val); + if (out != end) + found = true; + } + } + if (found) + output = traits::compose(sit, out); } + return result::get(HPX_MOVE(output)); + } - template - inline typename util::detail::algorithm_result::type - segmented_find(Algo&& algo, ExPolicy&& policy, FwdIter first, - FwdIter last, U&& f_or_val, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; + template + util::detail::algorithm_result_t segmented_find( + Algo&& algo, ExPolicy&& policy, FwdIter first, FwdIter last, + U&& f_or_val, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef util::detail::algorithm_result result; - typedef std::integral_constant> - forced_seq; + typedef std::integral_constant> + forced_seq; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, f_or_val), - [send, end, last]( - local_iterator_type const& out) -> FwdIter { - if (out != end) - return traits::compose(send, out); - else - return last; - })); - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy, + forced_seq(), beg, end, f_or_val), + [send, end, last]( + local_iterator_type const& out) -> FwdIter { + if (out != end) + return traits::compose(send, out); + else + return last; + })); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, f_or_val), - [sit, end, last]( - local_iterator_type const& out) -> FwdIter { - if (out != end) - return traits::compose(sit, out); - else - return last; - })); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, f_or_val), - [sit, end, last]( - local_iterator_type const& out) -> FwdIter { - if (out != end) - return traits::compose(sit, out); - else - return last; - })); - } - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy, + forced_seq(), beg, end, f_or_val), + [sit, end, last]( + local_iterator_type const& out) -> FwdIter { + if (out != end) + return traits::compose(sit, out); + else + return last; + })); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(hpx::make_future( @@ -201,32 +180,49 @@ namespace hpx { namespace parallel { })); } } - return result::get(dataflow( - [=](std::vector>&& r) -> FwdIter { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - std::vector res = hpx::unwrap(HPX_MOVE(r)); - auto it = res.begin(); - while (it != res.end()) - { - if (*it != last) - return *it; - it++; - } - return res.back(); - }, - HPX_MOVE(segments))); + + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy, + forced_seq(), beg, end, f_or_val), + [sit, end, last]( + local_iterator_type const& out) -> FwdIter { + if (out != end) + return traits::compose(sit, out); + else + return last; + })); + } } - } // namespace detail -}} // namespace hpx::parallel + return result::get(dataflow( + [=](std::vector>&& r) -> FwdIter { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + std::vector res = hpx::unwrap(HPX_MOVE(r)); + auto it = res.begin(); + while (it != res.end()) + { + if (*it != last) + return *it; + it++; + } + return res.back(); + }, + HPX_MOVE(segments))); + } +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) SegIter tag_invoke(hpx::find_t, SegIter first, SegIter last, T const& val) @@ -247,12 +243,12 @@ namespace hpx { namespace segmented { hpx::execution::seq, first, last, val, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::find_t, ExPolicy&& policy, SegIter first, SegIter last, + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::find_t, ExPolicy&& policy, SegIter first, SegIter last, T const& val) { static_assert(std::forward_iterator, @@ -274,7 +270,7 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, val, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) FwdIter tag_invoke(hpx::find_if_t, FwdIter first, FwdIter last, F&& f) @@ -296,12 +292,11 @@ namespace hpx { namespace segmented { std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke( + parallel::util::detail::algorithm_result_t tag_invoke( hpx::find_if_t, ExPolicy&& policy, FwdIter first, FwdIter last, F&& f) { static_assert(std::forward_iterator, @@ -324,7 +319,7 @@ namespace hpx { namespace segmented { is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) FwdIter tag_invoke(hpx::find_if_not_t, FwdIter first, FwdIter last, F&& f) @@ -346,13 +341,13 @@ namespace hpx { namespace segmented { std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::find_if_not_t, ExPolicy&& policy, FwdIter first, - FwdIter last, F&& f) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::find_if_not_t, ExPolicy&& policy, FwdIter first, FwdIter last, + F&& f) { static_assert(std::forward_iterator, "Requires at least forward iterator."); @@ -373,4 +368,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f), is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp index 29d762a9b887..24141bc15d22 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -20,142 +20,130 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_for_each - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL + /// \cond NOINTERNAL - // sequential remote implementation - template - static util::detail::algorithm_result_t - segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, Proj&& proj, std::true_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_for_each( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, + Proj&& proj, std::true_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - local_iterator_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f, proj); - last = traits::compose(send, out); - } + local_iterator_type out = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, f, proj); + last = traits::compose(send, out); } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - local_iterator_type out = traits::local(last); - - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + local_iterator_type out = traits::local(last); - // handle all full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - out = traits::begin(send); - - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - } - } + if (beg != end) + { + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); + } - // handle the beginning of the last partition + // handle all full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); + out = traits::begin(send); + if (beg != end) { out = dispatch(traits::get_id(sit), algo, policy, std::true_type(), beg, end, f, proj); } + } - last = traits::compose(send, out); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f, proj); } - return result::get(HPX_MOVE(last)); + last = traits::compose(send, out); } - // parallel remote implementation - template - static util::detail::algorithm_result_t - segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, Proj&& proj, std::false_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + return result::get(HPX_MOVE(last)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_for_each( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, + Proj&& proj, std::false_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; - using forced_seq = - std::integral_constant>; + using forced_seq = + std::integral_constant>; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f, proj)); - } - - // handle all full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, f, proj)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); + } - // handle the beginning of the last partition + // handle all full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -163,25 +151,33 @@ namespace hpx::parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) - -> SegIter { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - return traits::compose(send, r.back().get()); - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f, proj)); + } } - /// \endcond - } // namespace detail -} // namespace hpx::parallel + + return result::get(dataflow( + [=](std::vector>&& r) -> SegIter { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + return traits::compose(send, r.back().get()); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) InIter tag_invoke(hpx::for_each_t, InIter first, InIter last, F&& f) @@ -203,7 +199,7 @@ namespace hpx::segmented { hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) @@ -233,7 +229,7 @@ namespace hpx::segmented { hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) InIter tag_invoke(hpx::for_each_n_t, InIter first, Size count, F&& f) @@ -257,7 +253,8 @@ namespace hpx::segmented { hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/functional/segmented_iterator_helpers.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/functional/segmented_iterator_helpers.hpp index 69c3d2ee1b98..eaa12de87e75 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/functional/segmented_iterator_helpers.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/functional/segmented_iterator_helpers.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2024 Hartmut Kaiser +// Copyright (c) 2015-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -12,7 +12,7 @@ namespace hpx::util::functional { /////////////////////////////////////////////////////////////////////////// - struct segmented_iterator_segment + HPX_CXX_EXPORT struct segmented_iterator_segment { template struct apply @@ -29,7 +29,7 @@ namespace hpx::util::functional { }; }; - struct segmented_iterator_local + HPX_CXX_EXPORT struct segmented_iterator_local { template struct apply @@ -45,7 +45,7 @@ namespace hpx::util::functional { }; }; - struct segmented_iterator_begin + HPX_CXX_EXPORT struct segmented_iterator_begin { template struct apply @@ -61,7 +61,7 @@ namespace hpx::util::functional { }; }; - struct segmented_iterator_end + HPX_CXX_EXPORT struct segmented_iterator_end { template struct apply @@ -77,7 +77,7 @@ namespace hpx::util::functional { }; }; - struct segmented_iterator_local_begin + HPX_CXX_EXPORT struct segmented_iterator_local_begin { template struct apply @@ -93,7 +93,7 @@ namespace hpx::util::functional { }; }; - struct segmented_iterator_local_end + HPX_CXX_EXPORT struct segmented_iterator_local_end { template struct apply diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/generate.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/generate.hpp index 8a91f5a77950..75473d22a1eb 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/generate.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/generate.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -9,6 +9,7 @@ #include #include #include + #include #include @@ -17,140 +18,126 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_generate - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result::type - segmented_generate(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, std::true_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + /// \cond NOINTERNAL + + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_generate( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, + std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef util::detail::algorithm_result result; - if (sit == send) + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); + + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - local_iterator_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f); - last = traits::compose(send, out); - } + local_iterator_type out = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, f); + last = traits::compose(send, out); } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - local_iterator_type out = traits::local(last); - - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f); - } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + local_iterator_type out = traits::local(last); - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - out = dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f); - } - } + if (beg != end) + { + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { out = dispatch(traits::get_id(sit), algo, policy, std::true_type(), beg, end, f); } + } - last = traits::compose(send, out); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + out = dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, f); } - return result::get(HPX_MOVE(last)); + last = traits::compose(send, out); } - // parallel remote implementation - template - static typename util::detail::algorithm_result::type - segmented_generate(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; + return result::get(HPX_MOVE(last)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_generate( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, + std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; - typedef std::integral_constant> - forced_seq; - typedef util::detail::algorithm_result result; + typedef std::integral_constant> + forced_seq; + typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, f)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, f)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -158,24 +145,33 @@ namespace hpx { namespace parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) - -> SegIter { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - return traits::compose(send, r.back().get()); - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, f)); + } } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel -namespace hpx { namespace segmented { + return result::get(dataflow( + [=](std::vector>&& r) + -> SegIter { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + return traits::compose(send, r.back().get()); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail + +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) SegIter tag_invoke(hpx::generate_t, SegIter first, SegIter last, F&& f) @@ -197,7 +193,7 @@ namespace hpx { namespace segmented { std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && std::is_integral_v) @@ -222,12 +218,11 @@ namespace hpx { namespace segmented { std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke( + parallel::util::detail::algorithm_result_t tag_invoke( hpx::generate_t, ExPolicy&& policy, SegIter first, SegIter last, F&& f) { static_assert(std::forward_iterator, @@ -250,13 +245,13 @@ namespace hpx { namespace segmented { is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && std::is_integral_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke( + parallel::util::detail::algorithm_result_t tag_invoke( hpx::generate_n_t, ExPolicy&& policy, SegIter first, Size count, F&& f) { static_assert(std::forward_iterator, @@ -280,4 +275,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f), is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/inclusive_scan.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/inclusive_scan.hpp index 8ade6d1fc42e..0df4be7a238c 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/inclusive_scan.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/inclusive_scan.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2016 Minh-Khanh Do -// Copyright (c) 2020-2025 Hartmut Kaiser +// Copyright (c) 2020-2026 Hartmut Kaiser // Copyright (c) 2021 Akhil J Nair // // SPDX-License-Identifier: BSL-1.0 @@ -15,6 +15,7 @@ #include #include #include + #include #include @@ -23,231 +24,221 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented inclusive_scan - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - // adds init to each element from first to dest - struct merge_inclusive_scan + /// \cond NOINTERNAL + + // adds init to each element from first to dest + struct merge_inclusive_scan + { + template + OutIter operator()( + InIter first, InIter last, OutIter dest, T init, Op&& op) { - template - OutIter operator()( - InIter first, InIter last, OutIter dest, T init, Op&& op) + for (/* */; first != last; (void) ++first, ++dest) { - for (/* */; first != last; (void) ++first, ++dest) - { - *dest = op(init, *first); - } - return dest; + *dest = op(init, *first); } - }; + return dest; + } + }; + + /////////////////////////////////////////////////////////////////////// + + // do inclusive scan returns result as vector + template + struct segmented_inclusive_scan_vector + : public detail::algorithm, Value> + { + using vector_type = Value; - /////////////////////////////////////////////////////////////////////// + constexpr segmented_inclusive_scan_vector() noexcept + : segmented_inclusive_scan_vector::algorithm( + "segmented_inclusive_scan_vector") + { + } - // do inclusive scan returns result as vector - template - struct segmented_inclusive_scan_vector - : public detail::algorithm, - Value> + template + static vector_type sequential( + ExPolicy&& policy, InIter first, InIter last, Op&& op) { - using vector_type = Value; + vector_type result(std::distance(first, last)); - segmented_inclusive_scan_vector() - : segmented_inclusive_scan_vector::algorithm( - "segmented_inclusive_scan_vector") + // use first element as init value for inclusive_scan + if (result.size() != 0) { + result[0] = *first; + inclusive_scan().sequential( + HPX_FORWARD(ExPolicy, policy), first + 1, last, + result.begin() + 1, *first, HPX_FORWARD(Op, op)); } + return result; + } - template - static vector_type sequential( - ExPolicy&& policy, InIter first, InIter last, Op&& op) - { - vector_type result(std::distance(first, last)); - - // use first element as init value for inclusive_scan - if (result.size() != 0) - { - result[0] = *first; - inclusive_scan().sequential( - HPX_FORWARD(ExPolicy, policy), first + 1, last, - result.begin() + 1, *first, HPX_FORWARD(Op, op)); - } - return result; - } + template + static util::detail::algorithm_result_t parallel( + ExPolicy&& /* policy */, FwdIter first, FwdIter last, Op&& op) + { + using result = + util::detail::algorithm_result; - template - static typename util::detail::algorithm_result::type - parallel( - ExPolicy&& /* policy */, FwdIter first, FwdIter last, Op&& op) + vector_type res(std::distance(first, last)); + + // use first element as the init value for inclusive_scan + if (res.size() != 0) { - using result = - util::detail::algorithm_result; - - vector_type res(std::distance(first, last)); - - // use first element as the init value for inclusive_scan - if (res.size() != 0) - { - res[0] = *first; - } - - return result::get(dataflow( - [=](vector_type r) { - inclusive_scan() - .parallel(hpx::execution::par, first + 1, last, - r.begin() + 1, *first, op); - return r; - }, - HPX_MOVE(res))); + res[0] = *first; } - }; - - /////////////////////////////////////////////////////////////////////// - // sequential implementation - - // sequential segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_inclusive_scan_seq(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::true_type, - Conv&& conv) - { - using traits_out = hpx::traits::segmented_iterator_traits; - return segmented_scan_seq>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, - HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), - std::true_type()); + return result::get(dataflow( + [=](vector_type r) { + inclusive_scan().parallel( + hpx::execution::par, first + 1, last, r.begin() + 1, + *first, op); + return r; + }, + HPX_MOVE(res))); } + }; - // sequential non-segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_inclusive_scan_seq(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::false_type, - Conv&& /* conv */) - { - using vector_type = std::vector; - - return segmented_scan_seq_non< - segmented_inclusive_scan_vector>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), merge_inclusive_scan(), - // new init value is last element from - // segmented_inclusive_scan_vector + last init value - [op](vector_type v, T val) { return op(v.back(), val); }); - } + /////////////////////////////////////////////////////////////////////// + // sequential implementation - /////////////////////////////////////////////////////////////////////// - // parallel implementation + // sequential segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_inclusive_scan_seq(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) + { + using traits_out = hpx::traits::segmented_iterator_traits; - // parallel segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_inclusive_scan_par(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::true_type, - Conv&& conv) - { - using traits_out = hpx::traits::segmented_iterator_traits; + return segmented_scan_seq< + transform_inclusive_scan>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, + HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), + std::true_type()); + } - return segmented_scan_par>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, - HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), - std::true_type()); - } + // sequential non-segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_inclusive_scan_seq(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::false_type, + Conv&& /* conv */) + { + using vector_type = std::vector; + + return segmented_scan_seq_non< + segmented_inclusive_scan_vector>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, init, + HPX_FORWARD(Op, op), merge_inclusive_scan(), + // new init value is last element from + // segmented_inclusive_scan_vector + last init value + [op](vector_type v, T val) { return op(v.back(), val); }); + } + + /////////////////////////////////////////////////////////////////////// + // parallel implementation + + // parallel segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_inclusive_scan_par(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) + { + using traits_out = hpx::traits::segmented_iterator_traits; - // parallel non-segmented OutIter implementation - template - static typename util::detail::algorithm_result::type - segmented_inclusive_scan_par(ExPolicy&& policy, SegIter first, - SegIter last, OutIter dest, T const& init, Op&& op, std::false_type, - Conv&&) + return segmented_scan_par< + transform_inclusive_scan>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, + HPX_FORWARD(Conv, conv), init, HPX_FORWARD(Op, op), + std::true_type()); + } + + // parallel non-segmented OutIter implementation + template + util::detail::algorithm_result_t + segmented_inclusive_scan_par(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::false_type, Conv&&) + { + using vector_type = std::vector; + + return segmented_scan_par_non< + segmented_inclusive_scan_vector>( + HPX_FORWARD(ExPolicy, policy), first, last, dest, init, + HPX_FORWARD(Op, op), merge_inclusive_scan(), + // last T of scan is in the back + [](vector_type v) { return v.back(); }); + } + + /////////////////////////////////////////////////////////////////////// + // sequential remote implementation + template + util::detail::algorithm_result_t + segmented_inclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) + { + using is_out_seg = typename hpx::traits::segmented_iterator_traits< + OutIter>::is_segmented_iterator; + + // check if OutIter is segmented in the same way as SegIter + // NOLINTNEXTLINE(bugprone-branch-clone) + if (is_segmented_the_same(first, last, dest, is_out_seg())) { - using vector_type = std::vector; - - return segmented_scan_par_non< - segmented_inclusive_scan_vector>( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), merge_inclusive_scan(), - // last T of scan is in the back - [](vector_type v) { return v.back(); }); + return segmented_inclusive_scan_seq(HPX_FORWARD(ExPolicy, policy), + first, last, dest, init, HPX_FORWARD(Op, op), is_out_seg(), + HPX_FORWARD(Conv, conv)); } - - /////////////////////////////////////////////////////////////////////// - // sequential remote implementation - template - static typename util::detail::algorithm_result::type - segmented_inclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, - OutIter dest, T const& init, Op&& op, std::true_type, Conv&& conv) + else { - using is_out_seg = typename hpx::traits::segmented_iterator_traits< - OutIter>::is_segmented_iterator; - - // check if OutIter is segmented in the same way as SegIter - // NOLINTNEXTLINE(bugprone-branch-clone) - if (is_segmented_the_same(first, last, dest, is_out_seg())) - { - return segmented_inclusive_scan_seq( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), is_out_seg(), HPX_FORWARD(Conv, conv)); - } - else - { - return segmented_inclusive_scan_seq( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), std::false_type(), - HPX_FORWARD(Conv, conv)); - } + return segmented_inclusive_scan_seq(HPX_FORWARD(ExPolicy, policy), + first, last, dest, init, HPX_FORWARD(Op, op), std::false_type(), + HPX_FORWARD(Conv, conv)); } + } - /////////////////////////////////////////////////////////////////////// - // parallel remote implementation - template - static typename util::detail::algorithm_result::type - segmented_inclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, - OutIter dest, T const& init, Op&& op, std::false_type, Conv&& conv) - { - using is_out_seg = typename hpx::traits::segmented_iterator_traits< - OutIter>::is_segmented_iterator; + /////////////////////////////////////////////////////////////////////// + // parallel remote implementation + template + util::detail::algorithm_result_t + segmented_inclusive_scan(ExPolicy&& policy, SegIter first, SegIter last, + OutIter dest, T const& init, Op&& op, std::false_type, Conv&& conv) + { + using is_out_seg = typename hpx::traits::segmented_iterator_traits< + OutIter>::is_segmented_iterator; - // check if OutIter is segmented in the same way as SegIter - // NOLINTNEXTLINE(bugprone-branch-clone) - if (is_segmented_the_same(first, last, dest, is_out_seg())) - { - return segmented_inclusive_scan_par( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), is_out_seg(), HPX_FORWARD(Conv, conv)); - } - else - { - return segmented_inclusive_scan_par( - HPX_FORWARD(ExPolicy, policy), first, last, dest, init, - HPX_FORWARD(Op, op), std::false_type(), - HPX_FORWARD(Conv, conv)); - } + // check if OutIter is segmented in the same way as SegIter + // NOLINTNEXTLINE(bugprone-branch-clone) + if (is_segmented_the_same(first, last, dest, is_out_seg())) + { + return segmented_inclusive_scan_par(HPX_FORWARD(ExPolicy, policy), + first, last, dest, init, HPX_FORWARD(Op, op), is_out_seg(), + HPX_FORWARD(Conv, conv)); + } + else + { + return segmented_inclusive_scan_par(HPX_FORWARD(ExPolicy, policy), + first, last, dest, init, HPX_FORWARD(Op, op), std::false_type(), + HPX_FORWARD(Conv, conv)); } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template > + HPX_CXX_EXPORT template > requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -272,16 +263,16 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), std::true_type{}, hpx::identity_v); } - template > + HPX_CXX_EXPORT template > requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::inclusive_scan_t, ExPolicy&& policy, FwdIter1 first, - FwdIter1 last, FwdIter2 dest, Op&& op = Op()) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::inclusive_scan_t, ExPolicy&& policy, FwdIter1 first, FwdIter1 last, + FwdIter2 dest, Op&& op = Op()) { static_assert(std::forward_iterator, "Requires at least forward iterator."); @@ -301,7 +292,8 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), is_seq(), hpx::identity_v); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -324,16 +316,16 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), std::true_type{}, hpx::identity_v); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::inclusive_scan_t, ExPolicy&& policy, FwdIter1 first, - FwdIter1 last, FwdIter2 dest, Op&& op, T&& init) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::inclusive_scan_t, ExPolicy&& policy, FwdIter1 first, FwdIter1 last, + FwdIter2 dest, Op&& op, T&& init) { static_assert(std::forward_iterator, "Requires at least forward iterator."); @@ -352,4 +344,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(T, init), HPX_FORWARD(Op, op), is_seq(), hpx::identity_v); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_partitioned.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_partitioned.hpp index 96da034b5b0b..87dc74cc4e7e 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_partitioned.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_partitioned.hpp @@ -24,21 +24,19 @@ #include #include -namespace hpx::parallel { namespace detail { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_is_partitioned - /////////////////////////////////////////////////////////////////////// /// \cond NOINTERNAL // sequential remote implementation - template - static util::detail::algorithm_result_t - segmented_is_partitioned(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, Pred&& pred, Proj&& proj, std::true_type) + util::detail::algorithm_result_t segmented_is_partitioned( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, + Pred&& pred, Proj&& proj, std::true_type) { using traits = hpx::traits::segmented_iterator_traits; using segment_iterator = typename traits::segment_iterator; @@ -140,9 +138,9 @@ namespace hpx::parallel { namespace detail { template - static util::detail::algorithm_result_t - segmented_is_partitioned(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, Pred&& pred, Proj&& proj, std::false_type) + util::detail::algorithm_result_t segmented_is_partitioned( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, + Pred&& pred, Proj&& proj, std::false_type) { using traits = hpx::traits::segmented_iterator_traits; using segment_iterator = typename traits::segment_iterator; @@ -238,15 +236,13 @@ namespace hpx::parallel { namespace detail { }, HPX_MOVE(segments))); } - /// \endcond - -}} // namespace hpx::parallel::detail +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) bool tag_invoke( @@ -267,7 +263,7 @@ namespace hpx::segmented { hpx::identity_v, std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_sorted.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_sorted.hpp index 6355e09cbb23..03d43b382b4e 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_sorted.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/is_sorted.hpp @@ -24,7 +24,7 @@ #include #include -namespace hpx::parallel { namespace detail { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_is_sorted_until @@ -35,7 +35,7 @@ namespace hpx::parallel { namespace detail { // sequential remote implementation template - static util::detail::algorithm_result_t + util::detail::algorithm_result_t segmented_is_sorted_until(Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, Pred&& pred, Proj&& proj, std::true_type) { @@ -142,7 +142,7 @@ namespace hpx::parallel { namespace detail { // parallel remote implementation template - static util::detail::algorithm_result_t + util::detail::algorithm_result_t segmented_is_sorted_until(Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, Pred&& pred, Proj&& proj, std::false_type) { @@ -275,14 +275,14 @@ namespace hpx::parallel { namespace detail { }, HPX_MOVE(segments))); } - /// \endcond -}} // namespace hpx::parallel::detail +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) InIter tag_invoke( @@ -304,7 +304,7 @@ namespace hpx::segmented { hpx::identity_v, std::true_type()); } - template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && @@ -335,7 +335,8 @@ namespace hpx::segmented { hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) bool tag_invoke( @@ -357,7 +358,7 @@ namespace hpx::segmented { hpx::identity_v, std::true_type()) == last; } - template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/minmax.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/minmax.hpp index 9e0c036ee034..0f54fd2f9348 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/minmax.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/minmax.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -9,6 +9,7 @@ #include #include #include + #include #include @@ -19,80 +20,70 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel { template using minmax_element_result = hpx::parallel::util::min_max_result; +} + +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_minmax - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static util::detail::algorithm_result_t - segmented_minormax(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, Proj&& proj, std::true_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + /// \cond NOINTERNAL - std::vector positions; - positions.reserve(std::distance(sit, send) + 1); - - if (sit == send) - { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - local_iterator_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f, proj); + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_minormax( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, + Proj&& proj, std::true_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; - positions.push_back(traits::compose(send, out)); - } - } - else - { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - if (beg != end) - { - local_iterator_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f, proj); + std::vector positions; + positions.reserve(std::distance(sit, send) + 1); - positions.push_back(traits::compose(sit, out)); - } + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) + { + local_iterator_type out = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, f, proj); - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); + positions.push_back(traits::compose(send, out)); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); - if (beg != end) - { - local_iterator_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f, proj); + if (beg != end) + { + local_iterator_type out = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, f, proj); - positions.push_back(traits::compose(sit, out)); - } - } + positions.push_back(traits::compose(sit, out)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); + if (beg != end) { local_iterator_type out = dispatch(traits::get_id(sit), @@ -102,84 +93,81 @@ namespace hpx { namespace parallel { } } - return result::get(Algo::sequential_minmax_element_ind(policy, - positions.begin(), positions.size(), HPX_FORWARD(F, f), - HPX_FORWARD(Proj, proj))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + local_iterator_type out = dispatch(traits::get_id(sit), algo, + policy, std::true_type(), beg, end, f, proj); + + positions.push_back(traits::compose(sit, out)); + } } - // parallel remote implementation - template - static util::detail::algorithm_result_t - segmented_minormax(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, Proj&& proj, std::false_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result = util::detail::algorithm_result; + return result::get( + Algo::sequential_minmax_element_ind(policy, positions.begin(), + positions.size(), HPX_FORWARD(F, f), HPX_FORWARD(Proj, proj))); + } - using forced_seq = std::integral_constant>; + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_minormax( + Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, + Proj&& proj, std::false_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; + + using forced_seq = + std::integral_constant>; - using hpx::execution::non_task; + using hpx::execution::non_task; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send) + 1); + std::vector> segments; + segments.reserve(std::distance(sit, send) + 1); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, - policy(non_task), forced_seq(), beg, end, f, proj), - [sit](local_iterator_type const& out) -> SegIter { - return traits::compose(sit, out); - })); - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy(non_task), + forced_seq(), beg, end, f, proj), + [sit](local_iterator_type const& out) -> SegIter { + return traits::compose(sit, out); + })); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, - policy(non_task), forced_seq(), beg, end, f, proj), - [sit](local_iterator_type const& out) -> SegIter { - return traits::compose(sit, out); - })); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, - policy(non_task), forced_seq(), beg, end, f, - proj), - [sit](local_iterator_type const& out) -> SegIter { - return traits::compose(sit, out); - })); - } - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy(non_task), + forced_seq(), beg, end, f, proj), + [sit](local_iterator_type const& out) -> SegIter { + return traits::compose(sit, out); + })); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(hpx::make_future( @@ -191,105 +179,97 @@ namespace hpx { namespace parallel { } } - return result::get(hpx::dataflow( - hpx::launch::sync, - [=](std::vector>&& r) -> SegIter { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - std::vector res = hpx::unwrap(HPX_MOVE(r)); - return Algo::sequential_minmax_element_ind( - policy, res.begin(), res.size(), f, proj); - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy(non_task), + forced_seq(), beg, end, f, proj), + [sit](local_iterator_type const& out) -> SegIter { + return traits::compose(sit, out); + })); + } } - /// \endcond - } // namespace detail + + return result::get(hpx::dataflow( + hpx::launch::sync, + [=](std::vector>&& r) -> SegIter { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + std::vector res = hpx::unwrap(HPX_MOVE(r)); + return Algo::sequential_minmax_element_ind( + policy, res.begin(), res.size(), f, proj); + }, + HPX_MOVE(segments))); + } /////////////////////////////////////////////////////////////////////////// // segmented_minmax - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static util::detail::algorithm_result_t> - segmented_minmax(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, Proj&& proj, std::true_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; - using result_type = minmax_element_result; - using local_iterator_pair_type = - minmax_element_result; - using result = - util::detail::algorithm_result; + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_minmax(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, F&& f, Proj&& proj, std::true_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result_type = minmax_element_result; + using local_iterator_pair_type = + minmax_element_result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + using result = util::detail::algorithm_result; - std::vector positions; - positions.reserve(std::distance(sit, send) + 1); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - if (sit == send) - { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - local_iterator_pair_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f, proj); + std::vector positions; + positions.reserve(std::distance(sit, send) + 1); - positions.emplace_back( - result_type{traits::compose(send, out.min), - traits::compose(send, out.max)}); - } - } - else + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); + local_iterator_pair_type out = dispatch(traits::get_id(sit), + algo, policy, std::true_type(), beg, end, f, proj); - if (beg != end) - { - local_iterator_pair_type out = dispatch(traits::get_id(sit), - algo, policy, std::true_type(), beg, end, f, proj); + positions.emplace_back( + result_type{traits::compose(send, out.min), + traits::compose(send, out.max)}); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); - positions.emplace_back( - result_type{traits::compose(sit, out.min), - traits::compose(sit, out.max)}); - } + if (beg != end) + { + local_iterator_pair_type out = dispatch(traits::get_id(sit), + algo, policy, std::true_type(), beg, end, f, proj); - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - - if (beg != end) - { - local_iterator_pair_type out = - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, f, proj); - - positions.emplace_back( - result_type{traits::compose(sit, out.min), - traits::compose(sit, out.max)}); - } - } + positions.emplace_back( + result_type{traits::compose(sit, out.min), + traits::compose(sit, out.max)}); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); + if (beg != end) { local_iterator_pair_type out = dispatch(traits::get_id(sit), @@ -301,96 +281,90 @@ namespace hpx { namespace parallel { } } - return result::get(Algo::sequential_minmax_element_ind(policy, - positions.begin(), positions.size(), HPX_FORWARD(F, f), - HPX_FORWARD(Proj, proj))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + local_iterator_pair_type out = dispatch(traits::get_id(sit), + algo, policy, std::true_type(), beg, end, f, proj); + + positions.emplace_back( + result_type{traits::compose(sit, out.min), + traits::compose(sit, out.max)}); + } } - // parallel remote implementation - template - static util::detail::algorithm_result_t> - segmented_minmax(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, F&& f, Proj&& proj, std::false_type) - { - using traits = hpx::traits::segmented_iterator_traits; - using segment_iterator = typename traits::segment_iterator; - using local_iterator_type = typename traits::local_iterator; + return result::get( + Algo::sequential_minmax_element_ind(policy, positions.begin(), + positions.size(), HPX_FORWARD(F, f), HPX_FORWARD(Proj, proj))); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_minmax(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, F&& f, Proj&& proj, std::false_type) + { + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; - using forced_seq = std::integral_constant>; + using forced_seq = + std::integral_constant>; - using result_type = minmax_element_result; - using local_iterator_pair_type = - minmax_element_result; + using result_type = minmax_element_result; + using local_iterator_pair_type = + minmax_element_result; - using result = - util::detail::algorithm_result; + using result = util::detail::algorithm_result; - using hpx::execution::non_task; + using hpx::execution::non_task; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send) + 1); + std::vector> segments; + segments.reserve(std::distance(sit, send) + 1); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, - policy(non_task), forced_seq(), beg, end, f, proj), - [sit](local_iterator_pair_type out) -> result_type { - return {traits::compose(sit, out.min), - traits::compose(sit, out.max)}; - })); - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy(non_task), + forced_seq(), beg, end, f, proj), + [sit](local_iterator_pair_type out) -> result_type { + return {traits::compose(sit, out.min), + traits::compose(sit, out.max)}; + })); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, - policy(non_task), forced_seq(), beg, end, f, proj), - [sit](local_iterator_pair_type const& out) - -> result_type { - return {traits::compose(sit, out.min), - traits::compose(sit, out.max)}; - })); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(hpx::make_future( - dispatch_async(traits::get_id(sit), algo, - policy(non_task), forced_seq(), beg, end, f, - proj), - [sit](local_iterator_pair_type const& out) - -> result_type { - return {traits::compose(sit, out.min), - traits::compose(sit, out.max)}; - })); - } - } + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy(non_task), + forced_seq(), beg, end, f, proj), + [sit](local_iterator_pair_type const& out) -> result_type { + return {traits::compose(sit, out.min), + traits::compose(sit, out.max)}; + })); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(hpx::make_future( @@ -404,31 +378,45 @@ namespace hpx { namespace parallel { } } - return result::get(hpx::dataflow( - hpx::launch::sync, - [=](std::vector>&& r) -> result_type { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - std::vector res = hpx::unwrap(HPX_MOVE(r)); - return Algo::sequential_minmax_element_ind( - policy, res.begin(), res.size(), f, proj); - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(hpx::make_future( + dispatch_async(traits::get_id(sit), algo, policy(non_task), + forced_seq(), beg, end, f, proj), + [sit](local_iterator_pair_type const& out) -> result_type { + return {traits::compose(sit, out.min), + traits::compose(sit, out.max)}; + })); + } } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + + return result::get(hpx::dataflow( + hpx::launch::sync, + [=](std::vector>&& r) -> result_type { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + std::vector res = hpx::unwrap(HPX_MOVE(r)); + return Algo::sequential_minmax_element_ind( + policy, res.begin(), res.size(), f, proj); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template using minmax_element_result = hpx::parallel::util::min_max_result; - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) SegIter tag_invoke(hpx::min_element_t, SegIter first, SegIter last, F&& f) @@ -450,7 +438,7 @@ namespace hpx { namespace segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) @@ -478,7 +466,7 @@ namespace hpx { namespace segmented { hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) SegIter tag_invoke(hpx::max_element_t, SegIter first, SegIter last, F&& f) @@ -500,7 +488,7 @@ namespace hpx { namespace segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) @@ -528,7 +516,7 @@ namespace hpx { namespace segmented { hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) minmax_element_result tag_invoke( @@ -551,7 +539,7 @@ namespace hpx { namespace segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) @@ -581,4 +569,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f), hpx::identity_v, is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/mismatch.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/mismatch.hpp index ad60416f1567..cb8039996df6 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/mismatch.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/mismatch.hpp @@ -9,6 +9,8 @@ #include #include #include +#include + #include #include @@ -22,134 +24,142 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { + /////////////////////////////////////////////////////////////////////////// // mismatch - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - template - struct mismatch_distance_algo - : public algorithm, - std::pair> + + /// \cond NOINTERNAL + + template + struct mismatch_distance_algo + : public algorithm, + std::pair> + { + constexpr mismatch_distance_algo() noexcept + : algorithm>("mismatch_distance_algo") { - constexpr mismatch_distance_algo() noexcept - : algorithm>( - "mismatch_distance_algo") - { - } + } - template - struct is_future : std::false_type - { - }; - template - struct is_future> : std::true_type - { - }; - template - struct is_future> : std::true_type - { - }; + template + static std::pair sequential( + ExPolicy, Iter1 first1, Sent1 last1, Iter2 first2, Pred pred) + { + auto res = + hpx::parallel::detail::mismatch>() + .sequential( + hpx::execution::seq, first1, last1, first2, pred); + return std::make_pair(std::distance(first1, res.first), + std::distance(first2, res.second)); + } + + template + static auto parallel(ExPolicy&& policy, Iter1 first1, Sent1 last1, + Iter2 first2, Pred pred) + { + auto res = + hpx::parallel::detail::mismatch>() + .parallel(HPX_FORWARD(ExPolicy, policy), first1, last1, + first2, pred); - template - static std::pair sequential( - ExPolicy, Iter1 first1, Sent1 last1, Iter2 first2, Pred pred) + using res_t = std::decay_t; + if constexpr (hpx::traits::is_future_v) + { + return hpx::dataflow( + [first1, first2]( + auto&& f) -> std::pair { + auto p = f.get(); + return std::make_pair(std::distance(first1, p.first), + std::distance(first2, p.second)); + }, + HPX_MOVE(res)); + } + else { - auto res = - hpx::parallel::detail::mismatch>() - .sequential( - hpx::execution::seq, first1, last1, first2, pred); return std::make_pair(std::distance(first1, res.first), std::distance(first2, res.second)); } + } + }; - template - static auto parallel(ExPolicy&& policy, Iter1 first1, Sent1 last1, - Iter2 first2, Pred pred) - { - auto res = - hpx::parallel::detail::mismatch>() - .parallel(HPX_FORWARD(ExPolicy, policy), first1, last1, - first2, pred); + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_mismatch(ExPolicy const& policy, SegIter1 first1, SegIter1 last1, + SegIter2 first2, Pred&& pred, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; - using res_t = std::decay_t; - if constexpr (is_future::value) - { - return hpx::dataflow( - [first1, first2]( - auto&& f) -> std::pair { - auto p = f.get(); - return std::make_pair( - std::distance(first1, p.first), - std::distance(first2, p.second)); - }, - HPX_MOVE(res)); - } - else - { - return std::make_pair(std::distance(first1, res.first), - std::distance(first2, res.second)); - } - } - }; - - // sequential remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_mismatch(ExPolicy const& policy, SegIter1 first1, - SegIter1 last1, SegIter2 first2, Pred&& pred, std::true_type) - { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); + using result = util::detail::algorithm_result>; - using result = util::detail::algorithm_result>; + mismatch_distance_algo> algo; - mismatch_distance_algo> algo; + if (sit1 == send1) + { + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); - if (sit1 == send1) + if (beg1 != end1) { - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); + std::pair local_dist = + dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, pred); - if (beg1 != end1) - { - std::pair local_dist = - dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, pred); + local_iterator_type1 res1 = beg1; + std::advance(res1, local_dist.first); + local_iterator_type2 res2 = beg2; + std::advance(res2, local_dist.second); - local_iterator_type1 res1 = beg1; - std::advance(res1, local_dist.first); - local_iterator_type2 res2 = beg2; - std::advance(res2, local_dist.second); + return result::get(std::make_pair(traits1::compose(sit1, res1), + traits2::compose(sit2, res2))); + } + } + else + { + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); + + if (beg1 != end1) + { + std::pair local_dist = + dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, pred); + local_iterator_type1 res1 = beg1; + std::advance(res1, local_dist.first); + local_iterator_type2 res2 = beg2; + std::advance(res2, local_dist.second); + + if (res1 != end1) + { return result::get( std::make_pair(traits1::compose(sit1, res1), traits2::compose(sit2, res2))); } } - else + + for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) { - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); + beg1 = traits1::begin(sit1); + end1 = traits1::end(sit1); + beg2 = traits2::begin(sit2); if (beg1 != end1) { @@ -169,145 +179,103 @@ namespace hpx { namespace parallel { traits2::compose(sit2, res2))); } } + } - for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) - { - beg1 = traits1::begin(sit1); - end1 = traits1::end(sit1); - beg2 = traits2::begin(sit2); + beg1 = traits1::begin(sit1); + end1 = traits1::local(last1); + beg2 = traits2::begin(sit2); - if (beg1 != end1) - { - std::pair local_dist = - dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, pred); - - local_iterator_type1 res1 = beg1; - std::advance(res1, local_dist.first); - local_iterator_type2 res2 = beg2; - std::advance(res2, local_dist.second); - - if (res1 != end1) - { - return result::get( - std::make_pair(traits1::compose(sit1, res1), - traits2::compose(sit2, res2))); - } - } - } + if (beg1 != end1) + { + std::pair local_dist = + dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, pred); - beg1 = traits1::begin(sit1); - end1 = traits1::local(last1); - beg2 = traits2::begin(sit2); + local_iterator_type1 res1 = beg1; + std::advance(res1, local_dist.first); + local_iterator_type2 res2 = beg2; + std::advance(res2, local_dist.second); - if (beg1 != end1) + if (res1 != end1) { - std::pair local_dist = - dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, pred); - - local_iterator_type1 res1 = beg1; - std::advance(res1, local_dist.first); - local_iterator_type2 res2 = beg2; - std::advance(res2, local_dist.second); - - if (res1 != end1) - { - return result::get( - std::make_pair(traits1::compose(sit1, res1), - traits2::compose(sit2, res2))); - } + return result::get( + std::make_pair(traits1::compose(sit1, res1), + traits2::compose(sit2, res2))); } } - - auto dist = detail::distance(first1, last1); - SegIter2 expected_last2 = first2; - detail::advance(expected_last2, dist); - return result::get(std::make_pair(last1, expected_last2)); } - // parallel remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_mismatch(ExPolicy const& policy, SegIter1 first1, - SegIter1 last1, SegIter2 first2, Pred&& pred, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; + auto dist = detail::distance(first1, last1); + SegIter2 expected_last2 = first2; + detail::advance(expected_last2, dist); + return result::get(std::make_pair(last1, expected_last2)); + } - typedef std::integral_constant> - forced_seq; + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_mismatch(ExPolicy const& policy, SegIter1 first1, SegIter1 last1, + SegIter2 first2, Pred&& pred, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; - using result = util::detail::algorithm_result>; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); + typedef std::integral_constant> + forced_seq; - std::vector>> - segments; - segments.reserve(detail::distance(sit1, send1)); + using result = util::detail::algorithm_result>; - std::vector> - seg_data; - seg_data.reserve(detail::distance(sit1, send1)); + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); - mismatch_distance_algo> algo; + std::vector>> segments; + segments.reserve(detail::distance(sit1, send1)); - if (sit1 == send1) - { - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); + std::vector> + seg_data; + seg_data.reserve(detail::distance(sit1, send1)); - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, pred)); - seg_data.emplace_back(sit1, sit2, beg1, beg2, end1); - } - } - else - { - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); + mismatch_distance_algo> algo; - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, pred)); - seg_data.emplace_back(sit1, sit2, beg1, beg2, end1); - } + if (sit1 == send1) + { + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); - for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) - { - beg1 = traits1::begin(sit1); - end1 = traits1::end(sit1); - beg2 = traits2::begin(sit2); + if (beg1 != end1) + { + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, pred)); + seg_data.emplace_back(sit1, sit2, beg1, beg2, end1); + } + } + else + { + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); - if (beg1 != end1) - { - segments.push_back( - dispatch_async(traits1::get_id(sit1), algo, policy, - forced_seq(), beg1, end1, beg2, pred)); - seg_data.emplace_back(sit1, sit2, beg1, beg2, end1); - } - } + if (beg1 != end1) + { + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, pred)); + seg_data.emplace_back(sit1, sit2, beg1, beg2, end1); + } + for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) + { beg1 = traits1::begin(sit1); - end1 = traits1::local(last1); + end1 = traits1::end(sit1); beg2 = traits2::begin(sit2); if (beg1 != end1) @@ -318,49 +286,59 @@ namespace hpx { namespace parallel { } } - auto dist = detail::distance(first1, last1); - SegIter2 expected_last2 = first2; - detail::advance(expected_last2, dist); + beg1 = traits1::begin(sit1); + end1 = traits1::local(last1); + beg2 = traits2::begin(sit2); - return result::get(dataflow( - [seg_data = HPX_MOVE(seg_data), last1, expected_last2]( - std::vector< - hpx::future>>&& - r_futures) mutable -> std::pair { - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r_futures, errors); + if (beg1 != end1) + { + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, pred)); + seg_data.emplace_back(sit1, sit2, beg1, beg2, end1); + } + } + + auto dist = detail::distance(first1, last1); + SegIter2 expected_last2 = first2; + detail::advance(expected_last2, dist); - std::vector> r = - hpx::unwrap(HPX_MOVE(r_futures)); + return result::get(dataflow( + [seg_data = HPX_MOVE(seg_data), last1, expected_last2]( + std::vector>>&& + r_futures) mutable -> std::pair { + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r_futures, errors); - for (std::size_t i = 0; i < r.size(); ++i) + std::vector> r = + hpx::unwrap(HPX_MOVE(r_futures)); + + for (std::size_t i = 0; i < r.size(); ++i) + { + auto& data = seg_data[i]; + local_iterator_type1 res1 = std::get<2>(data); + std::advance(res1, r[i].first); + local_iterator_type2 res2 = std::get<3>(data); + std::advance(res2, r[i].second); + local_iterator_type1 end1 = std::get<4>(data); + + if (res1 != end1) { - auto& data = seg_data[i]; - local_iterator_type1 res1 = std::get<2>(data); - std::advance(res1, r[i].first); - local_iterator_type2 res2 = std::get<3>(data); - std::advance(res2, r[i].second); - local_iterator_type1 end1 = std::get<4>(data); - - if (res1 != end1) - { - return std::make_pair( - traits1::compose(std::get<0>(data), res1), - traits2::compose(std::get<1>(data), res2)); - } + return std::make_pair( + traits1::compose(std::get<0>(data), res1), + traits2::compose(std::get<1>(data), res2)); } - return std::make_pair(last1, expected_last2); - }, - HPX_MOVE(segments))); - } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + } + return std::make_pair(last1, expected_last2); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail namespace hpx::segmented { - template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -382,8 +360,8 @@ namespace hpx::segmented { first1, last1, first2, HPX_FORWARD(Pred, pred), std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -415,7 +393,7 @@ namespace hpx::segmented { HPX_FORWARD(Pred, pred), is_seq()); } - template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -446,8 +424,8 @@ namespace hpx::segmented { first1, last1, first2, HPX_FORWARD(Pred, pred), std::true_type()); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/reduce.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/reduce.hpp index e0c9de2c638e..d2d816ba8014 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/reduce.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/reduce.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2017 Ajai V George -// Copyright (c) 2022-2025 Hartmut Kaiser +// Copyright (c) 2022-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -25,71 +25,59 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_reduce - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result::type - segmented_reduce(Algo&& algo, ExPolicy const& policy, SegIterB first, - SegIterE last, T&& init, Reduce&& red_op, std::true_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + /// \cond NOINTERNAL + + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_reduce(Algo&& algo, + ExPolicy const& policy, SegIterB first, SegIterE last, T&& init, + Reduce&& red_op, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef util::detail::algorithm_result result; + + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - T overall_result = init; + T overall_result = init; - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, red_op)); - } + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, red_op)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, red_op)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, red_op)); - } - } + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, red_op)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { overall_result = HPX_INVOKE(red_op, overall_result, @@ -98,68 +86,68 @@ namespace hpx { namespace parallel { } } - return result::get(HPX_MOVE(overall_result)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, red_op)); + } } - // parallel remote implementation - template - static typename util::detail::algorithm_result::type - segmented_reduce(Algo&& algo, ExPolicy const& policy, SegIterB first, - SegIterE last, T&& init, Reduce&& red_op, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; + return result::get(HPX_MOVE(overall_result)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_reduce(Algo&& algo, + ExPolicy const& policy, SegIterB first, SegIterE last, T&& init, + Reduce&& red_op, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef util::detail::algorithm_result result; - typedef std::integral_constant> - forced_seq; + typedef std::integral_constant> + forced_seq; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(detail::distance(sit, send)); + std::vector> segments; + segments.reserve(detail::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, red_op)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, red_op)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, red_op)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), - algo, policy, forced_seq(), beg, end, red_op)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, red_op)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -167,30 +155,39 @@ namespace hpx { namespace parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) mutable -> T { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - // VS2015RC bails out if red_op is capture by ref - return detail::accumulate(r.begin(), r.end(), init, - [=](T val, shared_future& curr) mutable { - return HPX_INVOKE( - red_op, HPX_MOVE(val), curr.get()); - }); - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, red_op)); + } } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + + return result::get(dataflow( + [=](std::vector>&& r) mutable -> T { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + // VS2015RC bails out if red_op is capture by ref + return detail::accumulate(r.begin(), r.end(), init, + [=](T val, shared_future& curr) mutable { + return HPX_INVOKE(red_op, HPX_MOVE(val), curr.get()); + }); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx ::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -213,16 +210,16 @@ namespace hpx { namespace segmented { last, HPX_FORWARD(T, init), HPX_FORWARD(F, f), std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::reduce_t, ExPolicy&& policy, InIterB first, InIterE last, - T init, F&& f) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::reduce_t, ExPolicy&& policy, InIterB first, InIterE last, T init, + F&& f) { static_assert( std::input_iterator, "Requires at least input iterator."); @@ -243,4 +240,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(T, init), HPX_FORWARD(F, f), is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace.hpp index ca3e6ebc5f4c..0a372220488f 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace.hpp @@ -22,76 +22,74 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_replace - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - template - struct replace_function - { - replace_function() = default; + /// \cond NOINTERNAL - template - explicit replace_function(T1&& old_val, T2&& new_val) - : old_value_(HPX_FORWARD(T1, old_val)) - , new_value_(HPX_FORWARD(T2, new_val)) - { - } + template + struct replace_function + { + replace_function() = default; - T old_value_ = T(); - T new_value_ = T(); + template + explicit replace_function(T1&& old_val, T2&& new_val) + : old_value_(HPX_FORWARD(T1, old_val)) + , new_value_(HPX_FORWARD(T2, new_val)) + { + } + + T old_value_ = T(); + T new_value_ = T(); - void operator()(T& val) const + void operator()(T& val) const + { + if (val == old_value_) { - if (val == old_value_) - { - val = new_value_; - } + val = new_value_; } - }; + } + }; - template - replace_function(T, T) -> replace_function>; + template + replace_function(T, T) -> replace_function>; - template - struct replace_if_function - { - replace_if_function() = default; + template + struct replace_if_function + { + replace_if_function() = default; - template - explicit replace_if_function(T_&& new_val, F_&& pred) - : pred_(HPX_FORWARD(F_, pred)) - , new_value_(HPX_FORWARD(T_, new_val)) - { - } + template + explicit replace_if_function(T_&& new_val, F_&& pred) + : pred_(HPX_FORWARD(F_, pred)) + , new_value_(HPX_FORWARD(T_, new_val)) + { + } - F pred_ = F(); - T new_value_ = T(); + F pred_ = F(); + T new_value_ = T(); - void operator()(T& val) const + void operator()(T& val) const + { + if (HPX_INVOKE(pred_, val)) { - if (HPX_INVOKE(pred_, val)) - { - val = new_value_; - } + val = new_value_; } - }; + } + }; - template - replace_if_function(T&&, F&&) - -> replace_if_function, std::decay_t>; - } // namespace detail + template + replace_if_function(T&&, F&&) + -> replace_if_function, std::decay_t>; /// \endcond -} // namespace hpx::parallel +} // namespace hpx::parallel::detail namespace hpx::segmented { // segmented replace - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) SegIter tag_invoke(hpx::replace_t, SegIter first, SegIter last, @@ -115,11 +113,11 @@ namespace hpx::segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - static hpx::parallel::util::detail::algorithm_result_t + hpx::parallel::util::detail::algorithm_result_t tag_invoke(hpx::replace_t, ExPolicy&& policy, SegIter first, SegIter last, T const& old_value, T const& new_value) { @@ -147,7 +145,7 @@ namespace hpx::segmented { } // segmented replace_if - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) SegIter tag_invoke(hpx::replace_if_t, SegIter first, SegIter last, @@ -172,11 +170,12 @@ namespace hpx::segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - static hpx::parallel::util::detail::algorithm_result_t + hpx::parallel::util::detail::algorithm_result_t tag_invoke(hpx::replace_if_t, ExPolicy&& policy, SegIter first, SegIter last, Pred&& pred, T const& new_value) { diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace_copy.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace_copy.hpp index a18d8d30310f..1645220c5bf9 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace_copy.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/replace_copy.hpp @@ -10,6 +10,7 @@ #include #include #include + #include #include @@ -22,392 +23,382 @@ #include #include -namespace hpx::parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_replace_copy - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static util::detail::algorithm_result_t> - segmented_replace_copy(Algo&& algo, ExPolicy const& policy, - SegIter first, SegIter last, OutIter dest, T const& old_value, - T const& new_value, Proj&& proj, std::true_type) - { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; - using result = util::detail::algorithm_result>; + /// \cond NOINTERNAL - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_replace_copy(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, OutIter dest, T const& old_value, T const& new_value, + Proj&& proj, std::true_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; - if (sit == send) - { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - util::in_out_result - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, old_value, - new_value, HPX_FORWARD(Proj, proj)); - last = traits1::compose(send, out.in); - dest = traits2::compose(sdest, out.out); - } - } - else + using result = util::detail::algorithm_result>; + + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + if (sit == send) + { + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); util::in_out_result - out; - if (beg != end) - { out = dispatch(traits2::get_id(sdest), algo, policy, std::true_type(), beg, end, ldest, old_value, new_value, - proj); - } - - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, old_value, - new_value, proj); - } - } + HPX_FORWARD(Proj, proj)); + last = traits1::compose(send, out.in); + dest = traits2::compose(sdest, out.out); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + util::in_out_result out; + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, old_value, new_value, + proj); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); if (beg != end) { out = dispatch(traits2::get_id(sdest), algo, policy, std::true_type(), beg, end, ldest, old_value, new_value, - HPX_FORWARD(Proj, proj)); + proj); } - last = traits1::compose(send, out.in); - dest = traits2::compose(sdest, out.out); } - return result::get(util::in_out_result{ - HPX_MOVE(last), HPX_MOVE(dest)}); + + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, old_value, new_value, + HPX_FORWARD(Proj, proj)); + } + last = traits1::compose(send, out.in); + dest = traits2::compose(sdest, out.out); } + return result::get(util::in_out_result{ + HPX_MOVE(last), HPX_MOVE(dest)}); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_replace_copy(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, OutIter dest, T const& old_value, T const& new_value, + Proj&& proj, std::false_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; + + using result = util::detail::algorithm_result>; + + using forced_seq = std::integral_constant>; + + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + using segment_type = std::vector>>; + segment_type segments; + segments.reserve(std::distance(sit, send)); - // parallel remote implementation - template - static util::detail::algorithm_result_t> - segmented_replace_copy(Algo&& algo, ExPolicy const& policy, - SegIter first, SegIter last, OutIter dest, T const& old_value, - T const& new_value, Proj&& proj, std::false_type) + if (sit == send) { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; - - using result = util::detail::algorithm_result>; - - using forced_seq = std::integral_constant>; - - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); - - using segment_type = - std::vector>>; - segment_type segments; - segments.reserve(std::distance(sit, send)); - - if (sit == send) + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, old_value, - new_value, HPX_FORWARD(Proj, proj))); - } + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, old_value, new_value, + HPX_FORWARD(Proj, proj))); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, old_value, - new_value, proj)); - } - - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - segments.push_back(dispatch_async( - traits2::get_id(sdest), algo, policy, forced_seq(), - beg, end, ldest, old_value, new_value, proj)); - } - } + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, old_value, new_value, + proj)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); if (beg != end) { segments.push_back(dispatch_async(traits2::get_id(sdest), algo, policy, forced_seq(), beg, end, ldest, old_value, - new_value, HPX_FORWARD(Proj, proj))); + new_value, proj)); } } - return result::get(dataflow( - [=](segment_type&& r) -> util::in_out_result { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - auto ft = r.back().get(); - auto olast = traits1::compose(send, ft.in); - auto odest = traits2::compose(sdest, ft.out); - return util::in_out_result{olast, odest}; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, old_value, new_value, + HPX_FORWARD(Proj, proj))); + } } - /////////////////////////////////////////////////////////////////////// - // segmented_replace_copy_if - - // sequential remote implementation - template - static util::detail::algorithm_result_t> - segmented_replace_copy_if(Algo&& algo, ExPolicy const& policy, - SegIter first, SegIter last, OutIter dest, F&& f, - T const& new_value, Proj&& proj, std::true_type) - { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; + return result::get(dataflow( + [=](segment_type&& r) -> util::in_out_result { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + auto ft = r.back().get(); + auto olast = traits1::compose(send, ft.in); + auto odest = traits2::compose(sdest, ft.out); + return util::in_out_result{olast, odest}; + }, + HPX_MOVE(segments))); + } - using result = util::detail::algorithm_result>; + /////////////////////////////////////////////////////////////////////// + // segmented_replace_copy_if + + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_replace_copy_if(Algo&& algo, ExPolicy const& policy, + SegIter first, SegIter last, OutIter dest, F&& f, T const& new_value, + Proj&& proj, std::true_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); + using result = util::detail::algorithm_result>; - if (sit == send) - { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - util::in_out_result - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, f, new_value, - HPX_FORWARD(Proj, proj)); - last = traits1::compose(send, out.in); - dest = traits2::compose(sdest, out.out); - } - } - else + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + if (sit == send) + { + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); util::in_out_result - out; - if (beg != end) - { - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, f, new_value, proj); - } - - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, f, new_value, - proj); - } - } - - // handle the beginning of the last partition - beg = traits1::begin(sit); - end = traits1::local(last); - ldest = traits2::begin(sdest); - if (beg != end) - { out = dispatch(traits2::get_id(sdest), algo, policy, std::true_type(), beg, end, ldest, f, new_value, HPX_FORWARD(Proj, proj)); - } last = traits1::compose(send, out.in); dest = traits2::compose(sdest, out.out); } - return result::get(util::in_out_result{ - HPX_MOVE(last), HPX_MOVE(dest)}); } - - // parallel remote implementation - template - static util::detail::algorithm_result_t> - segmented_replace_copy_if(Algo&& algo, ExPolicy const& policy, - SegIter first, SegIter last, OutIter dest, F&& f, - T const& new_value, Proj&& proj, std::false_type) + else { - using traits1 = hpx::traits::segmented_iterator_traits; - using traits2 = hpx::traits::segmented_iterator_traits; - using segment_iterator1 = typename traits1::segment_iterator; - using local_iterator_type1 = typename traits1::local_iterator; - using segment_iterator2 = typename traits2::segment_iterator; - using local_iterator_type2 = typename traits2::local_iterator; - - using result = util::detail::algorithm_result>; - - using forced_seq = std::integral_constant>; - - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); - - using segment_type = - std::vector>>; - segment_type segments; - segments.reserve(std::distance(sit, send)); - - if (sit == send) + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + util::in_out_result out; + if (beg != end) { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, f, - new_value, HPX_FORWARD(Proj, proj))); - } + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, f, new_value, proj); } - else + + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); + beg = traits1::begin(sit); + end = traits1::end(sit); + ldest = traits2::begin(sdest); if (beg != end) { - segments.push_back( - dispatch_async(traits2::get_id(sdest), algo, policy, - forced_seq(), beg, end, ldest, f, new_value, proj)); + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, f, new_value, proj); } + } - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - segments.push_back(dispatch_async( - traits2::get_id(sdest), algo, policy, forced_seq(), - beg, end, ldest, f, new_value, proj)); - } - } + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, f, new_value, + HPX_FORWARD(Proj, proj)); + } + last = traits1::compose(send, out.in); + dest = traits2::compose(sdest, out.out); + } + return result::get(util::in_out_result{ + HPX_MOVE(last), HPX_MOVE(dest)}); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_replace_copy_if(Algo&& algo, ExPolicy const& policy, + SegIter first, SegIter last, OutIter dest, F&& f, T const& new_value, + Proj&& proj, std::false_type) + { + using traits1 = hpx::traits::segmented_iterator_traits; + using traits2 = hpx::traits::segmented_iterator_traits; + using segment_iterator1 = typename traits1::segment_iterator; + using local_iterator_type1 = typename traits1::local_iterator; + using segment_iterator2 = typename traits2::segment_iterator; + using local_iterator_type2 = typename traits2::local_iterator; + + using result = util::detail::algorithm_result>; + + using forced_seq = std::integral_constant>; + + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + using segment_type = std::vector>>; + segment_type segments; + segments.reserve(std::distance(sit, send)); + + if (sit == send) + { + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) + { + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, f, new_value, + HPX_FORWARD(Proj, proj))); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) + { + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, f, new_value, proj)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); if (beg != end) { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, f, - new_value, HPX_FORWARD(Proj, proj))); + segments.push_back( + dispatch_async(traits2::get_id(sdest), algo, policy, + forced_seq(), beg, end, ldest, f, new_value, proj)); } } - return result::get(dataflow( - [=](segment_type&& r) -> util::in_out_result { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - auto ft = r.back().get(); - auto olast = traits1::compose(send, ft.in); - auto odest = traits2::compose(sdest, ft.out); - return util::in_out_result{olast, odest}; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, f, new_value, + HPX_FORWARD(Proj, proj))); + } } - } // namespace detail + + return result::get(dataflow( + [=](segment_type&& r) -> util::in_out_result { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + auto ft = r.back().get(); + auto olast = traits1::compose(send, ft.in); + auto odest = traits2::compose(sdest, ft.out); + return util::in_out_result{olast, odest}; + }, + HPX_MOVE(segments))); + } /// \endcond -} // namespace hpx::parallel +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented namespace hpx::segmented { // segmented replace_copy - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -438,13 +429,14 @@ namespace hpx::segmented { return HPX_MOVE(result.out); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - static hpx::parallel::util::detail::algorithm_result_t + hpx::parallel::util::detail::algorithm_result_t tag_invoke(hpx::replace_copy_t, ExPolicy&& policy, SegIter first, SegIter last, OutIter dest, T const& old_value, T const& new_value) { @@ -477,7 +469,8 @@ namespace hpx::segmented { } // segmented replace_copy_if - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -508,14 +501,14 @@ namespace hpx::segmented { return HPX_MOVE(result.out); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - static hpx::parallel::util::detail::algorithm_result_t + hpx::parallel::util::detail::algorithm_result_t tag_invoke(hpx::replace_copy_if_t, ExPolicy&& policy, SegIter first, SegIter last, OutIter dest, Pred&& pred, T const& new_value) { diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/traits/zip_iterator.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/traits/zip_iterator.hpp index 48fd32df3efe..46865b4053c1 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/traits/zip_iterator.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/traits/zip_iterator.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2024 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // Copyright (c) 2014 Agustin Berge // // SPDX-License-Identifier: BSL-1.0 @@ -12,6 +12,7 @@ #include #include #include + #include #include @@ -24,7 +25,7 @@ namespace hpx::traits { /////////////////////////////////////////////////////////////////////////// namespace functional { - struct get_raw_iterator + HPX_CXX_EXPORT struct get_raw_iterator { template struct apply @@ -38,7 +39,7 @@ namespace hpx::traits { }; }; - struct get_remote_iterator + HPX_CXX_EXPORT struct get_remote_iterator { template struct apply diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform.hpp index 24a28415cba0..6fcc9765a002 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2017 Ajai V George -// Copyright (c) 2024-2025 Hartmut Kaiser +// Copyright (c) 2024-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -11,6 +11,7 @@ #include #include #include + #include #include @@ -23,170 +24,154 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_transform - namespace detail { - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transform(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, OutIter dest, F&& f, Proj&& proj, std::true_type) + + /// \cond NOINTERNAL + + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_transform(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, OutIter dest, F&& f, Proj&& proj, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + + typedef util::detail::algorithm_result> + result; + + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + if (sit == send) { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - - typedef util::detail::algorithm_result> - result; - - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); - - if (sit == send) + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - util::in_out_result - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, f, proj); - last = traits1::compose(send, out.in); - dest = traits2::compose(sdest, out.out); - } - } - else - { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); util::in_out_result - out; - if (beg != end) - { out = dispatch(traits2::get_id(sdest), algo, policy, std::true_type(), beg, end, ldest, f, proj); - } - - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - out = dispatch(traits2::get_id(sdest), algo, policy, - std::true_type(), beg, end, ldest, f, proj); - } - } + last = traits1::compose(send, out.in); + dest = traits2::compose(sdest, out.out); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + util::in_out_result out; + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, f, proj); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); if (beg != end) { out = dispatch(traits2::get_id(sdest), algo, policy, std::true_type(), beg, end, ldest, f, proj); } - last = traits1::compose(send, out.in); - dest = traits2::compose(sdest, out.out); } - return result::get(util::in_out_result{ - HPX_MOVE(last), HPX_MOVE(dest)}); + + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + out = dispatch(traits2::get_id(sdest), algo, policy, + std::true_type(), beg, end, ldest, f, proj); + } + last = traits1::compose(send, out.in); + dest = traits2::compose(sdest, out.out); } + return result::get(util::in_out_result{ + HPX_MOVE(last), HPX_MOVE(dest)}); + } - // parallel remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transform(Algo&& algo, ExPolicy const& policy, SegIter first, - SegIter last, OutIter dest, F&& f, Proj&& proj, std::false_type) + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_transform(Algo&& algo, ExPolicy const& policy, SegIter first, + SegIter last, OutIter dest, F&& f, Proj&& proj, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + + typedef util::detail::algorithm_result> + result; + + typedef std::integral_constant> + forced_seq; + + segment_iterator1 sit = traits1::segment(first); + segment_iterator1 send = traits1::segment(last); + segment_iterator2 sdest = traits2::segment(dest); + + typedef std::vector>> + segment_type; + segment_type segments; + segments.reserve(std::distance(sit, send)); + + if (sit == send) { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - - typedef util::detail::algorithm_result> - result; - - typedef std::integral_constant> - forced_seq; - - segment_iterator1 sit = traits1::segment(first); - segment_iterator1 send = traits1::segment(last); - segment_iterator2 sdest = traits2::segment(dest); - - typedef std::vector>> - segment_type; - segment_type segments; - segments.reserve(std::distance(sit, send)); - - if (sit == send) + // all elements are on the same partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::local(last); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // all elements are on the same partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::local(last); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, f, proj)); - } + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, f, proj)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg = traits1::local(first); + local_iterator_type1 end = traits1::end(sit); + local_iterator_type2 ldest = traits2::local(dest); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type1 beg = traits1::local(first); - local_iterator_type1 end = traits1::end(sit); - local_iterator_type2 ldest = traits2::local(dest); - if (beg != end) - { - segments.push_back(dispatch_async(traits2::get_id(sdest), - algo, policy, forced_seq(), beg, end, ldest, f, proj)); - } - - // handle all of the full partitions - for (++sit, ++sdest; sit != send; ++sit, ++sdest) - { - beg = traits1::begin(sit); - end = traits1::end(sit); - ldest = traits2::begin(sdest); - if (beg != end) - { - segments.push_back( - dispatch_async(traits2::get_id(sdest), algo, policy, - forced_seq(), beg, end, ldest, f, proj)); - } - } + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, f, proj)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit, ++sdest; sit != send; ++sit, ++sdest) + { beg = traits1::begin(sit); - end = traits1::local(last); + end = traits1::end(sit); ldest = traits2::begin(sdest); if (beg != end) { @@ -195,109 +180,106 @@ namespace hpx { namespace parallel { } } - return result::get(dataflow( - [=](segment_type&& r) -> util::in_out_result { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - auto ft = r.back().get(); - auto olast = traits1::compose(send, ft.in); - auto odest = traits2::compose(sdest, ft.out); - return util::in_out_result{olast, odest}; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits1::begin(sit); + end = traits1::local(last); + ldest = traits2::begin(sdest); + if (beg != end) + { + segments.push_back(dispatch_async(traits2::get_id(sdest), algo, + policy, forced_seq(), beg, end, ldest, f, proj)); + } } - // Binary transform - - // sequential remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, - InIter1 last1, InIter2 first2, OutIter dest, F&& f, Proj1&& proj1, - Proj2&& proj2, std::true_type) + return result::get(dataflow( + [=](segment_type&& r) -> util::in_out_result { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + auto ft = r.back().get(); + auto olast = traits1::compose(send, ft.in); + auto odest = traits2::compose(sdest, ft.out); + return util::in_out_result{olast, odest}; + }, + HPX_MOVE(segments))); + } + + // Binary transform + + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, + InIter1 last1, InIter2 first2, OutIter dest, F&& f, Proj1&& proj1, + Proj2&& proj2, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef hpx::traits::segmented_iterator_traits traits3; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + typedef typename traits3::segment_iterator segment_iterator3; + typedef typename traits3::local_iterator local_iterator_type3; + + typedef util::detail::algorithm_result> + result; + + auto last2 = first2; + detail::advance(last2, std::distance(first1, last1)); + + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); + segment_iterator2 send2 = traits2::segment(last2); + segment_iterator3 sdest = traits3::segment(dest); + if (sit1 == send1) { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef hpx::traits::segmented_iterator_traits traits3; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - typedef typename traits3::segment_iterator segment_iterator3; - typedef typename traits3::local_iterator local_iterator_type3; - - typedef util::detail::algorithm_result> - result; - - auto last2 = first2; - detail::advance(last2, std::distance(first1, last1)); - - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); - segment_iterator2 send2 = traits2::segment(last2); - segment_iterator3 sdest = traits3::segment(dest); - if (sit1 == send1) + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type3 ldest = traits3::local(dest); + if (beg1 != end1) { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type3 ldest = traits3::local(dest); - if (beg1 != end1) - { - util::in_in_out_result - out = dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, ldest, f, proj1, - proj2); - last1 = traits1::compose(send1, out.in1); - last2 = traits2::compose(send2, out.in2); - dest = traits3::compose(sdest, out.out); - } - } - else - { - // handle the remaining part of the first partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type3 ldest = traits3::local(dest); util::in_in_out_result - out; - if (beg1 != end1) - { out = dispatch(traits1::get_id(sit1), algo, policy, std::true_type(), beg1, end1, beg2, ldest, f, proj1, proj2); - } - - // handle all of the full partitions - for (++sit1, ++sit2, ++sdest; sit1 != send1; - ++sit1, ++sit2, ++sdest) - { - beg1 = traits1::begin(sit1); - end1 = traits1::end(sit1); - beg2 = traits2::begin(sit2); - ldest = traits3::begin(sdest); - if (beg1 != end1) - { - out = dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, ldest, f, proj1, - proj2); - } - } + last1 = traits1::compose(send1, out.in1); + last2 = traits2::compose(send2, out.in2); + dest = traits3::compose(sdest, out.out); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type3 ldest = traits3::local(dest); + util::in_in_out_result + out; + if (beg1 != end1) + { + out = dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, ldest, f, proj1, proj2); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit1, ++sit2, ++sdest; sit1 != send1; + ++sit1, ++sit2, ++sdest) + { beg1 = traits1::begin(sit1); - end1 = traits1::local(last1); + end1 = traits1::end(sit1); beg2 = traits2::begin(sit2); ldest = traits3::begin(sdest); if (beg1 != end1) @@ -306,107 +288,103 @@ namespace hpx { namespace parallel { std::true_type(), beg1, end1, beg2, ldest, f, proj1, proj2); } - last1 = traits1::compose(send1, out.in1); - last2 = traits2::compose(send2, out.in2); - dest = traits3::compose(sdest, out.out); } - return result::get( - util::in_in_out_result{ - HPX_MOVE(last1), HPX_MOVE(last2), HPX_MOVE(dest)}); + + // handle the beginning of the last partition + beg1 = traits1::begin(sit1); + end1 = traits1::local(last1); + beg2 = traits2::begin(sit2); + ldest = traits3::begin(sdest); + if (beg1 != end1) + { + out = dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, ldest, f, proj1, proj2); + } + last1 = traits1::compose(send1, out.in1); + last2 = traits2::compose(send2, out.in2); + dest = traits3::compose(sdest, out.out); } + return result::get(util::in_in_out_result{ + HPX_MOVE(last1), HPX_MOVE(last2), HPX_MOVE(dest)}); + } - // parallel remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, - InIter1 last1, InIter2 first2, OutIter dest, F&& f, Proj1&& proj1, - Proj2&& proj2, std::false_type) + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, + InIter1 last1, InIter2 first2, OutIter dest, F&& f, Proj1&& proj1, + Proj2&& proj2, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef hpx::traits::segmented_iterator_traits traits3; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + typedef typename traits3::segment_iterator segment_iterator3; + typedef typename traits3::local_iterator local_iterator_type3; + + typedef util::detail::algorithm_result> + result; + + typedef std::integral_constant || !std::forward_iterator> + forced_seq; + + auto last2 = first2; + detail::advance(last2, std::distance(first1, last1)); + + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); + segment_iterator2 send2 = traits2::segment(last2); + segment_iterator3 sdest = traits3::segment(dest); + + typedef std::vector>> + segment_type; + segment_type segments; + segments.reserve(std::distance(sit1, send1)); + + if (sit1 == send1) { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef hpx::traits::segmented_iterator_traits traits3; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - typedef typename traits3::segment_iterator segment_iterator3; - typedef typename traits3::local_iterator local_iterator_type3; - - typedef util::detail::algorithm_result> - result; - - typedef std::integral_constant || - !std::forward_iterator> - forced_seq; - - auto last2 = first2; - detail::advance(last2, std::distance(first1, last1)); - - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); - segment_iterator2 send2 = traits2::segment(last2); - segment_iterator3 sdest = traits3::segment(dest); - - typedef std::vector< - future>> - segment_type; - segment_type segments; - segments.reserve(std::distance(sit1, send1)); - - if (sit1 == send1) + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type3 ldest = traits3::local(dest); + if (beg1 != end1) { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type3 ldest = traits3::local(dest); - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, ldest, f, - proj1, proj2)); - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, ldest, f, proj1, + proj2)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type3 ldest = traits3::local(dest); + if (beg1 != end1) { - // handle the remaining part of the first partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type3 ldest = traits3::local(dest); - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, ldest, f, - proj1, proj2)); - } - - // handle all of the full partitions - for (++sit1, ++sit2, ++sdest; sit1 != send1; - ++sit1, ++sit2, ++sdest) - { - beg1 = traits1::begin(sit1); - end1 = traits1::end(sit1); - beg2 = traits2::begin(sit2); - ldest = traits3::begin(sdest); - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, ldest, - f, proj1, proj2)); - } - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, ldest, f, proj1, + proj2)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit1, ++sit2, ++sdest; sit1 != send1; + ++sit1, ++sit2, ++sdest) + { beg1 = traits1::begin(sit1); - end1 = traits1::local(last1); + end1 = traits1::end(sit1); beg2 = traits2::begin(sit2); ldest = traits3::begin(sdest); if (beg1 != end1) @@ -417,111 +395,110 @@ namespace hpx { namespace parallel { } } - return result::get(dataflow( - [=](segment_type&& r) - -> util::in_in_out_result { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - auto rl = r.back().get(); - auto olast1 = traits1::compose(send1, rl.in1); - auto olast2 = traits2::compose(send2, rl.in2); - auto odest = traits3::compose(sdest, rl.out); - return util::in_in_out_result{ - olast1, olast2, odest}; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg1 = traits1::begin(sit1); + end1 = traits1::local(last1); + beg2 = traits2::begin(sit2); + ldest = traits3::begin(sdest); + if (beg1 != end1) + { + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, ldest, f, proj1, + proj2)); + } } - // Binary transform1 - - // sequential remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, - InIter1 last1, InIter2 first2, InIter2 last2, OutIter dest, F&& f, - Proj1&& proj1, Proj2&& proj2, std::true_type) + return result::get(dataflow( + [=](segment_type&& r) + -> util::in_in_out_result { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + auto rl = r.back().get(); + auto olast1 = traits1::compose(send1, rl.in1); + auto olast2 = traits2::compose(send2, rl.in2); + auto odest = traits3::compose(sdest, rl.out); + return util::in_in_out_result{ + olast1, olast2, odest}; + }, + HPX_MOVE(segments))); + } + + // Binary transform1 + + // sequential remote implementation + template + util::detail::algorithm_result_t> + segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, + InIter1 last1, InIter2 first2, InIter2 last2, OutIter dest, F&& f, + Proj1&& proj1, Proj2&& proj2, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef hpx::traits::segmented_iterator_traits traits3; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + typedef typename traits3::segment_iterator segment_iterator3; + typedef typename traits3::local_iterator local_iterator_type3; + + typedef util::detail::algorithm_result> + result; + + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); + segment_iterator2 send2 = traits2::segment(last2); + segment_iterator3 sdest = traits3::segment(dest); + + if (sit1 == send1 && sit2 == send2) { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef hpx::traits::segmented_iterator_traits traits3; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - typedef typename traits3::segment_iterator segment_iterator3; - typedef typename traits3::local_iterator local_iterator_type3; - - typedef util::detail::algorithm_result> - result; - - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); - segment_iterator2 send2 = traits2::segment(last2); - segment_iterator3 sdest = traits3::segment(dest); - - if (sit1 == send1 && sit2 == send2) - { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type2 end2 = traits2::local(last2); - local_iterator_type3 ldest = traits3::local(dest); - if (beg1 != end1 && beg2 != end2) - { - util::in_in_out_result - out = dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, end2, ldest, f, - proj1, proj2); - last1 = traits1::compose(send1, out.in1); - last2 = traits2::compose(send2, out.in2); - dest = traits3::compose(sdest, out.out); - } - } - else + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type2 end2 = traits2::local(last2); + local_iterator_type3 ldest = traits3::local(dest); + if (beg1 != end1 && beg2 != end2) { - // handle the remaining part of the first partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type2 end2 = traits2::end(sit2); - local_iterator_type3 ldest = traits3::local(dest); util::in_in_out_result - out; - if (beg1 != end1 && beg2 != end2) - { out = dispatch(traits1::get_id(sit1), algo, policy, std::true_type(), beg1, end1, beg2, end2, ldest, f, proj1, proj2); - } - - // handle all of the full partitions - for (++sit1, ++sit2, ++sdest; sit1 != send1 && sit2 != send2; - ++sit1, ++sit2, ++sdest) - { - beg1 = traits1::begin(sit1); - end1 = traits1::end(sit1); - beg2 = traits2::begin(sit2); - end2 = traits2::end(sit2); - ldest = traits3::begin(sdest); - if (beg1 != end1 && beg2 != end2) - { - out = dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, end2, ldest, f, - proj1, proj2); - } - } + last1 = traits1::compose(send1, out.in1); + last2 = traits2::compose(send2, out.in2); + dest = traits3::compose(sdest, out.out); + } + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type2 end2 = traits2::end(sit2); + local_iterator_type3 ldest = traits3::local(dest); + util::in_in_out_result + out; + if (beg1 != end1 && beg2 != end2) + { + out = dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, end2, ldest, f, proj1, + proj2); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit1, ++sit2, ++sdest; sit1 != send1 && sit2 != send2; + ++sit1, ++sit2, ++sdest) + { beg1 = traits1::begin(sit1); end1 = traits1::end(sit1); beg2 = traits2::begin(sit2); @@ -533,105 +510,102 @@ namespace hpx { namespace parallel { std::true_type(), beg1, end1, beg2, end2, ldest, f, proj1, proj2); } - last1 = traits1::compose(send1, out.in1); - last2 = traits2::compose(send2, out.in2); - dest = traits3::compose(sdest, out.out); } - return result::get( - util::in_in_out_result{ - HPX_MOVE(last1), HPX_MOVE(last2), HPX_MOVE(dest)}); + + // handle the beginning of the last partition + beg1 = traits1::begin(sit1); + end1 = traits1::end(sit1); + beg2 = traits2::begin(sit2); + end2 = traits2::end(sit2); + ldest = traits3::begin(sdest); + if (beg1 != end1 && beg2 != end2) + { + out = dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, end2, ldest, f, proj1, + proj2); + } + last1 = traits1::compose(send1, out.in1); + last2 = traits2::compose(send2, out.in2); + dest = traits3::compose(sdest, out.out); } + return result::get(util::in_in_out_result{ + HPX_MOVE(last1), HPX_MOVE(last2), HPX_MOVE(dest)}); + } - // parallel remote implementation - template - static typename util::detail::algorithm_result>::type - segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, - InIter1 last1, InIter2 first2, InIter2 last2, OutIter dest, F&& f, - Proj1&& proj1, Proj2&& proj2, std::false_type) + // parallel remote implementation + template + util::detail::algorithm_result_t> + segmented_transform(Algo&& algo, ExPolicy&& policy, InIter1 first1, + InIter1 last1, InIter2 first2, InIter2 last2, OutIter dest, F&& f, + Proj1&& proj1, Proj2&& proj2, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef hpx::traits::segmented_iterator_traits traits3; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + typedef typename traits3::segment_iterator segment_iterator3; + typedef typename traits3::local_iterator local_iterator_type3; + + typedef util::detail::algorithm_result> + result; + + typedef std::integral_constant || !std::forward_iterator> + forced_seq; + + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits2::segment(first2); + segment_iterator2 send2 = traits2::segment(last2); + segment_iterator3 sdest = traits3::segment(dest); + + typedef std::vector>> + segment_type; + segment_type segments; + segments.reserve(std::distance(sit1, send1)); + + if (sit1 == send1 && sit2 == send2) { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef hpx::traits::segmented_iterator_traits traits3; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - typedef typename traits3::segment_iterator segment_iterator3; - typedef typename traits3::local_iterator local_iterator_type3; - - typedef util::detail::algorithm_result> - result; - - typedef std::integral_constant || - !std::forward_iterator> - forced_seq; - - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits2::segment(first2); - segment_iterator2 send2 = traits2::segment(last2); - segment_iterator3 sdest = traits3::segment(dest); - - typedef std::vector< - future>> - segment_type; - segment_type segments; - segments.reserve(std::distance(sit1, send1)); - - if (sit1 == send1 && sit2 == send2) + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::local(last1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type2 end2 = traits2::local(last2); + local_iterator_type3 ldest = traits3::local(dest); + if (beg1 != end1 && beg2 != end2) { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::local(last1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type2 end2 = traits2::local(last2); - local_iterator_type3 ldest = traits3::local(dest); - if (beg1 != end1 && beg2 != end2) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, end2, - ldest, f, proj1, proj2)); - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, end2, ldest, f, + proj1, proj2)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type2 end2 = traits2::end(sit2); + local_iterator_type3 ldest = traits3::local(dest); + if (beg1 != end1 && beg2 != end2) { - // handle the remaining part of the first partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type2 end2 = traits2::end(sit2); - local_iterator_type3 ldest = traits3::local(dest); - if (beg1 != end1 && beg2 != end2) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, end2, - ldest, f, proj1, proj2)); - } - - // handle all of the full partitions - for (++sit1, ++sit2, ++sdest; sit1 != send1 && sit2 != send2; - ++sit1, ++sit2, ++sdest) - { - beg1 = traits1::begin(sit1); - beg2 = traits2::begin(sit2); - end1 = traits1::end(sit1); - end2 = traits2::end(sit2); - ldest = traits3::begin(sdest); - if (beg1 != end1 && beg2 != end2) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, end2, - ldest, f, proj1, proj2)); - } - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, end2, ldest, f, + proj1, proj2)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit1, ++sit2, ++sdest; sit1 != send1 && sit2 != send2; + ++sit1, ++sit2, ++sdest) + { beg1 = traits1::begin(sit1); beg2 = traits2::begin(sit2); end1 = traits1::end(sit1); @@ -645,30 +619,43 @@ namespace hpx { namespace parallel { } } - return result::get(dataflow( - [=](segment_type&& r) - -> util::in_in_out_result { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - auto rl = r.back().get(); - auto olast1 = traits1::compose(send1, rl.in1); - auto olast2 = traits2::compose(send2, rl.in2); - auto odest = traits3::compose(sdest, rl.out); - return util::in_in_out_result{ - olast1, olast2, odest}; - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg1 = traits1::begin(sit1); + beg2 = traits2::begin(sit2); + end1 = traits1::end(sit1); + end2 = traits2::end(sit2); + ldest = traits3::begin(sdest); + if (beg1 != end1 && beg2 != end2) + { + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, end2, ldest, f, + proj1, proj2)); + } } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + + return result::get(dataflow( + [=](segment_type&& r) + -> util::in_in_out_result { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + auto rl = r.back().get(); + auto olast1 = traits1::compose(send1, rl.in1); + auto olast2 = traits2::compose(send2, rl.in2); + auto odest = traits3::compose(sdest, rl.out); + return util::in_in_out_result{ + olast1, olast2, odest}; + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -698,14 +685,15 @@ namespace hpx { namespace segmented { hpx::identity_v, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename hpx::parallel::util::detail::algorithm_result>::type + hpx::parallel::util::detail::algorithm_result_t> tag_invoke(hpx::transform_t, ExPolicy&& policy, SegIter first, SegIter last, OutIter dest, F&& f) { @@ -736,7 +724,8 @@ namespace hpx { namespace segmented { hpx::identity_v, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -778,8 +767,8 @@ namespace hpx { namespace segmented { proj_id{}, proj_id{}, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -787,8 +776,8 @@ namespace hpx { namespace segmented { hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename hpx::parallel::util::detail::algorithm_result>::type + hpx::parallel::util::detail::algorithm_result_t> tag_invoke(hpx::transform_t, ExPolicy&& policy, InIter1 first1, InIter1 last1, InIter2 first2, OutIter dest, F&& f) { @@ -828,7 +817,8 @@ namespace hpx { namespace segmented { HPX_FORWARD(F, f), proj_id{}, proj_id{}, is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -867,8 +857,8 @@ namespace hpx { namespace segmented { HPX_FORWARD(F, f), proj_id{}, proj_id{}, std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && @@ -876,8 +866,8 @@ namespace hpx { namespace segmented { hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename hpx::parallel::util::detail::algorithm_result>::type + hpx::parallel::util::detail::algorithm_result_t> tag_invoke(hpx::transform_t, ExPolicy&& policy, InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2, OutIter dest, F&& f) { @@ -913,4 +903,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first1, last1, first2, last2, dest, HPX_FORWARD(F, f), proj_id{}, proj_id{}, is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_exclusive_scan.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_exclusive_scan.hpp index b4249e77965a..3c7f85f36903 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_exclusive_scan.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_exclusive_scan.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 Ajai V George // Copyright (c) 2021 Akhil J Nair -// Copyright (c) 2024-2025 Hartmut Kaiser +// Copyright (c) 2024-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -14,6 +14,7 @@ #include #include + #include #include #include @@ -24,10 +25,10 @@ #include // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -50,17 +51,16 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), std::true_type{}, HPX_FORWARD(Conv, conv)); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::transform_exclusive_scan_t, ExPolicy&& policy, - FwdIter1 first, FwdIter1 last, FwdIter2 dest, T init, Op&& op, - Conv&& conv) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::transform_exclusive_scan_t, ExPolicy&& policy, FwdIter1 first, + FwdIter1 last, FwdIter2 dest, T init, Op&& op, Conv&& conv) { static_assert(std::forward_iterator, "Requires at least forward iterator."); @@ -78,4 +78,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, dest, HPX_MOVE(init), HPX_FORWARD(Op, op), is_seq(), HPX_FORWARD(Conv, conv)); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_inclusive_scan.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_inclusive_scan.hpp index 70d555d9dbfc..8b31ab75d81d 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_inclusive_scan.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_inclusive_scan.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 Ajai V George // Copyright (c) 2021 Akhil J Nair -// Copyright (c) 2024-2025 Hartmut Kaiser +// Copyright (c) 2024-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -14,6 +14,7 @@ #include #include + #include #include #include @@ -24,9 +25,10 @@ #include // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -51,16 +53,16 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), std::true_type{}, HPX_FORWARD(Conv, conv)); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::transform_inclusive_scan_t, ExPolicy&& policy, - FwdIter1 first, FwdIter1 last, FwdIter2 dest, Op&& op, Conv&& conv) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::transform_inclusive_scan_t, ExPolicy&& policy, FwdIter1 first, + FwdIter1 last, FwdIter2 dest, Op&& op, Conv&& conv) { static_assert(std::forward_iterator, "Requires at least forward iterator."); @@ -80,8 +82,8 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), is_seq(), HPX_FORWARD(Conv, conv)); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -104,17 +106,16 @@ namespace hpx { namespace segmented { HPX_FORWARD(Op, op), std::true_type{}, HPX_FORWARD(Conv, conv)); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::transform_inclusive_scan_t, ExPolicy&& policy, - FwdIter1 first, FwdIter1 last, FwdIter2 dest, Op&& op, Conv&& conv, - T init) + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::transform_inclusive_scan_t, ExPolicy&& policy, FwdIter1 first, + FwdIter1 last, FwdIter2 dest, Op&& op, Conv&& conv, T init) { static_assert(std::forward_iterator, "Requires at least forward iterator."); @@ -132,4 +133,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(ExPolicy, policy), first, last, dest, HPX_MOVE(init), HPX_FORWARD(Op, op), is_seq(), HPX_FORWARD(Conv, conv)); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_reduce.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_reduce.hpp index 04335a36a6c8..a2db4445e9cc 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_reduce.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/transform_reduce.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2025 Hartmut Kaiser +// Copyright (c) 2007-2026 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -10,6 +10,7 @@ #include #include #include + #include #include @@ -22,73 +23,59 @@ #include #include -namespace hpx { namespace parallel { +namespace hpx::parallel::detail { /////////////////////////////////////////////////////////////////////////// // segmented_transform_reduce - namespace detail { - - /////////////////////////////////////////////////////////////////////// - /// \cond NOINTERNAL - - // sequential remote implementation - template - static typename util::detail::algorithm_result::type - segmented_transform_reduce(Algo&& algo, ExPolicy const& policy, - FwdIter first, FwdIter last, T&& init, Reduce&& red_op, - Convert&& conv_op, std::true_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + /// \cond NOINTERNAL + + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_transform_reduce( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, + T&& init, Reduce&& red_op, Convert&& conv_op, std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef util::detail::algorithm_result result; - T overall_result = init; + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - if (sit == send) + T overall_result = init; + + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, red_op, conv_op)); - } + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, red_op, conv_op)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, red_op, conv_op)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits::get_id(sit), algo, policy, - std::true_type(), beg, end, red_op, conv_op)); - } - } + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, red_op, conv_op)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { overall_result = HPX_INVOKE(red_op, overall_result, @@ -97,70 +84,68 @@ namespace hpx { namespace parallel { } } - return result::get(HPX_MOVE(overall_result)); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits::get_id(sit), algo, policy, + std::true_type(), beg, end, red_op, conv_op)); + } } - // parallel remote implementation - template - static typename util::detail::algorithm_result::type - segmented_transform_reduce(Algo&& algo, ExPolicy const& policy, - FwdIter first, FwdIter last, T&& init, Reduce&& red_op, - Convert&& conv_op, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; + return result::get(HPX_MOVE(overall_result)); + } + + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_transform_reduce( + Algo&& algo, ExPolicy const& policy, FwdIter first, FwdIter last, + T&& init, Reduce&& red_op, Convert&& conv_op, std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits; + typedef typename traits::segment_iterator segment_iterator; + typedef typename traits::local_iterator local_iterator_type; + typedef util::detail::algorithm_result result; - typedef std::integral_constant> - forced_seq; + typedef std::integral_constant> + forced_seq; - segment_iterator sit = traits::segment(first); - segment_iterator send = traits::segment(last); + segment_iterator sit = traits::segment(first); + segment_iterator send = traits::segment(last); - std::vector> segments; - segments.reserve(std::distance(sit, send)); + std::vector> segments; + segments.reserve(std::distance(sit, send)); - if (sit == send) + if (sit == send) + { + // all elements are on the same partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::local(last); + if (beg != end) { - // all elements are on the same partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::local(last); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, red_op, conv_op)); - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, red_op, conv_op)); } - else + } + else + { + // handle the remaining part of the first partition + local_iterator_type beg = traits::local(first); + local_iterator_type end = traits::end(sit); + if (beg != end) { - // handle the remaining part of the first partition - local_iterator_type beg = traits::local(first); - local_iterator_type end = traits::end(sit); - if (beg != end) - { - segments.push_back(dispatch_async(traits::get_id(sit), algo, - policy, forced_seq(), beg, end, red_op, conv_op)); - } - - // handle all of the full partitions - for (++sit; sit != send; ++sit) - { - beg = traits::begin(sit); - end = traits::end(sit); - if (beg != end) - { - segments.push_back( - dispatch_async(traits::get_id(sit), algo, policy, - forced_seq(), beg, end, red_op, conv_op)); - } - } + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, red_op, conv_op)); + } - // handle the beginning of the last partition + // handle all of the full partitions + for (++sit; sit != send; ++sit) + { beg = traits::begin(sit); - end = traits::local(last); + end = traits::end(sit); if (beg != end) { segments.push_back(dispatch_async(traits::get_id(sit), algo, @@ -168,94 +153,89 @@ namespace hpx { namespace parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) -> T { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - // VS2015RC bails out if red_op is capture by ref - return std::accumulate(r.begin(), r.end(), init, - [=](T const& val, shared_future& curr) { - return red_op(val, curr.get()); - }); - }, - HPX_MOVE(segments))); + // handle the beginning of the last partition + beg = traits::begin(sit); + end = traits::local(last); + if (beg != end) + { + segments.push_back(dispatch_async(traits::get_id(sit), algo, + policy, forced_seq(), beg, end, red_op, conv_op)); + } } - // sequential remote implementation - template - static typename util::detail::algorithm_result::type - segmented_transform_reduce(Algo&& algo, ExPolicy const& policy, - FwdIter1 first1, FwdIter1 last1, FwdIter2 first2, T&& init, - Reduce&& red_op, Convert&& conv_op, std::true_type) - { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - typedef util::detail::algorithm_result result; + return result::get(dataflow( + [=](std::vector>&& r) -> T { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + // VS2015RC bails out if red_op is capture by ref + return std::accumulate(r.begin(), r.end(), init, + [=](T const& val, shared_future& curr) { + return red_op(val, curr.get()); + }); + }, + HPX_MOVE(segments))); + } - auto last2 = first2; - detail::advance(last2, std::distance(first1, last1)); + // sequential remote implementation + template + util::detail::algorithm_result_t segmented_transform_reduce( + Algo&& algo, ExPolicy const& policy, FwdIter1 first1, FwdIter1 last1, + FwdIter2 first2, T&& init, Reduce&& red_op, Convert&& conv_op, + std::true_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + typedef util::detail::algorithm_result result; + + auto last2 = first2; + detail::advance(last2, std::distance(first1, last1)); - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits1::segment(first2); + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits1::segment(first2); - T overall_result = init; + T overall_result = init; - if (sit1 == send1) + if (sit1 == send1) + { + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type1 end1 = traits1::local(last1); + if (beg1 != end1) { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type1 end1 = traits1::local(last1); - if (beg1 != end1) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, red_op, - conv_op)); - } + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, red_op, conv_op)); } - else + } + else + { + // handle the remaining part of the first1 partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type2 beg2 = traits2::local(first1); + local_iterator_type1 end1 = traits1::end(sit1); + if (beg1 != end1) { - // handle the remaining part of the first1 partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type2 beg2 = traits2::local(first1); - local_iterator_type1 end1 = traits1::end(sit1); - if (beg1 != end1) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, red_op, - conv_op)); - } - - // handle all of the full partitions - for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) - { - beg1 = traits1::begin(sit1); - beg2 = traits2::begin(sit2); - end1 = traits1::end(sit1); - if (beg1 != end1) - { - overall_result = HPX_INVOKE(red_op, overall_result, - dispatch(traits1::get_id(sit1), algo, policy, - std::true_type(), beg1, end1, beg2, red_op, - conv_op)); - } - } + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, red_op, conv_op)); + } - // handle the beginning of the last1 partition + // handle all of the full partitions + for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) + { beg1 = traits1::begin(sit1); beg2 = traits2::begin(sit2); - end1 = traits1::local(last1); + end1 = traits1::end(sit1); if (beg1 != end1) { overall_result = HPX_INVOKE(red_op, overall_result, @@ -265,83 +245,80 @@ namespace hpx { namespace parallel { } } - return result::get(HPX_MOVE(overall_result)); + // handle the beginning of the last1 partition + beg1 = traits1::begin(sit1); + beg2 = traits2::begin(sit2); + end1 = traits1::local(last1); + if (beg1 != end1) + { + overall_result = HPX_INVOKE(red_op, overall_result, + dispatch(traits1::get_id(sit1), algo, policy, + std::true_type(), beg1, end1, beg2, red_op, conv_op)); + } } - // parallel remote implementation - template - static typename util::detail::algorithm_result::type - segmented_transform_reduce(Algo&& algo, ExPolicy const& policy, - FwdIter1 first1, FwdIter1 last1, FwdIter2 first2, T&& init, - Reduce&& red_op, Convert&& conv_op, std::false_type) - { - typedef hpx::traits::segmented_iterator_traits traits1; - typedef typename traits1::segment_iterator segment_iterator1; - typedef typename traits1::local_iterator local_iterator_type1; - typedef hpx::traits::segmented_iterator_traits traits2; - typedef typename traits2::segment_iterator segment_iterator2; - typedef typename traits2::local_iterator local_iterator_type2; - typedef util::detail::algorithm_result result; + return result::get(HPX_MOVE(overall_result)); + } - auto last2 = first2; - detail::advance(last2, std::distance(first1, last1)); + // parallel remote implementation + template + util::detail::algorithm_result_t segmented_transform_reduce( + Algo&& algo, ExPolicy const& policy, FwdIter1 first1, FwdIter1 last1, + FwdIter2 first2, T&& init, Reduce&& red_op, Convert&& conv_op, + std::false_type) + { + typedef hpx::traits::segmented_iterator_traits traits1; + typedef typename traits1::segment_iterator segment_iterator1; + typedef typename traits1::local_iterator local_iterator_type1; + typedef hpx::traits::segmented_iterator_traits traits2; + typedef typename traits2::segment_iterator segment_iterator2; + typedef typename traits2::local_iterator local_iterator_type2; + typedef util::detail::algorithm_result result; + + auto last2 = first2; + detail::advance(last2, std::distance(first1, last1)); - segment_iterator1 sit1 = traits1::segment(first1); - segment_iterator1 send1 = traits1::segment(last1); - segment_iterator2 sit2 = traits1::segment(first2); + segment_iterator1 sit1 = traits1::segment(first1); + segment_iterator1 send1 = traits1::segment(last1); + segment_iterator2 sit2 = traits1::segment(first2); - typedef std::integral_constant> - forced_seq; + typedef std::integral_constant> + forced_seq; - std::vector> segments; - segments.reserve(std::distance(sit1, send1)); + std::vector> segments; + segments.reserve(std::distance(sit1, send1)); - if (sit1 == send1) + if (sit1 == send1) + { + // all elements are on the same partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type1 end1 = traits1::local(last1); + if (beg1 != end1) { - // all elements are on the same partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type1 end1 = traits1::local(last1); - if (beg1 != end1) - { - segments.push_back( - dispatch_async(traits1::get_id(sit1), algo, policy, - forced_seq(), beg1, end1, beg2, red_op, conv_op)); - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, red_op, conv_op)); } - else + } + else + { + // handle the remaining part of the first1 partition + local_iterator_type1 beg1 = traits1::local(first1); + local_iterator_type2 beg2 = traits2::local(first2); + local_iterator_type1 end1 = traits1::end(sit1); + if (beg1 != end1) { - // handle the remaining part of the first1 partition - local_iterator_type1 beg1 = traits1::local(first1); - local_iterator_type2 beg2 = traits2::local(first2); - local_iterator_type1 end1 = traits1::end(sit1); - if (beg1 != end1) - { - segments.push_back( - dispatch_async(traits1::get_id(sit1), algo, policy, - forced_seq(), beg1, end1, beg2, red_op, conv_op)); - } - - // handle all of the full partitions - for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) - { - beg1 = traits1::begin(sit1); - beg2 = traits2::begin(sit2); - end1 = traits1::end(sit1); - if (beg1 != end1) - { - segments.push_back(dispatch_async(traits1::get_id(sit1), - algo, policy, forced_seq(), beg1, end1, beg2, - red_op, conv_op)); - } - } + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, red_op, conv_op)); + } - // handle the beginning of the last1 partition + // handle all of the full partitions + for (++sit1, ++sit2; sit1 != send1; ++sit1, ++sit2) + { beg1 = traits1::begin(sit1); beg2 = traits2::begin(sit2); - end1 = traits1::local(last1); + end1 = traits1::end(sit1); if (beg1 != end1) { segments.push_back( @@ -350,34 +327,44 @@ namespace hpx { namespace parallel { } } - return result::get(dataflow( - [=](std::vector>&& r) -> T { - // handle any remote exceptions, will throw on error - std::list errors; - parallel::util::detail::handle_remote_exceptions< - ExPolicy>::call(r, errors); - - // VS2015RC bails out if red_op is capture by ref - return std::accumulate(r.begin(), r.end(), init, - [=](T const& val, shared_future& curr) { - return red_op(val, curr.get()); - }); - }, - HPX_MOVE(segments))); + // handle the beginning of the last1 partition + beg1 = traits1::begin(sit1); + beg2 = traits2::begin(sit2); + end1 = traits1::local(last1); + if (beg1 != end1) + { + segments.push_back(dispatch_async(traits1::get_id(sit1), algo, + policy, forced_seq(), beg1, end1, beg2, red_op, conv_op)); + } } - /// \endcond - } // namespace detail -}} // namespace hpx::parallel + + return result::get(dataflow( + [=](std::vector>&& r) -> T { + // handle any remote exceptions, will throw on error + std::list errors; + parallel::util::detail::handle_remote_exceptions< + ExPolicy>::call(r, errors); + + // VS2015RC bails out if red_op is capture by ref + return std::accumulate(r.begin(), r.end(), init, + [=](T const& val, shared_future& curr) { + return red_op(val, curr.get()); + }); + }, + HPX_MOVE(segments))); + } + /// \endcond +} // namespace hpx::parallel::detail // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename std::decay::type tag_invoke(hpx::transform_reduce_t, - SegIter first, SegIter last, T&& init, Reduce&& red_op, - Convert&& conv_op) + std::decay_t tag_invoke(hpx::transform_reduce_t, SegIter first, + SegIter last, T&& init, Reduce&& red_op, Convert&& conv_op) { static_assert( std::input_iterator, "Requires at least input iterator."); @@ -396,13 +383,12 @@ namespace hpx { namespace segmented { std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type>::type + parallel::util::detail::algorithm_result_t> tag_invoke(hpx::transform_reduce_t, ExPolicy&& policy, SegIter first, SegIter last, T&& init, Reduce&& red_op, Convert&& conv_op) { @@ -425,8 +411,8 @@ namespace hpx { namespace segmented { is_seq()); } - template + HPX_CXX_EXPORT template requires(hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && @@ -450,15 +436,15 @@ namespace hpx { namespace segmented { std::true_type{}); } - template + HPX_CXX_EXPORT template requires(hpx::is_execution_policy_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v && hpx::traits::is_iterator_v && hpx::traits::is_segmented_iterator_v) - typename parallel::util::detail::algorithm_result::type - tag_invoke(hpx::transform_reduce_t, ExPolicy&& policy, FwdIter1 first1, + parallel::util::detail::algorithm_result_t tag_invoke( + hpx::transform_reduce_t, ExPolicy&& policy, FwdIter1 first1, FwdIter1 last1, FwdIter2 first2, T init, Reduce&& red_op, Convert&& conv_op) { @@ -480,4 +466,4 @@ namespace hpx { namespace segmented { HPX_FORWARD(T, init), HPX_FORWARD(Reduce, red_op), HPX_FORWARD(Convert, conv_op), is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_copy.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_copy.cpp index cdd2f0c232c7..11787fe4b872 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_copy.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_copy.cpp @@ -11,8 +11,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_equal.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_equal.cpp index 32a7415083de..e7d3d867fb57 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_equal.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_equal.cpp @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_mismatch.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_mismatch.cpp index 7dcf7b9efcf8..3eebb0cb1e3e 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_mismatch.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_mismatch.cpp @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_move.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_move.cpp index dc9efff9339a..464983e43948 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_move.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_move.cpp @@ -11,8 +11,7 @@ #include #include #include -#include - +#include #include #include diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce1.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce1.cpp index b7837f4aaf5f..003ac209472b 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce1.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce1.cpp @@ -11,9 +11,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce2.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce2.cpp index bbf391db8440..545673e9f129 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce2.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce2.cpp @@ -11,9 +11,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary1.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary1.cpp index 65f5374a1e3e..9f1f74f7a69d 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary1.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary1.cpp @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary2.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary2.cpp index 0bebb57fd42b..885675576061 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary2.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_transform_reduce_binary2.cpp @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include #include