Skip to content

Commit

Permalink
Added projection to parallel::any_of (see STEllAR-GROUP#1668)
Browse files Browse the repository at this point in the history
  • Loading branch information
brjsp committed Nov 4, 2017
1 parent e15f763 commit e2e9dba
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 27 deletions.
49 changes: 34 additions & 15 deletions hpx/parallel/algorithms/all_any_none.hpp
Expand Up @@ -217,19 +217,26 @@ namespace hpx { namespace parallel { inline namespace v1
: any_of::algorithm("any_of")
{}

template <typename ExPolicy, typename InIter, typename F>
template <typename ExPolicy, typename InIter,
typename F, typename Proj>
static bool
sequential(ExPolicy, InIter first, InIter last, F && f)
sequential(ExPolicy, InIter first, InIter last,
F && f, Proj && proj)
{
return std::any_of(first, last, std::forward<F>(f));
return std::any_of(first, last,
util::invoke_projected<F, Proj>(
std::forward<F>(f),
std::forward<Proj>(proj)
));
}

template <typename ExPolicy, typename FwdIter, typename F>
template <typename ExPolicy, typename FwdIter,
typename F, typename Proj>
static typename util::detail::algorithm_result<
ExPolicy, bool
>::type
parallel(ExPolicy && policy, FwdIter first, FwdIter last,
F && op)
F && op, Proj && proj)
{
if (first == last)
{
Expand All @@ -240,17 +247,17 @@ namespace hpx { namespace parallel { inline namespace v1

util::cancellation_token<> tok;
auto f1 =
[op, tok, policy](
[op, tok, policy, proj](
FwdIter part_begin, std::size_t part_count
) mutable -> bool
{
HPX_UNUSED(policy);

util::loop_n<ExPolicy>(
part_begin, part_count, tok,
[&op, &tok](FwdIter const& curr)
[&op, &tok, &proj](FwdIter const& curr)
{
if (op(*curr))
if (op(proj(*curr)))
tok.cancel();
});

Expand Down Expand Up @@ -292,6 +299,8 @@ namespace hpx { namespace parallel { inline namespace v1
/// (deduced). Unlike its sequential form, the parallel
/// overload of \a any_of requires \a F to meet the
/// requirements of \a CopyConstructible.
/// \tparam Proj The type of an optional projection function. This
/// defaults to \a util::projection_identity
///
/// \param policy The execution policy to use for the scheduling of
/// the iterations.
Expand All @@ -312,6 +321,10 @@ namespace hpx { namespace parallel { inline namespace v1
/// to it. The type \a Type must be such that an object
/// of type \a FwdIter can be dereferenced and then
/// implicitly converted to Type.
/// \param proj Specifies the function (or function object) which
/// will be invoked for each of the elements as a
/// projection operation before the actual predicate
/// \a is invoked.
///
/// The application of function objects in parallel algorithm
/// invoked with an execution policy object of type
Expand All @@ -333,12 +346,18 @@ namespace hpx { namespace parallel { inline namespace v1
/// \a f returns true for at least one element in the range,
/// false otherwise. It returns false if the range is empty.
///
template <typename ExPolicy, typename FwdIter, typename F>
inline typename std::enable_if<
execution::is_execution_policy<ExPolicy>::value,
typename util::detail::algorithm_result<ExPolicy, bool>::type
>::type
any_of(ExPolicy && policy, FwdIter first, FwdIter last, F && f)
template <typename ExPolicy, typename FwdIter, typename F,
typename Proj = util::projection_identity,
HPX_CONCEPT_REQUIRES_(
execution::is_execution_policy<ExPolicy>::value &&
hpx::traits::is_iterator<FwdIter>::value &&
traits::is_projected<Proj, FwdIter>::value &&
traits::is_indirect_callable<
ExPolicy, F, traits::projected<Proj, FwdIter>
>::value)>
typename util::detail::algorithm_result<ExPolicy, bool>::type
any_of(ExPolicy && policy, FwdIter first, FwdIter last, F && f,
Proj && proj = Proj())
{
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
static_assert(
Expand All @@ -359,7 +378,7 @@ namespace hpx { namespace parallel { inline namespace v1

return detail::any_of().call(
std::forward<ExPolicy>(policy), is_seq(),
first, last, std::forward<F>(f));
first, last, std::forward<F>(f), std::forward<Proj>(proj));
}

///////////////////////////////////////////////////////////////////////////
Expand Down
54 changes: 42 additions & 12 deletions tests/unit/parallel/algorithms/any_of.cpp
Expand Up @@ -7,6 +7,7 @@
#include <hpx/hpx.hpp>
#include <hpx/include/parallel_all_any_none_of.hpp>
#include <hpx/util/lightweight_test.hpp>
#include <hpx/parallel/util/projection_identity.hpp>


#include <cstddef>
Expand All @@ -18,8 +19,9 @@
#include "test_utils.hpp"

///////////////////////////////////////////////////////////////////////////////
template <typename ExPolicy, typename IteratorTag>
void test_any_of(ExPolicy policy, IteratorTag)
template <typename ExPolicy, typename IteratorTag,
typename Proj = util::projection_identity>
void test_any_of(ExPolicy policy, IteratorTag,Proj proj=Proj())
{
static_assert(
hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
Expand All @@ -38,21 +40,22 @@ void test_any_of(ExPolicy policy, IteratorTag)
iterator(std::begin(c)), iterator(std::end(c)),
[](std::size_t v) {
return v != 0;
});
},proj);

// verify values
bool expected =
std::any_of(std::begin(c), std::end(c),
[](std::size_t v) {
return v != 0;
[proj](std::size_t v) {
return proj(v) != 0;
});

HPX_TEST_EQ(result, expected);
}
}

template <typename ExPolicy, typename IteratorTag>
void test_any_of_async(ExPolicy p, IteratorTag)
template <typename ExPolicy, typename IteratorTag,
typename Proj = util::projection_identity>
void test_any_of_async(ExPolicy p, IteratorTag,Proj proj=Proj())
{
typedef std::vector<std::size_t>::iterator base_iterator;
typedef test::test_iterator<base_iterator, IteratorTag> iterator;
Expand All @@ -67,14 +70,14 @@ void test_any_of_async(ExPolicy p, IteratorTag)
iterator(std::begin(c)), iterator(std::end(c)),
[](std::size_t v) {
return v != 0;
});
},proj);
f.wait();

// verify values
bool expected =
std::any_of(std::begin(c), std::end(c),
[](std::size_t v) {
return v != 0;
[proj](std::size_t v) {
return proj(v) != 0;
});

HPX_TEST_EQ(expected, f.get());
Expand All @@ -84,22 +87,49 @@ void test_any_of_async(ExPolicy p, IteratorTag)
template <typename IteratorTag>
void test_any_of()
{
struct proj
{
//This projection should cause tests to fail if it is not applied
//because it causes predicate to evaluate the opposite
constexpr std::size_t operator()(std::size_t x)const
{
return !static_cast<bool>(x);
}
};
using namespace hpx::parallel;

test_any_of(execution::seq, IteratorTag());
test_any_of(execution::par, IteratorTag());
test_any_of(execution::par_unseq, IteratorTag());

test_any_of(execution::seq, IteratorTag(), proj());
test_any_of(execution::par, IteratorTag(), proj());
test_any_of(execution::par_unseq, IteratorTag(), proj());

test_any_of_async(execution::seq(execution::task), IteratorTag());
test_any_of_async(execution::par(execution::task), IteratorTag());

test_any_of_async(execution::seq(execution::task), IteratorTag(), proj());
test_any_of_async(execution::par(execution::task), IteratorTag(), proj());

#if defined(HPX_HAVE_GENERIC_EXECUTION_POLICY)
test_any_of(execution_policy(execution::seq), IteratorTag());
test_any_of(execution_policy(execution::par), IteratorTag());
test_any_of(execution_policy(execution::par_unseq), IteratorTag());

test_any_of(execution_policy(execution::seq(execution::task)), IteratorTag());
test_any_of(execution_policy(execution::par(execution::task)), IteratorTag());
test_any_of(execution_policy(execution::seq), IteratorTag(), proj());
test_any_of(execution_policy(execution::par), IteratorTag(), proj());
test_any_of(execution_policy(execution::par_unseq), IteratorTag(), proj());

test_any_of(execution_policy(execution::seq(execution::task)),
IteratorTag());
test_any_of(execution_policy(execution::par(execution::task)),
IteratorTag());

test_any_of(execution_policy(execution::seq(execution::task)),
IteratorTag(), proj());
test_any_of(execution_policy(execution::par(execution::task)),
IteratorTag()), proj();
#endif
}

Expand Down

0 comments on commit e2e9dba

Please sign in to comment.