• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #855

20 Dec 2022 09:59PM UTC coverage: 86.55% (+0.04%) from 86.511%
#855

push

StellarBot
Merge #6112

6112: Modernize modules from levels 9 and 10 r=hkaiser a=hkaiser

working towards https://github.com/STEllAR-GROUP/hpx/issues/5497

Co-authored-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>

185 of 185 new or added lines in 30 files covered. (100.0%)

174495 of 201611 relevant lines covered (86.55%)

1898061.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.92
/libs/core/algorithms/include/hpx/parallel/algorithms/mismatch.hpp
1
//  Copyright (c) 2022 Bhumit Attarde
2
//  Copyright (c) 2007-2022 Hartmut Kaiser
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
/// \file parallel/algorithms/mismatch.hpp
9

10
#pragma once
11

12
#if defined(DOXYGEN)
13
namespace hpx {
14
    // clang-format off
15

16
    /// Returns the first mismatching pair of elements from two ranges: one
17
    /// defined by [first1, last1) and another defined by [first2,last2). If
18
    /// last2 is not provided, it denotes first2 + (last1 - first1).
19
    /// Executed according to the policy.
20
    ///
21
    /// \note   Complexity: At most min(last1 - first1, last2 - first2)
22
    ///         applications of the predicate \a op or \a operator==.
23
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
24
    ///         \a RandomAccessIterator and
25
    ///         (last1 - first1) != (last2 - first2) then no applications
26
    ///         of the predicate \a op or \a operator== are made.
27
    ///
28
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
29
    ///                     It describes the manner in which the execution
30
    ///                     of the algorithm may be parallelized and the manner
31
    ///                     in which it executes the assignments.
32
    /// \tparam FwdIter1    The type of the source iterators used for the
33
    ///                     first range (deduced).
34
    ///                     This iterator type must meet the requirements of an
35
    ///                     forward iterator.
36
    /// \tparam FwdIter2    The type of the source iterators used for the
37
    ///                     second range (deduced).
38
    ///                     This iterator type must meet the requirements of an
39
    ///                     forward iterator.
40
    /// \tparam Pred        The type of an optional function/function object to use.
41
    ///                     Unlike its sequential form, the parallel
42
    ///                     overload of \a mismatch requires \a Pred to meet the
43
    ///                     requirements of \a CopyConstructible. This defaults
44
    ///                     to std::equal_to<>
45
    ///
46
    /// \param policy       The execution policy to use for the scheduling of
47
    ///                     the iterations.
48
    /// \param first1       Refers to the beginning of the sequence of elements
49
    ///                     of the first range the algorithm will be applied to.
50
    /// \param last1        Refers to the end of the sequence of elements of
51
    ///                     the first range the algorithm will be applied to.
52
    /// \param first2       Refers to the beginning of the sequence of elements
53
    ///                     of the second range the algorithm will be applied to.
54
    /// \param last2        Refers to the end of the sequence of elements of
55
    ///                     the second range the algorithm will be applied to.
56
    /// \param op           The binary predicate which returns true if the
57
    ///                     elements should be treated as mismatch. The signature
58
    ///                     of the predicate function should be equivalent to
59
    ///                     the following:
60
    ///                     \code
61
    ///                     bool pred(const Type1 &a, const Type2 &b);
62
    ///                     \endcode \n
63
    ///                     The signature does not need to have const &, but
64
    ///                     the function must not modify the objects passed to
65
    ///                     it. The types \a Type1 and \a Type2 must be such
66
    ///                     that objects of types \a FwdIter1 and \a FwdIter2 can
67
    ///                     be dereferenced and then implicitly converted to
68
    ///                     \a Type1 and \a Type2 respectively
69
    ///
70
    /// The comparison operations in the parallel \a mismatch algorithm invoked
71
    /// with an execution policy object of type \a sequenced_policy
72
    /// execute in sequential order in the calling thread.
73
    ///
74
    /// The comparison operations in the parallel \a mismatch algorithm invoked
75
    /// with an execution policy object of type \a parallel_policy
76
    /// or \a parallel_task_policy are permitted to execute in an unordered
77
    /// fashion in unspecified threads, and indeterminately sequenced
78
    /// within each thread.
79
    ///
80
    /// \note     The two ranges are considered mismatch if, for every iterator
81
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
82
    ///           This overload of mismatch uses operator== to determine if two
83
    ///           elements are mismatch.
84
    ///
85
    /// \returns  The \a mismatch algorithm returns a
86
    ///           \a hpx::future<std::pair<FwdIter1,FwdIter2>>
87
    ///           if the execution policy is of type \a sequenced_task_policy or
88
    ///           \a parallel_task_policy and
89
    ///           returns \a std::pair<FwdIter1,FwdIter2> otherwise.
90
    ///           If no mismatches are found when the comparison reaches last1
91
    ///           or last2, whichever happens first, the pair holds the end
92
    ///           iterator and the corresponding iterator from the other range.
93
    ///
94
    template <typename ExPolicy, typename FwdIter1, typename FwdIter2,
95
        typename Pred>
96
    hpx::parallel::util::detail::algorithm_result_t
97
        <ExPolicy, std::pair<FwdIter1, FwdIter2>>
98
    mismatch(ExPolicy&& policy, FwdIter1 first1, FwdIter1 last1,
99
            FwdIter2 first2, FwdIter2 last2, Pred&& op);
100

101
    /// Returns the first mismatching pair of elements from two ranges: one
102
    /// defined by [first1, last1) and another defined by [first2,last2). If
103
    /// last2 is not provided, it denotes first2 + (last1 - first1).
104
    /// Executed according to the policy.
105
    ///
106
    /// \note   Complexity: At most min(last1 - first1, last2 - first2)
107
    ///         applications of \a operator==.
108
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
109
    ///         \a RandomAccessIterator and
110
    ///         (last1 - first1) != (last2 - first2) then no applications
111
    ///         of \a operator== are made.
112
    ///
113
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
114
    ///                     It describes the manner in which the execution
115
    ///                     of the algorithm may be parallelized and the manner
116
    ///                     in which it executes the assignments.
117
    /// \tparam FwdIter1    The type of the source iterators used for the
118
    ///                     first range (deduced).
119
    ///                     This iterator type must meet the requirements of an
120
    ///                     forward iterator.
121
    /// \tparam FwdIter2    The type of the source iterators used for the
122
    ///                     second range (deduced).
123
    ///                     This iterator type must meet the requirements of an
124
    ///                     forward iterator.
125
    ///
126
    /// \param policy       The execution policy to use for the scheduling of
127
    ///                     the iterations.
128
    /// \param first1       Refers to the beginning of the sequence of elements
129
    ///                     of the first range the algorithm will be applied to.
130
    /// \param last1        Refers to the end of the sequence of elements of
131
    ///                     the first range the algorithm will be applied to.
132
    /// \param first2       Refers to the beginning of the sequence of elements
133
    ///                     of the second range the algorithm will be applied to.
134
    /// \param last2        Refers to the end of the sequence of elements of
135
    ///                     the second range the algorithm will be applied to.
136
    ///
137
    /// The comparison operations in the parallel \a mismatch algorithm invoked
138
    /// with an execution policy object of type \a sequenced_policy
139
    /// execute in sequential order in the calling thread.
140
    ///
141
    /// The comparison operations in the parallel \a mismatch algorithm invoked
142
    /// with an execution policy object of type \a parallel_policy
143
    /// or \a parallel_task_policy are permitted to execute in an unordered
144
    /// fashion in unspecified threads, and indeterminately sequenced
145
    /// within each thread.
146
    ///
147
    /// \note     The two ranges are considered mismatch if, for every iterator
148
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
149
    ///           This overload of mismatch uses operator== to determine if two
150
    ///           elements are mismatch.
151
    ///
152
    /// \returns  The \a mismatch algorithm returns a
153
    ///           \a hpx::future<std::pair<FwdIter1,FwdIter2>>
154
    ///           if the execution policy is of type \a sequenced_task_policy or
155
    ///           \a parallel_task_policy and
156
    ///           returns \a std::pair<FwdIter1,FwdIter2> otherwise.
157
    ///           If no mismatches are found when the comparison reaches last1
158
    ///           or last2, whichever happens first, the pair holds the end
159
    ///           iterator and the corresponding iterator from the other range.
160
    ///
161
    template <typename ExPolicy, typename FwdIter1, typename FwdIter2>
162
    hpx::parallel::util::detail::algorithm_result_t
163
        <ExPolicy, std::pair<FwdIter1, FwdIter2>>
164
    mismatch(ExPolicy&& policy, FwdIter1 first1, FwdIter1 last1,
165
            FwdIter2 first2, FwdIter2 last2);
166

167
    /// Returns the first mismatching pair of elements from two ranges: one
168
    /// defined by [first1, last1) and another defined by [first2,last2). If
169
    /// last2 is not provided, it denotes first2 + (last1 - first1).
170
    /// Executed according to the policy.
171
    ///
172
    /// \note   Complexity: At most last1 - first1
173
    ///         applications of the predicate \a op or \a operator==.
174
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
175
    ///         \a RandomAccessIterator and
176
    ///         (last1 - first1) != (last2 - first2) then no applications
177
    ///         of the predicate \a op or \a operator== are made.
178
    ///
179
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
180
    ///                     It describes the manner in which the execution
181
    ///                     of the algorithm may be parallelized and the manner
182
    ///                     in which it executes the assignments.
183
    /// \tparam FwdIter1    The type of the source iterators used for the
184
    ///                     first range (deduced).
185
    ///                     This iterator type must meet the requirements of an
186
    ///                     forward iterator.
187
    /// \tparam FwdIter2    The type of the source iterators used for the
188
    ///                     second range (deduced).
189
    ///                     This iterator type must meet the requirements of an
190
    ///                     forward iterator.
191
    /// \tparam Pred        The type of an optional function/function object to use.
192
    ///                     Unlike its sequential form, the parallel
193
    ///                     overload of \a mismatch requires \a Pred to meet the
194
    ///                     requirements of \a CopyConstructible. This defaults
195
    ///                     to std::equal_to<>
196
    ///
197
    /// \param policy       The execution policy to use for the scheduling of
198
    ///                     the iterations.
199
    /// \param first1       Refers to the beginning of the sequence of elements
200
    ///                     of the first range the algorithm will be applied to.
201
    /// \param last1        Refers to the end of the sequence of elements of
202
    ///                     the first range the algorithm will be applied to.
203
    /// \param first2       Refers to the beginning of the sequence of elements
204
    ///                     of the second range the algorithm will be applied to.
205
    /// \param op           The binary predicate which returns true if the
206
    ///                     elements should be treated as mismatch. The signature
207
    ///                     of the predicate function should be equivalent to
208
    ///                     the following:
209
    ///                     \code
210
    ///                     bool pred(const Type1 &a, const Type2 &b);
211
    ///                     \endcode \n
212
    ///                     The signature does not need to have const &, but
213
    ///                     the function must not modify the objects passed to
214
    ///                     it. The types \a Type1 and \a Type2 must be such
215
    ///                     that objects of types \a FwdIter1 and \a FwdIter2 can
216
    ///                     be dereferenced and then implicitly converted to
217
    ///                     \a Type1 and \a Type2 respectively
218
    ///
219
    /// The comparison operations in the parallel \a mismatch algorithm invoked
220
    /// with an execution policy object of type \a sequenced_policy
221
    /// execute in sequential order in the calling thread.
222
    ///
223
    /// The comparison operations in the parallel \a mismatch algorithm invoked
224
    /// with an execution policy object of type \a parallel_policy
225
    /// or \a parallel_task_policy are permitted to execute in an unordered
226
    /// fashion in unspecified threads, and indeterminately sequenced
227
    /// within each thread.
228
    ///
229
    /// \note     The two ranges are considered mismatch if, for every iterator
230
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
231
    ///           This overload of mismatch uses operator== to determine if two
232
    ///           elements are mismatch.
233
    ///
234
    /// \returns  The \a mismatch algorithm returns a
235
    ///           \a hpx::future<std::pair<FwdIter1,FwdIter2>>
236
    ///           if the execution policy is of type \a sequenced_task_policy or
237
    ///           \a parallel_task_policy and
238
    ///           returns \a std::pair<FwdIter1,FwdIter2> otherwise.
239
    ///           If no mismatches are found when the comparison reaches last1
240
    ///           or last2, whichever happens first, the pair holds the end
241
    ///           iterator and the corresponding iterator from the other range.
242
    ///
243
    template <typename ExPolicy, typename FwdIter1, typename FwdIter2,
244
        typename Pred>
245
    hpx::parallel::util::detail::algorithm_result_t
246
        <ExPolicy, std::pair<FwdIter1, FwdIter2>>
247
    mismatch(ExPolicy&& policy, FwdIter1 first1, FwdIter1 last1,
248
            FwdIter2 first2, Pred&& op);
249

250
    /// Returns the first mismatching pair of elements from two ranges: one
251
    /// defined by [first1, last1) and another defined by [first2,last2). If
252
    /// last2 is not provided, it denotes first2 + (last1 - first1).
253
    /// Executed according to the policy.
254
    ///
255
    /// \note   Complexity: At most last1 - first1
256
    ///         applications of \a operator==.
257
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
258
    ///         \a RandomAccessIterator and
259
    ///         (last1 - first1) != (last2 - first2) then no applications
260
    ///         of \a operator== are made.
261
    ///
262
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
263
    ///                     It describes the manner in which the execution
264
    ///                     of the algorithm may be parallelized and the manner
265
    ///                     in which it executes the assignments.
266
    /// \tparam FwdIter1    The type of the source iterators used for the
267
    ///                     first range (deduced).
268
    ///                     This iterator type must meet the requirements of an
269
    ///                     forward iterator.
270
    /// \tparam FwdIter2    The type of the source iterators used for the
271
    ///                     second range (deduced).
272
    ///                     This iterator type must meet the requirements of an
273
    ///                     forward iterator.
274
    /// \tparam Pred        The type of an optional function/function object to use.
275
    ///                     Unlike its sequential form, the parallel
276
    ///                     overload of \a mismatch requires \a Pred to meet the
277
    ///                     requirements of \a CopyConstructible. This defaults
278
    ///                     to std::equal_to<>
279
    ///
280
    /// \param policy       The execution policy to use for the scheduling of
281
    ///                     the iterations.
282
    /// \param first1       Refers to the beginning of the sequence of elements
283
    ///                     of the first range the algorithm will be applied to.
284
    /// \param last1        Refers to the end of the sequence of elements of
285
    ///                     the first range the algorithm will be applied to.
286
    /// \param first2       Refers to the beginning of the sequence of elements
287
    ///                     of the second range the algorithm will be applied to.
288
    ///
289
    /// The comparison operations in the parallel \a mismatch algorithm invoked
290
    /// with an execution policy object of type \a sequenced_policy
291
    /// execute in sequential order in the calling thread.
292
    ///
293
    /// The comparison operations in the parallel \a mismatch algorithm invoked
294
    /// with an execution policy object of type \a parallel_policy
295
    /// or \a parallel_task_policy are permitted to execute in an unordered
296
    /// fashion in unspecified threads, and indeterminately sequenced
297
    /// within each thread.
298
    ///
299
    /// \note     The two ranges are considered mismatch if, for every iterator
300
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
301
    ///           This overload of mismatch uses operator== to determine if two
302
    ///           elements are mismatch.
303
    ///
304
    /// \returns  The \a mismatch algorithm returns a
305
    ///           \a hpx::future<std::pair<FwdIter1,FwdIter2>>
306
    ///           if the execution policy is of type \a sequenced_task_policy or
307
    ///           \a parallel_task_policy and
308
    ///           returns \a std::pair<FwdIter1,FwdIter2> otherwise.
309
    ///           If no mismatches are found when the comparison reaches last1
310
    ///           or last2, whichever happens first, the pair holds the end
311
    ///           iterator and the corresponding iterator from the other range.
312
    ///
313
    template <typename ExPolicy, typename FwdIter1, typename FwdIter2>
314
    hpx::parallel::util::detail::algorithm_result_t
315
        <ExPolicy, std::pair<FwdIter1, FwdIter2>>
316
    mismatch(ExPolicy&& policy, FwdIter1 first1, FwdIter1 last1,
317
            FwdIter2 first2);
318

319
    /// Returns the first mismatching pair of elements from two ranges: one
320
    /// defined by [first1, last1) and another defined by [first2,last2). If
321
    /// last2 is not provided, it denotes first2 + (last1 - first1).
322
    ///
323
    /// \note   Complexity: At most min(last1 - first1, last2 - first2)
324
    ///         applications of the predicate \a op or \a operator==.
325
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
326
    ///         \a RandomAccessIterator and
327
    ///         (last1 - first1) != (last2 - first2) then no applications
328
    ///         of the predicate \a op or \a operator== are made.
329
    ///
330
    /// \tparam FwdIter1    The type of the source iterators used for the
331
    ///                     first range (deduced).
332
    ///                     This iterator type must meet the requirements of an
333
    ///                     forward iterator.
334
    /// \tparam FwdIter2    The type of the source iterators used for the
335
    ///                     second range (deduced).
336
    ///                     This iterator type must meet the requirements of an
337
    ///                     forward iterator.
338
    /// \tparam Pred        The type of an optional function/function object to use.
339
    ///                     Unlike its sequential form, the parallel
340
    ///                     overload of \a mismatch requires \a Pred to meet the
341
    ///                     requirements of \a CopyConstructible. This defaults
342
    ///                     to std::equal_to<>
343
    ///
344
    /// \param first1       Refers to the beginning of the sequence of elements
345
    ///                     of the first range the algorithm will be applied to.
346
    /// \param last1        Refers to the end of the sequence of elements of
347
    ///                     the first range the algorithm will be applied to.
348
    /// \param first2       Refers to the beginning of the sequence of elements
349
    ///                     of the second range the algorithm will be applied to.
350
    /// \param last2        Refers to the end of the sequence of elements of
351
    ///                     the second range the algorithm will be applied to.
352
    /// \param op           The binary predicate which returns true if the
353
    ///                     elements should be treated as mismatch. The signature
354
    ///                     of the predicate function should be equivalent to
355
    ///                     the following:
356
    ///                     \code
357
    ///                     bool pred(const Type1 &a, const Type2 &b);
358
    ///                     \endcode \n
359
    ///                     The signature does not need to have const &, but
360
    ///                     the function must not modify the objects passed to
361
    ///                     it. The types \a Type1 and \a Type2 must be such
362
    ///                     that objects of types \a FwdIter1 and \a FwdIter2 can
363
    ///                     be dereferenced and then implicitly converted to
364
    ///                     \a Type1 and \a Type2 respectively
365
    ///
366
    /// \note     The two ranges are considered mismatch if, for every iterator
367
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
368
    ///           This overload of mismatch uses operator== to determine if two
369
    ///           elements are mismatch.
370
    ///
371
    /// \returns  The \a mismatch algorithm returns a
372
    ///           \a std::pair<FwdIter1,FwdIter2>.
373
    ///           If no mismatches are found when the comparison reaches last1
374
    ///           or last2, whichever happens first, the pair holds the end
375
    ///           iterator and the corresponding iterator from the other range.
376
    ///
377
    template <typename FwdIter1, typename FwdIter2,
378
        typename Pred>
379
    std::pair<FwdIter1, FwdIter2> mismatch(FwdIter1 first1, FwdIter1 last1,
380
            FwdIter2 first2, FwdIter2 last2, Pred&& op);
381

382
    /// Returns the first mismatching pair of elements from two ranges: one
383
    /// defined by [first1, last1) and another defined by [first2,last2). If
384
    /// last2 is not provided, it denotes first2 + (last1 - first1).
385
    ///
386
    /// \note   Complexity: At most min(last1 - first1, last2 - first2)
387
    ///         applications of \a operator==.
388
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
389
    ///         \a RandomAccessIterator and
390
    ///         (last1 - first1) != (last2 - first2) then no applications
391
    ///         of \a operator== are made.
392
    ///
393
    /// \tparam FwdIter1    The type of the source iterators used for the
394
    ///                     first range (deduced).
395
    ///                     This iterator type must meet the requirements of an
396
    ///                     forward iterator.
397
    /// \tparam FwdIter2    The type of the source iterators used for the
398
    ///                     second range (deduced).
399
    ///                     This iterator type must meet the requirements of an
400
    ///                     forward iterator.
401
    ///
402
    /// \param first1       Refers to the beginning of the sequence of elements
403
    ///                     of the first range the algorithm will be applied to.
404
    /// \param last1        Refers to the end of the sequence of elements of
405
    ///                     the first range the algorithm will be applied to.
406
    /// \param first2       Refers to the beginning of the sequence of elements
407
    ///                     of the second range the algorithm will be applied to.
408
    /// \param last2        Refers to the end of the sequence of elements of
409
    ///                     the second range the algorithm will be applied to.
410
    ///
411
    /// \note     The two ranges are considered mismatch if, for every iterator
412
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
413
    ///           This overload of mismatch uses operator== to determine if two
414
    ///           elements are mismatch.
415
    ///
416
    /// \returns  The \a mismatch algorithm returns a
417
    ///           \a std::pair<FwdIter1,FwdIter2>.
418
    ///           If no mismatches are found when the comparison reaches last1
419
    ///           or last2, whichever happens first, the pair holds the end
420
    ///           iterator and the corresponding iterator from the other range.
421
    ///
422
    template <typename FwdIter1, typename FwdIter2>
423
    std::pair<FwdIter1, FwdIter2> mismatch(FwdIter1 first1, FwdIter1 last1,
424
            FwdIter2 first2, FwdIter2 last2);
425

426
    /// Returns the first mismatching pair of elements from two ranges: one
427
    /// defined by [first1, last1) and another defined by [first2,last2). If
428
    /// last2 is not provided, it denotes first2 + (last1 - first1).
429
    ///
430
    /// \note   Complexity: At most last1 - first1
431
    ///         applications of the predicate \a op or \a operator==.
432
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
433
    ///         \a RandomAccessIterator and
434
    ///         (last1 - first1) != (last2 - first2) then no applications
435
    ///         of the predicate \a op or \a operator== are made.
436
    ///
437
    /// \tparam FwdIter1    The type of the source iterators used for the
438
    ///                     first range (deduced).
439
    ///                     This iterator type must meet the requirements of an
440
    ///                     forward iterator.
441
    /// \tparam FwdIter2    The type of the source iterators used for the
442
    ///                     second range (deduced).
443
    ///                     This iterator type must meet the requirements of an
444
    ///                     forward iterator.
445
    /// \tparam Pred        The type of an optional function/function object to use.
446
    ///                     Unlike its sequential form, the parallel
447
    ///                     overload of \a mismatch requires \a Pred to meet the
448
    ///                     requirements of \a CopyConstructible. This defaults
449
    ///                     to std::equal_to<>
450
    ///
451
    /// \param first1       Refers to the beginning of the sequence of elements
452
    ///                     of the first range the algorithm will be applied to.
453
    /// \param last1        Refers to the end of the sequence of elements of
454
    ///                     the first range the algorithm will be applied to.
455
    /// \param first2       Refers to the beginning of the sequence of elements
456
    ///                     of the second range the algorithm will be applied to.
457
    /// \param op           The binary predicate which returns true if the
458
    ///                     elements should be treated as mismatch. The signature
459
    ///                     of the predicate function should be equivalent to
460
    ///                     the following:
461
    ///                     \code
462
    ///                     bool pred(const Type1 &a, const Type2 &b);
463
    ///                     \endcode \n
464
    ///                     The signature does not need to have const &, but
465
    ///                     the function must not modify the objects passed to
466
    ///                     it. The types \a Type1 and \a Type2 must be such
467
    ///                     that objects of types \a FwdIter1 and \a FwdIter2 can
468
    ///                     be dereferenced and then implicitly converted to
469
    ///                     \a Type1 and \a Type2 respectively
470
    ///
471
    /// \note     The two ranges are considered mismatch if, for every iterator
472
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
473
    ///           This overload of mismatch uses operator== to determine if two
474
    ///           elements are mismatch.
475
    ///
476
    /// \returns  The \a mismatch algorithm returns a
477
    ///           \a std::pair<FwdIter1,FwdIter2>.
478
    ///           If no mismatches are found when the comparison reaches last1
479
    ///           or last2, whichever happens first, the pair holds the end
480
    ///           iterator and the corresponding iterator from the other range.
481
    ///
482
    template <typename FwdIter1, typename FwdIter2,
483
        typename Pred>
484
    std::pair<FwdIter1, FwdIter2> mismatch(FwdIter1 first1, FwdIter1 last1,
485
            FwdIter2 first2, Pred&& op);
486

487
    /// Returns the first mismatching pair of elements from two ranges: one
488
    /// defined by [first1, last1) and another defined by [first2,last2). If
489
    /// last2 is not provided, it denotes first2 + (last1 - first1).
490
    ///
491
    /// \note   Complexity: At most last1 - first1
492
    ///         applications of \a operator==.
493
    ///         If \a FwdIter1 and \a FwdIter2 meet the requirements of
494
    ///         \a RandomAccessIterator and
495
    ///         (last1 - first1) != (last2 - first2) then no applications
496
    ///         of \a operator== are made.
497
    ///
498
    /// \tparam FwdIter1    The type of the source iterators used for the
499
    ///                     first range (deduced).
500
    ///                     This iterator type must meet the requirements of an
501
    ///                     forward iterator.
502
    /// \tparam FwdIter2    The type of the source iterators used for the
503
    ///                     second range (deduced).
504
    ///                     This iterator type must meet the requirements of an
505
    ///                     forward iterator.
506
    /// \tparam Pred        The type of an optional function/function object to use.
507
    ///                     Unlike its sequential form, the parallel
508
    ///                     overload of \a mismatch requires \a Pred to meet the
509
    ///                     requirements of \a CopyConstructible. This defaults
510
    ///                     to std::equal_to<>
511
    ///
512
    /// \param first1       Refers to the beginning of the sequence of elements
513
    ///                     of the first range the algorithm will be applied to.
514
    /// \param last1        Refers to the end of the sequence of elements of
515
    ///                     the first range the algorithm will be applied to.
516
    /// \param first2       Refers to the beginning of the sequence of elements
517
    ///                     of the second range the algorithm will be applied to.
518
    ///
519
    /// \note     The two ranges are considered mismatch if, for every iterator
520
    ///           i in the range [first1,last1), *i mismatchs *(first2 + (i - first1)).
521
    ///           This overload of mismatch uses operator== to determine if two
522
    ///           elements are mismatch.
523
    ///
524
    /// \returns  The \a mismatch algorithm returns a
525
    ///           \a std::pair<FwdIter1,FwdIter2>.
526
    ///           If no mismatches are found when the comparison reaches last1
527
    ///           or last2, whichever happens first, the pair holds the end
528
    ///           iterator and the corresponding iterator from the other range.
529
    ///
530
    template <typename FwdIter1, typename FwdIter2>
531
    std::pair<FwdIter1, FwdIter2> mismatch(FwdIter1 first1,
532
        FwdIter1 last1, FwdIter2 first2);
533

534
    // clang-format on
535
}    // namespace hpx
536

