xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/pstl/numeric_impl.h (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg // -*- C++ -*-
2627f7eb2Smrg //===-- numeric_impl.h ----------------------------------------------------===//
3627f7eb2Smrg //
4627f7eb2Smrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5627f7eb2Smrg // See https://llvm.org/LICENSE.txt for license information.
6627f7eb2Smrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7627f7eb2Smrg //
8627f7eb2Smrg //===----------------------------------------------------------------------===//
9627f7eb2Smrg 
10*4c3eb207Smrg #ifndef _PSTL_NUMERIC_IMPL_H
11*4c3eb207Smrg #define _PSTL_NUMERIC_IMPL_H
12627f7eb2Smrg 
13627f7eb2Smrg #include <iterator>
14627f7eb2Smrg #include <type_traits>
15627f7eb2Smrg #include <numeric>
16627f7eb2Smrg 
17*4c3eb207Smrg #include "parallel_backend.h"
18*4c3eb207Smrg #include "pstl_config.h"
19627f7eb2Smrg #include "execution_impl.h"
20627f7eb2Smrg #include "unseq_backend_simd.h"
21627f7eb2Smrg #include "algorithm_fwd.h"
22627f7eb2Smrg 
23627f7eb2Smrg namespace __pstl
24627f7eb2Smrg {
25627f7eb2Smrg namespace __internal
26627f7eb2Smrg {
27627f7eb2Smrg 
28627f7eb2Smrg //------------------------------------------------------------------------
29627f7eb2Smrg // transform_reduce (version with two binary functions, according to draft N4659)
30627f7eb2Smrg //------------------------------------------------------------------------
31627f7eb2Smrg 
32627f7eb2Smrg template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
33627f7eb2Smrg _Tp
__brick_transform_reduce(_ForwardIterator1 __first1,_ForwardIterator1 __last1,_ForwardIterator2 __first2,_Tp __init,_BinaryOperation1 __binary_op1,_BinaryOperation2 __binary_op2,std::false_type)34627f7eb2Smrg __brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Tp __init,
35627f7eb2Smrg                          _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2,
36627f7eb2Smrg                          /*is_vector=*/std::false_type) noexcept
37627f7eb2Smrg {
38627f7eb2Smrg     return std::inner_product(__first1, __last1, __first2, __init, __binary_op1, __binary_op2);
39627f7eb2Smrg }
40627f7eb2Smrg 
41627f7eb2Smrg template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
42627f7eb2Smrg _Tp
__brick_transform_reduce(_ForwardIterator1 __first1,_ForwardIterator1 __last1,_ForwardIterator2 __first2,_Tp __init,_BinaryOperation1 __binary_op1,_BinaryOperation2 __binary_op2,std::true_type)43627f7eb2Smrg __brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Tp __init,
44627f7eb2Smrg                          _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2,
45627f7eb2Smrg                          /*is_vector=*/std::true_type) noexcept
46627f7eb2Smrg {
47627f7eb2Smrg     typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
48627f7eb2Smrg     return __unseq_backend::__simd_transform_reduce(
49627f7eb2Smrg         __last1 - __first1, __init, __binary_op1,
50627f7eb2Smrg         [=, &__binary_op2](_DifferenceType __i) { return __binary_op2(__first1[__i], __first2[__i]); });
51627f7eb2Smrg }
52627f7eb2Smrg 
53627f7eb2Smrg template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1,
54627f7eb2Smrg           class _BinaryOperation2, class _IsVector>
55627f7eb2Smrg _Tp
__pattern_transform_reduce(_ExecutionPolicy &&,_ForwardIterator1 __first1,_ForwardIterator1 __last1,_ForwardIterator2 __first2,_Tp __init,_BinaryOperation1 __binary_op1,_BinaryOperation2 __binary_op2,_IsVector __is_vector,std::false_type)56627f7eb2Smrg __pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
57627f7eb2Smrg                            _ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
58627f7eb2Smrg                            _BinaryOperation2 __binary_op2, _IsVector __is_vector,
59627f7eb2Smrg                            /*is_parallel=*/std::false_type) noexcept
60627f7eb2Smrg {
61627f7eb2Smrg     return __brick_transform_reduce(__first1, __last1, __first2, __init, __binary_op1, __binary_op2, __is_vector);
62627f7eb2Smrg }
63627f7eb2Smrg 
64627f7eb2Smrg template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp,
65627f7eb2Smrg           class _BinaryOperation1, class _BinaryOperation2, class _IsVector>
66627f7eb2Smrg _Tp
__pattern_transform_reduce(_ExecutionPolicy && __exec,_RandomAccessIterator1 __first1,_RandomAccessIterator1 __last1,_RandomAccessIterator2 __first2,_Tp __init,_BinaryOperation1 __binary_op1,_BinaryOperation2 __binary_op2,_IsVector __is_vector,std::true_type)67627f7eb2Smrg __pattern_transform_reduce(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
68627f7eb2Smrg                            _RandomAccessIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
69627f7eb2Smrg                            _BinaryOperation2 __binary_op2, _IsVector __is_vector, /*is_parallel=*/std::true_type)
70627f7eb2Smrg {
71627f7eb2Smrg     return __internal::__except_handler([&]() {
72627f7eb2Smrg         return __par_backend::__parallel_transform_reduce(
73627f7eb2Smrg             std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
74627f7eb2Smrg             [__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable {
75627f7eb2Smrg                 return __binary_op2(*__i, *(__first2 + (__i - __first1)));
76627f7eb2Smrg             },
77627f7eb2Smrg             __init,
78627f7eb2Smrg             __binary_op1, // Combine
79627f7eb2Smrg             [__first1, __first2, __binary_op1, __binary_op2,
80627f7eb2Smrg              __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j, _Tp __init) -> _Tp {
81627f7eb2Smrg                 return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init, __binary_op1,
82627f7eb2Smrg                                                             __binary_op2, __is_vector);
83627f7eb2Smrg             });
84627f7eb2Smrg     });
85627f7eb2Smrg }
86627f7eb2Smrg 
87627f7eb2Smrg //------------------------------------------------------------------------
88627f7eb2Smrg // transform_reduce (version with unary and binary functions)
89627f7eb2Smrg //------------------------------------------------------------------------
90627f7eb2Smrg 
91627f7eb2Smrg template <class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
92627f7eb2Smrg _Tp
__brick_transform_reduce(_ForwardIterator __first,_ForwardIterator __last,_Tp __init,_BinaryOperation __binary_op,_UnaryOperation __unary_op,std::false_type)93627f7eb2Smrg __brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __binary_op,
94627f7eb2Smrg                          _UnaryOperation __unary_op, /*is_vector=*/std::false_type) noexcept
95627f7eb2Smrg {
96627f7eb2Smrg     for (; __first != __last; ++__first)
97627f7eb2Smrg     {
98627f7eb2Smrg         __init = __binary_op(__init, __unary_op(*__first));
99627f7eb2Smrg     }
100627f7eb2Smrg     return __init;
101627f7eb2Smrg }
102627f7eb2Smrg 
103627f7eb2Smrg template <class _ForwardIterator, class _Tp, class _UnaryOperation, class _BinaryOperation>
104627f7eb2Smrg _Tp
__brick_transform_reduce(_ForwardIterator __first,_ForwardIterator __last,_Tp __init,_BinaryOperation __binary_op,_UnaryOperation __unary_op,std::true_type)105627f7eb2Smrg __brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __binary_op,
106627f7eb2Smrg                          _UnaryOperation __unary_op, /*is_vector=*/std::true_type) noexcept
107627f7eb2Smrg {
108627f7eb2Smrg     typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType;
109627f7eb2Smrg     return __unseq_backend::__simd_transform_reduce(
110627f7eb2Smrg         __last - __first, __init, __binary_op,
111627f7eb2Smrg         [=, &__unary_op](_DifferenceType __i) { return __unary_op(__first[__i]); });
112627f7eb2Smrg }
113627f7eb2Smrg 
114627f7eb2Smrg template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation,
115627f7eb2Smrg           class _IsVector>
116627f7eb2Smrg _Tp
__pattern_transform_reduce(_ExecutionPolicy &&,_ForwardIterator __first,_ForwardIterator __last,_Tp __init,_BinaryOperation __binary_op,_UnaryOperation __unary_op,_IsVector __is_vector,std::false_type)117627f7eb2Smrg __pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
118627f7eb2Smrg                            _BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector,
119627f7eb2Smrg                            /*is_parallel=*/std::false_type) noexcept
120627f7eb2Smrg {
121627f7eb2Smrg     return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op, __is_vector);
122627f7eb2Smrg }
123627f7eb2Smrg 
124627f7eb2Smrg template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation,
125627f7eb2Smrg           class _IsVector>
126627f7eb2Smrg _Tp
__pattern_transform_reduce(_ExecutionPolicy && __exec,_ForwardIterator __first,_ForwardIterator __last,_Tp __init,_BinaryOperation __binary_op,_UnaryOperation __unary_op,_IsVector __is_vector,std::true_type)127627f7eb2Smrg __pattern_transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
128627f7eb2Smrg                            _BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector,
129627f7eb2Smrg                            /*is_parallel=*/std::true_type)
130627f7eb2Smrg {
131627f7eb2Smrg     return __internal::__except_handler([&]() {
132627f7eb2Smrg         return __par_backend::__parallel_transform_reduce(
133627f7eb2Smrg             std::forward<_ExecutionPolicy>(__exec), __first, __last,
134627f7eb2Smrg             [__unary_op](_ForwardIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op,
135627f7eb2Smrg             [__unary_op, __binary_op, __is_vector](_ForwardIterator __i, _ForwardIterator __j, _Tp __init) {
136627f7eb2Smrg                 return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, __is_vector);
137627f7eb2Smrg             });
138627f7eb2Smrg     });
139627f7eb2Smrg }
140627f7eb2Smrg 
141627f7eb2Smrg //------------------------------------------------------------------------
142627f7eb2Smrg // transform_exclusive_scan
143627f7eb2Smrg //
144627f7eb2Smrg // walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...)
145627f7eb2Smrg //------------------------------------------------------------------------
146627f7eb2Smrg 
147627f7eb2Smrg // Exclusive form
148627f7eb2Smrg template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation>
149627f7eb2Smrg std::pair<_OutputIterator, _Tp>
__brick_transform_scan(_ForwardIterator __first,_ForwardIterator __last,_OutputIterator __result,_UnaryOperation __unary_op,_Tp __init,_BinaryOperation __binary_op,std::false_type,std::false_type)150627f7eb2Smrg __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
151627f7eb2Smrg                        _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
152627f7eb2Smrg                        /*Inclusive*/ std::false_type, /*is_vector=*/std::false_type) noexcept
153627f7eb2Smrg {
154627f7eb2Smrg     for (; __first != __last; ++__first, ++__result)
155627f7eb2Smrg     {
156627f7eb2Smrg         *__result = __init;
157*4c3eb207Smrg         _PSTL_PRAGMA_FORCEINLINE
158627f7eb2Smrg         __init = __binary_op(__init, __unary_op(*__first));
159627f7eb2Smrg     }
160627f7eb2Smrg     return std::make_pair(__result, __init);
161627f7eb2Smrg }
162627f7eb2Smrg 
163627f7eb2Smrg // Inclusive form
164627f7eb2Smrg template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation>
165627f7eb2Smrg std::pair<_OutputIterator, _Tp>
__brick_transform_scan(_ForwardIterator __first,_ForwardIterator __last,_OutputIterator __result,_UnaryOperation __unary_op,_Tp __init,_BinaryOperation __binary_op,std::true_type,std::false_type)166627f7eb2Smrg __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
167627f7eb2Smrg                        _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
168627f7eb2Smrg                        /*Inclusive*/ std::true_type, /*is_vector=*/std::false_type) noexcept
169627f7eb2Smrg {
170627f7eb2Smrg     for (; __first != __last; ++__first, ++__result)
171627f7eb2Smrg     {
172*4c3eb207Smrg         _PSTL_PRAGMA_FORCEINLINE
173627f7eb2Smrg         __init = __binary_op(__init, __unary_op(*__first));
174627f7eb2Smrg         *__result = __init;
175627f7eb2Smrg     }
176627f7eb2Smrg     return std::make_pair(__result, __init);
177627f7eb2Smrg }
178627f7eb2Smrg 
179627f7eb2Smrg // type is arithmetic and binary operation is a user defined operation.
180627f7eb2Smrg template <typename _Tp, typename _BinaryOperation>
181627f7eb2Smrg using is_arithmetic_udop = std::integral_constant<bool, std::is_arithmetic<_Tp>::value &&
182627f7eb2Smrg                                                             !std::is_same<_BinaryOperation, std::plus<_Tp>>::value>;
183627f7eb2Smrg 
184627f7eb2Smrg // [restriction] - T shall be DefaultConstructible.
185627f7eb2Smrg // [violation] - default ctor of T shall set the identity value for binary_op.
186627f7eb2Smrg template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation,
187627f7eb2Smrg           class _Inclusive>
188627f7eb2Smrg typename std::enable_if<!is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type
__brick_transform_scan(_ForwardIterator __first,_ForwardIterator __last,_OutputIterator __result,_UnaryOperation __unary_op,_Tp __init,_BinaryOperation __binary_op,_Inclusive,std::true_type)189627f7eb2Smrg __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
190627f7eb2Smrg                        _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive,
191627f7eb2Smrg                        /*is_vector=*/std::true_type) noexcept
192627f7eb2Smrg {
193*4c3eb207Smrg #if (_PSTL_UDS_PRESENT)
194627f7eb2Smrg     return __unseq_backend::__simd_scan(__first, __last - __first, __result, __unary_op, __init, __binary_op,
195627f7eb2Smrg                                         _Inclusive());
196627f7eb2Smrg #else
197627f7eb2Smrg     // We need to call serial brick here to call function for inclusive and exclusive scan that depends on _Inclusive() value
198627f7eb2Smrg     return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
199627f7eb2Smrg                                               /*is_vector=*/std::false_type());
200627f7eb2Smrg #endif
201627f7eb2Smrg }
202627f7eb2Smrg 
203627f7eb2Smrg template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation,
204627f7eb2Smrg           class _Inclusive>
205627f7eb2Smrg typename std::enable_if<is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type
__brick_transform_scan(_ForwardIterator __first,_ForwardIterator __last,_OutputIterator __result,_UnaryOperation __unary_op,_Tp __init,_BinaryOperation __binary_op,_Inclusive,std::true_type)206627f7eb2Smrg __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
207627f7eb2Smrg                        _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive,
208627f7eb2Smrg                        /*is_vector=*/std::true_type) noexcept
209627f7eb2Smrg {
210627f7eb2Smrg     return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
211627f7eb2Smrg                                               /*is_vector=*/std::false_type());
212627f7eb2Smrg }
213627f7eb2Smrg 
214627f7eb2Smrg template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
215627f7eb2Smrg           class _BinaryOperation, class _Inclusive, class _IsVector>
216627f7eb2Smrg _OutputIterator
__pattern_transform_scan(_ExecutionPolicy &&,_ForwardIterator __first,_ForwardIterator __last,_OutputIterator __result,_UnaryOperation __unary_op,_Tp __init,_BinaryOperation __binary_op,_Inclusive,_IsVector __is_vector,std::false_type)217627f7eb2Smrg __pattern_transform_scan(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
218627f7eb2Smrg                          _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
219627f7eb2Smrg                          _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
220627f7eb2Smrg {
221*4c3eb207Smrg     return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
222*4c3eb207Smrg                                               __is_vector)
223627f7eb2Smrg         .first;
224627f7eb2Smrg }
225627f7eb2Smrg 
226627f7eb2Smrg template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
227627f7eb2Smrg           class _BinaryOperation, class _Inclusive, class _IsVector>
228627f7eb2Smrg typename std::enable_if<!std::is_floating_point<_Tp>::value, _OutputIterator>::type
__pattern_transform_scan(_ExecutionPolicy && __exec,_RandomAccessIterator __first,_RandomAccessIterator __last,_OutputIterator __result,_UnaryOperation __unary_op,_Tp __init,_BinaryOperation __binary_op,_Inclusive,_IsVector __is_vector,std::true_type)229627f7eb2Smrg __pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
230627f7eb2Smrg                          _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
231627f7eb2Smrg                          _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::true_type)
232627f7eb2Smrg {
233627f7eb2Smrg     typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
234627f7eb2Smrg 
235627f7eb2Smrg     return __internal::__except_handler([&]() {
236627f7eb2Smrg         __par_backend::__parallel_transform_scan(
237627f7eb2Smrg             std::forward<_ExecutionPolicy>(__exec), __last - __first,
238627f7eb2Smrg             [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init,
239627f7eb2Smrg             __binary_op,
240627f7eb2Smrg             [__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init) {
241627f7eb2Smrg                 // Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan.
242*4c3eb207Smrg                 return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op,
243*4c3eb207Smrg                                                             __unary_op,
244627f7eb2Smrg                                                             /*__is_vector*/ std::false_type());
245627f7eb2Smrg             },
246627f7eb2Smrg             [__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __j,
247627f7eb2Smrg                                                                       _Tp __init) {
248*4c3eb207Smrg                 return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op,
249*4c3eb207Smrg                                                           __init, __binary_op, _Inclusive(), __is_vector)
250627f7eb2Smrg                     .second;
251627f7eb2Smrg             });
252627f7eb2Smrg         return __result + (__last - __first);
253627f7eb2Smrg     });
254627f7eb2Smrg }
255627f7eb2Smrg 
256627f7eb2Smrg template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
257627f7eb2Smrg           class _BinaryOperation, class _Inclusive, class _IsVector>
258627f7eb2Smrg typename std::enable_if<std::is_floating_point<_Tp>::value, _OutputIterator>::type
__pattern_transform_scan(_ExecutionPolicy && __exec,_RandomAccessIterator __first,_RandomAccessIterator __last,_OutputIterator __result,_UnaryOperation __unary_op,_Tp __init,_BinaryOperation __binary_op,_Inclusive,_IsVector __is_vector,std::true_type)259627f7eb2Smrg __pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
260627f7eb2Smrg                          _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
261627f7eb2Smrg                          _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::true_type)
262627f7eb2Smrg {
263627f7eb2Smrg     typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
264627f7eb2Smrg     _DifferenceType __n = __last - __first;
265627f7eb2Smrg 
266627f7eb2Smrg     if (__n <= 0)
267627f7eb2Smrg     {
268627f7eb2Smrg         return __result;
269627f7eb2Smrg     }
270627f7eb2Smrg     return __internal::__except_handler([&]() {
271627f7eb2Smrg         __par_backend::__parallel_strict_scan(
272627f7eb2Smrg             std::forward<_ExecutionPolicy>(__exec), __n, __init,
273627f7eb2Smrg             [__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __len) {
274*4c3eb207Smrg                 return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i,
275*4c3eb207Smrg                                                           __unary_op, _Tp{}, __binary_op, _Inclusive(), __is_vector)
276627f7eb2Smrg                     .second;
277627f7eb2Smrg             },
278627f7eb2Smrg             __binary_op,
279627f7eb2Smrg             [__result, &__binary_op](_DifferenceType __i, _DifferenceType __len, _Tp __initial) {
280627f7eb2Smrg                 return *(std::transform(__result + __i, __result + __i + __len, __result + __i,
281627f7eb2Smrg                                         [&__initial, &__binary_op](const _Tp& __x) {
282*4c3eb207Smrg                                             _PSTL_PRAGMA_FORCEINLINE
283627f7eb2Smrg                                             return __binary_op(__initial, __x);
284627f7eb2Smrg                                         }) -
285627f7eb2Smrg                          1);
286627f7eb2Smrg             },
287627f7eb2Smrg             [](_Tp __res) {});
288627f7eb2Smrg         return __result + (__last - __first);
289627f7eb2Smrg     });
290627f7eb2Smrg }
291627f7eb2Smrg 
292627f7eb2Smrg //------------------------------------------------------------------------
293627f7eb2Smrg // adjacent_difference
294627f7eb2Smrg //------------------------------------------------------------------------
295627f7eb2Smrg 
296627f7eb2Smrg template <class _ForwardIterator, class _OutputIterator, class _BinaryOperation>
297627f7eb2Smrg _OutputIterator
__brick_adjacent_difference(_ForwardIterator __first,_ForwardIterator __last,_OutputIterator __d_first,_BinaryOperation __op,std::false_type)298627f7eb2Smrg __brick_adjacent_difference(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __d_first,
299627f7eb2Smrg                             _BinaryOperation __op, /*is_vector*/ std::false_type) noexcept
300627f7eb2Smrg {
301627f7eb2Smrg     return std::adjacent_difference(__first, __last, __d_first, __op);
302627f7eb2Smrg }
303627f7eb2Smrg 
304627f7eb2Smrg template <class _ForwardIterator1, class _ForwardIterator2, class BinaryOperation>
305627f7eb2Smrg _ForwardIterator2
__brick_adjacent_difference(_ForwardIterator1 __first,_ForwardIterator1 __last,_ForwardIterator2 __d_first,BinaryOperation __op,std::true_type)306627f7eb2Smrg __brick_adjacent_difference(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first,
307627f7eb2Smrg                             BinaryOperation __op, /*is_vector=*/std::true_type) noexcept
308627f7eb2Smrg {
309*4c3eb207Smrg     _PSTL_ASSERT(__first != __last);
310627f7eb2Smrg 
311627f7eb2Smrg     typedef typename std::iterator_traits<_ForwardIterator1>::reference _ReferenceType1;
312627f7eb2Smrg     typedef typename std::iterator_traits<_ForwardIterator2>::reference _ReferenceType2;
313627f7eb2Smrg 
314627f7eb2Smrg     auto __n = __last - __first;
315627f7eb2Smrg     *__d_first = *__first;
316627f7eb2Smrg     return __unseq_backend::__simd_walk_3(
317627f7eb2Smrg         __first + 1, __n - 1, __first, __d_first + 1,
318627f7eb2Smrg         [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__x, __y); });
319627f7eb2Smrg }
320627f7eb2Smrg 
321627f7eb2Smrg template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation,
322627f7eb2Smrg           class _IsVector>
323627f7eb2Smrg _OutputIterator
__pattern_adjacent_difference(_ExecutionPolicy &&,_ForwardIterator __first,_ForwardIterator __last,_OutputIterator __d_first,_BinaryOperation __op,_IsVector __is_vector,std::false_type)324627f7eb2Smrg __pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
325627f7eb2Smrg                               _OutputIterator __d_first, _BinaryOperation __op, _IsVector __is_vector,
326627f7eb2Smrg                               /*is_parallel*/ std::false_type) noexcept
327627f7eb2Smrg {
328627f7eb2Smrg     return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, __is_vector);
329627f7eb2Smrg }
330627f7eb2Smrg 
331627f7eb2Smrg template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation,
332627f7eb2Smrg           class _IsVector>
333627f7eb2Smrg _ForwardIterator2
__pattern_adjacent_difference(_ExecutionPolicy && __exec,_ForwardIterator1 __first,_ForwardIterator1 __last,_ForwardIterator2 __d_first,_BinaryOperation __op,_IsVector __is_vector,std::true_type)334627f7eb2Smrg __pattern_adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
335627f7eb2Smrg                               _ForwardIterator2 __d_first, _BinaryOperation __op, _IsVector __is_vector,
336627f7eb2Smrg                               /*is_parallel=*/std::true_type)
337627f7eb2Smrg {
338*4c3eb207Smrg     _PSTL_ASSERT(__first != __last);
339627f7eb2Smrg     typedef typename std::iterator_traits<_ForwardIterator1>::reference _ReferenceType1;
340627f7eb2Smrg     typedef typename std::iterator_traits<_ForwardIterator2>::reference _ReferenceType2;
341627f7eb2Smrg 
342627f7eb2Smrg     *__d_first = *__first;
343627f7eb2Smrg     __par_backend::__parallel_for(
344627f7eb2Smrg         std::forward<_ExecutionPolicy>(__exec), __first, __last - 1,
345627f7eb2Smrg         [&__op, __is_vector, __d_first, __first](_ForwardIterator1 __b, _ForwardIterator1 __e) {
346627f7eb2Smrg             _ForwardIterator2 __d_b = __d_first + (__b - __first);
347627f7eb2Smrg             __internal::__brick_walk3(
348627f7eb2Smrg                 __b, __e, __b + 1, __d_b + 1,
349627f7eb2Smrg                 [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__y, __x); },
350627f7eb2Smrg                 __is_vector);
351627f7eb2Smrg         });
352627f7eb2Smrg     return __d_first + (__last - __first);
353627f7eb2Smrg }
354627f7eb2Smrg 
355627f7eb2Smrg } // namespace __internal
356627f7eb2Smrg } // namespace __pstl
357627f7eb2Smrg 
358*4c3eb207Smrg #endif /* _PSTL_NUMERIC_IMPL_H */
359