1134723edSLouis Dionne //===----------------------------------------------------------------------===// 2134723edSLouis Dionne // 3134723edSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4134723edSLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 5134723edSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6134723edSLouis Dionne // 7134723edSLouis Dionne //===----------------------------------------------------------------------===// 8134723edSLouis Dionne 9134723edSLouis Dionne #ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H 10134723edSLouis Dionne #define _LIBCPP___ALGORITHM_STABLE_PARTITION_H 11134723edSLouis Dionne 128ed702b8SKonstantin Varlamov #include <__algorithm/iterator_operations.h> 13134723edSLouis Dionne #include <__algorithm/rotate.h> 144d81a46fSArthur O'Dwyer #include <__config> 15*e99c4906SNikolas Klauser #include <__cstddef/ptrdiff_t.h> 163cd4531bSNikolas Klauser #include <__iterator/advance.h> 173cd4531bSNikolas Klauser #include <__iterator/distance.h> 18134723edSLouis Dionne #include <__iterator/iterator_traits.h> 19d5e26775SNikolas Klauser #include <__memory/destruct_n.h> 20d5e26775SNikolas Klauser #include <__memory/unique_ptr.h> 2194e7c0b0SA. Jiang #include <__memory/unique_temporary_buffer.h> 2209e3a360SLouis Dionne #include <__type_traits/remove_cvref.h> 237712ae0aSMark de Wever #include <__utility/move.h> 24d5e26775SNikolas Klauser #include <__utility/pair.h> 25134723edSLouis Dionne 26134723edSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 27134723edSLouis Dionne # pragma GCC system_header 28134723edSLouis Dionne #endif 29134723edSLouis Dionne 307b462251SLouis Dionne _LIBCPP_PUSH_MACROS 317b462251SLouis Dionne #include <__undef_macros> 327b462251SLouis Dionne 33134723edSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 34134723edSLouis Dionne 358ed702b8SKonstantin Varlamov template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair> 369783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( 379783f28cSLouis Dionne _ForwardIterator __first, 389783f28cSLouis Dionne _ForwardIterator __last, 399783f28cSLouis Dionne _Predicate __pred, 409783f28cSLouis Dionne _Distance __len, 419783f28cSLouis Dionne _Pair __p, 429783f28cSLouis Dionne forward_iterator_tag __fit) { 438ed702b8SKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 448ed702b8SKonstantin Varlamov 45134723edSLouis Dionne // *__first is known to be false 46134723edSLouis Dionne // __len >= 1 47134723edSLouis Dionne if (__len == 1) 48134723edSLouis Dionne return __first; 499783f28cSLouis Dionne if (__len == 2) { 50134723edSLouis Dionne _ForwardIterator __m = __first; 519783f28cSLouis Dionne if (__pred(*++__m)) { 528ed702b8SKonstantin Varlamov _Ops::iter_swap(__first, __m); 53134723edSLouis Dionne return __m; 54134723edSLouis Dionne } 55134723edSLouis Dionne return __first; 56134723edSLouis Dionne } 579783f28cSLouis Dionne if (__len <= __p.second) { // The buffer is big enough to use 58134723edSLouis Dionne typedef typename iterator_traits<_ForwardIterator>::value_type value_type; 59134723edSLouis Dionne __destruct_n __d(0); 60134723edSLouis Dionne unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); 61134723edSLouis Dionne // Move the falses into the temporary buffer, and the trues to the front of the line 62134723edSLouis Dionne // Update __first to always point to the end of the trues 63134723edSLouis Dionne value_type* __t = __p.first; 648ed702b8SKonstantin Varlamov ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); 65134723edSLouis Dionne __d.template __incr<value_type>(); 66134723edSLouis Dionne ++__t; 67134723edSLouis Dionne _ForwardIterator __i = __first; 689783f28cSLouis Dionne while (++__i != __last) { 699783f28cSLouis Dionne if (__pred(*__i)) { 708ed702b8SKonstantin Varlamov *__first = _Ops::__iter_move(__i); 71134723edSLouis Dionne ++__first; 729783f28cSLouis Dionne } else { 738ed702b8SKonstantin Varlamov ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); 74134723edSLouis Dionne __d.template __incr<value_type>(); 75134723edSLouis Dionne ++__t; 76134723edSLouis Dionne } 77134723edSLouis Dionne } 78134723edSLouis Dionne // All trues now at start of range, all falses in buffer 79134723edSLouis Dionne // Move falses back into range, but don't mess up __first which points to first false 80134723edSLouis Dionne __i = __first; 81134723edSLouis Dionne for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i) 828ed702b8SKonstantin Varlamov *__i = _Ops::__iter_move(__t2); 83134723edSLouis Dionne // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer 84134723edSLouis Dionne return __first; 85134723edSLouis Dionne } 86134723edSLouis Dionne // Else not enough buffer, do in place 87134723edSLouis Dionne // __len >= 3 88134723edSLouis Dionne _ForwardIterator __m = __first; 89134723edSLouis Dionne _Distance __len2 = __len / 2; // __len2 >= 2 908ed702b8SKonstantin Varlamov _Ops::advance(__m, __len2); 91134723edSLouis Dionne // recurse on [__first, __m), *__first know to be false 92134723edSLouis Dionne // F????????????????? 93134723edSLouis Dionne // f m l 949783f28cSLouis Dionne _ForwardIterator __first_false = 959783f28cSLouis Dionne std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m, __pred, __len2, __p, __fit); 96134723edSLouis Dionne // TTTFFFFF?????????? 97134723edSLouis Dionne // f ff m l 98134723edSLouis Dionne // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true 99134723edSLouis Dionne _ForwardIterator __m1 = __m; 100134723edSLouis Dionne _ForwardIterator __second_false = __last; 101134723edSLouis Dionne _Distance __len_half = __len - __len2; 1029783f28cSLouis Dionne while (__pred(*__m1)) { 103134723edSLouis Dionne if (++__m1 == __last) 104134723edSLouis Dionne goto __second_half_done; 105134723edSLouis Dionne --__len_half; 106134723edSLouis Dionne } 107134723edSLouis Dionne // TTTFFFFFTTTF?????? 108134723edSLouis Dionne // f ff m m1 l 1099783f28cSLouis Dionne __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __fit); 110134723edSLouis Dionne __second_half_done: 111134723edSLouis Dionne // TTTFFFFFTTTTTFFFFF 112134723edSLouis Dionne // f ff m sf l 11336c746caSKonstantin Varlamov return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; 114134723edSLouis Dionne // TTTTTTTTFFFFFFFFFF 115134723edSLouis Dionne // | 116134723edSLouis Dionne } 117134723edSLouis Dionne 1188ed702b8SKonstantin Varlamov template <class _AlgPolicy, class _Predicate, class _ForwardIterator> 11980c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI _ForwardIterator 1209783f28cSLouis Dionne __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) { 121b935ab8eSNikolas Klauser typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; 122b935ab8eSNikolas Klauser typedef typename iterator_traits<_ForwardIterator>::value_type value_type; 123b935ab8eSNikolas Klauser 124b935ab8eSNikolas Klauser const difference_type __alloc_limit = 3; // might want to make this a function of trivial assignment 125134723edSLouis Dionne // Either prove all true and return __first or point to first false 1269783f28cSLouis Dionne while (true) { 127134723edSLouis Dionne if (__first == __last) 128134723edSLouis Dionne return __first; 129134723edSLouis Dionne if (!__pred(*__first)) 130134723edSLouis Dionne break; 131134723edSLouis Dionne ++__first; 132134723edSLouis Dionne } 133134723edSLouis Dionne // We now have a reduced range [__first, __last) 134134723edSLouis Dionne // *__first is known to be false 1358ed702b8SKonstantin Varlamov difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last); 13694e7c0b0SA. Jiang __unique_temporary_buffer<value_type> __unique_buf; 137f13e1a65SLouis Dionne pair<value_type*, ptrdiff_t> __p(0, 0); 1389783f28cSLouis Dionne if (__len >= __alloc_limit) { 13994e7c0b0SA. Jiang __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len); 14094e7c0b0SA. Jiang __p.first = __unique_buf.get(); 14194e7c0b0SA. Jiang __p.second = __unique_buf.get_deleter().__count_; 142f13e1a65SLouis Dionne } 1438ed702b8SKonstantin Varlamov return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( 144f13e1a65SLouis Dionne std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag()); 145134723edSLouis Dionne } 146134723edSLouis Dionne 1478ed702b8SKonstantin Varlamov template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair> 1489783f28cSLouis Dionne _BidirectionalIterator __stable_partition_impl( 1499783f28cSLouis Dionne _BidirectionalIterator __first, 1509783f28cSLouis Dionne _BidirectionalIterator __last, 1519783f28cSLouis Dionne _Predicate __pred, 1529783f28cSLouis Dionne _Distance __len, 1539783f28cSLouis Dionne _Pair __p, 1549783f28cSLouis Dionne bidirectional_iterator_tag __bit) { 1558ed702b8SKonstantin Varlamov using _Ops = _IterOps<_AlgPolicy>; 1568ed702b8SKonstantin Varlamov 157134723edSLouis Dionne // *__first is known to be false 158134723edSLouis Dionne // *__last is known to be true 159134723edSLouis Dionne // __len >= 2 1609783f28cSLouis Dionne if (__len == 2) { 1618ed702b8SKonstantin Varlamov _Ops::iter_swap(__first, __last); 162134723edSLouis Dionne return __last; 163134723edSLouis Dionne } 1649783f28cSLouis Dionne if (__len == 3) { 165134723edSLouis Dionne _BidirectionalIterator __m = __first; 1669783f28cSLouis Dionne if (__pred(*++__m)) { 1678ed702b8SKonstantin Varlamov _Ops::iter_swap(__first, __m); 1688ed702b8SKonstantin Varlamov _Ops::iter_swap(__m, __last); 169134723edSLouis Dionne return __last; 170134723edSLouis Dionne } 1718ed702b8SKonstantin Varlamov _Ops::iter_swap(__m, __last); 1728ed702b8SKonstantin Varlamov _Ops::iter_swap(__first, __m); 173134723edSLouis Dionne return __m; 174134723edSLouis Dionne } 1759783f28cSLouis Dionne if (__len <= __p.second) { // The buffer is big enough to use 176134723edSLouis Dionne typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 177134723edSLouis Dionne __destruct_n __d(0); 178134723edSLouis Dionne unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); 179134723edSLouis Dionne // Move the falses into the temporary buffer, and the trues to the front of the line 180134723edSLouis Dionne // Update __first to always point to the end of the trues 181134723edSLouis Dionne value_type* __t = __p.first; 1828ed702b8SKonstantin Varlamov ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); 183134723edSLouis Dionne __d.template __incr<value_type>(); 184134723edSLouis Dionne ++__t; 185134723edSLouis Dionne _BidirectionalIterator __i = __first; 1869783f28cSLouis Dionne while (++__i != __last) { 1879783f28cSLouis Dionne if (__pred(*__i)) { 1888ed702b8SKonstantin Varlamov *__first = _Ops::__iter_move(__i); 189134723edSLouis Dionne ++__first; 1909783f28cSLouis Dionne } else { 1918ed702b8SKonstantin Varlamov ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); 192134723edSLouis Dionne __d.template __incr<value_type>(); 193134723edSLouis Dionne ++__t; 194134723edSLouis Dionne } 195134723edSLouis Dionne } 196134723edSLouis Dionne // move *__last, known to be true 1978ed702b8SKonstantin Varlamov *__first = _Ops::__iter_move(__i); 198134723edSLouis Dionne __i = ++__first; 199134723edSLouis Dionne // All trues now at start of range, all falses in buffer 200134723edSLouis Dionne // Move falses back into range, but don't mess up __first which points to first false 201134723edSLouis Dionne for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i) 2028ed702b8SKonstantin Varlamov *__i = _Ops::__iter_move(__t2); 203134723edSLouis Dionne // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer 204134723edSLouis Dionne return __first; 205134723edSLouis Dionne } 206134723edSLouis Dionne // Else not enough buffer, do in place 207134723edSLouis Dionne // __len >= 4 208134723edSLouis Dionne _BidirectionalIterator __m = __first; 209134723edSLouis Dionne _Distance __len2 = __len / 2; // __len2 >= 2 2108ed702b8SKonstantin Varlamov _Ops::advance(__m, __len2); 211134723edSLouis Dionne // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false 212134723edSLouis Dionne // F????????????????T 213134723edSLouis Dionne // f m l 214134723edSLouis Dionne _BidirectionalIterator __m1 = __m; 215134723edSLouis Dionne _BidirectionalIterator __first_false = __first; 216134723edSLouis Dionne _Distance __len_half = __len2; 2179783f28cSLouis Dionne while (!__pred(*--__m1)) { 218134723edSLouis Dionne if (__m1 == __first) 219134723edSLouis Dionne goto __first_half_done; 220134723edSLouis Dionne --__len_half; 221134723edSLouis Dionne } 222134723edSLouis Dionne // F???TFFF?????????T 223134723edSLouis Dionne // f m1 m l 2249783f28cSLouis Dionne __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m1, __pred, __len_half, __p, __bit); 225134723edSLouis Dionne __first_half_done: 226134723edSLouis Dionne // TTTFFFFF?????????T 227134723edSLouis Dionne // f ff m l 228134723edSLouis Dionne // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true 229134723edSLouis Dionne __m1 = __m; 230134723edSLouis Dionne _BidirectionalIterator __second_false = __last; 231134723edSLouis Dionne ++__second_false; 232134723edSLouis Dionne __len_half = __len - __len2; 2339783f28cSLouis Dionne while (__pred(*__m1)) { 234134723edSLouis Dionne if (++__m1 == __last) 235134723edSLouis Dionne goto __second_half_done; 236134723edSLouis Dionne --__len_half; 237134723edSLouis Dionne } 238134723edSLouis Dionne // TTTFFFFFTTTF?????T 239134723edSLouis Dionne // f ff m m1 l 2409783f28cSLouis Dionne __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __bit); 241134723edSLouis Dionne __second_half_done: 242134723edSLouis Dionne // TTTFFFFFTTTTTFFFFF 243134723edSLouis Dionne // f ff m sf l 24436c746caSKonstantin Varlamov return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; 245134723edSLouis Dionne // TTTTTTTTFFFFFFFFFF 246134723edSLouis Dionne // | 247134723edSLouis Dionne } 248134723edSLouis Dionne 2498ed702b8SKonstantin Varlamov template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator> 2509783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl( 2519783f28cSLouis Dionne _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) { 252134723edSLouis Dionne typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; 253134723edSLouis Dionne typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 254134723edSLouis Dionne const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment 255134723edSLouis Dionne // Either prove all true and return __first or point to first false 2569783f28cSLouis Dionne while (true) { 257134723edSLouis Dionne if (__first == __last) 258134723edSLouis Dionne return __first; 259134723edSLouis Dionne if (!__pred(*__first)) 260134723edSLouis Dionne break; 261134723edSLouis Dionne ++__first; 262134723edSLouis Dionne } 263134723edSLouis Dionne // __first points to first false, everything prior to __first is already set. 264134723edSLouis Dionne // Either prove [__first, __last) is all false and return __first, or point __last to last true 2659783f28cSLouis Dionne do { 266134723edSLouis Dionne if (__first == --__last) 267134723edSLouis Dionne return __first; 268134723edSLouis Dionne } while (!__pred(*__last)); 269134723edSLouis Dionne // We now have a reduced range [__first, __last] 270134723edSLouis Dionne // *__first is known to be false 271134723edSLouis Dionne // *__last is known to be true 272134723edSLouis Dionne // __len >= 2 2738ed702b8SKonstantin Varlamov difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1; 27494e7c0b0SA. Jiang __unique_temporary_buffer<value_type> __unique_buf; 275f13e1a65SLouis Dionne pair<value_type*, ptrdiff_t> __p(0, 0); 2769783f28cSLouis Dionne if (__len >= __alloc_limit) { 27794e7c0b0SA. Jiang __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len); 27894e7c0b0SA. Jiang __p.first = __unique_buf.get(); 27994e7c0b0SA. Jiang __p.second = __unique_buf.get_deleter().__count_; 280f13e1a65SLouis Dionne } 2818ed702b8SKonstantin Varlamov return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( 282f13e1a65SLouis Dionne std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag()); 2838ed702b8SKonstantin Varlamov } 2848ed702b8SKonstantin Varlamov 2858ed702b8SKonstantin Varlamov template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory> 2869783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition( 2878ed702b8SKonstantin Varlamov _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) { 2885fab33afSNikolas Klauser return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>( 2898ed702b8SKonstantin Varlamov std::move(__first), std::move(__last), __pred, __iter_category); 290134723edSLouis Dionne } 291134723edSLouis Dionne 292134723edSLouis Dionne template <class _ForwardIterator, class _Predicate> 2939783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 2949783f28cSLouis Dionne stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { 2958ed702b8SKonstantin Varlamov using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; 2968ed702b8SKonstantin Varlamov return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>( 2978ed702b8SKonstantin Varlamov std::move(__first), std::move(__last), __pred, _IterCategory()); 298134723edSLouis Dionne } 299134723edSLouis Dionne 300134723edSLouis Dionne _LIBCPP_END_NAMESPACE_STD 301134723edSLouis Dionne 3027b462251SLouis Dionne _LIBCPP_POP_MACROS 3037b462251SLouis Dionne 304134723edSLouis Dionne #endif // _LIBCPP___ALGORITHM_STABLE_PARTITION_H 305