537
#else    // DOXYGEN
538

539
#include <hpx/config.hpp>
540
#include <hpx/coroutines/thread_enums.hpp>
541
#include <hpx/execution/algorithms/detail/predicates.hpp>
542
#include <hpx/executors/execution_policy.hpp>
543
#include <hpx/functional/invoke.hpp>
544
#include <hpx/iterator_support/traits/is_iterator.hpp>
545
#include <hpx/parallel/algorithms/detail/advance_to_sentinel.hpp>
546
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
547
#include <hpx/parallel/algorithms/detail/distance.hpp>
548
#include <hpx/parallel/algorithms/detail/mismatch.hpp>
549
#include <hpx/parallel/util/adapt_placement_mode.hpp>
550
#include <hpx/parallel/util/cancellation_token.hpp>
551
#include <hpx/parallel/util/detail/algorithm_result.hpp>
552
#include <hpx/parallel/util/detail/clear_container.hpp>
553
#include <hpx/parallel/util/detail/sender_util.hpp>
554
#include <hpx/parallel/util/loop.hpp>
555
#include <hpx/parallel/util/partitioner.hpp>
556
#include <hpx/parallel/util/result_types.hpp>
557
#include <hpx/parallel/util/zip_iterator.hpp>
558

559
#include <algorithm>
560
#include <cstddef>
561
#include <iterator>
562
#include <type_traits>
563
#include <utility>
564
#include <vector>
565

