[libcxx-commits] [libcxx] 122efb2 - [libc++] Optimize std::is_heap_until (#209141)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 16 07:46:50 PDT 2026


Author: Nikolas Klauser
Date: 2026-07-16T16:46:46+02:00
New Revision: 122efb26893f7e214d0223615c3a4abcc0ac7796

URL: https://github.com/llvm/llvm-project/commit/122efb26893f7e214d0223615c3a4abcc0ac7796
DIFF: https://github.com/llvm/llvm-project/commit/122efb26893f7e214d0223615c3a4abcc0ac7796.diff

LOG: [libc++] Optimize std::is_heap_until (#209141)

Fixes #208299

Added: 
    

Modified: 
    libcxx/include/__algorithm/is_heap_until.h
    libcxx/test/std/algorithms/alg.sorting/alg.heap.operations/is.heap/ranges_is_heap_until.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__algorithm/is_heap_until.h b/libcxx/include/__algorithm/is_heap_until.h
index 7444d978e37f5..c05cc2177ae90 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,37 @@
 
 _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>::
diff erence_type 
diff erence_type;
-  
diff erence_type __len      = __last - __first;
-  
diff erence_type __p        = 0;
-  
diff erence_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;
+
+  // This points to one past the last parent that has two children.
+  // Integer division handles the case where the last parent has a single child.
+  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 the heap is even-sized, the last parent has a single child, handled here.
+  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