parallel/numeric

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 /**
00026  * @file parallel/numeric
00027 *
00028  * @brief Parallel STL function calls corresponding to stl_numeric.h.
00029  * The functions defined here mainly do case switches and
00030  * call the actual parallelized versions in other files.
00031  * Inlining policy: Functions that basically only contain one function call,
00032  * are declared inline.
00033  *  This file is a GNU parallel extension to the Standard C++ Library.
00034  */
00035 
00036 // Written by Johannes Singler and Felix Putze.
00037 
00038 #ifndef _GLIBCXX_PARALLEL_NUMERIC_H
00039 #define _GLIBCXX_PARALLEL_NUMERIC_H 1
00040 
00041 #include <numeric>
00042 #include <functional>
00043 #include <parallel/numericfwd.h>
00044 #include <parallel/iterator.h>
00045 #include <parallel/for_each.h>
00046 #include <parallel/for_each_selectors.h>
00047 #include <parallel/partial_sum.h>
00048 
00049 namespace std
00050 {
00051 namespace __parallel
00052 {
00053   // Sequential fallback.
00054   template<typename InputIterator, typename T>
00055     inline T
00056     accumulate(InputIterator begin, InputIterator end, T init, 
00057            __gnu_parallel::sequential_tag)
00058     { return _GLIBCXX_STD_P::accumulate(begin, end, init); }
00059 
00060   template<typename InputIterator, typename T, typename BinaryOperation>
00061     inline T
00062     accumulate(InputIterator begin, InputIterator end, T init,
00063            BinaryOperation binary_op, __gnu_parallel::sequential_tag)
00064     { return _GLIBCXX_STD_P::accumulate(begin, end, init, binary_op); }
00065 
00066   // Sequential fallback for input iterator case.
00067   template<typename InputIterator, typename T, typename IteratorTag>
00068     inline T
00069     accumulate_switch(InputIterator begin, InputIterator end,
00070               T init, IteratorTag) 
00071     { return accumulate(begin, end, init, __gnu_parallel::sequential_tag()); }
00072 
00073   template<typename InputIterator, typename T, typename BinaryOperation,
00074        typename IteratorTag>
00075     inline T
00076     accumulate_switch(InputIterator begin, InputIterator end, T init, 
00077               BinaryOperation binary_op, IteratorTag)
00078     { return accumulate(begin, end, init, binary_op, 
00079             __gnu_parallel::sequential_tag()); }
00080 
00081   // Parallel algorithm for random access iterators.
00082   template<typename _RandomAccessIterator, typename T,
00083        typename BinaryOperation>
00084     T
00085     accumulate_switch(_RandomAccessIterator begin, _RandomAccessIterator end, 
00086               T init, BinaryOperation binary_op, 
00087               random_access_iterator_tag, 
00088               __gnu_parallel::_Parallelism parallelism_tag  
00089               = __gnu_parallel::parallel_unbalanced)
00090     {
00091       if (_GLIBCXX_PARALLEL_CONDITION(
00092         static_cast<__gnu_parallel::sequence_index_t>(end - begin)
00093         >= __gnu_parallel::_Settings::get().accumulate_minimal_n
00094         && __gnu_parallel::is_parallel(parallelism_tag)))
00095     {
00096       T res = init;
00097       __gnu_parallel::accumulate_selector<_RandomAccessIterator>
00098         my_selector;
00099       __gnu_parallel::
00100 	    for_each_template_random_access_ed(begin, end,
00101                         __gnu_parallel::nothing(),
00102                         my_selector,
00103                         __gnu_parallel::
00104                         accumulate_binop_reduct
00105                         <BinaryOperation>(binary_op),
00106                         res, res, -1);
00107       return res;
00108     }
00109       else
00110     return accumulate(begin, end, init, binary_op, 
00111               __gnu_parallel::sequential_tag());
00112     }
00113 
00114   // Public interface.
00115   template<typename InputIterator, typename T>
00116     inline T
00117     accumulate(InputIterator begin, InputIterator end, T init, 
00118            __gnu_parallel::_Parallelism parallelism_tag)
00119     {
00120       typedef std::iterator_traits<InputIterator> iterator_traits;
00121       typedef typename iterator_traits::value_type value_type;
00122       typedef typename iterator_traits::iterator_category iterator_category;
00123 
00124       return accumulate_switch(begin, end, init,
00125                    __gnu_parallel::plus<T, value_type>(),
00126                    iterator_category(), parallelism_tag);
00127     }
00128 
00129   template<typename InputIterator, typename T>
00130     inline T
00131     accumulate(InputIterator begin, InputIterator end, T init)
00132     {
00133       typedef std::iterator_traits<InputIterator> iterator_traits;
00134       typedef typename iterator_traits::value_type value_type;
00135       typedef typename iterator_traits::iterator_category iterator_category;
00136 
00137       return accumulate_switch(begin, end, init,
00138                    __gnu_parallel::plus<T, value_type>(),
00139                    iterator_category());
00140     }
00141 
00142   template<typename InputIterator, typename T, typename BinaryOperation>
00143     inline T
00144     accumulate(InputIterator begin, InputIterator end, T init, 
00145            BinaryOperation binary_op, 
00146            __gnu_parallel::_Parallelism parallelism_tag)
00147     {
00148       typedef iterator_traits<InputIterator> iterator_traits;
00149       typedef typename iterator_traits::iterator_category iterator_category;
00150       return accumulate_switch(begin, end, init, binary_op, 
00151                    iterator_category(), parallelism_tag);
00152     }
00153 
00154   template<typename InputIterator, typename T, typename BinaryOperation>
00155     inline T
00156     accumulate(InputIterator begin, InputIterator end, T init, 
00157            BinaryOperation binary_op) 
00158     {
00159       typedef iterator_traits<InputIterator> iterator_traits;
00160       typedef typename iterator_traits::iterator_category iterator_category;
00161       return accumulate_switch(begin, end, init, binary_op, 
00162                    iterator_category());
00163     }
00164 
00165 
00166   // Sequential fallback.
00167   template<typename InputIterator1, typename InputIterator2, typename T>
00168     inline T
00169     inner_product(InputIterator1 first1, InputIterator1 last1, 
00170           InputIterator2 first2, T init,
00171           __gnu_parallel::sequential_tag)
00172     { return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init); }
00173 
00174   template<typename InputIterator1, typename InputIterator2, typename T,
00175        typename BinaryFunction1, typename BinaryFunction2>
00176     inline T
00177     inner_product(InputIterator1 first1, InputIterator1 last1, 
00178           InputIterator2 first2, T init, BinaryFunction1 binary_op1, 
00179           BinaryFunction2 binary_op2, __gnu_parallel::sequential_tag)
00180     { return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init, 
00181                        binary_op1, binary_op2); }
00182 
00183   // Parallel algorithm for random access iterators.
00184   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
00185        typename T, typename BinaryFunction1, typename BinaryFunction2>
00186     T
00187     inner_product_switch(RandomAccessIterator1 first1,
00188              RandomAccessIterator1 last1,
00189              RandomAccessIterator2 first2, T init,
00190              BinaryFunction1 binary_op1,
00191              BinaryFunction2 binary_op2,
00192              random_access_iterator_tag,
00193              random_access_iterator_tag,
00194              __gnu_parallel::_Parallelism parallelism_tag
00195              = __gnu_parallel::parallel_unbalanced)
00196     {
00197       if (_GLIBCXX_PARALLEL_CONDITION((last1 - first1)
00198                       >= __gnu_parallel::_Settings::get().
00199                       accumulate_minimal_n
00200                       && __gnu_parallel::
00201                       is_parallel(parallelism_tag)))
00202     {
00203       T res = init;
00204       __gnu_parallel::
00205 	    inner_product_selector<RandomAccessIterator1,
00206         RandomAccessIterator2, T> my_selector(first1, first2);
00207       __gnu_parallel::
00208 	    for_each_template_random_access_ed(first1, last1, binary_op2,
00209                         my_selector, binary_op1,
00210                         res, res, -1);
00211       return res;
00212     }
00213       else
00214     return inner_product(first1, last1, first2, init, 
00215                  __gnu_parallel::sequential_tag());
00216     }
00217 
00218   // No parallelism for input iterators.
00219   template<typename InputIterator1, typename InputIterator2, typename T,
00220        typename BinaryFunction1, typename BinaryFunction2,
00221        typename IteratorTag1, typename IteratorTag2>
00222     inline T
00223     inner_product_switch(InputIterator1 first1, InputIterator1 last1, 
00224              InputIterator2 first2, T init, 
00225              BinaryFunction1 binary_op1,
00226              BinaryFunction2 binary_op2, 
00227              IteratorTag1, IteratorTag2)
00228     { return inner_product(first1, last1, first2, init,
00229                binary_op1, binary_op2,
00230                __gnu_parallel::sequential_tag()); }
00231 
00232   template<typename InputIterator1, typename InputIterator2, typename T,
00233        typename BinaryFunction1, typename BinaryFunction2>
00234     inline T
00235     inner_product(InputIterator1 first1, InputIterator1 last1, 
00236           InputIterator2 first2, T init, BinaryFunction1 binary_op1, 
00237           BinaryFunction2 binary_op2, 
00238           __gnu_parallel::_Parallelism parallelism_tag)
00239     {
00240       typedef iterator_traits<InputIterator1> traits1_type;
00241       typedef typename traits1_type::iterator_category iterator1_category;
00242 
00243       typedef iterator_traits<InputIterator2> traits2_type;
00244       typedef typename traits2_type::iterator_category iterator2_category;
00245 
00246       return inner_product_switch(first1, last1, first2, init, binary_op1, 
00247                   binary_op2, iterator1_category(), 
00248                   iterator2_category(), parallelism_tag);
00249     }
00250 
00251   template<typename InputIterator1, typename InputIterator2, typename T,
00252        typename BinaryFunction1, typename BinaryFunction2>
00253     inline T
00254     inner_product(InputIterator1 first1, InputIterator1 last1, 
00255           InputIterator2 first2, T init, BinaryFunction1 binary_op1, 
00256           BinaryFunction2 binary_op2)
00257     {
00258       typedef iterator_traits<InputIterator1> traits1_type;
00259       typedef typename traits1_type::iterator_category iterator1_category;
00260 
00261       typedef iterator_traits<InputIterator2> traits2_type;
00262       typedef typename traits2_type::iterator_category iterator2_category;
00263 
00264       return inner_product_switch(first1, last1, first2, init, binary_op1, 
00265                   binary_op2, iterator1_category(),
00266                   iterator2_category());
00267     }
00268 
00269   template<typename InputIterator1, typename InputIterator2, typename T>
00270     inline T
00271     inner_product(InputIterator1 first1, InputIterator1 last1, 
00272           InputIterator2 first2, T init, 
00273           __gnu_parallel::_Parallelism parallelism_tag)
00274     {
00275       typedef iterator_traits<InputIterator1> traits_type1;
00276       typedef typename traits_type1::value_type value_type1;
00277       typedef iterator_traits<InputIterator2> traits_type2;
00278       typedef typename traits_type2::value_type value_type2;
00279 
00280       typedef typename
00281     __gnu_parallel::multiplies<value_type1, value_type2>::result
00282         multiplies_result_type;
00283       return inner_product(first1, last1, first2, init,
00284                            __gnu_parallel::plus<T, multiplies_result_type>(),
00285                            __gnu_parallel::
00286                multiplies<value_type1, value_type2>(),
00287                            parallelism_tag);
00288     }
00289 
00290   template<typename InputIterator1, typename InputIterator2, typename T>
00291     inline T
00292     inner_product(InputIterator1 first1, InputIterator1 last1, 
00293           InputIterator2 first2, T init)
00294     {
00295       typedef iterator_traits<InputIterator1> traits_type1;
00296       typedef typename traits_type1::value_type value_type1;
00297       typedef iterator_traits<InputIterator2> traits_type2;
00298       typedef typename traits_type2::value_type value_type2;
00299 
00300       typedef typename
00301     __gnu_parallel::multiplies<value_type1, value_type2>::result
00302         multiplies_result_type;
00303       return inner_product(first1, last1, first2, init,
00304                            __gnu_parallel::plus<T, multiplies_result_type>(),
00305                            __gnu_parallel::
00306                multiplies<value_type1, value_type2>());
00307     }
00308 
00309   // Sequential fallback.
00310   template<typename InputIterator, typename OutputIterator>
00311     inline OutputIterator
00312     partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
00313         __gnu_parallel::sequential_tag)
00314     { return _GLIBCXX_STD_P::partial_sum(begin, end, result); }
00315 
00316   // Sequential fallback.
00317   template<typename InputIterator, typename OutputIterator,
00318        typename BinaryOperation>
00319     inline OutputIterator
00320     partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
00321         BinaryOperation bin_op, __gnu_parallel::sequential_tag)
00322     { return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op); }
00323 
00324   // Sequential fallback for input iterator case.
00325   template<typename InputIterator, typename OutputIterator,
00326        typename BinaryOperation, typename IteratorTag1,
00327        typename IteratorTag2>
00328     inline OutputIterator
00329     partial_sum_switch(InputIterator begin, InputIterator end,
00330                OutputIterator result, BinaryOperation bin_op,
00331                IteratorTag1, IteratorTag2)
00332     { return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op); }
00333 
00334   // Parallel algorithm for random access iterators.
00335   template<typename InputIterator, typename OutputIterator,
00336        typename BinaryOperation>
00337     OutputIterator
00338     partial_sum_switch(InputIterator begin, InputIterator end,
00339                OutputIterator result, BinaryOperation bin_op,
00340                random_access_iterator_tag, random_access_iterator_tag)
00341     {
00342       if (_GLIBCXX_PARALLEL_CONDITION(
00343         static_cast<__gnu_parallel::sequence_index_t>(end - begin)
00344         >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
00345     return __gnu_parallel::parallel_partial_sum(begin, end,
00346                             result, bin_op);
00347       else
00348     return partial_sum(begin, end, result, bin_op,
00349                __gnu_parallel::sequential_tag());
00350     }
00351 
00352   // Public interface.
00353   template<typename InputIterator, typename OutputIterator>
00354     inline OutputIterator
00355     partial_sum(InputIterator begin, InputIterator end, OutputIterator result)
00356     {
00357       typedef typename iterator_traits<InputIterator>::value_type value_type;
00358       return partial_sum(begin, end, result, std::plus<value_type>());
00359     }
00360 
00361   // Public interface
00362   template<typename InputIterator, typename OutputIterator,
00363        typename BinaryOperation>
00364     inline OutputIterator
00365     partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
00366         BinaryOperation binary_op)
00367     {
00368       typedef iterator_traits<InputIterator> traitsi_type;
00369       typedef typename traitsi_type::iterator_category iteratori_category;
00370 
00371       typedef iterator_traits<OutputIterator> traitso_type;
00372       typedef typename traitso_type::iterator_category iteratoro_category;
00373 
00374       return partial_sum_switch(begin, end, result, binary_op,
00375                 iteratori_category(), iteratoro_category());
00376     }
00377 
00378   // Sequential fallback.
00379   template<typename InputIterator, typename OutputIterator>
00380     inline OutputIterator
00381     adjacent_difference(InputIterator begin, InputIterator end,
00382             OutputIterator result, __gnu_parallel::sequential_tag)
00383     { return _GLIBCXX_STD_P::adjacent_difference(begin, end, result); }
00384 
00385   // Sequential fallback.
00386   template<typename InputIterator, typename OutputIterator,
00387        typename BinaryOperation>
00388     inline OutputIterator
00389     adjacent_difference(InputIterator begin, InputIterator end,
00390             OutputIterator result, BinaryOperation bin_op,
00391             __gnu_parallel::sequential_tag)
00392     { return _GLIBCXX_STD_P::adjacent_difference(begin, end, result, bin_op); }
00393 
00394   // Sequential fallback for input iterator case.
00395   template<typename InputIterator, typename OutputIterator,
00396        typename BinaryOperation, typename IteratorTag1,
00397        typename IteratorTag2>
00398     inline OutputIterator
00399     adjacent_difference_switch(InputIterator begin, InputIterator end,
00400                    OutputIterator result, BinaryOperation bin_op,
00401                  IteratorTag1, IteratorTag2)
00402     { return adjacent_difference(begin, end, result, bin_op,  
00403                  __gnu_parallel::sequential_tag()); }
00404 
00405   // Parallel algorithm for random access iterators.
00406   template<typename InputIterator, typename OutputIterator,
00407        typename BinaryOperation>
00408     OutputIterator
00409     adjacent_difference_switch(InputIterator begin, InputIterator end,
00410                    OutputIterator result, BinaryOperation bin_op,
00411                    random_access_iterator_tag, 
00412                    random_access_iterator_tag,
00413                    __gnu_parallel::_Parallelism parallelism_tag
00414                    = __gnu_parallel::parallel_balanced)
00415     {
00416       if (_GLIBCXX_PARALLEL_CONDITION(
00417         static_cast<__gnu_parallel::sequence_index_t>(end - begin)
00418         >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
00419         && __gnu_parallel::is_parallel(parallelism_tag)))
00420     {
00421       bool dummy = true;
00422       typedef __gnu_parallel::iterator_pair<InputIterator, OutputIterator,
00423         random_access_iterator_tag> ip;
00424       *result = *begin;
00425       ip begin_pair(begin + 1, result + 1),
00426         end_pair(end, result + (end - begin));
00427       __gnu_parallel::adjacent_difference_selector<ip> functionality;
00428       __gnu_parallel::
00429 	    for_each_template_random_access_ed(begin_pair, end_pair, bin_op,
00430                         functionality,
00431                         __gnu_parallel::dummy_reduct(),
00432                         dummy, dummy, -1);
00433       return functionality.finish_iterator;
00434     }
00435       else
00436     return adjacent_difference(begin, end, result, bin_op, 
00437                    __gnu_parallel::sequential_tag());
00438     }
00439 
00440   // Public interface.
00441   template<typename InputIterator, typename OutputIterator>
00442     inline OutputIterator
00443     adjacent_difference(InputIterator begin, InputIterator end,
00444             OutputIterator result,
00445             __gnu_parallel::_Parallelism parallelism_tag)
00446     {
00447       typedef iterator_traits<InputIterator> traits_type;
00448       typedef typename traits_type::value_type value_type;
00449       return adjacent_difference(begin, end, result, std::minus<value_type>(),
00450                  parallelism_tag);
00451     }
00452 
00453   template<typename InputIterator, typename OutputIterator>
00454     inline OutputIterator
00455     adjacent_difference(InputIterator begin, InputIterator end,
00456             OutputIterator result)
00457     {
00458       typedef iterator_traits<InputIterator> traits_type;
00459       typedef typename traits_type::value_type value_type;
00460       return adjacent_difference(begin, end, result, std::minus<value_type>());
00461     }
00462 
00463   template<typename InputIterator, typename OutputIterator,
00464        typename BinaryOperation>
00465     inline OutputIterator
00466     adjacent_difference(InputIterator begin, InputIterator end,
00467             OutputIterator result, BinaryOperation binary_op,
00468             __gnu_parallel::_Parallelism parallelism_tag)
00469     {
00470       typedef iterator_traits<InputIterator> traitsi_type;
00471       typedef typename traitsi_type::iterator_category iteratori_category;
00472 
00473       typedef iterator_traits<OutputIterator> traitso_type;
00474       typedef typename traitso_type::iterator_category iteratoro_category;
00475 
00476       return adjacent_difference_switch(begin, end, result, binary_op,
00477                     iteratori_category(), 
00478                     iteratoro_category(), parallelism_tag);
00479     }
00480 
00481   template<typename InputIterator, typename OutputIterator,
00482        typename BinaryOperation>
00483     inline OutputIterator
00484     adjacent_difference(InputIterator begin, InputIterator end,
00485             OutputIterator result, BinaryOperation binary_op)
00486     {
00487       typedef iterator_traits<InputIterator> traitsi_type;
00488       typedef typename traitsi_type::iterator_category iteratori_category;
00489 
00490       typedef iterator_traits<OutputIterator> traitso_type;
00491       typedef typename traitso_type::iterator_category iteratoro_category;
00492 
00493       return adjacent_difference_switch(begin, end, result, binary_op,
00494                     iteratori_category(), 
00495                     iteratoro_category());
00496     }
00497 } // end namespace
00498 } // end namespace
00499 
00500 #endif /* _GLIBCXX_NUMERIC_H */

Generated on 27 Oct 2009 for libstdc++ by  doxygen 1.6.1