566
namespace hpx { namespace parallel { inline namespace v1 {
567
    ///////////////////////////////////////////////////////////////////////////
568
    // mismatch (binary)
569
    namespace detail {
570

571
        ///////////////////////////////////////////////////////////////////////
572
        template <typename IterPair>
573
        struct mismatch_binary
574
          : public detail::algorithm<mismatch_binary<IterPair>, IterPair>
575
        {
576
            constexpr mismatch_binary() noexcept
260✔
577
              : mismatch_binary::algorithm("mismatch_binary")
260✔
578
            {
260✔
579
            }
260✔
580

581
            template <typename ExPolicy, typename Iter1, typename Sent1,
582
                typename Iter2, typename Sent2, typename F, typename Proj1,
583
                typename Proj2>
584
            static constexpr util::in_in_result<Iter1, Iter2> sequential(
132✔
585
                ExPolicy, Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2,
586
                F&& f, Proj1&& proj1, Proj2&& proj2)
587
            {
588
                return sequential_mismatch_binary<std::decay_t<ExPolicy>>(
132✔
589
                    first1, last1, first2, last2, HPX_FORWARD(F, f),
132✔
590
                    HPX_FORWARD(Proj1, proj1), HPX_FORWARD(Proj2, proj2));
132✔
591
            }
592

593
            template <typename ExPolicy, typename Iter1, typename Sent1,
594
                typename Iter2, typename Sent2, typename F, typename Proj1,
595
                typename Proj2>
596
            static util::detail::algorithm_result_t<ExPolicy,
597
                util::in_in_result<Iter1, Iter2>>
598
            parallel(ExPolicy&& orgpolicy, Iter1 first1, Sent1 last1,
128✔
599
                Iter2 first2, Sent2 last2, F&& f, Proj1&& proj1, Proj2&& proj2)
600
            {
601
                if (first1 == last1 || first2 == last2)
128✔
602
                {
603
                    return util::detail::algorithm_result<ExPolicy,
×
604
                        util::in_in_result<Iter1, Iter2>>::
605
                        get(util::in_in_result<Iter1, Iter2>{first1, first2});
×
606
                }
607

608
                using difference_type1 =
609
                    typename std::iterator_traits<Iter1>::difference_type;
610
                difference_type1 count1 = detail::distance(first1, last1);
128✔
611

612
                // The specification of std::mismatch(_binary) states that if FwdIter1
613
                // and FwdIter2 meet the requirements of RandomAccessIterator and
614
                // last1 - first1 != last2 - first2 then no applications of the
615
                // predicate p are made.
616
                //
617
                // We perform this check for any iterator type better than input
618
                // iterators. This could turn into a QoI issue.
619
                using difference_type2 =
620
                    typename std::iterator_traits<Iter2>::difference_type;
621
                difference_type2 count2 = detail::distance(first2, last2);
128✔
622
                if (count1 != count2)
128✔
623
                {
624
                    return util::detail::algorithm_result<ExPolicy,
×
625
                        util::in_in_result<Iter1, Iter2>>::
626
                        get(util::in_in_result<Iter1, Iter2>{first1, first2});
×
627
                }
628

629
                using zip_iterator = hpx::util::zip_iterator<Iter1, Iter2>;
630

631
                decltype(auto) policy = parallel::util::adapt_placement_mode(
128✔
632
                    HPX_FORWARD(ExPolicy, orgpolicy),
128✔
633
                    hpx::threads::thread_placement_hint::breadth_first);
634

635
                using policy_type = std::decay_t<decltype(policy)>;
636

637
                hpx::parallel::util::cancellation_token<std::size_t> tok(
128✔
638
                    count1);
128✔
639

640
                auto f1 = [tok, f = HPX_FORWARD(F, f),
11,250✔
641
                              proj1 = HPX_FORWARD(Proj1, proj1),
128✔
642
                              proj2 = HPX_FORWARD(Proj2, proj2)](
128✔
643
                              zip_iterator it, std::size_t part_count,
644
                              std::size_t base_idx) mutable -> void {
645
                    sequential_mismatch_binary<policy_type>(base_idx, it,
1,333✔
646
                        part_count, tok, HPX_FORWARD(F, f),
1,333✔
647
                        HPX_FORWARD(Proj1, proj1), HPX_FORWARD(Proj2, proj2));
1,333✔
648
                };
1,333✔
649

650
                auto f2 = [=](auto&& data) mutable
800✔
651
                    -> util::in_in_result<Iter1, Iter2> {
652
                    // make sure iterators embedded in function object that is
653
                    // attached to futures are invalidated
654
                    util::detail::clear_container(data);
104✔
655
                    difference_type1 mismatched =
104✔
656
                        static_cast<difference_type1>(tok.get_data());
104✔
657
                    if (mismatched != count1)
104✔
658
                    {
659
                        std::advance(first1, mismatched);
52✔
660
                        std::advance(first2, mismatched);
52✔
661
                    }
52✔
662
                    else
663
                    {
664
                        first1 = detail::advance_to_sentinel(first1, last1);
52✔
665
                        first2 = detail::advance_to_sentinel(first2, last2);
52✔
666
                    }
667
                    return {first1, first2};
104✔
668
                };
669

670
                using partitioner_type = util::partitioner<policy_type,
671
                    util::in_in_result<Iter1, Iter2>, void>;
672

673
                return partitioner_type::call_with_index(
128✔
674
                    HPX_FORWARD(decltype(policy), policy),
675
                    zip_iterator(first1, first2), count1, 1, HPX_MOVE(f1),
128✔
676
                    HPX_MOVE(f2));
677
            }
128✔
678
        };
679

680
        ///////////////////////////////////////////////////////////////////////
681
        template <typename I1, typename I2>
682
        std::pair<I1, I2> get_pair(util::in_in_result<I1, I2>&& p)
32✔
683
        {
684
            return {p.in1, p.in2};
32✔
685
        }
686

687
        template <typename I1, typename I2>
688
        hpx::future<std::pair<I1, I2>> get_pair(
24✔
689
            hpx::future<util::in_in_result<I1, I2>>&& f)
690
        {
691
            return hpx::make_future<std::pair<I1, I2>>(HPX_MOVE(f),
24✔
692
                [](util::in_in_result<I1, I2>&& p) -> std::pair<I1, I2> {
16✔
693
                    return {HPX_MOVE(p.in1), HPX_MOVE(p.in2)};
16✔
694
                });
695
        }
696
    }    // namespace detail
697

698
    ///////////////////////////////////////////////////////////////////////////
699
    // mismatch
700
    namespace detail {
701

702
        template <typename IterPair>
703
        struct mismatch : public detail::algorithm<mismatch<IterPair>, IterPair>
704
        {
705
            constexpr mismatch() noexcept
64✔
706
              : mismatch::algorithm("mismatch")
64✔
707
            {
64✔
708
            }
64✔
709

710
            template <typename ExPolicy, typename InIter1, typename Sent,
711
                typename InIter2, typename F>
712
            static constexpr IterPair sequential(
32✔
713
                ExPolicy, InIter1 first1, Sent last1, InIter2 first2, F&& f)
714
            {
715
                return sequential_mismatch<std::decay_t<ExPolicy>>(
32✔
716
                    first1, last1, first2, HPX_FORWARD(F, f));
32✔
717
            }
718

719
            template <typename ExPolicy, typename FwdIter1, typename Sent,
720
                typename FwdIter2, typename F>
721
            static util::detail::algorithm_result_t<ExPolicy, IterPair>
722
            parallel(ExPolicy&& orgpolicy, FwdIter1 first1, Sent last1,
32✔
723
                FwdIter2 first2, F&& f)
724
            {
725
                if (first1 == last1)
32✔
726
                {
727
                    return util::detail::algorithm_result<ExPolicy,
×
728
                        IterPair>::get(std::make_pair(first1, first2));
×
729
                }
730

731
                using difference_type =
732
                    typename std::iterator_traits<FwdIter1>::difference_type;
733
                difference_type count = detail::distance(first1, last1);
32✔
734

735
                using zip_iterator =
736
                    hpx::util::zip_iterator<FwdIter1, FwdIter2>;
737

738
                decltype(auto) policy = parallel::util::adapt_placement_mode(
32✔
739
                    HPX_FORWARD(ExPolicy, orgpolicy),
32✔
740
                    hpx::threads::thread_placement_hint::breadth_first);
741

742
                using policy_type = std::decay_t<decltype(policy)>;
743

744
                hpx::parallel::util::cancellation_token<std::size_t> tok(count);
32✔
745

746
                auto f1 = [tok, f = HPX_FORWARD(F, f)](zip_iterator it,
2,688✔
747
                              std::size_t part_count,
748
                              std::size_t base_idx) mutable -> void {
749
                    sequential_mismatch<policy_type>(
320✔
750
                        base_idx, it, part_count, tok, HPX_FORWARD(F, f));
320✔
751
                };
320✔
752

753
                auto f2 =
754
                    [=](auto&& data) mutable -> std::pair<FwdIter1, FwdIter2> {
208✔
755
                    // make sure iterators embedded in function object that is
756
                    // attached to futures are invalidated
757
                    util::detail::clear_container(data);
24✔
758
                    difference_type mismatched =
24✔
759
                        static_cast<difference_type>(tok.get_data());
24✔
760
                    if (mismatched != count)
24✔
761
                        std::advance(first1, mismatched);
12✔
762
                    else
763
                        first1 = detail::advance_to_sentinel(first1, last1);
12✔
764

765
                    std::advance(first2, mismatched);
24✔
766
                    return std::make_pair(first1, first2);
24✔
767
                };
768

769
                using partitioner_type =
770
                    util::partitioner<policy_type, IterPair, void>;
771
                return partitioner_type::call_with_index(
32✔
772
                    HPX_FORWARD(decltype(policy), policy),
773
                    zip_iterator(first1, first2), count, 1, HPX_MOVE(f1),
32✔
774
                    HPX_MOVE(f2));
775
            }
32✔
776
        };
777
    }    // namespace detail
778
}}}      // namespace hpx::parallel::v1
779

