This commit is contained in:
Casey Carter 2020-08-12 12:45:48 -07:00 коммит произвёл GitHub
Родитель 3224307ff6
Коммит 4ce746ca4e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 166 добавлений и 23 удалений

Просмотреть файл

@ -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<iterator_t<_Rng>, _It>
constexpr move_backward_result<borrowed_iterator_t<_Rng>, _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
@ -6402,7 +6402,7 @@ namespace ranges {
// FUNCTION TEMPLATE make_heap
template <class _RanIt, class _Pr>
_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
@ -6431,8 +6431,8 @@ namespace ranges {
template <random_access_iterator _It, class _Pr, class _Pj>
requires sortable<_It, _Pr, _Pj>
constexpr void _Make_heap_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
// make nontrivial [_First, _Last) into a heap with respect to _Pred and _Proj
// clang-format on
// make [_First, _Last) into a heap with respect to _Pred and _Proj
using _Diff = iter_difference_t<_It>;
const _Diff _Bottom = _Last - _First;
for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen
@ -6452,6 +6452,7 @@ namespace ranges {
template <random_access_iterator _It, sentinel_for<_It> _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));
@ -6460,9 +6461,11 @@ namespace ranges {
return _First;
}
// clang-format off
template <random_access_range _Rng, class _Pr = ranges::less, class _Pj = identity>
requires sortable<iterator_t<_Rng>, _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_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
return _RANGES end(_Range);
@ -6472,7 +6475,6 @@ namespace ranges {
return _Rewrap_iterator(_Range, _STD move(_ULast));
}
}
// clang-format on
};
inline constexpr _Make_heap_fn make_heap{_Not_quite_object::_Construct_tag{}};
@ -6665,8 +6667,8 @@ namespace ranges {
template <random_access_iterator _It, class _Pr, class _Pj>
requires sortable<_It, _Pr, _Pj>
constexpr void _Sort_heap_common(const _It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
// order heap by repeatedly popping
// clang-format on
// order heap by repeatedly popping
for (; _Last - _First >= 2; --_Last) {
_RANGES _Pop_heap_unchecked(_First, _Last, _Pred, _Proj);
}
@ -6680,6 +6682,7 @@ namespace ranges {
template <random_access_iterator _It, sentinel_for<_It> _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));
@ -6688,9 +6691,11 @@ namespace ranges {
return _First;
}
// clang-format off
template <random_access_range _Rng, class _Pr = ranges::less, class _Pj = identity>
requires sortable<iterator_t<_Rng>, _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_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
return _RANGES end(_Range);
@ -6700,7 +6705,6 @@ namespace ranges {
return _Rewrap_iterator(_Range, _STD move(_ULast));
}
}
// clang-format on
};
inline constexpr _Sort_heap_fn sort_heap{_Not_quite_object::_Construct_tag{}};
@ -7628,6 +7632,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 {
@ -7635,6 +7640,7 @@ namespace ranges {
template <bidirectional_iterator _It, class _Pr, class _Pj>
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
@ -7643,7 +7649,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;
@ -7660,9 +7666,11 @@ namespace ranges {
}
}
// clang-format off
template <random_access_iterator _It, class _Pr, class _Pj>
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);
@ -7680,33 +7688,37 @@ namespace ranges {
}
}
// clang-format off
template <random_access_iterator _It, class _Pr, class _Pj>
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 <random_access_iterator _It, class _Pr, class _Pj>
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);
@ -7716,8 +7728,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;
}
@ -7775,10 +7786,76 @@ 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 <random_access_iterator _It, sentinel_for<_It> _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);
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 <random_access_range _Rng, class _Pr = ranges::less, class _Pj = identity>
requires sortable<iterator_t<_Rng>, _Pr, _Pj>
constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const {
// clang-format on
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));
}
private:
template <class _It, class _Pr, class _Pj>
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
_Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj);
return;
}
if (_Ideal <= 0) { // heap sort if too many divisions
_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] = _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, _STD move(_Mid_first), _Ideal, _Pred, _Proj);
_First = _STD move(_Mid_last);
} else { // loop on first half
_Sort_common(_STD move(_Mid_last), _Last, _Ideal, _Pred, _Proj);
_Last = _STD move(_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 <class _FwdIt, class _Ty, class _Pr>
@ -8184,7 +8261,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();
@ -8196,7 +8273,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));
}
};

Просмотреть файл

@ -298,6 +298,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

Просмотреть файл

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\concepts_matrix.lst

Просмотреть файл

@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <algorithm>
#include <array>
#include <cassert>
#include <concepts>
#include <ranges>
#include <utility>
#include <range_algorithm_support.hpp>
using namespace std;
using P = pair<int, int>;
// Validate dangling story
STATIC_ASSERT(same_as<decltype(ranges::sort(borrowed<false>{})), ranges::dangling>);
STATIC_ASSERT(same_as<decltype(ranges::sort(borrowed<true>{})), 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 <ranges::random_access_range R>
static constexpr void call() {
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163
if constexpr (!ranges::contiguous_range<R>)
#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<iterator_t<R>> 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<iterator_t<R>> 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<iterator_t<R>> auto result = sort(range, less{}, get_first);
assert(result == range.end());
assert(is_sorted(range, less{}, get_first));
}
}
}
};
int main() {
STATIC_ASSERT((test_random<instantiator, P>(), true));
test_random<instantiator, P>();
}