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