stable_partition.h 12 KB

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