stable_partition.h 11 KB

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