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 <bits/stl_function.h>
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 _IIter, typename _Tp>
00055     inline _Tp
00056     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
00057                __gnu_parallel::sequential_tag)
00058     { return _GLIBCXX_STD_P::accumulate(__begin, __end, __init); }
00059 
00060   template<typename _IIter, typename _Tp, typename _BinaryOperation>
00061     inline _Tp
00062     accumulate(_IIter __begin, _IIter __end, _Tp __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 _IIter, typename _Tp, typename _IteratorTag>
00068     inline _Tp
00069     __accumulate_switch(_IIter __begin, _IIter __end,
00070                       _Tp __init, _IteratorTag) 
00071     { return accumulate(__begin, __end, __init,
00072             __gnu_parallel::sequential_tag()); }
00073 
00074   template<typename _IIter, typename _Tp, typename _BinaryOperation,
00075            typename _IteratorTag>
00076     inline _Tp
00077     __accumulate_switch(_IIter __begin, _IIter __end, _Tp __init, 
00078                       _BinaryOperation __binary_op, _IteratorTag)
00079     { return accumulate(__begin, __end, __init, __binary_op, 
00080                         __gnu_parallel::sequential_tag()); }
00081 
00082   // Parallel algorithm for random access iterators.
00083   template<typename __RAIter, typename _Tp, typename _BinaryOperation>
00084     _Tp
00085     __accumulate_switch(__RAIter __begin, __RAIter __end, 
00086                       _Tp __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::_SequenceIndex>(__end - __begin)
00093             >= __gnu_parallel::_Settings::get().accumulate_minimal_n
00094             && __gnu_parallel::__is_parallel(__parallelism_tag)))
00095         {
00096           _Tp __res = __init;
00097           __gnu_parallel::__accumulate_selector<__RAIter>
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 _IIter, typename _Tp>
00116     inline _Tp
00117     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
00118                __gnu_parallel::_Parallelism __parallelism_tag)
00119     {
00120       typedef std::iterator_traits<_IIter> _IteratorTraits;
00121       typedef typename _IteratorTraits::value_type _ValueType;
00122       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
00123 
00124       return __accumulate_switch(__begin, __end, __init,
00125                  __gnu_parallel::_Plus<_Tp, _ValueType>(),
00126                  _IteratorCategory(), __parallelism_tag);
00127     }
00128 
00129   template<typename _IIter, typename _Tp>
00130     inline _Tp
00131     accumulate(_IIter __begin, _IIter __end, _Tp __init)
00132     {
00133       typedef std::iterator_traits<_IIter> _IteratorTraits;
00134       typedef typename _IteratorTraits::value_type _ValueType;
00135       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
00136 
00137       return __accumulate_switch(__begin, __end, __init,
00138                  __gnu_parallel::_Plus<_Tp, _ValueType>(),
00139                  _IteratorCategory());
00140     }
00141 
00142   template<typename _IIter, typename _Tp, typename _BinaryOperation>
00143     inline _Tp
00144     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
00145                _BinaryOperation __binary_op, 
00146                __gnu_parallel::_Parallelism __parallelism_tag)
00147     {
00148       typedef iterator_traits<_IIter> _IteratorTraits;
00149       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
00150       return __accumulate_switch(__begin, __end, __init, __binary_op, 
00151                  _IteratorCategory(), __parallelism_tag);
00152     }
00153 
00154   template<typename _IIter, typename _Tp, typename _BinaryOperation>
00155     inline _Tp
00156     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
00157                _BinaryOperation __binary_op) 
00158     {
00159       typedef iterator_traits<_IIter> _IteratorTraits;
00160       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
00161       return __accumulate_switch(__begin, __end, __init, __binary_op, 
00162                  _IteratorCategory());
00163     }
00164 
00165 
00166   // Sequential fallback.
00167   template<typename _IIter1, typename _IIter2, typename _Tp>
00168     inline _Tp
00169     inner_product(_IIter1 __first1, _IIter1 __last1, 
00170                   _IIter2 __first2, _Tp __init,
00171                   __gnu_parallel::sequential_tag)
00172     { return _GLIBCXX_STD_P::inner_product(
00173                                __first1, __last1, __first2, __init); }
00174 
00175   template<typename _IIter1, typename _IIter2, typename _Tp,
00176            typename _BinaryFunction1, typename _BinaryFunction2>
00177     inline _Tp
00178     inner_product(_IIter1 __first1, _IIter1 __last1,
00179                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1, 
00180                   _BinaryFunction2 __binary_op2,
00181                   __gnu_parallel::sequential_tag)
00182     { return _GLIBCXX_STD_P::inner_product(__first1, __last1, __first2, __init,
00183                                            __binary_op1, __binary_op2); }
00184 
00185   // Parallel algorithm for random access iterators.
00186   template<typename _RAIter1, typename _RAIter2,
00187            typename _Tp, typename _BinaryFunction1, typename _BinaryFunction2>
00188     _Tp
00189     __inner_product_switch(_RAIter1 __first1,
00190                _RAIter1 __last1,
00191                _RAIter2 __first2, _Tp __init,
00192                _BinaryFunction1 __binary_op1,
00193                _BinaryFunction2 __binary_op2,
00194                random_access_iterator_tag,
00195                random_access_iterator_tag,
00196                __gnu_parallel::_Parallelism __parallelism_tag
00197                = __gnu_parallel::parallel_unbalanced)
00198     {
00199       if (_GLIBCXX_PARALLEL_CONDITION((__last1 - __first1)
00200                                       >= __gnu_parallel::_Settings::get().
00201                                       accumulate_minimal_n
00202                                       && __gnu_parallel::
00203                                       __is_parallel(__parallelism_tag)))
00204         {
00205           _Tp __res = __init;
00206           __gnu_parallel::
00207             __inner_product_selector<_RAIter1,
00208             _RAIter2, _Tp> __my_selector(__first1, __first2);
00209           __gnu_parallel::
00210             __for_each_template_random_access_ed(
00211                 __first1, __last1, __binary_op2, __my_selector, __binary_op1,
00212                 __res, __res, -1);
00213           return __res;
00214         }
00215       else
00216         return inner_product(__first1, __last1, __first2, __init, 
00217                              __gnu_parallel::sequential_tag());
00218     }
00219 
00220   // No parallelism for input iterators.
00221   template<typename _IIter1, typename _IIter2, typename _Tp,
00222            typename _BinaryFunction1, typename _BinaryFunction2,
00223            typename _IteratorTag1, typename _IteratorTag2>
00224     inline _Tp
00225     __inner_product_switch(_IIter1 __first1, _IIter1 __last1, 
00226                _IIter2 __first2, _Tp __init, 
00227                _BinaryFunction1 __binary_op1,
00228                _BinaryFunction2 __binary_op2, 
00229                _IteratorTag1, _IteratorTag2)
00230     { return inner_product(__first1, __last1, __first2, __init, __binary_op1,
00231                __binary_op2, __gnu_parallel::sequential_tag()); }
00232 
00233   template<typename _IIter1, typename _IIter2, typename _Tp,
00234            typename _BinaryFunction1, typename _BinaryFunction2>
00235     inline _Tp
00236     inner_product(_IIter1 __first1, _IIter1 __last1, 
00237                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1, 
00238                   _BinaryFunction2 __binary_op2, 
00239                   __gnu_parallel::_Parallelism __parallelism_tag)
00240     {
00241       typedef iterator_traits<_IIter1> _TraitsType1;
00242       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
00243 
00244       typedef iterator_traits<_IIter2> _TraitsType2;
00245       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
00246 
00247       return __inner_product_switch(__first1, __last1, __first2, __init,
00248                     __binary_op1, __binary_op2,
00249                     _IteratorCategory1(), _IteratorCategory2(),
00250                     __parallelism_tag);
00251     }
00252 
00253   template<typename _IIter1, typename _IIter2, typename _Tp,
00254            typename _BinaryFunction1, typename _BinaryFunction2>
00255     inline _Tp
00256     inner_product(_IIter1 __first1, _IIter1 __last1, 
00257                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1, 
00258                   _BinaryFunction2 __binary_op2)
00259     {
00260       typedef iterator_traits<_IIter1> _TraitsType1;
00261       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
00262 
00263       typedef iterator_traits<_IIter2> _TraitsType2;
00264       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
00265 
00266       return __inner_product_switch(__first1, __last1, __first2, __init,
00267                     __binary_op1, __binary_op2,
00268                     _IteratorCategory1(),
00269                     _IteratorCategory2());
00270     }
00271 
00272   template<typename _IIter1, typename _IIter2, typename _Tp>
00273     inline _Tp
00274     inner_product(_IIter1 __first1, _IIter1 __last1, 
00275                   _IIter2 __first2, _Tp __init, 
00276                   __gnu_parallel::_Parallelism __parallelism_tag)
00277     {
00278       typedef iterator_traits<_IIter1> _TraitsType1;
00279       typedef typename _TraitsType1::value_type _ValueType1;
00280       typedef iterator_traits<_IIter2> _TraitsType2;
00281       typedef typename _TraitsType2::value_type _ValueType2;
00282 
00283       typedef typename
00284         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::__result
00285         _MultipliesResultType;
00286       return inner_product(__first1, __last1, __first2, __init,
00287                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
00288                            __gnu_parallel::
00289                            _Multiplies<_ValueType1, _ValueType2>(),
00290                            __parallelism_tag);
00291     }
00292 
00293   template<typename _IIter1, typename _IIter2, typename _Tp>
00294     inline _Tp
00295     inner_product(_IIter1 __first1, _IIter1 __last1, 
00296                   _IIter2 __first2, _Tp __init)
00297     {
00298       typedef iterator_traits<_IIter1> _TraitsType1;
00299       typedef typename _TraitsType1::value_type _ValueType1;
00300       typedef iterator_traits<_IIter2> _TraitsType2;
00301       typedef typename _TraitsType2::value_type _ValueType2;
00302 
00303       typedef typename
00304         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::__result
00305         _MultipliesResultType;
00306       return inner_product(__first1, __last1, __first2, __init,
00307                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
00308                            __gnu_parallel::
00309                            _Multiplies<_ValueType1, _ValueType2>());
00310     }
00311 
00312   // Sequential fallback.
00313   template<typename _IIter, typename _OutputIterator>
00314     inline _OutputIterator
00315     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
00316                 __gnu_parallel::sequential_tag)
00317     { return _GLIBCXX_STD_P::partial_sum(__begin, __end, __result); }
00318 
00319   // Sequential fallback.
00320   template<typename _IIter, typename _OutputIterator,
00321        typename _BinaryOperation>
00322     inline _OutputIterator
00323     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
00324                 _BinaryOperation __bin_op, __gnu_parallel::sequential_tag)
00325     { return _GLIBCXX_STD_P::partial_sum(__begin, __end, __result, __bin_op); }
00326 
00327   // Sequential fallback for input iterator case.
00328   template<typename _IIter, typename _OutputIterator,
00329            typename _BinaryOperation, typename _IteratorTag1,
00330            typename _IteratorTag2>
00331     inline _OutputIterator
00332     __partial_sum_switch(_IIter __begin, _IIter __end,
00333              _OutputIterator __result, _BinaryOperation __bin_op,
00334              _IteratorTag1, _IteratorTag2)
00335     { return _GLIBCXX_STD_P::partial_sum(__begin, __end, __result, __bin_op); }
00336 
00337   // Parallel algorithm for random access iterators.
00338   template<typename _IIter, typename _OutputIterator,
00339            typename _BinaryOperation>
00340     _OutputIterator
00341     __partial_sum_switch(_IIter __begin, _IIter __end,
00342              _OutputIterator __result, _BinaryOperation __bin_op,
00343              random_access_iterator_tag,
00344              random_access_iterator_tag)
00345     {
00346       if (_GLIBCXX_PARALLEL_CONDITION(
00347             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
00348             >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
00349         return __gnu_parallel::__parallel_partial_sum(__begin, __end,
00350                               __result, __bin_op);
00351       else
00352         return partial_sum(__begin, __end, __result, __bin_op,
00353                            __gnu_parallel::sequential_tag());
00354     }
00355 
00356   // Public interface.
00357   template<typename _IIter, typename _OutputIterator>
00358     inline _OutputIterator
00359     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result)
00360     {
00361       typedef typename iterator_traits<_IIter>::value_type _ValueType;
00362       return partial_sum(__begin, __end, __result, std::plus<_ValueType>());
00363     }
00364 
00365   // Public interface
00366   template<typename _IIter, typename _OutputIterator,
00367            typename _BinaryOperation>
00368     inline _OutputIterator
00369     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
00370                 _BinaryOperation __binary_op)
00371     {
00372       typedef iterator_traits<_IIter> _ITraitsType;
00373       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
00374 
00375       typedef iterator_traits<_OutputIterator> _OTraitsType;
00376       typedef typename _OTraitsType::iterator_category _OIterCategory;
00377 
00378       return __partial_sum_switch(__begin, __end, __result, __binary_op,
00379                   _IIteratorCategory(), _OIterCategory());
00380     }
00381 
00382   // Sequential fallback.
00383   template<typename _IIter, typename _OutputIterator>
00384     inline _OutputIterator
00385     adjacent_difference(_IIter __begin, _IIter __end, _OutputIterator __result,
00386                         __gnu_parallel::sequential_tag)
00387     { return _GLIBCXX_STD_P::adjacent_difference(__begin, __end, __result); }
00388 
00389   // Sequential fallback.
00390   template<typename _IIter, typename _OutputIterator,
00391            typename _BinaryOperation>
00392     inline _OutputIterator
00393     adjacent_difference(_IIter __begin, _IIter __end,
00394                         _OutputIterator __result, _BinaryOperation __bin_op,
00395                         __gnu_parallel::sequential_tag)
00396     { return _GLIBCXX_STD_P::adjacent_difference(__begin, __end,
00397                          __result, __bin_op); }
00398 
00399   // Sequential fallback for input iterator case.
00400   template<typename _IIter, typename _OutputIterator,
00401            typename _BinaryOperation, typename _IteratorTag1,
00402            typename _IteratorTag2>
00403     inline _OutputIterator
00404     __adjacent_difference_switch(_IIter __begin, _IIter __end,
00405                  _OutputIterator __result,
00406                  _BinaryOperation __bin_op, _IteratorTag1,
00407                  _IteratorTag2)
00408     { return adjacent_difference(__begin, __end, __result, __bin_op,
00409                                  __gnu_parallel::sequential_tag()); }
00410 
00411   // Parallel algorithm for random access iterators.
00412   template<typename _IIter, typename _OutputIterator,
00413            typename _BinaryOperation>
00414     _OutputIterator
00415     __adjacent_difference_switch(_IIter __begin, _IIter __end,
00416                  _OutputIterator __result,
00417                  _BinaryOperation __bin_op,
00418                  random_access_iterator_tag,
00419                  random_access_iterator_tag,
00420                  __gnu_parallel::_Parallelism
00421                  __parallelism_tag
00422                  = __gnu_parallel::parallel_balanced)
00423     {
00424       if (_GLIBCXX_PARALLEL_CONDITION(
00425             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
00426             >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
00427             && __gnu_parallel::__is_parallel(__parallelism_tag)))
00428         {
00429           bool __dummy = true;
00430           typedef __gnu_parallel::_IteratorPair<_IIter, _OutputIterator,
00431             random_access_iterator_tag> _ItTrip;
00432           *__result = *__begin;
00433           _ItTrip __begin_pair(__begin + 1, __result + 1),
00434             __end_pair(__end, __result + (__end - __begin));
00435           __gnu_parallel::__adjacent_difference_selector<_ItTrip>
00436                                                             __functionality;
00437           __gnu_parallel::
00438             __for_each_template_random_access_ed(
00439                 __begin_pair, __end_pair, __bin_op, __functionality,
00440                 __gnu_parallel::_DummyReduct(), __dummy, __dummy, -1);
00441           return __functionality._M_finish_iterator;
00442         }
00443       else
00444         return adjacent_difference(__begin, __end, __result, __bin_op, 
00445                                    __gnu_parallel::sequential_tag());
00446     }
00447 
00448   // Public interface.
00449   template<typename _IIter, typename _OutputIterator>
00450     inline _OutputIterator
00451     adjacent_difference(_IIter __begin, _IIter __end,
00452                         _OutputIterator __result,
00453                         __gnu_parallel::_Parallelism __parallelism_tag)
00454     {
00455       typedef iterator_traits<_IIter> _TraitsType;
00456       typedef typename _TraitsType::value_type _ValueType;
00457       return adjacent_difference(__begin, __end, __result,
00458                  std::minus<_ValueType>(),
00459                  __parallelism_tag);
00460     }
00461 
00462   template<typename _IIter, typename _OutputIterator>
00463     inline _OutputIterator
00464     adjacent_difference(_IIter __begin, _IIter __end,
00465                         _OutputIterator __result)
00466     {
00467       typedef iterator_traits<_IIter> _TraitsType;
00468       typedef typename _TraitsType::value_type _ValueType;
00469       return adjacent_difference(__begin, __end, __result,
00470                  std::minus<_ValueType>());
00471     }
00472 
00473   template<typename _IIter, typename _OutputIterator,
00474            typename _BinaryOperation>
00475     inline _OutputIterator
00476     adjacent_difference(_IIter __begin, _IIter __end,
00477                         _OutputIterator __result, _BinaryOperation __binary_op,
00478                         __gnu_parallel::_Parallelism __parallelism_tag)
00479     {
00480       typedef iterator_traits<_IIter> _ITraitsType;
00481       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
00482 
00483       typedef iterator_traits<_OutputIterator> _OTraitsType;
00484       typedef typename _OTraitsType::iterator_category _OIterCategory;
00485 
00486       return __adjacent_difference_switch(__begin, __end, __result,
00487                       __binary_op,
00488                       _IIteratorCategory(),
00489                       _OIterCategory(),
00490                       __parallelism_tag);
00491     }
00492 
00493   template<typename _IIter, typename _OutputIterator,
00494        typename _BinaryOperation>
00495     inline _OutputIterator
00496     adjacent_difference(_IIter __begin, _IIter __end,
00497             _OutputIterator __result, _BinaryOperation __binary_op)
00498     {
00499       typedef iterator_traits<_IIter> _ITraitsType;
00500       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
00501 
00502       typedef iterator_traits<_OutputIterator> _OTraitsType;
00503       typedef typename _OTraitsType::iterator_category _OIterCategory;
00504 
00505       return __adjacent_difference_switch(__begin, __end, __result,
00506                       __binary_op,
00507                       _IIteratorCategory(),
00508                       _OIterCategory());
00509     }
00510 } // end namespace
00511 } // end namespace
00512 
00513 #endif /* _GLIBCXX_NUMERIC_H */

Generated on 12 Mar 2010 for libstdc++ by  doxygen 1.6.1