Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 57 additions & 37 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class _Diff>
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -2764,7 +2764,7 @@ _CONSTEXPR20 void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _
template <class _RanIt, class _Pr>
_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);
Expand Down Expand Up @@ -2879,7 +2879,7 @@ _NODISCARD bool is_heap(_ExPo&& _Exec, _RanIt _First, _RanIt _Last) noexcept /*
template <class _RanIt, class _Pr>
_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);
}
}
Expand Down Expand Up @@ -3394,23 +3394,22 @@ void inplace_merge(_ExPo&&, _BidIt _First, _BidIt _Mid, _BidIt _Last) noexcept /

// FUNCTION TEMPLATE sort
template <class _BidIt, class _Pr>
_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
}
}

Expand Down Expand Up @@ -3520,11 +3519,27 @@ _CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _F
template <class _RanIt, class _Pr>
_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);
Expand All @@ -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 <class _RanIt, class _Pr>
Expand Down Expand Up @@ -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 <class _BidIt, class _Pr>
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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 <class _RanIt>
Expand Down
7 changes: 5 additions & 2 deletions stl/inc/execution
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down