[libcxx-commits] [libcxx] [libc++][pstl] Default implementation of parallel std::reverse_copy (PR #208085)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 8 09:15:09 PDT 2026


================
@@ -0,0 +1,116 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template <class ExecutionPolicy,
+//           class BidirectionalIterator,
+//           class ForwardIterator>
+//   ForwardIterator reverse_copy(ExecutionPolicy&& exec,
+//                                BidirectionalIterator first,
+//                                BidirectionalIterator last,
+//                                ForwardIterator result);
+
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+EXECUTION_POLICY_SFINAE_TEST(reverse_copy);
+
+static_assert(sfinae_test_reverse_copy<int, int*, int*, int*>);
+static_assert(!sfinae_test_reverse_copy<std::execution::parallel_policy, int*, int*, int*>);
+
+template <class Callable>
+void runway_sample(size_t size, Callable callable) {
+  constexpr size_t affix = 16;
+  // 0, 1, 2, ..., 15, 16, 50, 157, 493, 1548, ...
+  for (size_t i = 0; i < size; i = i < affix ? i + 1 : size_t(3.1415 * i)) {
+    callable(i);
+  }
+  if (size <= affix)
+    return;
+  // size - 16, size - 15, ..., size - 1
+  for (size_t i = size - affix; i < size; ++i) {
+    callable(i);
+  }
+}
+
+template <class Iter1, class Iter2>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      int ia[]              = {0};
+      int ib[std::size(ia)] = {-1};
+      Iter2 r = std::reverse_copy(policy, Iter1(std::begin(ia)), Iter1(std::begin(ia)), Iter2(std::begin(ib)));
+      assert(r == Iter2(std::begin(ib)));
+      assert(ib[0] == -1);
+      r = std::reverse_copy(policy, Iter1(std::begin(ia)), Iter1(std::end(ia)), Iter2(std::begin(ib)));
+      assert(ia[0] == 0);
+    }
+    {
+      int ia[]              = {0, 1};
+      int ib[std::size(ia)] = {-1};
+      Iter2 r = std::reverse_copy(policy, Iter1(std::begin(ia)), Iter1(std::end(ia)), Iter2(std::begin(ib)));
+      assert(r == Iter2(std::end(ib)));
+      assert(ib[0] == 1);
+      assert(ib[1] == 0);
+    }
+    {
+      int ia[]              = {0, 1, 2};
+      int ib[std::size(ia)] = {-1};
+      Iter2 r = std::reverse_copy(policy, Iter1(std::begin(ia)), Iter1(std::end(ia)), Iter2(std::begin(ib)));
+      assert(r == Iter2(std::end(ib)));
+      assert(ib[0] == 2);
+      assert(ib[1] == 1);
+      assert(ib[2] == 0);
+    }
+    {
+      int ia[]              = {0, 1, 2, 3};
+      int ib[std::size(ia)] = {-1};
+      Iter2 r = std::reverse_copy(policy, Iter1(std::begin(ia)), Iter1(std::end(ia)), Iter2(std::begin(ib)));
+      assert(r == Iter2(std::end(ib)));
+      assert(ib[0] == 3);
+      assert(ib[1] == 2);
+      assert(ib[2] == 1);
+      assert(ib[3] == 0);
+    }
+    {
+      int ia[1073];
+      int ib[1073];
+      std::iota(std::begin(ia), std::end(ia), 1);
+      runway_sample(std::size(ia) + 1, [&](size_t i) {
+        Iter2 r = std::reverse_copy(policy, Iter1(std::begin(ia)), Iter1(std::begin(ia) + i), Iter2(std::begin(ib)));
+        assert(r == Iter2(std::begin(ib) + i));
+        for (size_t j = 0; j < i; ++j) {
+          assert(ib[j] == static_cast<int>(i - j));
+        }
+      });
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(
+      types::concatenate_t<types::bidirectional_iterator_list<int*>, types::bidirectional_iterator_list<const int*>>{},
+      types::apply_type_identity{[](auto v) {
+        using Iter = typename decltype(v)::type;
+        types::for_each(types::forward_iterator_list<int*>{},
+                        TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+      }});
+}
----------------
ldionne wrote:

Nit: missing newline

https://github.com/llvm/llvm-project/pull/208085


More information about the libcxx-commits mailing list