Skip to content

Commit

Permalink
Fixing copy, copy_if, and move
Browse files Browse the repository at this point in the history
  • Loading branch information
hkaiser committed Jun 23, 2017
1 parent dc23b2e commit 134e952
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 111 deletions.
122 changes: 61 additions & 61 deletions hpx/parallel/algorithms/copy.hpp

Large diffs are not rendered by default.

48 changes: 33 additions & 15 deletions hpx/parallel/algorithms/detail/transfer.hpp
Expand Up @@ -27,31 +27,40 @@ namespace hpx { namespace parallel { inline namespace v1
namespace detail
{
// parallel version
template <typename Algo, typename ExPolicy, typename InIter, typename OutIter>
template <typename Algo, typename ExPolicy, typename FwdIter,
typename OutIter>
typename util::detail::algorithm_result<
ExPolicy, std::pair<InIter, OutIter>
ExPolicy, std::pair<FwdIter, OutIter>
>::type
transfer_(ExPolicy && policy, InIter first, InIter last, OutIter dest,
transfer_(ExPolicy && policy, FwdIter first, FwdIter last, OutIter dest,
std::false_type)
{
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
typedef std::integral_constant<bool,
parallel::execution::is_sequenced_execution_policy<
ExPolicy
>::value ||
!hpx::traits::is_forward_iterator<InIter>::value ||
!hpx::traits::is_forward_iterator<FwdIter>::value ||
!hpx::traits::is_forward_iterator<OutIter>::value
> is_seq;
#else
typedef parallel::execution::is_sequenced_execution_policy<
ExPolicy
> is_seq;
#endif

return Algo().call(
std::forward<ExPolicy>(policy), is_seq(),
first, last, dest);
}

// forward declare segmented version
template <typename Algo, typename ExPolicy, typename InIter, typename OutIter>
template <typename Algo, typename ExPolicy, typename FwdIter,
typename OutIter>
typename util::detail::algorithm_result<
ExPolicy, std::pair<InIter, OutIter>
ExPolicy, std::pair<FwdIter, OutIter>
>::type
transfer_(ExPolicy && policy, InIter first, InIter last, OutIter dest,
transfer_(ExPolicy && policy, FwdIter first, FwdIter last, OutIter dest,
std::true_type);

// Executes transfer algorithm on the elements in the range [first, last),
Expand All @@ -67,9 +76,9 @@ namespace hpx { namespace parallel { inline namespace v1
// It describes the manner in which the execution
// of the algorithm may be parallelized and the manner
// in which it executes the move assignments.
// \tparam InIter The type of the source iterators used (deduced).
// \tparam FwdIter The type of the source iterators used (deduced).
// This iterator type must meet the requirements of an
// input iterator.
// forward iterator.
// \tparam OutIter The type of the iterator representing the
// destination range (deduced).
// This iterator type must meet the requirements of an
Expand All @@ -93,25 +102,34 @@ namespace hpx { namespace parallel { inline namespace v1
// transfered.
//

template <typename Algo, typename ExPolicy, typename InIter, typename OutIter,
template <typename Algo, typename ExPolicy, typename FwdIter, typename OutIter,
HPX_CONCEPT_REQUIRES_(
hpx::parallel::execution::is_execution_policy<ExPolicy>::value &&
hpx::traits::is_iterator<InIter>::value &&
hpx::traits::is_iterator<FwdIter>::value &&
hpx::traits::is_iterator<OutIter>::value)>
typename util::detail::algorithm_result<
ExPolicy, hpx::util::tagged_pair<tag::in(InIter), tag::out(OutIter)>
ExPolicy, hpx::util::tagged_pair<tag::in(FwdIter), tag::out(OutIter)>
>::type
transfer(ExPolicy && policy, InIter first, InIter last, OutIter dest)
transfer(ExPolicy && policy, FwdIter first, FwdIter last, OutIter dest)
{
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
static_assert(
(hpx::traits::is_input_iterator<InIter>::value),
(hpx::traits::is_input_iterator<FwdIter>::value),
"Required at least input iterator.");
static_assert(
(hpx::traits::is_output_iterator<OutIter>::value ||
hpx::traits::is_forward_iterator<OutIter>::value),
"Requires at least output iterator.");
#else
static_assert(
(hpx::traits::is_forward_iterator<FwdIter>::value),
"Required at least forward iterator.");
static_assert(
(hpx::traits::is_forward_iterator<OutIter>::value),
"Requires at least forward iterator.");
#endif

typedef hpx::traits::is_segmented_iterator<InIter> is_segmented;
typedef hpx::traits::is_segmented_iterator<FwdIter> is_segmented;

return hpx::util::make_tagged_pair<tag::in, tag::out>(
transfer_<Algo>(
Expand Down
46 changes: 23 additions & 23 deletions hpx/parallel/algorithms/move.hpp
@@ -1,5 +1,5 @@
// Copyright (c) 2014 Grant Mercer
// Copyright (c) 2016 Hartmut Kaiser
// Copyright (c) 2016-2017 Hartmut Kaiser
//
// 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)
Expand Down Expand Up @@ -43,9 +43,9 @@ namespace hpx { namespace parallel { inline namespace v1
: move_pair::algorithm("move")
{}

template <typename ExPolicy, typename InIter, typename OutIter>
static std::pair<InIter, OutIter>
sequential(ExPolicy, InIter first, InIter last, OutIter dest)
template <typename ExPolicy, typename FwdIter, typename OutIter>
static std::pair<FwdIter, OutIter>
sequential(ExPolicy, FwdIter first, FwdIter last, OutIter dest)
{
return util::move(first, last, dest);
}
Expand Down Expand Up @@ -81,30 +81,30 @@ namespace hpx { namespace parallel { inline namespace v1
};

///////////////////////////////////////////////////////////////////////
template<typename InIter, typename OutIter, typename Enable = void>
template<typename FwdIter, typename OutIter, typename Enable = void>
struct move;

template <typename InIter, typename OutIter>
template <typename FwdIter, typename OutIter>
struct move<
InIter, OutIter,
FwdIter, OutIter,
typename std::enable_if<
iterators_are_segmented<InIter, OutIter>::value
iterators_are_segmented<FwdIter, OutIter>::value
>::type>
: public move_pair<std::pair<
typename hpx::traits::segmented_iterator_traits<InIter>
typename hpx::traits::segmented_iterator_traits<FwdIter>
::local_iterator,
typename hpx::traits::segmented_iterator_traits<OutIter>
::local_iterator
> >
{};

template<typename InIter, typename OutIter>
template<typename FwdIter, typename OutIter>
struct move<
InIter, OutIter,
FwdIter, OutIter,
typename std::enable_if<
iterators_are_not_segmented<InIter, OutIter>::value
iterators_are_not_segmented<FwdIter, OutIter>::value
>::type>
: public move_pair<std::pair<InIter, OutIter> >
: public move_pair<std::pair<FwdIter, OutIter> >
{};
/// \endcond
}
Expand All @@ -120,13 +120,13 @@ namespace hpx { namespace parallel { inline namespace v1
/// It describes the manner in which the execution
/// of the algorithm may be parallelized and the manner
/// in which it executes the move assignments.
/// \tparam InIter The type of the source iterators used (deduced).
/// \tparam FwdIter The type of the source iterators used (deduced).
/// This iterator type must meet the requirements of an
/// input iterator.
/// forward iterator.
/// \tparam OutIter The type of the iterator representing the
/// destination range (deduced).
/// This iterator type must meet the requirements of an
/// output iterator.
/// forward iterator.
///
/// \param policy The execution policy to use for the scheduling of
/// the iterations.
Expand All @@ -148,29 +148,29 @@ namespace hpx { namespace parallel { inline namespace v1
/// threads, and indeterminately sequenced within each thread.
///
/// \returns The \a move algorithm returns a
/// \a hpx::future<tagged_pair<tag::in(InIter), tag::out(OutIter)> >
/// \a hpx::future<tagged_pair<tag::in(FwdIter), tag::out(OutIter)> >
/// if the execution policy is of type
/// \a sequenced_task_policy or
/// \a parallel_task_policy and
/// returns \a tagged_pair<tag::in(InIter), tag::out(OutIter)>
/// returns \a tagged_pair<tag::in(FwdIter), tag::out(OutIter)>
/// otherwise.
/// The \a move algorithm returns the pair of the input iterator
/// \a last and the output iterator to the
/// element in the destination range, one past the last element
/// moved.
///
template <typename ExPolicy, typename InIter, typename OutIter,
template <typename ExPolicy, typename FwdIter, typename OutIter,
HPX_CONCEPT_REQUIRES_(
execution::is_execution_policy<ExPolicy>::value &&
hpx::traits::is_iterator<InIter>::value &&
hpx::traits::is_iterator<FwdIter>::value &&
hpx::traits::is_iterator<OutIter>::value)>
typename util::detail::algorithm_result<
ExPolicy, hpx::util::tagged_pair<tag::in(InIter), tag::out(OutIter)>
ExPolicy, hpx::util::tagged_pair<tag::in(FwdIter), tag::out(OutIter)>
>::type
move(ExPolicy && policy, InIter first, InIter last, OutIter dest)
move(ExPolicy && policy, FwdIter first, FwdIter last, OutIter dest)
{
return detail::transfer<
detail::move<InIter, OutIter>
detail::move<FwdIter, OutIter>
>(std::forward<ExPolicy>(policy), first, last, dest);
}
}}}
Expand Down
26 changes: 14 additions & 12 deletions hpx/parallel/segmented_algorithms/detail/transfer.hpp
@@ -1,4 +1,4 @@
// Copyright (c) 2007-2016 Hartmut Kaiser
// Copyright (c) 2007-2017 Hartmut Kaiser
//
// 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)
Expand Down Expand Up @@ -34,19 +34,19 @@ namespace hpx { namespace parallel { inline namespace v1
/// \cond NOINTERNAL

///////////////////////////////////////////////////////////////////////
template <typename InIter, typename OutIter>
template <typename FwdIter, typename OutIter>
struct iterators_are_segmented
: std::integral_constant<bool,
hpx::traits::segmented_iterator_traits<InIter>
hpx::traits::segmented_iterator_traits<FwdIter>
::is_segmented_iterator::value &&
hpx::traits::segmented_iterator_traits<OutIter>
::is_segmented_iterator::value>
{};

template <typename InIter, typename OutIter>
template <typename FwdIter, typename OutIter>
struct iterators_are_not_segmented
: std::integral_constant<bool,
!hpx::traits::segmented_iterator_traits<InIter>
!hpx::traits::segmented_iterator_traits<FwdIter>
::is_segmented_iterator::value &&
!hpx::traits::segmented_iterator_traits<OutIter>
::is_segmented_iterator::value>
Expand Down Expand Up @@ -259,17 +259,18 @@ namespace hpx { namespace parallel { inline namespace v1

///////////////////////////////////////////////////////////////////////
// segmented implementation
template <typename Algo, typename ExPolicy, typename InIter, typename OutIter>
template <typename Algo, typename ExPolicy, typename FwdIter,
typename OutIter>
typename util::detail::algorithm_result<
ExPolicy, std::pair<InIter, OutIter>
ExPolicy, std::pair<FwdIter, OutIter>
>::type
transfer_(ExPolicy&& policy, InIter first, InIter last, OutIter dest,
transfer_(ExPolicy&& policy, FwdIter first, FwdIter last, OutIter dest,
std::true_type)
{
if (first == last)
{
return util::detail::algorithm_result<
ExPolicy, std::pair<InIter, OutIter>
ExPolicy, std::pair<FwdIter, OutIter>
>::get(std::make_pair(last, dest));
}

Expand All @@ -282,11 +283,12 @@ namespace hpx { namespace parallel { inline namespace v1
}

// forward declare the non-segmented version of this algorithm
template <typename Algo, typename ExPolicy, typename InIter, typename OutIter>
template <typename Algo, typename ExPolicy, typename FwdIter,
typename OutIter>
typename util::detail::algorithm_result<
ExPolicy, std::pair<InIter, OutIter>
ExPolicy, std::pair<FwdIter, OutIter>
>::type
transfer_(ExPolicy&& policy, InIter first, InIter last, OutIter dest,
transfer_(ExPolicy&& policy, FwdIter first, FwdIter last, OutIter dest,
std::false_type);

/// \endcond
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/parallel/algorithms/copy.cpp
Expand Up @@ -71,6 +71,7 @@ void test_copy_async(ExPolicy p, IteratorTag)
HPX_TEST_EQ(count, d.size());
}

#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
template <typename ExPolicy, typename IteratorTag>
void test_copy_outiter(ExPolicy policy, IteratorTag)
{
Expand Down Expand Up @@ -122,6 +123,7 @@ void test_copy_outiter_async(ExPolicy p, IteratorTag)
}));
HPX_TEST_EQ(count, d.size());
}
#endif

template <typename IteratorTag>
void test_copy()
Expand All @@ -143,6 +145,7 @@ void test_copy()
test_copy(execution_policy(execution::par(execution::task)), IteratorTag());
#endif

#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
//assure output iterator will work
test_copy_outiter(execution::seq, IteratorTag());
test_copy_outiter(execution::par, IteratorTag());
Expand All @@ -159,13 +162,16 @@ void test_copy()
test_copy_outiter(execution_policy(execution::seq(execution::task)), IteratorTag());
test_copy_outiter(execution_policy(execution::par(execution::task)), IteratorTag());
#endif
#endif
}

void copy_test()
{
test_copy<std::random_access_iterator_tag>();
test_copy<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy<std::input_iterator_tag>();
#endif
}

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -270,7 +276,9 @@ void copy_exception_test()
{
test_copy_exception<std::random_access_iterator_tag>();
test_copy_exception<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy_exception<std::input_iterator_tag>();
#endif
}

//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -373,7 +381,9 @@ void copy_bad_alloc_test()
{
test_copy_bad_alloc<std::random_access_iterator_tag>();
test_copy_bad_alloc<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy_bad_alloc<std::input_iterator_tag>();
#endif
}

int hpx_main(boost::program_options::variables_map& vm)
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/parallel/algorithms/copyif_bad_alloc.cpp
Expand Up @@ -119,7 +119,9 @@ void copy_if_bad_alloc_test()
{
test_copy_if_bad_alloc<std::random_access_iterator_tag>();
test_copy_if_bad_alloc<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy_if_bad_alloc<std::input_iterator_tag>();
#endif
}

int hpx_main(boost::program_options::variables_map& vm)
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/parallel/algorithms/copyif_exception.cpp
Expand Up @@ -120,7 +120,9 @@ void copy_if_exception_test()
{
test_copy_if_exception<std::random_access_iterator_tag>();
test_copy_if_exception<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy_if_exception<std::input_iterator_tag>();
#endif
}

int hpx_main(boost::program_options::variables_map& vm)
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/parallel/algorithms/copyn.cpp
Expand Up @@ -169,7 +169,9 @@ void n_copy_test()
{
test_copy_n<std::random_access_iterator_tag>();
test_copy_n<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy_n<std::input_iterator_tag>();
#endif
}

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -279,7 +281,9 @@ void copy_n_exception_test()
{
test_copy_n_exception<std::random_access_iterator_tag>();
test_copy_n_exception<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy_n_exception<std::input_iterator_tag>();
#endif
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -388,7 +392,9 @@ void copy_n_bad_alloc_test()
{
test_copy_n_bad_alloc<std::random_access_iterator_tag>();
test_copy_n_bad_alloc<std::forward_iterator_tag>();
#if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
test_copy_n_bad_alloc<std::input_iterator_tag>();
#endif
}

int hpx_main(boost::program_options::variables_map& vm)
Expand Down

0 comments on commit 134e952

Please sign in to comment.