Skip to content

Commit

Permalink
Adding overload for merge and inplace_merge to ranges namespace
Browse files Browse the repository at this point in the history
- flyby: make projection_identity conform to C++20
  • Loading branch information
hkaiser committed Sep 22, 2020
1 parent 599d88e commit 9a98613
Show file tree
Hide file tree
Showing 9 changed files with 764 additions and 110 deletions.
6 changes: 4 additions & 2 deletions docs/sphinx/api/public_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Functions
- :cpp:func:`hpx::generate`
- :cpp:func:`hpx::generate_n`
- :cpp:func:`hpx::includes`
- :cpp:func:`hpx::parallel::v1::inplace_merge`
- :cpp:func:`hpx::inplace_merge`
- :cpp:func:`hpx::is_heap`
- :cpp:func:`hpx::is_heap_until`
- :cpp:func:`hpx::parallel::v1::is_partitioned`
Expand All @@ -61,7 +61,7 @@ Functions
- :cpp:func:`hpx::parallel::v1::lexicographical_compare`
- :cpp:func:`hpx::make_heap`
- :cpp:func:`hpx::parallel::v1::max_element`
- :cpp:func:`hpx::parallel::v1::merge`
- :cpp:func:`hpx::merge`
- :cpp:func:`hpx::parallel::v1::min_element`
- :cpp:func:`hpx::parallel::v1::minmax_element`
- :cpp:func:`hpx::parallel::v1::mismatch`
Expand Down Expand Up @@ -118,9 +118,11 @@ Functions
- :cpp:func:`hpx::ranges::generate`
- :cpp:func:`hpx::ranges::generate_n`
- :cpp:func:`hpx::ranges::includes`
- :cpp:func:`hpx::ranges::inplace_merge`
- :cpp:func:`hpx::ranges::is_heap`
- :cpp:func:`hpx::ranges::is_heap_until`
- :cpp:func:`hpx::ranges::make_heap`
- :cpp:func:`hpx::ranges::merge`
- :cpp:func:`hpx::ranges::move`
- :cpp:func:`hpx::ranges::none_of`
- :cpp:func:`hpx::ranges::set_difference`
Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/manual/writing_single_node_hpx_applications.rst
Original file line number Diff line number Diff line change
Expand Up @@ -537,11 +537,11 @@ Parallel algorithms
* Description
* In header
* Algorithm page at cppreference.com
* * :cpp:func:`hpx::parallel::v1::merge`
* * :cpp:func:`hpx::merge`
* Merges two sorted ranges.
* ``<hpx/algorithm.hpp>``
* :cppreference-algorithm:`merge`
* * :cpp:func:`hpx::parallel::v1::inplace_merge`
* * :cpp:func:`hpx::inplace_merge`
* Merges two ordered ranges in-place.
* ``<hpx/algorithm.hpp>``
* :cppreference-algorithm:`inplace_merge`
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,26 @@

#include <hpx/config.hpp>

#include <type_traits>
#include <utility>

namespace hpx { namespace parallel { namespace util {
///////////////////////////////////////////////////////////////////////////
struct projection_identity
{
using is_transparent = std::true_type;

template <typename T>
HPX_HOST_DEVICE HPX_FORCEINLINE constexpr T&& operator()(T&& val) const
HPX_HOST_DEVICE HPX_FORCEINLINE constexpr T&& operator()(
T&& val) const noexcept
{
return std::forward<T>(val);
}
};
}}} // namespace hpx::parallel::util

namespace hpx {

// C++20 introduces std::identity
using identity = hpx::parallel::util::projection_identity;
} // namespace hpx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ double run_inplace_merge_benchmark_hpx(int test_count, ExPolicy policy,
hpx::copy(hpx::execution::par, org_first, org_last, first);

