OSDN Git Service

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