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
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 std::ranges::empty(__r2) || !(oneapi::dpl::ranges::search(std::forward<_ExecutionPolicy>(__exec), __r1, __r2,
__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