[libcxx-commits] [libcxx] [libc++][pstl] Implementation of parallel std::reverse() based on parallel for_each (PR #213487)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 3 06:02:29 PDT 2026


================
@@ -0,0 +1,92 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+//   void reverse(ExecutionPolicy&& exec,
+//                BidirectionalIterator first,
+//                BidirectionalIterator last);
+
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <numeric>
+#include <type_traits>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(reverse);
+
+static_assert(sfinae_test_reverse<int, int*, int*>);
+static_assert(!sfinae_test_reverse<std::execution::parallel_policy, int*, int*>);
+
+template <class Iter>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    { // Check the return type
+      static_assert(std::is_same_v<
+                    void,
+                    decltype(std::reverse(
+                        std::declval<std::execution::parallel_policy>(), std::declval<Iter>(), std::declval<Iter>()))>);
+    }
+    { // Empty range
+      int a[] = {0};
+      std::reverse(policy, Iter(std::begin(a)), Iter(std::begin(a)));
+    }
+    { // Single element
+      int a[] = {0};
+      std::reverse(policy, Iter(std::begin(a)), Iter(std::end(a)));
+      assert(a[0] == 0);
+    }
+    { // Two elements
+      int a[] = {0, 1};
+      std::reverse(policy, Iter(std::begin(a)), Iter(std::end(a)));
+      assert(a[0] == 1);
+      assert(a[1] == 0);
+    }
+    { // Three elements
+      int a[] = {0, 1, 2};
+      std::reverse(policy, Iter(std::begin(a)), Iter(std::end(a)));
+      assert(a[0] == 2);
+      assert(a[1] == 1);
+      assert(a[2] == 0);
+    }
+    { // Four elements
+      int a[] = {0, 1, 2, 3};
+      std::reverse(policy, Iter(std::begin(a)), Iter(std::end(a)));
+      assert(a[0] == 3);
+      assert(a[1] == 2);
+      assert(a[2] == 1);
+      assert(a[3] == 0);
+    }
+    { // Many iotaed elements, reverse up to a sampled position, check and reverse back
+      int a[1073];
+      std::iota(std::begin(a), std::end(a), 1);
+      runway_sample(std::size(a) + 1, [&](size_t i) {
+        std::reverse(policy, Iter(std::begin(a)), Iter(std::begin(a) + i));
+        for (size_t j = 0; j < i; ++j) {
+          assert(a[j] == static_cast<int>(i - j));
+        }
+        std::reverse(policy, Iter(std::begin(a)), Iter(std::begin(a) + i));
+      });
+    }
+  }
+};
+
+int main(int, char**) { types::for_each(types::bidirectional_iterator_list<int*>{}, TestIteratorWithPolicies<Test>{}); }
----------------
ldionne wrote:

Also, I think `reverse` allows iterators from `ForwardIterator` onwards, right? If so, we should use `forward_iterator_list`?

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


More information about the libcxx-commits mailing list