[libcxx-commits] [libcxx] [libc++][pstl] Implementation of a parallel std::mismatch() based on __pstl::__parallel_find() (PR #209291)
Michael G. Kazakov via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jul 22 07:37:06 PDT 2026
https://github.com/mikekazakov updated https://github.com/llvm/llvm-project/pull/209291
>From 31208d7946efae8b2e45a121c5178562a7b639c8 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 21:03:38 +0100
Subject: [PATCH 01/15] Added a basic implementation of parallel 4-legged
mismatch() based on __parallel_find()
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__pstl/backend_fwd.h | 8 +
libcxx/include/__pstl/backends/libdispatch.h | 7 +-
libcxx/include/__pstl/backends/serial.h | 20 +++
libcxx/include/__pstl/backends/std_thread.h | 5 +
libcxx/include/__pstl/cpu_algos/mismatch.h | 88 +++++++++++
.../mismatch/pstl.mismatch.pass.cpp | 139 ++++++++++++++++++
7 files changed, 267 insertions(+), 1 deletion(-)
create mode 100644 libcxx/include/__pstl/cpu_algos/mismatch.h
create mode 100644 libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index b40f586161e62..6b5dc87fbe76d 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -677,6 +677,7 @@ set(files
__pstl/cpu_algos/find_if.h
__pstl/cpu_algos/for_each.h
__pstl/cpu_algos/merge.h
+ __pstl/cpu_algos/mismatch.h
__pstl/cpu_algos/stable_sort.h
__pstl/cpu_algos/transform.h
__pstl/cpu_algos/transform_reduce.h
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index 2ba5b4434fc33..aa7633a240722 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -324,6 +324,14 @@ struct __adjacent_difference;
// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
// _ForwardIterator2 __first2, _BinaryOperation &&__op) const noexcept;
+template <class _Backend, class _ExecutionPolicy>
+struct __mismatch;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Comp>
+// optional<pair<_ForwardIterator1, _ForwardIterator2>>
+// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+// _Comp __comp) const noexcept;
+
} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__pstl/backends/libdispatch.h b/libcxx/include/__pstl/backends/libdispatch.h
index f7141d24df090..5e89c6fe31cd8 100644
--- a/libcxx/include/__pstl/backends/libdispatch.h
+++ b/libcxx/include/__pstl/backends/libdispatch.h
@@ -37,6 +37,7 @@
#include <__pstl/cpu_algos/find_if.h>
#include <__pstl/cpu_algos/for_each.h>
#include <__pstl/cpu_algos/merge.h>
+#include <__pstl/cpu_algos/mismatch.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
@@ -241,7 +242,7 @@ struct __cpu_traits<__libdispatch_backend_tag> {
auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_;
auto __index = __chunk == 0 ? 0
: (__chunk * __partitions.__chunk_size_) +
- (__partitions.__first_chunk_size_ - __partitions.__chunk_size_);
+ (__partitions.__first_chunk_size_ - __partitions.__chunk_size_);
if (__this_chunk_size != 1) {
std::__construct_at(
__values.get() + __chunk,
@@ -368,6 +369,10 @@ template <class _ExecutionPolicy>
struct __merge<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_merge<__libdispatch_backend_tag, _ExecutionPolicy> {};
+template <class _ExecutionPolicy>
+struct __mismatch<__libdispatch_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_mismatch<__libdispatch_backend_tag, _ExecutionPolicy> {};
+
template <class _ExecutionPolicy>
struct __stable_sort<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_stable_sort<__libdispatch_backend_tag, _ExecutionPolicy> {};
diff --git a/libcxx/include/__pstl/backends/serial.h b/libcxx/include/__pstl/backends/serial.h
index f4142016ccc79..d90022ee37145 100644
--- a/libcxx/include/__pstl/backends/serial.h
+++ b/libcxx/include/__pstl/backends/serial.h
@@ -13,6 +13,7 @@
#include <__algorithm/find_if.h>
#include <__algorithm/for_each.h>
#include <__algorithm/merge.h>
+#include <__algorithm/mismatch.h>
#include <__algorithm/stable_sort.h>
#include <__algorithm/transform.h>
#include <__config>
@@ -55,6 +56,25 @@ struct __find_if<__serial_backend_tag, _ExecutionPolicy> {
}
};
+template <class _ExecutionPolicy>
+struct __mismatch<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
+ _LIBCPP_HIDE_FROM_ABI optional<pair<_ForwardIterator1, _ForwardIterator2>>
+ operator()(_Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _Predicate&& __pred) const noexcept {
+ return std::mismatch(
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::forward<_Predicate>(__pred));
+ }
+};
+
template <class _ExecutionPolicy>
struct __for_each<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _ForwardIterator, class _Function>
diff --git a/libcxx/include/__pstl/backends/std_thread.h b/libcxx/include/__pstl/backends/std_thread.h
index dd2c3f15403e3..93935d22b9442 100644
--- a/libcxx/include/__pstl/backends/std_thread.h
+++ b/libcxx/include/__pstl/backends/std_thread.h
@@ -17,6 +17,7 @@
#include <__pstl/cpu_algos/find_if.h>
#include <__pstl/cpu_algos/for_each.h>
#include <__pstl/cpu_algos/merge.h>
+#include <__pstl/cpu_algos/mismatch.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
@@ -100,6 +101,10 @@ template <class _ExecutionPolicy>
struct __merge<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_merge<__std_thread_backend_tag, _ExecutionPolicy> {};
+template <class _ExecutionPolicy>
+struct __mismatch<__std_thread_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_mismatch<__std_thread_backend_tag, _ExecutionPolicy> {};
+
template <class _ExecutionPolicy>
struct __stable_sort<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_stable_sort<__std_thread_backend_tag, _ExecutionPolicy> {};
diff --git a/libcxx/include/__pstl/cpu_algos/mismatch.h b/libcxx/include/__pstl/cpu_algos/mismatch.h
new file mode 100644
index 0000000000000..11ffdc332d633
--- /dev/null
+++ b/libcxx/include/__pstl/cpu_algos/mismatch.h
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___PSTL_CPU_ALGOS_MISMATCH_H
+#define _LIBCPP___PSTL_CPU_ALGOS_MISMATCH_H
+
+#include <__algorithm/mismatch.h>
+#include <__config>
+#include <__functional/operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__pstl/backend_fwd.h>
+#include <__pstl/cpu_algos/cpu_traits.h>
+#include <__pstl/cpu_algos/find_if.h>
+#include <__type_traits/is_execution_policy.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+#include <optional>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace __pstl {
+
+template <class _Backend, class _RawExecutionPolicy>
+struct __cpu_parallel_mismatch {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
+ _LIBCPP_HIDE_FROM_ABI optional<pair<_ForwardIterator1, _ForwardIterator2>>
+ operator()(_Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _Predicate __pred) const noexcept {
+ if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) {
+ // Look for a mismatch only in the prefix of the two ranges.
+ auto __n = std::min(__last1 - __first1, __last2 - __first2);
+ // Find a position in the first range where the predicate is false against the corresponding position in the
+ // second range.
+ auto __res = __pstl::__parallel_find<_Backend>(
+ __first1,
+ __first1 + __n,
+ [&__pred, __first1, __first2](_ForwardIterator1 __brick_first1, _ForwardIterator1 __brick_last1) {
+ // Run the sequential mismatch algorithm on these ranges:
+ // [__brick_first1, __brick_last1) and
+ // [__first2 + (__brick_first1 - __first1), __first2 + (__brick_last1 - __first1))
+ auto __brick_first2 = __first2 + (__brick_first1 - __first1);
+ return std::mismatch(std::move(__brick_first1), std::move(__brick_last1), std::move(__brick_first2), __pred)
+ .first;
+ },
+ less<>{},
+ true);
+ if (!__res) {
+ return std::nullopt; // Failed to run the algorithm, propagate the error.
+ }
+ auto __idx = *__res - __first1;
+ return pair<_ForwardIterator1, _ForwardIterator2>{std::move(*__res), __first2 + __idx};
+ } else {
+ // Non-random access iterators cannot be processed in parallel, fall back to the sequential implementation.
+ // Unsequenced execution is also implicitly covered by the sequential implementation.
+ return std::mismatch(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__pred));
+ }
+ }
+};
+
+} // namespace __pstl
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___PSTL_CPU_ALGOS_MISMATCH_H
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
new file mode 100644
index 0000000000000..9cbadda428ad9
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -0,0 +1,139 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+// pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2);
+
+#include <algorithm>
+#include <array>
+#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(mismatch);
+
+static_assert(sfinae_test_mismatch<int, int*, int*, int*, int*>);
+static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, int*>);
+
+// TODO: switch with a shared implemented once it's merged into main
+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) {
+ {
+ // empty ranges
+ std::array<int, 1> lhs = {0};
+ std::array<int, 1> rhs = {0};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
+ }
+ {
+ // single element only
+ std::array<int, 1> lhs = {0};
+ std::array<int, 1> rhs = {0};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // same range without mismatch
+ std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // same range with mismatch
+ std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
+ std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
+ }
+ { // second range is smaller
+ std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
+ std::array<int, 2> rhs = {0, 1};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ }
+ { // first range is smaller
+ std::array<int, 2> lhs = {0, 1};
+ std::array<int, 8> rhs = {0, 1, 2, 2, 0, 1, 2, 3};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ }
+ { // same size, mismatching at various positions
+ std::array<int, 1073> lhs;
+ std::array<int, 1073> rhs;
+ std::iota(std::begin(lhs), std::end(lhs), 0);
+ rhs = lhs;
+ runway_sample(lhs.size(), [&](size_t i) {
+ lhs[i] = -1;
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ lhs[i] = i;
+ });
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // same values, different lengths
+ std::array<int, 739> lhs;
+ std::array<int, 739> rhs;
+ lhs.fill(42);
+ rhs.fill(42);
+ runway_sample(lhs.size(), [&](size_t i) {
+ // lhs is shorter
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin() + i), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ // rhs is shorter
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.begin() + i)) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ });
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const int*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const int*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
>From ddbcca0bf2d23ac5caaed98c0912016bb23c7640 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 21:05:01 +0100
Subject: [PATCH 02/15] Added a definition of a parallel 4-legged
std::mismatch()
---
libcxx/include/__algorithm/pstl.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index 2bf9b4276baab..ab35b1a3e537b 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -138,6 +138,29 @@ count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __
std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), __value);
}
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator1, _ForwardIterator2>
+mismatch(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "mismatch requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "mismatch requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__mismatch, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ equal_to{});
+}
+
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
>From 81cdb4aa0a748c2a8039e0c478c19259860513a7 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 21:41:51 +0100
Subject: [PATCH 03/15] Added a default implementation of __mismatch_3leg based
on __mismatch
---
libcxx/include/__algorithm/pstl.h | 18 ++++++++++
libcxx/include/__pstl/backend_fwd.h | 7 ++++
libcxx/include/__pstl/backends/default.h | 36 +++++++++++++++++++
libcxx/include/module.modulemap.in | 3 ++
.../mismatch/pstl.mismatch.pass.cpp | 20 +++++++++++
5 files changed, 84 insertions(+)
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index ab35b1a3e537b..01c61fb00f4d5 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -161,6 +161,24 @@ mismatch(_ExecutionPolicy&& __policy,
equal_to{});
}
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator1, _ForwardIterator2> mismatch(
+ _ExecutionPolicy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "mismatch requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "mismatch requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__mismatch_3leg, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ equal_to{});
+}
+
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index aa7633a240722..ecd1f0b9b4049 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -332,6 +332,13 @@ struct __mismatch;
// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
// _Comp __comp) const noexcept;
+template <class _Backend, class _ExecutionPolicy>
+struct __mismatch_3leg;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Comp>
+// optional<pair<_ForwardIterator1, _ForwardIterator2>>
+// operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _Comp __comp) const noexcept;
+
} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index 28bc75be147aa..b6a15b234b8da 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -63,6 +63,10 @@ namespace __pstl {
// - is_partitioned
// - find_first_of
//
+// mismatch family
+// ---------------
+// - mismatch_3leg
+//
// for_each family
// ---------------
// - for_each_n
@@ -212,6 +216,38 @@ struct __find_first_of<__default_backend_tag, _ExecutionPolicy> {
}
};
+//////////////////////////////////////////////////////////////
+// mismatch family
+//////////////////////////////////////////////////////////////
+
+template <class _ExecutionPolicy>
+struct __mismatch_3leg<__default_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Comp>
+ optional<pair<_ForwardIterator1, _ForwardIterator2>>
+ operator()(_Policy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _Comp __comp) const noexcept {
+ if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) {
+ // Forward to the 4-legged version of mismatch.
+ using _Mismatch = __dispatch<__mismatch, __current_configuration, _ExecutionPolicy>;
+ _ForwardIterator2 __last2 = __first2 + (__last1 - __first1);
+ return _Mismatch()(
+ __policy,
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__comp));
+ } else {
+ // Currently only random access iterators are supported for parallel mismatch_3leg.
+ return std::mismatch(std::move(__first1), std::move(__last1), std::move(__first2), std::move(__comp));
+ }
+ }
+};
+
//////////////////////////////////////////////////////////////
// for_each family
//////////////////////////////////////////////////////////////
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 39b4e0bb986c6..752aa35643e2b 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2384,6 +2384,9 @@ module std {
module merge {
header "__pstl/cpu_algos/merge.h"
}
+ module mismatch {
+ header "__pstl/cpu_algos/mismatch.h"
+ }
module stable_sort {
header "__pstl/cpu_algos/stable_sort.h"
export std_core.utility_core.empty
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index 9cbadda428ad9..0cb5c7632eed8 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -10,6 +10,14 @@
// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+// template <class ExecutionPolicy,
+// class ForwardIterator1,
+// class ForwardIterator2>
+// pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2);
+//
// template <class ExecutionPolicy,
// class ForwardIterator1,
// class ForwardIterator2>
@@ -61,6 +69,8 @@ struct Test {
// empty ranges
std::array<int, 1> lhs = {0};
std::array<int, 1> rhs = {0};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin()), Iter2(rhs.begin())) ==
std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
}
@@ -68,18 +78,24 @@ struct Test {
// single element only
std::array<int, 1> lhs = {0};
std::array<int, 1> rhs = {0};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
}
{ // same range without mismatch
std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
}
{ // same range with mismatch
std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
}
@@ -102,10 +118,14 @@ struct Test {
rhs = lhs;
runway_sample(lhs.size(), [&](size_t i) {
lhs[i] = -1;
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
lhs[i] = i;
});
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
}
>From d5910cc36d457006d17cf1adad74a94ee5a4e759 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 22:20:42 +0100
Subject: [PATCH 04/15] Added predicated versions
---
libcxx/include/__algorithm/pstl.h | 49 +++++
.../mismatch/pstl.mismatch.pass.cpp | 2 +
.../mismatch/pstl.mismatch_pred.pass.cpp | 178 ++++++++++++++++++
3 files changed, 229 insertions(+)
create mode 100644 libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index 01c61fb00f4d5..bc48fd9f48d7f 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -31,6 +31,7 @@ _LIBCPP_PUSH_MACROS
# include <__type_traits/remove_cvref.h>
# include <__utility/forward.h>
# include <__utility/move.h>
+# include <__utility/pair.h>
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -138,6 +139,31 @@ count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __
std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), __value);
}
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _BinaryPredicate,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator1, _ForwardIterator2>
+mismatch(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _BinaryPredicate __pred) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "mismatch requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "mismatch requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__mismatch, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__pred));
+}
+
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
@@ -161,6 +187,29 @@ mismatch(_ExecutionPolicy&& __policy,
equal_to{});
}
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _BinaryPredicate,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator1, _ForwardIterator2>
+mismatch(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _BinaryPredicate __pred) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "mismatch requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "mismatch requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__mismatch_3leg, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__pred));
+}
+
template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index 0cb5c7632eed8..8584f2779927f 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -42,6 +42,8 @@
EXECUTION_POLICY_SFINAE_TEST(mismatch);
+static_assert(sfinae_test_mismatch<int, int*, int*, int*>);
+static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*>);
static_assert(sfinae_test_mismatch<int, int*, int*, int*, int*>);
static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, int*>);
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
new file mode 100644
index 0000000000000..39e952cbc38f6
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
@@ -0,0 +1,178 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 BinaryPredicate>
+// pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// BinaryPredicate pred);
+//
+// template <class ExecutionPolicy,
+// class ForwardIterator1,
+// class ForwardIterator2,
+// class BinaryPredicate>
+// pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec,
+// ForwardIterator1 first1,
+// ForwardIterator1 last1,
+// ForwardIterator2 first2,
+// ForwardIterator2 last2,
+// BinaryPredicate pred);
+
+#include <algorithm>
+#include <array>
+#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(mismatch);
+
+static_assert(sfinae_test_mismatch<int, int*, int*, int*, bool (*)(int, int)>);
+static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, bool (*)(int, int)>);
+static_assert(sfinae_test_mismatch<int, int*, int*, int*, int*, bool (*)(int, int)>);
+static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, int*, bool (*)(int, int)>);
+
+// TODO: switch with a shared implemented once it's merged into main
+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);
+ }
+}
+
+struct Pred {
+ bool operator()(int a, int b) const { return a * 2 == b; }
+};
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ {
+ // empty ranges
+ std::array<int, 1> lhs = {0};
+ std::array<int, 1> rhs = {0};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
+ assert(std::mismatch(
+ policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
+ }
+ {
+ // single element only
+ std::array<int, 1> lhs = {1};
+ std::array<int, 1> rhs = {2};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // same range without mismatch
+ std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ std::array<int, 8> rhs = {0, 2, 4, 6, 0, 2, 4, 6};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // same range with mismatch
+ std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ std::array<int, 8> rhs = {0, 2, 4, 7, 0, 2, 4, 6};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
+ }
+ { // second range is smaller
+ std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
+ std::array<int, 2> rhs = {0, 2};
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ }
+ { // first range is smaller
+ std::array<int, 2> lhs = {0, 1};
+ std::array<int, 8> rhs = {0, 2, 2, 2, 0, 1, 2, 3};
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ }
+ { // same size, mismatching at various positions
+ std::array<int, 1073> lhs;
+ std::array<int, 1073> rhs;
+ std::iota(std::begin(lhs), std::end(lhs), 0);
+ rhs = lhs;
+ std::for_each(std::begin(rhs), std::end(rhs), [](int& x) { x *= 2; });
+ runway_sample(lhs.size(), [&](size_t i) {
+ lhs[i] = -1;
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ lhs[i] = i;
+ });
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // same values, different lengths
+ std::array<int, 739> lhs;
+ std::array<int, 739> rhs;
+ lhs.fill(42);
+ rhs.fill(84);
+ runway_sample(lhs.size(), [&](size_t i) {
+ // lhs is shorter
+ assert(std::mismatch(
+ policy, Iter1(lhs.begin()), Iter1(lhs.begin() + i), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ // rhs is shorter
+ assert(std::mismatch(
+ policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.begin() + i), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ });
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<const int*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const int*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
>From 9b207d1481c9076b4bb2af97d049845f2c4e16e0 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 22:39:47 +0100
Subject: [PATCH 05/15] Added tests against custom types
---
libcxx/include/__pstl/backends/default.h | 1 +
.../mismatch/pstl.mismatch.pass.cpp | 53 ++++++++++++++++++
.../mismatch/pstl.mismatch_pred.pass.cpp | 56 ++++++++++++++++++-
3 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index b6a15b234b8da..776c76f3fdfbd 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -16,6 +16,7 @@
#include <__algorithm/find_if.h>
#include <__algorithm/for_each_n.h>
#include <__algorithm/is_sorted.h>
+#include <__algorithm/mismatch.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/not_fn.h>
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index 8584f2779927f..5e46831539c30 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -63,6 +63,30 @@ void runway_sample(size_t size, Callable callable) {
}
}
+// The types X and Y are provided to test that the mismatch algorithm 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;
+};
+
+bool operator==(const X& lhs, const Y& rhs) { return lhs.value() == rhs.value(); }
+
template <class Iter1, class Iter2>
struct Test {
template <class ExecutionPolicy>
@@ -150,6 +174,29 @@ struct Test {
}
};
+template <class Iter1, class Iter2>
+struct TestXY {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ { // same ranges
+ std::array<X, 3> lhs = {X(1), X(5), X(7)};
+ std::array<Y, 3> rhs = {Y(1), Y(5), Y(7)};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // one element mismatch
+ std::array<X, 3> lhs = {X(1), X(5), X(7)};
+ std::array<Y, 3> rhs = {Y(1), Y(5), Y(8)};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ }
+ }
+};
+
int main(int, char**) {
types::for_each(types::forward_iterator_list<const int*>{}, types::apply_type_identity{[](auto v) {
using Iter = typename decltype(v)::type;
@@ -157,5 +204,11 @@ int main(int, char**) {
types::forward_iterator_list<const int*>{},
TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
}});
+ types::for_each(types::forward_iterator_list<const X*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const Y*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<TestXY, Iter>::template apply>{});
+ }});
return 0;
}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
index 39e952cbc38f6..9c0dfc6c0c127 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
@@ -67,8 +67,31 @@ void runway_sample(size_t size, Callable callable) {
}
}
+// The types X and Y are provided to test that the mismatch algorithm 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 Pred {
- bool operator()(int a, int b) const { return a * 2 == b; }
+ bool operator()(int lhs, int rhs) const { return lhs * 2 == rhs; }
+ bool operator()(const X& lhs, const Y& rhs) const { return lhs.value() * 2 == rhs.value(); }
};
template <class Iter1, class Iter2>
@@ -167,6 +190,31 @@ struct Test {
}
};
+template <class Iter1, class Iter2>
+struct TestXY {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ { // same ranges
+ std::array<X, 3> lhs = {X(1), X(5), X(7)};
+ std::array<Y, 3> rhs = {Y(2), Y(10), Y(14)};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ }
+ { // one element mismatch
+ std::array<X, 3> lhs = {X(1), X(5), X(7)};
+ std::array<Y, 3> rhs = {Y(2), Y(10), Y(13)};
+ assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ assert(
+ std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
+ std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ }
+ }
+};
+
int main(int, char**) {
types::for_each(types::forward_iterator_list<const int*>{}, types::apply_type_identity{[](auto v) {
using Iter = typename decltype(v)::type;
@@ -174,5 +222,11 @@ int main(int, char**) {
types::forward_iterator_list<const int*>{},
TestIteratorWithPolicies<types::partial_instantiation<Test, Iter>::template apply>{});
}});
+ types::for_each(types::forward_iterator_list<const X*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<const Y*>{},
+ TestIteratorWithPolicies<types::partial_instantiation<TestXY, Iter>::template apply>{});
+ }});
return 0;
}
>From c21c583527e255d722f312b871d43527e5c4dbb6 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 22:52:50 +0100
Subject: [PATCH 06/15] Added a nodiscard test
---
libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
index f4fffd456a331..f5eaf1642b687 100644
--- a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
@@ -63,4 +63,12 @@ void test() {
std::adjacent_difference(std::execution::par, std::begin(a), std::end(a), std::begin(b));
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::adjacent_difference(std::execution::par, std::begin(a), std::end(a), std::begin(b), pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::mismatch(std::execution::par, std::begin(a), std::end(a), std::begin(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::mismatch(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::mismatch(std::execution::par, std::begin(a), std::end(a), std::begin(b), pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::mismatch(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b), pred2);
}
>From 189ba7a5f23d45939e0ff917985bc7049740d1b7 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 22:57:47 +0100
Subject: [PATCH 07/15] Added an iterator requirement test
---
.../pstl.iterator-requirements.verify.cpp | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
index 402d8fbf9131a..df11341008bc5 100644
--- a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
@@ -135,6 +135,22 @@ void f(non_forward_iterator non_fwd,
(void)std::merge(pol, it, it, it, it, non_output, pred); // expected-error@*:* {{static assertion failed: merge}}
}
+ {
+ (void)std::mismatch(pol, non_fwd, non_fwd, it); // expected-error@*:* {{static assertion failed: mismatch}}
+ (void)std::mismatch(pol, it, it, non_fwd); // expected-error@*:* {{static assertion failed: mismatch}}
+
+ (void)std::mismatch(pol, non_fwd, non_fwd, it, it); // expected-error@*:* {{static assertion failed: mismatch}}
+ (void)std::mismatch(pol, it, it, non_fwd, non_fwd); // expected-error@*:* {{static assertion failed: mismatch}}
+
+ (void)std::mismatch(pol, non_fwd, non_fwd, it, pred); // expected-error@*:* {{static assertion failed: mismatch}}
+ (void)std::mismatch(pol, it, it, non_fwd, pred); // expected-error@*:* {{static assertion failed: mismatch}}
+
+ (void)std::mismatch(
+ pol, non_fwd, non_fwd, it, it, pred); // expected-error@*:* {{static assertion failed: mismatch}}
+ (void)std::mismatch(
+ pol, it, it, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: mismatch}}
+ }
+
{
(void)std::move(pol, non_fwd, non_fwd, out); // expected-error@*:* {{static assertion failed: move}}
(void)std::move(pol, it, it, non_fwd); // expected-error@*:* {{static assertion failed: move}}
>From 731de4a2cf2c196b704234b0ee5653453554b9b7 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 23:00:09 +0100
Subject: [PATCH 08/15] Added an include of <__algorithm/min.h>
---
libcxx/include/__pstl/cpu_algos/mismatch.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__pstl/cpu_algos/mismatch.h b/libcxx/include/__pstl/cpu_algos/mismatch.h
index 11ffdc332d633..8361731e78cfc 100644
--- a/libcxx/include/__pstl/cpu_algos/mismatch.h
+++ b/libcxx/include/__pstl/cpu_algos/mismatch.h
@@ -9,8 +9,9 @@
#ifndef _LIBCPP___PSTL_CPU_ALGOS_MISMATCH_H
#define _LIBCPP___PSTL_CPU_ALGOS_MISMATCH_H
-#include <__algorithm/mismatch.h>
#include <__config>
+#include <__algorithm/mismatch.h>
+#include <__algorithm/min.h>
#include <__functional/operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
>From 105a17ed5abc39ad5ac34bd930af8727a9562bed Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Mon, 13 Jul 2026 23:05:29 +0100
Subject: [PATCH 09/15] Added an exception handling test
---
libcxx/include/__pstl/cpu_algos/mismatch.h | 4 +--
.../pstl.exception_handling.pass.cpp | 25 +++++++++++++++++++
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__pstl/cpu_algos/mismatch.h b/libcxx/include/__pstl/cpu_algos/mismatch.h
index 8361731e78cfc..597a47fb185c8 100644
--- a/libcxx/include/__pstl/cpu_algos/mismatch.h
+++ b/libcxx/include/__pstl/cpu_algos/mismatch.h
@@ -9,9 +9,9 @@
#ifndef _LIBCPP___PSTL_CPU_ALGOS_MISMATCH_H
#define _LIBCPP___PSTL_CPU_ALGOS_MISMATCH_H
-#include <__config>
-#include <__algorithm/mismatch.h>
#include <__algorithm/min.h>
+#include <__algorithm/mismatch.h>
+#include <__config>
#include <__functional/operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
diff --git a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
index e00046fdb1dd6..cbdb4663f168c 100644
--- a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
+++ b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
@@ -248,6 +248,31 @@ int main(int, char**) {
});
}
+ {
+ auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
+
+ // mismatch(first1, last1, first2)
+ assert_non_throwing([=, &policy] {
+ (void)std::mismatch(policy, std::move(first1), std::move(last1), std::move(first2));
+ });
+
+ // mismatch(first1, last1, first2, last2)
+ assert_non_throwing([=, &policy] {
+ (void)std::mismatch(policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2));
+ });
+
+ // mismatch(first1, last1, first2, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::mismatch(policy, std::move(first1), std::move(last1), std::move(first2), compare);
+ });
+
+ // mismatch(first1, last1, first2, last2, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::mismatch(
+ policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), compare);
+ });
+ }
+
{
// move(first, last, dest)
assert_non_throwing([=, &policy] {
>From 3bd32433db95c6995476e26d5b34c8000a5515f5 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Tue, 14 Jul 2026 09:43:45 +0100
Subject: [PATCH 10/15] Changed the variable name to avoid shadowing
---
.../alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp | 12 ++++++------
.../mismatch/pstl.mismatch_pred.pass.cpp | 12 ++++++------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index 5e46831539c30..941fe07b58327 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -67,22 +67,22 @@ void runway_sample(size_t size, Callable callable) {
struct X {
X() = delete;
- X(int i) : i(i) {}
+ X(int i) : i_(i) {}
X(const X&) = delete;
- int value() const { return i; }
+ int value() const { return i_; }
private:
- int i;
+ int i_;
};
struct Y {
Y() = delete;
- Y(int i) : i(i) {}
+ Y(int i) : i_(i) {}
Y(const Y&) = delete;
- int value() const { return i; }
+ int value() const { return i_; }
private:
- int i;
+ int i_;
};
bool operator==(const X& lhs, const Y& rhs) { return lhs.value() == rhs.value(); }
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
index 9c0dfc6c0c127..a4b15a56bd071 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
@@ -71,22 +71,22 @@ void runway_sample(size_t size, Callable callable) {
struct X {
X() = delete;
- X(int i) : i(i) {}
+ X(int i) : i_(i) {}
X(const X&) = delete;
- int value() const { return i; }
+ int value() const { return i_; }
private:
- int i;
+ int i_;
};
struct Y {
Y() = delete;
- Y(int i) : i(i) {}
+ Y(int i) : i_(i) {}
Y(const Y&) = delete;
- int value() const { return i; }
+ int value() const { return i_; }
private:
- int i;
+ int i_;
};
struct Pred {
>From a51af3556cdb7f7e24732077b6dce511e3ee9e89 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Tue, 14 Jul 2026 20:27:14 +0100
Subject: [PATCH 11/15] Use raw C array in the tests
---
.../mismatch/pstl.mismatch.pass.cpp | 153 +++++++-------
.../mismatch/pstl.mismatch_pred.pass.cpp | 192 +++++++++++-------
2 files changed, 198 insertions(+), 147 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index 941fe07b58327..17edf34ee7832 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -28,7 +28,6 @@
// ForwardIterator2 last2);
#include <algorithm>
-#include <array>
#include <cassert>
#include <functional>
#include <iterator>
@@ -93,82 +92,98 @@ struct Test {
void operator()(ExecutionPolicy&& policy) {
{
// empty ranges
- std::array<int, 1> lhs = {0};
- std::array<int, 1> rhs = {0};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
+ int lhs[1] = {0};
+ int rhs[1] = {0};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::begin(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs)), Iter2(std::begin(rhs))));
+ assert(
+ std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::begin(lhs)), Iter2(std::begin(rhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs)), Iter2(std::begin(rhs))));
}
{
// single element only
- std::array<int, 1> lhs = {0};
- std::array<int, 1> rhs = {0};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ int lhs[1] = {0};
+ int rhs[1] = {0};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // same range without mismatch
- std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
- std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ int lhs[8] = {0, 1, 2, 3, 0, 1, 2, 3};
+ int rhs[8] = {0, 1, 2, 3, 0, 1, 2, 3};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // same range with mismatch
- std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
- std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
+ int lhs[8] = {0, 1, 2, 2, 0, 1, 2, 3};
+ int rhs[8] = {0, 1, 2, 3, 0, 1, 2, 3};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + 3), Iter2(std::begin(rhs) + 3)));
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + 3), Iter2(std::begin(rhs) + 3)));
}
{ // second range is smaller
- std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
- std::array<int, 2> rhs = {0, 1};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ int lhs[8] = {0, 1, 2, 2, 0, 1, 2, 3};
+ int rhs[2] = {0, 1};
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
}
{ // first range is smaller
- std::array<int, 2> lhs = {0, 1};
- std::array<int, 8> rhs = {0, 1, 2, 2, 0, 1, 2, 3};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ int lhs[2] = {0, 1};
+ int rhs[8] = {0, 1, 2, 2, 0, 1, 2, 3};
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
}
{ // same size, mismatching at various positions
- std::array<int, 1073> lhs;
- std::array<int, 1073> rhs;
+ int lhs[1073];
+ int rhs[1073];
std::iota(std::begin(lhs), std::end(lhs), 0);
- rhs = lhs;
- runway_sample(lhs.size(), [&](size_t i) {
+ std::copy(std::begin(lhs), std::end(lhs), std::begin(rhs));
+ runway_sample(std::size(lhs), [&](size_t i) {
lhs[i] = -1;
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
+ assert(
+ std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
lhs[i] = i;
});
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // same values, different lengths
- std::array<int, 739> lhs;
- std::array<int, 739> rhs;
- lhs.fill(42);
- rhs.fill(42);
- runway_sample(lhs.size(), [&](size_t i) {
+ int lhs[739];
+ int rhs[739];
+ std::fill(std::begin(lhs), std::end(lhs), 42);
+ std::fill(std::begin(rhs), std::end(rhs), 42);
+ runway_sample(std::size(lhs), [&](size_t i) {
// lhs is shorter
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin() + i), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ assert(std::mismatch(
+ policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::begin(lhs) + i),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs))) == std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
// rhs is shorter
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.begin() + i)) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::begin(rhs) + i)) ==
+ std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
});
}
}
@@ -179,20 +194,22 @@ struct TestXY {
template <class ExecutionPolicy>
void operator()(ExecutionPolicy&& policy) {
{ // same ranges
- std::array<X, 3> lhs = {X(1), X(5), X(7)};
- std::array<Y, 3> rhs = {Y(1), Y(5), Y(7)};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ X lhs[3] = {X(1), X(5), X(7)};
+ Y rhs[3] = {Y(1), Y(5), Y(7)};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // one element mismatch
- std::array<X, 3> lhs = {X(1), X(5), X(7)};
- std::array<Y, 3> rhs = {Y(1), Y(5), Y(8)};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin())) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end())) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ X lhs[3] = {X(1), X(5), X(7)};
+ Y rhs[3] = {Y(1), Y(5), Y(8)};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
+ assert(std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Iter2(std::end(rhs))) ==
+ std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
}
}
};
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
index a4b15a56bd071..18c4fe1abad0c 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
@@ -32,7 +32,6 @@
// BinaryPredicate pred);
#include <algorithm>
-#include <array>
#include <cassert>
#include <functional>
#include <iterator>
@@ -100,91 +99,120 @@ struct Test {
void operator()(ExecutionPolicy&& policy) {
{
// empty ranges
- std::array<int, 1> lhs = {0};
- std::array<int, 1> rhs = {0};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
- assert(std::mismatch(
- policy, Iter1(lhs.begin()), Iter1(lhs.begin()), Iter2(rhs.begin()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin()), Iter2(rhs.begin())));
+ int lhs[1] = {0};
+ int rhs[1] = {0};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::begin(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::begin(lhs)), Iter2(std::begin(rhs))));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::begin(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::begin(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs)), Iter2(std::begin(rhs))));
}
{
// single element only
- std::array<int, 1> lhs = {1};
- std::array<int, 1> rhs = {2};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ int lhs[1] = {1};
+ int rhs[1] = {2};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // same range without mismatch
- std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
- std::array<int, 8> rhs = {0, 2, 4, 6, 0, 2, 4, 6};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ int lhs[8] = {0, 1, 2, 3, 0, 1, 2, 3};
+ int rhs[8] = {0, 2, 4, 6, 0, 2, 4, 6};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // same range with mismatch
- std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3};
- std::array<int, 8> rhs = {0, 2, 4, 7, 0, 2, 4, 6};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + 3), Iter2(rhs.begin() + 3)));
+ int lhs[8] = {0, 1, 2, 3, 0, 1, 2, 3};
+ int rhs[8] = {0, 2, 4, 7, 0, 2, 4, 6};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::begin(lhs) + 3), Iter2(std::begin(rhs) + 3)));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs) + 3), Iter2(std::begin(rhs) + 3)));
}
{ // second range is smaller
- std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3};
- std::array<int, 2> rhs = {0, 2};
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ int lhs[8] = {0, 1, 2, 2, 0, 1, 2, 3};
+ int rhs[2] = {0, 2};
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
}
{ // first range is smaller
- std::array<int, 2> lhs = {0, 1};
- std::array<int, 8> rhs = {0, 2, 2, 2, 0, 1, 2, 3};
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ int lhs[2] = {0, 1};
+ int rhs[8] = {0, 2, 2, 2, 0, 1, 2, 3};
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
}
{ // same size, mismatching at various positions
- std::array<int, 1073> lhs;
- std::array<int, 1073> rhs;
+ int lhs[1073];
+ int rhs[1073];
std::iota(std::begin(lhs), std::end(lhs), 0);
- rhs = lhs;
- std::for_each(std::begin(rhs), std::end(rhs), [](int& x) { x *= 2; });
- runway_sample(lhs.size(), [&](size_t i) {
+ std::transform(std::begin(lhs), std::end(lhs), std::begin(rhs), [](int x) { return x * 2; });
+ runway_sample(std::size(lhs), [&](size_t i) {
lhs[i] = -1;
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
lhs[i] = i;
});
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // same values, different lengths
- std::array<int, 739> lhs;
- std::array<int, 739> rhs;
- lhs.fill(42);
- rhs.fill(84);
- runway_sample(lhs.size(), [&](size_t i) {
+ int lhs[739];
+ int rhs[739];
+ std::fill(std::begin(lhs), std::end(lhs), 42);
+ std::fill(std::begin(rhs), std::end(rhs), 84);
+ runway_sample(std::size(lhs), [&](size_t i) {
// lhs is shorter
- assert(std::mismatch(
- policy, Iter1(lhs.begin()), Iter1(lhs.begin() + i), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::begin(lhs) + i),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
// rhs is shorter
- assert(std::mismatch(
- policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.begin() + i), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + i), Iter2(rhs.begin() + i)));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::begin(rhs) + i),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs) + i), Iter2(std::begin(rhs) + i)));
});
}
}
@@ -195,22 +223,28 @@ struct TestXY {
template <class ExecutionPolicy>
void operator()(ExecutionPolicy&& policy) {
{ // same ranges
- std::array<X, 3> lhs = {X(1), X(5), X(7)};
- std::array<Y, 3> rhs = {Y(2), Y(10), Y(14)};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.end()), Iter2(rhs.end())));
+ X lhs[3] = {X(1), X(5), X(7)};
+ Y rhs[3] = {Y(2), Y(10), Y(14)};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::end(lhs)), Iter2(std::end(rhs))));
}
{ // one element mismatch
- std::array<X, 3> lhs = {X(1), X(5), X(7)};
- std::array<Y, 3> rhs = {Y(2), Y(10), Y(13)};
- assert(std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
- assert(
- std::mismatch(policy, Iter1(lhs.begin()), Iter1(lhs.end()), Iter2(rhs.begin()), Iter2(rhs.end()), Pred{}) ==
- std::make_pair(Iter1(lhs.begin() + 2), Iter2(rhs.begin() + 2)));
+ X lhs[3] = {X(1), X(5), X(7)};
+ Y rhs[3] = {Y(2), Y(10), Y(13)};
+ assert(std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::end(lhs)), Iter2(std::begin(rhs)), Pred{}) ==
+ std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
+ assert(std::mismatch(policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::end(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::end(rhs)),
+ Pred{}) == std::make_pair(Iter1(std::begin(lhs) + 2), Iter2(std::begin(rhs) + 2)));
}
}
};
>From f3bfa5528fb2aea972a018cc68e56133e32db99b Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Tue, 14 Jul 2026 21:08:55 +0100
Subject: [PATCH 12/15] Fixed typos in the comment
---
.../algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp | 2 +-
.../alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index 17edf34ee7832..ed59fa9eca669 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -46,7 +46,7 @@ static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*,
static_assert(sfinae_test_mismatch<int, int*, int*, int*, int*>);
static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, int*>);
-// TODO: switch with a shared implemented once it's merged into main
+// TODO: switch to the shared implementation once it's merged into main
template <class Callable>
void runway_sample(size_t size, Callable callable) {
constexpr size_t affix = 16;
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
index 18c4fe1abad0c..338503d784a31 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
@@ -50,7 +50,7 @@ static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*,
static_assert(sfinae_test_mismatch<int, int*, int*, int*, int*, bool (*)(int, int)>);
static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, int*, bool (*)(int, int)>);
-// TODO: switch with a shared implemented once it's merged into main
+// TODO: switch to the shared implementation once it's merged into main
template <class Callable>
void runway_sample(size_t size, Callable callable) {
constexpr size_t affix = 16;
>From 4c7fccd82c3a4bea33038c9eee3ebcefddd7f230 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Wed, 15 Jul 2026 21:43:20 +0100
Subject: [PATCH 13/15] Added comments explaining what the parameters mean
---
libcxx/include/__pstl/cpu_algos/mismatch.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__pstl/cpu_algos/mismatch.h b/libcxx/include/__pstl/cpu_algos/mismatch.h
index 597a47fb185c8..3d702b03d3afe 100644
--- a/libcxx/include/__pstl/cpu_algos/mismatch.h
+++ b/libcxx/include/__pstl/cpu_algos/mismatch.h
@@ -63,8 +63,9 @@ struct __cpu_parallel_mismatch {
return std::mismatch(std::move(__brick_first1), std::move(__brick_last1), std::move(__brick_first2), __pred)
.first;
},
- less<>{},
- true);
+ less<>{}, // `less` here means the lowest index among the mismatches
+ true // `true` here means we want the first mismatch, not the last
+ );
if (!__res) {
return std::nullopt; // Failed to run the algorithm, propagate the error.
}
>From 22dfeede2c12c49a9f57db064f80e6d24e96f41b Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Wed, 15 Jul 2026 21:50:51 +0100
Subject: [PATCH 14/15] Added tests of the return types
---
.../mismatch/pstl.mismatch.pass.cpp | 10 ++++++++++
.../mismatch/pstl.mismatch_pred.pass.cpp | 16 ++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index ed59fa9eca669..cc7ef6feb2356 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -90,6 +90,16 @@ template <class Iter1, class Iter2>
struct Test {
template <class ExecutionPolicy>
void operator()(ExecutionPolicy&& policy) {
+ {
+ // check the return types
+ int lhs[1] = {0};
+ int rhs[1] = {0};
+ auto res_3legged = std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::begin(lhs)), Iter2(std::begin(rhs)));
+ auto res_4legged = std::mismatch(
+ policy, Iter1(std::begin(lhs)), Iter1(std::begin(lhs)), Iter2(std::begin(rhs)), Iter2(std::begin(rhs)));
+ static_assert(std::is_same_v<decltype(res_3legged), std::pair<Iter1, Iter2>>);
+ static_assert(std::is_same_v<decltype(res_4legged), std::pair<Iter1, Iter2>>);
+ }
{
// empty ranges
int lhs[1] = {0};
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
index 338503d784a31..d80da0cf0b542 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
@@ -97,6 +97,22 @@ template <class Iter1, class Iter2>
struct Test {
template <class ExecutionPolicy>
void operator()(ExecutionPolicy&& policy) {
+ {
+ // check the return types
+ int lhs[1] = {0};
+ int rhs[1] = {0};
+ auto res_3legged =
+ std::mismatch(policy, Iter1(std::begin(lhs)), Iter1(std::begin(lhs)), Iter2(std::begin(rhs)), Pred{});
+ auto res_4legged = std::mismatch(
+ policy,
+ Iter1(std::begin(lhs)),
+ Iter1(std::begin(lhs)),
+ Iter2(std::begin(rhs)),
+ Iter2(std::begin(rhs)),
+ Pred{});
+ static_assert(std::is_same_v<decltype(res_3legged), std::pair<Iter1, Iter2>>);
+ static_assert(std::is_same_v<decltype(res_4legged), std::pair<Iter1, Iter2>>);
+ }
{
// empty ranges
int lhs[1] = {0};
>From 8f9ddba49cfc2b501d8d42b1c8027f64b0695a31 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Tue, 21 Jul 2026 19:39:00 +0100
Subject: [PATCH 15/15] Rebased on support/runway_sample.h
---
.../mismatch/pstl.mismatch.pass.cpp | 17 +----------------
.../mismatch/pstl.mismatch_pred.pass.cpp | 17 +----------------
2 files changed, 2 insertions(+), 32 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
index cc7ef6feb2356..83f4b0f16d6c1 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch.pass.cpp
@@ -38,6 +38,7 @@
#include "test_iterators.h"
#include "test_macros.h"
#include "type_algorithms.h"
+#include "runway_sample.h"
EXECUTION_POLICY_SFINAE_TEST(mismatch);
@@ -46,22 +47,6 @@ static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*,
static_assert(sfinae_test_mismatch<int, int*, int*, int*, int*>);
static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, int*>);
-// TODO: switch to the shared implementation once it's merged into main
-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);
- }
-}
-
// The types X and Y are provided to test that the mismatch algorithm can be used with heterogeneous custom types.
struct X {
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
index d80da0cf0b542..89cf899a47b4c 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/pstl.mismatch_pred.pass.cpp
@@ -42,6 +42,7 @@
#include "test_iterators.h"
#include "test_macros.h"
#include "type_algorithms.h"
+#include "runway_sample.h"
EXECUTION_POLICY_SFINAE_TEST(mismatch);
@@ -50,22 +51,6 @@ static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*,
static_assert(sfinae_test_mismatch<int, int*, int*, int*, int*, bool (*)(int, int)>);
static_assert(!sfinae_test_mismatch<std::execution::parallel_policy, int*, int*, int*, int*, bool (*)(int, int)>);
-// TODO: switch to the shared implementation once it's merged into main
-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);
- }
-}
-
// The types X and Y are provided to test that the mismatch algorithm can be used with heterogeneous custom types.
struct X {
More information about the libcxx-commits
mailing list