1 // -*- C++ -*-
2 //===-- parallel_backend_utils.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_UTILS_H
11 #define _PSTL_PARALLEL_BACKEND_UTILS_H
12
13 #include <iterator>
14 #include <utility>
15 #include "utils.h"
16
17 namespace __pstl
18 {
19
20 namespace __utils
21 {
22
23 //! Destroy sequence [xs,xe)
24 struct __serial_destroy
25 {
26 template <typename _RandomAccessIterator>
27 void
operator__serial_destroy28 operator()(_RandomAccessIterator __zs, _RandomAccessIterator __ze)
29 {
30 typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _ValueType;
31 while (__zs != __ze)
32 {
33 --__ze;
34 (*__ze).~_ValueType();
35 }
36 }
37 };
38
39 //! Merge sequences [__xs,__xe) and [__ys,__ye) to output sequence [__zs,(__xe-__xs)+(__ye-__ys)), using std::move
40 struct __serial_move_merge
41 {
42 const std::size_t _M_nmerge;
43
__serial_move_merge__serial_move_merge44 explicit __serial_move_merge(std::size_t __nmerge) : _M_nmerge(__nmerge) {}
45 template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare,
46 class _MoveValueX, class _MoveValueY, class _MoveSequenceX, class _MoveSequenceY>
47 void
operator__serial_move_merge48 operator()(_RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys,
49 _RandomAccessIterator2 __ye, _RandomAccessIterator3 __zs, _Compare __comp, _MoveValueX __move_value_x,
50 _MoveValueY __move_value_y, _MoveSequenceX __move_sequence_x, _MoveSequenceY __move_sequence_y)
51 {
52 constexpr bool __same_move_val = std::is_same<_MoveValueX, _MoveValueY>::value;
53 constexpr bool __same_move_seq = std::is_same<_MoveSequenceX, _MoveSequenceY>::value;
54
55 auto __n = _M_nmerge;
56 _PSTL_ASSERT(__n > 0);
57
58 auto __nx = __xe - __xs;
59 //auto __ny = __ye - __ys;
60 _RandomAccessIterator3 __zs_beg = __zs;
61
62 if (__xs != __xe)
63 {
64 if (__ys != __ye)
65 {
66 for (;;)
67 {
68 if (__comp(*__ys, *__xs))
69 {
70 const auto __i = __zs - __zs_beg;
71 if (__i < __nx)
72 __move_value_x(__ys, __zs);
73 else
74 __move_value_y(__ys, __zs);
75 ++__zs, --__n;
76 if (++__ys == __ye)
77 {
78 break;
79 }
80 else if (__n == 0)
81 {
82 const auto __j = __zs - __zs_beg;
83 if (__same_move_seq || __j < __nx)
84 __zs = __move_sequence_x(__ys, __ye, __zs);
85 else
86 __zs = __move_sequence_y(__ys, __ye, __zs);
87 break;
88 }
89 }
90 else
91 {
92 const auto __i = __zs - __zs_beg;
93 if (__same_move_val || __i < __nx)
94 __move_value_x(__xs, __zs);
95 else
96 __move_value_y(__xs, __zs);
97 ++__zs, --__n;
98 if (++__xs == __xe)
99 {
100 const auto __j = __zs - __zs_beg;
101 if (__same_move_seq || __j < __nx)
102 __move_sequence_x(__ys, __ye, __zs);
103 else
104 __move_sequence_y(__ys, __ye, __zs);
105 return;
106 }
107 else if (__n == 0)
108 {
109 const auto __j = __zs - __zs_beg;
110 if (__same_move_seq || __j < __nx)
111 {
112 __zs = __move_sequence_x(__xs, __xe, __zs);
113 __move_sequence_x(__ys, __ye, __zs);
114 }
115 else
116 {
117 __zs = __move_sequence_y(__xs, __xe, __zs);
118 __move_sequence_y(__ys, __ye, __zs);
119 }
120 return;
121 }
122 }
123 }
124 }
125 __ys = __xs;
126 __ye = __xe;
127 }
128 const auto __i = __zs - __zs_beg;
129 if (__same_move_seq || __i < __nx)
130 __move_sequence_x(__ys, __ye, __zs);
131 else
132 __move_sequence_y(__ys, __ye, __zs);
133 }
134 };
135
136 template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare,
137 typename _CopyConstructRange>
138 _OutputIterator
__set_union_construct(_ForwardIterator1 __first1,_ForwardIterator1 __last1,_ForwardIterator2 __first2,_ForwardIterator2 __last2,_OutputIterator __result,_Compare __comp,_CopyConstructRange __cc_range)139 __set_union_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
140 _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
141 _CopyConstructRange __cc_range)
142 {
143 using _Tp = typename std::iterator_traits<_OutputIterator>::value_type;
144
145 for (; __first1 != __last1; ++__result)
146 {
147 if (__first2 == __last2)
148 return __cc_range(__first1, __last1, __result);
149 if (__comp(*__first2, *__first1))
150 {
151 ::new (std::addressof(*__result)) _Tp(*__first2);
152 ++__first2;
153 }
154 else
155 {
156 ::new (std::addressof(*__result)) _Tp(*__first1);
157 if (!__comp(*__first1, *__first2))
158 ++__first2;
159 ++__first1;
160 }
161 }
162 return __cc_range(__first2, __last2, __result);
163 }
164
165 template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare>
166 _OutputIterator
__set_intersection_construct(_ForwardIterator1 __first1,_ForwardIterator1 __last1,_ForwardIterator2 __first2,_ForwardIterator2 __last2,_OutputIterator __result,_Compare __comp)167 __set_intersection_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
168 _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp)
169 {
170 using _Tp = typename std::iterator_traits<_OutputIterator>::value_type;
171
172 for (; __first1 != __last1 && __first2 != __last2;)
173 {
174 if (__comp(*__first1, *__first2))
175 ++__first1;
176 else
177 {
178 if (!__comp(*__first2, *__first1))
179 {
180 ::new (std::addressof(*__result)) _Tp(*__first1);
181 ++__result;
182 ++__first1;
183 }
184 ++__first2;
185 }
186 }
187 return __result;
188 }
189
190 template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare,
191 typename _CopyConstructRange>
192 _OutputIterator
__set_difference_construct(_ForwardIterator1 __first1,_ForwardIterator1 __last1,_ForwardIterator2 __first2,_ForwardIterator2 __last2,_OutputIterator __result,_Compare __comp,_CopyConstructRange __cc_range)193 __set_difference_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
194 _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
195 _CopyConstructRange __cc_range)
196 {
197 using _Tp = typename std::iterator_traits<_OutputIterator>::value_type;
198
199 for (; __first1 != __last1;)
200 {
201 if (__first2 == __last2)
202 return __cc_range(__first1, __last1, __result);
203
204 if (__comp(*__first1, *__first2))
205 {
206 ::new (std::addressof(*__result)) _Tp(*__first1);
207 ++__result;
208 ++__first1;
209 }
210 else
211 {
212 if (!__comp(*__first2, *__first1))
213 ++__first1;
214 ++__first2;
215 }
216 }
217 return __result;
218 }
219 template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare,
220 typename _CopyConstructRange>
221 _OutputIterator
__set_symmetric_difference_construct(_ForwardIterator1 __first1,_ForwardIterator1 __last1,_ForwardIterator2 __first2,_ForwardIterator2 __last2,_OutputIterator __result,_Compare __comp,_CopyConstructRange __cc_range)222 __set_symmetric_difference_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
223 _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
224 _CopyConstructRange __cc_range)
225 {
226 using _Tp = typename std::iterator_traits<_OutputIterator>::value_type;
227
228 for (; __first1 != __last1;)
229 {
230 if (__first2 == __last2)
231 return __cc_range(__first1, __last1, __result);
232
233 if (__comp(*__first1, *__first2))
234 {
235 ::new (std::addressof(*__result)) _Tp(*__first1);
236 ++__result;
237 ++__first1;
238 }
239 else
240 {
241 if (__comp(*__first2, *__first1))
242 {
243 ::new (std::addressof(*__result)) _Tp(*__first2);
244 ++__result;
245 }
246 else
247 ++__first1;
248 ++__first2;
249 }
250 }
251 return __cc_range(__first2, __last2, __result);
252 }
253
254 } // namespace __utils
255 } // namespace __pstl
256
257 #endif /* _PSTL_PARALLEL_BACKEND_UTILS_H */
258