Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:12

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H
0010 #define _LIBCPP___ALGORITHM_STABLE_PARTITION_H
0011 
0012 #include <__algorithm/iterator_operations.h>
0013 #include <__algorithm/rotate.h>
0014 #include <__config>
0015 #include <__cstddef/ptrdiff_t.h>
0016 #include <__iterator/advance.h>
0017 #include <__iterator/distance.h>
0018 #include <__iterator/iterator_traits.h>
0019 #include <__memory/destruct_n.h>
0020 #include <__memory/unique_ptr.h>
0021 #include <__memory/unique_temporary_buffer.h>
0022 #include <__type_traits/remove_cvref.h>
0023 #include <__utility/move.h>
0024 #include <__utility/pair.h>
0025 
0026 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0027 #  pragma GCC system_header
0028 #endif
0029 
0030 _LIBCPP_PUSH_MACROS
0031 #include <__undef_macros>
0032 
0033 _LIBCPP_BEGIN_NAMESPACE_STD
0034 
0035 template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair>
0036 _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl(
0037     _ForwardIterator __first,
0038     _ForwardIterator __last,
0039     _Predicate __pred,
0040     _Distance __len,
0041     _Pair __p,
0042     forward_iterator_tag __fit) {
0043   using _Ops = _IterOps<_AlgPolicy>;
0044 
0045   // *__first is known to be false
0046   // __len >= 1
0047   if (__len == 1)
0048     return __first;
0049   if (__len == 2) {
0050     _ForwardIterator __m = __first;
0051     if (__pred(*++__m)) {
0052       _Ops::iter_swap(__first, __m);
0053       return __m;
0054     }
0055     return __first;
0056   }
0057   if (__len <= __p.second) { // The buffer is big enough to use
0058     typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
0059     __destruct_n __d(0);
0060     unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
0061     // Move the falses into the temporary buffer, and the trues to the front of the line
0062     // Update __first to always point to the end of the trues
0063     value_type* __t = __p.first;
0064     ::new ((void*)__t) value_type(_Ops::__iter_move(__first));
0065     __d.template __incr<value_type>();
0066     ++__t;
0067     _ForwardIterator __i = __first;
0068     while (++__i != __last) {
0069       if (__pred(*__i)) {
0070         *__first = _Ops::__iter_move(__i);
0071         ++__first;
0072       } else {
0073         ::new ((void*)__t) value_type(_Ops::__iter_move(__i));
0074         __d.template __incr<value_type>();
0075         ++__t;
0076       }
0077     }
0078     // All trues now at start of range, all falses in buffer
0079     // Move falses back into range, but don't mess up __first which points to first false
0080     __i = __first;
0081     for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
0082       *__i = _Ops::__iter_move(__t2);
0083     // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer
0084     return __first;
0085   }
0086   // Else not enough buffer, do in place
0087   // __len >= 3
0088   _ForwardIterator __m = __first;
0089   _Distance __len2     = __len / 2; // __len2 >= 2
0090   _Ops::advance(__m, __len2);
0091   // recurse on [__first, __m), *__first know to be false
0092   // F?????????????????
0093   // f       m         l
0094   _ForwardIterator __first_false =
0095       std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m, __pred, __len2, __p, __fit);
0096   // TTTFFFFF??????????
0097   // f  ff   m         l
0098   // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true
0099   _ForwardIterator __m1           = __m;
0100   _ForwardIterator __second_false = __last;
0101   _Distance __len_half            = __len - __len2;
0102   while (__pred(*__m1)) {
0103     if (++__m1 == __last)
0104       goto __second_half_done;
0105     --__len_half;
0106   }
0107   // TTTFFFFFTTTF??????
0108   // f  ff   m  m1     l
0109   __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __fit);
0110 __second_half_done:
0111   // TTTFFFFFTTTTTFFFFF
0112   // f  ff   m    sf   l
0113   return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
0114   // TTTTTTTTFFFFFFFFFF
0115   //         |
0116 }
0117 
0118 template <class _AlgPolicy, class _Predicate, class _ForwardIterator>
0119 _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0120 __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) {
0121   typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
0122   typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
0123 
0124   const difference_type __alloc_limit = 3; // might want to make this a function of trivial assignment
0125   // Either prove all true and return __first or point to first false
0126   while (true) {
0127     if (__first == __last)
0128       return __first;
0129     if (!__pred(*__first))
0130       break;
0131     ++__first;
0132   }
0133   // We now have a reduced range [__first, __last)
0134   // *__first is known to be false
0135   difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last);
0136   __unique_temporary_buffer<value_type> __unique_buf;
0137   pair<value_type*, ptrdiff_t> __p(0, 0);
0138   if (__len >= __alloc_limit) {
0139     __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
0140     __p.first    = __unique_buf.get();
0141     __p.second   = __unique_buf.get_deleter().__count_;
0142   }
0143   return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
0144       std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag());
0145 }
0146 
0147 template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair>
0148 _BidirectionalIterator __stable_partition_impl(
0149     _BidirectionalIterator __first,
0150     _BidirectionalIterator __last,
0151     _Predicate __pred,
0152     _Distance __len,
0153     _Pair __p,
0154     bidirectional_iterator_tag __bit) {
0155   using _Ops = _IterOps<_AlgPolicy>;
0156 
0157   // *__first is known to be false
0158   // *__last is known to be true
0159   // __len >= 2
0160   if (__len == 2) {
0161     _Ops::iter_swap(__first, __last);
0162     return __last;
0163   }
0164   if (__len == 3) {
0165     _BidirectionalIterator __m = __first;
0166     if (__pred(*++__m)) {
0167       _Ops::iter_swap(__first, __m);
0168       _Ops::iter_swap(__m, __last);
0169       return __last;
0170     }
0171     _Ops::iter_swap(__m, __last);
0172     _Ops::iter_swap(__first, __m);
0173     return __m;
0174   }
0175   if (__len <= __p.second) { // The buffer is big enough to use
0176     typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
0177     __destruct_n __d(0);
0178     unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
0179     // Move the falses into the temporary buffer, and the trues to the front of the line
0180     // Update __first to always point to the end of the trues
0181     value_type* __t = __p.first;
0182     ::new ((void*)__t) value_type(_Ops::__iter_move(__first));
0183     __d.template __incr<value_type>();
0184     ++__t;
0185     _BidirectionalIterator __i = __first;
0186     while (++__i != __last) {
0187       if (__pred(*__i)) {
0188         *__first = _Ops::__iter_move(__i);
0189         ++__first;
0190       } else {
0191         ::new ((void*)__t) value_type(_Ops::__iter_move(__i));
0192         __d.template __incr<value_type>();
0193         ++__t;
0194       }
0195     }
0196     // move *__last, known to be true
0197     *__first = _Ops::__iter_move(__i);
0198     __i      = ++__first;
0199     // All trues now at start of range, all falses in buffer
0200     // Move falses back into range, but don't mess up __first which points to first false
0201     for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
0202       *__i = _Ops::__iter_move(__t2);
0203     // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer
0204     return __first;
0205   }
0206   // Else not enough buffer, do in place
0207   // __len >= 4
0208   _BidirectionalIterator __m = __first;
0209   _Distance __len2           = __len / 2; // __len2 >= 2
0210   _Ops::advance(__m, __len2);
0211   // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false
0212   // F????????????????T
0213   // f       m        l
0214   _BidirectionalIterator __m1          = __m;
0215   _BidirectionalIterator __first_false = __first;
0216   _Distance __len_half                 = __len2;
0217   while (!__pred(*--__m1)) {
0218     if (__m1 == __first)
0219       goto __first_half_done;
0220     --__len_half;
0221   }
0222   // F???TFFF?????????T
0223   // f   m1  m        l
0224   __first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m1, __pred, __len_half, __p, __bit);
0225 __first_half_done:
0226   // TTTFFFFF?????????T
0227   // f  ff   m        l
0228   // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true
0229   __m1                                  = __m;
0230   _BidirectionalIterator __second_false = __last;
0231   ++__second_false;
0232   __len_half = __len - __len2;
0233   while (__pred(*__m1)) {
0234     if (++__m1 == __last)
0235       goto __second_half_done;
0236     --__len_half;
0237   }
0238   // TTTFFFFFTTTF?????T
0239   // f  ff   m  m1    l
0240   __second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __bit);
0241 __second_half_done:
0242   // TTTFFFFFTTTTTFFFFF
0243   // f  ff   m    sf  l
0244   return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
0245   // TTTTTTTTFFFFFFFFFF
0246   //         |
0247 }
0248 
0249 template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator>
0250 _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl(
0251     _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) {
0252   typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
0253   typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
0254   const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment
0255   // Either prove all true and return __first or point to first false
0256   while (true) {
0257     if (__first == __last)
0258       return __first;
0259     if (!__pred(*__first))
0260       break;
0261     ++__first;
0262   }
0263   // __first points to first false, everything prior to __first is already set.
0264   // Either prove [__first, __last) is all false and return __first, or point __last to last true
0265   do {
0266     if (__first == --__last)
0267       return __first;
0268   } while (!__pred(*__last));
0269   // We now have a reduced range [__first, __last]
0270   // *__first is known to be false
0271   // *__last is known to be true
0272   // __len >= 2
0273   difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1;
0274   __unique_temporary_buffer<value_type> __unique_buf;
0275   pair<value_type*, ptrdiff_t> __p(0, 0);
0276   if (__len >= __alloc_limit) {
0277     __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
0278     __p.first    = __unique_buf.get();
0279     __p.second   = __unique_buf.get_deleter().__count_;
0280   }
0281   return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
0282       std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag());
0283 }
0284 
0285 template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory>
0286 _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition(
0287     _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) {
0288   return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>(
0289       std::move(__first), std::move(__last), __pred, __iter_category);
0290 }
0291 
0292 template <class _ForwardIterator, class _Predicate>
0293 inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
0294 stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
0295   using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
0296   return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>(
0297       std::move(__first), std::move(__last), __pred, _IterCategory());
0298 }
0299 
0300 _LIBCPP_END_NAMESPACE_STD
0301 
0302 _LIBCPP_POP_MACROS
0303 
0304 #endif // _LIBCPP___ALGORITHM_STABLE_PARTITION_H