3 // Copyright (C) 2007-2014 Free Software Foundation, Inc.
 
    5 // This file is part of the GNU ISO C++ Library.  This library is free
 
    6 // software; you can redistribute it and/or modify it under the terms
 
    7 // of the GNU General Public License as published by the Free Software
 
    8 // Foundation; either version 3, or (at your option) any later
 
   11 // This library is distributed in the hope that it will be useful, but
 
   12 // WITHOUT ANY WARRANTY; without even the implied warranty of
 
   13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
   14 // General Public License for more details.
 
   16 // Under Section 7 of GPL version 3, you are granted additional
 
   17 // permissions described in the GCC Runtime Library Exception, version
 
   18 // 3.1, as published by the Free Software Foundation.
 
   20 // You should have received a copy of the GNU General Public License and
 
   21 // a copy of the GCC Runtime Library Exception along with this program;
 
   22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   23 // <http://www.gnu.org/licenses/>.
 
   26  * @file parallel/numeric
 
   28  * @brief Parallel STL function calls corresponding to stl_numeric.h.
 
   29  * The functions defined here mainly do case switches and
 
   30  * call the actual parallelized versions in other files.
 
   31  * Inlining policy: Functions that basically only contain one function call,
 
   32  * are declared inline.
 
   33  *  This file is a GNU parallel extension to the Standard C++ Library.
 
   36 // Written by Johannes Singler and Felix Putze.
 
   38 #ifndef _GLIBCXX_PARALLEL_NUMERIC_H
 
   39 #define _GLIBCXX_PARALLEL_NUMERIC_H 1
 
   42 #include <bits/stl_function.h>
 
   43 #include <parallel/numericfwd.h>
 
   44 #include <parallel/iterator.h>
 
   45 #include <parallel/for_each.h>
 
   46 #include <parallel/for_each_selectors.h>
 
   47 #include <parallel/partial_sum.h>
 
   49 namespace std _GLIBCXX_VISIBILITY(default)
 
   53   // Sequential fallback.
 
   54   template<typename _IIter, typename _Tp>
 
   56     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
 
   57                __gnu_parallel::sequential_tag)
 
   58     { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init); }
 
   60   template<typename _IIter, typename _Tp, typename _BinaryOperation>
 
   62     accumulate(_IIter __begin, _IIter __end, _Tp __init,
 
   63                _BinaryOperation __binary_op, __gnu_parallel::sequential_tag)
 
   64     { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init, __binary_op); }
 
   66   // Sequential fallback for input iterator case.
 
   67   template<typename _IIter, typename _Tp, typename _IteratorTag>
 
   69     __accumulate_switch(_IIter __begin, _IIter __end,
 
   70                       _Tp __init, _IteratorTag) 
 
   71     { return accumulate(__begin, __end, __init,
 
   72            __gnu_parallel::sequential_tag()); }
 
   74   template<typename _IIter, typename _Tp, typename _BinaryOperation,
 
   75            typename _IteratorTag>
 
   77     __accumulate_switch(_IIter __begin, _IIter __end, _Tp __init, 
 
   78                       _BinaryOperation __binary_op, _IteratorTag)
 
   79     { return accumulate(__begin, __end, __init, __binary_op, 
 
   80                         __gnu_parallel::sequential_tag()); }
 
   82   // Parallel algorithm for random access iterators.
 
   83   template<typename __RAIter, typename _Tp, typename _BinaryOperation>
 
   85     __accumulate_switch(__RAIter __begin, __RAIter __end, 
 
   86                       _Tp __init, _BinaryOperation __binary_op, 
 
   87                       random_access_iterator_tag, 
 
   88                       __gnu_parallel::_Parallelism __parallelism_tag)
 
   90       if (_GLIBCXX_PARALLEL_CONDITION(
 
   91             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
 
   92             >= __gnu_parallel::_Settings::get().accumulate_minimal_n
 
   93             && __gnu_parallel::__is_parallel(__parallelism_tag)))
 
   96           __gnu_parallel::__accumulate_selector<__RAIter>
 
   99             __for_each_template_random_access_ed(__begin, __end,
 
  100                         __gnu_parallel::_Nothing(),
 
  103                         __accumulate_binop_reduct
 
  104                           <_BinaryOperation>(__binary_op),
 
  109         return accumulate(__begin, __end, __init, __binary_op, 
 
  110                           __gnu_parallel::sequential_tag());
 
  114   template<typename _IIter, typename _Tp>
 
  116     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
 
  117                __gnu_parallel::_Parallelism __parallelism_tag)
 
  119       typedef std::iterator_traits<_IIter> _IteratorTraits;
 
  120       typedef typename _IteratorTraits::value_type _ValueType;
 
  121       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
 
  123       return __accumulate_switch(__begin, __end, __init,
 
  124                 __gnu_parallel::_Plus<_Tp, _ValueType>(),
 
  125                 _IteratorCategory(), __parallelism_tag);
 
  128   template<typename _IIter, typename _Tp>
 
  130     accumulate(_IIter __begin, _IIter __end, _Tp __init)
 
  132       typedef std::iterator_traits<_IIter> _IteratorTraits;
 
  133       typedef typename _IteratorTraits::value_type _ValueType;
 
  134       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
 
  136       return __accumulate_switch(__begin, __end, __init,
 
  137                 __gnu_parallel::_Plus<_Tp, _ValueType>(),
 
  138                 _IteratorCategory());
 
  141   template<typename _IIter, typename _Tp, typename _BinaryOperation>
 
  143     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
 
  144                _BinaryOperation __binary_op, 
 
  145                __gnu_parallel::_Parallelism __parallelism_tag)
 
  147       typedef iterator_traits<_IIter> _IteratorTraits;
 
  148       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
 
  149       return __accumulate_switch(__begin, __end, __init, __binary_op, 
 
  150                 _IteratorCategory(), __parallelism_tag);
 
  153   template<typename _IIter, typename _Tp, typename _BinaryOperation>
 
  155     accumulate(_IIter __begin, _IIter __end, _Tp __init, 
 
  156                _BinaryOperation __binary_op) 
 
  158       typedef iterator_traits<_IIter> _IteratorTraits;
 
  159       typedef typename _IteratorTraits::iterator_category _IteratorCategory;
 
  160       return __accumulate_switch(__begin, __end, __init, __binary_op, 
 
  161                 _IteratorCategory());
 
  165   // Sequential fallback.
 
  166   template<typename _IIter1, typename _IIter2, typename _Tp>
 
  168     inner_product(_IIter1 __first1, _IIter1 __last1, 
 
  169                   _IIter2 __first2, _Tp __init,
 
  170                   __gnu_parallel::sequential_tag)
 
  171     { return _GLIBCXX_STD_A::inner_product(
 
  172                                __first1, __last1, __first2, __init); }
 
  174   template<typename _IIter1, typename _IIter2, typename _Tp,
 
  175            typename _BinaryFunction1, typename _BinaryFunction2>
 
  177     inner_product(_IIter1 __first1, _IIter1 __last1,
 
  178                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1, 
 
  179                   _BinaryFunction2 __binary_op2,
 
  180                   __gnu_parallel::sequential_tag)
 
  181     { return _GLIBCXX_STD_A::inner_product(__first1, __last1, __first2, __init,
 
  182                                            __binary_op1, __binary_op2); }
 
  184   // Parallel algorithm for random access iterators.
 
  185   template<typename _RAIter1, typename _RAIter2,
 
  186            typename _Tp, typename _BinaryFunction1, typename _BinaryFunction2>
 
  188     __inner_product_switch(_RAIter1 __first1,
 
  190               _RAIter2 __first2, _Tp __init,
 
  191               _BinaryFunction1 __binary_op1,
 
  192               _BinaryFunction2 __binary_op2,
 
  193               random_access_iterator_tag,
 
  194               random_access_iterator_tag,
 
  195               __gnu_parallel::_Parallelism __parallelism_tag)
 
  197       if (_GLIBCXX_PARALLEL_CONDITION((__last1 - __first1)
 
  198                                       >= __gnu_parallel::_Settings::get().
 
  201                                       __is_parallel(__parallelism_tag)))
 
  205             __inner_product_selector<_RAIter1,
 
  206             _RAIter2, _Tp> __my_selector(__first1, __first2);
 
  208             __for_each_template_random_access_ed(
 
  209                 __first1, __last1, __binary_op2, __my_selector, __binary_op1,
 
  214         return inner_product(__first1, __last1, __first2, __init, 
 
  215                              __gnu_parallel::sequential_tag());
 
  218   // No parallelism for input iterators.
 
  219   template<typename _IIter1, typename _IIter2, typename _Tp,
 
  220            typename _BinaryFunction1, typename _BinaryFunction2,
 
  221            typename _IteratorTag1, typename _IteratorTag2>
 
  223     __inner_product_switch(_IIter1 __first1, _IIter1 __last1, 
 
  224               _IIter2 __first2, _Tp __init, 
 
  225               _BinaryFunction1 __binary_op1,
 
  226               _BinaryFunction2 __binary_op2, 
 
  227               _IteratorTag1, _IteratorTag2)
 
  228     { return inner_product(__first1, __last1, __first2, __init, __binary_op1,
 
  229               __binary_op2, __gnu_parallel::sequential_tag()); }
 
  231   template<typename _IIter1, typename _IIter2, typename _Tp,
 
  232            typename _BinaryFunction1, typename _BinaryFunction2>
 
  234     inner_product(_IIter1 __first1, _IIter1 __last1, 
 
  235                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1, 
 
  236                   _BinaryFunction2 __binary_op2, 
 
  237                   __gnu_parallel::_Parallelism __parallelism_tag)
 
  239       typedef iterator_traits<_IIter1> _TraitsType1;
 
  240       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
 
  242       typedef iterator_traits<_IIter2> _TraitsType2;
 
  243       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
 
  245       return __inner_product_switch(__first1, __last1, __first2, __init,
 
  246                    __binary_op1, __binary_op2,
 
  247                    _IteratorCategory1(), _IteratorCategory2(),
 
  251   template<typename _IIter1, typename _IIter2, typename _Tp,
 
  252            typename _BinaryFunction1, typename _BinaryFunction2>
 
  254     inner_product(_IIter1 __first1, _IIter1 __last1, 
 
  255                   _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1, 
 
  256                   _BinaryFunction2 __binary_op2)
 
  258       typedef iterator_traits<_IIter1> _TraitsType1;
 
  259       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
 
  261       typedef iterator_traits<_IIter2> _TraitsType2;
 
  262       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
 
  264       return __inner_product_switch(__first1, __last1, __first2, __init,
 
  265                    __binary_op1, __binary_op2,
 
  266                    _IteratorCategory1(),
 
  267                    _IteratorCategory2());
 
  270   template<typename _IIter1, typename _IIter2, typename _Tp>
 
  272     inner_product(_IIter1 __first1, _IIter1 __last1, 
 
  273                   _IIter2 __first2, _Tp __init, 
 
  274                   __gnu_parallel::_Parallelism __parallelism_tag)
 
  276       typedef iterator_traits<_IIter1> _TraitsType1;
 
  277       typedef typename _TraitsType1::value_type _ValueType1;
 
  278       typedef iterator_traits<_IIter2> _TraitsType2;
 
  279       typedef typename _TraitsType2::value_type _ValueType2;
 
  282         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
 
  283         _MultipliesResultType;
 
  284       return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
 
  285                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
 
  287                            _Multiplies<_ValueType1, _ValueType2>(),
 
  291   template<typename _IIter1, typename _IIter2, typename _Tp>
 
  293     inner_product(_IIter1 __first1, _IIter1 __last1, 
 
  294                   _IIter2 __first2, _Tp __init)
 
  296       typedef iterator_traits<_IIter1> _TraitsType1;
 
  297       typedef typename _TraitsType1::value_type _ValueType1;
 
  298       typedef iterator_traits<_IIter2> _TraitsType2;
 
  299       typedef typename _TraitsType2::value_type _ValueType2;
 
  302         __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
 
  303         _MultipliesResultType;
 
  304       return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
 
  305                            __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
 
  307                            _Multiplies<_ValueType1, _ValueType2>());
 
  310   // Sequential fallback.
 
  311   template<typename _IIter, typename _OutputIterator>
 
  312     inline _OutputIterator
 
  313     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
 
  314                 __gnu_parallel::sequential_tag)
 
  315     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result); }
 
  317   // Sequential fallback.
 
  318   template<typename _IIter, typename _OutputIterator,
 
  319       typename _BinaryOperation>
 
  320     inline _OutputIterator
 
  321     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
 
  322                 _BinaryOperation __bin_op, __gnu_parallel::sequential_tag)
 
  323     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
 
  325   // Sequential fallback for input iterator case.
 
  326   template<typename _IIter, typename _OutputIterator,
 
  327            typename _BinaryOperation, typename _IteratorTag1,
 
  328            typename _IteratorTag2>
 
  329     inline _OutputIterator
 
  330     __partial_sum_switch(_IIter __begin, _IIter __end,
 
  331             _OutputIterator __result, _BinaryOperation __bin_op,
 
  332             _IteratorTag1, _IteratorTag2)
 
  333     { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
 
  335   // Parallel algorithm for random access iterators.
 
  336   template<typename _IIter, typename _OutputIterator,
 
  337            typename _BinaryOperation>
 
  339     __partial_sum_switch(_IIter __begin, _IIter __end,
 
  340             _OutputIterator __result, _BinaryOperation __bin_op,
 
  341             random_access_iterator_tag,
 
  342             random_access_iterator_tag)
 
  344       if (_GLIBCXX_PARALLEL_CONDITION(
 
  345             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
 
  346             >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
 
  347         return __gnu_parallel::__parallel_partial_sum(__begin, __end,
 
  350         return partial_sum(__begin, __end, __result, __bin_op,
 
  351                            __gnu_parallel::sequential_tag());
 
  355   template<typename _IIter, typename _OutputIterator>
 
  356     inline _OutputIterator
 
  357     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result)
 
  359       typedef typename iterator_traits<_IIter>::value_type _ValueType;
 
  360       return __gnu_parallel::partial_sum(__begin, __end,
 
  361                                          __result, std::plus<_ValueType>());
 
  365   template<typename _IIter, typename _OutputIterator,
 
  366            typename _BinaryOperation>
 
  367     inline _OutputIterator
 
  368     partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
 
  369                 _BinaryOperation __binary_op)
 
  371       typedef iterator_traits<_IIter> _ITraitsType;
 
  372       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
 
  374       typedef iterator_traits<_OutputIterator> _OTraitsType;
 
  375       typedef typename _OTraitsType::iterator_category _OIterCategory;
 
  377       return __partial_sum_switch(__begin, __end, __result, __binary_op,
 
  378                  _IIteratorCategory(), _OIterCategory());
 
  381   // Sequential fallback.
 
  382   template<typename _IIter, typename _OutputIterator>
 
  383     inline _OutputIterator
 
  384     adjacent_difference(_IIter __begin, _IIter __end, _OutputIterator __result,
 
  385                         __gnu_parallel::sequential_tag)
 
  386     { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end, __result); }
 
  388   // Sequential fallback.
 
  389   template<typename _IIter, typename _OutputIterator,
 
  390            typename _BinaryOperation>
 
  391     inline _OutputIterator
 
  392     adjacent_difference(_IIter __begin, _IIter __end,
 
  393                         _OutputIterator __result, _BinaryOperation __bin_op,
 
  394                         __gnu_parallel::sequential_tag)
 
  395     { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end,
 
  396                         __result, __bin_op); }
 
  398   // Sequential fallback for input iterator case.
 
  399   template<typename _IIter, typename _OutputIterator,
 
  400            typename _BinaryOperation, typename _IteratorTag1,
 
  401            typename _IteratorTag2>
 
  402     inline _OutputIterator
 
  403     __adjacent_difference_switch(_IIter __begin, _IIter __end,
 
  404                 _OutputIterator __result,
 
  405                 _BinaryOperation __bin_op, _IteratorTag1,
 
  407     { return adjacent_difference(__begin, __end, __result, __bin_op,
 
  408                                  __gnu_parallel::sequential_tag()); }
 
  410   // Parallel algorithm for random access iterators.
 
  411   template<typename _IIter, typename _OutputIterator,
 
  412            typename _BinaryOperation>
 
  414     __adjacent_difference_switch(_IIter __begin, _IIter __end,
 
  415                 _OutputIterator __result,
 
  416                 _BinaryOperation __bin_op,
 
  417                 random_access_iterator_tag,
 
  418                 random_access_iterator_tag,
 
  419                 __gnu_parallel::_Parallelism
 
  422       if (_GLIBCXX_PARALLEL_CONDITION(
 
  423             static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
 
  424             >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
 
  425             && __gnu_parallel::__is_parallel(__parallelism_tag)))
 
  428           typedef __gnu_parallel::_IteratorPair<_IIter, _OutputIterator,
 
  429             random_access_iterator_tag> _ItTrip;
 
  430           *__result = *__begin;
 
  431           _ItTrip __begin_pair(__begin + 1, __result + 1),
 
  432             __end_pair(__end, __result + (__end - __begin));
 
  433           __gnu_parallel::__adjacent_difference_selector<_ItTrip>
 
  436             __for_each_template_random_access_ed(
 
  437                 __begin_pair, __end_pair, __bin_op, __functionality,
 
  438                 __gnu_parallel::_DummyReduct(), __dummy, __dummy, -1);
 
  439           return __functionality._M_finish_iterator;
 
  442         return adjacent_difference(__begin, __end, __result, __bin_op, 
 
  443                                    __gnu_parallel::sequential_tag());
 
  447   template<typename _IIter, typename _OutputIterator>
 
  448     inline _OutputIterator
 
  449     adjacent_difference(_IIter __begin, _IIter __end,
 
  450                         _OutputIterator __result,
 
  451                         __gnu_parallel::_Parallelism __parallelism_tag)
 
  453       typedef iterator_traits<_IIter> _TraitsType;
 
  454       typedef typename _TraitsType::value_type _ValueType;
 
  455       return adjacent_difference(__begin, __end, __result,
 
  456                 std::minus<_ValueType>(),
 
  460   template<typename _IIter, typename _OutputIterator>
 
  461     inline _OutputIterator
 
  462     adjacent_difference(_IIter __begin, _IIter __end,
 
  463                         _OutputIterator __result)
 
  465       typedef iterator_traits<_IIter> _TraitsType;
 
  466       typedef typename _TraitsType::value_type _ValueType;
 
  467       return adjacent_difference(__begin, __end, __result,
 
  468                 std::minus<_ValueType>());
 
  471   template<typename _IIter, typename _OutputIterator,
 
  472            typename _BinaryOperation>
 
  473     inline _OutputIterator
 
  474     adjacent_difference(_IIter __begin, _IIter __end,
 
  475                         _OutputIterator __result, _BinaryOperation __binary_op,
 
  476                         __gnu_parallel::_Parallelism __parallelism_tag)
 
  478       typedef iterator_traits<_IIter> _ITraitsType;
 
  479       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
 
  481       typedef iterator_traits<_OutputIterator> _OTraitsType;
 
  482       typedef typename _OTraitsType::iterator_category _OIterCategory;
 
  484       return __adjacent_difference_switch(__begin, __end, __result,
 
  486                      _IIteratorCategory(),
 
  491   template<typename _IIter, typename _OutputIterator,
 
  492       typename _BinaryOperation>
 
  493     inline _OutputIterator
 
  494     adjacent_difference(_IIter __begin, _IIter __end,
 
  495            _OutputIterator __result, _BinaryOperation __binary_op)
 
  497       typedef iterator_traits<_IIter> _ITraitsType;
 
  498       typedef typename _ITraitsType::iterator_category _IIteratorCategory;
 
  500       typedef iterator_traits<_OutputIterator> _OTraitsType;
 
  501       typedef typename _OTraitsType::iterator_category _OIterCategory;
 
  503       return __adjacent_difference_switch(__begin, __end, __result,
 
  505                      _IIteratorCategory(),
 
  511 #endif /* _GLIBCXX_NUMERIC_H */