diff --git a/libs/parallelism/algorithms/include/hpx/parallel/algorithms/lexicographical_compare.hpp b/libs/parallelism/algorithms/include/hpx/parallel/algorithms/lexicographical_compare.hpp index cce3698424bd..83f07254950b 100644 --- a/libs/parallelism/algorithms/include/hpx/parallel/algorithms/lexicographical_compare.hpp +++ b/libs/parallelism/algorithms/include/hpx/parallel/algorithms/lexicographical_compare.hpp @@ -250,7 +250,8 @@ namespace hpx { namespace parallel { inline namespace v1 { std::size_t part_count, std::size_t base_idx) mutable -> void { util::loop_idx_n(base_idx, it, part_count, tok, - [&pred, &tok](reference t, std::size_t i) -> void { + [&pred, &tok, &proj1, &proj2]( + reference t, std::size_t i) -> void { using hpx::get; using hpx::util::invoke; if (invoke(pred, invoke(proj1, get<0>(t)), diff --git a/libs/parallelism/algorithms/tests/unit/container_algorithms/CMakeLists.txt b/libs/parallelism/algorithms/tests/unit/container_algorithms/CMakeLists.txt index 93b5807d86cd..3f13ab5bf70f 100644 --- a/libs/parallelism/algorithms/tests/unit/container_algorithms/CMakeLists.txt +++ b/libs/parallelism/algorithms/tests/unit/container_algorithms/CMakeLists.txt @@ -53,6 +53,7 @@ set(tests is_partitioned_projection_range is_sorted_range is_sorted_until_range + lexicographical_compare_range make_heap_range max_element_range merge_range diff --git a/libs/parallelism/algorithms/tests/unit/container_algorithms/lexicographical_compare_range.cpp b/libs/parallelism/algorithms/tests/unit/container_algorithms/lexicographical_compare_range.cpp new file mode 100644 index 000000000000..e1594075f3d5 --- /dev/null +++ b/libs/parallelism/algorithms/tests/unit/container_algorithms/lexicographical_compare_range.cpp @@ -0,0 +1,281 @@ +// Copyright (c) 2018 Christopher Ogle +// Copyright (c) 2020 Hartmut Kaiser +// +// 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) + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "test_utils.hpp" + +//////////////////////////////////////////////////////////////////////////// +unsigned int seed; +std::mt19937 gen; +std::uniform_int_distribution<> dis(0, 25); + +void test_fill_sent() +{ + std::vector c1(10); + std::generate( + std::begin(c1), std::end(c1), []() { return 'a' + dis(gen); }); + + std::vector c2(10); + std::generate( + std::begin(c2), std::end(c2), []() { return 'a' + dis(gen); }); + + bool actual_result1 = std::lexicographical_compare( + std::begin(c1), std::begin(c1) + 5, std::begin(c2), std::begin(c2) + 5); + bool result1 = hpx::ranges::lexicographical_compare(std::begin(c1), + sentinel{*(std::begin(c1) + 5)}, std::begin(c2), + sentinel{*(std::begin(c2) + 5)}); + + bool actual_result2 = std::lexicographical_compare( + std::begin(c2), std::begin(c2) + 5, std::begin(c1), std::begin(c1) + 5); + bool result2 = hpx::ranges::lexicographical_compare(std::begin(c2), + sentinel{*(std::begin(c2) + 5)}, std::begin(c1), + sentinel{*(std::begin(c1) + 5)}); + + bool actual_result3 = std::lexicographical_compare( + std::begin(c1), std::begin(c1) + 5, std::begin(c1), std::begin(c1) + 5); + bool result3 = hpx::ranges::lexicographical_compare(std::begin(c1), + sentinel{*(std::begin(c1) + 5)}, std::begin(c1), + sentinel{*(std::begin(c1) + 5)}); + + HPX_TEST_EQ(actual_result1, result1); + HPX_TEST_EQ(actual_result2, result2); + HPX_TEST_EQ(actual_result3, result3); + + // check corner cases + std::vector c3 = {1, 1, 1, 1, 3, 2, 2, 8}; + std::vector c4 = {1, 1, 1, 1, 3, 5, 5, 8}; + auto result4 = hpx::ranges::lexicographical_compare( + std::begin(c3), sentinel{3}, std::begin(c4), sentinel{3}); + auto result5 = hpx::ranges::lexicographical_compare( + std::begin(c3), sentinel{8}, std::begin(c4), sentinel{8}); + + HPX_TEST_EQ(false, result4); + HPX_TEST_EQ(true, result5); +} + +template +void test_fill_sent(ExPolicy policy) +{ + static_assert(hpx::is_execution_policy::value, + "hpx::is_execution_policy::value"); + + std::vector c1(10); + std::generate( + std::begin(c1), std::end(c1), []() { return 'a' + dis(gen); }); + + std::vector c2(10); + std::generate( + std::begin(c2), std::end(c2), []() { return 'a' + dis(gen); }); + + bool actual_result1 = std::lexicographical_compare( + std::begin(c1), std::begin(c1) + 5, std::begin(c2), std::begin(c2) + 5); + bool result1 = hpx::ranges::lexicographical_compare(policy, std::begin(c1), + sentinel{*(std::begin(c1) + 5)}, std::begin(c2), + sentinel{*(std::begin(c2) + 5)}); + + bool actual_result2 = std::lexicographical_compare( + std::begin(c2), std::begin(c2) + 5, std::begin(c1), std::begin(c1) + 5); + bool result2 = hpx::ranges::lexicographical_compare(policy, std::begin(c2), + sentinel{*(std::begin(c2) + 5)}, std::begin(c1), + sentinel{*(std::begin(c1) + 5)}); + + bool actual_result3 = std::lexicographical_compare( + std::begin(c1), std::begin(c1) + 5, std::begin(c1), std::begin(c1) + 5); + bool result3 = hpx::ranges::lexicographical_compare(policy, std::begin(c1), + sentinel{*(std::begin(c1) + 5)}, std::begin(c1), + sentinel{*(std::begin(c1) + 5)}); + + HPX_TEST_EQ(actual_result1, result1); + HPX_TEST_EQ(actual_result2, result2); + HPX_TEST_EQ(actual_result3, result3); + + // check corner cases + std::vector c3 = {1, 1, 1, 1, 3, 2, 2, 8}; + std::vector c4 = {1, 1, 1, 1, 3, 5, 5, 8}; + auto result4 = hpx::ranges::lexicographical_compare(policy, std::begin(c3), + sentinel{3}, std::begin(c4), sentinel{3}); + auto result5 = hpx::ranges::lexicographical_compare(policy, std::begin(c3), + sentinel{8}, std::begin(c4), sentinel{8}); + + HPX_TEST_EQ(false, result4); + HPX_TEST_EQ(true, result5); +} + +template +void test_lexicographical_compare(IteratorTag) +{ + std::vector c1(10); + std::generate(std::begin(c1), std::end(c1), + []() { return 'a' + dis(gen); }); + + std::vector c2(10); + std::generate( + std::begin(c2), std::end(c2), []() { return 'a' + dis(gen); }); + + bool actual_result1 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + bool result1 = hpx::ranges::lexicographical_compare(c1, c2); + + bool actual_result2 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + bool result2 = hpx::ranges::lexicographical_compare(c1, c2); + + bool actual_result3 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + bool result3 = hpx::ranges::lexicographical_compare(c1, c2); + + HPX_TEST_EQ(actual_result1, result1); + HPX_TEST_EQ(actual_result2, result2); + HPX_TEST_EQ(actual_result3, result3); +} + +template +void test_lexicographical_compare(ExPolicy policy, IteratorTag) +{ + static_assert(hpx::is_execution_policy::value, + "hpx::is_execution_policy::value"); + + std::vector c1(10); + std::generate( + std::begin(c1), std::end(c1), []() { return 'a' + dis(gen); }); + + std::vector c2(10); + std::generate( + std::begin(c2), std::end(c2), []() { return 'a' + dis(gen); }); + + bool actual_result1 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + bool result1 = hpx::ranges::lexicographical_compare(policy, c1, c2); + + bool actual_result2 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + bool result2 = hpx::ranges::lexicographical_compare(policy, c1, c2); + + bool actual_result3 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + bool result3 = hpx::ranges::lexicographical_compare(policy, c1, c2); + + HPX_TEST_EQ(actual_result1, result1); + HPX_TEST_EQ(actual_result2, result2); + HPX_TEST_EQ(actual_result3, result3); +} + +template +void test_fill_async(ExPolicy policy, IteratorTag) +{ + static_assert(hpx::is_execution_policy::value, + "hpx::is_execution_policy::value"); + + std::vector c1(10); + std::generate( + std::begin(c1), std::end(c1), []() { return 'a' + dis(gen); }); + + std::vector c2(10); + std::generate( + std::begin(c2), std::end(c2), []() { return 'a' + dis(gen); }); + + bool actual_result1 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + hpx::future result1 = + hpx::ranges::lexicographical_compare(policy, c1, c2); + + bool actual_result2 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + hpx::future result2 = + hpx::ranges::lexicographical_compare(policy, c1, c2); + + bool actual_result3 = std::lexicographical_compare( + std::begin(c1), std::end(c1), std::begin(c2), std::end(c2)); + hpx::future result3 = + hpx::ranges::lexicographical_compare(policy, c1, c2); + + result1.wait(); + result2.wait(); + result3.wait(); + + HPX_TEST_EQ(actual_result1, result1.get()); + HPX_TEST_EQ(actual_result2, result2.get()); + HPX_TEST_EQ(actual_result3, result3.get()); +} + +template +void test_lexicographical_compare() +{ + using namespace hpx::execution; + + test_lexicographical_compare(IteratorTag()); + test_lexicographical_compare(seq, IteratorTag()); + test_lexicographical_compare(par, IteratorTag()); + test_lexicographical_compare(par_unseq, IteratorTag()); + + test_fill_async(seq(task), IteratorTag()); + test_fill_async(par(task), IteratorTag()); + + test_fill_sent(); + test_fill_sent(seq); + test_fill_sent(par); + test_fill_sent(par_unseq); +} + +void lexicographical_compare_test() +{ + test_lexicographical_compare(); + test_lexicographical_compare(); +} + +//////////////////////////////////////////////////////////////////////////// +int hpx_main(hpx::program_options::variables_map& vm) +{ + unsigned int seed1 = (unsigned int) std::time(nullptr); + if (vm.count("seed")) + seed1 = vm["seed"].as(); + + std::cout << "using seed: " << seed1 << std::endl; + std::srand(seed1); + + seed = seed1; + gen = std::mt19937(seed); + + lexicographical_compare_test(); + return hpx::local::finalize(); +} + +int main(int argc, char* argv[]) +{ + // add command line option which controls the random number generator seed + using namespace hpx::program_options; + options_description desc_commandline( + "Usage: " HPX_APPLICATION_STRING " [options]"); + + desc_commandline.add_options()("seed,s", value(), + "the random number generator seed to use for this run"); + + // By default this test should run on all available cores + std::vector const cfg = {"hpx.os_threads=all"}; + + // Initialize and run HPX + hpx::local::init_params init_args; + init_args.desc_cmdline = desc_commandline; + init_args.cfg = cfg; + + HPX_TEST_EQ_MSG(hpx::local::init(hpx_main, argc, argv, init_args), 0, + "HPX main exited with non-zero status"); + + return hpx::util::report_errors(); +}