#ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H
#define _LIBCPP___ALGORITHM_STABLE_PARTITION_H
#include <__algorithm/iterator_operations.h>
#include <__algorithm/rotate.h>
#include <__config>
#include <__cstddef/ptrdiff_t.h>
#include <__iterator/advance.h>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__memory/construct_at.h>
#include <__memory/destruct_n.h>
#include <__memory/unique_ptr.h>
#include <__memory/unique_temporary_buffer.h>
#include <__type_traits/remove_cvref.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition_impl(
_ForwardIterator __first,
_ForwardIterator __last,
_Predicate __pred,
_Distance __len,
_Pair __p,
forward_iterator_tag __fit) {
using _Ops = _IterOps<_AlgPolicy>;
if (__len == 1)
return __first;
if (__len == 2) {
_ForwardIterator __m = __first;
if (__pred(*++__m)) {
_Ops::iter_swap(__first, __m);
return __m;
}
return __first;
}
if (__len <= __p.second) {
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
__destruct_n __d(0);
unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
value_type* __t = __p.first;
std::__construct_at(__t, _Ops::__iter_move(__first));
__d.template __incr<value_type>();
++__t;
_ForwardIterator __i = __first;
while (++__i != __last) {
if (__pred(*__i)) {
*__first = _Ops::__iter_move(__i);
++__first;
} else {
std::__construct_at(__t, _Ops::__iter_move(__i));
__d.template __incr<value_type>();
++__t;
}
}
__i = __first;
for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
*__i = _Ops::__iter_move(__t2);
return __first;
}
_ForwardIterator __m = __first;
_Distance __len2 = __len / 2;
_Ops::advance(__m, __len2);
_ForwardIterator __first_false =
std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m, __pred, __len2, __p, __fit);
_ForwardIterator __m1 = __m;
_ForwardIterator __second_false = __last;
_Distance __len_half = __len - __len2;
while (__pred(*__m1)) {
if (++__m1 == __last)
goto __second_half_done;
--__len_half;
}
__second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __fit);
__second_half_done:
return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
}
template <class _AlgPolicy, class _Predicate, class _ForwardIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) {
typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
const difference_type __alloc_limit = 3;
while (true) {
if (__first == __last)
return __first;
if (!__pred(*__first))
break;
++__first;
}
difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last);
__unique_temporary_buffer<value_type> __unique_buf;
pair<value_type*, ptrdiff_t> __p(0, 0);
if (__len >= __alloc_limit) {
__unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
__p.first = __unique_buf.get();
__p.second = __unique_buf.get_deleter().__count_;
}
return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag());
}
template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair>
_LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl(
_BidirectionalIterator __first,
_BidirectionalIterator __last,
_Predicate __pred,
_Distance __len,
_Pair __p,
bidirectional_iterator_tag __bit) {
using _Ops = _IterOps<_AlgPolicy>;
if (__len == 2) {
_Ops::iter_swap(__first, __last);
return __last;
}
if (__len == 3) {
_BidirectionalIterator __m = __first;
if (__pred(*++__m)) {
_Ops::iter_swap(__first, __m);
_Ops::iter_swap(__m, __last);
return __last;
}
_Ops::iter_swap(__m, __last);
_Ops::iter_swap(__first, __m);
return __m;
}
if (__len <= __p.second) {
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
__destruct_n __d(0);
unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
value_type* __t = __p.first;
std::__construct_at(__t, _Ops::__iter_move(__first));
__d.template __incr<value_type>();
++__t;
_BidirectionalIterator __i = __first;
while (++__i != __last) {
if (__pred(*__i)) {
*__first = _Ops::__iter_move(__i);
++__first;
} else {
std::__construct_at(__t, _Ops::__iter_move(__i));
__d.template __incr<value_type>();
++__t;
}
}
*__first = _Ops::__iter_move(__i);
__i = ++__first;
for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
*__i = _Ops::__iter_move(__t2);
return __first;
}
_BidirectionalIterator __m = __first;
_Distance __len2 = __len / 2;
_Ops::advance(__m, __len2);
_BidirectionalIterator __m1 = __m;
_BidirectionalIterator __first_false = __first;
_Distance __len_half = __len2;
while (!__pred(*--__m1)) {
if (__m1 == __first)
goto __first_half_done;
--__len_half;
}
__first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m1, __pred, __len_half, __p, __bit);
__first_half_done:
__m1 = __m;
_BidirectionalIterator __second_false = __last;
++__second_false;
__len_half = __len - __len2;
while (__pred(*__m1)) {
if (++__m1 == __last)
goto __second_half_done;
--__len_half;
}
__second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __bit);
__second_half_done:
return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
}
template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl(
_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) {
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
const difference_type __alloc_limit = 4;
while (true) {
if (__first == __last)
return __first;
if (!__pred(*__first))
break;
++__first;
}
do {
if (__first == --__last)
return __first;
} while (!__pred(*__last));
difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1;
__unique_temporary_buffer<value_type> __unique_buf;
pair<value_type*, ptrdiff_t> __p(0, 0);
if (__len >= __alloc_limit) {
__unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
__p.first = __unique_buf.get();
__p.second = __unique_buf.get_deleter().__count_;
}
return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag());
}
template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition(
_ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) {
return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>(
std::move(__first), std::move(__last), __pred, __iter_category);
}
template <class _ForwardIterator, class _Predicate>
_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>(
std::move(__first), std::move(__last), __pred, _IterCategory());
}
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif