1e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 2e78f53d1SNikolas Klauser // 3e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e78f53d1SNikolas Klauser // 7e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 8e78f53d1SNikolas Klauser 9*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___ALGORITHM_STABLE_PARTITION_H 10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___ALGORITHM_STABLE_PARTITION_H 11e78f53d1SNikolas Klauser 1273fbae83SNikolas Klauser #include <__cxx03/__algorithm/iterator_operations.h> 1373fbae83SNikolas Klauser #include <__cxx03/__algorithm/rotate.h> 1473fbae83SNikolas Klauser #include <__cxx03/__config> 1573fbae83SNikolas Klauser #include <__cxx03/__iterator/advance.h> 1673fbae83SNikolas Klauser #include <__cxx03/__iterator/distance.h> 1773fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h> 1873fbae83SNikolas Klauser #include <__cxx03/__memory/destruct_n.h> 1973fbae83SNikolas Klauser #include <__cxx03/__memory/temporary_buffer.h> 2073fbae83SNikolas Klauser #include <__cxx03/__memory/unique_ptr.h> 2173fbae83SNikolas Klauser #include <__cxx03/__utility/move.h> 2273fbae83SNikolas Klauser #include <__cxx03/__utility/pair.h> 2373fbae83SNikolas Klauser #include <__cxx03/new> 24e78f53d1SNikolas Klauser 25e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 26e78f53d1SNikolas Klauser # pragma GCC system_header 27e78f53d1SNikolas Klauser #endif 28e78f53d1SNikolas Klauser 29e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS 3073fbae83SNikolas Klauser #include <__cxx03/__undef_macros> 31e78f53d1SNikolas Klauser 32e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 33e78f53d1SNikolas Klauser 34e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair> 35e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( 36e78f53d1SNikolas Klauser _ForwardIterator __first, 37e78f53d1SNikolas Klauser _ForwardIterator __last, 38e78f53d1SNikolas Klauser _Predicate __pred, 39e78f53d1SNikolas Klauser _Distance __len, 40e78f53d1SNikolas Klauser _Pair __p, 41e78f53d1SNikolas Klauser forward_iterator_tag __fit) { 42e78f53d1SNikolas Klauser using _Ops = _IterOps<_AlgPolicy>; 43e78f53d1SNikolas Klauser 44e78f53d1SNikolas Klauser // *__first is known to be false 45e78f53d1SNikolas Klauser // __len >= 1 46e78f53d1SNikolas Klauser if (__len == 1) 47e78f53d1SNikolas Klauser return __first; 48e78f53d1SNikolas Klauser if (__len == 2) { 49e78f53d1SNikolas Klauser _ForwardIterator __m = __first; 50e78f53d1SNikolas Klauser if (__pred(*++__m)) { 51e78f53d1SNikolas Klauser _Ops::iter_swap(__first, __m); 52e78f53d1SNikolas Klauser return __m; 53e78f53d1SNikolas Klauser } 54e78f53d1SNikolas Klauser return __first; 55e78f53d1SNikolas Klauser } 56e78f53d1SNikolas Klauser if (__len <= __p.second) { // The buffer is big enough to use 57e78f53d1SNikolas Klauser typedef typename iterator_traits<_ForwardIterator>::value_type value_type; 58e78f53d1SNikolas Klauser __destruct_n __d(0); 59e78f53d1SNikolas Klauser unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); 60e78f53d1SNikolas Klauser // Move the falses into the temporary buffer, and the trues to the front of the line 61e78f53d1SNikolas Klauser // Update __first to always point to the end of the trues 62e78f53d1SNikolas Klauser value_type* __t = __p.first; 63e78f53d1SNikolas Klauser ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); 64e78f53d1SNikolas Klauser __d.template __incr<value_type>(); 65e78f53d1SNikolas Klauser ++__t; 66e78f53d1SNikolas Klauser _ForwardIterator __i = __first; 67e78f53d1SNikolas Klauser while (++__i != __last) { 68e78f53d1SNikolas Klauser if (__pred(*__i)) { 69e78f53d1SNikolas Klauser *__first = _Ops::__iter_move(__i); 70e78f53d1SNikolas Klauser ++__first; 71e78f53d1SNikolas Klauser } else { 72e78f53d1SNikolas Klauser ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); 73e78f53d1SNikolas Klauser __d.template __incr<value_type>(); 74e78f53d1SNikolas Klauser ++__t; 75e78f53d1SNikolas Klauser } 76e78f53d1SNikolas Klauser } 77e78f53d1SNikolas Klauser // All trues now at start of range, all falses in buffer 78e78f53d1SNikolas Klauser // Move falses back into range, but don't mess up __first which points to first false 79e78f53d1SNikolas Klauser __i = __first; 80e78f53d1SNikolas Klauser for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i) 81e78f53d1SNikolas Klauser *__i = _Ops::__iter_move(__t2); 82e78f53d1SNikolas Klauser // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer 83e78f53d1SNikolas Klauser return __first; 84e78f53d1SNikolas Klauser } 85e78f53d1SNikolas Klauser // Else not enough buffer, do in place 86e78f53d1SNikolas Klauser // __len >= 3 87e78f53d1SNikolas Klauser _ForwardIterator __m = __first; 88e78f53d1SNikolas Klauser _Distance __len2 = __len / 2; // __len2 >= 2 89e78f53d1SNikolas Klauser _Ops::advance(__m, __len2); 90e78f53d1SNikolas Klauser // recurse on [__first, __m), *__first know to be false 91e78f53d1SNikolas Klauser // F????????????????? 92e78f53d1SNikolas Klauser // f m l 93e78f53d1SNikolas Klauser _ForwardIterator __first_false = 94e78f53d1SNikolas Klauser std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m, __pred, __len2, __p, __fit); 95e78f53d1SNikolas Klauser // TTTFFFFF?????????? 96e78f53d1SNikolas Klauser // f ff m l 97e78f53d1SNikolas Klauser // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true 98e78f53d1SNikolas Klauser _ForwardIterator __m1 = __m; 99e78f53d1SNikolas Klauser _ForwardIterator __second_false = __last; 100e78f53d1SNikolas Klauser _Distance __len_half = __len - __len2; 101e78f53d1SNikolas Klauser while (__pred(*__m1)) { 102e78f53d1SNikolas Klauser if (++__m1 == __last) 103e78f53d1SNikolas Klauser goto __second_half_done; 104e78f53d1SNikolas Klauser --__len_half; 105e78f53d1SNikolas Klauser } 106e78f53d1SNikolas Klauser // TTTFFFFFTTTF?????? 107e78f53d1SNikolas Klauser // f ff m m1 l 108e78f53d1SNikolas Klauser __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __fit); 109e78f53d1SNikolas Klauser __second_half_done: 110e78f53d1SNikolas Klauser // TTTFFFFFTTTTTFFFFF 111e78f53d1SNikolas Klauser // f ff m sf l 112e78f53d1SNikolas Klauser return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; 113e78f53d1SNikolas Klauser // TTTTTTTTFFFFFFFFFF 114e78f53d1SNikolas Klauser // | 115e78f53d1SNikolas Klauser } 116e78f53d1SNikolas Klauser 117e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Predicate, class _ForwardIterator> 118e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _ForwardIterator 119e78f53d1SNikolas Klauser __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) { 120e78f53d1SNikolas Klauser typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; 121e78f53d1SNikolas Klauser typedef typename iterator_traits<_ForwardIterator>::value_type value_type; 122e78f53d1SNikolas Klauser 123e78f53d1SNikolas Klauser const difference_type __alloc_limit = 3; // might want to make this a function of trivial assignment 124e78f53d1SNikolas Klauser // Either prove all true and return __first or point to first false 125e78f53d1SNikolas Klauser while (true) { 126e78f53d1SNikolas Klauser if (__first == __last) 127e78f53d1SNikolas Klauser return __first; 128e78f53d1SNikolas Klauser if (!__pred(*__first)) 129e78f53d1SNikolas Klauser break; 130e78f53d1SNikolas Klauser ++__first; 131e78f53d1SNikolas Klauser } 132e78f53d1SNikolas Klauser // We now have a reduced range [__first, __last) 133e78f53d1SNikolas Klauser // *__first is known to be false 134e78f53d1SNikolas Klauser difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last); 135e78f53d1SNikolas Klauser pair<value_type*, ptrdiff_t> __p(0, 0); 136e78f53d1SNikolas Klauser unique_ptr<value_type, __return_temporary_buffer> __h; 137e78f53d1SNikolas Klauser if (__len >= __alloc_limit) { 138e78f53d1SNikolas Klauser // TODO: Remove the use of std::get_temporary_buffer 139e78f53d1SNikolas Klauser _LIBCPP_SUPPRESS_DEPRECATED_PUSH 140e78f53d1SNikolas Klauser __p = std::get_temporary_buffer<value_type>(__len); 141e78f53d1SNikolas Klauser _LIBCPP_SUPPRESS_DEPRECATED_POP 142e78f53d1SNikolas Klauser __h.reset(__p.first); 143e78f53d1SNikolas Klauser } 144e78f53d1SNikolas Klauser return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( 145e78f53d1SNikolas Klauser std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag()); 146e78f53d1SNikolas Klauser } 147e78f53d1SNikolas Klauser 148e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair> 149e78f53d1SNikolas Klauser _BidirectionalIterator __stable_partition_impl( 150e78f53d1SNikolas Klauser _BidirectionalIterator __first, 151e78f53d1SNikolas Klauser _BidirectionalIterator __last, 152e78f53d1SNikolas Klauser _Predicate __pred, 153e78f53d1SNikolas Klauser _Distance __len, 154e78f53d1SNikolas Klauser _Pair __p, 155e78f53d1SNikolas Klauser bidirectional_iterator_tag __bit) { 156e78f53d1SNikolas Klauser using _Ops = _IterOps<_AlgPolicy>; 157e78f53d1SNikolas Klauser 158e78f53d1SNikolas Klauser // *__first is known to be false 159e78f53d1SNikolas Klauser // *__last is known to be true 160e78f53d1SNikolas Klauser // __len >= 2 161e78f53d1SNikolas Klauser if (__len == 2) { 162e78f53d1SNikolas Klauser _Ops::iter_swap(__first, __last); 163e78f53d1SNikolas Klauser return __last; 164e78f53d1SNikolas Klauser } 165e78f53d1SNikolas Klauser if (__len == 3) { 166e78f53d1SNikolas Klauser _BidirectionalIterator __m = __first; 167e78f53d1SNikolas Klauser if (__pred(*++__m)) { 168e78f53d1SNikolas Klauser _Ops::iter_swap(__first, __m); 169e78f53d1SNikolas Klauser _Ops::iter_swap(__m, __last); 170e78f53d1SNikolas Klauser return __last; 171e78f53d1SNikolas Klauser } 172e78f53d1SNikolas Klauser _Ops::iter_swap(__m, __last); 173e78f53d1SNikolas Klauser _Ops::iter_swap(__first, __m); 174e78f53d1SNikolas Klauser return __m; 175e78f53d1SNikolas Klauser } 176e78f53d1SNikolas Klauser if (__len <= __p.second) { // The buffer is big enough to use 177e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 178e78f53d1SNikolas Klauser __destruct_n __d(0); 179e78f53d1SNikolas Klauser unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); 180e78f53d1SNikolas Klauser // Move the falses into the temporary buffer, and the trues to the front of the line 181e78f53d1SNikolas Klauser // Update __first to always point to the end of the trues 182e78f53d1SNikolas Klauser value_type* __t = __p.first; 183e78f53d1SNikolas Klauser ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); 184e78f53d1SNikolas Klauser __d.template __incr<value_type>(); 185e78f53d1SNikolas Klauser ++__t; 186e78f53d1SNikolas Klauser _BidirectionalIterator __i = __first; 187e78f53d1SNikolas Klauser while (++__i != __last) { 188e78f53d1SNikolas Klauser if (__pred(*__i)) { 189e78f53d1SNikolas Klauser *__first = _Ops::__iter_move(__i); 190e78f53d1SNikolas Klauser ++__first; 191e78f53d1SNikolas Klauser } else { 192e78f53d1SNikolas Klauser ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); 193e78f53d1SNikolas Klauser __d.template __incr<value_type>(); 194e78f53d1SNikolas Klauser ++__t; 195e78f53d1SNikolas Klauser } 196e78f53d1SNikolas Klauser } 197e78f53d1SNikolas Klauser // move *__last, known to be true 198e78f53d1SNikolas Klauser *__first = _Ops::__iter_move(__i); 199e78f53d1SNikolas Klauser __i = ++__first; 200e78f53d1SNikolas Klauser // All trues now at start of range, all falses in buffer 201e78f53d1SNikolas Klauser // Move falses back into range, but don't mess up __first which points to first false 202e78f53d1SNikolas Klauser for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i) 203e78f53d1SNikolas Klauser *__i = _Ops::__iter_move(__t2); 204e78f53d1SNikolas Klauser // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer 205e78f53d1SNikolas Klauser return __first; 206e78f53d1SNikolas Klauser } 207e78f53d1SNikolas Klauser // Else not enough buffer, do in place 208e78f53d1SNikolas Klauser // __len >= 4 209e78f53d1SNikolas Klauser _BidirectionalIterator __m = __first; 210e78f53d1SNikolas Klauser _Distance __len2 = __len / 2; // __len2 >= 2 211e78f53d1SNikolas Klauser _Ops::advance(__m, __len2); 212e78f53d1SNikolas Klauser // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false 213e78f53d1SNikolas Klauser // F????????????????T 214e78f53d1SNikolas Klauser // f m l 215e78f53d1SNikolas Klauser _BidirectionalIterator __m1 = __m; 216e78f53d1SNikolas Klauser _BidirectionalIterator __first_false = __first; 217e78f53d1SNikolas Klauser _Distance __len_half = __len2; 218e78f53d1SNikolas Klauser while (!__pred(*--__m1)) { 219e78f53d1SNikolas Klauser if (__m1 == __first) 220e78f53d1SNikolas Klauser goto __first_half_done; 221e78f53d1SNikolas Klauser --__len_half; 222e78f53d1SNikolas Klauser } 223e78f53d1SNikolas Klauser // F???TFFF?????????T 224e78f53d1SNikolas Klauser // f m1 m l 225e78f53d1SNikolas Klauser __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m1, __pred, __len_half, __p, __bit); 226e78f53d1SNikolas Klauser __first_half_done: 227e78f53d1SNikolas Klauser // TTTFFFFF?????????T 228e78f53d1SNikolas Klauser // f ff m l 229e78f53d1SNikolas Klauser // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true 230e78f53d1SNikolas Klauser __m1 = __m; 231e78f53d1SNikolas Klauser _BidirectionalIterator __second_false = __last; 232e78f53d1SNikolas Klauser ++__second_false; 233e78f53d1SNikolas Klauser __len_half = __len - __len2; 234e78f53d1SNikolas Klauser while (__pred(*__m1)) { 235e78f53d1SNikolas Klauser if (++__m1 == __last) 236e78f53d1SNikolas Klauser goto __second_half_done; 237e78f53d1SNikolas Klauser --__len_half; 238e78f53d1SNikolas Klauser } 239e78f53d1SNikolas Klauser // TTTFFFFFTTTF?????T 240e78f53d1SNikolas Klauser // f ff m m1 l 241e78f53d1SNikolas Klauser __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __bit); 242e78f53d1SNikolas Klauser __second_half_done: 243e78f53d1SNikolas Klauser // TTTFFFFFTTTTTFFFFF 244e78f53d1SNikolas Klauser // f ff m sf l 245e78f53d1SNikolas Klauser return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; 246e78f53d1SNikolas Klauser // TTTTTTTTFFFFFFFFFF 247e78f53d1SNikolas Klauser // | 248e78f53d1SNikolas Klauser } 249e78f53d1SNikolas Klauser 250e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator> 251e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl( 252e78f53d1SNikolas Klauser _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) { 253e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; 254e78f53d1SNikolas Klauser typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; 255e78f53d1SNikolas Klauser const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment 256e78f53d1SNikolas Klauser // Either prove all true and return __first or point to first false 257e78f53d1SNikolas Klauser while (true) { 258e78f53d1SNikolas Klauser if (__first == __last) 259e78f53d1SNikolas Klauser return __first; 260e78f53d1SNikolas Klauser if (!__pred(*__first)) 261e78f53d1SNikolas Klauser break; 262e78f53d1SNikolas Klauser ++__first; 263e78f53d1SNikolas Klauser } 264e78f53d1SNikolas Klauser // __first points to first false, everything prior to __first is already set. 265e78f53d1SNikolas Klauser // Either prove [__first, __last) is all false and return __first, or point __last to last true 266e78f53d1SNikolas Klauser do { 267e78f53d1SNikolas Klauser if (__first == --__last) 268e78f53d1SNikolas Klauser return __first; 269e78f53d1SNikolas Klauser } while (!__pred(*__last)); 270e78f53d1SNikolas Klauser // We now have a reduced range [__first, __last] 271e78f53d1SNikolas Klauser // *__first is known to be false 272e78f53d1SNikolas Klauser // *__last is known to be true 273e78f53d1SNikolas Klauser // __len >= 2 274e78f53d1SNikolas Klauser difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1; 275e78f53d1SNikolas Klauser pair<value_type*, ptrdiff_t> __p(0, 0); 276e78f53d1SNikolas Klauser unique_ptr<value_type, __return_temporary_buffer> __h; 277e78f53d1SNikolas Klauser if (__len >= __alloc_limit) { 278e78f53d1SNikolas Klauser // TODO: Remove the use of std::get_temporary_buffer 279e78f53d1SNikolas Klauser _LIBCPP_SUPPRESS_DEPRECATED_PUSH 280e78f53d1SNikolas Klauser __p = std::get_temporary_buffer<value_type>(__len); 281e78f53d1SNikolas Klauser _LIBCPP_SUPPRESS_DEPRECATED_POP 282e78f53d1SNikolas Klauser __h.reset(__p.first); 283e78f53d1SNikolas Klauser } 284e78f53d1SNikolas Klauser return std::__stable_partition_impl<_AlgPolicy, _Predicate&>( 285e78f53d1SNikolas Klauser std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag()); 286e78f53d1SNikolas Klauser } 287e78f53d1SNikolas Klauser 288e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory> 289e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition( 290e78f53d1SNikolas Klauser _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) { 291e78f53d1SNikolas Klauser return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>( 292e78f53d1SNikolas Klauser std::move(__first), std::move(__last), __pred, __iter_category); 293e78f53d1SNikolas Klauser } 294e78f53d1SNikolas Klauser 295e78f53d1SNikolas Klauser template <class _ForwardIterator, class _Predicate> 296e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator 297e78f53d1SNikolas Klauser stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { 298e78f53d1SNikolas Klauser using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; 299e78f53d1SNikolas Klauser return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>( 300e78f53d1SNikolas Klauser std::move(__first), std::move(__last), __pred, _IterCategory()); 301e78f53d1SNikolas Klauser } 302e78f53d1SNikolas Klauser 303e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 304e78f53d1SNikolas Klauser 305e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS 306e78f53d1SNikolas Klauser 307*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___ALGORITHM_STABLE_PARTITION_H 308