xref: /llvm-project/libcxx/include/__cxx03/__algorithm/stable_partition.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
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