stable_partition.h 11 KB

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