File indexing completed on 2026-05-03 08:13:12
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H
0010 #define _LIBCPP___ALGORITHM_STABLE_PARTITION_H
0011
0012 #include <__algorithm/iterator_operations.h>
0013 #include <__algorithm/rotate.h>
0014 #include <__config>
0015 #include <__cstddef/ptrdiff_t.h>
0016 #include <__iterator/advance.h>
0017 #include <__iterator/distance.h>
0018 #include <__iterator/iterator_traits.h>
0019 #include <__memory/destruct_n.h>
0020 #include <__memory/unique_ptr.h>
0021 #include <__memory/unique_temporary_buffer.h>
0022 #include <__type_traits/remove_cvref.h>
0023 #include <__utility/move.h>
0024 #include <__utility/pair.h>
0025
0026 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0027 # pragma GCC system_header
0028 #endif
0029
0030 _LIBCPP_PUSH_MACROS
0031 #include <__undef_macros>
0032
0033 _LIBCPP_BEGIN_NAMESPACE_STD
0034
0035 template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair>
0036 _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl(
0037 _ForwardIterator __first,
0038 _ForwardIterator __last,
0039 _Predicate __pred,
0040 _Distance __len,
0041 _Pair __p,
0042 forward_iterator_tag __fit) {
0043 using _Ops = _IterOps<_AlgPolicy>;
0044
0045
0046
0047 if (__len == 1)
0048 return __first;
0049 if (__len == 2) {
0050 _ForwardIterator __m = __first;
0051 if (__pred(*++__m)) {
0052 _Ops::iter_swap(__first, __m);
0053 return __m;
0054 }
0055 return __first;
0056 }
0057 if (__len <= __p.second) {
0058 typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
0059 __destruct_n __d(0);
0060 unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
0061
0062
0063 value_type* __t = __p.first;
0064 ::new ((void*)__t) value_type(_Ops::__iter_move(__first));
0065 __d.template __incr<value_type>();
0066 ++__t;
0067 _ForwardIterator __i = __first;
0068 while (++__i != __last) {
0069 if (__pred(*__i)) {
0070 *__first = _Ops::__iter_move(__i);
0071 ++__first;
0072 } else {
0073 ::new ((void*)__t) value_type(_Ops::__iter_move(__i));
0074 __d.template __incr<value_type>();
0075 ++__t;
0076 }
0077 }
0078
0079
0080 __i = __first;
0081 for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
0082 *__i = _Ops::__iter_move(__t2);
0083
0084 return __first;
0085 }
0086
0087
0088 _ForwardIterator __m = __first;
0089 _Distance __len2 = __len / 2;
0090 _Ops::advance(__m, __len2);
0091
0092
0093
0094 _ForwardIterator __first_false =
0095 std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m, __pred, __len2, __p, __fit);
0096
0097
0098
0099 _ForwardIterator __m1 = __m;
0100 _ForwardIterator __second_false = __last;
0101 _Distance __len_half = __len - __len2;
0102 while (__pred(*__m1)) {
0103 if (++__m1 == __last)
0104 goto __second_half_done;
0105 --__len_half;
0106 }
0107
0108
0109 __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __fit);
0110 __second_half_done:
0111
0112
0113 return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
0114
0115
0116 }
0117
0118 template <class _AlgPolicy, class _Predicate, class _ForwardIterator>
0119 _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0120 __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) {
0121 typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
0122 typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
0123
0124 const difference_type __alloc_limit = 3;
0125
0126 while (true) {
0127 if (__first == __last)
0128 return __first;
0129 if (!__pred(*__first))
0130 break;
0131 ++__first;
0132 }
0133
0134
0135 difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last);
0136 __unique_temporary_buffer<value_type> __unique_buf;
0137 pair<value_type*, ptrdiff_t> __p(0, 0);
0138 if (__len >= __alloc_limit) {
0139 __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
0140 __p.first = __unique_buf.get();
0141 __p.second = __unique_buf.get_deleter().__count_;
0142 }
0143 return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
0144 std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag());
0145 }
0146
0147 template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair>
0148 _BidirectionalIterator __stable_partition_impl(
0149 _BidirectionalIterator __first,
0150 _BidirectionalIterator __last,
0151 _Predicate __pred,
0152 _Distance __len,
0153 _Pair __p,
0154 bidirectional_iterator_tag __bit) {
0155 using _Ops = _IterOps<_AlgPolicy>;
0156
0157
0158
0159
0160 if (__len == 2) {
0161 _Ops::iter_swap(__first, __last);
0162 return __last;
0163 }
0164 if (__len == 3) {
0165 _BidirectionalIterator __m = __first;
0166 if (__pred(*++__m)) {
0167 _Ops::iter_swap(__first, __m);
0168 _Ops::iter_swap(__m, __last);
0169 return __last;
0170 }
0171 _Ops::iter_swap(__m, __last);
0172 _Ops::iter_swap(__first, __m);
0173 return __m;
0174 }
0175 if (__len <= __p.second) {
0176 typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
0177 __destruct_n __d(0);
0178 unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
0179
0180
0181 value_type* __t = __p.first;
0182 ::new ((void*)__t) value_type(_Ops::__iter_move(__first));
0183 __d.template __incr<value_type>();
0184 ++__t;
0185 _BidirectionalIterator __i = __first;
0186 while (++__i != __last) {
0187 if (__pred(*__i)) {
0188 *__first = _Ops::__iter_move(__i);
0189 ++__first;
0190 } else {
0191 ::new ((void*)__t) value_type(_Ops::__iter_move(__i));
0192 __d.template __incr<value_type>();
0193 ++__t;
0194 }
0195 }
0196
0197 *__first = _Ops::__iter_move(__i);
0198 __i = ++__first;
0199
0200
0201 for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
0202 *__i = _Ops::__iter_move(__t2);
0203
0204 return __first;
0205 }
0206
0207
0208 _BidirectionalIterator __m = __first;
0209 _Distance __len2 = __len / 2;
0210 _Ops::advance(__m, __len2);
0211
0212
0213
0214 _BidirectionalIterator __m1 = __m;
0215 _BidirectionalIterator __first_false = __first;
0216 _Distance __len_half = __len2;
0217 while (!__pred(*--__m1)) {
0218 if (__m1 == __first)
0219 goto __first_half_done;
0220 --__len_half;
0221 }
0222
0223
0224 __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m1, __pred, __len_half, __p, __bit);
0225 __first_half_done:
0226
0227
0228
0229 __m1 = __m;
0230 _BidirectionalIterator __second_false = __last;
0231 ++__second_false;
0232 __len_half = __len - __len2;
0233 while (__pred(*__m1)) {
0234 if (++__m1 == __last)
0235 goto __second_half_done;
0236 --__len_half;
0237 }
0238
0239
0240 __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __bit);
0241 __second_half_done:
0242
0243
0244 return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
0245
0246
0247 }
0248
0249 template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator>
0250 _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl(
0251 _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) {
0252 typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
0253 typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
0254 const difference_type __alloc_limit = 4;
0255
0256 while (true) {
0257 if (__first == __last)
0258 return __first;
0259 if (!__pred(*__first))
0260 break;
0261 ++__first;
0262 }
0263
0264
0265 do {
0266 if (__first == --__last)
0267 return __first;
0268 } while (!__pred(*__last));
0269
0270
0271
0272
0273 difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1;
0274 __unique_temporary_buffer<value_type> __unique_buf;
0275 pair<value_type*, ptrdiff_t> __p(0, 0);
0276 if (__len >= __alloc_limit) {
0277 __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
0278 __p.first = __unique_buf.get();
0279 __p.second = __unique_buf.get_deleter().__count_;
0280 }
0281 return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
0282 std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag());
0283 }
0284
0285 template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory>
0286 _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition(
0287 _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) {
0288 return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>(
0289 std::move(__first), std::move(__last), __pred, __iter_category);
0290 }
0291
0292 template <class _ForwardIterator, class _Predicate>
0293 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0294 stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
0295 using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
0296 return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>(
0297 std::move(__first), std::move(__last), __pred, _IterCategory());
0298 }
0299
0300 _LIBCPP_END_NAMESPACE_STD
0301
0302 _LIBCPP_POP_MACROS
0303
0304 #endif