780
namespace hpx {
781

782
    ///////////////////////////////////////////////////////////////////////////
783
    // CPO for hpx::mismatch
784
    inline constexpr struct mismatch_t final
785
      : hpx::detail::tag_parallel_algorithm<mismatch_t>
786
    {
787
    private:
788
        // clang-format off
789
        template <typename ExPolicy, typename FwdIter1, typename FwdIter2,
790
            typename Pred,
791
            HPX_CONCEPT_REQUIRES_(
792
                hpx::is_execution_policy_v<ExPolicy> &&
793
                hpx::traits::is_iterator_v<FwdIter1> &&
794
                hpx::traits::is_iterator_v<FwdIter2> &&
795
                hpx::is_invocable_v<Pred,
796
                    typename std::iterator_traits<FwdIter1>::value_type,
797
                    typename std::iterator_traits<FwdIter2>::value_type
798
                >
799
            )>
800
        // clang-format on
801
        friend hpx::parallel::util::detail::algorithm_result_t<ExPolicy,
802
            std::pair<FwdIter1, FwdIter2>>
803
        tag_fallback_invoke(mismatch_t, ExPolicy&& policy, FwdIter1 first1,
36✔
804
            FwdIter1 last1, FwdIter2 first2, FwdIter2 last2, Pred&& op)
805
        {
806
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
807
                "Requires at least forward iterator.");
808
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
809
                "Requires at least forward iterator.");
810

811
            return hpx::parallel::v1::detail::get_pair(
36✔
812
                hpx::parallel::v1::detail::mismatch_binary<
36✔
813
                    hpx::parallel::util::in_in_result<FwdIter1, FwdIter2>>()
814
                    .call(HPX_FORWARD(ExPolicy, policy), first1, last1, first2,
72✔
815
                        last2, HPX_FORWARD(Pred, op),
36✔
816
                        hpx::parallel::util::projection_identity{},
817
                        hpx::parallel::util::projection_identity{}));
818
        }
