-
Notifications
You must be signed in to change notification settings - Fork 12.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++][PSTL] Implement adjacent_difference #102431
Draft
philnik777
wants to merge
1
commit into
llvm:main
Choose a base branch
from
philnik777:pstl_adjacent_difference
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
philnik777
force-pushed
the
pstl_adjacent_difference
branch
2 times, most recently
from
August 8, 2024 14:41
19744c9
to
522dd60
Compare
philnik777
added
the
libc++
libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
label
Aug 15, 2024
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesFull diff: https://github.com/llvm/llvm-project/pull/102431.diff 5 Files Affected:
diff --git a/libcxx/docs/Status/PSTLPaper.csv b/libcxx/docs/Status/PSTLPaper.csv
index 3fb5adfe3ec46a..cb0e2423e42a36 100644
--- a/libcxx/docs/Status/PSTLPaper.csv
+++ b/libcxx/docs/Status/PSTLPaper.csv
@@ -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|
diff --git a/libcxx/include/__numeric/pstl.h b/libcxx/include/__numeric/pstl.h
index 7557686a3663db..08d7fa9cbebd63 100644
--- a/libcxx/include/__numeric/pstl.h
+++ b/libcxx/include/__numeric/pstl.h
@@ -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
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index 32c5da576fb3c0..92cbb6dbbc2093 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -63,6 +63,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>
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index 61a128805f8549..195a0b08e95450 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -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>
@@ -88,6 +89,7 @@ namespace __pstl {
// - copy
// - copy_n
// - rotate_copy
+// - adjacent_difference
//
//////////////////////////////////////////////////////////////
@@ -495,6 +497,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
diff --git a/libcxx/test/std/numerics/numeric.ops/adjacent.difference/pstl.adjacent_difference.pass.cpp b/libcxx/test/std/numerics/numeric.ops/adjacent.difference/pstl.adjacent_difference.pass.cpp
new file mode 100644
index 00000000000000..b5e3902a4f0d0c
--- /dev/null
+++ b/libcxx/test/std/numerics/numeric.ops/adjacent.difference/pstl.adjacent_difference.pass.cpp
@@ -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;
+}
|
philnik777
force-pushed
the
pstl_adjacent_difference
branch
from
November 19, 2024 12:25
522dd60
to
1adba9a
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.