[libcxx-commits] [PATCH] D118003: [libc++] Floyd's improvement to pop_heap
Arthur O'Dwyer via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Mar 7 10:03:28 PST 2022
Quuxplusone updated this revision to Diff 413538.
Quuxplusone marked an inline comment as done.
Quuxplusone added a comment.
`s/typedef/using/`
`s/_VSTD/std/`
I claim this is ready to land. @ldionne?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D118003/new/
https://reviews.llvm.org/D118003
Files:
libcxx/include/__algorithm/pop_heap.h
libcxx/include/__algorithm/sift_down.h
Index: libcxx/include/__algorithm/sift_down.h
===================================================================
--- libcxx/include/__algorithm/sift_down.h
+++ libcxx/include/__algorithm/sift_down.h
@@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_SIFT_DOWN_H
#include <__config>
+#include <__debug>
#include <__iterator/iterator_traits.h>
#include <__utility/move.h>
@@ -73,6 +74,38 @@
*__start = _VSTD::move(__top);
}
+template <class _Compare, class _RandomAccessIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator
+__floyd_sift_down(_RandomAccessIterator __first, _Compare __comp,
+ typename iterator_traits<_RandomAccessIterator>::difference_type __len)
+{
+ using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
+ _LIBCPP_ASSERT(__len >= 2, "shouldn't be called unless __len >= 2");
+
+ _RandomAccessIterator __hole = __first;
+ _RandomAccessIterator __child_i = __first;
+ difference_type __child = 0;
+
+ while (true) {
+ __child_i += difference_type(__child + 1);
+ __child = 2 * __child + 1;
+
+ if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) {
+ // right-child exists and is greater than left-child
+ ++__child_i;
+ ++__child;
+ }
+
+ // swap __hole with its largest child
+ *__hole = std::move(*__child_i);
+ __hole = std::move(__child_i);
+
+ // if __hole is now a leaf, we're done
+ if (__child > (__len - 2) / 2)
+ return __hole;
+ }
+}
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_SIFT_DOWN_H
Index: libcxx/include/__algorithm/pop_heap.h
===================================================================
--- libcxx/include/__algorithm/pop_heap.h
+++ libcxx/include/__algorithm/pop_heap.h
@@ -11,10 +11,11 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
+#include <__algorithm/push_heap.h>
#include <__algorithm/sift_down.h>
#include <__config>
#include <__iterator/iterator_traits.h>
-#include <__utility/swap.h>
+#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -28,10 +29,21 @@
__pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len)
{
+ using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
+
if (__len > 1)
{
- swap(*__first, *--__last);
- _VSTD::__sift_down<_Compare>(__first, __comp, __len - 1, __first);
+ value_type __top = std::move(*__first); // create a hole at __first
+ _RandomAccessIterator __hole = std::__floyd_sift_down<_Compare>(__first, __comp, __len);
+ --__last;
+ if (__hole == __last) {
+ *__hole = std::move(__top);
+ } else {
+ *__hole = std::move(*__last);
+ ++__hole;
+ *__last = std::move(__top);
+ std::__sift_up<_Compare>(__first, __hole, __comp, __hole - __first);
+ }
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D118003.413538.patch
Type: text/x-patch
Size: 3155 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20220307/7808d3c7/attachment-0001.bin>
More information about the libcxx-commits
mailing list