×
819

820
        // clang-format off
821
        template <typename ExPolicy, typename FwdIter1, typename FwdIter2,
822
            HPX_CONCEPT_REQUIRES_(
823
                hpx::is_execution_policy_v<ExPolicy> &&
824
                hpx::traits::is_iterator_v<FwdIter1> &&
825
                hpx::traits::is_iterator_v<FwdIter2>
826
            )>
827
        // clang-format on
828
        friend hpx::parallel::util::detail::algorithm_result_t<ExPolicy,
829
            std::pair<FwdIter1, FwdIter2>>
830
        tag_fallback_invoke(mismatch_t, ExPolicy&& policy, FwdIter1 first1,
20✔
831
            FwdIter1 last1, FwdIter2 first2, FwdIter2 last2)
832
        {
833
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
834
                "Requires at least forward iterator.");
835
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
836
                "Requires at least forward iterator.");
837

838
            return hpx::parallel::v1::detail::get_pair(
20✔
839
                hpx::parallel::v1::detail::mismatch_binary<
20✔
840
                    hpx::parallel::util::in_in_result<FwdIter1, FwdIter2>>()
841
                    .call(HPX_FORWARD(ExPolicy, policy), first1, last1, first2,
20✔
842
                        last2, hpx::parallel::v1::detail::equal_to{},
843
                        hpx::parallel::util::projection_identity{},
844
                        hpx::parallel::util::projection_identity{}));
