]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/parallel/algo.h
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / parallel / algo.h
1 // -*- C++ -*-
2
3 // Copyright (C) 2007-2023 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 3, or (at your option) any later
9 // version.
10
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24
25 /** @file parallel/algo.h
26 * @brief Parallel STL function calls corresponding to the stl_algo.h header.
27 *
28 * The functions defined here mainly do case switches and
29 * call the actual parallelized versions in other files.
30 * Inlining policy: Functions that basically only contain one function call,
31 * are declared inline.
32 * This file is a GNU parallel extension to the Standard C++ Library.
33 */
34
35 // Written by Johannes Singler and Felix Putze.
36
37 #ifndef _GLIBCXX_PARALLEL_ALGO_H
38 #define _GLIBCXX_PARALLEL_ALGO_H 1
39
40 #include <parallel/algorithmfwd.h>
41 #include <bits/stl_algobase.h>
42 #include <bits/stl_algo.h>
43 #include <parallel/iterator.h>
44 #include <parallel/base.h>
45 #include <parallel/sort.h>
46 #include <parallel/workstealing.h>
47 #include <parallel/par_loop.h>
48 #include <parallel/omp_loop.h>
49 #include <parallel/omp_loop_static.h>
50 #include <parallel/for_each_selectors.h>
51 #include <parallel/for_each.h>
52 #include <parallel/find.h>
53 #include <parallel/find_selectors.h>
54 #include <parallel/search.h>
55 #include <parallel/random_shuffle.h>
56 #include <parallel/partition.h>
57 #include <parallel/merge.h>
58 #include <parallel/unique_copy.h>
59 #include <parallel/set_operations.h>
60
61 namespace std _GLIBCXX_VISIBILITY(default)
62 {
63 namespace __parallel
64 {
65 // Sequential fallback
66 template<typename _IIter, typename _Function>
67 inline _Function
68 for_each(_IIter __begin, _IIter __end, _Function __f,
69 __gnu_parallel::sequential_tag)
70 { return _GLIBCXX_STD_A::for_each(__begin, __end, __f); }
71
72 // Sequential fallback for input iterator case
73 template<typename _IIter, typename _Function, typename _IteratorTag>
74 inline _Function
75 __for_each_switch(_IIter __begin, _IIter __end, _Function __f,
76 _IteratorTag)
77 { return for_each(__begin, __end, __f, __gnu_parallel::sequential_tag()); }
78
79 // Parallel algorithm for random access iterators
80 template<typename _RAIter, typename _Function>
81 _Function
82 __for_each_switch(_RAIter __begin, _RAIter __end,
83 _Function __f, random_access_iterator_tag,
84 __gnu_parallel::_Parallelism __parallelism_tag)
85 {
86 if (_GLIBCXX_PARALLEL_CONDITION(
87 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
88 >= __gnu_parallel::_Settings::get().for_each_minimal_n
89 && __gnu_parallel::__is_parallel(__parallelism_tag)))
90 {
91 bool __dummy;
92 __gnu_parallel::__for_each_selector<_RAIter> __functionality;
93
94 return __gnu_parallel::
95 __for_each_template_random_access(
96 __begin, __end, __f, __functionality,
97 __gnu_parallel::_DummyReduct(), true, __dummy, -1,
98 __parallelism_tag);
99 }
100 else
101 return for_each(__begin, __end, __f, __gnu_parallel::sequential_tag());
102 }
103
104 // Public interface
105 template<typename _Iterator, typename _Function>
106 inline _Function
107 for_each(_Iterator __begin, _Iterator __end, _Function __f,
108 __gnu_parallel::_Parallelism __parallelism_tag)
109 {
110 return __for_each_switch(__begin, __end, __f,
111 std::__iterator_category(__begin),
112 __parallelism_tag);
113 }
114
115 template<typename _Iterator, typename _Function>
116 inline _Function
117 for_each(_Iterator __begin, _Iterator __end, _Function __f)
118 {
119 return __for_each_switch(__begin, __end, __f,
120 std::__iterator_category(__begin));
121 }
122
123 // Sequential fallback
124 template<typename _IIter, typename _Tp>
125 inline _IIter
126 find(_IIter __begin, _IIter __end, const _Tp& __val,
127 __gnu_parallel::sequential_tag)
128 { return _GLIBCXX_STD_A::find(__begin, __end, __val); }
129
130 // Sequential fallback for input iterator case
131 template<typename _IIter, typename _Tp, typename _IteratorTag>
132 inline _IIter
133 __find_switch(_IIter __begin, _IIter __end, const _Tp& __val,
134 _IteratorTag)
135 { return _GLIBCXX_STD_A::find(__begin, __end, __val); }
136
137 // Parallel find for random access iterators
138 template<typename _RAIter, typename _Tp>
139 _RAIter
140 __find_switch(_RAIter __begin, _RAIter __end,
141 const _Tp& __val, random_access_iterator_tag)
142 {
143 typedef iterator_traits<_RAIter> _TraitsType;
144 typedef typename _TraitsType::value_type _ValueType;
145
146 if (_GLIBCXX_PARALLEL_CONDITION(true))
147 {
148 __gnu_parallel::__binder2nd<__gnu_parallel::_EqualTo<_ValueType,
149 const _Tp&>,
150 _ValueType, const _Tp&, bool>
151 __comp(__gnu_parallel::_EqualTo<_ValueType, const _Tp&>(), __val);
152 return __gnu_parallel::__find_template(
153 __begin, __end, __begin, __comp,
154 __gnu_parallel::__find_if_selector()).first;
155 }
156 else
157 return _GLIBCXX_STD_A::find(__begin, __end, __val);
158 }
159
160 // Public interface
161 template<typename _IIter, typename _Tp>
162 inline _IIter
163 find(_IIter __begin, _IIter __end, const _Tp& __val)
164 {
165 return __find_switch(__begin, __end, __val,
166 std::__iterator_category(__begin));
167 }
168
169 // Sequential fallback
170 template<typename _IIter, typename _Predicate>
171 inline _IIter
172 find_if(_IIter __begin, _IIter __end, _Predicate __pred,
173 __gnu_parallel::sequential_tag)
174 { return _GLIBCXX_STD_A::find_if(__begin, __end, __pred); }
175
176 // Sequential fallback for input iterator case
177 template<typename _IIter, typename _Predicate, typename _IteratorTag>
178 inline _IIter
179 __find_if_switch(_IIter __begin, _IIter __end, _Predicate __pred,
180 _IteratorTag)
181 { return _GLIBCXX_STD_A::find_if(__begin, __end, __pred); }
182
183 // Parallel find_if for random access iterators
184 template<typename _RAIter, typename _Predicate>
185 _RAIter
186 __find_if_switch(_RAIter __begin, _RAIter __end,
187 _Predicate __pred, random_access_iterator_tag)
188 {
189 if (_GLIBCXX_PARALLEL_CONDITION(true))
190 return __gnu_parallel::__find_template(__begin, __end, __begin, __pred,
191 __gnu_parallel::
192 __find_if_selector()).first;
193 else
194 return _GLIBCXX_STD_A::find_if(__begin, __end, __pred);
195 }
196
197 // Public interface
198 template<typename _IIter, typename _Predicate>
199 inline _IIter
200 find_if(_IIter __begin, _IIter __end, _Predicate __pred)
201 {
202 return __find_if_switch(__begin, __end, __pred,
203 std::__iterator_category(__begin));
204 }
205
206 // Sequential fallback
207 template<typename _IIter, typename _FIterator>
208 inline _IIter
209 find_first_of(_IIter __begin1, _IIter __end1,
210 _FIterator __begin2, _FIterator __end2,
211 __gnu_parallel::sequential_tag)
212 {
213 return _GLIBCXX_STD_A::find_first_of(__begin1, __end1, __begin2, __end2);
214 }
215
216 // Sequential fallback
217 template<typename _IIter, typename _FIterator,
218 typename _BinaryPredicate>
219 inline _IIter
220 find_first_of(_IIter __begin1, _IIter __end1,
221 _FIterator __begin2, _FIterator __end2,
222 _BinaryPredicate __comp, __gnu_parallel::sequential_tag)
223 { return _GLIBCXX_STD_A::find_first_of(
224 __begin1, __end1, __begin2, __end2, __comp); }
225
226 // Sequential fallback for input iterator type
227 template<typename _IIter, typename _FIterator,
228 typename _IteratorTag1, typename _IteratorTag2>
229 inline _IIter
230 __find_first_of_switch(_IIter __begin1, _IIter __end1,
231 _FIterator __begin2, _FIterator __end2,
232 _IteratorTag1, _IteratorTag2)
233 { return find_first_of(__begin1, __end1, __begin2, __end2,
234 __gnu_parallel::sequential_tag()); }
235
236 // Parallel algorithm for random access iterators
237 template<typename _RAIter, typename _FIterator,
238 typename _BinaryPredicate, typename _IteratorTag>
239 inline _RAIter
240 __find_first_of_switch(_RAIter __begin1,
241 _RAIter __end1,
242 _FIterator __begin2, _FIterator __end2,
243 _BinaryPredicate __comp, random_access_iterator_tag,
244 _IteratorTag)
245 {
246 return __gnu_parallel::
247 __find_template(__begin1, __end1, __begin1, __comp,
248 __gnu_parallel::__find_first_of_selector
249 <_FIterator>(__begin2, __end2)).first;
250 }
251
252 // Sequential fallback for input iterator type
253 template<typename _IIter, typename _FIterator,
254 typename _BinaryPredicate, typename _IteratorTag1,
255 typename _IteratorTag2>
256 inline _IIter
257 __find_first_of_switch(_IIter __begin1, _IIter __end1,
258 _FIterator __begin2, _FIterator __end2,
259 _BinaryPredicate __comp, _IteratorTag1, _IteratorTag2)
260 { return find_first_of(__begin1, __end1, __begin2, __end2, __comp,
261 __gnu_parallel::sequential_tag()); }
262
263 // Public interface
264 template<typename _IIter, typename _FIterator,
265 typename _BinaryPredicate>
266 inline _IIter
267 find_first_of(_IIter __begin1, _IIter __end1,
268 _FIterator __begin2, _FIterator __end2,
269 _BinaryPredicate __comp)
270 {
271 return __find_first_of_switch(__begin1, __end1, __begin2, __end2, __comp,
272 std::__iterator_category(__begin1),
273 std::__iterator_category(__begin2));
274 }
275
276 // Public interface, insert default comparator
277 template<typename _IIter, typename _FIterator>
278 inline _IIter
279 find_first_of(_IIter __begin1, _IIter __end1,
280 _FIterator __begin2, _FIterator __end2)
281 {
282 typedef typename std::iterator_traits<_IIter>::value_type _IValueType;
283 typedef typename std::iterator_traits<_FIterator>::value_type _FValueType;
284
285 return __gnu_parallel::find_first_of(__begin1, __end1, __begin2, __end2,
286 __gnu_parallel::_EqualTo<_IValueType, _FValueType>());
287 }
288
289 // Sequential fallback
290 template<typename _IIter, typename _OutputIterator>
291 inline _OutputIterator
292 unique_copy(_IIter __begin1, _IIter __end1, _OutputIterator __out,
293 __gnu_parallel::sequential_tag)
294 { return _GLIBCXX_STD_A::unique_copy(__begin1, __end1, __out); }
295
296 // Sequential fallback
297 template<typename _IIter, typename _OutputIterator,
298 typename _Predicate>
299 inline _OutputIterator
300 unique_copy(_IIter __begin1, _IIter __end1, _OutputIterator __out,
301 _Predicate __pred, __gnu_parallel::sequential_tag)
302 { return _GLIBCXX_STD_A::unique_copy(__begin1, __end1, __out, __pred); }
303
304 // Sequential fallback for input iterator case
305 template<typename _IIter, typename _OutputIterator,
306 typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
307 inline _OutputIterator
308 __unique_copy_switch(_IIter __begin, _IIter __last,
309 _OutputIterator __out, _Predicate __pred,
310 _IteratorTag1, _IteratorTag2)
311 { return _GLIBCXX_STD_A::unique_copy(__begin, __last, __out, __pred); }
312
313 // Parallel unique_copy for random access iterators
314 template<typename _RAIter, typename _RandomAccessOutputIterator,
315 typename _Predicate>
316 _RandomAccessOutputIterator
317 __unique_copy_switch(_RAIter __begin, _RAIter __last,
318 _RandomAccessOutputIterator __out, _Predicate __pred,
319 random_access_iterator_tag, random_access_iterator_tag)
320 {
321 if (_GLIBCXX_PARALLEL_CONDITION(
322 static_cast<__gnu_parallel::_SequenceIndex>(__last - __begin)
323 > __gnu_parallel::_Settings::get().unique_copy_minimal_n))
324 return __gnu_parallel::__parallel_unique_copy(
325 __begin, __last, __out, __pred);
326 else
327 return _GLIBCXX_STD_A::unique_copy(__begin, __last, __out, __pred);
328 }
329
330 // Public interface
331 template<typename _IIter, typename _OutputIterator>
332 inline _OutputIterator
333 unique_copy(_IIter __begin1, _IIter __end1, _OutputIterator __out)
334 {
335 typedef typename std::iterator_traits<_IIter>::value_type _ValueType;
336
337 return __unique_copy_switch(
338 __begin1, __end1, __out, equal_to<_ValueType>(),
339 std::__iterator_category(__begin1),
340 std::__iterator_category(__out));
341 }
342
343 // Public interface
344 template<typename _IIter, typename _OutputIterator, typename _Predicate>
345 inline _OutputIterator
346 unique_copy(_IIter __begin1, _IIter __end1, _OutputIterator __out,
347 _Predicate __pred)
348 {
349 return __unique_copy_switch(
350 __begin1, __end1, __out, __pred,
351 std::__iterator_category(__begin1),
352 std::__iterator_category(__out));
353 }
354
355 // Sequential fallback
356 template<typename _IIter1, typename _IIter2,
357 typename _OutputIterator>
358 inline _OutputIterator
359 set_union(_IIter1 __begin1, _IIter1 __end1,
360 _IIter2 __begin2, _IIter2 __end2,
361 _OutputIterator __out, __gnu_parallel::sequential_tag)
362 { return _GLIBCXX_STD_A::set_union(
363 __begin1, __end1, __begin2, __end2, __out); }
364
365 // Sequential fallback
366 template<typename _IIter1, typename _IIter2,
367 typename _OutputIterator, typename _Predicate>
368 inline _OutputIterator
369 set_union(_IIter1 __begin1, _IIter1 __end1,
370 _IIter2 __begin2, _IIter2 __end2,
371 _OutputIterator __out, _Predicate __pred,
372 __gnu_parallel::sequential_tag)
373 { return _GLIBCXX_STD_A::set_union(__begin1, __end1,
374 __begin2, __end2, __out, __pred); }
375
376 // Sequential fallback for input iterator case
377 template<typename _IIter1, typename _IIter2, typename _Predicate,
378 typename _OutputIterator, typename _IteratorTag1,
379 typename _IteratorTag2, typename _IteratorTag3>
380 inline _OutputIterator
381 __set_union_switch(
382 _IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2,
383 _OutputIterator __result, _Predicate __pred,
384 _IteratorTag1, _IteratorTag2, _IteratorTag3)
385 { return _GLIBCXX_STD_A::set_union(__begin1, __end1,
386 __begin2, __end2, __result, __pred); }
387
388 // Parallel set_union for random access iterators
389 template<typename _RAIter1, typename _RAIter2,
390 typename _Output_RAIter, typename _Predicate>
391 _Output_RAIter
392 __set_union_switch(_RAIter1 __begin1, _RAIter1 __end1,
393 _RAIter2 __begin2, _RAIter2 __end2,
394 _Output_RAIter __result, _Predicate __pred,
395 random_access_iterator_tag, random_access_iterator_tag,
396 random_access_iterator_tag)
397 {
398 if (_GLIBCXX_PARALLEL_CONDITION(
399 static_cast<__gnu_parallel::_SequenceIndex>(__end1 - __begin1)
400 >= __gnu_parallel::_Settings::get().set_union_minimal_n
401 || static_cast<__gnu_parallel::_SequenceIndex>(__end2 - __begin2)
402 >= __gnu_parallel::_Settings::get().set_union_minimal_n))
403 return __gnu_parallel::__parallel_set_union(
404 __begin1, __end1, __begin2, __end2, __result, __pred);
405 else
406 return _GLIBCXX_STD_A::set_union(__begin1, __end1,
407 __begin2, __end2, __result, __pred);
408 }
409
410 // Public interface
411 template<typename _IIter1, typename _IIter2,
412 typename _OutputIterator>
413 inline _OutputIterator
414 set_union(_IIter1 __begin1, _IIter1 __end1,
415 _IIter2 __begin2, _IIter2 __end2, _OutputIterator __out)
416 {
417 typedef typename std::iterator_traits<_IIter1>::value_type _ValueType1;
418 typedef typename std::iterator_traits<_IIter2>::value_type _ValueType2;
419
420 return __set_union_switch(
421 __begin1, __end1, __begin2, __end2, __out,
422 __gnu_parallel::_Less<_ValueType1, _ValueType2>(),
423 std::__iterator_category(__begin1),
424 std::__iterator_category(__begin2),
425 std::__iterator_category(__out));
426 }
427
428 // Public interface
429 template<typename _IIter1, typename _IIter2,
430 typename _OutputIterator, typename _Predicate>
431 inline _OutputIterator
432 set_union(_IIter1 __begin1, _IIter1 __end1,
433 _IIter2 __begin2, _IIter2 __end2,
434 _OutputIterator __out, _Predicate __pred)
435 {
436 return __set_union_switch(
437 __begin1, __end1, __begin2, __end2, __out, __pred,
438 std::__iterator_category(__begin1),
439 std::__iterator_category(__begin2),
440 std::__iterator_category(__out));
441 }
442
443 // Sequential fallback.
444 template<typename _IIter1, typename _IIter2,
445 typename _OutputIterator>
446 inline _OutputIterator
447 set_intersection(_IIter1 __begin1, _IIter1 __end1,
448 _IIter2 __begin2, _IIter2 __end2,
449 _OutputIterator __out, __gnu_parallel::sequential_tag)
450 { return _GLIBCXX_STD_A::set_intersection(__begin1, __end1,
451 __begin2, __end2, __out); }
452
453 // Sequential fallback.
454 template<typename _IIter1, typename _IIter2,
455 typename _OutputIterator, typename _Predicate>
456 inline _OutputIterator
457 set_intersection(_IIter1 __begin1, _IIter1 __end1,
458 _IIter2 __begin2, _IIter2 __end2,
459 _OutputIterator __out, _Predicate __pred,
460 __gnu_parallel::sequential_tag)
461 { return _GLIBCXX_STD_A::set_intersection(
462 __begin1, __end1, __begin2, __end2, __out, __pred); }
463
464 // Sequential fallback for input iterator case
465 template<typename _IIter1, typename _IIter2,
466 typename _Predicate, typename _OutputIterator,
467 typename _IteratorTag1, typename _IteratorTag2,
468 typename _IteratorTag3>
469 inline _OutputIterator
470 __set_intersection_switch(_IIter1 __begin1, _IIter1 __end1,
471 _IIter2 __begin2, _IIter2 __end2,
472 _OutputIterator __result, _Predicate __pred,
473 _IteratorTag1, _IteratorTag2, _IteratorTag3)
474 { return _GLIBCXX_STD_A::set_intersection(__begin1, __end1, __begin2,
475 __end2, __result, __pred); }
476
477 // Parallel set_intersection for random access iterators
478 template<typename _RAIter1, typename _RAIter2,
479 typename _Output_RAIter, typename _Predicate>
480 _Output_RAIter
481 __set_intersection_switch(_RAIter1 __begin1,
482 _RAIter1 __end1,
483 _RAIter2 __begin2,
484 _RAIter2 __end2,
485 _Output_RAIter __result,
486 _Predicate __pred,
487 random_access_iterator_tag,
488 random_access_iterator_tag,
489 random_access_iterator_tag)
490 {
491 if (_GLIBCXX_PARALLEL_CONDITION(
492 static_cast<__gnu_parallel::_SequenceIndex>(__end1 - __begin1)
493 >= __gnu_parallel::_Settings::get().set_union_minimal_n
494 || static_cast<__gnu_parallel::_SequenceIndex>(__end2 - __begin2)
495 >= __gnu_parallel::_Settings::get().set_union_minimal_n))
496 return __gnu_parallel::__parallel_set_intersection(
497 __begin1, __end1, __begin2, __end2, __result, __pred);
498 else
499 return _GLIBCXX_STD_A::set_intersection(
500 __begin1, __end1, __begin2, __end2, __result, __pred);
501 }
502
503 // Public interface
504 template<typename _IIter1, typename _IIter2,
505 typename _OutputIterator>
506 inline _OutputIterator
507 set_intersection(_IIter1 __begin1, _IIter1 __end1,
508 _IIter2 __begin2, _IIter2 __end2,
509 _OutputIterator __out)
510 {
511 typedef typename std::iterator_traits<_IIter1>::value_type _ValueType1;
512 typedef typename std::iterator_traits<_IIter2>::value_type _ValueType2;
513
514 return __set_intersection_switch(
515 __begin1, __end1, __begin2, __end2, __out,
516 __gnu_parallel::_Less<_ValueType1, _ValueType2>(),
517 std::__iterator_category(__begin1),
518 std::__iterator_category(__begin2),
519 std::__iterator_category(__out));
520 }
521
522 template<typename _IIter1, typename _IIter2,
523 typename _OutputIterator, typename _Predicate>
524 inline _OutputIterator
525 set_intersection(_IIter1 __begin1, _IIter1 __end1,
526 _IIter2 __begin2, _IIter2 __end2,
527 _OutputIterator __out, _Predicate __pred)
528 {
529 return __set_intersection_switch(
530 __begin1, __end1, __begin2, __end2, __out, __pred,
531 std::__iterator_category(__begin1),
532 std::__iterator_category(__begin2),
533 std::__iterator_category(__out));
534 }
535
536 // Sequential fallback
537 template<typename _IIter1, typename _IIter2,
538 typename _OutputIterator>
539 inline _OutputIterator
540 set_symmetric_difference(_IIter1 __begin1, _IIter1 __end1,
541 _IIter2 __begin2, _IIter2 __end2,
542 _OutputIterator __out,
543 __gnu_parallel::sequential_tag)
544 { return _GLIBCXX_STD_A::set_symmetric_difference(
545 __begin1, __end1, __begin2, __end2, __out); }
546
547 // Sequential fallback
548 template<typename _IIter1, typename _IIter2,
549 typename _OutputIterator, typename _Predicate>
550 inline _OutputIterator
551 set_symmetric_difference(_IIter1 __begin1, _IIter1 __end1,
552 _IIter2 __begin2, _IIter2 __end2,
553 _OutputIterator __out, _Predicate __pred,
554 __gnu_parallel::sequential_tag)
555 { return _GLIBCXX_STD_A::set_symmetric_difference(
556 __begin1, __end1, __begin2, __end2, __out, __pred); }
557
558 // Sequential fallback for input iterator case
559 template<typename _IIter1, typename _IIter2,
560 typename _Predicate, typename _OutputIterator,
561 typename _IteratorTag1, typename _IteratorTag2,
562 typename _IteratorTag3>
563 inline _OutputIterator
564 __set_symmetric_difference_switch(
565 _IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2,
566 _OutputIterator __result, _Predicate __pred,
567 _IteratorTag1, _IteratorTag2, _IteratorTag3)
568 { return _GLIBCXX_STD_A::set_symmetric_difference(
569 __begin1, __end1, __begin2, __end2, __result, __pred); }
570
571 // Parallel set_symmetric_difference for random access iterators
572 template<typename _RAIter1, typename _RAIter2,
573 typename _Output_RAIter, typename _Predicate>
574 _Output_RAIter
575 __set_symmetric_difference_switch(_RAIter1 __begin1,
576 _RAIter1 __end1,
577 _RAIter2 __begin2,
578 _RAIter2 __end2,
579 _Output_RAIter __result,
580 _Predicate __pred,
581 random_access_iterator_tag,
582 random_access_iterator_tag,
583 random_access_iterator_tag)
584 {
585 if (_GLIBCXX_PARALLEL_CONDITION(
586 static_cast<__gnu_parallel::_SequenceIndex>(__end1 - __begin1)
587 >= __gnu_parallel::_Settings::get().set_symmetric_difference_minimal_n
588 || static_cast<__gnu_parallel::_SequenceIndex>(__end2 - __begin2)
589 >= __gnu_parallel::_Settings::get().set_symmetric_difference_minimal_n))
590 return __gnu_parallel::__parallel_set_symmetric_difference(
591 __begin1, __end1, __begin2, __end2, __result, __pred);
592 else
593 return _GLIBCXX_STD_A::set_symmetric_difference(
594 __begin1, __end1, __begin2, __end2, __result, __pred);
595 }
596
597 // Public interface.
598 template<typename _IIter1, typename _IIter2,
599 typename _OutputIterator>
600 inline _OutputIterator
601 set_symmetric_difference(_IIter1 __begin1, _IIter1 __end1,
602 _IIter2 __begin2, _IIter2 __end2,
603 _OutputIterator __out)
604 {
605 typedef typename std::iterator_traits<_IIter1>::value_type _ValueType1;
606 typedef typename std::iterator_traits<_IIter2>::value_type _ValueType2;
607
608 return __set_symmetric_difference_switch(
609 __begin1, __end1, __begin2, __end2, __out,
610 __gnu_parallel::_Less<_ValueType1, _ValueType2>(),
611 std::__iterator_category(__begin1),
612 std::__iterator_category(__begin2),
613 std::__iterator_category(__out));
614 }
615
616 // Public interface.
617 template<typename _IIter1, typename _IIter2,
618 typename _OutputIterator, typename _Predicate>
619 inline _OutputIterator
620 set_symmetric_difference(_IIter1 __begin1, _IIter1 __end1,
621 _IIter2 __begin2, _IIter2 __end2,
622 _OutputIterator __out, _Predicate __pred)
623 {
624 return __set_symmetric_difference_switch(
625 __begin1, __end1, __begin2, __end2, __out, __pred,
626 std::__iterator_category(__begin1),
627 std::__iterator_category(__begin2),
628 std::__iterator_category(__out));
629 }
630
631 // Sequential fallback.
632 template<typename _IIter1, typename _IIter2,
633 typename _OutputIterator>
634 inline _OutputIterator
635 set_difference(_IIter1 __begin1, _IIter1 __end1,
636 _IIter2 __begin2, _IIter2 __end2,
637 _OutputIterator __out, __gnu_parallel::sequential_tag)
638 { return _GLIBCXX_STD_A::set_difference(
639 __begin1,__end1, __begin2, __end2, __out); }
640
641 // Sequential fallback.
642 template<typename _IIter1, typename _IIter2,
643 typename _OutputIterator, typename _Predicate>
644 inline _OutputIterator
645 set_difference(_IIter1 __begin1, _IIter1 __end1,
646 _IIter2 __begin2, _IIter2 __end2,
647 _OutputIterator __out, _Predicate __pred,
648 __gnu_parallel::sequential_tag)
649 { return _GLIBCXX_STD_A::set_difference(__begin1, __end1,
650 __begin2, __end2, __out, __pred); }
651
652 // Sequential fallback for input iterator case.
653 template<typename _IIter1, typename _IIter2, typename _Predicate,
654 typename _OutputIterator, typename _IteratorTag1,
655 typename _IteratorTag2, typename _IteratorTag3>
656 inline _OutputIterator
657 __set_difference_switch(_IIter1 __begin1, _IIter1 __end1,
658 _IIter2 __begin2, _IIter2 __end2,
659 _OutputIterator __result, _Predicate __pred,
660 _IteratorTag1, _IteratorTag2, _IteratorTag3)
661 { return _GLIBCXX_STD_A::set_difference(
662 __begin1, __end1, __begin2, __end2, __result, __pred); }
663
664 // Parallel set_difference for random access iterators
665 template<typename _RAIter1, typename _RAIter2,
666 typename _Output_RAIter, typename _Predicate>
667 _Output_RAIter
668 __set_difference_switch(_RAIter1 __begin1,
669 _RAIter1 __end1,
670 _RAIter2 __begin2,
671 _RAIter2 __end2,
672 _Output_RAIter __result, _Predicate __pred,
673 random_access_iterator_tag,
674 random_access_iterator_tag,
675 random_access_iterator_tag)
676 {
677 if (_GLIBCXX_PARALLEL_CONDITION(
678 static_cast<__gnu_parallel::_SequenceIndex>(__end1 - __begin1)
679 >= __gnu_parallel::_Settings::get().set_difference_minimal_n
680 || static_cast<__gnu_parallel::_SequenceIndex>(__end2 - __begin2)
681 >= __gnu_parallel::_Settings::get().set_difference_minimal_n))
682 return __gnu_parallel::__parallel_set_difference(
683 __begin1, __end1, __begin2, __end2, __result, __pred);
684 else
685 return _GLIBCXX_STD_A::set_difference(
686 __begin1, __end1, __begin2, __end2, __result, __pred);
687 }
688
689 // Public interface
690 template<typename _IIter1, typename _IIter2,
691 typename _OutputIterator>
692 inline _OutputIterator
693 set_difference(_IIter1 __begin1, _IIter1 __end1,
694 _IIter2 __begin2, _IIter2 __end2,
695 _OutputIterator __out)
696 {
697 typedef typename std::iterator_traits<_IIter1>::value_type _ValueType1;
698 typedef typename std::iterator_traits<_IIter2>::value_type _ValueType2;
699
700 return __set_difference_switch(
701 __begin1, __end1, __begin2, __end2, __out,
702 __gnu_parallel::_Less<_ValueType1, _ValueType2>(),
703 std::__iterator_category(__begin1),
704 std::__iterator_category(__begin2),
705 std::__iterator_category(__out));
706 }
707
708 // Public interface
709 template<typename _IIter1, typename _IIter2,
710 typename _OutputIterator, typename _Predicate>
711 inline _OutputIterator
712 set_difference(_IIter1 __begin1, _IIter1 __end1,
713 _IIter2 __begin2, _IIter2 __end2,
714 _OutputIterator __out, _Predicate __pred)
715 {
716 return __set_difference_switch(
717 __begin1, __end1, __begin2, __end2, __out, __pred,
718 std::__iterator_category(__begin1),
719 std::__iterator_category(__begin2),
720 std::__iterator_category(__out));
721 }
722
723 // Sequential fallback
724 template<typename _FIterator>
725 inline _FIterator
726 adjacent_find(_FIterator __begin, _FIterator __end,
727 __gnu_parallel::sequential_tag)
728 { return _GLIBCXX_STD_A::adjacent_find(__begin, __end); }
729
730 // Sequential fallback
731 template<typename _FIterator, typename _BinaryPredicate>
732 inline _FIterator
733 adjacent_find(_FIterator __begin, _FIterator __end,
734 _BinaryPredicate __binary_pred,
735 __gnu_parallel::sequential_tag)
736 { return _GLIBCXX_STD_A::adjacent_find(__begin, __end, __binary_pred); }
737
738 // Parallel algorithm for random access iterators
739 template<typename _RAIter>
740 _RAIter
741 __adjacent_find_switch(_RAIter __begin, _RAIter __end,
742 random_access_iterator_tag)
743 {
744 typedef iterator_traits<_RAIter> _TraitsType;
745 typedef typename _TraitsType::value_type _ValueType;
746
747 if (_GLIBCXX_PARALLEL_CONDITION(true))
748 {
749 _RAIter __spot = __gnu_parallel::
750 __find_template(
751 __begin, __end - 1, __begin, equal_to<_ValueType>(),
752 __gnu_parallel::__adjacent_find_selector())
753 .first;
754 if (__spot == (__end - 1))
755 return __end;
756 else
757 return __spot;
758 }
759 else
760 return adjacent_find(__begin, __end, __gnu_parallel::sequential_tag());
761 }
762
763 // Sequential fallback for input iterator case
764 template<typename _FIterator, typename _IteratorTag>
765 inline _FIterator
766 __adjacent_find_switch(_FIterator __begin, _FIterator __end,
767 _IteratorTag)
768 { return adjacent_find(__begin, __end, __gnu_parallel::sequential_tag()); }
769
770 // Public interface
771 template<typename _FIterator>
772 inline _FIterator
773 adjacent_find(_FIterator __begin, _FIterator __end)
774 {
775 return __adjacent_find_switch(__begin, __end,
776 std::__iterator_category(__begin));
777 }
778
779 // Sequential fallback for input iterator case
780 template<typename _FIterator, typename _BinaryPredicate,
781 typename _IteratorTag>
782 inline _FIterator
783 __adjacent_find_switch(_FIterator __begin, _FIterator __end,
784 _BinaryPredicate __pred, _IteratorTag)
785 { return adjacent_find(__begin, __end, __pred,
786 __gnu_parallel::sequential_tag()); }
787
788 // Parallel algorithm for random access iterators
789 template<typename _RAIter, typename _BinaryPredicate>
790 _RAIter
791 __adjacent_find_switch(_RAIter __begin, _RAIter __end,
792 _BinaryPredicate __pred, random_access_iterator_tag)
793 {
794 if (_GLIBCXX_PARALLEL_CONDITION(true))
795 return __gnu_parallel::__find_template(__begin, __end, __begin, __pred,
796 __gnu_parallel::
797 __adjacent_find_selector()).first;
798 else
799 return adjacent_find(__begin, __end, __pred,
800 __gnu_parallel::sequential_tag());
801 }
802
803 // Public interface
804 template<typename _FIterator, typename _BinaryPredicate>
805 inline _FIterator
806 adjacent_find(_FIterator __begin, _FIterator __end,
807 _BinaryPredicate __pred)
808 {
809 return __adjacent_find_switch(__begin, __end, __pred,
810 std::__iterator_category(__begin));
811 }
812
813 // Sequential fallback
814 template<typename _IIter, typename _Tp>
815 inline typename iterator_traits<_IIter>::difference_type
816 count(_IIter __begin, _IIter __end, const _Tp& __value,
817 __gnu_parallel::sequential_tag)
818 { return _GLIBCXX_STD_A::count(__begin, __end, __value); }
819
820 // Parallel code for random access iterators
821 template<typename _RAIter, typename _Tp>
822 typename iterator_traits<_RAIter>::difference_type
823 __count_switch(_RAIter __begin, _RAIter __end,
824 const _Tp& __value, random_access_iterator_tag,
825 __gnu_parallel::_Parallelism __parallelism_tag)
826 {
827 typedef iterator_traits<_RAIter> _TraitsType;
828 typedef typename _TraitsType::value_type _ValueType;
829 typedef typename _TraitsType::difference_type _DifferenceType;
830 typedef __gnu_parallel::_SequenceIndex _SequenceIndex;
831
832 if (_GLIBCXX_PARALLEL_CONDITION(
833 static_cast<_SequenceIndex>(__end - __begin)
834 >= __gnu_parallel::_Settings::get().count_minimal_n
835 && __gnu_parallel::__is_parallel(__parallelism_tag)))
836 {
837 __gnu_parallel::__count_selector<_RAIter, _DifferenceType>
838 __functionality;
839 _DifferenceType __res = 0;
840 __gnu_parallel::
841 __for_each_template_random_access(
842 __begin, __end, __value, __functionality,
843 std::plus<_SequenceIndex>(), __res, __res, -1,
844 __parallelism_tag);
845 return __res;
846 }
847 else
848 return count(__begin, __end, __value,
849 __gnu_parallel::sequential_tag());
850 }
851
852 // Sequential fallback for input iterator case.
853 template<typename _IIter, typename _Tp, typename _IteratorTag>
854 inline typename iterator_traits<_IIter>::difference_type
855 __count_switch(_IIter __begin, _IIter __end, const _Tp& __value,
856 _IteratorTag)
857 { return count(__begin, __end, __value, __gnu_parallel::sequential_tag());
858 }
859
860 // Public interface.
861 template<typename _IIter, typename _Tp>
862 inline typename iterator_traits<_IIter>::difference_type
863 count(_IIter __begin, _IIter __end, const _Tp& __value,
864 __gnu_parallel::_Parallelism __parallelism_tag)
865 {
866 return __count_switch(__begin, __end, __value,
867 std::__iterator_category(__begin),
868 __parallelism_tag);
869 }
870
871 template<typename _IIter, typename _Tp>
872 inline typename iterator_traits<_IIter>::difference_type
873 count(_IIter __begin, _IIter __end, const _Tp& __value)
874 {
875 return __count_switch(__begin, __end, __value,
876 std::__iterator_category(__begin));
877 }
878
879
880 // Sequential fallback.
881 template<typename _IIter, typename _Predicate>
882 inline typename iterator_traits<_IIter>::difference_type
883 count_if(_IIter __begin, _IIter __end, _Predicate __pred,
884 __gnu_parallel::sequential_tag)
885 { return _GLIBCXX_STD_A::count_if(__begin, __end, __pred); }
886
887 // Parallel count_if for random access iterators
888 template<typename _RAIter, typename _Predicate>
889 typename iterator_traits<_RAIter>::difference_type
890 __count_if_switch(_RAIter __begin, _RAIter __end,
891 _Predicate __pred, random_access_iterator_tag,
892 __gnu_parallel::_Parallelism __parallelism_tag)
893 {
894 typedef iterator_traits<_RAIter> _TraitsType;
895 typedef typename _TraitsType::value_type _ValueType;
896 typedef typename _TraitsType::difference_type _DifferenceType;
897 typedef __gnu_parallel::_SequenceIndex _SequenceIndex;
898
899 if (_GLIBCXX_PARALLEL_CONDITION(
900 static_cast<_SequenceIndex>(__end - __begin)
901 >= __gnu_parallel::_Settings::get().count_minimal_n
902 && __gnu_parallel::__is_parallel(__parallelism_tag)))
903 {
904 _DifferenceType __res = 0;
905 __gnu_parallel::
906 __count_if_selector<_RAIter, _DifferenceType>
907 __functionality;
908 __gnu_parallel::
909 __for_each_template_random_access(
910 __begin, __end, __pred, __functionality,
911 std::plus<_SequenceIndex>(), __res, __res, -1,
912 __parallelism_tag);
913 return __res;
914 }
915 else
916 return count_if(__begin, __end, __pred,
917 __gnu_parallel::sequential_tag());
918 }
919
920 // Sequential fallback for input iterator case.
921 template<typename _IIter, typename _Predicate, typename _IteratorTag>
922 inline typename iterator_traits<_IIter>::difference_type
923 __count_if_switch(_IIter __begin, _IIter __end, _Predicate __pred,
924 _IteratorTag)
925 { return count_if(__begin, __end, __pred,
926 __gnu_parallel::sequential_tag()); }
927
928 // Public interface.
929 template<typename _IIter, typename _Predicate>
930 inline typename iterator_traits<_IIter>::difference_type
931 count_if(_IIter __begin, _IIter __end, _Predicate __pred,
932 __gnu_parallel::_Parallelism __parallelism_tag)
933 {
934 return __count_if_switch(__begin, __end, __pred,
935 std::__iterator_category(__begin),
936 __parallelism_tag);
937 }
938
939 template<typename _IIter, typename _Predicate>
940 inline typename iterator_traits<_IIter>::difference_type
941 count_if(_IIter __begin, _IIter __end, _Predicate __pred)
942 {
943 return __count_if_switch(__begin, __end, __pred,
944 std::__iterator_category(__begin));
945 }
946
947
948 // Sequential fallback.
949 template<typename _FIterator1, typename _FIterator2>
950 inline _FIterator1
951 search(_FIterator1 __begin1, _FIterator1 __end1,
952 _FIterator2 __begin2, _FIterator2 __end2,
953 __gnu_parallel::sequential_tag)
954 { return _GLIBCXX_STD_A::search(__begin1, __end1, __begin2, __end2); }
955
956 // Parallel algorithm for random access iterator
957 template<typename _RAIter1, typename _RAIter2>
958 _RAIter1
959 __search_switch(_RAIter1 __begin1, _RAIter1 __end1,
960 _RAIter2 __begin2, _RAIter2 __end2,
961 random_access_iterator_tag, random_access_iterator_tag)
962 {
963 typedef typename std::iterator_traits<_RAIter1>::value_type _ValueType1;
964 typedef typename std::iterator_traits<_RAIter2>::value_type _ValueType2;
965
966 if (_GLIBCXX_PARALLEL_CONDITION(
967 static_cast<__gnu_parallel::_SequenceIndex>(__end1 - __begin1)
968 >= __gnu_parallel::_Settings::get().search_minimal_n))
969 return __gnu_parallel::
970 __search_template(
971 __begin1, __end1, __begin2, __end2,
972 __gnu_parallel::_EqualTo<_ValueType1, _ValueType2>());
973 else
974 return search(__begin1, __end1, __begin2, __end2,
975 __gnu_parallel::sequential_tag());
976 }
977
978 // Sequential fallback for input iterator case
979 template<typename _FIterator1, typename _FIterator2,
980 typename _IteratorTag1, typename _IteratorTag2>
981 inline _FIterator1
982 __search_switch(_FIterator1 __begin1, _FIterator1 __end1,
983 _FIterator2 __begin2, _FIterator2 __end2,
984 _IteratorTag1, _IteratorTag2)
985 { return search(__begin1, __end1, __begin2, __end2,
986 __gnu_parallel::sequential_tag()); }
987
988 // Public interface.
989 template<typename _FIterator1, typename _FIterator2>
990 inline _FIterator1
991 search(_FIterator1 __begin1, _FIterator1 __end1,
992 _FIterator2 __begin2, _FIterator2 __end2)
993 {
994 return __search_switch(__begin1, __end1, __begin2, __end2,
995 std::__iterator_category(__begin1),
996 std::__iterator_category(__begin2));
997 }
998
999 // Public interface.
1000 template<typename _FIterator1, typename _FIterator2,
1001 typename _BinaryPredicate>
1002 inline _FIterator1
1003 search(_FIterator1 __begin1, _FIterator1 __end1,
1004 _FIterator2 __begin2, _FIterator2 __end2,
1005 _BinaryPredicate __pred, __gnu_parallel::sequential_tag)
1006 { return _GLIBCXX_STD_A::search(
1007 __begin1, __end1, __begin2, __end2, __pred); }
1008
1009 // Parallel algorithm for random access iterator.
1010 template<typename _RAIter1, typename _RAIter2,
1011 typename _BinaryPredicate>
1012 _RAIter1
1013 __search_switch(_RAIter1 __begin1, _RAIter1 __end1,
1014 _RAIter2 __begin2, _RAIter2 __end2,
1015 _BinaryPredicate __pred,
1016 random_access_iterator_tag, random_access_iterator_tag)
1017 {
1018 if (_GLIBCXX_PARALLEL_CONDITION(
1019 static_cast<__gnu_parallel::_SequenceIndex>(__end1 - __begin1)
1020 >= __gnu_parallel::_Settings::get().search_minimal_n))
1021 return __gnu_parallel::__search_template(__begin1, __end1,
1022 __begin2, __end2, __pred);
1023 else
1024 return search(__begin1, __end1, __begin2, __end2, __pred,
1025 __gnu_parallel::sequential_tag());
1026 }
1027
1028 // Sequential fallback for input iterator case
1029 template<typename _FIterator1, typename _FIterator2,
1030 typename _BinaryPredicate, typename _IteratorTag1,
1031 typename _IteratorTag2>
1032 inline _FIterator1
1033 __search_switch(_FIterator1 __begin1, _FIterator1 __end1,
1034 _FIterator2 __begin2, _FIterator2 __end2,
1035 _BinaryPredicate __pred, _IteratorTag1, _IteratorTag2)
1036 { return search(__begin1, __end1, __begin2, __end2, __pred,
1037 __gnu_parallel::sequential_tag()); }
1038
1039 // Public interface
1040 template<typename _FIterator1, typename _FIterator2,
1041 typename _BinaryPredicate>
1042 inline _FIterator1
1043 search(_FIterator1 __begin1, _FIterator1 __end1,
1044 _FIterator2 __begin2, _FIterator2 __end2,
1045 _BinaryPredicate __pred)
1046 {
1047 return __search_switch(__begin1, __end1, __begin2, __end2, __pred,
1048 std::__iterator_category(__begin1),
1049 std::__iterator_category(__begin2));
1050 }
1051
1052 #if __cplusplus >= 201703L
1053 /** @brief Search a sequence using a Searcher object.
1054 *
1055 * @param __first A forward iterator.
1056 * @param __last A forward iterator.
1057 * @param __searcher A callable object.
1058 * @return @p __searcher(__first,__last).first
1059 */
1060 template<typename _ForwardIterator, typename _Searcher>
1061 inline _ForwardIterator
1062 search(_ForwardIterator __first, _ForwardIterator __last,
1063 const _Searcher& __searcher)
1064 { return __searcher(__first, __last).first; }
1065 #endif
1066
1067 // Sequential fallback
1068 template<typename _FIterator, typename _Integer, typename _Tp>
1069 inline _FIterator
1070 search_n(_FIterator __begin, _FIterator __end, _Integer __count,
1071 const _Tp& __val, __gnu_parallel::sequential_tag)
1072 { return _GLIBCXX_STD_A::search_n(__begin, __end, __count, __val); }
1073
1074 // Sequential fallback
1075 template<typename _FIterator, typename _Integer, typename _Tp,
1076 typename _BinaryPredicate>
1077 inline _FIterator
1078 search_n(_FIterator __begin, _FIterator __end, _Integer __count,
1079 const _Tp& __val, _BinaryPredicate __binary_pred,
1080 __gnu_parallel::sequential_tag)
1081 { return _GLIBCXX_STD_A::search_n(
1082 __begin, __end, __count, __val, __binary_pred); }
1083
1084 // Public interface.
1085 template<typename _FIterator, typename _Integer, typename _Tp>
1086 inline _FIterator
1087 search_n(_FIterator __begin, _FIterator __end, _Integer __count,
1088 const _Tp& __val)
1089 {
1090 typedef typename iterator_traits<_FIterator>::value_type _ValueType;
1091 return __gnu_parallel::search_n(__begin, __end, __count, __val,
1092 __gnu_parallel::_EqualTo<_ValueType, _Tp>());
1093 }
1094
1095 // Parallel algorithm for random access iterators.
1096 template<typename _RAIter, typename _Integer,
1097 typename _Tp, typename _BinaryPredicate>
1098 _RAIter
1099 __search_n_switch(_RAIter __begin, _RAIter __end, _Integer __count,
1100 const _Tp& __val, _BinaryPredicate __binary_pred,
1101 random_access_iterator_tag)
1102 {
1103 if (_GLIBCXX_PARALLEL_CONDITION(
1104 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
1105 >= __gnu_parallel::_Settings::get().search_minimal_n))
1106 {
1107 __gnu_parallel::_PseudoSequence<_Tp, _Integer> __ps(__val, __count);
1108 return __gnu_parallel::__search_template(
1109 __begin, __end, __ps.begin(), __ps.end(), __binary_pred);
1110 }
1111 else
1112 return _GLIBCXX_STD_A::search_n(__begin, __end, __count, __val,
1113 __binary_pred);
1114 }
1115
1116 // Sequential fallback for input iterator case.
1117 template<typename _FIterator, typename _Integer, typename _Tp,
1118 typename _BinaryPredicate, typename _IteratorTag>
1119 inline _FIterator
1120 __search_n_switch(_FIterator __begin, _FIterator __end, _Integer __count,
1121 const _Tp& __val, _BinaryPredicate __binary_pred,
1122 _IteratorTag)
1123 { return _GLIBCXX_STD_A::search_n(__begin, __end, __count, __val,
1124 __binary_pred); }
1125
1126 // Public interface.
1127 template<typename _FIterator, typename _Integer, typename _Tp,
1128 typename _BinaryPredicate>
1129 inline _FIterator
1130 search_n(_FIterator __begin, _FIterator __end, _Integer __count,
1131 const _Tp& __val, _BinaryPredicate __binary_pred)
1132 {
1133 return __search_n_switch(__begin, __end, __count, __val, __binary_pred,
1134 std::__iterator_category(__begin));
1135 }
1136
1137
1138 // Sequential fallback.
1139 template<typename _IIter, typename _OutputIterator,
1140 typename _UnaryOperation>
1141 inline _OutputIterator
1142 transform(_IIter __begin, _IIter __end, _OutputIterator __result,
1143 _UnaryOperation __unary_op, __gnu_parallel::sequential_tag)
1144 { return _GLIBCXX_STD_A::transform(__begin, __end, __result, __unary_op); }
1145
1146 // Parallel unary transform for random access iterators.
1147 template<typename _RAIter1, typename _RAIter2,
1148 typename _UnaryOperation>
1149 _RAIter2
1150 __transform1_switch(_RAIter1 __begin, _RAIter1 __end,
1151 _RAIter2 __result, _UnaryOperation __unary_op,
1152 random_access_iterator_tag, random_access_iterator_tag,
1153 __gnu_parallel::_Parallelism __parallelism_tag)
1154 {
1155 if (_GLIBCXX_PARALLEL_CONDITION(
1156 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
1157 >= __gnu_parallel::_Settings::get().transform_minimal_n
1158 && __gnu_parallel::__is_parallel(__parallelism_tag)))
1159 {
1160 bool __dummy = true;
1161 typedef __gnu_parallel::_IteratorPair<_RAIter1,
1162 _RAIter2, random_access_iterator_tag> _ItTrip;
1163 _ItTrip __begin_pair(__begin, __result),
1164 __end_pair(__end, __result + (__end - __begin));
1165 __gnu_parallel::__transform1_selector<_ItTrip> __functionality;
1166 __gnu_parallel::
1167 __for_each_template_random_access(
1168 __begin_pair, __end_pair, __unary_op, __functionality,
1169 __gnu_parallel::_DummyReduct(),
1170 __dummy, __dummy, -1, __parallelism_tag);
1171 return __functionality._M_finish_iterator;
1172 }
1173 else
1174 return transform(__begin, __end, __result, __unary_op,
1175 __gnu_parallel::sequential_tag());
1176 }
1177
1178 // Sequential fallback for input iterator case.
1179 template<typename _RAIter1, typename _RAIter2,
1180 typename _UnaryOperation, typename _IteratorTag1,
1181 typename _IteratorTag2>
1182 inline _RAIter2
1183 __transform1_switch(_RAIter1 __begin, _RAIter1 __end,
1184 _RAIter2 __result, _UnaryOperation __unary_op,
1185 _IteratorTag1, _IteratorTag2)
1186 { return transform(__begin, __end, __result, __unary_op,
1187 __gnu_parallel::sequential_tag()); }
1188
1189 // Public interface.
1190 template<typename _IIter, typename _OutputIterator,
1191 typename _UnaryOperation>
1192 inline _OutputIterator
1193 transform(_IIter __begin, _IIter __end, _OutputIterator __result,
1194 _UnaryOperation __unary_op,
1195 __gnu_parallel::_Parallelism __parallelism_tag)
1196 {
1197 return __transform1_switch(__begin, __end, __result, __unary_op,
1198 std::__iterator_category(__begin),
1199 std::__iterator_category(__result),
1200 __parallelism_tag);
1201 }
1202
1203 template<typename _IIter, typename _OutputIterator,
1204 typename _UnaryOperation>
1205 inline _OutputIterator
1206 transform(_IIter __begin, _IIter __end, _OutputIterator __result,
1207 _UnaryOperation __unary_op)
1208 {
1209 return __transform1_switch(__begin, __end, __result, __unary_op,
1210 std::__iterator_category(__begin),
1211 std::__iterator_category(__result));
1212 }
1213
1214
1215 // Sequential fallback
1216 template<typename _IIter1, typename _IIter2,
1217 typename _OutputIterator, typename _BinaryOperation>
1218 inline _OutputIterator
1219 transform(_IIter1 __begin1, _IIter1 __end1,
1220 _IIter2 __begin2, _OutputIterator __result,
1221 _BinaryOperation __binary_op, __gnu_parallel::sequential_tag)
1222 { return _GLIBCXX_STD_A::transform(__begin1, __end1,
1223 __begin2, __result, __binary_op); }
1224
1225 // Parallel binary transform for random access iterators.
1226 template<typename _RAIter1, typename _RAIter2,
1227 typename _RAIter3, typename _BinaryOperation>
1228 _RAIter3
1229 __transform2_switch(_RAIter1 __begin1, _RAIter1 __end1,
1230 _RAIter2 __begin2,
1231 _RAIter3 __result, _BinaryOperation __binary_op,
1232 random_access_iterator_tag, random_access_iterator_tag,
1233 random_access_iterator_tag,
1234 __gnu_parallel::_Parallelism __parallelism_tag)
1235 {
1236 if (_GLIBCXX_PARALLEL_CONDITION(
1237 (__end1 - __begin1) >=
1238 __gnu_parallel::_Settings::get().transform_minimal_n
1239 && __gnu_parallel::__is_parallel(__parallelism_tag)))
1240 {
1241 bool __dummy = true;
1242 typedef __gnu_parallel::_IteratorTriple<_RAIter1,
1243 _RAIter2, _RAIter3,
1244 random_access_iterator_tag> _ItTrip;
1245 _ItTrip __begin_triple(__begin1, __begin2, __result),
1246 __end_triple(__end1, __begin2 + (__end1 - __begin1),
1247 __result + (__end1 - __begin1));
1248 __gnu_parallel::__transform2_selector<_ItTrip> __functionality;
1249 __gnu_parallel::
1250 __for_each_template_random_access(__begin_triple, __end_triple,
1251 __binary_op, __functionality,
1252 __gnu_parallel::_DummyReduct(),
1253 __dummy, __dummy, -1,
1254 __parallelism_tag);
1255 return __functionality._M_finish_iterator;
1256 }
1257 else
1258 return transform(__begin1, __end1, __begin2, __result, __binary_op,
1259 __gnu_parallel::sequential_tag());
1260 }
1261
1262 // Sequential fallback for input iterator case.
1263 template<typename _IIter1, typename _IIter2,
1264 typename _OutputIterator, typename _BinaryOperation,
1265 typename _Tag1, typename _Tag2, typename _Tag3>
1266 inline _OutputIterator
1267 __transform2_switch(_IIter1 __begin1, _IIter1 __end1,
1268 _IIter2 __begin2, _OutputIterator __result,
1269 _BinaryOperation __binary_op, _Tag1, _Tag2, _Tag3)
1270 { return transform(__begin1, __end1, __begin2, __result, __binary_op,
1271 __gnu_parallel::sequential_tag()); }
1272
1273 // Public interface.
1274 template<typename _IIter1, typename _IIter2,
1275 typename _OutputIterator, typename _BinaryOperation>
1276 inline _OutputIterator
1277 transform(_IIter1 __begin1, _IIter1 __end1,
1278 _IIter2 __begin2, _OutputIterator __result,
1279 _BinaryOperation __binary_op,
1280 __gnu_parallel::_Parallelism __parallelism_tag)
1281 {
1282 return __transform2_switch(
1283 __begin1, __end1, __begin2, __result, __binary_op,
1284 std::__iterator_category(__begin1),
1285 std::__iterator_category(__begin2),
1286 std::__iterator_category(__result),
1287 __parallelism_tag);
1288 }
1289
1290 template<typename _IIter1, typename _IIter2,
1291 typename _OutputIterator, typename _BinaryOperation>
1292 inline _OutputIterator
1293 transform(_IIter1 __begin1, _IIter1 __end1,
1294 _IIter2 __begin2, _OutputIterator __result,
1295 _BinaryOperation __binary_op)
1296 {
1297 return __transform2_switch(
1298 __begin1, __end1, __begin2, __result, __binary_op,
1299 std::__iterator_category(__begin1),
1300 std::__iterator_category(__begin2),
1301 std::__iterator_category(__result));
1302 }
1303
1304 // Sequential fallback
1305 template<typename _FIterator, typename _Tp>
1306 inline void
1307 replace(_FIterator __begin, _FIterator __end, const _Tp& __old_value,
1308 const _Tp& __new_value, __gnu_parallel::sequential_tag)
1309 { _GLIBCXX_STD_A::replace(__begin, __end, __old_value, __new_value); }
1310
1311 // Sequential fallback for input iterator case
1312 template<typename _FIterator, typename _Tp, typename _IteratorTag>
1313 inline void
1314 __replace_switch(_FIterator __begin, _FIterator __end,
1315 const _Tp& __old_value, const _Tp& __new_value,
1316 _IteratorTag)
1317 { replace(__begin, __end, __old_value, __new_value,
1318 __gnu_parallel::sequential_tag()); }
1319
1320 // Parallel replace for random access iterators
1321 template<typename _RAIter, typename _Tp>
1322 inline void
1323 __replace_switch(_RAIter __begin, _RAIter __end,
1324 const _Tp& __old_value, const _Tp& __new_value,
1325 random_access_iterator_tag,
1326 __gnu_parallel::_Parallelism __parallelism_tag)
1327 {
1328 // XXX parallel version is where?
1329 replace(__begin, __end, __old_value, __new_value,
1330 __gnu_parallel::sequential_tag());
1331 }
1332
1333 // Public interface
1334 template<typename _FIterator, typename _Tp>
1335 inline void
1336 replace(_FIterator __begin, _FIterator __end, const _Tp& __old_value,
1337 const _Tp& __new_value,
1338 __gnu_parallel::_Parallelism __parallelism_tag)
1339 {
1340 __replace_switch(__begin, __end, __old_value, __new_value,
1341 std::__iterator_category(__begin),
1342 __parallelism_tag);
1343 }
1344
1345 template<typename _FIterator, typename _Tp>
1346 inline void
1347 replace(_FIterator __begin, _FIterator __end, const _Tp& __old_value,
1348 const _Tp& __new_value)
1349 {
1350 __replace_switch(__begin, __end, __old_value, __new_value,
1351 std::__iterator_category(__begin));
1352 }
1353
1354
1355 // Sequential fallback
1356 template<typename _FIterator, typename _Predicate, typename _Tp>
1357 inline void
1358 replace_if(_FIterator __begin, _FIterator __end, _Predicate __pred,
1359 const _Tp& __new_value, __gnu_parallel::sequential_tag)
1360 { _GLIBCXX_STD_A::replace_if(__begin, __end, __pred, __new_value); }
1361
1362 // Sequential fallback for input iterator case
1363 template<typename _FIterator, typename _Predicate, typename _Tp,
1364 typename _IteratorTag>
1365 inline void
1366 __replace_if_switch(_FIterator __begin, _FIterator __end,
1367 _Predicate __pred, const _Tp& __new_value, _IteratorTag)
1368 { replace_if(__begin, __end, __pred, __new_value,
1369 __gnu_parallel::sequential_tag()); }
1370
1371 // Parallel algorithm for random access iterators.
1372 template<typename _RAIter, typename _Predicate, typename _Tp>
1373 void
1374 __replace_if_switch(_RAIter __begin, _RAIter __end,
1375 _Predicate __pred, const _Tp& __new_value,
1376 random_access_iterator_tag,
1377 __gnu_parallel::_Parallelism __parallelism_tag)
1378 {
1379 if (_GLIBCXX_PARALLEL_CONDITION(
1380 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
1381 >= __gnu_parallel::_Settings::get().replace_minimal_n
1382 && __gnu_parallel::__is_parallel(__parallelism_tag)))
1383 {
1384 bool __dummy;
1385 __gnu_parallel::
1386 __replace_if_selector<_RAIter, _Predicate, _Tp>
1387 __functionality(__new_value);
1388 __gnu_parallel::
1389 __for_each_template_random_access(
1390 __begin, __end, __pred, __functionality,
1391 __gnu_parallel::_DummyReduct(),
1392 true, __dummy, -1, __parallelism_tag);
1393 }
1394 else
1395 replace_if(__begin, __end, __pred, __new_value,
1396 __gnu_parallel::sequential_tag());
1397 }
1398
1399 // Public interface.
1400 template<typename _FIterator, typename _Predicate, typename _Tp>
1401 inline void
1402 replace_if(_FIterator __begin, _FIterator __end,
1403 _Predicate __pred, const _Tp& __new_value,
1404 __gnu_parallel::_Parallelism __parallelism_tag)
1405 {
1406 __replace_if_switch(__begin, __end, __pred, __new_value,
1407 std::__iterator_category(__begin),
1408 __parallelism_tag);
1409 }
1410
1411 template<typename _FIterator, typename _Predicate, typename _Tp>
1412 inline void
1413 replace_if(_FIterator __begin, _FIterator __end,
1414 _Predicate __pred, const _Tp& __new_value)
1415 {
1416 __replace_if_switch(__begin, __end, __pred, __new_value,
1417 std::__iterator_category(__begin));
1418 }
1419
1420 // Sequential fallback
1421 template<typename _FIterator, typename _Generator>
1422 inline void
1423 generate(_FIterator __begin, _FIterator __end, _Generator __gen,
1424 __gnu_parallel::sequential_tag)
1425 { _GLIBCXX_STD_A::generate(__begin, __end, __gen); }
1426
1427 // Sequential fallback for input iterator case.
1428 template<typename _FIterator, typename _Generator, typename _IteratorTag>
1429 inline void
1430 __generate_switch(_FIterator __begin, _FIterator __end, _Generator __gen,
1431 _IteratorTag)
1432 { generate(__begin, __end, __gen, __gnu_parallel::sequential_tag()); }
1433
1434 // Parallel algorithm for random access iterators.
1435 template<typename _RAIter, typename _Generator>
1436 void
1437 __generate_switch(_RAIter __begin, _RAIter __end,
1438 _Generator __gen, random_access_iterator_tag,
1439 __gnu_parallel::_Parallelism __parallelism_tag)
1440 {
1441 if (_GLIBCXX_PARALLEL_CONDITION(
1442 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
1443 >= __gnu_parallel::_Settings::get().generate_minimal_n
1444 && __gnu_parallel::__is_parallel(__parallelism_tag)))
1445 {
1446 bool __dummy;
1447 __gnu_parallel::__generate_selector<_RAIter>
1448 __functionality;
1449 __gnu_parallel::
1450 __for_each_template_random_access(
1451 __begin, __end, __gen, __functionality,
1452 __gnu_parallel::_DummyReduct(),
1453 true, __dummy, -1, __parallelism_tag);
1454 }
1455 else
1456 generate(__begin, __end, __gen, __gnu_parallel::sequential_tag());
1457 }
1458
1459 // Public interface.
1460 template<typename _FIterator, typename _Generator>
1461 inline void
1462 generate(_FIterator __begin, _FIterator __end,
1463 _Generator __gen, __gnu_parallel::_Parallelism __parallelism_tag)
1464 {
1465 __generate_switch(__begin, __end, __gen,
1466 std::__iterator_category(__begin),
1467 __parallelism_tag);
1468 }
1469
1470 template<typename _FIterator, typename _Generator>
1471 inline void
1472 generate(_FIterator __begin, _FIterator __end, _Generator __gen)
1473 {
1474 __generate_switch(__begin, __end, __gen,
1475 std::__iterator_category(__begin));
1476 }
1477
1478
1479 // Sequential fallback.
1480 template<typename _OutputIterator, typename _Size, typename _Generator>
1481 inline _OutputIterator
1482 generate_n(_OutputIterator __begin, _Size __n, _Generator __gen,
1483 __gnu_parallel::sequential_tag)
1484 { return _GLIBCXX_STD_A::generate_n(__begin, __n, __gen); }
1485
1486 // Sequential fallback for input iterator case.
1487 template<typename _OutputIterator, typename _Size, typename _Generator,
1488 typename _IteratorTag>
1489 inline _OutputIterator
1490 __generate_n_switch(_OutputIterator __begin, _Size __n, _Generator __gen,
1491 _IteratorTag)
1492 { return generate_n(__begin, __n, __gen,
1493 __gnu_parallel::sequential_tag()); }
1494
1495 // Parallel algorithm for random access iterators.
1496 template<typename _RAIter, typename _Size, typename _Generator>
1497 inline _RAIter
1498 __generate_n_switch(_RAIter __begin, _Size __n, _Generator __gen,
1499 random_access_iterator_tag,
1500 __gnu_parallel::_Parallelism __parallelism_tag)
1501 {
1502 // XXX parallel version is where?
1503 return generate_n(__begin, __n, __gen, __gnu_parallel::sequential_tag());
1504 }
1505
1506 // Public interface.
1507 template<typename _OutputIterator, typename _Size, typename _Generator>
1508 inline _OutputIterator
1509 generate_n(_OutputIterator __begin, _Size __n, _Generator __gen,
1510 __gnu_parallel::_Parallelism __parallelism_tag)
1511 {
1512 return __generate_n_switch(__begin, __n, __gen,
1513 std::__iterator_category(__begin),
1514 __parallelism_tag);
1515 }
1516
1517 template<typename _OutputIterator, typename _Size, typename _Generator>
1518 inline _OutputIterator
1519 generate_n(_OutputIterator __begin, _Size __n, _Generator __gen)
1520 {
1521 return __generate_n_switch(__begin, __n, __gen,
1522 std::__iterator_category(__begin));
1523 }
1524
1525
1526 // Sequential fallback.
1527 template<typename _RAIter>
1528 inline void
1529 random_shuffle(_RAIter __begin, _RAIter __end,
1530 __gnu_parallel::sequential_tag)
1531 { _GLIBCXX_STD_A::random_shuffle(__begin, __end); }
1532
1533 // Sequential fallback.
1534 template<typename _RAIter, typename _RandomNumberGenerator>
1535 inline void
1536 random_shuffle(_RAIter __begin, _RAIter __end,
1537 _RandomNumberGenerator& __rand,
1538 __gnu_parallel::sequential_tag)
1539 { _GLIBCXX_STD_A::random_shuffle(__begin, __end, __rand); }
1540
1541
1542 /** @brief Functor wrapper for std::rand(). */
1543 template<typename _MustBeInt = int>
1544 struct _CRandNumber
1545 {
1546 int
1547 operator()(int __limit)
1548 { return rand() % __limit; }
1549 };
1550
1551 // Fill in random number generator.
1552 template<typename _RAIter>
1553 inline void
1554 random_shuffle(_RAIter __begin, _RAIter __end)
1555 {
1556 _CRandNumber<> __r;
1557 // Parallelization still possible.
1558 __gnu_parallel::random_shuffle(__begin, __end, __r);
1559 }
1560
1561 // Parallel algorithm for random access iterators.
1562 template<typename _RAIter, typename _RandomNumberGenerator>
1563 void
1564 random_shuffle(_RAIter __begin, _RAIter __end,
1565 #if __cplusplus >= 201103L
1566 _RandomNumberGenerator&& __rand)
1567 #else
1568 _RandomNumberGenerator& __rand)
1569 #endif
1570 {
1571 if (__begin == __end)
1572 return;
1573 if (_GLIBCXX_PARALLEL_CONDITION(
1574 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
1575 >= __gnu_parallel::_Settings::get().random_shuffle_minimal_n))
1576 __gnu_parallel::__parallel_random_shuffle(__begin, __end, __rand);
1577 else
1578 __gnu_parallel::__sequential_random_shuffle(__begin, __end, __rand);
1579 }
1580
1581 // Sequential fallback.
1582 template<typename _FIterator, typename _Predicate>
1583 inline _FIterator
1584 partition(_FIterator __begin, _FIterator __end,
1585 _Predicate __pred, __gnu_parallel::sequential_tag)
1586 { return _GLIBCXX_STD_A::partition(__begin, __end, __pred); }
1587
1588 // Sequential fallback for input iterator case.
1589 template<typename _FIterator, typename _Predicate, typename _IteratorTag>
1590 inline _FIterator
1591 __partition_switch(_FIterator __begin, _FIterator __end,
1592 _Predicate __pred, _IteratorTag)
1593 { return partition(__begin, __end, __pred,
1594 __gnu_parallel::sequential_tag()); }
1595
1596 // Parallel algorithm for random access iterators.
1597 template<typename _RAIter, typename _Predicate>
1598 _RAIter
1599 __partition_switch(_RAIter __begin, _RAIter __end,
1600 _Predicate __pred, random_access_iterator_tag)
1601 {
1602 if (_GLIBCXX_PARALLEL_CONDITION(
1603 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
1604 >= __gnu_parallel::_Settings::get().partition_minimal_n))
1605 {
1606 typedef typename std::iterator_traits<_RAIter>::
1607 difference_type _DifferenceType;
1608 _DifferenceType __middle = __gnu_parallel::
1609 __parallel_partition(__begin, __end, __pred,
1610 __gnu_parallel::__get_max_threads());
1611 return __begin + __middle;
1612 }
1613 else
1614 return partition(__begin, __end, __pred,
1615 __gnu_parallel::sequential_tag());
1616 }
1617
1618 // Public interface.
1619 template<typename _FIterator, typename _Predicate>
1620 inline _FIterator
1621 partition(_FIterator __begin, _FIterator __end, _Predicate __pred)
1622 {
1623 return __partition_switch(__begin, __end, __pred,
1624 std::__iterator_category(__begin));
1625 }
1626
1627 // sort interface
1628
1629 // Sequential fallback
1630 template<typename _RAIter>
1631 inline void
1632 sort(_RAIter __begin, _RAIter __end,
1633 __gnu_parallel::sequential_tag)
1634 { _GLIBCXX_STD_A::sort(__begin, __end); }
1635
1636 // Sequential fallback
1637 template<typename _RAIter, typename _Compare>
1638 inline void
1639 sort(_RAIter __begin, _RAIter __end, _Compare __comp,
1640 __gnu_parallel::sequential_tag)
1641 { _GLIBCXX_STD_A::sort<_RAIter, _Compare>(__begin, __end,
1642 __comp); }
1643
1644 // Public interface
1645 template<typename _RAIter, typename _Compare,
1646 typename _Parallelism>
1647 void
1648 sort(_RAIter __begin, _RAIter __end, _Compare __comp,
1649 _Parallelism __parallelism)
1650 {
1651 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1652
1653 if (__begin != __end)
1654 {
1655 if (_GLIBCXX_PARALLEL_CONDITION(
1656 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin) >=
1657 __gnu_parallel::_Settings::get().sort_minimal_n))
1658 __gnu_parallel::__parallel_sort<false>(
1659 __begin, __end, __comp, __parallelism);
1660 else
1661 sort(__begin, __end, __comp, __gnu_parallel::sequential_tag());
1662 }
1663 }
1664
1665 // Public interface, insert default comparator
1666 template<typename _RAIter>
1667 inline void
1668 sort(_RAIter __begin, _RAIter __end)
1669 {
1670 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1671 sort(__begin, __end, std::less<_ValueType>(),
1672 __gnu_parallel::default_parallel_tag());
1673 }
1674
1675 // Public interface, insert default comparator
1676 template<typename _RAIter>
1677 inline void
1678 sort(_RAIter __begin, _RAIter __end,
1679 __gnu_parallel::default_parallel_tag __parallelism)
1680 {
1681 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1682 sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1683 }
1684
1685 // Public interface, insert default comparator
1686 template<typename _RAIter>
1687 inline void
1688 sort(_RAIter __begin, _RAIter __end,
1689 __gnu_parallel::parallel_tag __parallelism)
1690 {
1691 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1692 sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1693 }
1694
1695 // Public interface, insert default comparator
1696 template<typename _RAIter>
1697 inline void
1698 sort(_RAIter __begin, _RAIter __end,
1699 __gnu_parallel::multiway_mergesort_tag __parallelism)
1700 {
1701 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1702 sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1703 }
1704
1705 // Public interface, insert default comparator
1706 template<typename _RAIter>
1707 inline void
1708 sort(_RAIter __begin, _RAIter __end,
1709 __gnu_parallel::multiway_mergesort_sampling_tag __parallelism)
1710 {
1711 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1712 sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1713 }
1714
1715 // Public interface, insert default comparator
1716 template<typename _RAIter>
1717 inline void
1718 sort(_RAIter __begin, _RAIter __end,
1719 __gnu_parallel::multiway_mergesort_exact_tag __parallelism)
1720 {
1721 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1722 sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1723 }
1724
1725 // Public interface, insert default comparator
1726 template<typename _RAIter>
1727 inline void
1728 sort(_RAIter __begin, _RAIter __end,
1729 __gnu_parallel::quicksort_tag __parallelism)
1730 {
1731 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1732 sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1733 }
1734
1735 // Public interface, insert default comparator
1736 template<typename _RAIter>
1737 inline void
1738 sort(_RAIter __begin, _RAIter __end,
1739 __gnu_parallel::balanced_quicksort_tag __parallelism)
1740 {
1741 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1742 sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1743 }
1744
1745 // Public interface
1746 template<typename _RAIter, typename _Compare>
1747 void
1748 sort(_RAIter __begin, _RAIter __end, _Compare __comp)
1749 {
1750 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1751 sort(__begin, __end, __comp, __gnu_parallel::default_parallel_tag());
1752 }
1753
1754 // stable_sort interface
1755
1756
1757 // Sequential fallback
1758 template<typename _RAIter>
1759 inline void
1760 stable_sort(_RAIter __begin, _RAIter __end,
1761 __gnu_parallel::sequential_tag)
1762 { _GLIBCXX_STD_A::stable_sort(__begin, __end); }
1763
1764 // Sequential fallback
1765 template<typename _RAIter, typename _Compare>
1766 inline void
1767 stable_sort(_RAIter __begin, _RAIter __end,
1768 _Compare __comp, __gnu_parallel::sequential_tag)
1769 { _GLIBCXX_STD_A::stable_sort<_RAIter, _Compare>(__begin, __end, __comp); }
1770
1771 // Public interface
1772 template<typename _RAIter, typename _Compare,
1773 typename _Parallelism>
1774 void
1775 stable_sort(_RAIter __begin, _RAIter __end,
1776 _Compare __comp, _Parallelism __parallelism)
1777 {
1778 typedef iterator_traits<_RAIter> _TraitsType;
1779 typedef typename _TraitsType::value_type _ValueType;
1780
1781 if (__begin != __end)
1782 {
1783 if (_GLIBCXX_PARALLEL_CONDITION(
1784 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin) >=
1785 __gnu_parallel::_Settings::get().sort_minimal_n))
1786 __gnu_parallel::__parallel_sort<true>(__begin, __end,
1787 __comp, __parallelism);
1788 else
1789 stable_sort(__begin, __end, __comp,
1790 __gnu_parallel::sequential_tag());
1791 }
1792 }
1793
1794 // Public interface, insert default comparator
1795 template<typename _RAIter>
1796 inline void
1797 stable_sort(_RAIter __begin, _RAIter __end)
1798 {
1799 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1800 stable_sort(__begin, __end, std::less<_ValueType>(),
1801 __gnu_parallel::default_parallel_tag());
1802 }
1803
1804 // Public interface, insert default comparator
1805 template<typename _RAIter>
1806 inline void
1807 stable_sort(_RAIter __begin, _RAIter __end,
1808 __gnu_parallel::default_parallel_tag __parallelism)
1809 {
1810 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1811 stable_sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1812 }
1813
1814 // Public interface, insert default comparator
1815 template<typename _RAIter>
1816 inline void
1817 stable_sort(_RAIter __begin, _RAIter __end,
1818 __gnu_parallel::parallel_tag __parallelism)
1819 {
1820 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1821 stable_sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1822 }
1823
1824 // Public interface, insert default comparator
1825 template<typename _RAIter>
1826 inline void
1827 stable_sort(_RAIter __begin, _RAIter __end,
1828 __gnu_parallel::multiway_mergesort_tag __parallelism)
1829 {
1830 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1831 stable_sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1832 }
1833
1834 // Public interface, insert default comparator
1835 template<typename _RAIter>
1836 inline void
1837 stable_sort(_RAIter __begin, _RAIter __end,
1838 __gnu_parallel::quicksort_tag __parallelism)
1839 {
1840 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1841 stable_sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1842 }
1843
1844 // Public interface, insert default comparator
1845 template<typename _RAIter>
1846 inline void
1847 stable_sort(_RAIter __begin, _RAIter __end,
1848 __gnu_parallel::balanced_quicksort_tag __parallelism)
1849 {
1850 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1851 stable_sort(__begin, __end, std::less<_ValueType>(), __parallelism);
1852 }
1853
1854 // Public interface
1855 template<typename _RAIter, typename _Compare>
1856 void
1857 stable_sort(_RAIter __begin, _RAIter __end, _Compare __comp)
1858 {
1859 stable_sort(
1860 __begin, __end, __comp, __gnu_parallel::default_parallel_tag());
1861 }
1862
1863 // Sequential fallback
1864 template<typename _IIter1, typename _IIter2,
1865 typename _OutputIterator>
1866 inline _OutputIterator
1867 merge(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
1868 _IIter2 __end2, _OutputIterator __result,
1869 __gnu_parallel::sequential_tag)
1870 { return _GLIBCXX_STD_A::merge(
1871 __begin1, __end1, __begin2, __end2, __result); }
1872
1873 // Sequential fallback
1874 template<typename _IIter1, typename _IIter2,
1875 typename _OutputIterator, typename _Compare>
1876 inline _OutputIterator
1877 merge(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
1878 _IIter2 __end2, _OutputIterator __result, _Compare __comp,
1879 __gnu_parallel::sequential_tag)
1880 { return _GLIBCXX_STD_A::merge(
1881 __begin1, __end1, __begin2, __end2, __result, __comp); }
1882
1883 // Sequential fallback for input iterator case
1884 template<typename _IIter1, typename _IIter2, typename _OutputIterator,
1885 typename _Compare, typename _IteratorTag1,
1886 typename _IteratorTag2, typename _IteratorTag3>
1887 inline _OutputIterator
1888 __merge_switch(_IIter1 __begin1, _IIter1 __end1,
1889 _IIter2 __begin2, _IIter2 __end2,
1890 _OutputIterator __result, _Compare __comp,
1891 _IteratorTag1, _IteratorTag2, _IteratorTag3)
1892 { return _GLIBCXX_STD_A::merge(__begin1, __end1, __begin2, __end2,
1893 __result, __comp); }
1894
1895 // Parallel algorithm for random access iterators
1896 template<typename _IIter1, typename _IIter2,
1897 typename _OutputIterator, typename _Compare>
1898 _OutputIterator
1899 __merge_switch(_IIter1 __begin1, _IIter1 __end1,
1900 _IIter2 __begin2, _IIter2 __end2,
1901 _OutputIterator __result, _Compare __comp,
1902 random_access_iterator_tag, random_access_iterator_tag,
1903 random_access_iterator_tag)
1904 {
1905 if (_GLIBCXX_PARALLEL_CONDITION(
1906 (static_cast<__gnu_parallel::_SequenceIndex>(__end1 - __begin1)
1907 >= __gnu_parallel::_Settings::get().merge_minimal_n
1908 || static_cast<__gnu_parallel::_SequenceIndex>(__end2 - __begin2)
1909 >= __gnu_parallel::_Settings::get().merge_minimal_n)))
1910 return __gnu_parallel::__parallel_merge_advance(
1911 __begin1, __end1, __begin2, __end2, __result,
1912 (__end1 - __begin1) + (__end2 - __begin2), __comp);
1913 else
1914 return __gnu_parallel::__merge_advance(
1915 __begin1, __end1, __begin2, __end2, __result,
1916 (__end1 - __begin1) + (__end2 - __begin2), __comp);
1917 }
1918
1919 // Public interface
1920 template<typename _IIter1, typename _IIter2,
1921 typename _OutputIterator, typename _Compare>
1922 inline _OutputIterator
1923 merge(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
1924 _IIter2 __end2, _OutputIterator __result, _Compare __comp)
1925 {
1926 return __merge_switch(
1927 __begin1, __end1, __begin2, __end2, __result, __comp,
1928 std::__iterator_category(__begin1),
1929 std::__iterator_category(__begin2),
1930 std::__iterator_category(__result));
1931 }
1932
1933 // Public interface, insert default comparator
1934 template<typename _IIter1, typename _IIter2,
1935 typename _OutputIterator>
1936 inline _OutputIterator
1937 merge(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
1938 _IIter2 __end2, _OutputIterator __result)
1939 {
1940 typedef typename std::iterator_traits<_IIter1>::value_type _ValueType1;
1941 typedef typename std::iterator_traits<_IIter2>::value_type _ValueType2;
1942
1943 return __gnu_parallel::merge(__begin1, __end1, __begin2, __end2,
1944 __result, __gnu_parallel::_Less<_ValueType1, _ValueType2>());
1945 }
1946
1947 // Sequential fallback
1948 template<typename _RAIter>
1949 inline void
1950 nth_element(_RAIter __begin, _RAIter __nth,
1951 _RAIter __end, __gnu_parallel::sequential_tag)
1952 { return _GLIBCXX_STD_A::nth_element(__begin, __nth, __end); }
1953
1954 // Sequential fallback
1955 template<typename _RAIter, typename _Compare>
1956 inline void
1957 nth_element(_RAIter __begin, _RAIter __nth,
1958 _RAIter __end, _Compare __comp,
1959 __gnu_parallel::sequential_tag)
1960 { return _GLIBCXX_STD_A::nth_element(__begin, __nth, __end, __comp); }
1961
1962 // Public interface
1963 template<typename _RAIter, typename _Compare>
1964 inline void
1965 nth_element(_RAIter __begin, _RAIter __nth,
1966 _RAIter __end, _Compare __comp)
1967 {
1968 if (_GLIBCXX_PARALLEL_CONDITION(
1969 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
1970 >= __gnu_parallel::_Settings::get().nth_element_minimal_n))
1971 __gnu_parallel::__parallel_nth_element(__begin, __nth, __end, __comp);
1972 else
1973 nth_element(__begin, __nth, __end, __comp,
1974 __gnu_parallel::sequential_tag());
1975 }
1976
1977 // Public interface, insert default comparator
1978 template<typename _RAIter>
1979 inline void
1980 nth_element(_RAIter __begin, _RAIter __nth,
1981 _RAIter __end)
1982 {
1983 typedef typename iterator_traits<_RAIter>::value_type _ValueType;
1984 __gnu_parallel::nth_element(__begin, __nth, __end,
1985 std::less<_ValueType>());
1986 }
1987
1988 // Sequential fallback
1989 template<typename _RAIter, typename _Compare>
1990 inline void
1991 partial_sort(_RAIter __begin, _RAIter __middle,
1992 _RAIter __end, _Compare __comp,
1993 __gnu_parallel::sequential_tag)
1994 { _GLIBCXX_STD_A::partial_sort(__begin, __middle, __end, __comp); }
1995
1996 // Sequential fallback
1997 template<typename _RAIter>
1998 inline void
1999 partial_sort(_RAIter __begin, _RAIter __middle,
2000 _RAIter __end, __gnu_parallel::sequential_tag)
2001 { _GLIBCXX_STD_A::partial_sort(__begin, __middle, __end); }
2002
2003 // Public interface, parallel algorithm for random access iterators
2004 template<typename _RAIter, typename _Compare>
2005 void
2006 partial_sort(_RAIter __begin, _RAIter __middle,
2007 _RAIter __end, _Compare __comp)
2008 {
2009 if (_GLIBCXX_PARALLEL_CONDITION(
2010 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
2011 >= __gnu_parallel::_Settings::get().partial_sort_minimal_n))
2012 __gnu_parallel::
2013 __parallel_partial_sort(__begin, __middle, __end, __comp);
2014 else
2015 partial_sort(__begin, __middle, __end, __comp,
2016 __gnu_parallel::sequential_tag());
2017 }
2018
2019 // Public interface, insert default comparator
2020 template<typename _RAIter>
2021 inline void
2022 partial_sort(_RAIter __begin, _RAIter __middle,
2023 _RAIter __end)
2024 {
2025 typedef iterator_traits<_RAIter> _TraitsType;
2026 typedef typename _TraitsType::value_type _ValueType;
2027 __gnu_parallel::partial_sort(__begin, __middle, __end,
2028 std::less<_ValueType>());
2029 }
2030
2031 // Sequential fallback
2032 template<typename _FIterator>
2033 inline _FIterator
2034 max_element(_FIterator __begin, _FIterator __end,
2035 __gnu_parallel::sequential_tag)
2036 { return _GLIBCXX_STD_A::max_element(__begin, __end); }
2037
2038 // Sequential fallback
2039 template<typename _FIterator, typename _Compare>
2040 inline _FIterator
2041 max_element(_FIterator __begin, _FIterator __end, _Compare __comp,
2042 __gnu_parallel::sequential_tag)
2043 { return _GLIBCXX_STD_A::max_element(__begin, __end, __comp); }
2044
2045 // Sequential fallback for input iterator case
2046 template<typename _FIterator, typename _Compare, typename _IteratorTag>
2047 inline _FIterator
2048 __max_element_switch(_FIterator __begin, _FIterator __end,
2049 _Compare __comp, _IteratorTag)
2050 { return max_element(__begin, __end, __comp,
2051 __gnu_parallel::sequential_tag()); }
2052
2053 // Parallel algorithm for random access iterators
2054 template<typename _RAIter, typename _Compare>
2055 _RAIter
2056 __max_element_switch(_RAIter __begin, _RAIter __end,
2057 _Compare __comp, random_access_iterator_tag,
2058 __gnu_parallel::_Parallelism __parallelism_tag)
2059 {
2060 if (_GLIBCXX_PARALLEL_CONDITION(
2061 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
2062 >= __gnu_parallel::_Settings::get().max_element_minimal_n
2063 && __gnu_parallel::__is_parallel(__parallelism_tag)))
2064 {
2065 _RAIter __res(__begin);
2066 __gnu_parallel::__identity_selector<_RAIter>
2067 __functionality;
2068 __gnu_parallel::
2069 __for_each_template_random_access(
2070 __begin, __end, __gnu_parallel::_Nothing(), __functionality,
2071 __gnu_parallel::__max_element_reduct<_Compare, _RAIter>(__comp),
2072 __res, __res, -1, __parallelism_tag);
2073 return __res;
2074 }
2075 else
2076 return max_element(__begin, __end, __comp,
2077 __gnu_parallel::sequential_tag());
2078 }
2079
2080 // Public interface, insert default comparator
2081 template<typename _FIterator>
2082 inline _FIterator
2083 max_element(_FIterator __begin, _FIterator __end,
2084 __gnu_parallel::_Parallelism __parallelism_tag)
2085 {
2086 typedef typename iterator_traits<_FIterator>::value_type _ValueType;
2087 return max_element(__begin, __end, std::less<_ValueType>(),
2088 __parallelism_tag);
2089 }
2090
2091 template<typename _FIterator>
2092 inline _FIterator
2093 max_element(_FIterator __begin, _FIterator __end)
2094 {
2095 typedef typename iterator_traits<_FIterator>::value_type _ValueType;
2096 return __gnu_parallel::max_element(__begin, __end,
2097 std::less<_ValueType>());
2098 }
2099
2100 // Public interface
2101 template<typename _FIterator, typename _Compare>
2102 inline _FIterator
2103 max_element(_FIterator __begin, _FIterator __end, _Compare __comp,
2104 __gnu_parallel::_Parallelism __parallelism_tag)
2105 {
2106 return __max_element_switch(__begin, __end, __comp,
2107 std::__iterator_category(__begin),
2108 __parallelism_tag);
2109 }
2110
2111 template<typename _FIterator, typename _Compare>
2112 inline _FIterator
2113 max_element(_FIterator __begin, _FIterator __end, _Compare __comp)
2114 {
2115 return __max_element_switch(__begin, __end, __comp,
2116 std::__iterator_category(__begin));
2117 }
2118
2119
2120 // Sequential fallback
2121 template<typename _FIterator>
2122 inline _FIterator
2123 min_element(_FIterator __begin, _FIterator __end,
2124 __gnu_parallel::sequential_tag)
2125 { return _GLIBCXX_STD_A::min_element(__begin, __end); }
2126
2127 // Sequential fallback
2128 template<typename _FIterator, typename _Compare>
2129 inline _FIterator
2130 min_element(_FIterator __begin, _FIterator __end, _Compare __comp,
2131 __gnu_parallel::sequential_tag)
2132 { return _GLIBCXX_STD_A::min_element(__begin, __end, __comp); }
2133
2134 // Sequential fallback for input iterator case
2135 template<typename _FIterator, typename _Compare, typename _IteratorTag>
2136 inline _FIterator
2137 __min_element_switch(_FIterator __begin, _FIterator __end,
2138 _Compare __comp, _IteratorTag)
2139 { return min_element(__begin, __end, __comp,
2140 __gnu_parallel::sequential_tag()); }
2141
2142 // Parallel algorithm for random access iterators
2143 template<typename _RAIter, typename _Compare>
2144 _RAIter
2145 __min_element_switch(_RAIter __begin, _RAIter __end,
2146 _Compare __comp, random_access_iterator_tag,
2147 __gnu_parallel::_Parallelism __parallelism_tag)
2148 {
2149 if (_GLIBCXX_PARALLEL_CONDITION(
2150 static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
2151 >= __gnu_parallel::_Settings::get().min_element_minimal_n
2152 && __gnu_parallel::__is_parallel(__parallelism_tag)))
2153 {
2154 _RAIter __res(__begin);
2155 __gnu_parallel::__identity_selector<_RAIter>
2156 __functionality;
2157 __gnu_parallel::
2158 __for_each_template_random_access(
2159 __begin, __end, __gnu_parallel::_Nothing(), __functionality,
2160 __gnu_parallel::__min_element_reduct<_Compare, _RAIter>(__comp),
2161 __res, __res, -1, __parallelism_tag);
2162 return __res;
2163 }
2164 else
2165 return min_element(__begin, __end, __comp,
2166 __gnu_parallel::sequential_tag());
2167 }
2168
2169 // Public interface, insert default comparator
2170 template<typename _FIterator>
2171 inline _FIterator
2172 min_element(_FIterator __begin, _FIterator __end,
2173 __gnu_parallel::_Parallelism __parallelism_tag)
2174 {
2175 typedef typename iterator_traits<_FIterator>::value_type _ValueType;
2176 return min_element(__begin, __end, std::less<_ValueType>(),
2177 __parallelism_tag);
2178 }
2179
2180 template<typename _FIterator>
2181 inline _FIterator
2182 min_element(_FIterator __begin, _FIterator __end)
2183 {
2184 typedef typename iterator_traits<_FIterator>::value_type _ValueType;
2185 return __gnu_parallel::min_element(__begin, __end,
2186 std::less<_ValueType>());
2187 }
2188
2189 // Public interface
2190 template<typename _FIterator, typename _Compare>
2191 inline _FIterator
2192 min_element(_FIterator __begin, _FIterator __end, _Compare __comp,
2193 __gnu_parallel::_Parallelism __parallelism_tag)
2194 {
2195 return __min_element_switch(__begin, __end, __comp,
2196 std::__iterator_category(__begin),
2197 __parallelism_tag);
2198 }
2199
2200 template<typename _FIterator, typename _Compare>
2201 inline _FIterator
2202 min_element(_FIterator __begin, _FIterator __end, _Compare __comp)
2203 {
2204 return __min_element_switch(__begin, __end, __comp,
2205 std::__iterator_category(__begin));
2206 }
2207
2208 #if __cplusplus >= 201703L
2209 using _GLIBCXX_STD_A::for_each_n;
2210 using _GLIBCXX_STD_A::sample;
2211 #endif
2212 } // end namespace
2213 } // end namespace
2214
2215 #endif /* _GLIBCXX_PARALLEL_ALGO_H */