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