Skip to content
Draft
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: 1 addition & 1 deletion libcxx/docs/Status/PSTLPaper.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Section,Description,Assignee,Complete
| `[adjacent.difference] <https://wg21.link/adjacent.difference>`_,std::adjacent_difference,Nikolas Klauser,|Not Started|
| `[adjacent.difference] <https://wg21.link/adjacent.difference>`_,std::adjacent_difference,Nikolas Klauser,|Complete|
| `[alg.adjacent.find] <https://wg21.link/alg.adjacent.find>`_,std::adjacent_find,Nikolas Klauser,|Not Started|
| `[alg.all.of] <https://wg21.link/alg.all.of>`_,std::all_of,Nikolas Klauser,|Complete|
| `[alg.any.of] <https://wg21.link/alg.any.of>`_,std::any_of,Nikolas Klauser,|Complete|
Expand Down
35 changes: 35 additions & 0 deletions libcxx/include/__numeric/pstl.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,41 @@ _LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
std::move(__transform));
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _BinaryOperation,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator adjacent_difference(
_ExecutionPolicy&& __policy,
_ForwardIterator __first,
_ForwardIterator __last,
_ForwardOutIterator __out_it,
_BinaryOperation __bin_op) {
using _Implementation =
__pstl::__dispatch<__pstl::__adjacent_difference, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy),
std::move(__first),
std::move(__last),
std::move(__out_it),
std::move(__bin_op));
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _ForwardOutIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator adjacent_difference(
_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) {
using _Implementation =
__pstl::__dispatch<__pstl::__adjacent_difference, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__out_it), minus{});
}

_LIBCPP_END_NAMESPACE_STD

#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/__pstl/backend_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ using __current_configuration = __backend_configuration<__libdispatch_backend_ta
# error "Invalid PSTL backend configuration"
# endif

template <class _Backend, class _ExecutionPolicy>
struct __adjacent_difference;
// template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _BinaryOp>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _ForwardOutIterator __out_it,
// _BinaryOp __bin_op) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __find_if;
// template <class _Policy, class _ForwardIterator, class _Predicate>
Expand Down
19 changes: 19 additions & 0 deletions libcxx/include/__pstl/backends/default.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <__functional/operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
#include <__pstl/backend_fwd.h>
#include <__pstl/dispatch.h>
#include <__utility/empty.h>
Expand Down Expand Up @@ -90,6 +91,7 @@ namespace __pstl {
// - copy
// - copy_n
// - rotate_copy
// - adjacent_difference
//

//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -497,6 +499,23 @@ struct __rotate_copy<__default_backend_tag, _ExecutionPolicy> {
}
};

template <class _ExecutionPolicy>
struct __adjacent_difference<__default_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _BinaryOp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator>
operator()(_Policy&& __policy,
_ForwardIterator __first,
_ForwardIterator __last,
_ForwardOutIterator __out_it,
_BinaryOp __bin_op) const noexcept {
if (__first == __last)
return __out_it;

using _TransformBinary = __dispatch<__transform_binary, __current_configuration, _ExecutionPolicy>;
return _TransformBinary()(__policy, std::next(__first), __last, __first, __out_it, __bin_op);
}
};

} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// UNSUPPORTED: libcpp-has-no-incomplete-pstl

// <numeric>

// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2>
// ForwardIterator2
// adjacent_difference(ExecutionPolicy&& exec,
// ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result);
//
// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
// class BinaryOperation>
// ForwardIterator2
// adjacent_difference(ExecutionPolicy&& exec,
// ForwardIterator1 first, ForwardIterator1 last,
// ForwardIterator2 result, BinaryOperation binary_op);

#include <algorithm>
#include <array>
#include <numeric>
#include <vector>

#include "test_execution_policies.h"
#include "test_iterators.h"

template <class Iter1, class Iter2>
struct Test {
template <int N, int OutN = N - 1, class Policy>
void test(Policy&& policy,
std::array<int, N> input,
std::array<int, OutN> plus_expected,
std::array<int, OutN> minus_expected) {
{
std::array<int, OutN> out;
auto ret =
std::adjacent_difference(policy, Iter1(input.data()), Iter1(input.data() + input.size()), Iter2(out.data()));
assert(base(ret) == out.data() + out.size());
assert(out == minus_expected);
}
{
std::array<int, OutN> out;
auto ret = std::adjacent_difference(
policy, Iter1(input.data()), Iter1(input.data() + input.size()), Iter2(out.data()), std::plus{});
assert(base(ret) == out.data() + out.size());
assert(out == plus_expected);
}
}

template <class Policy>
void operator()(Policy&& policy) {
// simple test
test<4>(policy, {1, 2, 3, 4}, {3, 5, 7}, {1, 1, 1});
// empty range
test<0, 0>(policy, {}, {}, {});
// single element range
test<1>(policy, {1}, {}, {});
// two element range
test<2>(policy, {10, 5}, {15}, {-5});

// Large inputs with generated data
for (auto e : {100, 322, 497, 2048}) {
std::vector<int> input(e);
std::iota(input.begin(), input.end(), 0);
std::vector<int> expected(e - 1);
auto binop = [](int lhs, int rhs) { return lhs + rhs * 3; };
std::adjacent_difference(input.begin(), input.end(), expected.begin(), binop);
std::vector<int> output(e - 1);
std::adjacent_difference(input.begin(), input.end(), output.begin(), binop);
assert(output == expected);
}

{ // ensure that all values are used exactly once
std::array input = {0, 1, 2, 3, 4, 5, 6, 7};
std::array<bool, input.size() - 1> called{};
std::array<int, input.size() - 1> output;
std::adjacent_difference(input.data(), input.data() + input.size(), output.data(), [&](int lhs, int rhs) {
assert(!called[rhs]);
called[rhs] = true;
return rhs - lhs;
});
assert(std::all_of(called.begin(), called.end(), [](bool b) { return b; }));
}
}
};

int main(int, char**) {
types::for_each(types::forward_iterator_list<int*>{}, types::apply_type_identity{[](auto v1) {
using Iter1 = typename decltype(v1)::type;
types::for_each(
types::forward_iterator_list<int*>{},
TestIteratorWithPolicies<types::partial_instantiation<Test, Iter1>::template apply>{});
}});

return 0;
}
Loading