|
| 1 | +// __msvc_heap_algorithms.hpp internal header |
| 2 | + |
| 3 | +// Copyright (c) Microsoft Corporation. |
| 4 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 5 | + |
| 6 | +#ifndef __MSVC_HEAP_ALGORITHMS_HPP |
| 7 | +#define __MSVC_HEAP_ALGORITHMS_HPP |
| 8 | +#include <yvals_core.h> |
| 9 | +#if _STL_COMPILER_PREPROCESSOR |
| 10 | + |
| 11 | +#include <xutility> |
| 12 | + |
| 13 | +#pragma pack(push, _CRT_PACKING) |
| 14 | +#pragma warning(push, _STL_WARNING_LEVEL) |
| 15 | +#pragma warning(disable : _STL_DISABLED_WARNINGS) |
| 16 | +_STL_DISABLE_CLANG_WARNINGS |
| 17 | +#pragma push_macro("new") |
| 18 | +#undef new |
| 19 | + |
| 20 | +_STD_BEGIN |
| 21 | +template <class _RanIt, class _Ty, class _Pr> |
| 22 | +_CONSTEXPR20 void _Push_heap_by_index( |
| 23 | + _RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Top, _Ty&& _Val, _Pr _Pred) { |
| 24 | + // percolate _Hole to _Top or where _Val belongs |
| 25 | + using _Diff = _Iter_diff_t<_RanIt>; |
| 26 | + for (_Diff _Idx = (_Hole - 1) >> 1; // shift for codegen |
| 27 | + _Top < _Hole && _DEBUG_LT_PRED(_Pred, *(_First + _Idx), _Val); _Idx = (_Hole - 1) >> 1) { // shift for codegen |
| 28 | + // move _Hole up to parent |
| 29 | + *(_First + _Hole) = _STD move(*(_First + _Idx)); |
| 30 | + _Hole = _Idx; |
| 31 | + } |
| 32 | + |
| 33 | + *(_First + _Hole) = _STD forward<_Ty>(_Val); // drop _Val into final hole |
| 34 | +} |
| 35 | + |
| 36 | +_EXPORT_STD template <class _RanIt, class _Pr> |
| 37 | +_CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { |
| 38 | + // push *(_Last - 1) onto heap at [_First, _Last - 1) |
| 39 | + _STD _Adl_verify_range(_First, _Last); |
| 40 | + const auto _UFirst = _STD _Get_unwrapped(_First); |
| 41 | + auto _ULast = _STD _Get_unwrapped(_Last); |
| 42 | + using _Diff = _Iter_diff_t<_RanIt>; |
| 43 | + _Diff _Count = _ULast - _UFirst; |
| 44 | + if (2 <= _Count) { |
| 45 | + _Iter_value_t<_RanIt> _Val(_STD move(*--_ULast)); |
| 46 | + _STD _Push_heap_by_index(_UFirst, --_Count, _Diff(0), _STD move(_Val), _STD _Pass_fn(_Pred)); |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +_EXPORT_STD template <class _RanIt> |
| 51 | +_CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last) { |
| 52 | + // push *(_Last - 1) onto heap at [_First, _Last - 1) |
| 53 | + _STD push_heap(_First, _Last, less<>{}); |
| 54 | +} |
| 55 | + |
| 56 | +template <class _RanIt, class _Ty, class _Pr> |
| 57 | +_CONSTEXPR20 void _Pop_heap_hole_by_index( |
| 58 | + _RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Bottom, _Ty&& _Val, _Pr _Pred) { |
| 59 | + // percolate _Hole to _Bottom, then push _Val |
| 60 | + _STL_INTERNAL_CHECK(_Bottom > 0); |
| 61 | + |
| 62 | + using _Diff = _Iter_diff_t<_RanIt>; |
| 63 | + const _Diff _Top = _Hole; |
| 64 | + _Diff _Idx = _Hole; |
| 65 | + |
| 66 | + // Check whether _Idx can have a child before calculating that child's index, since |
| 67 | + // calculating the child's index can trigger integer overflows |
| 68 | + const _Diff _Max_sequence_non_leaf = (_Bottom - 1) >> 1; // shift for codegen |
| 69 | + while (_Idx < _Max_sequence_non_leaf) { // move _Hole down to larger child |
| 70 | + _Idx = 2 * _Idx + 2; |
| 71 | + if (_DEBUG_LT_PRED(_Pred, *(_First + _Idx), *(_First + (_Idx - 1)))) { |
| 72 | + --_Idx; |
| 73 | + } |
| 74 | + *(_First + _Hole) = _STD move(*(_First + _Idx)); |
| 75 | + _Hole = _Idx; |
| 76 | + } |
| 77 | + |
| 78 | + if (_Idx == _Max_sequence_non_leaf && _Bottom % 2 == 0) { // only child at bottom, move _Hole down to it |
| 79 | + *(_First + _Hole) = _STD move(*(_First + (_Bottom - 1))); |
| 80 | + _Hole = _Bottom - 1; |
| 81 | + } |
| 82 | + |
| 83 | + _STD _Push_heap_by_index(_First, _Hole, _Top, _STD forward<_Ty>(_Val), _Pred); |
| 84 | +} |
| 85 | + |
| 86 | +template <class _RanIt, class _Ty, class _Pr> |
| 87 | +_CONSTEXPR20 void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _Dest, _Ty&& _Val, _Pr _Pred) { |
| 88 | + // pop *_First to *_Dest and reheap |
| 89 | + // precondition: _First != _Last |
| 90 | + // precondition: _First != _Dest |
| 91 | + *_Dest = _STD move(*_First); |
| 92 | + using _Diff = _Iter_diff_t<_RanIt>; |
| 93 | + _STD _Pop_heap_hole_by_index( |
| 94 | + _First, static_cast<_Diff>(0), static_cast<_Diff>(_Last - _First), _STD forward<_Ty>(_Val), _Pred); |
| 95 | +} |
| 96 | + |
| 97 | +template <class _RanIt, class _Pr> |
| 98 | +_CONSTEXPR20 void _Pop_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { |
| 99 | + // pop *_First to *(_Last - 1) and reheap |
| 100 | + if (2 <= _Last - _First) { |
| 101 | + --_Last; |
| 102 | + _Iter_value_t<_RanIt> _Val(_STD move(*_Last)); |
| 103 | + _STD _Pop_heap_hole_unchecked(_First, _Last, _Last, _STD move(_Val), _Pred); |
| 104 | + } |
| 105 | +} |
| 106 | + |
| 107 | +_EXPORT_STD template <class _RanIt, class _Pr> |
| 108 | +_CONSTEXPR20 void pop_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { |
| 109 | + // pop *_First to *(_Last - 1) and reheap |
| 110 | + _STD _Adl_verify_range(_First, _Last); |
| 111 | + _STD _Pop_heap_unchecked(_STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last), _STD _Pass_fn(_Pred)); |
| 112 | +} |
| 113 | + |
| 114 | +_EXPORT_STD template <class _RanIt> |
| 115 | +_CONSTEXPR20 void pop_heap(_RanIt _First, _RanIt _Last) { |
| 116 | + // pop *_First to *(_Last - 1) and reheap |
| 117 | + _STD pop_heap(_First, _Last, less<>{}); |
| 118 | +} |
| 119 | + |
| 120 | +template <class _RanIt, class _Pr> |
| 121 | +_CONSTEXPR20 void _Make_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { |
| 122 | + // make [_First, _Last) into a heap |
| 123 | + using _Diff = _Iter_diff_t<_RanIt>; |
| 124 | + _Diff _Bottom = _Last - _First; |
| 125 | + for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen |
| 126 | + // reheap top half, bottom to top |
| 127 | + --_Hole; |
| 128 | + _Iter_value_t<_RanIt> _Val(_STD move(*(_First + _Hole))); |
| 129 | + _STD _Pop_heap_hole_by_index(_First, _Hole, _Bottom, _STD move(_Val), _Pred); |
| 130 | + } |
| 131 | +} |
| 132 | + |
| 133 | +_EXPORT_STD template <class _RanIt, class _Pr> |
| 134 | +_CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // make [_First, _Last) into a heap |
| 135 | + _STD _Adl_verify_range(_First, _Last); |
| 136 | + _STD _Make_heap_unchecked(_STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last), _STD _Pass_fn(_Pred)); |
| 137 | +} |
| 138 | + |
| 139 | +_EXPORT_STD template <class _RanIt> |
| 140 | +_CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last) { // make [_First, _Last) into a heap |
| 141 | + _STD make_heap(_First, _Last, less<>{}); |
| 142 | +} |
| 143 | +_STD_END |
| 144 | + |
| 145 | +#pragma pop_macro("new") |
| 146 | +_STL_RESTORE_CLANG_WARNINGS |
| 147 | +#pragma warning(pop) |
| 148 | +#pragma pack(pop) |
| 149 | +#endif // _STL_COMPILER_PREPROCESSOR |
| 150 | +#endif // __MSVC_HEAP_ALGORITHMS_HPP |
0 commit comments