176d0caaeSpatrick //===----------------------------------------------------------------------===//
276d0caaeSpatrick //
376d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
476d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
576d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
676d0caaeSpatrick //
776d0caaeSpatrick //===----------------------------------------------------------------------===//
876d0caaeSpatrick
976d0caaeSpatrick #ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H
1076d0caaeSpatrick #define _LIBCPP___ALGORITHM_STABLE_PARTITION_H
1176d0caaeSpatrick
12*4bdff4beSrobert #include <__algorithm/iterator_operations.h>
1376d0caaeSpatrick #include <__algorithm/rotate.h>
14*4bdff4beSrobert #include <__config>
15*4bdff4beSrobert #include <__iterator/advance.h>
16*4bdff4beSrobert #include <__iterator/distance.h>
1776d0caaeSpatrick #include <__iterator/iterator_traits.h>
18*4bdff4beSrobert #include <__memory/destruct_n.h>
19*4bdff4beSrobert #include <__memory/temporary_buffer.h>
20*4bdff4beSrobert #include <__memory/unique_ptr.h>
21*4bdff4beSrobert #include <__utility/move.h>
22*4bdff4beSrobert #include <__utility/pair.h>
23*4bdff4beSrobert #include <new>
24*4bdff4beSrobert #include <type_traits>
2576d0caaeSpatrick
2676d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2776d0caaeSpatrick # pragma GCC system_header
2876d0caaeSpatrick #endif
2976d0caaeSpatrick
3076d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD
3176d0caaeSpatrick
32*4bdff4beSrobert template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair>
33*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _ForwardIterator
__stable_partition_impl(_ForwardIterator __first,_ForwardIterator __last,_Predicate __pred,_Distance __len,_Pair __p,forward_iterator_tag __fit)34*4bdff4beSrobert __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
3576d0caaeSpatrick _Distance __len, _Pair __p, forward_iterator_tag __fit)
3676d0caaeSpatrick {
37*4bdff4beSrobert using _Ops = _IterOps<_AlgPolicy>;
38*4bdff4beSrobert
3976d0caaeSpatrick // *__first is known to be false
4076d0caaeSpatrick // __len >= 1
4176d0caaeSpatrick if (__len == 1)
4276d0caaeSpatrick return __first;
4376d0caaeSpatrick if (__len == 2)
4476d0caaeSpatrick {
4576d0caaeSpatrick _ForwardIterator __m = __first;
4676d0caaeSpatrick if (__pred(*++__m))
4776d0caaeSpatrick {
48*4bdff4beSrobert _Ops::iter_swap(__first, __m);
4976d0caaeSpatrick return __m;
5076d0caaeSpatrick }
5176d0caaeSpatrick return __first;
5276d0caaeSpatrick }
5376d0caaeSpatrick if (__len <= __p.second)
5476d0caaeSpatrick { // The buffer is big enough to use
5576d0caaeSpatrick typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
5676d0caaeSpatrick __destruct_n __d(0);
5776d0caaeSpatrick unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
5876d0caaeSpatrick // Move the falses into the temporary buffer, and the trues to the front of the line
5976d0caaeSpatrick // Update __first to always point to the end of the trues
6076d0caaeSpatrick value_type* __t = __p.first;
61*4bdff4beSrobert ::new ((void*)__t) value_type(_Ops::__iter_move(__first));
6276d0caaeSpatrick __d.template __incr<value_type>();
6376d0caaeSpatrick ++__t;
6476d0caaeSpatrick _ForwardIterator __i = __first;
6576d0caaeSpatrick while (++__i != __last)
6676d0caaeSpatrick {
6776d0caaeSpatrick if (__pred(*__i))
6876d0caaeSpatrick {
69*4bdff4beSrobert *__first = _Ops::__iter_move(__i);
7076d0caaeSpatrick ++__first;
7176d0caaeSpatrick }
7276d0caaeSpatrick else
7376d0caaeSpatrick {
74*4bdff4beSrobert ::new ((void*)__t) value_type(_Ops::__iter_move(__i));
7576d0caaeSpatrick __d.template __incr<value_type>();
7676d0caaeSpatrick ++__t;
7776d0caaeSpatrick }
7876d0caaeSpatrick }
7976d0caaeSpatrick // All trues now at start of range, all falses in buffer
8076d0caaeSpatrick // Move falses back into range, but don't mess up __first which points to first false
8176d0caaeSpatrick __i = __first;
8276d0caaeSpatrick for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i)
83*4bdff4beSrobert *__i = _Ops::__iter_move(__t2);
8476d0caaeSpatrick // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer
8576d0caaeSpatrick return __first;
8676d0caaeSpatrick }
8776d0caaeSpatrick // Else not enough buffer, do in place
8876d0caaeSpatrick // __len >= 3
8976d0caaeSpatrick _ForwardIterator __m = __first;
9076d0caaeSpatrick _Distance __len2 = __len / 2; // __len2 >= 2
91*4bdff4beSrobert _Ops::advance(__m, __len2);
9276d0caaeSpatrick // recurse on [__first, __m), *__first know to be false
9376d0caaeSpatrick // F?????????????????
9476d0caaeSpatrick // f m l
95*4bdff4beSrobert _ForwardIterator __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
96*4bdff4beSrobert __first, __m, __pred, __len2, __p, __fit);
9776d0caaeSpatrick // TTTFFFFF??????????
9876d0caaeSpatrick // f ff m l
9976d0caaeSpatrick // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true
10076d0caaeSpatrick _ForwardIterator __m1 = __m;
10176d0caaeSpatrick _ForwardIterator __second_false = __last;
10276d0caaeSpatrick _Distance __len_half = __len - __len2;
10376d0caaeSpatrick while (__pred(*__m1))
10476d0caaeSpatrick {
10576d0caaeSpatrick if (++__m1 == __last)
10676d0caaeSpatrick goto __second_half_done;
10776d0caaeSpatrick --__len_half;
10876d0caaeSpatrick }
10976d0caaeSpatrick // TTTFFFFFTTTF??????
11076d0caaeSpatrick // f ff m m1 l
111*4bdff4beSrobert __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
112*4bdff4beSrobert __m1, __last, __pred, __len_half, __p, __fit);
11376d0caaeSpatrick __second_half_done:
11476d0caaeSpatrick // TTTFFFFFTTTTTFFFFF
11576d0caaeSpatrick // f ff m sf l
116*4bdff4beSrobert return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
11776d0caaeSpatrick // TTTTTTTTFFFFFFFFFF
11876d0caaeSpatrick // |
11976d0caaeSpatrick }
12076d0caaeSpatrick
121*4bdff4beSrobert template <class _AlgPolicy, class _Predicate, class _ForwardIterator>
122*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _ForwardIterator
__stable_partition_impl(_ForwardIterator __first,_ForwardIterator __last,_Predicate __pred,forward_iterator_tag)123*4bdff4beSrobert __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
12476d0caaeSpatrick forward_iterator_tag)
12576d0caaeSpatrick {
12676d0caaeSpatrick const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment
12776d0caaeSpatrick // Either prove all true and return __first or point to first false
12876d0caaeSpatrick while (true)
12976d0caaeSpatrick {
13076d0caaeSpatrick if (__first == __last)
13176d0caaeSpatrick return __first;
13276d0caaeSpatrick if (!__pred(*__first))
13376d0caaeSpatrick break;
13476d0caaeSpatrick ++__first;
13576d0caaeSpatrick }
13676d0caaeSpatrick // We now have a reduced range [__first, __last)
13776d0caaeSpatrick // *__first is known to be false
13876d0caaeSpatrick typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
13976d0caaeSpatrick typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
140*4bdff4beSrobert difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last);
14176d0caaeSpatrick pair<value_type*, ptrdiff_t> __p(0, 0);
14276d0caaeSpatrick unique_ptr<value_type, __return_temporary_buffer> __h;
14376d0caaeSpatrick if (__len >= __alloc_limit)
14476d0caaeSpatrick {
145*4bdff4beSrobert // TODO: Remove the use of std::get_temporary_buffer
146*4bdff4beSrobert _LIBCPP_SUPPRESS_DEPRECATED_PUSH
14776d0caaeSpatrick __p = _VSTD::get_temporary_buffer<value_type>(__len);
148*4bdff4beSrobert _LIBCPP_SUPPRESS_DEPRECATED_POP
14976d0caaeSpatrick __h.reset(__p.first);
15076d0caaeSpatrick }
151*4bdff4beSrobert return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
152*4bdff4beSrobert std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag());
15376d0caaeSpatrick }
15476d0caaeSpatrick
155*4bdff4beSrobert template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair>
15676d0caaeSpatrick _BidirectionalIterator
__stable_partition_impl(_BidirectionalIterator __first,_BidirectionalIterator __last,_Predicate __pred,_Distance __len,_Pair __p,bidirectional_iterator_tag __bit)157*4bdff4beSrobert __stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred,
15876d0caaeSpatrick _Distance __len, _Pair __p, bidirectional_iterator_tag __bit)
15976d0caaeSpatrick {
160*4bdff4beSrobert using _Ops = _IterOps<_AlgPolicy>;
161*4bdff4beSrobert
16276d0caaeSpatrick // *__first is known to be false
16376d0caaeSpatrick // *__last is known to be true
16476d0caaeSpatrick // __len >= 2
16576d0caaeSpatrick if (__len == 2)
16676d0caaeSpatrick {
167*4bdff4beSrobert _Ops::iter_swap(__first, __last);
16876d0caaeSpatrick return __last;
16976d0caaeSpatrick }
17076d0caaeSpatrick if (__len == 3)
17176d0caaeSpatrick {
17276d0caaeSpatrick _BidirectionalIterator __m = __first;
17376d0caaeSpatrick if (__pred(*++__m))
17476d0caaeSpatrick {
175*4bdff4beSrobert _Ops::iter_swap(__first, __m);
176*4bdff4beSrobert _Ops::iter_swap(__m, __last);
17776d0caaeSpatrick return __last;
17876d0caaeSpatrick }
179*4bdff4beSrobert _Ops::iter_swap(__m, __last);
180*4bdff4beSrobert _Ops::iter_swap(__first, __m);
18176d0caaeSpatrick return __m;
18276d0caaeSpatrick }
18376d0caaeSpatrick if (__len <= __p.second)
18476d0caaeSpatrick { // The buffer is big enough to use
18576d0caaeSpatrick typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
18676d0caaeSpatrick __destruct_n __d(0);
18776d0caaeSpatrick unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
18876d0caaeSpatrick // Move the falses into the temporary buffer, and the trues to the front of the line
18976d0caaeSpatrick // Update __first to always point to the end of the trues
19076d0caaeSpatrick value_type* __t = __p.first;
191*4bdff4beSrobert ::new ((void*)__t) value_type(_Ops::__iter_move(__first));
19276d0caaeSpatrick __d.template __incr<value_type>();
19376d0caaeSpatrick ++__t;
19476d0caaeSpatrick _BidirectionalIterator __i = __first;
19576d0caaeSpatrick while (++__i != __last)
19676d0caaeSpatrick {
19776d0caaeSpatrick if (__pred(*__i))
19876d0caaeSpatrick {
199*4bdff4beSrobert *__first = _Ops::__iter_move(__i);
20076d0caaeSpatrick ++__first;
20176d0caaeSpatrick }
20276d0caaeSpatrick else
20376d0caaeSpatrick {
204*4bdff4beSrobert ::new ((void*)__t) value_type(_Ops::__iter_move(__i));
20576d0caaeSpatrick __d.template __incr<value_type>();
20676d0caaeSpatrick ++__t;
20776d0caaeSpatrick }
20876d0caaeSpatrick }
20976d0caaeSpatrick // move *__last, known to be true
210*4bdff4beSrobert *__first = _Ops::__iter_move(__i);
21176d0caaeSpatrick __i = ++__first;
21276d0caaeSpatrick // All trues now at start of range, all falses in buffer
21376d0caaeSpatrick // Move falses back into range, but don't mess up __first which points to first false
21476d0caaeSpatrick for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i)
215*4bdff4beSrobert *__i = _Ops::__iter_move(__t2);
21676d0caaeSpatrick // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer
21776d0caaeSpatrick return __first;
21876d0caaeSpatrick }
21976d0caaeSpatrick // Else not enough buffer, do in place
22076d0caaeSpatrick // __len >= 4
22176d0caaeSpatrick _BidirectionalIterator __m = __first;
22276d0caaeSpatrick _Distance __len2 = __len / 2; // __len2 >= 2
223*4bdff4beSrobert _Ops::advance(__m, __len2);
22476d0caaeSpatrick // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false
22576d0caaeSpatrick // F????????????????T
22676d0caaeSpatrick // f m l
22776d0caaeSpatrick _BidirectionalIterator __m1 = __m;
22876d0caaeSpatrick _BidirectionalIterator __first_false = __first;
22976d0caaeSpatrick _Distance __len_half = __len2;
23076d0caaeSpatrick while (!__pred(*--__m1))
23176d0caaeSpatrick {
23276d0caaeSpatrick if (__m1 == __first)
23376d0caaeSpatrick goto __first_half_done;
23476d0caaeSpatrick --__len_half;
23576d0caaeSpatrick }
23676d0caaeSpatrick // F???TFFF?????????T
23776d0caaeSpatrick // f m1 m l
238*4bdff4beSrobert __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
239*4bdff4beSrobert __first, __m1, __pred, __len_half, __p, __bit);
24076d0caaeSpatrick __first_half_done:
24176d0caaeSpatrick // TTTFFFFF?????????T
24276d0caaeSpatrick // f ff m l
24376d0caaeSpatrick // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true
24476d0caaeSpatrick __m1 = __m;
24576d0caaeSpatrick _BidirectionalIterator __second_false = __last;
24676d0caaeSpatrick ++__second_false;
24776d0caaeSpatrick __len_half = __len - __len2;
24876d0caaeSpatrick while (__pred(*__m1))
24976d0caaeSpatrick {
25076d0caaeSpatrick if (++__m1 == __last)
25176d0caaeSpatrick goto __second_half_done;
25276d0caaeSpatrick --__len_half;
25376d0caaeSpatrick }
25476d0caaeSpatrick // TTTFFFFFTTTF?????T
25576d0caaeSpatrick // f ff m m1 l
256*4bdff4beSrobert __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
257*4bdff4beSrobert __m1, __last, __pred, __len_half, __p, __bit);
25876d0caaeSpatrick __second_half_done:
25976d0caaeSpatrick // TTTFFFFFTTTTTFFFFF
26076d0caaeSpatrick // f ff m sf l
261*4bdff4beSrobert return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
26276d0caaeSpatrick // TTTTTTTTFFFFFFFFFF
26376d0caaeSpatrick // |
26476d0caaeSpatrick }
26576d0caaeSpatrick
266*4bdff4beSrobert template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator>
267*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator
__stable_partition_impl(_BidirectionalIterator __first,_BidirectionalIterator __last,_Predicate __pred,bidirectional_iterator_tag)268*4bdff4beSrobert __stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred,
26976d0caaeSpatrick bidirectional_iterator_tag)
27076d0caaeSpatrick {
27176d0caaeSpatrick typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
27276d0caaeSpatrick typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
27376d0caaeSpatrick const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment
27476d0caaeSpatrick // Either prove all true and return __first or point to first false
27576d0caaeSpatrick while (true)
27676d0caaeSpatrick {
27776d0caaeSpatrick if (__first == __last)
27876d0caaeSpatrick return __first;
27976d0caaeSpatrick if (!__pred(*__first))
28076d0caaeSpatrick break;
28176d0caaeSpatrick ++__first;
28276d0caaeSpatrick }
28376d0caaeSpatrick // __first points to first false, everything prior to __first is already set.
28476d0caaeSpatrick // Either prove [__first, __last) is all false and return __first, or point __last to last true
28576d0caaeSpatrick do
28676d0caaeSpatrick {
28776d0caaeSpatrick if (__first == --__last)
28876d0caaeSpatrick return __first;
28976d0caaeSpatrick } while (!__pred(*__last));
29076d0caaeSpatrick // We now have a reduced range [__first, __last]
29176d0caaeSpatrick // *__first is known to be false
29276d0caaeSpatrick // *__last is known to be true
29376d0caaeSpatrick // __len >= 2
294*4bdff4beSrobert difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1;
29576d0caaeSpatrick pair<value_type*, ptrdiff_t> __p(0, 0);
29676d0caaeSpatrick unique_ptr<value_type, __return_temporary_buffer> __h;
29776d0caaeSpatrick if (__len >= __alloc_limit)
29876d0caaeSpatrick {
299*4bdff4beSrobert // TODO: Remove the use of std::get_temporary_buffer
300*4bdff4beSrobert _LIBCPP_SUPPRESS_DEPRECATED_PUSH
30176d0caaeSpatrick __p = _VSTD::get_temporary_buffer<value_type>(__len);
302*4bdff4beSrobert _LIBCPP_SUPPRESS_DEPRECATED_POP
30376d0caaeSpatrick __h.reset(__p.first);
30476d0caaeSpatrick }
305*4bdff4beSrobert return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
306*4bdff4beSrobert std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag());
307*4bdff4beSrobert }
308*4bdff4beSrobert
309*4bdff4beSrobert template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory>
310*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
__stable_partition(_ForwardIterator __first,_ForwardIterator __last,_Predicate && __pred,_IterCategory __iter_category)311*4bdff4beSrobert _ForwardIterator __stable_partition(
312*4bdff4beSrobert _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) {
313*4bdff4beSrobert return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>(
314*4bdff4beSrobert std::move(__first), std::move(__last), __pred, __iter_category);
31576d0caaeSpatrick }
31676d0caaeSpatrick
31776d0caaeSpatrick template <class _ForwardIterator, class _Predicate>
31876d0caaeSpatrick inline _LIBCPP_INLINE_VISIBILITY
31976d0caaeSpatrick _ForwardIterator
stable_partition(_ForwardIterator __first,_ForwardIterator __last,_Predicate __pred)32076d0caaeSpatrick stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
32176d0caaeSpatrick {
322*4bdff4beSrobert using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
323*4bdff4beSrobert return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>(
324*4bdff4beSrobert std::move(__first), std::move(__last), __pred, _IterCategory());
32576d0caaeSpatrick }
32676d0caaeSpatrick
32776d0caaeSpatrick _LIBCPP_END_NAMESPACE_STD
32876d0caaeSpatrick
32976d0caaeSpatrick #endif // _LIBCPP___ALGORITHM_STABLE_PARTITION_H
330