1 // -*- C++ -*-
2 //===-- parallel_backend_serial.h -----------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _PSTL_PARALLEL_BACKEND_SERIAL_H
11 #define _PSTL_PARALLEL_BACKEND_SERIAL_H
12 
13 #include <algorithm>
14 #include <cstddef>
15 #include <memory>
16 #include <numeric>
17 #include <utility>
18 
19 namespace __pstl
20 {
21 namespace __serial
22 {
23 
24 template <typename _Tp>
25 class __buffer
26 {
27     std::allocator<_Tp> __allocator_;
28     _Tp* __ptr_;
29     const std::size_t __buf_size_;
30     __buffer(const __buffer&) = delete;
31     void
32     operator=(const __buffer&) = delete;
33 
34   public:
__buffer(std::size_t __n)35     __buffer(std::size_t __n) : __allocator_(), __ptr_(__allocator_.allocate(__n)), __buf_size_(__n) {}
36 
37     operator bool() const { return __ptr_ != nullptr; }
38     _Tp*
get()39     get() const
40     {
41         return __ptr_;
42     }
~__buffer()43     ~__buffer() { __allocator_.deallocate(__ptr_, __buf_size_); }
44 };
45 
46 inline void
__cancel_execution()47 __cancel_execution()
48 {
49 }
50 
51 template <class _ExecutionPolicy, class _Index, class _Fp>
52 void
__parallel_for(_ExecutionPolicy &&,_Index __first,_Index __last,_Fp __f)53 __parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f)
54 {
55     __f(__first, __last);
56 }
57 
58 template <class _ExecutionPolicy, class _Value, class _Index, typename _RealBody, typename _Reduction>
59 _Value
__parallel_reduce(_ExecutionPolicy &&,_Index __first,_Index __last,const _Value & __identity,const _RealBody & __real_body,const _Reduction &)60 __parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Value& __identity,
61                   const _RealBody& __real_body, const _Reduction&)
62 {
63     if (__first == __last)
64     {
65         return __identity;
66     }
67     else
68     {
69         return __real_body(__first, __last, __identity);
70     }
71 }
72 
73 template <class _ExecutionPolicy, class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce>
74 _Tp
__parallel_transform_reduce(_ExecutionPolicy &&,_Index __first,_Index __last,_UnaryOp,_Tp __init,_BinaryOp,_Reduce __reduce)75 __parallel_transform_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp,
76                             _Reduce __reduce)
77 {
78     return __reduce(__first, __last, __init);
79 }
80 
81 template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap>
82 void
__parallel_strict_scan(_ExecutionPolicy &&,_Index __n,_Tp __initial,_Rp __reduce,_Cp __combine,_Sp __scan,_Ap __apex)83 __parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan,
84                        _Ap __apex)
85 {
86     _Tp __sum = __initial;
87     if (__n)
88         __sum = __combine(__sum, __reduce(_Index(0), __n));
89     __apex(__sum);
90     if (__n)
91         __scan(_Index(0), __n, __initial);
92 }
93 
94 template <class _ExecutionPolicy, class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce, class _Scan>
95 _Tp
__parallel_transform_scan(_ExecutionPolicy &&,_Index __n,_UnaryOp,_Tp __init,_BinaryOp,_Reduce,_Scan __scan)96 __parallel_transform_scan(_ExecutionPolicy&&, _Index __n, _UnaryOp, _Tp __init, _BinaryOp, _Reduce, _Scan __scan)
97 {
98     return __scan(_Index(0), __n, __init);
99 }
100 
101 template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort>
102 void
103 __parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
104                        _LeafSort __leaf_sort, std::size_t = 0)
105 {
106     __leaf_sort(__first, __last, __comp);
107 }
108 
109 template <class _ExecutionPolicy, typename _RandomAccessIterator1, typename _RandomAccessIterator2,
110           typename _RandomAccessIterator3, typename _Compare, typename _LeafMerge>
111 void
__parallel_merge(_ExecutionPolicy &&,_RandomAccessIterator1 __first1,_RandomAccessIterator1 __last1,_RandomAccessIterator2 __first2,_RandomAccessIterator2 __last2,_RandomAccessIterator3 __out,_Compare __comp,_LeafMerge __leaf_merge)112 __parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
113                  _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _RandomAccessIterator3 __out,
114                  _Compare __comp, _LeafMerge __leaf_merge)
115 {
116     __leaf_merge(__first1, __last1, __first2, __last2, __out, __comp);
117 }
118 
119 template <class _ExecutionPolicy, typename _F1, typename _F2>
120 void
__parallel_invoke(_ExecutionPolicy &&,_F1 && __f1,_F2 && __f2)121 __parallel_invoke(_ExecutionPolicy&&, _F1&& __f1, _F2&& __f2)
122 {
123     std::forward<_F1>(__f1)();
124     std::forward<_F2>(__f2)();
125 }
126 
127 } // namespace __serial
128 } // namespace __pstl
129 
130 namespace __pstl
131 {
132 namespace __par_backend
133 {
134 using namespace __pstl::__serial;
135 }
136 } // namespace __pstl
137 
138 #endif /* _PSTL_PARALLEL_BACKEND_SERIAL_H */
139