From 332b236ef0b787922db15209fbf6905a1629e40d Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 27 Jul 2020 18:49:44 -0700 Subject: [PATCH 1/2] Implement ranges::sort --- stl/inc/algorithm | 146 +++++++++++++----- tests/std/test.lst | 1 + .../std/tests/P0896R4_ranges_alg_sort/env.lst | 4 + .../tests/P0896R4_ranges_alg_sort/test.cpp | 61 ++++++++ 4 files changed, 176 insertions(+), 36 deletions(-) create mode 100644 tests/std/tests/P0896R4_ranges_alg_sort/env.lst create mode 100644 tests/std/tests/P0896R4_ranges_alg_sort/test.cpp diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 4e431bb53a0..0cb66abfc49 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -6330,6 +6330,22 @@ _CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last) { // make [_First, _Las #ifdef __cpp_lib_concepts namespace ranges { // VARIABLE ranges::make_heap + // clang-format off + template + requires sortable<_It, _Pr, _Pj> + constexpr void _Make_heap_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) { + // clang-format on + // make nontrivial [_First, _Last) into a heap + using _Diff = iter_difference_t<_It>; + const _Diff _Bottom = _Last - _First; + for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen + // reheap top half, bottom to top + --_Hole; + iter_value_t<_It> _Val = _RANGES iter_move(_First + _Hole); + _RANGES _Pop_heap_hole_by_index(_First, _Hole, _Bottom, _STD move(_Val), _Pred, _Proj); + } + } + class _Make_heap_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -6338,43 +6354,29 @@ namespace ranges { template _Se, class _Pr = ranges::less, class _Pj = identity> requires sortable<_It, _Pr, _Pj> constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const { + // clang-format on _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_STD move(_First)); auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last)); _Seek_wrapped(_First, _ULast); - _Make_heap_unchecked(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _RANGES _Make_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _First; } + // clang-format off template requires sortable, _Pr, _Pj> constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { + // clang-format on if constexpr (common_range<_Rng>) { - _Make_heap_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _RANGES _Make_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _RANGES end(_Range); } else { auto _ULast = _Get_final_iterator_unwrapped(_Range); - _Make_heap_unchecked(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); + _RANGES _Make_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_iterator(_Range, _STD move(_ULast)); } } - // clang-format on - private: - template - static constexpr void _Make_heap_unchecked(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) { - // make nontrivial [_First, _Last) into a heap - _STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>); - _STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>); - - using _Diff = iter_difference_t<_It>; - const _Diff _Bottom = _Last - _First; - for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen - // reheap top half, bottom to top - --_Hole; - iter_value_t<_It> _Val = _RANGES iter_move(_First + _Hole); - _RANGES _Pop_heap_hole_by_index(_First, _Hole, _Bottom, _STD move(_Val), _Pred, _Proj); - } - } }; inline constexpr _Make_heap_fn make_heap{_Not_quite_object::_Construct_tag{}}; @@ -6563,6 +6565,17 @@ _CONSTEXPR20 void sort_heap(_RanIt _First, _RanIt _Last) { // order heap by repe #ifdef __cpp_lib_concepts namespace ranges { // VARIABLE ranges::sort_heap + // clang-format off + template + requires sortable<_It, _Pr, _Pj> + constexpr void _Sort_heap_common(const _It _First, _It _Last, _Pr _Pred, _Pj _Proj) { + // clang-format on + // order heap by repeatedly popping + for (; _Last - _First >= 2; --_Last) { + _RANGES _Pop_heap_unchecked(_First, _Last, _Pred, _Proj); + } + } + class _Sort_heap_fn : private _Not_quite_object { public: using _Not_quite_object::_Not_quite_object; @@ -6571,38 +6584,29 @@ namespace ranges { template _Se, class _Pr = ranges::less, class _Pj = identity> requires sortable<_It, _Pr, _Pj> constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const { + // clang-format on _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_STD move(_First)); auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last)); _Seek_wrapped(_First, _ULast); - _Sort_heap_unchecked(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _RANGES _Sort_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _First; } + // clang-format off template requires sortable, _Pr, _Pj> constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { + // clang-format on if constexpr (common_range<_Rng>) { - _Sort_heap_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _RANGES _Sort_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _RANGES end(_Range); } else { auto _ULast = _Get_final_iterator_unwrapped(_Range); - _Sort_heap_unchecked(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); + _RANGES _Sort_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_iterator(_Range, _STD move(_ULast)); } } - // clang-format on - private: - template - static constexpr void _Sort_heap_unchecked(const _It _First, _It _Last, _Pr _Pred, _Pj _Proj) { - // order heap by repeatedly popping - _STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>); - _STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>); - - for (; _Last - _First >= 2; --_Last) { - _RANGES _Pop_heap_unchecked(_First, _Last, _Pred, _Proj); - } - } }; inline constexpr _Sort_heap_fn sort_heap{_Not_quite_object::_Construct_tag{}}; @@ -7446,6 +7450,7 @@ void sort(_ExPo&& _Exec, const _RanIt _First, const _RanIt _Last) noexcept /* te // order [_First, _Last) _STD sort(_STD forward<_ExPo>(_Exec), _First, _Last, less{}); } +#endif // _HAS_CXX17 #ifdef __cpp_lib_concepts namespace ranges { @@ -7594,9 +7599,78 @@ namespace ranges { } } // clang-format on + + // VARIABLE ranges::sort + class _Sort_fn : private _Not_quite_object { + public: + using _Not_quite_object::_Not_quite_object; + + // clang-format off + template _Se, class _Pr = ranges::less, class _Pj = identity> + requires sortable<_It, _Pr, _Pj> + _NODISCARD constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const { + // clang-format on + _Adl_verify_range(_First, _Last); + auto _UFirst = _Get_unwrapped(_STD move(_First)); + auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last)); + _Seek_wrapped(_First, _ULast); + const auto _Count = _ULast - _UFirst; + _Sort_common(_STD move(_UFirst), _STD move(_ULast), _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); + return _First; + } + + // clang-format off + template + requires sortable, _Pr, _Pj> + _NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { + // clang-format on + auto _ULast = _Get_final_iterator_unwrapped(_Range); + auto _UFirst = _Ubegin(_Range); + const auto _Count = _ULast - _UFirst; + _Sort_common(_STD move(_UFirst), _ULast, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); + return _Rewrap_iterator(_Range, _STD move(_ULast)); + } + + private: + template + _NODISCARD static constexpr void _Sort_common( + _It _First, _It _Last, iter_difference_t<_It> _Ideal, _Pr _Pred, _Pj _Proj) { + // sort [_First, _Last) with respect to _Pred and _Proj + _STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>); + _STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>); + + for (;;) { + if (_Last - _First <= _ISORT_MAX) { // small + _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); + return; + } + + if (_Ideal <= 0) { // heap sort if too many divisions + _RANGES _Make_heap_common(_First, _Last, _Pred, _Proj); + _RANGES _Sort_heap_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); + return; + } + + // divide and conquer by quicksort + auto [_Mid_first, _Mid_last] = + _RANGES _Partition_by_median_guess_unchecked(_First, _Last, _Pred, _Proj); + + _Ideal = (_Ideal >> 1) + (_Ideal >> 2); // allow 1.5 log2(N) divisions + + if (_Mid_first - _First < _Last - _Mid_last) { // loop on second half + _Sort_common(_First, _Mid_first, _Ideal, _Pred, _Proj); + _First = _Mid_last; + } else { // loop on first half + _Sort_common(_Mid_last, _Last, _Ideal, _Pred, _Proj); + _Last = _Mid_first; + } + } + } + }; + + inline constexpr _Sort_fn sort{_Not_quite_object::_Construct_tag{}}; } // namespace ranges #endif // __cpp_lib_concepts -#endif // _HAS_CXX17 // FUNCTION TEMPLATE stable_sort template diff --git a/tests/std/test.lst b/tests/std/test.lst index f6eda1e96ff..5d3b2380da4 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -294,6 +294,7 @@ tests\P0896R4_ranges_alg_set_intersection tests\P0896R4_ranges_alg_set_symmetric_difference tests\P0896R4_ranges_alg_set_union tests\P0896R4_ranges_alg_shuffle +tests\P0896R4_ranges_alg_sort tests\P0896R4_ranges_alg_swap_ranges tests\P0896R4_ranges_alg_transform_binary tests\P0896R4_ranges_alg_transform_unary diff --git a/tests/std/tests/P0896R4_ranges_alg_sort/env.lst b/tests/std/tests/P0896R4_ranges_alg_sort/env.lst new file mode 100644 index 00000000000..f3ccc8613c6 --- /dev/null +++ b/tests/std/tests/P0896R4_ranges_alg_sort/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_matrix.lst diff --git a/tests/std/tests/P0896R4_ranges_alg_sort/test.cpp b/tests/std/tests/P0896R4_ranges_alg_sort/test.cpp new file mode 100644 index 00000000000..88c838a4eba --- /dev/null +++ b/tests/std/tests/P0896R4_ranges_alg_sort/test.cpp @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; +using P = pair; + +// Validate dangling story +STATIC_ASSERT(same_as{})), ranges::dangling>); +STATIC_ASSERT(same_as{})), int*>); + +struct instantiator { + static constexpr array input = {P{-1200257975, 0}, P{-1260655766, 1}, P{-1298559576, 2}, P{-1459960308, 3}, + P{-2095681771, 4}, P{-441494788, 5}, P{-47163201, 6}, P{-912489821, 7}, P{1429106719, 8}, P{1668617627, 9}}; + + template + static constexpr void call() { +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163 + if constexpr (!ranges::contiguous_range) +#endif // TRANSITION, VSO-938163 + { + using ranges::sort, ranges::is_sorted, ranges::iterator_t, ranges::less; + + { // Validate range overload + auto buff = input; + const R range{buff}; + const same_as> auto result = sort(range, less{}, get_first); + assert(result == range.end()); + assert(is_sorted(range, less{}, get_first)); + } + + { // Validate iterator overload + auto buff = input; + const R range{buff}; + const same_as> auto result = sort(range.begin(), range.end(), less{}, get_first); + assert(result == range.end()); + assert(is_sorted(range.begin(), range.end(), less{}, get_first)); + } + + { // Validate empty range + const R range{}; + const same_as> auto result = sort(range, less{}, get_first); + assert(result == range.end()); + assert(is_sorted(range, less{}, get_first)); + } + } + } +}; + +int main() { + STATIC_ASSERT((test_random(), true)); + test_random(); +} From f1bd8776afb9cff442276e0f5a823bcb6ec49a01 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 5 Aug 2020 10:54:52 -0700 Subject: [PATCH 2/2] STL and miscco review comments --- stl/inc/algorithm | 81 ++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 0cb66abfc49..fc32facbeeb 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1925,7 +1925,7 @@ namespace ranges { auto _UFirst = _Get_unwrapped(_STD move(_First)); auto _ULast = _Get_final_iterator_unwrapped<_It1>(_UFirst, _STD move(_Last)); _Seek_wrapped(_First, _ULast); - _Result = _RANGES _Move_backward_common(_STD move(_UFirst), _STD move(_ULast), _STD move(_Result)); + _Result = _Move_backward_common(_STD move(_UFirst), _STD move(_ULast), _STD move(_Result)); return {_STD move(_First), _STD move(_Result)}; } @@ -1933,7 +1933,7 @@ namespace ranges { requires indirectly_movable, _It> constexpr move_backward_result, _It> operator()(_Rng&& _Range, _It _Result) const { auto _ULast = _Get_final_iterator_unwrapped(_Range); - _Result = _RANGES _Move_backward_common(_Ubegin(_Range), _ULast, _STD move(_Result)); + _Result = _Move_backward_common(_Ubegin(_Range), _ULast, _STD move(_Result)); return {_Rewrap_iterator(_Range, _STD move(_ULast)), _STD move(_Result)}; } // clang-format on @@ -6305,7 +6305,7 @@ namespace ranges { // FUNCTION TEMPLATE make_heap template _CONSTEXPR20 void _Make_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { - // make nontrivial [_First, _Last) into a heap + // make [_First, _Last) into a heap using _Diff = _Iter_diff_t<_RanIt>; _Diff _Bottom = _Last - _First; for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen @@ -6335,7 +6335,7 @@ namespace ranges { requires sortable<_It, _Pr, _Pj> constexpr void _Make_heap_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) { // clang-format on - // make nontrivial [_First, _Last) into a heap + // make [_First, _Last) into a heap using _Diff = iter_difference_t<_It>; const _Diff _Bottom = _Last - _First; for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen @@ -6359,7 +6359,7 @@ namespace ranges { auto _UFirst = _Get_unwrapped(_STD move(_First)); auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last)); _Seek_wrapped(_First, _ULast); - _RANGES _Make_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _Make_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _First; } @@ -6369,11 +6369,11 @@ namespace ranges { constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { // clang-format on if constexpr (common_range<_Rng>) { - _RANGES _Make_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _Make_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _RANGES end(_Range); } else { auto _ULast = _Get_final_iterator_unwrapped(_Range); - _RANGES _Make_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); + _Make_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_iterator(_Range, _STD move(_ULast)); } } @@ -6589,7 +6589,7 @@ namespace ranges { auto _UFirst = _Get_unwrapped(_STD move(_First)); auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last)); _Seek_wrapped(_First, _ULast); - _RANGES _Sort_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _Sort_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _First; } @@ -6599,11 +6599,11 @@ namespace ranges { constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { // clang-format on if constexpr (common_range<_Rng>) { - _RANGES _Sort_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); + _Sort_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _RANGES end(_Range); } else { auto _ULast = _Get_final_iterator_unwrapped(_Range); - _RANGES _Sort_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); + _Sort_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_iterator(_Range, _STD move(_ULast)); } } @@ -7458,6 +7458,7 @@ namespace ranges { template requires sortable<_It, _Pr, _Pj> constexpr void _Insertion_sort_common(const _It _First, const _It _Last, _Pr _Pred, _Pj _Proj) { + // clang-format on // insertion sort [_First, _Last) if (_First == _Last) { // empty range is sorted @@ -7466,7 +7467,7 @@ namespace ranges { for (auto _Mid = _First; ++_Mid != _Last;) { // order next element iter_value_t<_It> _Val = _RANGES iter_move(_Mid); - auto _Hole = _Mid; + auto _Hole = _Mid; for (auto _Prev = _Hole;;) { --_Prev; @@ -7483,9 +7484,11 @@ namespace ranges { } } + // clang-format off template requires sortable<_It, _Pr, _Pj> - constexpr void _Med3_unchecked(_It _First, _It _Mid, _It _Last, _Pr _Pred, _Pj _Proj) { + constexpr void _Med3_common(_It _First, _It _Mid, _It _Last, _Pr _Pred, _Pj _Proj) { + // clang-format on // sort median of three elements to middle if (_STD invoke(_Pred, _STD invoke(_Proj, *_Mid), _STD invoke(_Proj, *_First))) { _RANGES iter_swap(_Mid, _First); @@ -7503,33 +7506,37 @@ namespace ranges { } } + // clang-format off template requires sortable<_It, _Pr, _Pj> - constexpr void _Guess_median_unchecked(_It _First, _It _Mid, _It _Last, _Pr _Pred, _Pj _Proj) { + constexpr void _Guess_median_common(_It _First, _It _Mid, _It _Last, _Pr _Pred, _Pj _Proj) { + // clang-format on // sort median element to middle using _Diff = iter_difference_t<_It>; const _Diff _Count = _Last - _First; if (_Count > 40) { // Tukey's ninther const _Diff _Step = (_Count + 1) >> 3; // +1 can't overflow because range was made inclusive in caller const _Diff _Two_step = _Step << 1; // note: intentionally discards low-order bit - _Med3_unchecked(_First, _First + _Step, _First + _Two_step, _Pred, _Proj); - _Med3_unchecked(_Mid - _Step, _Mid, _Mid + _Step, _Pred, _Proj); - _Med3_unchecked(_Last - _Two_step, _Last - _Step, _Last, _Pred, _Proj); - _Med3_unchecked(_First + _Step, _Mid, _Last - _Step, _Pred, _Proj); + _Med3_common(_First, _First + _Step, _First + _Two_step, _Pred, _Proj); + _Med3_common(_Mid - _Step, _Mid, _Mid + _Step, _Pred, _Proj); + _Med3_common(_Last - _Two_step, _Last - _Step, _Last, _Pred, _Proj); + _Med3_common(_First + _Step, _Mid, _Last - _Step, _Pred, _Proj); } else { - _Med3_unchecked(_First, _Mid, _Last, _Pred, _Proj); + _Med3_common(_First, _Mid, _Last, _Pred, _Proj); } } + // clang-format off template requires sortable<_It, _Pr, _Pj> - _NODISCARD constexpr subrange<_It> _Partition_by_median_guess_unchecked( + _NODISCARD constexpr subrange<_It> _Partition_by_median_guess_common( _It _First, _It _Last, _Pr _Pred, _Pj _Proj) { + // clang-format on // Choose a pivot, partition [_First, _Last) into elements less than pivot, elements equal to pivot, and // elements greater than pivot; return the equal partition as a subrange. _It _Mid = _First + ((_Last - _First) >> 1); // shift for codegen - _RANGES _Guess_median_unchecked(_First, _Mid, _RANGES prev(_Last), _Pred, _Proj); + _Guess_median_common(_First, _Mid, _RANGES prev(_Last), _Pred, _Proj); _It _Pfirst = _Mid; _It _Plast = _RANGES next(_Pfirst); @@ -7539,8 +7546,7 @@ namespace ranges { --_Pfirst; } - while (_Plast < _Last - && !_STD invoke(_Pred, _STD invoke(_Proj, *_Plast), _STD invoke(_Proj, *_Pfirst)) + while (_Plast < _Last && !_STD invoke(_Pred, _STD invoke(_Proj, *_Plast), _STD invoke(_Proj, *_Pfirst)) && !_STD invoke(_Pred, _STD invoke(_Proj, *_Pfirst), _STD invoke(_Proj, *_Plast))) { ++_Plast; } @@ -7598,7 +7604,6 @@ namespace ranges { } } } - // clang-format on // VARIABLE ranges::sort class _Sort_fn : private _Not_quite_object { @@ -7608,7 +7613,7 @@ namespace ranges { // clang-format off template _Se, class _Pr = ranges::less, class _Pj = identity> requires sortable<_It, _Pr, _Pj> - _NODISCARD constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const { + constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const { // clang-format on _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_STD move(_First)); @@ -7622,10 +7627,10 @@ namespace ranges { // clang-format off template requires sortable, _Pr, _Pj> - _NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { + constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { // clang-format on - auto _ULast = _Get_final_iterator_unwrapped(_Range); auto _UFirst = _Ubegin(_Range); + auto _ULast = _Get_final_iterator_unwrapped(_Range); const auto _Count = _ULast - _UFirst; _Sort_common(_STD move(_UFirst), _ULast, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_iterator(_Range, _STD move(_ULast)); @@ -7633,36 +7638,34 @@ namespace ranges { private: template - _NODISCARD static constexpr void _Sort_common( - _It _First, _It _Last, iter_difference_t<_It> _Ideal, _Pr _Pred, _Pj _Proj) { + static constexpr void _Sort_common(_It _First, _It _Last, iter_difference_t<_It> _Ideal, _Pr _Pred, _Pj _Proj) { // sort [_First, _Last) with respect to _Pred and _Proj _STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>); _STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>); for (;;) { if (_Last - _First <= _ISORT_MAX) { // small - _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); + _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); return; } if (_Ideal <= 0) { // heap sort if too many divisions - _RANGES _Make_heap_common(_First, _Last, _Pred, _Proj); - _RANGES _Sort_heap_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); + _Make_heap_common(_First, _Last, _Pred, _Proj); + _Sort_heap_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); return; } // divide and conquer by quicksort - auto [_Mid_first, _Mid_last] = - _RANGES _Partition_by_median_guess_unchecked(_First, _Last, _Pred, _Proj); + auto [_Mid_first, _Mid_last] = _Partition_by_median_guess_common(_First, _Last, _Pred, _Proj); _Ideal = (_Ideal >> 1) + (_Ideal >> 2); // allow 1.5 log2(N) divisions if (_Mid_first - _First < _Last - _Mid_last) { // loop on second half - _Sort_common(_First, _Mid_first, _Ideal, _Pred, _Proj); - _First = _Mid_last; + _Sort_common(_First, _STD move(_Mid_first), _Ideal, _Pred, _Proj); + _First = _STD move(_Mid_last); } else { // loop on first half - _Sort_common(_Mid_last, _Last, _Ideal, _Pred, _Proj); - _Last = _Mid_first; + _Sort_common(_STD move(_Mid_last), _Last, _Ideal, _Pred, _Proj); + _Last = _STD move(_Mid_first); } } } @@ -8076,7 +8079,7 @@ namespace ranges { } while (_ISORT_MAX < _Last - _First) { // divide and conquer, ordering partition containing Nth - subrange<_It> _Mid = _RANGES _Partition_by_median_guess_unchecked(_First, _Last, _Pred, _Proj); + subrange<_It> _Mid = _Partition_by_median_guess_common(_First, _Last, _Pred, _Proj); if (_Mid.end() <= _Nth) { _First = _Mid.end(); @@ -8088,7 +8091,7 @@ namespace ranges { } // sort any remainder - _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _STD move(_Pred), _STD move(_Proj)); + _Insertion_sort_common(_STD move(_First), _STD move(_Last), _STD move(_Pred), _STD move(_Proj)); } };