xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/parallel/numeric (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj// -*- C++ -*-
2*38fd1498Szrj
3*38fd1498Szrj// Copyright (C) 2007-2018 Free Software Foundation, Inc.
4*38fd1498Szrj//
5*38fd1498Szrj// This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj// software; you can redistribute it and/or modify it under the terms
7*38fd1498Szrj// of the GNU General Public License as published by the Free Software
8*38fd1498Szrj// Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj// version.
10*38fd1498Szrj
11*38fd1498Szrj// This library is distributed in the hope that it will be useful, but
12*38fd1498Szrj// WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*38fd1498Szrj// General Public License for more details.
15*38fd1498Szrj
16*38fd1498Szrj// Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj// permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj// 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj
20*38fd1498Szrj// You should have received a copy of the GNU General Public License and
21*38fd1498Szrj// a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*38fd1498Szrj// <http://www.gnu.org/licenses/>.
24*38fd1498Szrj
25*38fd1498Szrj/**
26*38fd1498Szrj * @file parallel/numeric
27*38fd1498Szrj*
28*38fd1498Szrj * @brief Parallel STL function calls corresponding to stl_numeric.h.
29*38fd1498Szrj * The functions defined here mainly do case switches and
30*38fd1498Szrj * call the actual parallelized versions in other files.
31*38fd1498Szrj * Inlining policy: Functions that basically only contain one function call,
32*38fd1498Szrj * are declared inline.
33*38fd1498Szrj *  This file is a GNU parallel extension to the Standard C++ Library.
34*38fd1498Szrj */
35*38fd1498Szrj
36*38fd1498Szrj// Written by Johannes Singler and Felix Putze.
37*38fd1498Szrj
38*38fd1498Szrj#ifndef _GLIBCXX_PARALLEL_NUMERIC_H
39*38fd1498Szrj#define _GLIBCXX_PARALLEL_NUMERIC_H 1
40*38fd1498Szrj
41*38fd1498Szrj#include <numeric>
42*38fd1498Szrj#include <bits/stl_function.h>
43*38fd1498Szrj#include <parallel/numericfwd.h>
44*38fd1498Szrj#include <parallel/iterator.h>
45*38fd1498Szrj#include <parallel/for_each.h>
46*38fd1498Szrj#include <parallel/for_each_selectors.h>
47*38fd1498Szrj#include <parallel/partial_sum.h>
48*38fd1498Szrj
49*38fd1498Szrjnamespace std _GLIBCXX_VISIBILITY(default)
50*38fd1498Szrj{
51*38fd1498Szrjnamespace __parallel
52*38fd1498Szrj{
53*38fd1498Szrj  // Sequential fallback.
54*38fd1498Szrj  template<typename _IIter, typename _Tp>
55*38fd1498Szrj    inline _Tp
56*38fd1498Szrj    accumulate(_IIter __begin, _IIter __end, _Tp __init,
57*38fd1498Szrj               __gnu_parallel::sequential_tag)
58*38fd1498Szrj    { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init); }
59*38fd1498Szrj
60*38fd1498Szrj  template<typename _IIter, typename _Tp, typename _BinaryOperation>
61*38fd1498Szrj    inline _Tp
62*38fd1498Szrj    accumulate(_IIter __begin, _IIter __end, _Tp __init,
63*38fd1498Szrj               _BinaryOperation __binary_op, __gnu_parallel::sequential_tag)
64*38fd1498Szrj    { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init, __binary_op); }
65*38fd1498Szrj
66*38fd1498Szrj  // Sequential fallback for input iterator case.
67*38fd1498Szrj  template<typename _IIter, typename _Tp, typename _IteratorTag>
68*38fd1498Szrj    inline _Tp
69*38fd1498Szrj    __accumulate_switch(_IIter __begin, _IIter __end,
70*38fd1498Szrj                      _Tp __init, _IteratorTag)
71*38fd1498Szrj    { return accumulate(__begin, __end, __init,
72*38fd1498Szrj			__gnu_parallel::sequential_tag()); }
73*38fd1498Szrj
74*38fd1498Szrj  template<typename _IIter, typename _Tp, typename _BinaryOperation,
75*38fd1498Szrj           typename _IteratorTag>
76*38fd1498Szrj    inline _Tp
77*38fd1498Szrj    __accumulate_switch(_IIter __begin, _IIter __end, _Tp __init,
78*38fd1498Szrj                      _BinaryOperation __binary_op, _IteratorTag)
79*38fd1498Szrj    { return accumulate(__begin, __end, __init, __binary_op,
80*38fd1498Szrj                        __gnu_parallel::sequential_tag()); }
81*38fd1498Szrj
82*38fd1498Szrj  // Parallel algorithm for random access iterators.
83*38fd1498Szrj  template<typename __RAIter, typename _Tp, typename _BinaryOperation>
84*38fd1498Szrj    _Tp
85*38fd1498Szrj    __accumulate_switch(__RAIter __begin, __RAIter __end,
86*38fd1498Szrj                      _Tp __init, _BinaryOperation __binary_op,
87*38fd1498Szrj                      random_access_iterator_tag,
88*38fd1498Szrj                      __gnu_parallel::_Parallelism __parallelism_tag)
89*38fd1498Szrj    {
90*38fd1498Szrj      if (_GLIBCXX_PARALLEL_CONDITION(
91*38fd1498Szrj            static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
92*38fd1498Szrj            >= __gnu_parallel::_Settings::get().accumulate_minimal_n
93*38fd1498Szrj            && __gnu_parallel::__is_parallel(__parallelism_tag)))
94*38fd1498Szrj        {
95*38fd1498Szrj          _Tp __res = __init;
96*38fd1498Szrj          __gnu_parallel::__accumulate_selector<__RAIter>
97*38fd1498Szrj            __my_selector;
98*38fd1498Szrj          __gnu_parallel::
99*38fd1498Szrj            __for_each_template_random_access_ed(__begin, __end,
100*38fd1498Szrj						 __gnu_parallel::_Nothing(),
101*38fd1498Szrj						 __my_selector,
102*38fd1498Szrj						 __gnu_parallel::
103*38fd1498Szrj						 __accumulate_binop_reduct
104*38fd1498Szrj					       <_BinaryOperation>(__binary_op),
105*38fd1498Szrj						 __res, __res, -1);
106*38fd1498Szrj          return __res;
107*38fd1498Szrj        }
108*38fd1498Szrj      else
109*38fd1498Szrj        return accumulate(__begin, __end, __init, __binary_op,
110*38fd1498Szrj                          __gnu_parallel::sequential_tag());
111*38fd1498Szrj    }
112*38fd1498Szrj
113*38fd1498Szrj  // Public interface.
114*38fd1498Szrj  template<typename _IIter, typename _Tp>
115*38fd1498Szrj    inline _Tp
116*38fd1498Szrj    accumulate(_IIter __begin, _IIter __end, _Tp __init,
117*38fd1498Szrj               __gnu_parallel::_Parallelism __parallelism_tag)
118*38fd1498Szrj    {
119*38fd1498Szrj      typedef std::iterator_traits<_IIter> _IteratorTraits;
120*38fd1498Szrj      typedef typename _IteratorTraits::value_type _ValueType;
121*38fd1498Szrj      typedef typename _IteratorTraits::iterator_category _IteratorCategory;
122*38fd1498Szrj
123*38fd1498Szrj      return __accumulate_switch(__begin, __end, __init,
124*38fd1498Szrj				 __gnu_parallel::_Plus<_Tp, _ValueType>(),
125*38fd1498Szrj				 _IteratorCategory(), __parallelism_tag);
126*38fd1498Szrj    }
127*38fd1498Szrj
128*38fd1498Szrj  template<typename _IIter, typename _Tp>
129*38fd1498Szrj    inline _Tp
130*38fd1498Szrj    accumulate(_IIter __begin, _IIter __end, _Tp __init)
131*38fd1498Szrj    {
132*38fd1498Szrj      typedef std::iterator_traits<_IIter> _IteratorTraits;
133*38fd1498Szrj      typedef typename _IteratorTraits::value_type _ValueType;
134*38fd1498Szrj      typedef typename _IteratorTraits::iterator_category _IteratorCategory;
135*38fd1498Szrj
136*38fd1498Szrj      return __accumulate_switch(__begin, __end, __init,
137*38fd1498Szrj				 __gnu_parallel::_Plus<_Tp, _ValueType>(),
138*38fd1498Szrj				 _IteratorCategory());
139*38fd1498Szrj    }
140*38fd1498Szrj
141*38fd1498Szrj  template<typename _IIter, typename _Tp, typename _BinaryOperation>
142*38fd1498Szrj    inline _Tp
143*38fd1498Szrj    accumulate(_IIter __begin, _IIter __end, _Tp __init,
144*38fd1498Szrj               _BinaryOperation __binary_op,
145*38fd1498Szrj               __gnu_parallel::_Parallelism __parallelism_tag)
146*38fd1498Szrj    {
147*38fd1498Szrj      typedef iterator_traits<_IIter> _IteratorTraits;
148*38fd1498Szrj      typedef typename _IteratorTraits::iterator_category _IteratorCategory;
149*38fd1498Szrj      return __accumulate_switch(__begin, __end, __init, __binary_op,
150*38fd1498Szrj				 _IteratorCategory(), __parallelism_tag);
151*38fd1498Szrj    }
152*38fd1498Szrj
153*38fd1498Szrj  template<typename _IIter, typename _Tp, typename _BinaryOperation>
154*38fd1498Szrj    inline _Tp
155*38fd1498Szrj    accumulate(_IIter __begin, _IIter __end, _Tp __init,
156*38fd1498Szrj               _BinaryOperation __binary_op)
157*38fd1498Szrj    {
158*38fd1498Szrj      typedef iterator_traits<_IIter> _IteratorTraits;
159*38fd1498Szrj      typedef typename _IteratorTraits::iterator_category _IteratorCategory;
160*38fd1498Szrj      return __accumulate_switch(__begin, __end, __init, __binary_op,
161*38fd1498Szrj				 _IteratorCategory());
162*38fd1498Szrj    }
163*38fd1498Szrj
164*38fd1498Szrj
165*38fd1498Szrj  // Sequential fallback.
166*38fd1498Szrj  template<typename _IIter1, typename _IIter2, typename _Tp>
167*38fd1498Szrj    inline _Tp
168*38fd1498Szrj    inner_product(_IIter1 __first1, _IIter1 __last1,
169*38fd1498Szrj                  _IIter2 __first2, _Tp __init,
170*38fd1498Szrj                  __gnu_parallel::sequential_tag)
171*38fd1498Szrj    { return _GLIBCXX_STD_A::inner_product(
172*38fd1498Szrj                               __first1, __last1, __first2, __init); }
173*38fd1498Szrj
174*38fd1498Szrj  template<typename _IIter1, typename _IIter2, typename _Tp,
175*38fd1498Szrj           typename _BinaryFunction1, typename _BinaryFunction2>
176*38fd1498Szrj    inline _Tp
177*38fd1498Szrj    inner_product(_IIter1 __first1, _IIter1 __last1,
178*38fd1498Szrj                  _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
179*38fd1498Szrj                  _BinaryFunction2 __binary_op2,
180*38fd1498Szrj                  __gnu_parallel::sequential_tag)
181*38fd1498Szrj    { return _GLIBCXX_STD_A::inner_product(__first1, __last1, __first2, __init,
182*38fd1498Szrj                                           __binary_op1, __binary_op2); }
183*38fd1498Szrj
184*38fd1498Szrj  // Parallel algorithm for random access iterators.
185*38fd1498Szrj  template<typename _RAIter1, typename _RAIter2,
186*38fd1498Szrj           typename _Tp, typename _BinaryFunction1, typename _BinaryFunction2>
187*38fd1498Szrj    _Tp
188*38fd1498Szrj    __inner_product_switch(_RAIter1 __first1,
189*38fd1498Szrj			   _RAIter1 __last1,
190*38fd1498Szrj			   _RAIter2 __first2, _Tp __init,
191*38fd1498Szrj			   _BinaryFunction1 __binary_op1,
192*38fd1498Szrj			   _BinaryFunction2 __binary_op2,
193*38fd1498Szrj			   random_access_iterator_tag,
194*38fd1498Szrj			   random_access_iterator_tag,
195*38fd1498Szrj			   __gnu_parallel::_Parallelism __parallelism_tag)
196*38fd1498Szrj    {
197*38fd1498Szrj      if (_GLIBCXX_PARALLEL_CONDITION((__last1 - __first1)
198*38fd1498Szrj                                      >= __gnu_parallel::_Settings::get().
199*38fd1498Szrj                                      accumulate_minimal_n
200*38fd1498Szrj                                      && __gnu_parallel::
201*38fd1498Szrj                                      __is_parallel(__parallelism_tag)))
202*38fd1498Szrj        {
203*38fd1498Szrj          _Tp __res = __init;
204*38fd1498Szrj          __gnu_parallel::
205*38fd1498Szrj            __inner_product_selector<_RAIter1,
206*38fd1498Szrj            _RAIter2, _Tp> __my_selector(__first1, __first2);
207*38fd1498Szrj          __gnu_parallel::
208*38fd1498Szrj            __for_each_template_random_access_ed(
209*38fd1498Szrj                __first1, __last1, __binary_op2, __my_selector, __binary_op1,
210*38fd1498Szrj                __res, __res, -1);
211*38fd1498Szrj          return __res;
212*38fd1498Szrj        }
213*38fd1498Szrj      else
214*38fd1498Szrj        return inner_product(__first1, __last1, __first2, __init,
215*38fd1498Szrj                             __gnu_parallel::sequential_tag());
216*38fd1498Szrj    }
217*38fd1498Szrj
218*38fd1498Szrj  // No parallelism for input iterators.
219*38fd1498Szrj  template<typename _IIter1, typename _IIter2, typename _Tp,
220*38fd1498Szrj           typename _BinaryFunction1, typename _BinaryFunction2,
221*38fd1498Szrj           typename _IteratorTag1, typename _IteratorTag2>
222*38fd1498Szrj    inline _Tp
223*38fd1498Szrj    __inner_product_switch(_IIter1 __first1, _IIter1 __last1,
224*38fd1498Szrj			   _IIter2 __first2, _Tp __init,
225*38fd1498Szrj			   _BinaryFunction1 __binary_op1,
226*38fd1498Szrj			   _BinaryFunction2 __binary_op2,
227*38fd1498Szrj			   _IteratorTag1, _IteratorTag2)
228*38fd1498Szrj    { return inner_product(__first1, __last1, __first2, __init, __binary_op1,
229*38fd1498Szrj			   __binary_op2, __gnu_parallel::sequential_tag()); }
230*38fd1498Szrj
231*38fd1498Szrj  template<typename _IIter1, typename _IIter2, typename _Tp,
232*38fd1498Szrj           typename _BinaryFunction1, typename _BinaryFunction2>
233*38fd1498Szrj    inline _Tp
234*38fd1498Szrj    inner_product(_IIter1 __first1, _IIter1 __last1,
235*38fd1498Szrj                  _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
236*38fd1498Szrj                  _BinaryFunction2 __binary_op2,
237*38fd1498Szrj                  __gnu_parallel::_Parallelism __parallelism_tag)
238*38fd1498Szrj    {
239*38fd1498Szrj      typedef iterator_traits<_IIter1> _TraitsType1;
240*38fd1498Szrj      typedef typename _TraitsType1::iterator_category _IteratorCategory1;
241*38fd1498Szrj
242*38fd1498Szrj      typedef iterator_traits<_IIter2> _TraitsType2;
243*38fd1498Szrj      typedef typename _TraitsType2::iterator_category _IteratorCategory2;
244*38fd1498Szrj
245*38fd1498Szrj      return __inner_product_switch(__first1, __last1, __first2, __init,
246*38fd1498Szrj				    __binary_op1, __binary_op2,
247*38fd1498Szrj				    _IteratorCategory1(), _IteratorCategory2(),
248*38fd1498Szrj				    __parallelism_tag);
249*38fd1498Szrj    }
250*38fd1498Szrj
251*38fd1498Szrj  template<typename _IIter1, typename _IIter2, typename _Tp,
252*38fd1498Szrj           typename _BinaryFunction1, typename _BinaryFunction2>
253*38fd1498Szrj    inline _Tp
254*38fd1498Szrj    inner_product(_IIter1 __first1, _IIter1 __last1,
255*38fd1498Szrj                  _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
256*38fd1498Szrj                  _BinaryFunction2 __binary_op2)
257*38fd1498Szrj    {
258*38fd1498Szrj      typedef iterator_traits<_IIter1> _TraitsType1;
259*38fd1498Szrj      typedef typename _TraitsType1::iterator_category _IteratorCategory1;
260*38fd1498Szrj
261*38fd1498Szrj      typedef iterator_traits<_IIter2> _TraitsType2;
262*38fd1498Szrj      typedef typename _TraitsType2::iterator_category _IteratorCategory2;
263*38fd1498Szrj
264*38fd1498Szrj      return __inner_product_switch(__first1, __last1, __first2, __init,
265*38fd1498Szrj				    __binary_op1, __binary_op2,
266*38fd1498Szrj				    _IteratorCategory1(),
267*38fd1498Szrj				    _IteratorCategory2());
268*38fd1498Szrj    }
269*38fd1498Szrj
270*38fd1498Szrj  template<typename _IIter1, typename _IIter2, typename _Tp>
271*38fd1498Szrj    inline _Tp
272*38fd1498Szrj    inner_product(_IIter1 __first1, _IIter1 __last1,
273*38fd1498Szrj                  _IIter2 __first2, _Tp __init,
274*38fd1498Szrj                  __gnu_parallel::_Parallelism __parallelism_tag)
275*38fd1498Szrj    {
276*38fd1498Szrj      typedef iterator_traits<_IIter1> _TraitsType1;
277*38fd1498Szrj      typedef typename _TraitsType1::value_type _ValueType1;
278*38fd1498Szrj      typedef iterator_traits<_IIter2> _TraitsType2;
279*38fd1498Szrj      typedef typename _TraitsType2::value_type _ValueType2;
280*38fd1498Szrj
281*38fd1498Szrj      typedef typename
282*38fd1498Szrj        __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
283*38fd1498Szrj        _MultipliesResultType;
284*38fd1498Szrj      return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
285*38fd1498Szrj                           __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
286*38fd1498Szrj                           __gnu_parallel::
287*38fd1498Szrj                           _Multiplies<_ValueType1, _ValueType2>(),
288*38fd1498Szrj                           __parallelism_tag);
289*38fd1498Szrj    }
290*38fd1498Szrj
291*38fd1498Szrj  template<typename _IIter1, typename _IIter2, typename _Tp>
292*38fd1498Szrj    inline _Tp
293*38fd1498Szrj    inner_product(_IIter1 __first1, _IIter1 __last1,
294*38fd1498Szrj                  _IIter2 __first2, _Tp __init)
295*38fd1498Szrj    {
296*38fd1498Szrj      typedef iterator_traits<_IIter1> _TraitsType1;
297*38fd1498Szrj      typedef typename _TraitsType1::value_type _ValueType1;
298*38fd1498Szrj      typedef iterator_traits<_IIter2> _TraitsType2;
299*38fd1498Szrj      typedef typename _TraitsType2::value_type _ValueType2;
300*38fd1498Szrj
301*38fd1498Szrj      typedef typename
302*38fd1498Szrj        __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
303*38fd1498Szrj        _MultipliesResultType;
304*38fd1498Szrj      return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
305*38fd1498Szrj                           __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
306*38fd1498Szrj                           __gnu_parallel::
307*38fd1498Szrj                           _Multiplies<_ValueType1, _ValueType2>());
308*38fd1498Szrj    }
309*38fd1498Szrj
310*38fd1498Szrj  // Sequential fallback.
311*38fd1498Szrj  template<typename _IIter, typename _OutputIterator>
312*38fd1498Szrj    inline _OutputIterator
313*38fd1498Szrj    partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
314*38fd1498Szrj                __gnu_parallel::sequential_tag)
315*38fd1498Szrj    { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result); }
316*38fd1498Szrj
317*38fd1498Szrj  // Sequential fallback.
318*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
319*38fd1498Szrj	   typename _BinaryOperation>
320*38fd1498Szrj    inline _OutputIterator
321*38fd1498Szrj    partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
322*38fd1498Szrj                _BinaryOperation __bin_op, __gnu_parallel::sequential_tag)
323*38fd1498Szrj    { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
324*38fd1498Szrj
325*38fd1498Szrj  // Sequential fallback for input iterator case.
326*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
327*38fd1498Szrj           typename _BinaryOperation, typename _IteratorTag1,
328*38fd1498Szrj           typename _IteratorTag2>
329*38fd1498Szrj    inline _OutputIterator
330*38fd1498Szrj    __partial_sum_switch(_IIter __begin, _IIter __end,
331*38fd1498Szrj			 _OutputIterator __result, _BinaryOperation __bin_op,
332*38fd1498Szrj			 _IteratorTag1, _IteratorTag2)
333*38fd1498Szrj    { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
334*38fd1498Szrj
335*38fd1498Szrj  // Parallel algorithm for random access iterators.
336*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
337*38fd1498Szrj           typename _BinaryOperation>
338*38fd1498Szrj    _OutputIterator
339*38fd1498Szrj    __partial_sum_switch(_IIter __begin, _IIter __end,
340*38fd1498Szrj			 _OutputIterator __result, _BinaryOperation __bin_op,
341*38fd1498Szrj			 random_access_iterator_tag,
342*38fd1498Szrj			 random_access_iterator_tag)
343*38fd1498Szrj    {
344*38fd1498Szrj      if (_GLIBCXX_PARALLEL_CONDITION(
345*38fd1498Szrj            static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
346*38fd1498Szrj            >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
347*38fd1498Szrj        return __gnu_parallel::__parallel_partial_sum(__begin, __end,
348*38fd1498Szrj						      __result, __bin_op);
349*38fd1498Szrj      else
350*38fd1498Szrj        return partial_sum(__begin, __end, __result, __bin_op,
351*38fd1498Szrj                           __gnu_parallel::sequential_tag());
352*38fd1498Szrj    }
353*38fd1498Szrj
354*38fd1498Szrj  // Public interface.
355*38fd1498Szrj  template<typename _IIter, typename _OutputIterator>
356*38fd1498Szrj    inline _OutputIterator
357*38fd1498Szrj    partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result)
358*38fd1498Szrj    {
359*38fd1498Szrj      typedef typename iterator_traits<_IIter>::value_type _ValueType;
360*38fd1498Szrj      return __gnu_parallel::partial_sum(__begin, __end,
361*38fd1498Szrj                                         __result, std::plus<_ValueType>());
362*38fd1498Szrj    }
363*38fd1498Szrj
364*38fd1498Szrj  // Public interface
365*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
366*38fd1498Szrj           typename _BinaryOperation>
367*38fd1498Szrj    inline _OutputIterator
368*38fd1498Szrj    partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
369*38fd1498Szrj                _BinaryOperation __binary_op)
370*38fd1498Szrj    {
371*38fd1498Szrj      typedef iterator_traits<_IIter> _ITraitsType;
372*38fd1498Szrj      typedef typename _ITraitsType::iterator_category _IIteratorCategory;
373*38fd1498Szrj
374*38fd1498Szrj      typedef iterator_traits<_OutputIterator> _OTraitsType;
375*38fd1498Szrj      typedef typename _OTraitsType::iterator_category _OIterCategory;
376*38fd1498Szrj
377*38fd1498Szrj      return __partial_sum_switch(__begin, __end, __result, __binary_op,
378*38fd1498Szrj				  _IIteratorCategory(), _OIterCategory());
379*38fd1498Szrj    }
380*38fd1498Szrj
381*38fd1498Szrj  // Sequential fallback.
382*38fd1498Szrj  template<typename _IIter, typename _OutputIterator>
383*38fd1498Szrj    inline _OutputIterator
384*38fd1498Szrj    adjacent_difference(_IIter __begin, _IIter __end, _OutputIterator __result,
385*38fd1498Szrj                        __gnu_parallel::sequential_tag)
386*38fd1498Szrj    { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end, __result); }
387*38fd1498Szrj
388*38fd1498Szrj  // Sequential fallback.
389*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
390*38fd1498Szrj           typename _BinaryOperation>
391*38fd1498Szrj    inline _OutputIterator
392*38fd1498Szrj    adjacent_difference(_IIter __begin, _IIter __end,
393*38fd1498Szrj                        _OutputIterator __result, _BinaryOperation __bin_op,
394*38fd1498Szrj                        __gnu_parallel::sequential_tag)
395*38fd1498Szrj    { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end,
396*38fd1498Szrj						 __result, __bin_op); }
397*38fd1498Szrj
398*38fd1498Szrj  // Sequential fallback for input iterator case.
399*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
400*38fd1498Szrj           typename _BinaryOperation, typename _IteratorTag1,
401*38fd1498Szrj           typename _IteratorTag2>
402*38fd1498Szrj    inline _OutputIterator
403*38fd1498Szrj    __adjacent_difference_switch(_IIter __begin, _IIter __end,
404*38fd1498Szrj				 _OutputIterator __result,
405*38fd1498Szrj				 _BinaryOperation __bin_op, _IteratorTag1,
406*38fd1498Szrj				 _IteratorTag2)
407*38fd1498Szrj    { return adjacent_difference(__begin, __end, __result, __bin_op,
408*38fd1498Szrj                                 __gnu_parallel::sequential_tag()); }
409*38fd1498Szrj
410*38fd1498Szrj  // Parallel algorithm for random access iterators.
411*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
412*38fd1498Szrj           typename _BinaryOperation>
413*38fd1498Szrj    _OutputIterator
414*38fd1498Szrj    __adjacent_difference_switch(_IIter __begin, _IIter __end,
415*38fd1498Szrj				 _OutputIterator __result,
416*38fd1498Szrj				 _BinaryOperation __bin_op,
417*38fd1498Szrj				 random_access_iterator_tag,
418*38fd1498Szrj				 random_access_iterator_tag,
419*38fd1498Szrj				 __gnu_parallel::_Parallelism
420*38fd1498Szrj				 __parallelism_tag)
421*38fd1498Szrj    {
422*38fd1498Szrj      if (_GLIBCXX_PARALLEL_CONDITION(
423*38fd1498Szrj            static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
424*38fd1498Szrj            >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
425*38fd1498Szrj            && __gnu_parallel::__is_parallel(__parallelism_tag)))
426*38fd1498Szrj        {
427*38fd1498Szrj          bool __dummy = true;
428*38fd1498Szrj          typedef __gnu_parallel::_IteratorPair<_IIter, _OutputIterator,
429*38fd1498Szrj            random_access_iterator_tag> _ItTrip;
430*38fd1498Szrj          *__result = *__begin;
431*38fd1498Szrj          _ItTrip __begin_pair(__begin + 1, __result + 1),
432*38fd1498Szrj            __end_pair(__end, __result + (__end - __begin));
433*38fd1498Szrj          __gnu_parallel::__adjacent_difference_selector<_ItTrip>
434*38fd1498Szrj                                                            __functionality;
435*38fd1498Szrj          __gnu_parallel::
436*38fd1498Szrj            __for_each_template_random_access_ed(
437*38fd1498Szrj                __begin_pair, __end_pair, __bin_op, __functionality,
438*38fd1498Szrj                __gnu_parallel::_DummyReduct(), __dummy, __dummy, -1);
439*38fd1498Szrj          return __functionality._M_finish_iterator;
440*38fd1498Szrj        }
441*38fd1498Szrj      else
442*38fd1498Szrj        return adjacent_difference(__begin, __end, __result, __bin_op,
443*38fd1498Szrj                                   __gnu_parallel::sequential_tag());
444*38fd1498Szrj    }
445*38fd1498Szrj
446*38fd1498Szrj  // Public interface.
447*38fd1498Szrj  template<typename _IIter, typename _OutputIterator>
448*38fd1498Szrj    inline _OutputIterator
449*38fd1498Szrj    adjacent_difference(_IIter __begin, _IIter __end,
450*38fd1498Szrj                        _OutputIterator __result,
451*38fd1498Szrj                        __gnu_parallel::_Parallelism __parallelism_tag)
452*38fd1498Szrj    {
453*38fd1498Szrj      typedef iterator_traits<_IIter> _TraitsType;
454*38fd1498Szrj      typedef typename _TraitsType::value_type _ValueType;
455*38fd1498Szrj      return adjacent_difference(__begin, __end, __result,
456*38fd1498Szrj				 std::minus<_ValueType>(),
457*38fd1498Szrj				 __parallelism_tag);
458*38fd1498Szrj    }
459*38fd1498Szrj
460*38fd1498Szrj  template<typename _IIter, typename _OutputIterator>
461*38fd1498Szrj    inline _OutputIterator
462*38fd1498Szrj    adjacent_difference(_IIter __begin, _IIter __end,
463*38fd1498Szrj                        _OutputIterator __result)
464*38fd1498Szrj    {
465*38fd1498Szrj      typedef iterator_traits<_IIter> _TraitsType;
466*38fd1498Szrj      typedef typename _TraitsType::value_type _ValueType;
467*38fd1498Szrj      return adjacent_difference(__begin, __end, __result,
468*38fd1498Szrj				 std::minus<_ValueType>());
469*38fd1498Szrj    }
470*38fd1498Szrj
471*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
472*38fd1498Szrj           typename _BinaryOperation>
473*38fd1498Szrj    inline _OutputIterator
474*38fd1498Szrj    adjacent_difference(_IIter __begin, _IIter __end,
475*38fd1498Szrj                        _OutputIterator __result, _BinaryOperation __binary_op,
476*38fd1498Szrj                        __gnu_parallel::_Parallelism __parallelism_tag)
477*38fd1498Szrj    {
478*38fd1498Szrj      typedef iterator_traits<_IIter> _ITraitsType;
479*38fd1498Szrj      typedef typename _ITraitsType::iterator_category _IIteratorCategory;
480*38fd1498Szrj
481*38fd1498Szrj      typedef iterator_traits<_OutputIterator> _OTraitsType;
482*38fd1498Szrj      typedef typename _OTraitsType::iterator_category _OIterCategory;
483*38fd1498Szrj
484*38fd1498Szrj      return __adjacent_difference_switch(__begin, __end, __result,
485*38fd1498Szrj					  __binary_op,
486*38fd1498Szrj					  _IIteratorCategory(),
487*38fd1498Szrj					  _OIterCategory(),
488*38fd1498Szrj					  __parallelism_tag);
489*38fd1498Szrj    }
490*38fd1498Szrj
491*38fd1498Szrj  template<typename _IIter, typename _OutputIterator,
492*38fd1498Szrj	   typename _BinaryOperation>
493*38fd1498Szrj    inline _OutputIterator
494*38fd1498Szrj    adjacent_difference(_IIter __begin, _IIter __end,
495*38fd1498Szrj			_OutputIterator __result, _BinaryOperation __binary_op)
496*38fd1498Szrj    {
497*38fd1498Szrj      typedef iterator_traits<_IIter> _ITraitsType;
498*38fd1498Szrj      typedef typename _ITraitsType::iterator_category _IIteratorCategory;
499*38fd1498Szrj
500*38fd1498Szrj      typedef iterator_traits<_OutputIterator> _OTraitsType;
501*38fd1498Szrj      typedef typename _OTraitsType::iterator_category _OIterCategory;
502*38fd1498Szrj
503*38fd1498Szrj      return __adjacent_difference_switch(__begin, __end, __result,
504*38fd1498Szrj					  __binary_op,
505*38fd1498Szrj					  _IIteratorCategory(),
506*38fd1498Szrj					  _OIterCategory());
507*38fd1498Szrj    }
508*38fd1498Szrj} // end namespace
509*38fd1498Szrj} // end namespace
510*38fd1498Szrj
511*38fd1498Szrj#endif /* _GLIBCXX_NUMERIC_H */
512