[libcxx-commits] [libcxx] [libc++][pstl] Implementation of parallel std::search_n() based on __parallel_find() (PR #214069)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 5 08:55:11 PDT 2026


================
@@ -0,0 +1,160 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator, class Size, class T>
+//   ForwardIterator
+//   search_n(ExecutionPolicy&& exec,
+//            ForwardIterator first, ForwardIterator last,
+//            Size count, const T& value);
+
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+
+#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(search_n);
+
+static_assert(sfinae_test_search_n<int, int*, int*, int, int>);
+static_assert(!sfinae_test_search_n<std::execution::parallel_policy, int*, int*, int, int>);
+
+template <class Iter>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    { // check the return types
+      int a[]  = {0};
+      auto res = std::search_n(policy, Iter(std::begin(a)), Iter(std::begin(a)), 1, 0);
+      static_assert(std::is_same_v<decltype(res), Iter>);
+    }
+    { // single element range with count = 1, matching
+      int a[]  = {5};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 1, 5);
+      assert(ret == Iter(std::begin(a)));
+    }
+    { // single element range with count = 1, not matching
+      int a[]  = {5};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 1, 3);
+      assert(ret == Iter(std::end(a)));
+    }
+    { // simple test - single match in the middle, count = 1
+      int a[]  = {1, 2, 3, 4, 5, 6};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 1, 3);
+      assert(ret == Iter(std::begin(a) + 2));
+    }
+    { // matching part begins at the front
+      int a[]  = {7, 7, 3, 7, 3, 6};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 2, 7);
+      assert(ret == Iter(std::begin(a)));
+    }
+    { // matching part ends at the back
+      int a[]  = {9, 3, 6, 4, 4};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 2, 4);
+      assert(ret == Iter(std::begin(a) + 3));
+    }
+    { // pattern does not match
+      int a[]  = {9, 3, 6, 4, 8};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 1, 1);
+      assert(ret == Iter(std::end(a)));
+    }
+    { // range and pattern are identical
+      int a[]  = {1, 1, 1, 1};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 4, 1);
+      assert(ret == Iter(std::begin(a)));
+    }
+    { // pattern is longer than range
+      int a[]  = {5};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 2, 5);
+      assert(ret == Iter(std::end(a)));
+    }
+    { // pattern is longer than range
+      int a[]  = {3, 3, 3};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 4, 3);
+      assert(ret == Iter(std::end(a)));
+    }
+    { // pattern has zero length
+      int a[]  = {6, 7, 8};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 0, 7);
+      assert(ret == Iter(std::begin(a)));
+    }
+    { // range has zero length
+      int a[]  = {0};
+      auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::begin(a)), 1, 1);
+      assert(ret == Iter(std::begin(a)));
+    }
+    {   // check that the first match is returned
+      { // match is at the start
+        int a[]  = {6, 6, 8, 6, 6, 8, 6, 6, 8};
+        auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 2, 6);
+        assert(ret == Iter(std::begin(a)));
+      }
+      { // match is in the middle
+        int a[]  = {6, 8, 8, 6, 6, 8, 6, 6, 8};
+        auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 2, 6);
+        assert(ret == Iter(std::begin(a) + 3));
+      }
+      { // match is at the end
+        int a[]  = {6, 6, 8, 6, 6, 8, 6, 6, 6};
+        auto ret = std::search_n(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
+        assert(ret == Iter(std::begin(a) + 6));
+      }
+      { // multiple overlapping potential matches
----------------
ldionne wrote:

Could you add the coverage you added here back in the tests for the serial implementations too? I think it's small enough to do as a drive-by in this PR.

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


More information about the libcxx-commits mailing list