Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions include/oneapi/dpl/pstl/algorithm_ranges_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,35 @@ __pattern_reverse_copy(__serial_tag</*IsVector*/ std::false_type>, _ExecutionPol
std::ranges::reverse_copy(std::forward<_InRange>(__in_r), std::ranges::begin(__out_r));
}

//---------------------------------------------------------------------------------------------------------------------
// __pattern_replace_copy_if
//---------------------------------------------------------------------------------------------------------------------

template <typename _Tag, typename _ExecutionPolicy, typename _InRange, typename _OutRange, typename _Pred, typename _T,
typename _Proj>
void
__pattern_replace_copy_if(_Tag __tag, _ExecutionPolicy&& __exec, _InRange&& __r, _OutRange&& __out_r, _Pred __pred,
const _T& __new_value, _Proj __proj)
{
static_assert(__is_parallel_tag_v<_Tag> || typename _Tag::__is_vector{});
assert(std::ranges::size(__r) <= std::ranges::size(__out_r));

oneapi::dpl::__internal::__replace_copy_functor<_T, oneapi::dpl::__internal::__unary_op<_Pred, _Proj>>
__f{__new_value, {__pred, __proj}};

oneapi::dpl::__internal::__pattern_walk2(__tag, std::forward<_ExecutionPolicy>(__exec), std::ranges::begin(__r),
std::ranges::begin(__r) + std::ranges::size(__r),
std::ranges::begin(__out_r), __f);
}

template <typename _ExecutionPolicy, typename _InRange, typename _OutRange, typename _Pred, typename _T, typename _Proj>
void
__pattern_replace_copy_if(__serial_tag</*IsVector*/ std::false_type>, _ExecutionPolicy&&, _InRange&& __r,
_OutRange&& __out_r, _Pred __pred, const _T& __new_value, _Proj __proj)
{
std::ranges::replace_copy_if(std::forward<_InRange>(__r), std::ranges::begin(__out_r), __pred, __new_value, __proj);
}

//---------------------------------------------------------------------------------------------------------------------
// __pattern_move
//---------------------------------------------------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions include/oneapi/dpl/pstl/glue_algorithm_ranges_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ struct __move_fn;
struct __swap_ranges_fn;
struct __replace_if_fn;
struct __replace_fn;
struct __replace_copy_if_fn;
struct __replace_copy_fn;
struct __reverse_fn;
struct __reverse_copy_fn;
struct __mismatch_fn;
Expand Down
57 changes: 57 additions & 0 deletions include/oneapi/dpl/pstl/glue_algorithm_ranges_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,63 @@ struct __internal::__replace_fn
}; //__replace_fn
inline constexpr __internal::__replace_fn replace;

struct __internal::__replace_copy_if_fn
{
template <typename _ExecutionPolicy, std::ranges::random_access_range _InRange,
std::ranges::random_access_range _OutRange, class _T = std::ranges::range_value_t<_OutRange>,
typename _Proj = std::identity,
std::indirect_unary_predicate<std::projected<std::ranges::iterator_t<_InRange>, _Proj>> _Pred>
requires oneapi::dpl::is_execution_policy_v<std::remove_cvref_t<_ExecutionPolicy>>
&& std::ranges::sized_range<_InRange> && std::ranges::sized_range<_OutRange>
&& std::indirectly_copyable<std::ranges::iterator_t<_InRange>, std::ranges::iterator_t<_OutRange>>
&& std::indirectly_writable<std::ranges::iterator_t<_OutRange>, const _T&>

std::ranges::replace_copy_if_result<std::ranges::borrowed_iterator_t<_InRange>,
std::ranges::borrowed_iterator_t<_OutRange>>
operator()(_ExecutionPolicy&& __exec, _InRange&& __in_r, _OutRange&& __out_r, _Pred __pred, const _T& __new_value,
_Proj __proj = {}) const
{
const auto __dispatch_tag = oneapi::dpl::__ranges::__select_backend(__exec);
const oneapi::dpl::__ranges::__common_size_t<_InRange, _OutRange> __size =
oneapi::dpl::__ranges::__min_size_calc{}(__in_r, __out_r);

oneapi::dpl::__internal::__ranges::__pattern_replace_copy_if(
__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), std::ranges::take_view(__in_r, __size),
std::ranges::take_view(__out_r, __size), __pred,
oneapi::dpl::__internal::__ref_or_copy<_ExecutionPolicy, const _T>{__new_value}, __proj);

return {std::ranges::begin(__in_r) + __size, std::ranges::begin(__out_r) + __size};
}
}; //__replace_copy_if_fn
inline constexpr __internal::__replace_copy_if_fn replace_copy_if;

