[libcxx-commits] [libcxx] [libc++][pstl] Implementation of parallel std::lexicographical_compare() based on std::mismatch() (PR #212366)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 29 18:33:25 PDT 2026


================
@@ -0,0 +1,214 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 ForwardIterator1,
+//           class ForwardIterator2,
+//           class Compare>
+//   bool lexicographical_compare(ExecutionPolicy&& exec,
+//                                ForwardIterator1 first1,
+//                                ForwardIterator1 last1,
+//                                ForwardIterator2 first2,
+//                                ForwardIterator2 last2,
+//                                Compare comp);
+
+#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"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(lexicographical_compare);
+
+static_assert(sfinae_test_lexicographical_compare<int, int*, int*, int*, int*, bool (*)(int, int)>);
+static_assert(
+    !sfinae_test_lexicographical_compare<std::execution::parallel_policy, int*, int*, int*, int*, bool (*)(int, int)>);
+
+// The types X and Y are provided to test that lexicographical_compare can be used with heterogeneous custom types.
+
+struct X {
+  X() = delete;
+  X(int i) : i_(i) {}
+  X(const X&) = delete;
+  int value() const { return i_; }
+
+private:
+  int i_;
+};
+
+struct Y {
+  Y() = delete;
+  Y(int i) : i_(i) {}
+  Y(const Y&) = delete;
+  int value() const { return i_; }
+
+private:
+  int i_;
+};
+
+struct Comp {
+  bool operator()(int lhs, int rhs) const { return lhs > rhs; }
+  bool operator()(const X& lhs, const Y& rhs) const { return lhs.value() > rhs.value(); }
+  bool operator()(const Y& lhs, const X& rhs) const { return lhs.value() > rhs.value(); }
+};
+
+template <class Iter1, class Iter2>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    { // check the return types
+      int lhs[] = {0};
+      int rhs[] = {0};
+      auto res  = std::lexicographical_compare(
+          policy,
+          Iter1(std::begin(lhs)),
+          Iter1(std::begin(lhs)),
+          Iter2(std::begin(rhs)),
+          Iter2(std::begin(rhs)),
+          Comp{});
+      static_assert(std::is_same_v<decltype(res), bool>);
+    }
+    { // 2 empty ranges
+      int lhs[] = {0};
+      int rhs[] = {0};
+      assert(!std::lexicographical_compare(
+          policy,
+          Iter1(std::begin(lhs)),
+          Iter1(std::begin(lhs)),
+          Iter2(std::begin(rhs)),
+          Iter2(std::begin(rhs)),
+          Comp{}));
+    }
+    { // left empty, right non-empty
+      int lhs[] = {0};
+      int rhs[] = {0};
+      assert(std::lexicographical_compare(
+          policy,
+          Iter1(std::begin(lhs)),
+          Iter1(std::begin(lhs)),
+          Iter2(std::begin(rhs)),
+          Iter2(std::end(rhs)),
+          Comp{}));
+    }
+    { // left non-empty, right empty
+      int lhs[] = {0};
+      int rhs[] = {0};
+      assert(!std::lexicographical_compare(
+          policy,
+          Iter1(std::begin(lhs)),
+          Iter1(std::end(lhs)),
+          Iter2(std::begin(rhs)),
+          Iter2(std::begin(rhs)),
+          Comp{}));
+    }
+    { // same size, same single element
+      int lhs[] = {0};
+      int rhs[] = {0};
+      assert(!std::lexicographical_compare(
+          policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs)), Comp{}));
+    }
+    { // left longer
+      int lhs[] = {1, 2, 3, 4, 5};
+      int rhs[] = {1, 2, 3};
+      assert(!std::lexicographical_compare(
+          policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs)), Comp{}));
+    }
+    { // right longer
+      int lhs[] = {1, 2, 3};
+      int rhs[] = {1, 2, 3, 4, 5};
+      assert(std::lexicographical_compare(
+          policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs)), Comp{}));
+    }
+    { // same size, left is lexicographically less than right
+      int lhs[] = {1, 2, 4, 4, 5};
+      int rhs[] = {1, 2, 3, 4, 5};
+      assert(std::lexicographical_compare(
+          policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs)), Comp{}));
+    }
+    { // same size, right is lexicographically less than left
+      int lhs[] = {1, 2, 3, 4, 5};
+      int rhs[] = {1, 2, 4, 4, 5};
+      assert(!std::lexicographical_compare(
+          policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs)), Comp{}));
+    }
+    { // same size, different at various positions
+      int lhs[1073];
+      int rhs[1073];
+      std::iota(std::begin(lhs), std::end(lhs), 0);
+      std::copy(std::begin(lhs), std::end(lhs), std::begin(rhs));
+      runway_sample(std::size(lhs), [&](size_t i) {
+        lhs[i] = 10'000;
+        assert(std::lexicographical_compare(
+            policy,
+            Iter1(std::begin(lhs)),
+            Iter1(std::end(lhs)),
+            Iter2(std::begin(rhs)),
+            Iter2(std::end(rhs)),
+            Comp{}));
+        lhs[i] = i;
----------------
frederick-vs-ja wrote:

No change requested for this PR.

Due to a recent PR in MSVC STL (microsoft/STL#6385), I noticed that several test files you created for PSTL contain such narrowing converting assignment (from `size_t` to `int`). These test files are (or will be) used by MSVC STL, and MSVC complains about the conversion on 64-bit platforms.

Maybe it's clearer to write `lhs[i] = static_cast<int>(i)` which makes MSVC happy. I think it might be better to have a concentrated PR for this.

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


More information about the libcxx-commits mailing list