Home | History | Annotate | Download | only in parallel
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2007-2013 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 #if __cplusplus >= 201103L
   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 */
   2364