845
        }
×
846

847
        // clang-format off
848
        template <typename ExPolicy, typename FwdIter1, typename FwdIter2,
849
            typename Pred,
850
            HPX_CONCEPT_REQUIRES_(
851
                hpx::is_execution_policy_v<ExPolicy> &&
852
                hpx::traits::is_iterator_v<FwdIter1> &&
853
                hpx::traits::is_iterator_v<FwdIter2> &&
854
                hpx::is_invocable_v<Pred,
855
                    typename std::iterator_traits<FwdIter1>::value_type,
856
                    typename std::iterator_traits<FwdIter2>::value_type
857
                >
858
            )>
859
        // clang-format on
860
        friend hpx::parallel::util::detail::algorithm_result_t<ExPolicy,
861
            std::pair<FwdIter1, FwdIter2>>
862
        tag_fallback_invoke(mismatch_t, ExPolicy&& policy, FwdIter1 first1,
36✔
863
            FwdIter1 last1, FwdIter2 first2, Pred&& op)
864
        {
865
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
866
                "Requires at least forward iterator.");
867
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
868
                "Requires at least forward iterator.");
869

870
            return hpx::parallel::v1::detail::mismatch<
72✔
871
                std::pair<FwdIter1, FwdIter2>>()
872
                .call(HPX_FORWARD(ExPolicy, policy), first1, last1, first2,
72✔
873
                    HPX_FORWARD(Pred, op));
