Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===----------------------------------------------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef _LIBCPP___ALGORITHM_STABLE_SORT_H |
10 | #define _LIBCPP___ALGORITHM_STABLE_SORT_H |
11 | |
12 | #include <__algorithm/comp.h> |
13 | #include <__algorithm/comp_ref_type.h> |
14 | #include <__algorithm/inplace_merge.h> |
15 | #include <__algorithm/iterator_operations.h> |
16 | #include <__algorithm/radix_sort.h> |
17 | #include <__algorithm/sort.h> |
18 | #include <__config> |
19 | #include <__cstddef/ptrdiff_t.h> |
20 | #include <__debug_utils/strict_weak_ordering_check.h> |
21 | #include <__iterator/iterator_traits.h> |
22 | #include <__memory/construct_at.h> |
23 | #include <__memory/destruct_n.h> |
24 | #include <__memory/unique_ptr.h> |
25 | #include <__memory/unique_temporary_buffer.h> |
26 | #include <__type_traits/desugars_to.h> |
27 | #include <__type_traits/enable_if.h> |
28 | #include <__type_traits/is_constant_evaluated.h> |
29 | #include <__type_traits/is_same.h> |
30 | #include <__type_traits/is_trivially_assignable.h> |
31 | #include <__utility/move.h> |
32 | #include <__utility/pair.h> |
33 | |
34 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
35 | # pragma GCC system_header |
36 | #endif |
37 | |
38 | _LIBCPP_PUSH_MACROS |
39 | #include <__undef_macros> |
40 | |
41 | _LIBCPP_BEGIN_NAMESPACE_STD |
42 | |
43 | template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> |
44 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insertion_sort_move( |
45 | _BidirectionalIterator __first1, |
46 | _BidirectionalIterator __last1, |
47 | typename iterator_traits<_BidirectionalIterator>::value_type* __first2, |
48 | _Compare __comp) { |
49 | using _Ops = _IterOps<_AlgPolicy>; |
50 | |
51 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; |
52 | if (__first1 != __last1) { |
53 | __destruct_n __d(0); |
54 | unique_ptr<value_type, __destruct_n&> __h(__first2, __d); |
55 | value_type* __last2 = __first2; |
56 | std::__construct_at(__last2, _Ops::__iter_move(__first1)); |
57 | __d.template __incr<value_type>(); |
58 | for (++__last2; ++__first1 != __last1; ++__last2) { |
59 | value_type* __j2 = __last2; |
60 | value_type* __i2 = __j2; |
61 | if (__comp(*__first1, *--__i2)) { |
62 | std::__construct_at(__j2, std::move(*__i2)); |
63 | __d.template __incr<value_type>(); |
64 | for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) |
65 | *__j2 = std::move(*__i2); |
66 | *__j2 = _Ops::__iter_move(__first1); |
67 | } else { |
68 | std::__construct_at(__j2, _Ops::__iter_move(__first1)); |
69 | __d.template __incr<value_type>(); |
70 | } |
71 | } |
72 | __h.release(); |
73 | } |
74 | } |
75 | |
76 | template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2> |
77 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct( |
78 | _InputIterator1 __first1, |
79 | _InputIterator1 __last1, |
80 | _InputIterator2 __first2, |
81 | _InputIterator2 __last2, |
82 | typename iterator_traits<_InputIterator1>::value_type* __result, |
83 | _Compare __comp) { |
84 | using _Ops = _IterOps<_AlgPolicy>; |
85 | |
86 | typedef typename iterator_traits<_InputIterator1>::value_type value_type; |
87 | __destruct_n __d(0); |
88 | unique_ptr<value_type, __destruct_n&> __h(__result, __d); |
89 | for (; true; ++__result) { |
90 | if (__first1 == __last1) { |
91 | for (; __first2 != __last2; ++__first2, (void)++__result, __d.template __incr<value_type>()) |
92 | std::__construct_at(__result, _Ops::__iter_move(__first2)); |
93 | __h.release(); |
94 | return; |
95 | } |
96 | if (__first2 == __last2) { |
97 | for (; __first1 != __last1; ++__first1, (void)++__result, __d.template __incr<value_type>()) |
98 | std::__construct_at(__result, _Ops::__iter_move(__first1)); |
99 | __h.release(); |
100 | return; |
101 | } |
102 | if (__comp(*__first2, *__first1)) { |
103 | std::__construct_at(__result, _Ops::__iter_move(__first2)); |
104 | __d.template __incr<value_type>(); |
105 | ++__first2; |
106 | } else { |
107 | std::__construct_at(__result, _Ops::__iter_move(__first1)); |
108 | __d.template __incr<value_type>(); |
109 | ++__first1; |
110 | } |
111 | } |
112 | } |
113 | |
114 | template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> |
115 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_assign( |
116 | _InputIterator1 __first1, |
117 | _InputIterator1 __last1, |
118 | _InputIterator2 __first2, |
119 | _InputIterator2 __last2, |
120 | _OutputIterator __result, |
121 | _Compare __comp) { |
122 | using _Ops = _IterOps<_AlgPolicy>; |
123 | |
124 | for (; __first1 != __last1; ++__result) { |
125 | if (__first2 == __last2) { |
126 | for (; __first1 != __last1; ++__first1, (void)++__result) |
127 | *__result = _Ops::__iter_move(__first1); |
128 | return; |
129 | } |
130 | if (__comp(*__first2, *__first1)) { |
131 | *__result = _Ops::__iter_move(__first2); |
132 | ++__first2; |
133 | } else { |
134 | *__result = _Ops::__iter_move(__first1); |
135 | ++__first1; |
136 | } |
137 | } |
138 | for (; __first2 != __last2; ++__first2, (void)++__result) |
139 | *__result = _Ops::__iter_move(__first2); |
140 | } |
141 | |
142 | template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> |
143 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort( |
144 | _RandomAccessIterator __first, |
145 | _RandomAccessIterator __last, |
146 | _Compare __comp, |
147 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, |
148 | typename iterator_traits<_RandomAccessIterator>::value_type* __buff, |
149 | ptrdiff_t __buff_size); |
150 | |
151 | template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> |
152 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move( |
153 | _RandomAccessIterator __first1, |
154 | _RandomAccessIterator __last1, |
155 | _Compare __comp, |
156 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, |
157 | typename iterator_traits<_RandomAccessIterator>::value_type* __first2) { |
158 | using _Ops = _IterOps<_AlgPolicy>; |
159 | |
160 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; |
161 | switch (__len) { |
162 | case 0: |
163 | return; |
164 | case 1: |
165 | std::__construct_at(__first2, _Ops::__iter_move(__first1)); |
166 | return; |
167 | case 2: |
168 | __destruct_n __d(0); |
169 | unique_ptr<value_type, __destruct_n&> __h2(__first2, __d); |
170 | if (__comp(*--__last1, *__first1)) { |
171 | std::__construct_at(__first2, _Ops::__iter_move(__last1)); |
172 | __d.template __incr<value_type>(); |
173 | ++__first2; |
174 | std::__construct_at(__first2, _Ops::__iter_move(__first1)); |
175 | } else { |
176 | std::__construct_at(__first2, _Ops::__iter_move(__first1)); |
177 | __d.template __incr<value_type>(); |
178 | ++__first2; |
179 | std::__construct_at(__first2, _Ops::__iter_move(__last1)); |
180 | } |
181 | __h2.release(); |
182 | return; |
183 | } |
184 | if (__len <= 8) { |
185 | std::__insertion_sort_move<_AlgPolicy, _Compare>(__first1, __last1, __first2, __comp); |
186 | return; |
187 | } |
188 | typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; |
189 | _RandomAccessIterator __m = __first1 + __l2; |
190 | std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2); |
191 | std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2); |
192 | std::__merge_move_construct<_AlgPolicy, _Compare>(__first1, __m, __m, __last1, __first2, __comp); |
193 | } |
194 | |
195 | template <class _Tp> |
196 | struct __stable_sort_switch { |
197 | static const unsigned value = 128 * is_trivially_copy_assignable<_Tp>::value; |
198 | }; |
199 | |
200 | #if _LIBCPP_STD_VER >= 17 |
201 | template <class _Tp> |
202 | _LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_min_bound() { |
203 | static_assert(__is_ordered_integer_representable_v<_Tp>); |
204 | if constexpr (sizeof(_Tp) == 1) { |
205 | return 1 << 8; |
206 | } |
207 | |
208 | return 1 << 10; |
209 | } |
210 | |
211 | template <class _Tp> |
212 | _LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_max_bound() { |
213 | static_assert(__is_ordered_integer_representable_v<_Tp>); |
214 | if constexpr (sizeof(_Tp) >= 8) { |
215 | return 1 << 15; |
216 | } |
217 | |
218 | return 1 << 16; |
219 | } |
220 | #endif // _LIBCPP_STD_VER >= 17 |
221 | |
222 | template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> |
223 | _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort( |
224 | _RandomAccessIterator __first, |
225 | _RandomAccessIterator __last, |
226 | _Compare __comp, |
227 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, |
228 | typename iterator_traits<_RandomAccessIterator>::value_type* __buff, |
229 | ptrdiff_t __buff_size) { |
230 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; |
231 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; |
232 | switch (__len) { |
233 | case 0: |
234 | case 1: |
235 | return; |
236 | case 2: |
237 | if (__comp(*--__last, *__first)) |
238 | _IterOps<_AlgPolicy>::iter_swap(__first, __last); |
239 | return; |
240 | } |
241 | if (__len <= static_cast<difference_type>(__stable_sort_switch<value_type>::value)) { |
242 | std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp); |
243 | return; |
244 | } |
245 | |
246 | #if _LIBCPP_STD_VER >= 17 |
247 | constexpr auto __default_comp = __desugars_to_v<__less_tag, _Compare, value_type, value_type >; |
248 | constexpr auto __radix_sortable = |
249 | __is_ordered_integer_representable_v<value_type> && |
250 | is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>; |
251 | if constexpr (__default_comp && __radix_sortable) { |
252 | if (__len <= __buff_size && __len >= static_cast<difference_type>(std::__radix_sort_min_bound<value_type>()) && |
253 | __len <= static_cast<difference_type>(std::__radix_sort_max_bound<value_type>())) { |
254 | if (__libcpp_is_constant_evaluated()) { |
255 | for (auto* __p = __buff; __p < __buff + __buff_size; ++__p) { |
256 | std::__construct_at(__p); |
257 | } |
258 | } |
259 | |
260 | std::__radix_sort(__first, __last, __buff); |
261 | return; |
262 | } |
263 | } |
264 | #endif // _LIBCPP_STD_VER >= 17 |
265 | |
266 | typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; |
267 | _RandomAccessIterator __m = __first + __l2; |
268 | if (__len <= __buff_size) { |
269 | __destruct_n __d(0); |
270 | unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); |
271 | std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff); |
272 | __d.__set(__l2, (value_type*)nullptr); |
273 | std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2); |
274 | __d.__set(__len, (value_type*)nullptr); |
275 | std::__merge_move_assign<_AlgPolicy, _Compare>( |
276 | __buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp); |
277 | // std::__merge<_Compare>(move_iterator<value_type*>(__buff), |
278 | // move_iterator<value_type*>(__buff + __l2), |
279 | // move_iterator<_RandomAccessIterator>(__buff + __l2), |
280 | // move_iterator<_RandomAccessIterator>(__buff + __len), |
281 | // __first, __comp); |
282 | return; |
283 | } |
284 | std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size); |
285 | std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); |
286 | std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); |
287 | } |
288 | |
289 | template <class _AlgPolicy, class _RandomAccessIterator, class _Compare> |
290 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void |
291 | __stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { |
292 | using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; |
293 | using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; |
294 | |
295 | difference_type __len = __last - __first; |
296 | __unique_temporary_buffer<value_type> __unique_buf; |
297 | pair<value_type*, ptrdiff_t> __buf(0, 0); |
298 | if (__len > static_cast<difference_type>(__stable_sort_switch<value_type>::value)) { |
299 | __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len); |
300 | __buf.first = __unique_buf.get(); |
301 | __buf.second = __unique_buf.get_deleter().__count_; |
302 | } |
303 | |
304 | std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second); |
305 | std::__check_strict_weak_ordering_sorted(__first, __last, __comp); |
306 | } |
307 | |
308 | template <class _RandomAccessIterator, class _Compare> |
309 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void |
310 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { |
311 | std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp); |
312 | } |
313 | |
314 | template <class _RandomAccessIterator> |
315 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void |
316 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { |
317 | std::stable_sort(__first, __last, __less<>()); |
318 | } |
319 | |
320 | _LIBCPP_END_NAMESPACE_STD |
321 | _LIBCPP_POP_MACROS |
322 | |
323 | #endif // _LIBCPP___ALGORITHM_STABLE_SORT_H |
324 |
Warning: This file is not a C or C++ file. It does not have highlighting.