brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.3 KiB · 64c8080 Raw
324 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___ALGORITHM_STABLE_SORT_H10#define _LIBCPP___ALGORITHM_STABLE_SORT_H11 12#include <__algorithm/comp.h>13#include <__algorithm/comp_ref_type.h>14#include <__algorithm/inplace_merge.h>15#include <__algorithm/iterator_operations.h>16#include <__algorithm/radix_sort.h>17#include <__algorithm/sort.h>18#include <__config>19#include <__cstddef/ptrdiff_t.h>20#include <__debug_utils/strict_weak_ordering_check.h>21#include <__iterator/iterator_traits.h>22#include <__memory/construct_at.h>23#include <__memory/destruct_n.h>24#include <__memory/unique_ptr.h>25#include <__memory/unique_temporary_buffer.h>26#include <__type_traits/desugars_to.h>27#include <__type_traits/enable_if.h>28#include <__type_traits/is_constant_evaluated.h>29#include <__type_traits/is_same.h>30#include <__type_traits/is_trivially_assignable.h>31#include <__utility/move.h>32#include <__utility/pair.h>33 34#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)35#  pragma GCC system_header36#endif37 38_LIBCPP_PUSH_MACROS39#include <__undef_macros>40 41_LIBCPP_BEGIN_NAMESPACE_STD42 43template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>44_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insertion_sort_move(45    _BidirectionalIterator __first1,46    _BidirectionalIterator __last1,47    typename iterator_traits<_BidirectionalIterator>::value_type* __first2,48    _Compare __comp) {49  using _Ops = _IterOps<_AlgPolicy>;50 51  typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;52  if (__first1 != __last1) {53    __destruct_n __d(0);54    unique_ptr<value_type, __destruct_n&> __h(__first2, __d);55    value_type* __last2 = __first2;56    std::__construct_at(__last2, _Ops::__iter_move(__first1));57    __d.template __incr<value_type>();58    for (++__last2; ++__first1 != __last1; ++__last2) {59      value_type* __j2 = __last2;60      value_type* __i2 = __j2;61      if (__comp(*__first1, *--__i2)) {62        std::__construct_at(__j2, std::move(*__i2));63        __d.template __incr<value_type>();64        for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2)65          *__j2 = std::move(*__i2);66        *__j2 = _Ops::__iter_move(__first1);67      } else {68        std::__construct_at(__j2, _Ops::__iter_move(__first1));69        __d.template __incr<value_type>();70      }71    }72    __h.release();73  }74}75 76template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2>77_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(78    _InputIterator1 __first1,79    _InputIterator1 __last1,80    _InputIterator2 __first2,81    _InputIterator2 __last2,82    typename iterator_traits<_InputIterator1>::value_type* __result,83    _Compare __comp) {84  using _Ops = _IterOps<_AlgPolicy>;85 86  typedef typename iterator_traits<_InputIterator1>::value_type value_type;87  __destruct_n __d(0);88  unique_ptr<value_type, __destruct_n&> __h(__result, __d);89  for (; true; ++__result) {90    if (__first1 == __last1) {91      for (; __first2 != __last2; ++__first2, (void)++__result, __d.template __incr<value_type>())92        std::__construct_at(__result, _Ops::__iter_move(__first2));93      __h.release();94      return;95    }96    if (__first2 == __last2) {97      for (; __first1 != __last1; ++__first1, (void)++__result, __d.template __incr<value_type>())98        std::__construct_at(__result, _Ops::__iter_move(__first1));99      __h.release();100      return;101    }102    if (__comp(*__first2, *__first1)) {103      std::__construct_at(__result, _Ops::__iter_move(__first2));104      __d.template __incr<value_type>();105      ++__first2;106    } else {107      std::__construct_at(__result, _Ops::__iter_move(__first1));108      __d.template __incr<value_type>();109      ++__first1;110    }111  }112}113 114template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>115_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_assign(116    _InputIterator1 __first1,117    _InputIterator1 __last1,118    _InputIterator2 __first2,119    _InputIterator2 __last2,120    _OutputIterator __result,121    _Compare __comp) {122  using _Ops = _IterOps<_AlgPolicy>;123 124  for (; __first1 != __last1; ++__result) {125    if (__first2 == __last2) {126      for (; __first1 != __last1; ++__first1, (void)++__result)127        *__result = _Ops::__iter_move(__first1);128      return;129    }130    if (__comp(*__first2, *__first1)) {131      *__result = _Ops::__iter_move(__first2);132      ++__first2;133    } else {134      *__result = _Ops::__iter_move(__first1);135      ++__first1;136    }137  }138  for (; __first2 != __last2; ++__first2, (void)++__result)139    *__result = _Ops::__iter_move(__first2);140}141 142template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>143_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(144    _RandomAccessIterator __first,145    _RandomAccessIterator __last,146    _Compare __comp,147    typename iterator_traits<_RandomAccessIterator>::difference_type __len,148    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,149    ptrdiff_t __buff_size);150 151template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>152_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move(153    _RandomAccessIterator __first1,154    _RandomAccessIterator __last1,155    _Compare __comp,156    typename iterator_traits<_RandomAccessIterator>::difference_type __len,157    typename iterator_traits<_RandomAccessIterator>::value_type* __first2) {158  using _Ops = _IterOps<_AlgPolicy>;159 160  typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;161  switch (__len) {162  case 0:163    return;164  case 1:165    std::__construct_at(__first2, _Ops::__iter_move(__first1));166    return;167  case 2:168    __destruct_n __d(0);169    unique_ptr<value_type, __destruct_n&> __h2(__first2, __d);170    if (__comp(*--__last1, *__first1)) {171      std::__construct_at(__first2, _Ops::__iter_move(__last1));172      __d.template __incr<value_type>();173      ++__first2;174      std::__construct_at(__first2, _Ops::__iter_move(__first1));175    } else {176      std::__construct_at(__first2, _Ops::__iter_move(__first1));177      __d.template __incr<value_type>();178      ++__first2;179      std::__construct_at(__first2, _Ops::__iter_move(__last1));180    }181    __h2.release();182    return;183  }184  if (__len <= 8) {185    std::__insertion_sort_move<_AlgPolicy, _Compare>(__first1, __last1, __first2, __comp);186    return;187  }188  typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2;189  _RandomAccessIterator __m                                             = __first1 + __l2;190  std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2);191  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2);192  std::__merge_move_construct<_AlgPolicy, _Compare>(__first1, __m, __m, __last1, __first2, __comp);193}194 195template <class _Tp>196struct __stable_sort_switch {197  static const unsigned value = 128 * is_trivially_copy_assignable<_Tp>::value;198};199 200#if _LIBCPP_STD_VER >= 17201template <class _Tp>202_LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_min_bound() {203  static_assert(__is_ordered_integer_representable_v<_Tp>);204  if constexpr (sizeof(_Tp) == 1) {205    return 1 << 8;206  }207 208  return 1 << 10;209}210 211template <class _Tp>212_LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_max_bound() {213  static_assert(__is_ordered_integer_representable_v<_Tp>);214  if constexpr (sizeof(_Tp) >= 8) {215    return 1 << 15;216  }217 218  return 1 << 16;219}220#endif // _LIBCPP_STD_VER >= 17221 222template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>223_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(224    _RandomAccessIterator __first,225    _RandomAccessIterator __last,226    _Compare __comp,227    typename iterator_traits<_RandomAccessIterator>::difference_type __len,228    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,229    ptrdiff_t __buff_size) {230  typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;231  typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;232  switch (__len) {233  case 0:234  case 1:235    return;236  case 2:237    if (__comp(*--__last, *__first))238      _IterOps<_AlgPolicy>::iter_swap(__first, __last);239    return;240  }241  if (__len <= static_cast<difference_type>(__stable_sort_switch<value_type>::value)) {242    std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp);243    return;244  }245 246#if _LIBCPP_STD_VER >= 17247  constexpr auto __default_comp = __desugars_to_v<__less_tag, _Compare, value_type, value_type >;248  constexpr auto __radix_sortable =249      __is_ordered_integer_representable_v<value_type> &&250      is_same_v< value_type&, __iterator_reference<_RandomAccessIterator>>;251  if constexpr (__default_comp && __radix_sortable) {252    if (__len <= __buff_size && __len >= static_cast<difference_type>(std::__radix_sort_min_bound<value_type>()) &&253        __len <= static_cast<difference_type>(std::__radix_sort_max_bound<value_type>())) {254      if (__libcpp_is_constant_evaluated()) {255        for (auto* __p = __buff; __p < __buff + __buff_size; ++__p) {256          std::__construct_at(__p);257        }258      }259 260      std::__radix_sort(__first, __last, __buff);261      return;262    }263  }264#endif // _LIBCPP_STD_VER >= 17265 266  typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2;267  _RandomAccessIterator __m                                             = __first + __l2;268  if (__len <= __buff_size) {269    __destruct_n __d(0);270    unique_ptr<value_type, __destruct_n&> __h2(__buff, __d);271    std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff);272    __d.__set(__l2, (value_type*)nullptr);273    std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2);274    __d.__set(__len, (value_type*)nullptr);275    std::__merge_move_assign<_AlgPolicy, _Compare>(276        __buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp);277    //         std::__merge<_Compare>(move_iterator<value_type*>(__buff),278    //                                  move_iterator<value_type*>(__buff + __l2),279    //                                  move_iterator<_RandomAccessIterator>(__buff + __l2),280    //                                  move_iterator<_RandomAccessIterator>(__buff + __len),281    //                                  __first, __comp);282    return;283  }284  std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size);285  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size);286  std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size);287}288 289template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>290_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void291__stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {292  using value_type      = typename iterator_traits<_RandomAccessIterator>::value_type;293  using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;294 295  difference_type __len = __last - __first;296  __unique_temporary_buffer<value_type> __unique_buf;297  pair<value_type*, ptrdiff_t> __buf(0, 0);298  if (__len > static_cast<difference_type>(__stable_sort_switch<value_type>::value)) {299    __unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);300    __buf.first  = __unique_buf.get();301    __buf.second = __unique_buf.get_deleter().__count_;302  }303 304  std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second);305  std::__check_strict_weak_ordering_sorted(__first, __last, __comp);306}307 308template <class _RandomAccessIterator, class _Compare>309_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void310stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {311  std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);312}313 314template <class _RandomAccessIterator>315_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void316stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {317  std::stable_sort(__first, __last, __less<>());318}319 320_LIBCPP_END_NAMESPACE_STD321_LIBCPP_POP_MACROS322 323#endif // _LIBCPP___ALGORITHM_STABLE_SORT_H324