36✔
874
        }
875

876
        // clang-format off
877
        template <typename ExPolicy, typename FwdIter1, typename FwdIter2,
878
            HPX_CONCEPT_REQUIRES_(
879
                hpx::is_execution_policy_v<ExPolicy> &&
880
                hpx::traits::is_iterator_v<FwdIter1> &&
881
                hpx::traits::is_iterator_v<FwdIter2>
882
            )>
883
        // clang-format on
884
        friend hpx::parallel::util::detail::algorithm_result_t<ExPolicy,
885
            std::pair<FwdIter1, FwdIter2>>
886
        tag_fallback_invoke(mismatch_t, ExPolicy&& policy, FwdIter1 first1,
20✔
887
            FwdIter1 last1, FwdIter2 first2)
888
        {
889
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
890
                "Requires at least forward iterator.");
891
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
892
                "Requires at least forward iterator.");
893

894
            return hpx::parallel::v1::detail::mismatch<
40✔
895
                std::pair<FwdIter1, FwdIter2>>()
896
                .call(HPX_FORWARD(ExPolicy, policy), first1, last1, first2,
20✔
897
                    hpx::parallel::v1::detail::equal_to{});
898
        }
899

900
        // clang-format off
901
        template <typename FwdIter1, typename FwdIter2,
