[libcxx-commits] [libcxx] [libc++] Optimize std::is_heap_until (PR #209141)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jul 13 04:19:29 PDT 2026
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/209141
None
>From 732a97e86e6c43f81620cadcf85d4ee9dbe9aceb Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 13 Jul 2026 13:18:00 +0200
Subject: [PATCH] [libc++] Optimize std::is_heap_until
---
libcxx/include/__algorithm/is_heap_until.h | 50 ++++++++++---------
.../is.heap/ranges_is_heap_until.pass.cpp | 6 +++
2 files changed, 33 insertions(+), 23 deletions(-)
diff --git a/libcxx/include/__algorithm/is_heap_until.h b/libcxx/include/__algorithm/is_heap_until.h
index 7444d978e37f5..cb5ea0373a019 100644
--- a/libcxx/include/__algorithm/is_heap_until.h
+++ b/libcxx/include/__algorithm/is_heap_until.h
@@ -12,7 +12,6 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
#include <__config>
-#include <__iterator/iterator_traits.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -20,29 +19,34 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Compare, class _RandomAccessIterator>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
-__is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
- difference_type __len = __last - __first;
- difference_type __p = 0;
- difference_type __c = 1;
- _RandomAccessIterator __pp = __first;
- while (__c < __len) {
- _RandomAccessIterator __cp = __first + __c;
- if (__comp(*__pp, *__cp))
- return __cp;
- ++__c;
- ++__cp;
- if (__c == __len)
- return __last;
- if (__comp(*__pp, *__cp))
- return __cp;
- ++__p;
- ++__pp;
- __c = 2 * __p + 1;
+template <class _Compare, class _Iter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
+__is_heap_until(_Iter __first, _Iter __last, _Compare&& __comp) {
+ auto __count = __last - __first;
+
+ if (__count < 2)
+ return __last;
+
+ auto __parent_last = __first + (__count - 1) / 2;
+ auto __child = __first;
+ ++__child;
+ for (; __first != __parent_last; ++__first) {
+ if (__comp(*__first, *__child))
+ return __child;
+ ++__child;
+
+ if (__comp(*__first, *__child))
+ return __child;
+ ++__child;
}
- return __last;
+
+ if (__count % 2 == 0) {
+ if (__comp(*__first, *__child))
+ return __child;
+ ++__child;
+ }
+
+ return __child;
}
template <class _RandomAccessIterator, class _Compare>
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.heap.operations/is.heap/ranges_is_heap_until.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.heap.operations/is.heap/ranges_is_heap_until.pass.cpp
index 5fd119a21a98f..42a66fa5723d6 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.heap.operations/is.heap/ranges_is_heap_until.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.heap.operations/is.heap/ranges_is_heap_until.pass.cpp
@@ -100,6 +100,12 @@ constexpr void test_iter_sent() {
test_one<Iter, Sent>(std::array{2, 1}, 2);
// 2-element sequence, not a heap.
test_one<Iter, Sent>(std::array{1, 2}, 1);
+ // 3-element sequence, a heap.
+ test_one<Iter, Sent>(std::array{3, 2, 1}, 3);
+ // 3-element sequence, LHS not a heap.
+ test_one<Iter, Sent>(std::array{2, 3, 1}, 1);
+ // 3-element sequence, RHS not a heap.
+ test_one<Iter, Sent>(std::array{2, 1, 3}, 2);
// Longer sequence, a heap.
test_one<Iter, Sent>(std::array{8, 6, 7, 3, 4, 1, 5, 2}, 8);
// Longer sequence, not a heap.
More information about the libcxx-commits
mailing list