1e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 2e78f53d1SNikolas Klauser // 3e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e78f53d1SNikolas Klauser // 7e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 8e78f53d1SNikolas Klauser 9*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___ALGORITHM_SIFT_DOWN_H 10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___ALGORITHM_SIFT_DOWN_H 11e78f53d1SNikolas Klauser 1273fbae83SNikolas Klauser #include <__cxx03/__algorithm/iterator_operations.h> 1373fbae83SNikolas Klauser #include <__cxx03/__assert> 1473fbae83SNikolas Klauser #include <__cxx03/__config> 1573fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h> 1673fbae83SNikolas Klauser #include <__cxx03/__utility/move.h> 17e78f53d1SNikolas Klauser 18e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19e78f53d1SNikolas Klauser # pragma GCC system_header 20e78f53d1SNikolas Klauser #endif 21e78f53d1SNikolas Klauser 22e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS 2373fbae83SNikolas Klauser #include <__cxx03/__undef_macros> 24e78f53d1SNikolas Klauser 25e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 26e78f53d1SNikolas Klauser 27e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> 28e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void 29e78f53d1SNikolas Klauser __sift_down(_RandomAccessIterator __first, 30e78f53d1SNikolas Klauser _Compare&& __comp, 31e78f53d1SNikolas Klauser typename iterator_traits<_RandomAccessIterator>::difference_type __len, 32e78f53d1SNikolas Klauser _RandomAccessIterator __start) { 33e78f53d1SNikolas Klauser using _Ops = _IterOps<_AlgPolicy>; 34e78f53d1SNikolas Klauser 35e78f53d1SNikolas Klauser typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 36e78f53d1SNikolas Klauser typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; 37e78f53d1SNikolas Klauser // left-child of __start is at 2 * __start + 1 38e78f53d1SNikolas Klauser // right-child of __start is at 2 * __start + 2 39e78f53d1SNikolas Klauser difference_type __child = __start - __first; 40e78f53d1SNikolas Klauser 41e78f53d1SNikolas Klauser if (__len < 2 || (__len - 2) / 2 < __child) 42e78f53d1SNikolas Klauser return; 43e78f53d1SNikolas Klauser 44e78f53d1SNikolas Klauser __child = 2 * __child + 1; 45e78f53d1SNikolas Klauser _RandomAccessIterator __child_i = __first + __child; 46e78f53d1SNikolas Klauser 47e78f53d1SNikolas Klauser if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { 48e78f53d1SNikolas Klauser // right-child exists and is greater than left-child 49e78f53d1SNikolas Klauser ++__child_i; 50e78f53d1SNikolas Klauser ++__child; 51e78f53d1SNikolas Klauser } 52e78f53d1SNikolas Klauser 53e78f53d1SNikolas Klauser // check if we are in heap-order 54e78f53d1SNikolas Klauser if (__comp(*__child_i, *__start)) 55e78f53d1SNikolas Klauser // we are, __start is larger than its largest child 56e78f53d1SNikolas Klauser return; 57e78f53d1SNikolas Klauser 58e78f53d1SNikolas Klauser value_type __top(_Ops::__iter_move(__start)); 59e78f53d1SNikolas Klauser do { 60e78f53d1SNikolas Klauser // we are not in heap-order, swap the parent with its largest child 61e78f53d1SNikolas Klauser *__start = _Ops::__iter_move(__child_i); 62e78f53d1SNikolas Klauser __start = __child_i; 63e78f53d1SNikolas Klauser 64e78f53d1SNikolas Klauser if ((__len - 2) / 2 < __child) 65e78f53d1SNikolas Klauser break; 66e78f53d1SNikolas Klauser 67e78f53d1SNikolas Klauser // recompute the child based off of the updated parent 68e78f53d1SNikolas Klauser __child = 2 * __child + 1; 69e78f53d1SNikolas Klauser __child_i = __first + __child; 70e78f53d1SNikolas Klauser 71e78f53d1SNikolas Klauser if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { 72e78f53d1SNikolas Klauser // right-child exists and is greater than left-child 73e78f53d1SNikolas Klauser ++__child_i; 74e78f53d1SNikolas Klauser ++__child; 75e78f53d1SNikolas Klauser } 76e78f53d1SNikolas Klauser 77e78f53d1SNikolas Klauser // check if we are in heap-order 78e78f53d1SNikolas Klauser } while (!__comp(*__child_i, __top)); 79e78f53d1SNikolas Klauser *__start = std::move(__top); 80e78f53d1SNikolas Klauser } 81e78f53d1SNikolas Klauser 82e78f53d1SNikolas Klauser template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> 83e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator __floyd_sift_down( 84e78f53d1SNikolas Klauser _RandomAccessIterator __first, 85e78f53d1SNikolas Klauser _Compare&& __comp, 86e78f53d1SNikolas Klauser typename iterator_traits<_RandomAccessIterator>::difference_type __len) { 87e78f53d1SNikolas Klauser using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; 88e78f53d1SNikolas Klauser _LIBCPP_ASSERT_INTERNAL(__len >= 2, "shouldn't be called unless __len >= 2"); 89e78f53d1SNikolas Klauser 90e78f53d1SNikolas Klauser _RandomAccessIterator __hole = __first; 91e78f53d1SNikolas Klauser _RandomAccessIterator __child_i = __first; 92e78f53d1SNikolas Klauser difference_type __child = 0; 93e78f53d1SNikolas Klauser 94e78f53d1SNikolas Klauser while (true) { 95e78f53d1SNikolas Klauser __child_i += difference_type(__child + 1); 96e78f53d1SNikolas Klauser __child = 2 * __child + 1; 97e78f53d1SNikolas Klauser 98e78f53d1SNikolas Klauser if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) { 99e78f53d1SNikolas Klauser // right-child exists and is greater than left-child 100e78f53d1SNikolas Klauser ++__child_i; 101e78f53d1SNikolas Klauser ++__child; 102e78f53d1SNikolas Klauser } 103e78f53d1SNikolas Klauser 104e78f53d1SNikolas Klauser // swap __hole with its largest child 105e78f53d1SNikolas Klauser *__hole = _IterOps<_AlgPolicy>::__iter_move(__child_i); 106e78f53d1SNikolas Klauser __hole = __child_i; 107e78f53d1SNikolas Klauser 108e78f53d1SNikolas Klauser // if __hole is now a leaf, we're done 109e78f53d1SNikolas Klauser if (__child > (__len - 2) / 2) 110e78f53d1SNikolas Klauser return __hole; 111e78f53d1SNikolas Klauser } 112e78f53d1SNikolas Klauser } 113e78f53d1SNikolas Klauser 114e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 115e78f53d1SNikolas Klauser 116e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS 117e78f53d1SNikolas Klauser 118*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___ALGORITHM_SIFT_DOWN_H 119