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