# algo.h

Go to the documentation of this file.

    00001 // -*- C++ -*-
    00002
    00003 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the terms
    00007 // of the GNU General Public License as published by the Free Software
    00008 // Foundation; either version 3, or (at your option) any later
    00009 // version.
    00010
    00011 // This library is distributed in the hope that it will be useful, but
    00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014 // General Public License for more details.
    00015
    00016 // Under Section 7 of GPL version 3, you are granted additional
    00017 // permissions described in the GCC Runtime Library Exception, version
    00018 // 3.1, as published by the Free Software Foundation.
    00019
    00020 // You should have received a copy of the GNU General Public License and
    00021 // a copy of the GCC Runtime Library Exception along with this program;
    00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    00023 // <http://www.gnu.org/licenses/>.
    00024
    00025 /** @file parallel/algo.h
    00026  *  @brief Parallel STL function calls corresponding to the stl_algo.h header.
    00027  *
    00028  *  The functions defined here mainly do case switches and
    00029  *  call the actual parallelized versions in other files.
    00030  *  Inlining policy: Functions that basically only contain one function call,
    00031  *  are declared inline.
    00032  *  This file is a GNU parallel extension to the Standard C++ Library.
    00033  */
    00034
    00035 // Written by Johannes Singler and Felix Putze.
    00036
    00037 #ifndef _GLIBCXX_PARALLEL_ALGO_H
    00038 #define _GLIBCXX_PARALLEL_ALGO_H 1
    00039
    00040 #include <parallel/algorithmfwd.h>
    00041 #include <bits/stl_algobase.h>
    00042 #include <bits/stl_algo.h>
    00043 #include <parallel/iterator.h>
    00044 #include <parallel/base.h>
    00045 #include <parallel/sort.h>
    00046 #include <parallel/workstealing.h>
    00047 #include <parallel/par_loop.h>
    00048 #include <parallel/omp_loop.h>
    00049 #include <parallel/omp_loop_static.h>
    00050 #include <parallel/for_each_selectors.h>
    00051 #include <parallel/for_each.h>
    00052 #include <parallel/find.h>
    00053 #include <parallel/find_selectors.h>
    00054 #include <parallel/search.h>
    00055 #include <parallel/random_shuffle.h>
    00056 #include <parallel/partition.h>
    00057 #include <parallel/merge.h>
    00058 #include <parallel/unique_copy.h>
    00059 #include <parallel/set_operations.h>
    00060
    00061 namespace std
    00062 {
    00063 namespace __parallel
    00064 {
    00065   // Sequential fallback
    00066   template<typename InputIterator, typename Function>
    00067     inline Function
    00068     for_each(InputIterator begin, InputIterator end, Function f,
    00069              __gnu_parallel::sequential_tag)
    00070     { return _GLIBCXX_STD_P::for_each(begin, end, f); }
    00071
    00072
    00073   // Sequential fallback for input iterator case
    00074   template<typename InputIterator, typename Function, typename IteratorTag>
    00075     inline Function
    00076     for_each_switch(InputIterator begin, InputIterator end, Function f,
    00077                     IteratorTag)
    00078     { return for_each(begin, end, f, __gnu_parallel::sequential_tag()); }
    00079
    00080   // Parallel algorithm for random access iterators
    00081   template<typename RandomAccessIterator, typename Function>
    00082     Function
    00083     for_each_switch(RandomAccessIterator begin, RandomAccessIterator end,
    00084                     Function f, random_access_iterator_tag,
    00085                     __gnu_parallel::_Parallelism parallelism_tag
    00086                     = __gnu_parallel::parallel_balanced)
    00087     {
    00088       if (_GLIBCXX_PARALLEL_CONDITION(
    00089             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    00090             >= __gnu_parallel::_Settings::get().for_each_minimal_n
    00091             && __gnu_parallel::is_parallel(parallelism_tag)))
    00092         {
    00093           bool dummy;
    00094     __gnu_parallel::for_each_selector<RandomAccessIterator> functionality;
    00095
    00096           return __gnu_parallel::
    00097             for_each_template_random_access(begin, end, f, functionality,
    00098                                             __gnu_parallel::dummy_reduct(),
    00099                                             true, dummy, -1, parallelism_tag);
    00100         }
    00101       else
    00102         return for_each(begin, end, f, __gnu_parallel::sequential_tag());
    00103     }
    00104
    00105   // Public interface
    00106   template<typename Iterator, typename Function>
    00107     inline Function
    00108     for_each(Iterator begin, Iterator end, Function f,
    00109              __gnu_parallel::_Parallelism parallelism_tag)
    00110     {
    00111       typedef std::iterator_traits<Iterator> iterator_traits;
    00112       typedef typename iterator_traits::iterator_category iterator_category;
    00113       return for_each_switch(begin, end, f, iterator_category(),
    00114                              parallelism_tag);
    00115     }
    00116
    00117   template<typename Iterator, typename Function>
    00118     inline Function
    00119     for_each(Iterator begin, Iterator end, Function f)
    00120     {
    00121       typedef std::iterator_traits<Iterator> iterator_traits;
    00122       typedef typename iterator_traits::iterator_category iterator_category;
    00123       return for_each_switch(begin, end, f, iterator_category());
    00124     }
    00125
    00126
    00127   // Sequential fallback
    00128   template<typename InputIterator, typename T>
    00129     inline InputIterator
    00130     find(InputIterator begin, InputIterator end, const T& val,
    00131          __gnu_parallel::sequential_tag)
    00132     { return _GLIBCXX_STD_P::find(begin, end, val); }
    00133
    00134   // Sequential fallback for input iterator case
    00135   template<typename InputIterator, typename T, typename IteratorTag>
    00136     inline InputIterator
    00137     find_switch(InputIterator begin, InputIterator end, const T& val,
    00138                 IteratorTag)
    00139     { return _GLIBCXX_STD_P::find(begin, end, val); }
    00140
    00141   // Parallel find for random access iterators
    00142   template<typename RandomAccessIterator, typename T>
    00143     RandomAccessIterator
    00144     find_switch(RandomAccessIterator begin, RandomAccessIterator end,
    00145                 const T& val, random_access_iterator_tag)
    00146     {
    00147       typedef iterator_traits<RandomAccessIterator> traits_type;
    00148       typedef typename traits_type::value_type value_type;
    00149
    00150       if (_GLIBCXX_PARALLEL_CONDITION(true))
    00151         {
    00152           binder2nd<__gnu_parallel::equal_to<value_type, T> >
    00153             comp(__gnu_parallel::equal_to<value_type, T>(), val);
    00154           return __gnu_parallel::find_template(begin, end, begin, comp,
    00155                                                __gnu_parallel::
    00156                                                find_if_selector()).first;
    00157         }
    00158       else
    00159         return _GLIBCXX_STD_P::find(begin, end, val);
    00160     }
    00161
    00162   // Public interface
    00163   template<typename InputIterator, typename T>
    00164     inline InputIterator
    00165     find(InputIterator begin, InputIterator end, const T& val)
    00166     {
    00167       typedef std::iterator_traits<InputIterator> iterator_traits;
    00168       typedef typename iterator_traits::iterator_category iterator_category;
    00169       return find_switch(begin, end, val, iterator_category());
    00170     }
    00171
    00172   // Sequential fallback
    00173   template<typename InputIterator, typename Predicate>
    00174     inline InputIterator
    00175     find_if(InputIterator begin, InputIterator end, Predicate pred,
    00176             __gnu_parallel::sequential_tag)
    00177     { return _GLIBCXX_STD_P::find_if(begin, end, pred); }
    00178
    00179   // Sequential fallback for input iterator case
    00180   template<typename InputIterator, typename Predicate, typename IteratorTag>
    00181     inline InputIterator
    00182     find_if_switch(InputIterator begin, InputIterator end, Predicate pred,
    00183                    IteratorTag)
    00184     { return _GLIBCXX_STD_P::find_if(begin, end, pred); }
    00185
    00186   // Parallel find_if for random access iterators
    00187   template<typename RandomAccessIterator, typename Predicate>
    00188     RandomAccessIterator
    00189     find_if_switch(RandomAccessIterator begin, RandomAccessIterator end,
    00190                    Predicate pred, random_access_iterator_tag)
    00191     {
    00192       if (_GLIBCXX_PARALLEL_CONDITION(true))
    00193         return __gnu_parallel::find_template(begin, end, begin, pred,
    00194                                              __gnu_parallel::
    00195                                              find_if_selector()).first;
    00196       else
    00197         return _GLIBCXX_STD_P::find_if(begin, end, pred);
    00198     }
    00199
    00200   // Public interface
    00201   template<typename InputIterator, typename Predicate>
    00202     inline InputIterator
    00203     find_if(InputIterator begin, InputIterator end, Predicate pred)
    00204     {
    00205       typedef std::iterator_traits<InputIterator> iterator_traits;
    00206       typedef typename iterator_traits::iterator_category iterator_category;
    00207       return find_if_switch(begin, end, pred, iterator_category());
    00208     }
    00209
    00210   // Sequential fallback
    00211   template<typename InputIterator, typename ForwardIterator>
    00212     inline InputIterator
    00213     find_first_of(InputIterator begin1, InputIterator end1,
    00214                   ForwardIterator begin2, ForwardIterator end2,
    00215                   __gnu_parallel::sequential_tag)
    00216     { return _GLIBCXX_STD_P::find_first_of(begin1, end1, begin2, end2); }
    00217
    00218   // Sequential fallback
    00219   template<typename InputIterator, typename ForwardIterator,
    00220            typename BinaryPredicate>
    00221     inline InputIterator
    00222     find_first_of(InputIterator begin1, InputIterator end1,
    00223                   ForwardIterator begin2, ForwardIterator end2,
    00224                   BinaryPredicate comp, __gnu_parallel::sequential_tag)
    00225   { return _GLIBCXX_STD_P::find_first_of(begin1, end1, begin2, end2, comp); }
    00226
    00227   // Sequential fallback for input iterator type
    00228   template<typename InputIterator, typename ForwardIterator,
    00229            typename IteratorTag1, typename IteratorTag2>
    00230     inline InputIterator
    00231     find_first_of_switch(InputIterator begin1, InputIterator end1,
    00232                          ForwardIterator begin2, ForwardIterator end2,
    00233                          IteratorTag1, IteratorTag2)
    00234     { return find_first_of(begin1, end1, begin2, end2,
    00235                            __gnu_parallel::sequential_tag()); }
    00236
    00237   // Parallel algorithm for random access iterators
    00238   template<typename RandomAccessIterator, typename ForwardIterator,
    00239            typename BinaryPredicate, typename IteratorTag>
    00240     inline RandomAccessIterator
    00241     find_first_of_switch(RandomAccessIterator begin1,
    00242                          RandomAccessIterator end1,
    00243                          ForwardIterator begin2, ForwardIterator end2,
    00244                          BinaryPredicate comp, random_access_iterator_tag,
    00245                          IteratorTag)
    00246     {
    00247       return __gnu_parallel::
    00248         find_template(begin1, end1, begin1, comp,
    00249                       __gnu_parallel::find_first_of_selector
    00250                       <ForwardIterator>(begin2, end2)).first;
    00251     }
    00252
    00253   // Sequential fallback for input iterator type
    00254   template<typename InputIterator, typename ForwardIterator,
    00255            typename BinaryPredicate, typename IteratorTag1,
    00256            typename IteratorTag2>
    00257     inline InputIterator
    00258     find_first_of_switch(InputIterator begin1, InputIterator end1,
    00259                          ForwardIterator begin2, ForwardIterator end2,
    00260                          BinaryPredicate comp, IteratorTag1, IteratorTag2)
    00261     { return find_first_of(begin1, end1, begin2, end2, comp,
    00262                            __gnu_parallel::sequential_tag()); }
    00263
    00264   // Public interface
    00265   template<typename InputIterator, typename ForwardIterator,
    00266            typename BinaryPredicate>
    00267     inline InputIterator
    00268     find_first_of(InputIterator begin1, InputIterator end1,
    00269                   ForwardIterator begin2, ForwardIterator end2,
    00270                   BinaryPredicate comp)
    00271     {
    00272       typedef std::iterator_traits<InputIterator> iteratori_traits;
    00273       typedef std::iterator_traits<ForwardIterator> iteratorf_traits;
    00274       typedef typename iteratori_traits::iterator_category iteratori_category;
    00275       typedef typename iteratorf_traits::iterator_category iteratorf_category;
    00276
    00277       return find_first_of_switch(begin1, end1, begin2, end2, comp,
    00278                                   iteratori_category(), iteratorf_category());
    00279     }
    00280
    00281   // Public interface, insert default comparator
    00282   template<typename InputIterator, typename ForwardIterator>
    00283     inline InputIterator
    00284     find_first_of(InputIterator begin1, InputIterator end1,
    00285                   ForwardIterator begin2, ForwardIterator end2)
    00286     {
    00287       typedef std::iterator_traits<InputIterator> iteratori_traits;
    00288       typedef std::iterator_traits<ForwardIterator> iteratorf_traits;
    00289       typedef typename iteratori_traits::value_type valuei_type;
    00290       typedef typename iteratorf_traits::value_type valuef_type;
    00291
    00292       return find_first_of(begin1, end1, begin2, end2, __gnu_parallel::
    00293                            equal_to<valuei_type, valuef_type>());
    00294     }
    00295
    00296   // Sequential fallback
    00297   template<typename InputIterator, typename OutputIterator>
    00298     inline OutputIterator
    00299     unique_copy(InputIterator begin1, InputIterator end1, OutputIterator out,
    00300                 __gnu_parallel::sequential_tag)
    00301     { return _GLIBCXX_STD_P::unique_copy(begin1, end1, out); }
    00302
    00303   // Sequential fallback
    00304   template<typename InputIterator, typename OutputIterator,
    00305            typename Predicate>
    00306     inline OutputIterator
    00307     unique_copy(InputIterator begin1, InputIterator end1, OutputIterator out,
    00308                 Predicate pred, __gnu_parallel::sequential_tag)
    00309     { return _GLIBCXX_STD_P::unique_copy(begin1, end1, out, pred); }
    00310
    00311   // Sequential fallback for input iterator case
    00312   template<typename InputIterator, typename OutputIterator,
    00313            typename Predicate, typename IteratorTag1, typename IteratorTag2>
    00314     inline OutputIterator
    00315     unique_copy_switch(InputIterator begin, InputIterator last,
    00316                        OutputIterator out, Predicate pred,
    00317                        IteratorTag1, IteratorTag2)
    00318     { return _GLIBCXX_STD_P::unique_copy(begin, last, out, pred); }
    00319
    00320   // Parallel unique_copy for random access iterators
    00321   template<typename RandomAccessIterator, typename RandomAccessOutputIterator,
    00322            typename Predicate>
    00323     RandomAccessOutputIterator
    00324     unique_copy_switch(RandomAccessIterator begin, RandomAccessIterator last,
    00325                        RandomAccessOutputIterator out, Predicate pred,
    00326                        random_access_iterator_tag, random_access_iterator_tag)
    00327     {
    00328       if (_GLIBCXX_PARALLEL_CONDITION(
    00329             static_cast<__gnu_parallel::sequence_index_t>(last - begin)
    00330             > __gnu_parallel::_Settings::get().unique_copy_minimal_n))
    00331         return __gnu_parallel::parallel_unique_copy(begin, last, out, pred);
    00332       else
    00333         return _GLIBCXX_STD_P::unique_copy(begin, last, out, pred);
    00334     }
    00335
    00336   // Public interface
    00337   template<typename InputIterator, typename OutputIterator>
    00338     inline OutputIterator
    00339     unique_copy(InputIterator begin1, InputIterator end1, OutputIterator out)
    00340     {
    00341       typedef std::iterator_traits<InputIterator> iteratori_traits;
    00342       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00343       typedef typename iteratori_traits::iterator_category iteratori_category;
    00344       typedef typename iteratori_traits::value_type value_type;
    00345       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00346
    00347       return unique_copy_switch(begin1, end1, out, equal_to<value_type>(),
    00348                                 iteratori_category(), iteratoro_category());
    00349     }
    00350
    00351   // Public interface
    00352   template<typename InputIterator, typename OutputIterator, typename Predicate>
    00353     inline OutputIterator
    00354     unique_copy(InputIterator begin1, InputIterator end1, OutputIterator out,
    00355                 Predicate pred)
    00356     {
    00357       typedef std::iterator_traits<InputIterator> iteratori_traits;
    00358       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00359       typedef typename iteratori_traits::iterator_category iteratori_category;
    00360       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00361
    00362       return unique_copy_switch(begin1, end1, out, pred, iteratori_category(),
    00363                                 iteratoro_category());
    00364     }
    00365
    00366   // Sequential fallback
    00367   template<typename InputIterator1, typename InputIterator2,
    00368            typename OutputIterator>
    00369     inline OutputIterator
    00370     set_union(InputIterator1 begin1, InputIterator1 end1,
    00371               InputIterator2 begin2, InputIterator2 end2,
    00372               OutputIterator out, __gnu_parallel::sequential_tag)
    00373     { return _GLIBCXX_STD_P::set_union(begin1, end1, begin2, end2, out); }
    00374
    00375   // Sequential fallback
    00376   template<typename InputIterator1, typename InputIterator2,
    00377            typename OutputIterator, typename Predicate>
    00378     inline OutputIterator
    00379     set_union(InputIterator1 begin1, InputIterator1 end1,
    00380               InputIterator2 begin2, InputIterator2 end2,
    00381               OutputIterator out, Predicate pred,
    00382               __gnu_parallel::sequential_tag)
    00383     { return _GLIBCXX_STD_P::set_union(begin1, end1,
    00384                                        begin2, end2, out, pred); }
    00385
    00386   // Sequential fallback for input iterator case
    00387   template<typename InputIterator1, typename InputIterator2,
    00388            typename Predicate, typename OutputIterator,
    00389            typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
    00390     inline OutputIterator
    00391     set_union_switch(InputIterator1 begin1, InputIterator1 end1,
    00392                      InputIterator2 begin2, InputIterator2 end2,
    00393                      OutputIterator result, Predicate pred, IteratorTag1,
    00394                      IteratorTag2, IteratorTag3)
    00395     { return _GLIBCXX_STD_P::set_union(begin1, end1,
    00396                                        begin2, end2, result, pred); }
    00397
    00398   // Parallel set_union for random access iterators
    00399   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    00400            typename OutputRandomAccessIterator, typename Predicate>
    00401     OutputRandomAccessIterator
    00402     set_union_switch(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
    00403                      RandomAccessIterator2 begin2, RandomAccessIterator2 end2,
    00404                      OutputRandomAccessIterator result, Predicate pred,
    00405                      random_access_iterator_tag, random_access_iterator_tag,
    00406                      random_access_iterator_tag)
    00407     {
    00408       if (_GLIBCXX_PARALLEL_CONDITION(
    00409             static_cast<__gnu_parallel::sequence_index_t>(end1 - begin1)
    00410             >= __gnu_parallel::_Settings::get().set_union_minimal_n
    00411             || static_cast<__gnu_parallel::sequence_index_t>(end2 - begin2)
    00412             >= __gnu_parallel::_Settings::get().set_union_minimal_n))
    00413         return __gnu_parallel::parallel_set_union(begin1, end1,
    00414                                                   begin2, end2, result, pred);
    00415       else
    00416         return _GLIBCXX_STD_P::set_union(begin1, end1,
    00417                                          begin2, end2, result, pred);
    00418     }
    00419
    00420   // Public interface
    00421   template<typename InputIterator1, typename InputIterator2,
    00422            typename OutputIterator>
    00423     inline OutputIterator
    00424     set_union(InputIterator1 begin1, InputIterator1 end1,
    00425               InputIterator2 begin2, InputIterator2 end2, OutputIterator out)
    00426     {
    00427       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00428       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00429       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00430       typedef typename iteratori1_traits::iterator_category
    00431         iteratori1_category;
    00432       typedef typename iteratori2_traits::iterator_category
    00433         iteratori2_category;
    00434       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00435       typedef typename iteratori1_traits::value_type value1_type;
    00436       typedef typename iteratori2_traits::value_type value2_type;
    00437
    00438       return set_union_switch(begin1, end1, begin2, end2, out,
    00439                               __gnu_parallel::less<value1_type, value2_type>(),
    00440                               iteratori1_category(), iteratori2_category(),
    00441                               iteratoro_category());
    00442     }
    00443
    00444   // Public interface
    00445   template<typename InputIterator1, typename InputIterator2,
    00446            typename OutputIterator, typename Predicate>
    00447     inline OutputIterator
    00448     set_union(InputIterator1 begin1, InputIterator1 end1,
    00449               InputIterator2 begin2, InputIterator2 end2,
    00450               OutputIterator out, Predicate pred)
    00451     {
    00452       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00453       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00454       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00455       typedef typename iteratori1_traits::iterator_category
    00456         iteratori1_category;
    00457       typedef typename iteratori2_traits::iterator_category
    00458         iteratori2_category;
    00459       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00460
    00461       return set_union_switch(begin1, end1, begin2, end2, out, pred,
    00462                               iteratori1_category(), iteratori2_category(),
    00463                               iteratoro_category());
    00464     }
    00465
    00466   // Sequential fallback.
    00467   template<typename InputIterator1, typename InputIterator2,
    00468            typename OutputIterator>
    00469     inline OutputIterator
    00470     set_intersection(InputIterator1 begin1, InputIterator1 end1,
    00471                      InputIterator2 begin2, InputIterator2 end2,
    00472                      OutputIterator out, __gnu_parallel::sequential_tag)
    00473     { return _GLIBCXX_STD_P::set_intersection(begin1, end1,
    00474                                               begin2, end2, out); }
    00475
    00476   // Sequential fallback.
    00477   template<typename InputIterator1, typename InputIterator2,
    00478            typename OutputIterator, typename Predicate>
    00479     inline OutputIterator
    00480     set_intersection(InputIterator1 begin1, InputIterator1 end1,
    00481                      InputIterator2 begin2, InputIterator2 end2,
    00482                      OutputIterator out, Predicate pred,
    00483                      __gnu_parallel::sequential_tag)
    00484     { return _GLIBCXX_STD_P::set_intersection(begin1, end1, begin2, end2,
    00485                                               out, pred); }
    00486
    00487   // Sequential fallback for input iterator case
    00488   template<typename InputIterator1, typename InputIterator2,
    00489            typename Predicate, typename OutputIterator,
    00490            typename IteratorTag1, typename IteratorTag2,
    00491            typename IteratorTag3>
    00492     inline OutputIterator
    00493     set_intersection_switch(InputIterator1 begin1, InputIterator1 end1,
    00494                             InputIterator2 begin2, InputIterator2 end2,
    00495                             OutputIterator result, Predicate pred,
    00496                             IteratorTag1, IteratorTag2, IteratorTag3)
    00497     { return _GLIBCXX_STD_P::set_intersection(begin1, end1, begin2,
    00498                                               end2, result, pred); }
    00499
    00500   // Parallel set_intersection for random access iterators
    00501   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    00502            typename OutputRandomAccessIterator, typename Predicate>
    00503     OutputRandomAccessIterator
    00504     set_intersection_switch(RandomAccessIterator1 begin1,
    00505                             RandomAccessIterator1 end1,
    00506                             RandomAccessIterator2 begin2,
    00507                             RandomAccessIterator2 end2,
    00508                             OutputRandomAccessIterator result,
    00509                             Predicate pred,
    00510                             random_access_iterator_tag,
    00511                             random_access_iterator_tag,
    00512                             random_access_iterator_tag)
    00513     {
    00514       if (_GLIBCXX_PARALLEL_CONDITION(
    00515             static_cast<__gnu_parallel::sequence_index_t>(end1 - begin1)
    00516             >= __gnu_parallel::_Settings::get().set_union_minimal_n
    00517             || static_cast<__gnu_parallel::sequence_index_t>(end2 - begin2)
    00518             >= __gnu_parallel::_Settings::get().set_union_minimal_n))
    00519         return __gnu_parallel::parallel_set_intersection(begin1, end1, begin2,
    00520                                                          end2, result, pred);
    00521       else
    00522         return _GLIBCXX_STD_P::set_intersection(begin1, end1, begin2,
    00523                                                 end2, result, pred);
    00524     }
    00525
    00526   // Public interface
    00527   template<typename InputIterator1, typename InputIterator2,
    00528            typename OutputIterator>
    00529     inline OutputIterator
    00530     set_intersection(InputIterator1 begin1, InputIterator1 end1,
    00531                      InputIterator2 begin2, InputIterator2 end2,
    00532                      OutputIterator out)
    00533     {
    00534       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00535       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00536       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00537       typedef typename iteratori1_traits::iterator_category
    00538         iteratori1_category;
    00539       typedef typename iteratori2_traits::iterator_category
    00540         iteratori2_category;
    00541       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00542       typedef typename iteratori1_traits::value_type value1_type;
    00543       typedef typename iteratori2_traits::value_type value2_type;
    00544
    00545       return set_intersection_switch(begin1, end1, begin2, end2, out,
    00546                                      __gnu_parallel::
    00547                                      less<value1_type, value2_type>(),
    00548                                      iteratori1_category(),
    00549                                      iteratori2_category(),
    00550                                      iteratoro_category());
    00551     }
    00552
    00553   template<typename InputIterator1, typename InputIterator2,
    00554            typename OutputIterator, typename Predicate>
    00555     inline OutputIterator
    00556     set_intersection(InputIterator1 begin1, InputIterator1 end1,
    00557                      InputIterator2 begin2, InputIterator2 end2,
    00558                      OutputIterator out, Predicate pred)
    00559     {
    00560       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00561       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00562       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00563       typedef typename iteratori1_traits::iterator_category
    00564         iteratori1_category;
    00565       typedef typename iteratori2_traits::iterator_category
    00566         iteratori2_category;
    00567       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00568
    00569       return set_intersection_switch(begin1, end1, begin2, end2, out, pred,
    00570                                      iteratori1_category(),
    00571                                      iteratori2_category(),
    00572                                      iteratoro_category());
    00573     }
    00574
    00575   // Sequential fallback
    00576   template<typename InputIterator1, typename InputIterator2,
    00577            typename OutputIterator>
    00578     inline OutputIterator
    00579     set_symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
    00580                              InputIterator2 begin2, InputIterator2 end2,
    00581                              OutputIterator out,
    00582                              __gnu_parallel::sequential_tag)
    00583     { return _GLIBCXX_STD_P::set_symmetric_difference(begin1,end1,
    00584                                                       begin2, end2, out); }
    00585
    00586   // Sequential fallback
    00587   template<typename InputIterator1, typename InputIterator2,
    00588            typename OutputIterator, typename Predicate>
    00589     inline OutputIterator
    00590     set_symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
    00591                              InputIterator2 begin2, InputIterator2 end2,
    00592                              OutputIterator out, Predicate pred,
    00593                              __gnu_parallel::sequential_tag)
    00594     { return _GLIBCXX_STD_P::set_symmetric_difference(begin1, end1, begin2,
    00595                                                       end2, out, pred); }
    00596
    00597   // Sequential fallback for input iterator case
    00598   template<typename InputIterator1, typename InputIterator2,
    00599            typename Predicate, typename OutputIterator,
    00600            typename IteratorTag1, typename IteratorTag2,
    00601            typename IteratorTag3>
    00602     inline OutputIterator
    00603     set_symmetric_difference_switch(InputIterator1 begin1,
    00604                                     InputIterator1 end1,
    00605                                     InputIterator2 begin2,
    00606                                     InputIterator2 end2,
    00607                                     OutputIterator result, Predicate pred,
    00608                                     IteratorTag1, IteratorTag2, IteratorTag3)
    00609     { return _GLIBCXX_STD_P::set_symmetric_difference(begin1, end1,
    00610                                                       begin2, end2,
    00611                                                       result, pred); }
    00612
    00613   // Parallel set_symmetric_difference for random access iterators
    00614   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    00615            typename OutputRandomAccessIterator, typename Predicate>
    00616     OutputRandomAccessIterator
    00617     set_symmetric_difference_switch(RandomAccessIterator1 begin1,
    00618                                     RandomAccessIterator1 end1,
    00619                                     RandomAccessIterator2 begin2,
    00620                                     RandomAccessIterator2 end2,
    00621                                     OutputRandomAccessIterator result,
    00622                                     Predicate pred,
    00623                                     random_access_iterator_tag,
    00624                                     random_access_iterator_tag,
    00625                                     random_access_iterator_tag)
    00626     {
    00627       if (_GLIBCXX_PARALLEL_CONDITION(
    00628       static_cast<__gnu_parallel::sequence_index_t>(end1 - begin1)
    00629       >= __gnu_parallel::_Settings::get().set_symmetric_difference_minimal_n
    00630       || static_cast<__gnu_parallel::sequence_index_t>(end2 - begin2)
    00631       >= __gnu_parallel::_Settings::get().set_symmetric_difference_minimal_n))
    00632   return __gnu_parallel::parallel_set_symmetric_difference(begin1, end1,
    00633                                                                  begin2, end2,
    00634                                                                  result, pred);
    00635       else
    00636         return _GLIBCXX_STD_P::set_symmetric_difference(begin1, end1,
    00637                                                         begin2, end2,
    00638                                                         result, pred);
    00639     }
    00640
    00641   // Public interface.
    00642   template<typename InputIterator1, typename InputIterator2,
    00643            typename OutputIterator>
    00644     inline OutputIterator
    00645     set_symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
    00646                              InputIterator2 begin2, InputIterator2 end2,
    00647                              OutputIterator out)
    00648     {
    00649       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00650       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00651       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00652       typedef typename iteratori1_traits::iterator_category
    00653         iteratori1_category;
    00654       typedef typename iteratori2_traits::iterator_category
    00655         iteratori2_category;
    00656       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00657       typedef typename iteratori1_traits::value_type value1_type;
    00658       typedef typename iteratori2_traits::value_type value2_type;
    00659
    00660       return set_symmetric_difference_switch(begin1, end1, begin2, end2, out,
    00661                                              __gnu_parallel::
    00662                                              less<value1_type, value2_type>(),
    00663                                              iteratori1_category(),
    00664                                              iteratori2_category(),
    00665                                              iteratoro_category());
    00666     }
    00667
    00668   // Public interface.
    00669   template<typename InputIterator1, typename InputIterator2,
    00670            typename OutputIterator, typename Predicate>
    00671     inline OutputIterator
    00672     set_symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
    00673                              InputIterator2 begin2, InputIterator2 end2,
    00674                              OutputIterator out, Predicate pred)
    00675     {
    00676       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00677       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00678       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00679       typedef typename iteratori1_traits::iterator_category
    00680         iteratori1_category;
    00681       typedef typename iteratori2_traits::iterator_category
    00682         iteratori2_category;
    00683       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00684
    00685       return set_symmetric_difference_switch(begin1, end1, begin2, end2, out,
    00686                                              pred, iteratori1_category(),
    00687                                              iteratori2_category(),
    00688                                              iteratoro_category());
    00689     }
    00690
    00691   // Sequential fallback.
    00692   template<typename InputIterator1, typename InputIterator2,
    00693            typename OutputIterator>
    00694     inline OutputIterator
    00695     set_difference(InputIterator1 begin1, InputIterator1 end1,
    00696                    InputIterator2 begin2, InputIterator2 end2,
    00697                    OutputIterator out, __gnu_parallel::sequential_tag)
    00698     { return _GLIBCXX_STD_P::set_difference(begin1,end1, begin2, end2, out); }
    00699
    00700   // Sequential fallback.
    00701   template<typename InputIterator1, typename InputIterator2,
    00702            typename OutputIterator, typename Predicate>
    00703     inline OutputIterator
    00704     set_difference(InputIterator1 begin1, InputIterator1 end1,
    00705                    InputIterator2 begin2, InputIterator2 end2,
    00706                    OutputIterator out, Predicate pred,
    00707                    __gnu_parallel::sequential_tag)
    00708     { return _GLIBCXX_STD_P::set_difference(begin1, end1,
    00709                                             begin2, end2, out, pred); }
    00710
    00711   // Sequential fallback for input iterator case.
    00712   template<typename InputIterator1, typename InputIterator2,
    00713            typename Predicate, typename OutputIterator,
    00714            typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
    00715     inline OutputIterator
    00716     set_difference_switch(InputIterator1 begin1, InputIterator1 end1,
    00717                           InputIterator2 begin2, InputIterator2 end2,
    00718                           OutputIterator result, Predicate pred,
    00719                           IteratorTag1, IteratorTag2, IteratorTag3)
    00720     { return _GLIBCXX_STD_P::set_difference(begin1, end1,
    00721                                             begin2, end2, result, pred); }
    00722
    00723   // Parallel set_difference for random access iterators
    00724   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    00725            typename OutputRandomAccessIterator, typename Predicate>
    00726     OutputRandomAccessIterator
    00727     set_difference_switch(RandomAccessIterator1 begin1,
    00728                           RandomAccessIterator1 end1,
    00729                           RandomAccessIterator2 begin2,
    00730                           RandomAccessIterator2 end2,
    00731                           OutputRandomAccessIterator result, Predicate pred,
    00732                           random_access_iterator_tag,
    00733                           random_access_iterator_tag,
    00734                           random_access_iterator_tag)
    00735     {
    00736       if (_GLIBCXX_PARALLEL_CONDITION(
    00737             static_cast<__gnu_parallel::sequence_index_t>(end1 - begin1)
    00738             >= __gnu_parallel::_Settings::get().set_difference_minimal_n
    00739             || static_cast<__gnu_parallel::sequence_index_t>(end2 - begin2)
    00740             >= __gnu_parallel::_Settings::get().set_difference_minimal_n))
    00741         return __gnu_parallel::parallel_set_difference(begin1, end1,
    00742                                                        begin2, end2,
    00743                                                        result, pred);
    00744       else
    00745         return _GLIBCXX_STD_P::set_difference(begin1, end1,
    00746                                               begin2, end2, result, pred);
    00747     }
    00748
    00749   // Public interface
    00750   template<typename InputIterator1, typename InputIterator2,
    00751            typename OutputIterator>
    00752     inline OutputIterator
    00753     set_difference(InputIterator1 begin1, InputIterator1 end1,
    00754                    InputIterator2 begin2, InputIterator2 end2,
    00755                    OutputIterator out)
    00756     {
    00757       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00758       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00759       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00760       typedef typename iteratori1_traits::iterator_category
    00761         iteratori1_category;
    00762       typedef typename iteratori2_traits::iterator_category
    00763         iteratori2_category;
    00764       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00765       typedef typename iteratori1_traits::value_type value1_type;
    00766       typedef typename iteratori2_traits::value_type value2_type;
    00767
    00768       return set_difference_switch(begin1, end1, begin2, end2, out,
    00769                                    __gnu_parallel::
    00770                                    less<value1_type, value2_type>(),
    00771                                    iteratori1_category(),
    00772                                    iteratori2_category(),
    00773                                    iteratoro_category());
    00774     }
    00775
    00776   // Public interface
    00777   template<typename InputIterator1, typename InputIterator2,
    00778            typename OutputIterator, typename Predicate>
    00779     inline OutputIterator
    00780     set_difference(InputIterator1 begin1, InputIterator1 end1,
    00781                    InputIterator2 begin2, InputIterator2 end2,
    00782                    OutputIterator out, Predicate pred)
    00783     {
    00784       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    00785       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    00786       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    00787       typedef typename iteratori1_traits::iterator_category
    00788         iteratori1_category;
    00789       typedef typename iteratori2_traits::iterator_category
    00790         iteratori2_category;
    00791       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    00792
    00793       return set_difference_switch(begin1, end1, begin2, end2, out, pred,
    00794                                    iteratori1_category(),
    00795                                    iteratori2_category(),
    00796                                    iteratoro_category());
    00797     }
    00798
    00799   // Sequential fallback
    00800   template<typename ForwardIterator>
    00801     inline ForwardIterator
    00802     adjacent_find(ForwardIterator begin, ForwardIterator end,
    00803                   __gnu_parallel::sequential_tag)
    00804     { return _GLIBCXX_STD_P::adjacent_find(begin, end); }
    00805
    00806   // Sequential fallback
    00807   template<typename ForwardIterator, typename BinaryPredicate>
    00808     inline ForwardIterator
    00809     adjacent_find(ForwardIterator begin, ForwardIterator end,
    00810                   BinaryPredicate binary_pred, __gnu_parallel::sequential_tag)
    00811     { return _GLIBCXX_STD_P::adjacent_find(begin, end, binary_pred); }
    00812
    00813   // Parallel algorithm for random access iterators
    00814   template<typename RandomAccessIterator>
    00815     RandomAccessIterator
    00816     adjacent_find_switch(RandomAccessIterator begin, RandomAccessIterator end,
    00817                          random_access_iterator_tag)
    00818     {
    00819       typedef iterator_traits<RandomAccessIterator> traits_type;
    00820       typedef typename traits_type::value_type value_type;
    00821
    00822       if (_GLIBCXX_PARALLEL_CONDITION(true))
    00823         {
    00824           RandomAccessIterator spot = __gnu_parallel::
    00825             find_template(begin, end - 1, begin, equal_to<value_type>(),
    00826                           __gnu_parallel::adjacent_find_selector()).first;
    00827           if (spot == (end - 1))
    00828             return end;
    00829           else
    00830             return spot;
    00831         }
    00832       else
    00833         return adjacent_find(begin, end, __gnu_parallel::sequential_tag());
    00834     }
    00835
    00836   // Sequential fallback for input iterator case
    00837   template<typename ForwardIterator, typename IteratorTag>
    00838     inline ForwardIterator
    00839     adjacent_find_switch(ForwardIterator begin, ForwardIterator end,
    00840                          IteratorTag)
    00841     { return adjacent_find(begin, end, __gnu_parallel::sequential_tag()); }
    00842
    00843   // Public interface
    00844   template<typename ForwardIterator>
    00845     inline ForwardIterator
    00846     adjacent_find(ForwardIterator begin, ForwardIterator end)
    00847     {
    00848       typedef iterator_traits<ForwardIterator> traits_type;
    00849       typedef typename traits_type::iterator_category iterator_category;
    00850       return adjacent_find_switch(begin, end, iterator_category());
    00851     }
    00852
    00853   // Sequential fallback for input iterator case
    00854   template<typename ForwardIterator, typename BinaryPredicate,
    00855            typename IteratorTag>
    00856     inline ForwardIterator
    00857     adjacent_find_switch(ForwardIterator begin, ForwardIterator end,
    00858                          BinaryPredicate pred, IteratorTag)
    00859     { return adjacent_find(begin, end, pred,
    00860                            __gnu_parallel::sequential_tag()); }
    00861
    00862   // Parallel algorithm for random access iterators
    00863   template<typename RandomAccessIterator, typename BinaryPredicate>
    00864     RandomAccessIterator
    00865     adjacent_find_switch(RandomAccessIterator begin, RandomAccessIterator end,
    00866                          BinaryPredicate pred, random_access_iterator_tag)
    00867     {
    00868       if (_GLIBCXX_PARALLEL_CONDITION(true))
    00869         return __gnu_parallel::find_template(begin, end, begin, pred,
    00870                                              __gnu_parallel::
    00871                                              adjacent_find_selector()).first;
    00872       else
    00873         return adjacent_find(begin, end, pred,
    00874                              __gnu_parallel::sequential_tag());
    00875     }
    00876
    00877   // Public interface
    00878   template<typename ForwardIterator, typename BinaryPredicate>
    00879     inline ForwardIterator
    00880     adjacent_find(ForwardIterator begin, ForwardIterator end,
    00881                   BinaryPredicate pred)
    00882     {
    00883       typedef iterator_traits<ForwardIterator> traits_type;
    00884       typedef typename traits_type::iterator_category iterator_category;
    00885       return adjacent_find_switch(begin, end, pred, iterator_category());
    00886     }
    00887
    00888   // Sequential fallback
    00889   template<typename InputIterator, typename T>
    00890     inline typename iterator_traits<InputIterator>::difference_type
    00891     count(InputIterator begin, InputIterator end, const T& value,
    00892           __gnu_parallel::sequential_tag)
    00893     { return _GLIBCXX_STD_P::count(begin, end, value); }
    00894
    00895   // Parallel code for random access iterators
    00896   template<typename RandomAccessIterator, typename T>
    00897     typename iterator_traits<RandomAccessIterator>::difference_type
    00898     count_switch(RandomAccessIterator begin, RandomAccessIterator end,
    00899                  const T& value, random_access_iterator_tag,
    00900                  __gnu_parallel::_Parallelism parallelism_tag
    00901                  = __gnu_parallel::parallel_unbalanced)
    00902     {
    00903       typedef iterator_traits<RandomAccessIterator> traits_type;
    00904       typedef typename traits_type::value_type value_type;
    00905       typedef typename traits_type::difference_type difference_type;
    00906       typedef __gnu_parallel::sequence_index_t sequence_index_t;
    00907
    00908       if (_GLIBCXX_PARALLEL_CONDITION(
    00909             static_cast<sequence_index_t>(end - begin)
    00910             >= __gnu_parallel::_Settings::get().count_minimal_n
    00911             && __gnu_parallel::is_parallel(parallelism_tag)))
    00912         {
    00913           __gnu_parallel::count_selector<RandomAccessIterator, difference_type>
    00914             functionality;
    00915           difference_type res = 0;
    00916           __gnu_parallel::
    00917             for_each_template_random_access(begin, end, value,
    00918                                             functionality,
    00919                                             std::plus<sequence_index_t>(),
    00920                                             res, res, -1, parallelism_tag);
    00921           return res;
    00922         }
    00923       else
    00924         return count(begin, end, value, __gnu_parallel::sequential_tag());
    00925     }
    00926
    00927   // Sequential fallback for input iterator case.
    00928   template<typename InputIterator, typename T, typename IteratorTag>
    00929     inline typename iterator_traits<InputIterator>::difference_type
    00930     count_switch(InputIterator begin, InputIterator end, const T& value,
    00931                  IteratorTag)
    00932     { return count(begin, end, value, __gnu_parallel::sequential_tag()); }
    00933
    00934   // Public interface.
    00935   template<typename InputIterator, typename T>
    00936     inline typename iterator_traits<InputIterator>::difference_type
    00937     count(InputIterator begin, InputIterator end, const T& value,
    00938           __gnu_parallel::_Parallelism parallelism_tag)
    00939     {
    00940       typedef iterator_traits<InputIterator> traits_type;
    00941       typedef typename traits_type::iterator_category iterator_category;
    00942       return count_switch(begin, end, value, iterator_category(),
    00943                           parallelism_tag);
    00944     }
    00945
    00946   template<typename InputIterator, typename T>
    00947     inline typename iterator_traits<InputIterator>::difference_type
    00948     count(InputIterator begin, InputIterator end, const T& value)
    00949     {
    00950       typedef iterator_traits<InputIterator> traits_type;
    00951       typedef typename traits_type::iterator_category iterator_category;
    00952       return count_switch(begin, end, value, iterator_category());
    00953     }
    00954
    00955
    00956   // Sequential fallback.
    00957   template<typename InputIterator, typename Predicate>
    00958     inline typename iterator_traits<InputIterator>::difference_type
    00959     count_if(InputIterator begin, InputIterator end, Predicate pred,
    00960              __gnu_parallel::sequential_tag)
    00961     { return _GLIBCXX_STD_P::count_if(begin, end, pred); }
    00962
    00963   // Parallel count_if for random access iterators
    00964   template<typename RandomAccessIterator, typename Predicate>
    00965     typename iterator_traits<RandomAccessIterator>::difference_type
    00966     count_if_switch(RandomAccessIterator begin, RandomAccessIterator end,
    00967                     Predicate pred, random_access_iterator_tag,
    00968                     __gnu_parallel::_Parallelism parallelism_tag
    00969                     = __gnu_parallel::parallel_unbalanced)
    00970     {
    00971       typedef iterator_traits<RandomAccessIterator> traits_type;
    00972       typedef typename traits_type::value_type value_type;
    00973       typedef typename traits_type::difference_type difference_type;
    00974       typedef __gnu_parallel::sequence_index_t sequence_index_t;
    00975
    00976       if (_GLIBCXX_PARALLEL_CONDITION(
    00977             static_cast<sequence_index_t>(end - begin)
    00978             >= __gnu_parallel::_Settings::get().count_minimal_n
    00979             && __gnu_parallel::is_parallel(parallelism_tag)))
    00980         {
    00981           difference_type res = 0;
    00982           __gnu_parallel::
    00983             count_if_selector<RandomAccessIterator, difference_type>
    00984             functionality;
    00985           __gnu_parallel::
    00986             for_each_template_random_access(begin, end, pred,
    00987                                             functionality,
    00988                                             std::plus<sequence_index_t>(),
    00989                                             res, res, -1, parallelism_tag);
    00990           return res;
    00991         }
    00992       else
    00993         return count_if(begin, end, pred, __gnu_parallel::sequential_tag());
    00994     }
    00995
    00996   // Sequential fallback for input iterator case.
    00997   template<typename InputIterator, typename Predicate, typename IteratorTag>
    00998     inline typename iterator_traits<InputIterator>::difference_type
    00999     count_if_switch(InputIterator begin, InputIterator end, Predicate pred,
    01000                     IteratorTag)
    01001     { return count_if(begin, end, pred, __gnu_parallel::sequential_tag()); }
    01002
    01003   // Public interface.
    01004   template<typename InputIterator, typename Predicate>
    01005     inline typename iterator_traits<InputIterator>::difference_type
    01006     count_if(InputIterator begin, InputIterator end, Predicate pred,
    01007              __gnu_parallel::_Parallelism parallelism_tag)
    01008     {
    01009       typedef iterator_traits<InputIterator> traits_type;
    01010       typedef typename traits_type::iterator_category iterator_category;
    01011       return count_if_switch(begin, end, pred, iterator_category(),
    01012                              parallelism_tag);
    01013     }
    01014
    01015   template<typename InputIterator, typename Predicate>
    01016     inline typename iterator_traits<InputIterator>::difference_type
    01017     count_if(InputIterator begin, InputIterator end, Predicate pred)
    01018     {
    01019       typedef iterator_traits<InputIterator> traits_type;
    01020       typedef typename traits_type::iterator_category iterator_category;
    01021       return count_if_switch(begin, end, pred, iterator_category());
    01022     }
    01023
    01024
    01025   // Sequential fallback.
    01026   template<typename ForwardIterator1, typename ForwardIterator2>
    01027     inline ForwardIterator1
    01028     search(ForwardIterator1 begin1, ForwardIterator1 end1,
    01029            ForwardIterator2 begin2, ForwardIterator2 end2,
    01030            __gnu_parallel::sequential_tag)
    01031     { return _GLIBCXX_STD_P::search(begin1, end1, begin2, end2); }
    01032
    01033   // Parallel algorithm for random access iterator
    01034   template<typename RandomAccessIterator1, typename RandomAccessIterator2>
    01035     RandomAccessIterator1
    01036     search_switch(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
    01037                   RandomAccessIterator2 begin2, RandomAccessIterator2 end2,
    01038                   random_access_iterator_tag, random_access_iterator_tag)
    01039     {
    01040       typedef std::iterator_traits<RandomAccessIterator1> iterator1_traits;
    01041       typedef typename iterator1_traits::value_type value1_type;
    01042       typedef std::iterator_traits<RandomAccessIterator2> iterator2_traits;
    01043       typedef typename iterator2_traits::value_type value2_type;
    01044
    01045       if (_GLIBCXX_PARALLEL_CONDITION(true))
    01046         return __gnu_parallel::
    01047           search_template(begin1, end1, begin2, end2, __gnu_parallel::
    01048                           equal_to<value1_type, value2_type>());
    01049       else
    01050         return search(begin1, end1, begin2, end2,
    01051                       __gnu_parallel::sequential_tag());
    01052     }
    01053
    01054   // Sequential fallback for input iterator case
    01055   template<typename ForwardIterator1, typename ForwardIterator2,
    01056            typename IteratorTag1, typename IteratorTag2>
    01057     inline ForwardIterator1
    01058     search_switch(ForwardIterator1 begin1, ForwardIterator1 end1,
    01059                   ForwardIterator2 begin2, ForwardIterator2 end2,
    01060                   IteratorTag1, IteratorTag2)
    01061     { return search(begin1, end1, begin2, end2,
    01062                     __gnu_parallel::sequential_tag()); }
    01063
    01064   // Public interface.
    01065   template<typename ForwardIterator1, typename ForwardIterator2>
    01066     inline ForwardIterator1
    01067     search(ForwardIterator1 begin1, ForwardIterator1 end1,
    01068            ForwardIterator2 begin2, ForwardIterator2 end2)
    01069     {
    01070       typedef std::iterator_traits<ForwardIterator1> iterator1_traits;
    01071       typedef typename iterator1_traits::iterator_category iterator1_category;
    01072       typedef std::iterator_traits<ForwardIterator2> iterator2_traits;
    01073       typedef typename iterator2_traits::iterator_category iterator2_category;
    01074
    01075       return search_switch(begin1, end1, begin2, end2,
    01076                            iterator1_category(), iterator2_category());
    01077     }
    01078
    01079   // Public interface.
    01080   template<typename ForwardIterator1, typename ForwardIterator2,
    01081            typename BinaryPredicate>
    01082     inline ForwardIterator1
    01083     search(ForwardIterator1 begin1, ForwardIterator1 end1,
    01084            ForwardIterator2 begin2, ForwardIterator2 end2,
    01085            BinaryPredicate pred, __gnu_parallel::sequential_tag)
    01086     { return _GLIBCXX_STD_P::search(begin1, end1, begin2, end2, pred); }
    01087
    01088   // Parallel algorithm for random access iterator.
    01089   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    01090            typename BinaryPredicate>
    01091     RandomAccessIterator1
    01092     search_switch(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
    01093                   RandomAccessIterator2 begin2, RandomAccessIterator2 end2,
    01094                   BinaryPredicate pred,
    01095                   random_access_iterator_tag, random_access_iterator_tag)
    01096     {
    01097       if (_GLIBCXX_PARALLEL_CONDITION(true))
    01098         return __gnu_parallel::search_template(begin1, end1,
    01099                                                begin2, end2, pred);
    01100       else
    01101         return search(begin1, end1, begin2, end2, pred,
    01102                       __gnu_parallel::sequential_tag());
    01103     }
    01104
    01105   // Sequential fallback for input iterator case
    01106   template<typename ForwardIterator1, typename ForwardIterator2,
    01107            typename BinaryPredicate, typename IteratorTag1,
    01108            typename IteratorTag2>
    01109     inline ForwardIterator1
    01110     search_switch(ForwardIterator1 begin1, ForwardIterator1 end1,
    01111                   ForwardIterator2 begin2, ForwardIterator2 end2,
    01112                   BinaryPredicate pred, IteratorTag1, IteratorTag2)
    01113     { return search(begin1, end1, begin2, end2, pred,
    01114                     __gnu_parallel::sequential_tag()); }
    01115
    01116   // Public interface
    01117   template<typename ForwardIterator1, typename ForwardIterator2,
    01118            typename BinaryPredicate>
    01119     inline ForwardIterator1
    01120     search(ForwardIterator1 begin1, ForwardIterator1 end1,
    01121            ForwardIterator2 begin2, ForwardIterator2 end2,
    01122            BinaryPredicate  pred)
    01123     {
    01124       typedef std::iterator_traits<ForwardIterator1> iterator1_traits;
    01125       typedef typename iterator1_traits::iterator_category iterator1_category;
    01126       typedef std::iterator_traits<ForwardIterator2> iterator2_traits;
    01127       typedef typename iterator2_traits::iterator_category iterator2_category;
    01128       return search_switch(begin1, end1, begin2, end2, pred,
    01129                            iterator1_category(), iterator2_category());
    01130     }
    01131
    01132   // Sequential fallback
    01133   template<typename ForwardIterator, typename Integer, typename T>
    01134     inline ForwardIterator
    01135     search_n(ForwardIterator begin, ForwardIterator end, Integer count,
    01136              const T& val, __gnu_parallel::sequential_tag)
    01137     { return _GLIBCXX_STD_P::search_n(begin, end, count, val); }
    01138
    01139   // Sequential fallback
    01140   template<typename ForwardIterator, typename Integer, typename T,
    01141            typename BinaryPredicate>
    01142     inline ForwardIterator
    01143     search_n(ForwardIterator begin, ForwardIterator end, Integer count,
    01144              const T& val, BinaryPredicate binary_pred,
    01145              __gnu_parallel::sequential_tag)
    01146     { return _GLIBCXX_STD_P::search_n(begin, end, count, val, binary_pred); }
    01147
    01148   // Public interface.
    01149   template<typename ForwardIterator, typename Integer, typename T>
    01150     inline ForwardIterator
    01151     search_n(ForwardIterator begin, ForwardIterator end, Integer count,
    01152              const T& val)
    01153     {
    01154       typedef typename iterator_traits<ForwardIterator>::value_type value_type;
    01155       return search_n(begin, end, count, val,
    01156                       __gnu_parallel::equal_to<value_type, T>());
    01157     }
    01158
    01159   // Parallel algorithm for random access iterators.
    01160   template<typename RandomAccessIterator, typename Integer,
    01161            typename T, typename BinaryPredicate>
    01162     RandomAccessIterator
    01163     search_n_switch(RandomAccessIterator begin, RandomAccessIterator end,
    01164                     Integer count, const T& val, BinaryPredicate binary_pred,
    01165                     random_access_iterator_tag)
    01166     {
    01167       if (_GLIBCXX_PARALLEL_CONDITION(true))
    01168         {
    01169           __gnu_parallel::pseudo_sequence<T, Integer> ps(val, count);
    01170           return __gnu_parallel::search_template(begin, end, ps.begin(),
    01171                                                  ps.end(), binary_pred);
    01172         }
    01173       else
    01174         return std::__search_n(begin, end, count, val,
    01175                                binary_pred, random_access_iterator_tag());
    01176     }
    01177
    01178   // Sequential fallback for input iterator case.
    01179   template<typename ForwardIterator, typename Integer, typename T,
    01180            typename BinaryPredicate, typename IteratorTag>
    01181     inline ForwardIterator
    01182     search_n_switch(ForwardIterator begin, ForwardIterator end, Integer count,
    01183                     const T& val, BinaryPredicate binary_pred, IteratorTag)
    01184     { return __search_n(begin, end, count, val, binary_pred, IteratorTag()); }
    01185
    01186   // Public interface.
    01187   template<typename ForwardIterator, typename Integer, typename T,
    01188            typename BinaryPredicate>
    01189     inline ForwardIterator
    01190     search_n(ForwardIterator begin, ForwardIterator end, Integer count,
    01191              const T& val, BinaryPredicate binary_pred)
    01192     {
    01193       return search_n_switch(begin, end, count, val, binary_pred,
    01194                              typename std::iterator_traits<ForwardIterator>::
    01195                              iterator_category());
    01196     }
    01197
    01198
    01199   // Sequential fallback.
    01200   template<typename InputIterator, typename OutputIterator,
    01201            typename UnaryOperation>
    01202     inline OutputIterator
    01203     transform(InputIterator begin, InputIterator end, OutputIterator result,
    01204               UnaryOperation unary_op, __gnu_parallel::sequential_tag)
    01205     { return _GLIBCXX_STD_P::transform(begin, end, result, unary_op); }
    01206
    01207   // Parallel unary transform for random access iterators.
    01208   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    01209            typename UnaryOperation>
    01210     RandomAccessIterator2
    01211     transform1_switch(RandomAccessIterator1 begin, RandomAccessIterator1 end,
    01212                       RandomAccessIterator2 result, UnaryOperation unary_op,
    01213                       random_access_iterator_tag, random_access_iterator_tag,
    01214                       __gnu_parallel::_Parallelism parallelism_tag
    01215                       = __gnu_parallel::parallel_balanced)
    01216     {
    01217       if (_GLIBCXX_PARALLEL_CONDITION(
    01218             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    01219             >= __gnu_parallel::_Settings::get().transform_minimal_n
    01220             && __gnu_parallel::is_parallel(parallelism_tag)))
    01221         {
    01222           bool dummy = true;
    01223           typedef __gnu_parallel::iterator_pair<RandomAccessIterator1,
    01224             RandomAccessIterator2, random_access_iterator_tag> ip;
    01225           ip begin_pair(begin, result), end_pair(end, result + (end - begin));
    01226           __gnu_parallel::transform1_selector<ip> functionality;
    01227           __gnu_parallel::
    01228             for_each_template_random_access(begin_pair, end_pair,
    01229                                             unary_op, functionality,
    01230                                             __gnu_parallel::dummy_reduct(),
    01231                                             dummy, dummy, -1, parallelism_tag);
    01232           return functionality.finish_iterator;
    01233         }
    01234       else
    01235         return transform(begin, end, result, unary_op,
    01236                          __gnu_parallel::sequential_tag());
    01237     }
    01238
    01239   // Sequential fallback for input iterator case.
    01240   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    01241            typename UnaryOperation, typename IteratorTag1,
    01242            typename IteratorTag2>
    01243     inline RandomAccessIterator2
    01244     transform1_switch(RandomAccessIterator1 begin, RandomAccessIterator1 end,
    01245                       RandomAccessIterator2 result, UnaryOperation unary_op,
    01246                       IteratorTag1, IteratorTag2)
    01247     { return transform(begin, end, result, unary_op,
    01248                        __gnu_parallel::sequential_tag()); }
    01249
    01250   // Public interface.
    01251   template<typename InputIterator, typename OutputIterator,
    01252            typename UnaryOperation>
    01253     inline OutputIterator
    01254     transform(InputIterator begin, InputIterator end, OutputIterator result,
    01255               UnaryOperation unary_op,
    01256               __gnu_parallel::_Parallelism parallelism_tag)
    01257     {
    01258       typedef std::iterator_traits<InputIterator> iteratori_traits;
    01259       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    01260       typedef typename iteratori_traits::iterator_category iteratori_category;
    01261       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    01262
    01263       return transform1_switch(begin, end, result, unary_op,
    01264                                iteratori_category(), iteratoro_category(),
    01265                                parallelism_tag);
    01266     }
    01267
    01268   template<typename InputIterator, typename OutputIterator,
    01269            typename UnaryOperation>
    01270     inline OutputIterator
    01271     transform(InputIterator begin, InputIterator end, OutputIterator result,
    01272               UnaryOperation unary_op)
    01273     {
    01274       typedef std::iterator_traits<InputIterator> iteratori_traits;
    01275       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    01276       typedef typename iteratori_traits::iterator_category iteratori_category;
    01277       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    01278
    01279       return transform1_switch(begin, end, result, unary_op,
    01280                                iteratori_category(), iteratoro_category());
    01281     }
    01282
    01283
    01284   // Sequential fallback
    01285   template<typename InputIterator1, typename InputIterator2,
    01286            typename OutputIterator, typename BinaryOperation>
    01287     inline OutputIterator
    01288     transform(InputIterator1 begin1, InputIterator1 end1,
    01289               InputIterator2 begin2, OutputIterator result,
    01290               BinaryOperation binary_op, __gnu_parallel::sequential_tag)
    01291     { return _GLIBCXX_STD_P::transform(begin1, end1,
    01292                                        begin2, result, binary_op); }
    01293
    01294   // Parallel binary transform for random access iterators.
    01295   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    01296            typename RandomAccessIterator3, typename BinaryOperation>
    01297     RandomAccessIterator3
    01298     transform2_switch(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
    01299                       RandomAccessIterator2 begin2,
    01300                       RandomAccessIterator3 result, BinaryOperation binary_op,
    01301                       random_access_iterator_tag, random_access_iterator_tag,
    01302                       random_access_iterator_tag,
    01303                       __gnu_parallel::_Parallelism parallelism_tag
    01304                       = __gnu_parallel::parallel_balanced)
    01305     {
    01306       if (_GLIBCXX_PARALLEL_CONDITION(
    01307             (end1 - begin1) >=
    01308                 __gnu_parallel::_Settings::get().transform_minimal_n
    01309             && __gnu_parallel::is_parallel(parallelism_tag)))
    01310         {
    01311           bool dummy = true;
    01312           typedef __gnu_parallel::iterator_triple<RandomAccessIterator1,
    01313             RandomAccessIterator2, RandomAccessIterator3,
    01314             random_access_iterator_tag> ip;
    01315           ip begin_triple(begin1, begin2, result),
    01316             end_triple(end1, begin2 + (end1 - begin1),
    01317                        result + (end1 - begin1));
    01318           __gnu_parallel::transform2_selector<ip> functionality;
    01319           __gnu_parallel::
    01320             for_each_template_random_access(begin_triple, end_triple,
    01321                                             binary_op, functionality,
    01322                                             __gnu_parallel::dummy_reduct(),
    01323                                             dummy, dummy, -1,
    01324                                             parallelism_tag);
    01325           return functionality.finish_iterator;
    01326         }
    01327       else
    01328         return transform(begin1, end1, begin2, result, binary_op,
    01329                          __gnu_parallel::sequential_tag());
    01330     }
    01331
    01332   // Sequential fallback for input iterator case.
    01333   template<typename InputIterator1, typename InputIterator2,
    01334            typename OutputIterator, typename BinaryOperation,
    01335            typename tag1, typename tag2, typename tag3>
    01336     inline OutputIterator
    01337     transform2_switch(InputIterator1 begin1, InputIterator1 end1,
    01338                       InputIterator2 begin2, OutputIterator result,
    01339                       BinaryOperation binary_op, tag1, tag2, tag3)
    01340     { return transform(begin1, end1, begin2, result, binary_op,
    01341                        __gnu_parallel::sequential_tag()); }
    01342
    01343   // Public interface.
    01344   template<typename InputIterator1, typename InputIterator2,
    01345            typename OutputIterator, typename BinaryOperation>
    01346     inline OutputIterator
    01347     transform(InputIterator1 begin1, InputIterator1 end1,
    01348               InputIterator2 begin2, OutputIterator result,
    01349               BinaryOperation binary_op,
    01350               __gnu_parallel::_Parallelism parallelism_tag)
    01351     {
    01352       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    01353       typedef typename iteratori1_traits::iterator_category
    01354         iteratori1_category;
    01355       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    01356       typedef typename iteratori2_traits::iterator_category
    01357         iteratori2_category;
    01358       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    01359       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    01360
    01361       return transform2_switch(begin1, end1, begin2, result, binary_op,
    01362                                iteratori1_category(), iteratori2_category(),
    01363                                iteratoro_category(), parallelism_tag);
    01364     }
    01365
    01366   template<typename InputIterator1, typename InputIterator2,
    01367            typename OutputIterator, typename BinaryOperation>
    01368     inline OutputIterator
    01369     transform(InputIterator1 begin1, InputIterator1 end1,
    01370               InputIterator2 begin2, OutputIterator result,
    01371               BinaryOperation binary_op)
    01372     {
    01373       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    01374       typedef typename iteratori1_traits::iterator_category
    01375         iteratori1_category;
    01376       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    01377       typedef typename iteratori2_traits::iterator_category
    01378         iteratori2_category;
    01379       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    01380       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    01381
    01382       return transform2_switch(begin1, end1, begin2, result, binary_op,
    01383                                iteratori1_category(), iteratori2_category(),
    01384                                iteratoro_category());
    01385     }
    01386
    01387   // Sequential fallback
    01388   template<typename ForwardIterator, typename T>
    01389     inline void
    01390     replace(ForwardIterator begin, ForwardIterator end, const T& old_value,
    01391             const T& new_value, __gnu_parallel::sequential_tag)
    01392     { _GLIBCXX_STD_P::replace(begin, end, old_value, new_value); }
    01393
    01394   // Sequential fallback for input iterator case
    01395   template<typename ForwardIterator, typename T, typename IteratorTag>
    01396     inline void
    01397     replace_switch(ForwardIterator begin, ForwardIterator end,
    01398                    const T& old_value, const T& new_value, IteratorTag)
    01399     { replace(begin, end, old_value, new_value,
    01400               __gnu_parallel::sequential_tag()); }
    01401
    01402   // Parallel replace for random access iterators
    01403   template<typename RandomAccessIterator, typename T>
    01404     inline void
    01405     replace_switch(RandomAccessIterator begin, RandomAccessIterator end,
    01406                    const T& old_value, const T& new_value,
    01407                    random_access_iterator_tag,
    01408                    __gnu_parallel::_Parallelism parallelism_tag
    01409                    = __gnu_parallel::parallel_balanced)
    01410     {
    01411       // XXX parallel version is where?
    01412       replace(begin, end, old_value, new_value,
    01413               __gnu_parallel::sequential_tag());
    01414     }
    01415
    01416   // Public interface
    01417   template<typename ForwardIterator, typename T>
    01418     inline void
    01419     replace(ForwardIterator begin, ForwardIterator end, const T& old_value,
    01420             const T& new_value, __gnu_parallel::_Parallelism parallelism_tag)
    01421     {
    01422       typedef iterator_traits<ForwardIterator> traits_type;
    01423       typedef typename traits_type::iterator_category iterator_category;
    01424       replace_switch(begin, end, old_value, new_value, iterator_category(),
    01425                      parallelism_tag);
    01426     }
    01427
    01428   template<typename ForwardIterator, typename T>
    01429     inline void
    01430     replace(ForwardIterator begin, ForwardIterator end, const T& old_value,
    01431             const T& new_value)
    01432     {
    01433       typedef iterator_traits<ForwardIterator> traits_type;
    01434       typedef typename traits_type::iterator_category iterator_category;
    01435       replace_switch(begin, end, old_value, new_value, iterator_category());
    01436     }
    01437
    01438
    01439   // Sequential fallback
    01440   template<typename ForwardIterator, typename Predicate, typename T>
    01441     inline void
    01442     replace_if(ForwardIterator begin, ForwardIterator end, Predicate pred,
    01443                const T& new_value, __gnu_parallel::sequential_tag)
    01444     { _GLIBCXX_STD_P::replace_if(begin, end, pred, new_value); }
    01445
    01446   // Sequential fallback for input iterator case
    01447   template<typename ForwardIterator, typename Predicate, typename T,
    01448            typename IteratorTag>
    01449     inline void
    01450     replace_if_switch(ForwardIterator begin, ForwardIterator end,
    01451                       Predicate pred, const T& new_value, IteratorTag)
    01452     { replace_if(begin, end, pred, new_value,
    01453                  __gnu_parallel::sequential_tag()); }
    01454
    01455   // Parallel algorithm for random access iterators.
    01456   template<typename RandomAccessIterator, typename Predicate, typename T>
    01457     void
    01458     replace_if_switch(RandomAccessIterator begin, RandomAccessIterator end,
    01459                       Predicate pred, const T& new_value,
    01460                       random_access_iterator_tag,
    01461                       __gnu_parallel::_Parallelism parallelism_tag
    01462                       = __gnu_parallel::parallel_balanced)
    01463     {
    01464       if (_GLIBCXX_PARALLEL_CONDITION(
    01465             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    01466             >= __gnu_parallel::_Settings::get().replace_minimal_n
    01467             && __gnu_parallel::is_parallel(parallelism_tag)))
    01468         {
    01469           bool dummy;
    01470           __gnu_parallel::
    01471             replace_if_selector<RandomAccessIterator, Predicate, T>
    01472             functionality(new_value);
    01473           __gnu_parallel::
    01474             for_each_template_random_access(begin, end, pred,
    01475                                             functionality,
    01476                                             __gnu_parallel::dummy_reduct(),
    01477                                             true, dummy, -1, parallelism_tag);
    01478         }
    01479       else
    01480         replace_if(begin, end, pred, new_value,
    01481                    __gnu_parallel::sequential_tag());
    01482     }
    01483
    01484   // Public interface.
    01485   template<typename ForwardIterator, typename Predicate, typename T>
    01486     inline void
    01487     replace_if(ForwardIterator begin, ForwardIterator end,
    01488                Predicate pred, const T& new_value,
    01489                __gnu_parallel::_Parallelism parallelism_tag)
    01490     {
    01491       typedef std::iterator_traits<ForwardIterator> iterator_traits;
    01492       typedef typename iterator_traits::iterator_category iterator_category;
    01493       replace_if_switch(begin, end, pred, new_value, iterator_category(),
    01494                         parallelism_tag);
    01495     }
    01496
    01497   template<typename ForwardIterator, typename Predicate, typename T>
    01498     inline void
    01499     replace_if(ForwardIterator begin, ForwardIterator end,
    01500                Predicate pred, const T& new_value)
    01501     {
    01502       typedef std::iterator_traits<ForwardIterator> iterator_traits;
    01503       typedef typename iterator_traits::iterator_category iterator_category;
    01504       replace_if_switch(begin, end, pred, new_value, iterator_category());
    01505     }
    01506
    01507   // Sequential fallback
    01508   template<typename ForwardIterator, typename Generator>
    01509     inline void
    01510     generate(ForwardIterator begin, ForwardIterator end, Generator gen,
    01511              __gnu_parallel::sequential_tag)
    01512     { _GLIBCXX_STD_P::generate(begin, end, gen); }
    01513
    01514   // Sequential fallback for input iterator case.
    01515   template<typename ForwardIterator, typename Generator, typename IteratorTag>
    01516     inline void
    01517     generate_switch(ForwardIterator begin, ForwardIterator end, Generator gen,
    01518                     IteratorTag)
    01519     { generate(begin, end, gen, __gnu_parallel::sequential_tag()); }
    01520
    01521   // Parallel algorithm for random access iterators.
    01522   template<typename RandomAccessIterator, typename Generator>
    01523     void
    01524     generate_switch(RandomAccessIterator begin, RandomAccessIterator end,
    01525                     Generator gen, random_access_iterator_tag,
    01526                     __gnu_parallel::_Parallelism parallelism_tag
    01527                     = __gnu_parallel::parallel_balanced)
    01528     {
    01529       if (_GLIBCXX_PARALLEL_CONDITION(
    01530             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    01531             >= __gnu_parallel::_Settings::get().generate_minimal_n
    01532             && __gnu_parallel::is_parallel(parallelism_tag)))
    01533         {
    01534           bool dummy;
    01535           __gnu_parallel::generate_selector<RandomAccessIterator>
    01536             functionality;
    01537           __gnu_parallel::
    01538             for_each_template_random_access(begin, end, gen, functionality,
    01539                                             __gnu_parallel::dummy_reduct(),
    01540                                             true, dummy, -1, parallelism_tag);
    01541         }
    01542       else
    01543         generate(begin, end, gen, __gnu_parallel::sequential_tag());
    01544     }
    01545
    01546   // Public interface.
    01547   template<typename ForwardIterator, typename Generator>
    01548     inline void
    01549     generate(ForwardIterator begin, ForwardIterator end,
    01550              Generator gen, __gnu_parallel::_Parallelism parallelism_tag)
    01551     {
    01552       typedef std::iterator_traits<ForwardIterator> iterator_traits;
    01553       typedef typename iterator_traits::iterator_category iterator_category;
    01554       generate_switch(begin, end, gen, iterator_category(), parallelism_tag);
    01555     }
    01556
    01557   template<typename ForwardIterator, typename Generator>
    01558     inline void
    01559     generate(ForwardIterator begin, ForwardIterator end, Generator gen)
    01560     {
    01561       typedef std::iterator_traits<ForwardIterator> iterator_traits;
    01562       typedef typename iterator_traits::iterator_category iterator_category;
    01563       generate_switch(begin, end, gen, iterator_category());
    01564     }
    01565
    01566
    01567   // Sequential fallback.
    01568   template<typename OutputIterator, typename Size, typename Generator>
    01569     inline OutputIterator
    01570     generate_n(OutputIterator begin, Size n, Generator gen,
    01571                __gnu_parallel::sequential_tag)
    01572     { return _GLIBCXX_STD_P::generate_n(begin, n, gen); }
    01573
    01574   // Sequential fallback for input iterator case.
    01575   template<typename OutputIterator, typename Size, typename Generator,
    01576            typename IteratorTag>
    01577     inline OutputIterator
    01578     generate_n_switch(OutputIterator begin, Size n, Generator gen, IteratorTag)
    01579     { return generate_n(begin, n, gen, __gnu_parallel::sequential_tag()); }
    01580
    01581   // Parallel algorithm for random access iterators.
    01582   template<typename RandomAccessIterator, typename Size, typename Generator>
    01583     inline RandomAccessIterator
    01584     generate_n_switch(RandomAccessIterator begin, Size n, Generator gen,
    01585                       random_access_iterator_tag,
    01586                       __gnu_parallel::_Parallelism parallelism_tag
    01587                       = __gnu_parallel::parallel_balanced)
    01588     {
    01589       // XXX parallel version is where?
    01590       return generate_n(begin, n, gen, __gnu_parallel::sequential_tag());
    01591     }
    01592
    01593   // Public interface.
    01594   template<typename OutputIterator, typename Size, typename Generator>
    01595     inline OutputIterator
    01596     generate_n(OutputIterator begin, Size n, Generator gen,
    01597                __gnu_parallel::_Parallelism parallelism_tag)
    01598     {
    01599       typedef std::iterator_traits<OutputIterator> iterator_traits;
    01600       typedef typename iterator_traits::iterator_category iterator_category;
    01601       return generate_n_switch(begin, n, gen, iterator_category(),
    01602                                parallelism_tag);
    01603     }
    01604
    01605   template<typename OutputIterator, typename Size, typename Generator>
    01606     inline OutputIterator
    01607     generate_n(OutputIterator begin, Size n, Generator gen)
    01608     {
    01609       typedef std::iterator_traits<OutputIterator> iterator_traits;
    01610       typedef typename iterator_traits::iterator_category iterator_category;
    01611       return generate_n_switch(begin, n, gen, iterator_category());
    01612     }
    01613
    01614
    01615   // Sequential fallback.
    01616   template<typename RandomAccessIterator>
    01617     inline void
    01618     random_shuffle(RandomAccessIterator begin, RandomAccessIterator end,
    01619                    __gnu_parallel::sequential_tag)
    01620     { _GLIBCXX_STD_P::random_shuffle(begin, end); }
    01621
    01622   // Sequential fallback.
    01623   template<typename RandomAccessIterator, typename RandomNumberGenerator>
    01624     inline void
    01625     random_shuffle(RandomAccessIterator begin, RandomAccessIterator end,
    01626                    RandomNumberGenerator& rand, __gnu_parallel::sequential_tag)
    01627     { _GLIBCXX_STD_P::random_shuffle(begin, end, rand); }
    01628
    01629
    01630   /** @brief Functor wrapper for std::rand(). */
    01631   template<typename must_be_int = int>
    01632     struct c_rand_number
    01633     {
    01634       int
    01635       operator()(int limit)
    01636       { return rand() % limit; }
    01637     };
    01638
    01639   // Fill in random number generator.
    01640   template<typename RandomAccessIterator>
    01641     inline void
    01642     random_shuffle(RandomAccessIterator begin, RandomAccessIterator end)
    01643     {
    01644       c_rand_number<> r;
    01645       // Parallelization still possible.
    01646       __gnu_parallel::random_shuffle(begin, end, r);
    01647     }
    01648
    01649   // Parallel algorithm for random access iterators.
    01650   template<typename RandomAccessIterator, typename RandomNumberGenerator>
    01651     void
    01652     random_shuffle(RandomAccessIterator begin, RandomAccessIterator end,
    01653                    RandomNumberGenerator& rand)
    01654     {
    01655       if (begin == end)
    01656         return;
    01657       if (_GLIBCXX_PARALLEL_CONDITION(
    01658             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    01659             >= __gnu_parallel::_Settings::get().random_shuffle_minimal_n))
    01660         __gnu_parallel::parallel_random_shuffle(begin, end, rand);
    01661       else
    01662         __gnu_parallel::sequential_random_shuffle(begin, end, rand);
    01663     }
    01664
    01665   // Sequential fallback.
    01666   template<typename ForwardIterator, typename Predicate>
    01667     inline ForwardIterator
    01668     partition(ForwardIterator begin, ForwardIterator end,
    01669               Predicate pred, __gnu_parallel::sequential_tag)
    01670     { return _GLIBCXX_STD_P::partition(begin, end, pred); }
    01671
    01672   // Sequential fallback for input iterator case.
    01673   template<typename ForwardIterator, typename Predicate, typename IteratorTag>
    01674     inline ForwardIterator
    01675     partition_switch(ForwardIterator begin, ForwardIterator end,
    01676                      Predicate pred, IteratorTag)
    01677     { return partition(begin, end, pred, __gnu_parallel::sequential_tag()); }
    01678
    01679   // Parallel algorithm for random access iterators.
    01680   template<typename RandomAccessIterator, typename Predicate>
    01681     RandomAccessIterator
    01682     partition_switch(RandomAccessIterator begin, RandomAccessIterator end,
    01683                      Predicate pred, random_access_iterator_tag)
    01684     {
    01685       if (_GLIBCXX_PARALLEL_CONDITION(
    01686             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    01687             >= __gnu_parallel::_Settings::get().partition_minimal_n))
    01688         {
    01689           typedef typename std::iterator_traits<RandomAccessIterator>::
    01690             difference_type difference_type;
    01691           difference_type middle = __gnu_parallel::
    01692             parallel_partition(begin, end, pred,
    01693                                __gnu_parallel::get_max_threads());
    01694           return begin + middle;
    01695         }
    01696       else
    01697         return partition(begin, end, pred, __gnu_parallel::sequential_tag());
    01698     }
    01699
    01700   // Public interface.
    01701   template<typename ForwardIterator, typename Predicate>
    01702     inline ForwardIterator
    01703     partition(ForwardIterator begin, ForwardIterator end, Predicate pred)
    01704     {
    01705       typedef iterator_traits<ForwardIterator> traits_type;
    01706       typedef typename traits_type::iterator_category iterator_category;
    01707       return partition_switch(begin, end, pred, iterator_category());
    01708     }
    01709
    01710   // sort interface
    01711
    01712   // Sequential fallback
    01713   template<typename RandomAccessIterator>
    01714     inline void
    01715     sort(RandomAccessIterator begin, RandomAccessIterator end,
    01716          __gnu_parallel::sequential_tag)
    01717     { _GLIBCXX_STD_P::sort(begin, end); }
    01718
    01719   // Sequential fallback
    01720   template<typename RandomAccessIterator, typename Comparator>
    01721     inline void
    01722     sort(RandomAccessIterator begin, RandomAccessIterator end, Comparator comp,
    01723          __gnu_parallel::sequential_tag)
    01724     { _GLIBCXX_STD_P::sort<RandomAccessIterator, Comparator>(begin, end,
    01725                                                              comp); }
    01726
    01727   // Public interface
    01728   template<typename RandomAccessIterator, typename Comparator,
    01729            typename Parallelism>
    01730   void
    01731   sort(RandomAccessIterator begin, RandomAccessIterator end, Comparator comp,
    01732        Parallelism parallelism)
    01733   {
    01734     typedef iterator_traits<RandomAccessIterator> traits_type;
    01735     typedef typename traits_type::value_type value_type;
    01736
    01737     if (begin != end)
    01738       {
    01739         if (_GLIBCXX_PARALLEL_CONDITION(
    01740             static_cast<__gnu_parallel::sequence_index_t>(end - begin) >=
    01741               __gnu_parallel::_Settings::get().sort_minimal_n))
    01742           __gnu_parallel::parallel_sort<false>(begin, end, comp, parallelism);
    01743         else
    01744           sort(begin, end, comp, __gnu_parallel::sequential_tag());
    01745       }
    01746   }
    01747
    01748   // Public interface, insert default comparator
    01749   template<typename RandomAccessIterator>
    01750     inline void
    01751     sort(RandomAccessIterator begin, RandomAccessIterator end)
    01752     {
    01753       typedef iterator_traits<RandomAccessIterator> traits_type;
    01754       typedef typename traits_type::value_type value_type;
    01755       sort(begin, end, std::less<value_type>(),
    01756            __gnu_parallel::default_parallel_tag());
    01757     }
    01758
    01759   // Public interface, insert default comparator
    01760   template<typename RandomAccessIterator>
    01761   inline void
    01762   sort(RandomAccessIterator begin, RandomAccessIterator end,
    01763        __gnu_parallel::default_parallel_tag parallelism)
    01764   {
    01765     typedef iterator_traits<RandomAccessIterator> traits_type;
    01766     typedef typename traits_type::value_type value_type;
    01767     sort(begin, end, std::less<value_type>(), parallelism);
    01768   }
    01769
    01770   // Public interface, insert default comparator
    01771   template<typename RandomAccessIterator>
    01772   inline void
    01773   sort(RandomAccessIterator begin, RandomAccessIterator end,
    01774        __gnu_parallel::parallel_tag parallelism)
    01775   {
    01776     typedef iterator_traits<RandomAccessIterator> traits_type;
    01777     typedef typename traits_type::value_type value_type;
    01778     sort(begin, end, std::less<value_type>(), parallelism);
    01779   }
    01780
    01781   // Public interface, insert default comparator
    01782   template<typename RandomAccessIterator>
    01783   inline void
    01784   sort(RandomAccessIterator begin, RandomAccessIterator end,
    01785        __gnu_parallel::multiway_mergesort_tag parallelism)
    01786   {
    01787     typedef iterator_traits<RandomAccessIterator> traits_type;
    01788     typedef typename traits_type::value_type value_type;
    01789     sort(begin, end, std::less<value_type>(), parallelism);
    01790   }
    01791
    01792   // Public interface, insert default comparator
    01793   template<typename RandomAccessIterator>
    01794   inline void
    01795   sort(RandomAccessIterator begin, RandomAccessIterator end,
    01796        __gnu_parallel::multiway_mergesort_sampling_tag parallelism)
    01797   {
    01798     typedef iterator_traits<RandomAccessIterator> traits_type;
    01799     typedef typename traits_type::value_type value_type;
    01800     sort(begin, end, std::less<value_type>(), parallelism);
    01801   }
    01802
    01803   // Public interface, insert default comparator
    01804   template<typename RandomAccessIterator>
    01805   inline void
    01806   sort(RandomAccessIterator begin, RandomAccessIterator end,
    01807        __gnu_parallel::multiway_mergesort_exact_tag parallelism)
    01808   {
    01809     typedef iterator_traits<RandomAccessIterator> traits_type;
    01810     typedef typename traits_type::value_type value_type;
    01811     sort(begin, end, std::less<value_type>(), parallelism);
    01812   }
    01813
    01814   // Public interface, insert default comparator
    01815   template<typename RandomAccessIterator>
    01816   inline void
    01817   sort(RandomAccessIterator begin, RandomAccessIterator end,
    01818        __gnu_parallel::quicksort_tag parallelism)
    01819   {
    01820     typedef iterator_traits<RandomAccessIterator> traits_type;
    01821     typedef typename traits_type::value_type value_type;
    01822     sort(begin, end, std::less<value_type>(), parallelism);
    01823   }
    01824
    01825   // Public interface, insert default comparator
    01826   template<typename RandomAccessIterator>
    01827   inline void
    01828   sort(RandomAccessIterator begin, RandomAccessIterator end,
    01829        __gnu_parallel::balanced_quicksort_tag parallelism)
    01830   {
    01831     typedef iterator_traits<RandomAccessIterator> traits_type;
    01832     typedef typename traits_type::value_type value_type;
    01833     sort(begin, end, std::less<value_type>(), parallelism);
    01834   }
    01835
    01836   // Public interface
    01837   template<typename RandomAccessIterator, typename Comparator>
    01838     void
    01839     sort(RandomAccessIterator begin, RandomAccessIterator end, Comparator comp)
    01840     {
    01841       typedef iterator_traits<RandomAccessIterator> traits_type;
    01842       typedef typename traits_type::value_type value_type;
    01843     sort(begin, end, comp, __gnu_parallel::default_parallel_tag());
    01844   }
    01845
    01846
    01847   // stable_sort interface
    01848
    01849
    01850   // Sequential fallback
    01851   template<typename RandomAccessIterator>
    01852   inline void
    01853   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01854        __gnu_parallel::sequential_tag)
    01855   { _GLIBCXX_STD_P::stable_sort(begin, end); }
    01856
    01857   // Sequential fallback
    01858   template<typename RandomAccessIterator, typename Comparator>
    01859   inline void
    01860   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01861               Comparator comp, __gnu_parallel::sequential_tag)
    01862   { _GLIBCXX_STD_P::stable_sort<RandomAccessIterator, Comparator>(
    01863       begin, end, comp); }
    01864
    01865   // Public interface
    01866   template<typename RandomAccessIterator, typename Comparator,
    01867            typename Parallelism>
    01868   void
    01869   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01870               Comparator comp, Parallelism parallelism)
    01871   {
    01872     typedef iterator_traits<RandomAccessIterator> traits_type;
    01873     typedef typename traits_type::value_type value_type;
    01874
    01875     if (begin != end)
    01876       {
    01877         if (_GLIBCXX_PARALLEL_CONDITION(
    01878               static_cast<__gnu_parallel::sequence_index_t>(end - begin) >=
    01879               __gnu_parallel::_Settings::get().sort_minimal_n))
    01880           __gnu_parallel::parallel_sort<true>(begin, end, comp, parallelism);
    01881         else
    01882           stable_sort(begin, end, comp, __gnu_parallel::sequential_tag());
    01883       }
    01884   }
    01885
    01886   // Public interface, insert default comparator
    01887   template<typename RandomAccessIterator>
    01888   inline void
    01889   stable_sort(RandomAccessIterator begin, RandomAccessIterator end)
    01890   {
    01891     typedef iterator_traits<RandomAccessIterator> traits_type;
    01892     typedef typename traits_type::value_type value_type;
    01893     stable_sort(begin, end, std::less<value_type>(),
    01894                 __gnu_parallel::default_parallel_tag());
    01895   }
    01896
    01897   // Public interface, insert default comparator
    01898   template<typename RandomAccessIterator>
    01899   inline void
    01900   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01901               __gnu_parallel::default_parallel_tag parallelism)
    01902   {
    01903     typedef iterator_traits<RandomAccessIterator> traits_type;
    01904     typedef typename traits_type::value_type value_type;
    01905     stable_sort(begin, end, std::less<value_type>(), parallelism);
    01906   }
    01907
    01908   // Public interface, insert default comparator
    01909   template<typename RandomAccessIterator>
    01910   inline void
    01911   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01912               __gnu_parallel::parallel_tag parallelism)
    01913   {
    01914     typedef iterator_traits<RandomAccessIterator> traits_type;
    01915     typedef typename traits_type::value_type value_type;
    01916     stable_sort(begin, end, std::less<value_type>(), parallelism);
    01917   }
    01918
    01919   // Public interface, insert default comparator
    01920   template<typename RandomAccessIterator>
    01921   inline void
    01922   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01923               __gnu_parallel::multiway_mergesort_tag parallelism)
    01924   {
    01925     typedef iterator_traits<RandomAccessIterator> traits_type;
    01926     typedef typename traits_type::value_type value_type;
    01927     stable_sort(begin, end, std::less<value_type>(), parallelism);
    01928   }
    01929
    01930   // Public interface, insert default comparator
    01931   template<typename RandomAccessIterator>
    01932   inline void
    01933   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01934               __gnu_parallel::quicksort_tag parallelism)
    01935   {
    01936     typedef iterator_traits<RandomAccessIterator> traits_type;
    01937     typedef typename traits_type::value_type value_type;
    01938     stable_sort(begin, end, std::less<value_type>(), parallelism);
    01939   }
    01940
    01941   // Public interface, insert default comparator
    01942   template<typename RandomAccessIterator>
    01943   inline void
    01944   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01945               __gnu_parallel::balanced_quicksort_tag parallelism)
    01946   {
    01947     typedef iterator_traits<RandomAccessIterator> traits_type;
    01948     typedef typename traits_type::value_type value_type;
    01949     stable_sort(begin, end, std::less<value_type>(), parallelism);
    01950   }
    01951
    01952   // Public interface
    01953   template<typename RandomAccessIterator, typename Comparator>
    01954   void
    01955   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01956               Comparator comp)
    01957   {
    01958     typedef iterator_traits<RandomAccessIterator> traits_type;
    01959     typedef typename traits_type::value_type value_type;
    01960     stable_sort(begin, end, comp, __gnu_parallel::default_parallel_tag());
    01961   }
    01962
    01963
    01964 //   // Sequential fallback
    01965 //   template<typename RandomAccessIterator>
    01966 //   inline void
    01967 //   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01968 //            __gnu_parallel::sequential_tag)
    01969 //   { return _GLIBCXX_STD_P::stable_sort(begin, end); }
    01970 //
    01971 //   // Sequential fallback
    01972 //   template<typename RandomAccessIterator, typename Comparator>
    01973 //   inline void
    01974 //   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01975 //            Comparator comp, __gnu_parallel::sequential_tag)
    01976 //   { return _GLIBCXX_STD_P::stable_sort(begin, end, comp); }
    01977 //
    01978 //   template<typename RandomAccessIterator>
    01979 //   void
    01980 //   stable_sort(RandomAccessIterator begin, RandomAccessIterator end)
    01981 //   {
    01982 //     typedef iterator_traits<RandomAccessIterator> traits_type;
    01983 //     typedef typename traits_type::value_type value_type;
    01984 //     stable_sort(begin, end, std::less<value_type>());
    01985 //   }
    01986 //
    01987 //   // Parallel algorithm for random access iterators
    01988 //   template<typename RandomAccessIterator, typename Comparator>
    01989 //   void
    01990 //   stable_sort(RandomAccessIterator begin, RandomAccessIterator end,
    01991 //            Comparator comp)
    01992 //   {
    01993 //     if (begin != end)
    01994 //       {
    01995 //      if (_GLIBCXX_PARALLEL_CONDITION(
    01996 //            static_cast<__gnu_parallel::sequence_index_t>(end - begin) >=
    01997 //                __gnu_parallel::_Settings::get().sort_minimal_n))
    01998 //        __gnu_parallel::parallel_sort(begin, end, comp,
    01999 //                                      __gnu_parallel::parallel_tag());
    02000 //      else
    02001 //        stable_sort(begin, end, comp, __gnu_parallel::sequential_tag());
    02002 //       }
    02003 //   }
    02004
    02005   // Sequential fallback
    02006   template<typename InputIterator1, typename InputIterator2,
    02007            typename OutputIterator>
    02008     inline OutputIterator
    02009     merge(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    02010           InputIterator2 end2, OutputIterator result,
    02011           __gnu_parallel::sequential_tag)
    02012     { return _GLIBCXX_STD_P::merge(begin1, end1, begin2, end2, result); }
    02013
    02014   // Sequential fallback
    02015   template<typename InputIterator1, typename InputIterator2,
    02016            typename OutputIterator, typename Comparator>
    02017     inline OutputIterator
    02018     merge(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    02019           InputIterator2 end2, OutputIterator result, Comparator comp,
    02020           __gnu_parallel::sequential_tag)
    02021     { return _GLIBCXX_STD_P::merge(begin1, end1, begin2, end2, result, comp); }
    02022
    02023   // Sequential fallback for input iterator case
    02024   template<typename InputIterator1, typename InputIterator2,
    02025            typename OutputIterator, typename Comparator,
    02026            typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
    02027     inline OutputIterator
    02028     merge_switch(InputIterator1 begin1, InputIterator1 end1,
    02029                  InputIterator2 begin2, InputIterator2 end2,
    02030                  OutputIterator result, Comparator comp,
    02031                  IteratorTag1, IteratorTag2, IteratorTag3)
    02032      { return _GLIBCXX_STD_P::merge(begin1, end1, begin2, end2,
    02033                                     result, comp); }
    02034
    02035   // Parallel algorithm for random access iterators
    02036   template<typename InputIterator1, typename InputIterator2,
    02037            typename OutputIterator, typename Comparator>
    02038     OutputIterator
    02039     merge_switch(InputIterator1 begin1, InputIterator1 end1,
    02040                  InputIterator2 begin2, InputIterator2 end2,
    02041                  OutputIterator result, Comparator comp,
    02042                  random_access_iterator_tag, random_access_iterator_tag,
    02043                  random_access_iterator_tag)
    02044     {
    02045       if (_GLIBCXX_PARALLEL_CONDITION(
    02046             (static_cast<__gnu_parallel::sequence_index_t>(end1 - begin1)
    02047              >= __gnu_parallel::_Settings::get().merge_minimal_n
    02048              || static_cast<__gnu_parallel::sequence_index_t>(end2 - begin2)
    02049              >= __gnu_parallel::_Settings::get().merge_minimal_n)))
    02050         return __gnu_parallel::parallel_merge_advance(begin1, end1,
    02051                                                       begin2, end2,
    02052                                                       result, (end1 - begin1)
    02053                                                       + (end2 - begin2), comp);
    02054       else
    02055         return __gnu_parallel::merge_advance(begin1, end1, begin2, end2,
    02056                                              result, (end1 - begin1)
    02057                                              + (end2 - begin2), comp);
    02058   }
    02059
    02060   // Public interface
    02061   template<typename InputIterator1, typename InputIterator2,
    02062            typename OutputIterator, typename Comparator>
    02063     inline OutputIterator
    02064     merge(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    02065           InputIterator2 end2, OutputIterator result, Comparator comp)
    02066     {
    02067       typedef typename iterator_traits<InputIterator1>::value_type value_type;
    02068
    02069       typedef std::iterator_traits<InputIterator1> iteratori1_traits;
    02070       typedef std::iterator_traits<InputIterator2> iteratori2_traits;
    02071       typedef std::iterator_traits<OutputIterator> iteratoro_traits;
    02072       typedef typename iteratori1_traits::iterator_category
    02073         iteratori1_category;
    02074       typedef typename iteratori2_traits::iterator_category
    02075         iteratori2_category;
    02076       typedef typename iteratoro_traits::iterator_category iteratoro_category;
    02077
    02078       return merge_switch(begin1, end1, begin2, end2, result, comp,
    02079                           iteratori1_category(), iteratori2_category(),
    02080                           iteratoro_category());
    02081   }
    02082
    02083
    02084   // Public interface, insert default comparator
    02085   template<typename InputIterator1, typename InputIterator2,
    02086            typename OutputIterator>
    02087     inline OutputIterator
    02088     merge(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    02089           InputIterator2 end2, OutputIterator result)
    02090     {
    02091       typedef std::iterator_traits<InputIterator1> iterator1_traits;
    02092       typedef std::iterator_traits<InputIterator2> iterator2_traits;
    02093       typedef typename iterator1_traits::value_type value1_type;
    02094       typedef typename iterator2_traits::value_type value2_type;
    02095
    02096       return merge(begin1, end1, begin2, end2, result,
    02097                    __gnu_parallel::less<value1_type, value2_type>());
    02098     }
    02099
    02100   // Sequential fallback
    02101   template<typename RandomAccessIterator>
    02102     inline void
    02103     nth_element(RandomAccessIterator begin, RandomAccessIterator nth,
    02104                 RandomAccessIterator end, __gnu_parallel::sequential_tag)
    02105     { return _GLIBCXX_STD_P::nth_element(begin, nth, end); }
    02106
    02107   // Sequential fallback
    02108   template<typename RandomAccessIterator, typename Comparator>
    02109     inline void
    02110     nth_element(RandomAccessIterator begin, RandomAccessIterator nth,
    02111                 RandomAccessIterator end, Comparator comp,
    02112               __gnu_parallel::sequential_tag)
    02113     { return _GLIBCXX_STD_P::nth_element(begin, nth, end, comp); }
    02114
    02115   // Public interface
    02116   template<typename RandomAccessIterator, typename Comparator>
    02117     inline void
    02118     nth_element(RandomAccessIterator begin, RandomAccessIterator nth,
    02119                 RandomAccessIterator end, Comparator comp)
    02120     {
    02121       if (_GLIBCXX_PARALLEL_CONDITION(
    02122             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    02123             >= __gnu_parallel::_Settings::get().nth_element_minimal_n))
    02124         __gnu_parallel::parallel_nth_element(begin, nth, end, comp);
    02125       else
    02126         nth_element(begin, nth, end, comp, __gnu_parallel::sequential_tag());
    02127     }
    02128
    02129   // Public interface, insert default comparator
    02130   template<typename RandomAccessIterator>
    02131     inline void
    02132     nth_element(RandomAccessIterator begin, RandomAccessIterator nth,
    02133                 RandomAccessIterator end)
    02134     {
    02135       typedef iterator_traits<RandomAccessIterator> traits_type;
    02136       typedef typename traits_type::value_type value_type;
    02137       nth_element(begin, nth, end, std::less<value_type>());
    02138     }
    02139
    02140   // Sequential fallback
    02141   template<typename RandomAccessIterator, typename _Compare>
    02142     inline void
    02143     partial_sort(RandomAccessIterator begin, RandomAccessIterator middle,
    02144                  RandomAccessIterator end, _Compare comp,
    02145                  __gnu_parallel::sequential_tag)
    02146     { _GLIBCXX_STD_P::partial_sort(begin, middle, end, comp); }
    02147
    02148   // Sequential fallback
    02149   template<typename RandomAccessIterator>
    02150     inline void
    02151     partial_sort(RandomAccessIterator begin, RandomAccessIterator middle,
    02152                  RandomAccessIterator end, __gnu_parallel::sequential_tag)
    02153     { _GLIBCXX_STD_P::partial_sort(begin, middle, end); }
    02154
    02155   // Public interface, parallel algorithm for random access iterators
    02156   template<typename RandomAccessIterator, typename _Compare>
    02157     void
    02158     partial_sort(RandomAccessIterator begin, RandomAccessIterator middle,
    02159                  RandomAccessIterator end, _Compare comp)
    02160     {
    02161       if (_GLIBCXX_PARALLEL_CONDITION(
    02162             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    02163             >= __gnu_parallel::_Settings::get().partial_sort_minimal_n))
    02164         __gnu_parallel::parallel_partial_sort(begin, middle, end, comp);
    02165       else
    02166         partial_sort(begin, middle, end, comp,
    02167                      __gnu_parallel::sequential_tag());
    02168     }
    02169
    02170   // Public interface, insert default comparator
    02171   template<typename RandomAccessIterator>
    02172     inline void
    02173     partial_sort(RandomAccessIterator begin, RandomAccessIterator middle,
    02174                  RandomAccessIterator end)
    02175     {
    02176       typedef iterator_traits<RandomAccessIterator> traits_type;
    02177       typedef typename traits_type::value_type value_type;
    02178       partial_sort(begin, middle, end, std::less<value_type>());
    02179     }
    02180
    02181   // Sequential fallback
    02182   template<typename ForwardIterator>
    02183     inline ForwardIterator
    02184     max_element(ForwardIterator begin, ForwardIterator end,
    02185                 __gnu_parallel::sequential_tag)
    02186     { return _GLIBCXX_STD_P::max_element(begin, end); }
    02187
    02188   // Sequential fallback
    02189   template<typename ForwardIterator, typename Comparator>
    02190     inline ForwardIterator
    02191     max_element(ForwardIterator begin, ForwardIterator end, Comparator comp,
    02192                 __gnu_parallel::sequential_tag)
    02193     { return _GLIBCXX_STD_P::max_element(begin, end, comp); }
    02194
    02195   // Sequential fallback for input iterator case
    02196   template<typename ForwardIterator, typename Comparator, typename IteratorTag>
    02197     inline ForwardIterator
    02198     max_element_switch(ForwardIterator begin, ForwardIterator end,
    02199                        Comparator comp, IteratorTag)
    02200     { return max_element(begin, end, comp, __gnu_parallel::sequential_tag()); }
    02201
    02202   // Parallel algorithm for random access iterators
    02203   template<typename RandomAccessIterator, typename Comparator>
    02204     RandomAccessIterator
    02205     max_element_switch(RandomAccessIterator begin, RandomAccessIterator end,
    02206                        Comparator comp, random_access_iterator_tag,
    02207                        __gnu_parallel::_Parallelism parallelism_tag
    02208                        = __gnu_parallel::parallel_balanced)
    02209     {
    02210       if (_GLIBCXX_PARALLEL_CONDITION(
    02211             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    02212             >= __gnu_parallel::_Settings::get().max_element_minimal_n
    02213             && __gnu_parallel::is_parallel(parallelism_tag)))
    02214         {
    02215           RandomAccessIterator res(begin);
    02216           __gnu_parallel::identity_selector<RandomAccessIterator>
    02217             functionality;
    02218           __gnu_parallel::
    02219             for_each_template_random_access(begin, end,
    02220                                             __gnu_parallel::nothing(),
    02221                                             functionality,
    02222                                             __gnu_parallel::
    02223                                             max_element_reduct<Comparator,
    02224                                             RandomAccessIterator>(comp),
    02225                                             res, res, -1, parallelism_tag);
    02226           return res;
    02227         }
    02228       else
    02229         return max_element(begin, end, comp, __gnu_parallel::sequential_tag());
    02230     }
    02231
    02232   // Public interface, insert default comparator
    02233   template<typename ForwardIterator>
    02234     inline ForwardIterator
    02235     max_element(ForwardIterator begin, ForwardIterator end,
    02236                 __gnu_parallel::_Parallelism parallelism_tag)
    02237     {
    02238       typedef typename iterator_traits<ForwardIterator>::value_type value_type;
    02239       return max_element(begin, end, std::less<value_type>(), parallelism_tag);
    02240     }
    02241
    02242   template<typename ForwardIterator>
    02243     inline ForwardIterator
    02244     max_element(ForwardIterator begin, ForwardIterator end)
    02245     {
    02246       typedef typename iterator_traits<ForwardIterator>::value_type value_type;
    02247       return max_element(begin, end, std::less<value_type>());
    02248     }
    02249
    02250   // Public interface
    02251   template<typename ForwardIterator, typename Comparator>
    02252     inline ForwardIterator
    02253     max_element(ForwardIterator begin, ForwardIterator end, Comparator comp,
    02254                 __gnu_parallel::_Parallelism parallelism_tag)
    02255     {
    02256       typedef iterator_traits<ForwardIterator> traits_type;
    02257       typedef typename traits_type::iterator_category iterator_category;
    02258       return max_element_switch(begin, end, comp, iterator_category(),
    02259                                 parallelism_tag);
    02260     }
    02261
    02262   template<typename ForwardIterator, typename Comparator>
    02263     inline ForwardIterator
    02264     max_element(ForwardIterator begin, ForwardIterator end, Comparator comp)
    02265     {
    02266       typedef iterator_traits<ForwardIterator> traits_type;
    02267       typedef typename traits_type::iterator_category iterator_category;
    02268       return max_element_switch(begin, end, comp, iterator_category());
    02269     }
    02270
    02271
    02272   // Sequential fallback
    02273   template<typename ForwardIterator>
    02274     inline ForwardIterator
    02275     min_element(ForwardIterator begin, ForwardIterator end,
    02276                 __gnu_parallel::sequential_tag)
    02277     { return _GLIBCXX_STD_P::min_element(begin, end); }
    02278
    02279   // Sequential fallback
    02280   template<typename ForwardIterator, typename Comparator>
    02281     inline ForwardIterator
    02282     min_element(ForwardIterator begin, ForwardIterator end, Comparator comp,
    02283                 __gnu_parallel::sequential_tag)
    02284     { return _GLIBCXX_STD_P::min_element(begin, end, comp); }
    02285
    02286   // Sequential fallback for input iterator case
    02287   template<typename ForwardIterator, typename Comparator, typename IteratorTag>
    02288     inline ForwardIterator
    02289     min_element_switch(ForwardIterator begin, ForwardIterator end,
    02290                        Comparator comp, IteratorTag)
    02291     { return min_element(begin, end, comp, __gnu_parallel::sequential_tag()); }
    02292
    02293   // Parallel algorithm for random access iterators
    02294   template<typename RandomAccessIterator, typename Comparator>
    02295     RandomAccessIterator
    02296     min_element_switch(RandomAccessIterator begin, RandomAccessIterator end,
    02297                        Comparator comp, random_access_iterator_tag,
    02298                        __gnu_parallel::_Parallelism parallelism_tag
    02299                        = __gnu_parallel::parallel_balanced)
    02300     {
    02301       if (_GLIBCXX_PARALLEL_CONDITION(
    02302             static_cast<__gnu_parallel::sequence_index_t>(end - begin)
    02303             >= __gnu_parallel::_Settings::get().min_element_minimal_n
    02304             && __gnu_parallel::is_parallel(parallelism_tag)))
    02305         {
    02306           RandomAccessIterator res(begin);
    02307           __gnu_parallel::identity_selector<RandomAccessIterator>
    02308             functionality;
    02309           __gnu_parallel::
    02310             for_each_template_random_access(begin, end,
    02311                                             __gnu_parallel::nothing(),
    02312                                             functionality,
    02313                                             __gnu_parallel::
    02314                                             min_element_reduct<Comparator,
    02315                                             RandomAccessIterator>(comp),
    02316                                             res, res, -1, parallelism_tag);
    02317           return res;
    02318         }
    02319       else
    02320         return min_element(begin, end, comp, __gnu_parallel::sequential_tag());
    02321     }
    02322
    02323   // Public interface, insert default comparator
    02324   template<typename ForwardIterator>
    02325     inline ForwardIterator
    02326     min_element(ForwardIterator begin, ForwardIterator end,
    02327                 __gnu_parallel::_Parallelism parallelism_tag)
    02328     {
    02329       typedef typename iterator_traits<ForwardIterator>::value_type value_type;
    02330       return min_element(begin, end, std::less<value_type>(), parallelism_tag);
    02331     }
    02332
    02333   template<typename ForwardIterator>
    02334     inline ForwardIterator
    02335     min_element(ForwardIterator begin, ForwardIterator end)
    02336     {
    02337       typedef typename iterator_traits<ForwardIterator>::value_type value_type;
    02338       return min_element(begin, end, std::less<value_type>());
    02339     }
    02340
    02341   // Public interface
    02342   template<typename ForwardIterator, typename Comparator>
    02343     inline ForwardIterator
    02344     min_element(ForwardIterator begin, ForwardIterator end, Comparator comp,
    02345                 __gnu_parallel::_Parallelism parallelism_tag)
    02346     {
    02347       typedef iterator_traits<ForwardIterator> traits_type;
    02348       typedef typename traits_type::iterator_category iterator_category;
    02349       return min_element_switch(begin, end, comp, iterator_category(),
    02350                                 parallelism_tag);
    02351     }
    02352
    02353   template<typename ForwardIterator, typename Comparator>
    02354     inline ForwardIterator
    02355     min_element(ForwardIterator begin, ForwardIterator end, Comparator comp)
    02356     {
    02357       typedef iterator_traits<ForwardIterator> traits_type;
    02358       typedef typename traits_type::iterator_category iterator_category;
    02359       return min_element_switch(begin, end, comp, iterator_category());
    02360     }
    02361 } // end namespace
    02362 } // end namespace
    02363
    02364 #endif /* _GLIBCXX_PARALLEL_ALGO_H */