
libc++ has started splicing standard library headers into much more fine-grained content for maintainability. It's very likely that outdated and naive tooling (some of which is outside of LLVM's scope) will suggest users include things such as <__ranges/access.h> instead of <ranges>, and Hyrum's law suggests that users will eventually begin to rely on this without the help of tooling. As such, this commit intends to protect users from themselves, by making it a hard error for anyone outside of the standard library to include libc++ detail headers. Differential Revision: https://reviews.llvm.org/D106124
80 lines
2.6 KiB
C++
80 lines
2.6 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___ALGORITHM_SIFT_DOWN_H
|
|
#define _LIBCPP___ALGORITHM_SIFT_DOWN_H
|
|
|
|
#include <__config>
|
|
#include <__iterator/iterator_traits.h>
|
|
#include <__utility/move.h>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
# pragma GCC system_header
|
|
# pragma clang include_instead(<algorithm>)
|
|
#endif
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
template <class _Compare, class _RandomAccessIterator>
|
|
_LIBCPP_CONSTEXPR_AFTER_CXX11 void
|
|
__sift_down(_RandomAccessIterator __first, _Compare __comp,
|
|
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
|
|
_RandomAccessIterator __start)
|
|
{
|
|
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
|
|
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
|
|
// left-child of __start is at 2 * __start + 1
|
|
// right-child of __start is at 2 * __start + 2
|
|
difference_type __child = __start - __first;
|
|
|
|
if (__len < 2 || (__len - 2) / 2 < __child)
|
|
return;
|
|
|
|
__child = 2 * __child + 1;
|
|
_RandomAccessIterator __child_i = __first + __child;
|
|
|
|
if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) {
|
|
// right-child exists and is greater than left-child
|
|
++__child_i;
|
|
++__child;
|
|
}
|
|
|
|
// check if we are in heap-order
|
|
if (__comp(*__child_i, *__start))
|
|
// we are, __start is larger than its largest child
|
|
return;
|
|
|
|
value_type __top(_VSTD::move(*__start));
|
|
do
|
|
{
|
|
// we are not in heap-order, swap the parent with its largest child
|
|
*__start = _VSTD::move(*__child_i);
|
|
__start = __child_i;
|
|
|
|
if ((__len - 2) / 2 < __child)
|
|
break;
|
|
|
|
// recompute the child based off of the updated parent
|
|
__child = 2 * __child + 1;
|
|
__child_i = __first + __child;
|
|
|
|
if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) {
|
|
// right-child exists and is greater than left-child
|
|
++__child_i;
|
|
++__child;
|
|
}
|
|
|
|
// check if we are in heap-order
|
|
} while (!__comp(*__child_i, __top));
|
|
*__start = _VSTD::move(__top);
|
|
}
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif // _LIBCPP___ALGORITHM_SIFT_DOWN_H
|