std::uint64_t elapsed = hpx::util::high_resolution_clock::now();
hpx::parallel::inplace_merge(policy, first, middle, last);
hpx::inplace_merge(policy, first, middle, last);
time += hpx::util::high_resolution_clock::now() - elapsed;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ double run_merge_benchmark_hpx(int test_count, ExPolicy policy, FwdIter1 first1,

for (int i = 0; i < test_count; ++i)
{
hpx::parallel::merge(policy, first1, last1, first2, last2, dest);
hpx::merge(policy, first1, last1, first2, last2, dest);
}

time = hpx::util::high_resolution_clock::now() - time;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void test_merge_stable(ExPolicy policy, DataType, int rand_base)
std::sort(std::begin(src1), std::end(src1));
std::sort(std::begin(src2), std::end(src2));

hpx::parallel::merge(
hpx::ranges::merge(
policy, std::begin(src1), std::end(src1), std::begin(src2),
std::end(src2), std::begin(dest),
[](DataType const& a, DataType const& b) -> bool { return a < b; },
Expand Down Expand Up @@ -127,7 +127,7 @@ int hpx_main(int argc, char** argv)

// I expect a stable merge to order {3, 'a'} and {3, 'b'} before {3, 'c'}
// because they come from the first sequence
hpx::parallel::merge(hpx::execution::par, a1.begin(), a1.end(), a2.begin(),
hpx::ranges::merge(hpx::execution::par, a1.begin(), a1.end(), a2.begin(),
a2.end(), result.begin(), [](ElemType const& a, ElemType const& b) {
return std::get<0>(a) < std::get<0>(b);
});
Expand All @@ -139,7 +139,7 @@ int hpx_main(int argc, char** argv)
HPX_TEST(result == solution);

// Expect {3, 'c'}, {3, 'a'}, {3, 'b'} in order.
hpx::parallel::merge(hpx::execution::par, a2.begin(), a2.end(), a1.begin(),
hpx::ranges::merge(hpx::execution::par, a2.begin(), a2.end(), a1.begin(),
a1.end(), result.begin(), [](ElemType const& a, ElemType const& b) {
return std::get<0>(a) < std::get<0>(b);
});
Expand All @@ -150,7 +150,7 @@ int hpx_main(int argc, char** argv)

HPX_TEST(result == solution);

// Do moduler operation for avoiding overflow in ramdom_fill. (#2954)
// Do modulus operation for avoiding overflow in ramdom_fill. (#2954)
std::uniform_int_distribution<> dis(0, 9999);
int rand_base = dis(_rand);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct user_defined_type
user_defined_type() = default;
user_defined_type(int rand_no)
: val(rand_no)
, name(name_list[std::rand() % name_list.size()])
, name(name_list[_gen() % name_list.size()])
{
}

Expand Down Expand Up @@ -78,7 +78,7 @@ const std::vector<std::string> user_defined_type::name_list{
struct random_fill
{
random_fill(int rand_base, int range)
: gen(std::rand())
: gen(_gen())
, dist(rand_base - range / 2, rand_base + range / 2)
{
}
Expand Down Expand Up @@ -166,9 +166,7 @@ template <typename ExPolicy, typename IteratorTag, typename DataType>
void test_inplace_merge_stable(
ExPolicy&& policy, IteratorTag, DataType, int rand_base)
{
#if defined(HPX_HAVE_STABLE_INPLACE_MERGE)
static_assert(
hpx::is_execution_policy<ExPolicy>::value,
static_assert(hpx::is_execution_policy<ExPolicy>::value,
"hpx::is_execution_policy<ExPolicy>::value");

typedef typename std::pair<DataType, int> ElemType;
Expand All @@ -185,16 +183,16 @@ void test_inplace_merge_stable(
int no = 0;
auto rf = random_fill(rand_base, 6);
std::generate(res_first, res_middle, [&no, &rf]() -> std::pair<int, int> {
return { rf(), no++ };
});
return {rf(), no++};
});
rf = random_fill(rand_base, 8);
std::generate(res_middle, res_last, [&no, &rf]() -> std::pair<int, int> {
return { rf(), no++ };
});
return {rf(), no++};
});
std::sort(res_first, res_middle);
std::sort(res_middle, res_last);

hpx::inplace_merge(
hpx::ranges::inplace_merge(
policy, iterator(res_first), iterator(res_middle), iterator(res_last),
[](DataType const& a, DataType const& b) -> bool { return a < b; },
[](ElemType const& elem) -> DataType const& {
Expand All @@ -218,7 +216,6 @@ void test_inplace_merge_stable(

HPX_TEST(test_is_meaningful);
HPX_TEST(stable);
#endif
}

///////////////////////////////////////////////////////////////////////////////
Expand All @@ -241,28 +238,45 @@ void test_inplace_merge()
test_inplace_merge<user_defined_type>();
}

template <typename IteratorTag, typename DataType>
void test_inplace_merge_stable()
{
////////// Test cases for checking whether the algorithm is stable.
using namespace hpx::execution;

////////// Test cases for checking whether the algorithm is stable.
test_inplace_merge_stable(seq, IteratorTag(), int(), rand_base);
test_inplace_merge_stable(par, IteratorTag(), int(), rand_base);
test_inplace_merge_stable(par_unseq, IteratorTag(), int(), rand_base);
test_inplace_merge_stable(
seq, IteratorTag(), user_defined_type(), rand_base);
test_inplace_merge_stable(
par, IteratorTag(), user_defined_type(), rand_base);
test_inplace_merge_stable(
par_unseq, IteratorTag(), user_defined_type(), rand_base);
int rand_base = _gen();

////////// Test cases for checking whether the algorithm is stable.
test_inplace_merge_stable(seq, IteratorTag(), int(), rand_base);
test_inplace_merge_stable(par, IteratorTag(), int(), rand_base);
test_inplace_merge_stable(par_unseq, IteratorTag(), int(), rand_base);
test_inplace_merge_stable(
seq, IteratorTag(), user_defined_type(), rand_base);
test_inplace_merge_stable(
par, IteratorTag(), user_defined_type(), rand_base);
test_inplace_merge_stable(
par_unseq, IteratorTag(), user_defined_type(), rand_base);
}

void test_inplace_merge_stable()
{
test_inplace_merge_stable<std::random_access_iterator_tag, int>();
test_inplace_merge_stable<std::random_access_iterator_tag,
user_defined_type>();
}

int hpx_main(hpx::program_options::variables_map& vm)
{
unsigned int seed = (unsigned int) std::time(nullptr);
if (vm.count("seed"))
{
seed = vm["seed"].as<unsigned int>();

_gen.seed(seed);
}
std::cout << "using seed: " << seed << std::endl;
std::srand(seed);

test_inplace_merge();
test_inplace_merge_stable();

return hpx::finalize();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,37 @@ struct random_fill
};

////////////////////////////////////////////////////////////////////////////
template <typename DataType>
void test_merge(DataType)
{
std::size_t const size1 = 300007, size2 = 123456;
std::vector<DataType> src1(size1), src2(size2), dest_res(size1 + size2),
dest_sol(size1 + size2);

std::generate(std::begin(src1), std::end(src1), random_fill(0, 6));
std::generate(std::begin(src2), std::end(src2), random_fill(0, 8));
std::sort(std::begin(src1), std::end(src1));
std::sort(std::begin(src2), std::end(src2));

auto result = hpx::ranges::merge(src1, src2, std::begin(dest_res));
auto solution = std::merge(std::begin(src1), std::end(src1),
std::begin(src2), std::end(src2), std::begin(dest_sol));

HPX_TEST(result.in1 == std::end(src1));
HPX_TEST(result.in2 == std::end(src2));

bool equality = test::equal(
std::begin(dest_res), result.out, std::begin(dest_sol), solution);

HPX_TEST(equality);
}

template <typename ExPolicy, typename DataType>
void test_merge(ExPolicy policy, DataType)
void test_merge(ExPolicy&& policy, DataType)
{
static_assert(hpx::is_execution_policy<ExPolicy>::value,
"hpx::is_execution_policy<ExPolicy>::value");

using hpx::get;

std::size_t const size1 = 300007, size2 = 123456;
std::vector<DataType> src1(size1), src2(size2), dest_res(size1 + size2),
dest_sol(size1 + size2);
Expand All @@ -110,28 +133,25 @@ void test_merge(ExPolicy policy, DataType)
std::sort(std::begin(src1), std::end(src1));
std::sort(std::begin(src2), std::end(src2));

auto result =
hpx::parallel::merge(policy, src1, src2, std::begin(dest_res));
auto result = hpx::ranges::merge(policy, src1, src2, std::begin(dest_res));
auto solution = std::merge(std::begin(src1), std::end(src1),
std::begin(src2), std::end(src2), std::begin(dest_sol));

HPX_TEST(get<0>(result) == std::end(src1));
HPX_TEST(get<1>(result) == std::end(src2));
HPX_TEST(result.in1 == std::end(src1));
HPX_TEST(result.in2 == std::end(src2));

bool equality = test::equal(
std::begin(dest_res), get<2>(result), std::begin(dest_sol), solution);
std::begin(dest_res), result.out, std::begin(dest_sol), solution);

HPX_TEST(equality);
}

template <typename ExPolicy, typename DataType>
void test_merge_async(ExPolicy policy, DataType)
void test_merge_async(ExPolicy&& policy, DataType)
{
static_assert(hpx::is_execution_policy<ExPolicy>::value,
"hpx::is_execution_policy<ExPolicy>::value");

using hpx::get;

std::size_t const size1 = 300007, size2 = 123456;
std::vector<DataType> src1(size1), src2(size2), dest_res(size1 + size2),
dest_sol(size1 + size2);
Expand All @@ -141,16 +161,16 @@ void test_merge_async(ExPolicy policy, DataType)
std::sort(std::begin(src1), std::end(src1));
std::sort(std::begin(src2), std::end(src2));

auto f = hpx::parallel::merge(policy, src1, src2, std::begin(dest_res));
auto f = hpx::ranges::merge(policy, src1, src2, std::begin(dest_res));
auto result = f.get();
auto solution = std::merge(std::begin(src1), std::end(src1),
std::begin(src2), std::end(src2), std::begin(dest_sol));

HPX_TEST(get<0>(result) == std::end(src1));
HPX_TEST(get<1>(result) == std::end(src2));
HPX_TEST(result.in1 == std::end(src1));
HPX_TEST(result.in2 == std::end(src2));

bool equality = test::equal(
std::begin(dest_res), get<2>(result), std::begin(dest_sol), solution);
std::begin(dest_res), result.out, std::begin(dest_sol), solution);

HPX_TEST(equality);
}
Expand All @@ -161,6 +181,8 @@ void test_merge()
{
using namespace hpx::execution;

test_merge(DataType());

test_merge(seq, DataType());
test_merge(par, DataType());
test_merge(par_unseq, DataType());
Expand Down Expand Up @@ -222,8 +244,7 @@ void test_merge_etc(IteratorTag, DataType, int rand_base)
template <typename ExPolicy, typename IteratorTag, typename DataType>
void test_merge_etc(ExPolicy&& policy, IteratorTag, DataType, int rand_base)
{
static_assert(
hpx::is_execution_policy<ExPolicy>::value,
static_assert(hpx::is_execution_policy<ExPolicy>::value,
"hpx::is_execution_policy<ExPolicy>::value");

typedef typename std::vector<DataType>::iterator base_iterator;
Expand Down Expand Up @@ -291,7 +312,7 @@ void test_merge_stable(IteratorTag, DataType, int rand_base)
std::sort(std::begin(src1), std::end(src1));
std::sort(std::begin(src2), std::end(src2));

hpx::merge(
hpx::ranges::merge(
iterator(std::begin(src1)), iterator(std::end(src1)),
iterator(std::begin(src2)), iterator(std::end(src2)),
iterator(std::begin(dest)),
Expand Down Expand Up @@ -326,8 +347,7 @@ void test_merge_stable(IteratorTag, DataType, int rand_base)
template <typename ExPolicy, typename IteratorTag, typename DataType>
void test_merge_stable(ExPolicy&& policy, IteratorTag, DataType, int rand_base)
{
static_assert(
hpx::is_execution_policy<ExPolicy>::value,
static_assert(hpx::is_execution_policy<ExPolicy>::value,
"hpx::is_execution_policy<ExPolicy>::value");

typedef typename std::pair<DataType, int> ElemType;
Expand All @@ -351,7 +371,7 @@ void test_merge_stable(ExPolicy&& policy, IteratorTag, DataType, int rand_base)
std::sort(std::begin(src1), std::end(src1));
std::sort(std::begin(src2), std::end(src2));

hpx::merge(
hpx::ranges::merge(
policy, iterator(std::begin(src1)), iterator(std::end(src1)),
iterator(std::begin(src2)), iterator(std::end(src2)),
iterator(std::begin(dest)),
Expand Down

0 comments on commit 9a98613

Please sign in to comment.