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