-
-
Notifications
You must be signed in to change notification settings - Fork 437
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Contains and contains_subrange parallel algorithm implementaion
- Loading branch information
1 parent
ba8f05f
commit 711ca44
Showing
8 changed files
with
697 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
libs/core/algorithms/include/hpx/parallel/algorithms/contains.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// Copyright (c) 2024 Zakaria Abdi | ||
// 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) | ||
|
||
#pragma once | ||
|
||
#include <hpx/config.hpp> | ||
#include <hpx/coroutines/thread_enums.hpp> | ||
#include <hpx/execution/algorithms/detail/predicates.hpp> | ||
#include <hpx/executors/execution_policy.hpp> | ||
#include <hpx/iterator_support/traits/is_iterator.hpp> | ||
#include <hpx/parallel/algorithms/detail/contains.hpp> | ||
#include <hpx/parallel/algorithms/detail/dispatch.hpp> | ||
#include <hpx/parallel/algorithms/detail/distance.hpp> | ||
#include <hpx/parallel/util/adapt_placement_mode.hpp> | ||
#include <hpx/parallel/util/cancellation_token.hpp> | ||
#include <hpx/parallel/util/detail/algorithm_result.hpp> | ||
#include <hpx/parallel/util/loop.hpp> | ||
#include <hpx/parallel/util/partitioner.hpp> | ||
#include <hpx/parallel/util/zip_iterator.hpp> | ||
#include <hpx/type_support/identity.hpp> | ||
|
||
#include <algorithm> | ||
#include <cstddef> | ||
#include <iterator> | ||
#include <type_traits> | ||
#include <utility> | ||
|
||
namespace hpx::parallel { namespace detail { | ||
struct contains : public algorithm<contains, bool> | ||
{ | ||
constexpr contains() noexcept | ||
: algorithm("contains") | ||
{ | ||
} | ||
|
||
template <typename ExPolicy, typename Iterator, typename Sentinel, | ||
typename T, typename Proj> | ||
static constexpr bool sequential( | ||
ExPolicy, Iterator first, Sentinel last, const T& val, Proj&& proj) | ||
{ | ||
return sequential_contains<std::decay<ExPolicy>>( | ||
first, last, val, HPX_FORWARD(Proj, proj)); | ||
} | ||
|
||
template <typename ExPolicy, typename Iterator, typename Sentinel, | ||
typename T, typename Proj> | ||
static util::detail::algorithm_result_t<ExPolicy, bool> parallel( | ||
ExPolicy&& orgpolicy, Iterator first, Sentinel last, const T& val, | ||
Proj&& proj) | ||
{ | ||
using difference_type = | ||
typename std::iterator_traits<Iterator>::difference_type; | ||
difference_type count = detail::distance(first, last); | ||
if (count <= 0) | ||
return util::detail::algorithm_result<ExPolicy, bool>::get( | ||
false); | ||
|
||
decltype(auto) policy = parallel::util::adapt_placement_mode( | ||
HPX_FORWARD(ExPolicy, orgpolicy), | ||
hpx::threads::thread_placement_hint::breadth_first); | ||
|
||
using policy_type = std::decay_t<decltype(policy)>; | ||
util::cancellation_token<> tok; | ||
auto f1 = [val, tok, proj](Iterator first, std::size_t count) { | ||
sequential_contains<policy_type>(first, val, count, tok, proj); | ||
return tok.was_cancelled(); | ||
}; | ||
|
||
auto f2 = [](auto&& results) { | ||
return std::any_of(hpx::util::begin(results), | ||
hpx::util::end(results), | ||
[](hpx::future<bool>& val) { return val.get(); }); | ||
}; | ||
|
||
return util::partitioner<policy_type, bool>::call( | ||
HPX_FORWARD(decltype(policy), policy), first, count, | ||
HPX_MOVE(f1), HPX_MOVE(f2)); | ||
} | ||
}; | ||
}} // namespace hpx::parallel::detail | ||
namespace hpx { | ||
|
||
inline constexpr struct contains_t final | ||
: hpx::functional::detail::tag_fallback<contains_t> | ||
{ | ||
private: | ||
template <typename Iterator, typename Sentinel, typename T, | ||
typename Proj = hpx::identity, | ||
HPX_CONCEPT_REQUIRES_(hpx::traits::is_iterator_v<Iterator>&& hpx:: | ||
traits::is_iterator_v<Iterator>&& hpx::is_invocable_v<Proj, | ||
typename std::iterator_traits<Iterator>::value_type>)> | ||
|
||
friend bool tag_fallback_invoke(hpx::contains_t, Iterator first, | ||
Sentinel last, const T& val, Proj&& proj = Proj()) | ||
{ | ||
static_assert(hpx::traits::is_input_iterator_v<Iterator>, | ||
"Required at least input iterator."); | ||
|
||
static_assert(hpx::traits::is_input_iterator_v<Sentinel>, | ||
"Required at least input iterator."); | ||
|
||
return hpx::parallel::detail::contains().call( | ||
hpx::execution::seq, first, last, val, proj); | ||
} | ||
|
||
template <typename ExPolicy, typename Iterator, typename Sentinel, | ||
typename T, typename Proj = hpx::identity, | ||
HPX_CONCEPT_REQUIRES_(hpx::is_execution_policy_v< | ||
ExPolicy>&& hpx::traits::is_iterator_v<Iterator>&& hpx::traits:: | ||
is_iterator_v<Iterator>&& hpx::is_invocable_v<Proj, | ||
typename std::iterator_traits<Iterator>::value_type>)> | ||
|
||
friend typename parallel::util::detail::algorithm_result<ExPolicy, | ||
bool>::type | ||
tag_fallback_invoke(hpx::contains_t, ExPolicy&& policy, Iterator first, | ||
Sentinel last, T const& val, Proj&& proj = Proj()) | ||
{ | ||
static_assert(hpx::traits::is_iterator_v<Iterator>, | ||
"Required at least iterator."); | ||
|
||
static_assert(hpx::traits::is_iterator_v<Sentinel>, | ||
"Required at least iterator."); | ||
|
||
return hpx::parallel::detail::contains().call( | ||
HPX_FORWARD(ExPolicy, policy), first, last, val, | ||
HPX_FORWARD(Proj, proj)); | ||
} | ||
|
||
} contains{}; | ||
} // namespace hpx |
63 changes: 63 additions & 0 deletions
63
libs/core/algorithms/include/hpx/parallel/algorithms/detail/contains.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright (c) 2024 Zakaria Abdi | ||
// 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) | ||
|
||
#pragma once | ||
|
||
#include <hpx/config.hpp> | ||
#include <hpx/functional/detail/tag_fallback_invoke.hpp> | ||
#include <hpx/functional/invoke.hpp> | ||
#include <hpx/parallel/util/loop.hpp> | ||
|
||
#include <algorithm> | ||
#include <cstddef> | ||
#include <type_traits> | ||
#include <utility> | ||
|
||
namespace hpx::parallel::detail { | ||
|
||
template <typename ExPolicy> | ||
struct sequential_contains_t final | ||
: hpx::functional::detail::tag_fallback<sequential_contains_t<ExPolicy>> | ||
{ | ||
private: | ||
template <typename Iterator, typename Sentinel, typename T, | ||
typename Proj> | ||
friend constexpr bool tag_fallback_invoke(sequential_contains_t, | ||
Iterator first, Sentinel last, const T& val, Proj&& proj) | ||
{ | ||
using difference_type = | ||
typename std::iterator_traits<Iterator>::difference_type; | ||
difference_type distance = detail::distance(first, last); | ||
if (distance <= 0) | ||
return false; | ||
|
||
const auto itr = | ||
util::loop_pred<std::decay_t<hpx::execution::sequenced_policy>>( | ||
first, last, [&val, &proj](const auto& cur) { | ||
return HPX_INVOKE(proj, *cur) == val; | ||
}); | ||
|
||
return itr != last; | ||
} | ||
|
||
template <typename Iterator, typename T, typename Token, typename Proj> | ||
friend constexpr void tag_fallback_invoke(sequential_contains_t, | ||
Iterator first, T const& val, std::size_t count, Token& tok, | ||
Proj&& proj) | ||
{ | ||
util::loop_n<ExPolicy>( | ||
first, count, tok, [&val, &tok, &proj](const auto& cur) { | ||
if (HPX_INVOKE(proj, *cur) == val) | ||
{ | ||
tok.cancel(); | ||
return; | ||
} | ||
}); | ||
} | ||
}; | ||
template <typename ExPolicy> | ||
inline constexpr sequential_contains_t<ExPolicy> sequential_contains = | ||
sequential_contains_t<ExPolicy>{}; | ||
} //namespace hpx::parallel::detail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ set(tests | |
adjacentfind_binary | ||
all_of | ||
any_of | ||
contains | ||
copy | ||
copyif_random | ||
copyif_forward | ||
|
112 changes: 112 additions & 0 deletions
112
libs/core/algorithms/tests/unit/algorithms/contains.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Copyright (c) 2024 Zakaria Abdi | ||
// 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) | ||
|
||
#pragma once | ||
|
||
#include <iostream> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include <hpx/init.hpp> | ||
#include "contains_tests.hpp" | ||
|
||
//////////////////////////////////////////////////////////////////////////// | ||
template <typename IteratorTag> | ||
void test_contains() | ||
{ | ||
using namespace hpx::execution; | ||
|
||
test_contains(IteratorTag()); | ||
|
||
test_contains(seq, IteratorTag()); | ||
test_contains(par, IteratorTag()); | ||
test_contains(par_unseq, IteratorTag()); | ||
|
||
test_contains_async(seq(task), IteratorTag()); | ||
test_contains_async(par(task), IteratorTag()); | ||
test_contains_async(par_unseq(task), IteratorTag()); | ||
} | ||
|
||
void contains_test() | ||
{ | ||
test_contains<std::random_access_iterator_tag>(); | ||
test_contains<std::forward_iterator_tag>(); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////////// | ||
template <typename IteratorTag> | ||
void test_contains_exception() | ||
{ | ||
using namespace hpx::execution; | ||
|
||
test_contains_exception(IteratorTag()); | ||
|
||
test_contains_exception(seq, IteratorTag()); | ||
test_contains_exception(par, IteratorTag()); | ||
|
||
test_contains_exception_async(seq(task), IteratorTag()); | ||
test_contains_exception_async(par(task), IteratorTag()); | ||
} | ||
|
||
void contains_exception_test() | ||
{ | ||
test_contains_exception<std::random_access_iterator_tag>(); | ||
test_contains_exception<std::forward_iterator_tag>(); | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////////// | ||
template <typename IteratorTag> | ||
void test_contains_bad_alloc() | ||
{ | ||
using namespace hpx::execution; | ||
|
||
test_contains_bad_alloc(seq, IteratorTag()); | ||
test_contains_bad_alloc(par, IteratorTag()); | ||
|
||
test_contains_bad_alloc_async(seq(task), IteratorTag()); | ||
test_contains_bad_alloc_async(par(task), IteratorTag()); | ||
} | ||
|
||
void contains_bad_alloc_test() | ||
{ | ||
test_contains_bad_alloc<std::random_access_iterator_tag>(); | ||
test_contains_bad_alloc<std::forward_iterator_tag>(); | ||
} | ||
|
||
int hpx_main(hpx::program_options::variables_map& vm) | ||
{ | ||
if (vm.count("seed")) | ||
seed = vm["seed"].as<unsigned int>(); | ||
|
||
std::cout << "Using seed as: " << seed << std::endl; | ||
gen.seed(seed); | ||
|
||
contains_test(); | ||
contains_exception_test(); | ||
contains_bad_alloc_test(); | ||
|
||
return hpx::local::finalize(); | ||
} | ||
|
||
int main(int argc, char* argv[]) | ||
{ | ||
using namespace hpx::program_options; | ||
options_description desc_commandline( | ||
"Usage" HPX_APPLICATION_STRING " [options]"); | ||
|
||
desc_commandline.add_options()("seed,s", value<unsigned int>(), | ||
" the random number generator to use for this run"); | ||
|
||
std::vector<std::string> cfg = {"hpx.os_threads=all"}; | ||
|
||
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(); | ||
} |
Oops, something went wrong.