902
            typename Pred,
903
            HPX_CONCEPT_REQUIRES_(
904
                hpx::traits::is_iterator_v<FwdIter1> &&
905
                hpx::traits::is_iterator_v<FwdIter2> &&
906
                hpx::is_invocable_v<Pred,
907
                    typename std::iterator_traits<FwdIter1>::value_type,
908
                    typename std::iterator_traits<FwdIter2>::value_type
909
                >
910
            )>
911
        // clang-format on
912
        friend std::pair<FwdIter1, FwdIter2> tag_fallback_invoke(mismatch_t,
6✔
913
            FwdIter1 first1, FwdIter1 last1, FwdIter2 first2, FwdIter2 last2,
914
            Pred&& op)
915
        {
916
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
917
                "Requires at least forward iterator.");
918
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
919
                "Requires at least forward iterator.");
920

921
            return hpx::parallel::v1::detail::get_pair(
6✔
922
                hpx::parallel::v1::detail::mismatch_binary<
6✔
923
                    hpx::parallel::util::in_in_result<FwdIter1, FwdIter2>>()
924
                    .call(hpx::execution::seq, first1, last1, first2, last2,
6✔
925
                        HPX_FORWARD(Pred, op),
6✔
926
                        hpx::parallel::util::projection_identity{},
927
                        hpx::parallel::util::projection_identity{}));
928
        }
929

930
        // clang-format off
931
        template <typename FwdIter1, typename FwdIter2,
932
            HPX_CONCEPT_REQUIRES_(
933
                hpx::traits::is_iterator_v<FwdIter1> &&
934
                hpx::traits::is_iterator_v<FwdIter2>
935
            )>
936
        // clang-format on
937
        friend std::pair<FwdIter1, FwdIter2> tag_fallback_invoke(mismatch_t,
4✔
938
            FwdIter1 first1, FwdIter1 last1, FwdIter2 first2, FwdIter2 last2)
939
        {
940
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
941
                "Requires at least forward iterator.");
942
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
943
                "Requires at least forward iterator.");
944

945
            return hpx::parallel::v1::detail::get_pair(
4✔
946
                hpx::parallel::v1::detail::mismatch_binary<
4✔
947
                    hpx::parallel::util::in_in_result<FwdIter1, FwdIter2>>()
948
                    .call(hpx::execution::seq, first1, last1, first2, last2,
4✔
949
                        hpx::parallel::v1::detail::equal_to{},
950
                        hpx::parallel::util::projection_identity{},
951
                        hpx::parallel::util::projection_identity{}));
952
        }
953

954
        // clang-format off
955
        template <typename FwdIter1, typename FwdIter2,
956
            typename Pred,
957
            HPX_CONCEPT_REQUIRES_(
958
                hpx::traits::is_iterator_v<FwdIter1> &&
959
                hpx::traits::is_iterator_v<FwdIter2> &&
960
                hpx::is_invocable_v<Pred,
961
                    typename std::iterator_traits<FwdIter1>::value_type,
962
                    typename std::iterator_traits<FwdIter2>::value_type
963
                >
964
            )>
965
        // clang-format on
966
        friend std::pair<FwdIter1, FwdIter2> tag_fallback_invoke(mismatch_t,
4✔
967
            FwdIter1 first1, FwdIter1 last1, FwdIter2 first2, Pred&& op)
968
        {
969
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
970
                "Requires at least forward iterator.");
971
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
972
                "Requires at least forward iterator.");
973

974
            return hpx::parallel::v1::detail::mismatch<
8✔
975
                std::pair<FwdIter1, FwdIter2>>()
976
                .call(hpx::execution::seq, first1, last1, first2,
4✔
977
                    HPX_FORWARD(Pred, op));
4✔
978
        }
979

980
        // clang-format off
981
        template <typename FwdIter1, typename FwdIter2,
982
            HPX_CONCEPT_REQUIRES_(
983
                hpx::traits::is_iterator_v<FwdIter1> &&
984
                hpx::traits::is_iterator_v<FwdIter2>
985
            )>
986
        // clang-format on
987
        friend std::pair<FwdIter1, FwdIter2> tag_fallback_invoke(
4✔
988
            mismatch_t, FwdIter1 first1, FwdIter1 last1, FwdIter2 first2)
989
        {
990
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter1>),
991
                "Requires at least forward iterator.");
992
            static_assert((hpx::traits::is_forward_iterator_v<FwdIter2>),
993
                "Requires at least forward iterator.");
994

995
            return hpx::parallel::v1::detail::mismatch<
8✔
996
                std::pair<FwdIter1, FwdIter2>>()
997
                .call(hpx::execution::seq, first1, last1, first2,
4✔
998
                    hpx::parallel::v1::detail::equal_to{});
999
        }
1000

1001
    } mismatch{};
1002
}    // namespace hpx
1003

1004
#endif    // DOXYGEN
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc