Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
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 @@ -41,6 +41,8 @@ struct __none_of_fn;
struct __adjacent_find_fn;
struct __search_fn;
struct __search_n_fn;
struct __contains_fn;
struct __contains_subrange_fn;
struct __count_if_fn;
struct __count_fn;
struct __equal_fn;
Expand Down
39 changes: 39 additions & 0 deletions include/oneapi/dpl/pstl/glue_algorithm_ranges_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,45 @@ struct __internal::__search_n_fn
}; //__search_n_fn
inline constexpr __internal::__search_n_fn search_n;

// [alg.contains]

struct __internal::__contains_fn
{
template <typename _ExecutionPolicy, std::ranges::random_access_range _R, typename _Proj = std::identity,
typename _T = oneapi::dpl::projected_value_t<std::ranges::iterator_t<_R>, _Proj>>
requires oneapi::dpl::is_execution_policy_v<std::remove_cvref_t<_ExecutionPolicy>> &&
std::ranges::sized_range<_R> &&
std::indirect_binary_predicate<std::ranges::equal_to,
std::projected<std::ranges::iterator_t<_R>, _Proj>, const _T*>
bool
operator()(_ExecutionPolicy&& __exec, _R&& __r, const _T& __value, _Proj __proj = {}) const
{
// To ensure no dangling iterator is returned, __r may not be forwarded
return oneapi::dpl::ranges::find(std::forward<_ExecutionPolicy>(__exec), __r, __value, __proj)
!= std::ranges::end(__r);
}
};
inline constexpr __internal::__contains_fn contains;

struct __internal::__contains_subrange_fn
{
template <typename _ExecutionPolicy, std::ranges::random_access_range _R1, std::ranges::random_access_range _R2,
typename _Pred = std::ranges::equal_to, typename _Proj1 = std::identity, typename _Proj2 = std::identity>
requires oneapi::dpl::is_execution_policy_v<std::remove_cvref_t<_ExecutionPolicy>> &&
std::ranges::sized_range<_R1> && std::ranges::sized_range<_R2> &&
std::indirectly_comparable<std::ranges::iterator_t<_R1>, std::ranges::iterator_t<_R2>,
_Pred, _Proj1, _Proj2>
bool
operator()(_ExecutionPolicy&& __exec, _R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const
{
// To ensure no dangling subrange is returned, __r1 may not be forwarded
return __r2.size() == 0 || !(oneapi::dpl::ranges::search(std::forward<_ExecutionPolicy>(__exec), __r1, __r2,
Comment thread
akukanov marked this conversation as resolved.
Outdated
__pred, __proj1, __proj2).empty());
}
};
inline constexpr __internal::__contains_subrange_fn contains_subrange;

// [alg.count]

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

#include "std_ranges_test.h"

#if _ENABLE_STD_RANGES_TESTING
#if __cpp_lib_ranges_contains >= 202207L
auto contains_checker = TEST_PREPARE_CALLABLE(std::ranges::contains);
#else
struct {
template<std::ranges::input_range R, typename V, typename Proj = std::identity>
bool operator()(R&& r, V value, Proj proj = {})
{
auto last = std::ranges::end(r);
return std::ranges::find(std::ranges::begin(r), last, value, proj) != last;
}
} contains_checker;
#endif
#endif

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

// expected to be found
test_range_algo<0>{big_sz}(dpl_ranges::contains, contains_checker, small_size - 19);
test_range_algo<1>{}(dpl_ranges::contains, contains_checker, proj(small_size/2 + 28), proj);
test_range_algo<2, P2>{}(dpl_ranges::contains, contains_checker, 137, &P2::x);

// expected to be absent
test_range_algo<3, P2>{}(dpl_ranges::contains, contains_checker, -27, &P2::proj);
test_range_algo<4>{big_sz}(dpl_ranges::contains, contains_checker, -43);
#endif //_ENABLE_STD_RANGES_TESTING

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

#include "std_ranges_test.h"

#if _ENABLE_STD_RANGES_TESTING
template<int call_id, typename T, typename DataGen2 = std::identity>
using launcher = test_std_ranges::test_range_algo<call_id, T, test_std_ranges::data_in_in,
/*DataGen1*/ std::identity, DataGen2>;
#if __cpp_lib_ranges_contains >= 202207L
auto checker = TEST_PREPARE_CALLABLE(std::ranges::contains_subrange);
#else
struct {
template<std::ranges::forward_range R1, std::ranges::forward_range R2, typename Pred = std::ranges::equal_to,
typename Proj1 = std::identity, typename Proj2 = std::identity>
bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {})
{
if (std::ranges::begin(r2) == std::ranges::end(r2))
return true;
auto&& result = std::ranges::search(r1, r2, pred, proj1, proj2);
return !result.empty();
}
} checker;
#endif
#endif

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

auto shift = [](auto i) { return i + 371; };
using data_gen_shifted = decltype(shift);

// Sizes of both sequences vary in the test, so each call might test both successful and unsuccessful searches
launcher<0, int>{big_sz}(dpl_ranges::contains_subrange, checker, binary_pred_const);
launcher<1, int>{}(dpl_ranges::contains_subrange, checker);
launcher<2, int>{}(dpl_ranges::contains_subrange, checker, binary_pred, dpl::identity{});
launcher<3, int, data_gen_shifted>{big_sz}(dpl_ranges::contains_subrange, checker, binary_pred, proj, proj);
launcher<4, P3, data_gen_shifted>{}(dpl_ranges::contains_subrange, checker, binary_pred_const, &P3::x, &P3::proj);
launcher<5, P3>{}(dpl_ranges::contains_subrange, checker, std::equal_to<>{}, &P3::proj, &P3::y);
#endif //_ENABLE_STD_RANGES_TESTING

return TestUtils::done(_ENABLE_STD_RANGES_TESTING);
}
Loading