struct __internal::__replace_copy_fn
{
template <typename _ExecutionPolicy, std::ranges::random_access_range _InRange,
std::ranges::random_access_range _OutRange, typename _Proj = std::identity,
typename _T1 = oneapi::dpl::projected_value_t<std::ranges::iterator_t<_InRange>, _Proj>,
typename _T2 = std::ranges::range_value_t<_OutRange>>
requires oneapi::dpl::is_execution_policy_v<std::remove_cvref_t<_ExecutionPolicy>>
&& std::ranges::sized_range<_InRange> && std::ranges::sized_range<_OutRange>
&& std::indirectly_copyable<std::ranges::iterator_t<_InRange>, std::ranges::iterator_t<_OutRange>>
&& std::indirect_binary_predicate<std::ranges::equal_to,
std::projected<std::ranges::iterator_t<_InRange>, _Proj>, const _T1*>
&& std::indirectly_writable<std::ranges::iterator_t<_OutRange>, const _T2&>

std::ranges::replace_copy_result<std::ranges::borrowed_iterator_t<_InRange>,
std::ranges::borrowed_iterator_t<_OutRange>>
operator()(_ExecutionPolicy&& __exec, _InRange&& __in_r, _OutRange&& __out_r, const _T1& __old_value,
const _T2& __new_value, _Proj __proj = {}) const
{
return oneapi::dpl::ranges::replace_copy_if(
std::forward<_ExecutionPolicy>(__exec), std::forward<_InRange>(__in_r), std::forward<_OutRange>(__out_r),
oneapi::dpl::__internal::__equal_value<oneapi::dpl::__internal::__ref_or_copy<_ExecutionPolicy, const _T1>>(
__old_value),
__new_value, __proj);
}
}; //__replace_copy_fn
inline constexpr __internal::__replace_copy_fn replace_copy;

// [alg.reverse]

struct __internal::__reverse_fn
Expand Down
18 changes: 18 additions & 0 deletions include/oneapi/dpl/pstl/hetero/algorithm_ranges_impl_hetero.h
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,24 @@ __pattern_reverse_copy(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _In
.__checked_deferrable_wait();
}

//------------------------------------------------------------------------
// replace_copy
//------------------------------------------------------------------------
template <typename _BackendTag, typename _ExecutionPolicy, typename _InRange, typename _OutRange, typename _Pred,
typename _T, typename _Proj>
void
__pattern_replace_copy_if(__hetero_tag<_BackendTag> __tag, _ExecutionPolicy&& __exec, _InRange&& __r,
_OutRange&& __out_r, _Pred __pred, const _T& __new_value, _Proj __proj)
{
assert(std::ranges::size(__r) <= std::ranges::size(__out_r));
oneapi::dpl::__internal::__replace_copy_functor<const _T, oneapi::dpl::__internal::__unary_op<_Pred, _Proj>>
__f{__new_value, {__pred, __proj}};

oneapi::dpl::__internal::__ranges::__pattern_walk_n(__tag, std::forward<_ExecutionPolicy>(__exec), __f,
oneapi::dpl::__ranges::views::all_read(std::forward<_InRange>(__r)),
oneapi::dpl::__ranges::views::all_write(std::forward<_OutRange>(__out_r)));
}

//------------------------------------------------------------------------
// move
//------------------------------------------------------------------------
Expand Down
9 changes: 6 additions & 3 deletions include/oneapi/dpl/pstl/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class __set_value
};

//TODO: to do the same fix for output type (by re-using __transform_functor if applicable) for the other functor below:
// __transform_if_unary_functor, __transform_if_binary_functor, __replace_functor, __replace_copy_functor
// __transform_if_unary_functor, __transform_if_binary_functor, __replace_functor
template <typename _F, typename _RevTag = std::false_type>
class __transform_functor
{
Expand Down Expand Up @@ -445,9 +445,12 @@ class __replace_copy_functor

template <typename _InputType, typename _OutputType>
void
operator()(const _InputType& __x, _OutputType& __y) const
operator()(_InputType&& __x, _OutputType&& __y) const
{
__y = _M_pred(__x) ? _M_value : __x;
if (_M_pred(__x))
std::forward<_OutputType>(__y) = _M_value;
else
std::forward<_OutputType>(__y) = std::forward<_InputType>(__x);
Comment thread
dmitriy-sobolev marked this conversation as resolved.
}
};

