[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