diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 77777c5b4b5..afd23b21b74 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -27,7 +27,7 @@ _END_EXTERN_C _STD_BEGIN // COMMON SORT PARAMETERS -const int _ISORT_MAX = 32; // maximum size for insertion sort +_INLINE_VAR constexpr int _ISORT_MAX = 32; // maximum size for insertion sort // STRUCT TEMPLATE _Optimistic_temporary_buffer template @@ -2709,7 +2709,7 @@ _CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { auto _ULast = _Get_unwrapped(_Last); using _Diff = _Iter_diff_t<_RanIt>; _Diff _Count = _ULast - _UFirst; - if (2 <= _Count) { + if (1 < _Count) { _Iter_value_t<_RanIt> _Val = _STD move(*--_ULast); _Push_heap_by_index(_UFirst, --_Count, _Diff(0), _STD move(_Val), _Pass_fn(_Pred)); } @@ -2764,7 +2764,7 @@ _CONSTEXPR20 void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _ template _CONSTEXPR20 void _Pop_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { // pop *_First to *(_Last - 1) and reheap, using _Pred - if (2 <= _Last - _First) { + if (1 < _Last - _First) { --_Last; _Iter_value_t<_RanIt> _Val = _STD move(*_Last); _Pop_heap_hole_unchecked(_First, _Last, _Last, _STD move(_Val), _Pred); @@ -2879,7 +2879,7 @@ _NODISCARD bool is_heap(_ExPo&& _Exec, _RanIt _First, _RanIt _Last) noexcept /* template _CONSTEXPR20 void _Sort_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order heap by repeatedly popping, using _Pred - for (; 2 <= _Last - _First; --_Last) { + for (; 1 < _Last - _First; --_Last) { _Pop_heap_unchecked(_First, _Last, _Pred); } } @@ -3394,23 +3394,22 @@ void inplace_merge(_ExPo&&, _BidIt _First, _BidIt _Mid, _BidIt _Last) noexcept / // FUNCTION TEMPLATE sort template -_CONSTEXPR20_ICE _BidIt _Insertion_sort_unchecked(_BidIt _First, const _BidIt _Last, _Pr _Pred) { +_CONSTEXPR20_ICE _BidIt _Insertion_sort_unchecked2(_BidIt _First, const _BidIt _Last, _Pr _Pred) { // insertion sort [_First, _Last), using _Pred - if (_First != _Last) { - for (_BidIt _Next = _First; ++_Next != _Last;) { // order next element - _BidIt _Next1 = _Next; - _Iter_value_t<_BidIt> _Val = _STD move(*_Next); - - if (_DEBUG_LT_PRED(_Pred, _Val, *_First)) { // found new earliest element, move to front - _Move_backward_unchecked(_First, _Next, ++_Next1); - *_First = _STD move(_Val); - } else { // look for insertion point after first - for (_BidIt _First1 = _Next1; _DEBUG_LT_PRED(_Pred, _Val, *--_First1); _Next1 = _First1) { - *_Next1 = _STD move(*_First1); // move hole down - } - - *_Next1 = _STD move(_Val); // insert element in hole + _STL_INTERNAL_CHECK(_First != _Last); + for (_BidIt _Next = _First; ++_Next != _Last;) { // order next element + _BidIt _Next1 = _Next; + _Iter_value_t<_BidIt> _Val = _STD move(*_Next); + + if (_DEBUG_LT_PRED(_Pred, _Val, *_First)) { // found new earliest element, move to front + _Move_backward_unchecked(_First, _Next, ++_Next1); + *_First = _STD move(_Val); + } else { // look for insertion point after first + for (_BidIt _First1 = _Next1; _DEBUG_LT_PRED(_Pred, _Val, *--_First1); _Next1 = _First1) { + *_Next1 = _STD move(*_First1); // move hole down } + + *_Next1 = _STD move(_Val); // insert element in hole } } @@ -3520,11 +3519,27 @@ _CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _F template _CONSTEXPR20_ICE void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _Pr _Pred) { // order [_First, _Last), using _Pred - _Iter_diff_t<_RanIt> _Count = 0; - while (_ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal) { // divide and conquer by quicksort + for (;;) { + const _Iter_diff_t<_RanIt> _Count = _Last - _First; + + if (_Count <= _ISORT_MAX) { + if (1 < _Count) { + _Insertion_sort_unchecked2(_First, _Last, _Pred); + } + + return; + } + + if (_Ideal <= 0) { // heap sort if too many divisions + _Make_heap_unchecked(_First, _Last, _Pred); + _Sort_heap_unchecked(_First, _Last, _Pred); + return; + } + + // divide and conquer by quicksort auto _Mid = _Partition_by_median_guess_unchecked(_First, _Last, _Pred); - _Ideal = _Ideal / 2 + _Ideal / 4; // allow 1.5 log2(N) divisions + _Ideal = (_Ideal >> 1) + (_Ideal >> 2); // allow 1.5 log2(N) divisions if (_Mid.first - _First < _Last - _Mid.second) { // loop on second half _Sort_unchecked(_First, _Mid.first, _Ideal, _Pred); @@ -3534,13 +3549,6 @@ _CONSTEXPR20_ICE void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t< _Last = _Mid.first; } } - - if (_ISORT_MAX < _Count) { // heap sort if too many divisions - _Make_heap_unchecked(_First, _Last, _Pred); - _Sort_heap_unchecked(_First, _Last, _Pred); - } else if (2 <= _Count) { - _Insertion_sort_unchecked(_First, _Last, _Pred); // small - } } template @@ -3667,10 +3675,12 @@ void _Insertion_sort_isort_max_chunks(_BidIt _First, const _BidIt _Last, _Iter_d // pre: _Count == distance(_First, _Last) constexpr auto _Diffsort_max = static_cast<_Iter_diff_t<_BidIt>>(_ISORT_MAX); for (; _Diffsort_max < _Count; _Count -= _Diffsort_max) { // sort chunks - _First = _Insertion_sort_unchecked(_First, _STD next(_First, _Diffsort_max), _Pred); + _First = _Insertion_sort_unchecked2(_First, _STD next(_First, _Diffsort_max), _Pred); } - _Insertion_sort_unchecked(_First, _Last, _Pred); // sort partial last chunk + if (1 < _Count) { + _Insertion_sort_unchecked2(_First, _Last, _Pred); // sort partial last chunk + } } template @@ -3710,7 +3720,9 @@ void _Stable_sort_unchecked(const _BidIt _First, const _BidIt _Last, const _Iter // sort preserving order of equivalents, using _Pred using _Diff = _Iter_diff_t<_BidIt>; if (_Count <= _ISORT_MAX) { - _Insertion_sort_unchecked(_First, _Last, _Pred); // small + if (1 < _Count) { + _Insertion_sort_unchecked2(_First, _Last, _Pred); // small + } } else { // sort halves and merge const auto _Half_count = static_cast<_Diff>(_Count / 2); const auto _Half_count_ceil = static_cast<_Diff>(_Count - _Half_count); @@ -3736,8 +3748,8 @@ void stable_sort(const _BidIt _First, const _BidIt _Last, _Pr _Pred) { const auto _ULast = _Get_unwrapped(_Last); const auto _Count = _STD distance(_UFirst, _ULast); if (_Count <= _ISORT_MAX) { - if (_Count > 1) { - _Insertion_sort_unchecked(_UFirst, _ULast, _Pass_fn(_Pred)); + if (1 < _Count) { + _Insertion_sort_unchecked2(_UFirst, _ULast, _Pass_fn(_Pred)); } return; @@ -3884,7 +3896,17 @@ _CONSTEXPR20_ICE void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr return; // nothing to do } - while (_ISORT_MAX < _ULast - _UFirst) { // divide and conquer, ordering partition containing Nth + for (;;) { + const _Iter_diff_t<_RanIt> _Count = _Last - _First; + if (_Count <= _ISORT_MAX) { + if (1 < _Count) { + _Insertion_sort_unchecked2(_UFirst, _ULast, _Pass_fn(_Pred)); // sort any remainder + } + + return; + } + + // divide and conquer, ordering partition containing Nth auto _UMid = _Partition_by_median_guess_unchecked(_UFirst, _ULast, _Pass_fn(_Pred)); if (_UMid.second <= _UNth) { @@ -3895,8 +3917,6 @@ _CONSTEXPR20_ICE void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _ULast = _UMid.first; } } - - _Insertion_sort_unchecked(_UFirst, _ULast, _Pass_fn(_Pred)); // sort any remainder } template diff --git a/stl/inc/execution b/stl/inc/execution index 15c210a8871..c2fc6a321f7 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -2673,7 +2673,10 @@ bool _Process_sort_work_item(const _RanIt _Basis, _Pr _Pred, _Sort_work_item<_Ra const auto _Last = _First + _Size; const auto _Ideal = _Wi._Ideal; if (_Size <= _Diffsort_max) { - _Insertion_sort_unchecked(_First, _Last, _Pred); + if (1 < _Size) { + _Insertion_sort_unchecked2(_First, _Last, _Pred); + } + _Work_complete += _Size; return false; } @@ -3015,7 +3018,7 @@ void stable_sort(_ExPo&&, const _BidIt _First, const _BidIt _Last, _Pr _Pred) no const auto _Count = _STD distance(_UFirst, _ULast); if (_Count <= _ISORT_MAX) { if (_Count > 1) { - _Insertion_sort_unchecked(_UFirst, _ULast, _Pass_fn(_Pred)); + _Insertion_sort_unchecked2(_UFirst, _ULast, _Pass_fn(_Pred)); } return;