Expand Down
42 changes: 42 additions & 0 deletions test/parallel_api/ranges/std_ranges_replace_copy.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// -*- C++ -*-
//===------------------------------------------------------===//
//
// Copyright (C) UXL Foundation Contributors
//
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===------------------------------------------------------===//

#include "std_ranges_test.h"

std::int32_t
main()
{
#if _ENABLE_STD_RANGES_TESTING
using namespace test_std_ranges;
namespace dpl_ranges = oneapi::dpl::ranges;

//A checker below modifies a return type; a range based version with policy has another return type.
auto replace_copy_checker = [](std::ranges::random_access_range auto&& r_in,
std::ranges::random_access_range auto&& r_out, auto&&... args)
{
using Size = std::common_type_t<std::ranges::range_size_t<decltype(r_in)>,
std::ranges::range_size_t<decltype(r_out)>>;
Size size = std::ranges::min(std::ranges::size(r_in), std::ranges::size(r_out));

std::ranges::replace_copy(std::ranges::take_view(r_in, size), std::ranges::begin(r_out),
std::forward<decltype(args)>(args)...);

using ret_type = std::ranges::replace_copy_result<std::ranges::borrowed_iterator_t<decltype(r_in)>,
std::ranges::borrowed_iterator_t<decltype(r_out)>>;
return ret_type{std::ranges::begin(r_in) + size, std::ranges::begin(r_out) + size};
};

test_range_algo<0, int, data_in_out_lim>{big_sz}(dpl_ranges::replace_copy, replace_copy_checker, 273, -13);
test_range_algo<1, int, data_in_out_lim>{}(dpl_ranges::replace_copy, replace_copy_checker, 91, -189, proj);
test_range_algo<2, P2, data_in_out_lim>{}(dpl_ranges::replace_copy, replace_copy_checker, 5, -43, &P2::x);
test_range_algo<3, P2, data_in_out_lim>{}(dpl_ranges::replace_copy, replace_copy_checker, 117, -7, &P2::proj);
#endif //_ENABLE_STD_RANGES_TESTING

return TestUtils::done(_ENABLE_STD_RANGES_TESTING);
}
42 changes: 42 additions & 0 deletions test/parallel_api/ranges/std_ranges_replace_copy_if.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// -*- C++ -*-
//===------------------------------------------------------===//
//
// Copyright (C) UXL Foundation Contributors
//
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===------------------------------------------------------===//

#include "std_ranges_test.h"

std::int32_t
main()
{
#if _ENABLE_STD_RANGES_TESTING
using namespace test_std_ranges;
namespace dpl_ranges = oneapi::dpl::ranges;

//A checker below modifies a return type; a range based version with policy has another return type.
auto replace_copy_if_checker = [](std::ranges::random_access_range auto&& r_in,
std::ranges::random_access_range auto&& r_out, auto&&... args)
{
using Size = std::common_type_t<std::ranges::range_size_t<decltype(r_in)>,
std::ranges::range_size_t<decltype(r_out)>>;
Size size = std::ranges::min(std::ranges::size(r_in), std::ranges::size(r_out));

std::ranges::replace_copy_if(std::ranges::take_view(r_in, size), std::ranges::begin(r_out),
std::forward<decltype(args)>(args)...);

using ret_type = std::ranges::replace_copy_if_result<std::ranges::borrowed_iterator_t<decltype(r_in)>,
std::ranges::borrowed_iterator_t<decltype(r_out)>>;
return ret_type{std::ranges::begin(r_in) + size, std::ranges::begin(r_out) + size};
};

test_range_algo<0, int, data_in_out_lim>{big_sz}(dpl_ranges::replace_copy_if, replace_copy_if_checker, pred, -29);
test_range_algo<1, int, data_in_out_lim>{}(dpl_ranges::replace_copy_if, replace_copy_if_checker, pred1, -277, proj);
test_range_algo<2, P2, data_in_out_lim>{}(dpl_ranges::replace_copy_if, replace_copy_if_checker, pred2, -43, &P2::x);
test_range_algo<3, P2, data_in_out_lim>{}(dpl_ranges::replace_copy_if, replace_copy_if_checker, pred3, -817, &P2::proj);
Comment on lines +35 to +38
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A case with different types of R and OutR is not covered. It's not a blocker, since it is not done in other similar tests nor in the iterator-based tests. We can leave a TODO and create an issue.

#endif //_ENABLE_STD_RANGES_TESTING

return TestUtils::done(_ENABLE_STD_RANGES_TESTING);
}
Loading