1  // Heap implementation -*- C++ -*-
       2  
       3  // Copyright (C) 2001-2023 Free Software Foundation, Inc.
       4  //
       5  // This file is part of the GNU ISO C++ Library.  This library is free
       6  // software; you can redistribute it and/or modify it under the
       7  // terms of the GNU General Public License as published by the
       8  // Free Software Foundation; either version 3, or (at your option)
       9  // any later version.
      10  
      11  // This library is distributed in the hope that it will be useful,
      12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  // GNU General Public License for more details.
      15  
      16  // Under Section 7 of GPL version 3, you are granted additional
      17  // permissions described in the GCC Runtime Library Exception, version
      18  // 3.1, as published by the Free Software Foundation.
      19  
      20  // You should have received a copy of the GNU General Public License and
      21  // a copy of the GCC Runtime Library Exception along with this program;
      22  // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  // <http://www.gnu.org/licenses/>.
      24  
      25  /*
      26   *
      27   * Copyright (c) 1994
      28   * Hewlett-Packard Company
      29   *
      30   * Permission to use, copy, modify, distribute and sell this software
      31   * and its documentation for any purpose is hereby granted without fee,
      32   * provided that the above copyright notice appear in all copies and
      33   * that both that copyright notice and this permission notice appear
      34   * in supporting documentation.  Hewlett-Packard Company makes no
      35   * representations about the suitability of this software for any
      36   * purpose.  It is provided "as is" without express or implied warranty.
      37   *
      38   * Copyright (c) 1997
      39   * Silicon Graphics Computer Systems, Inc.
      40   *
      41   * Permission to use, copy, modify, distribute and sell this software
      42   * and its documentation for any purpose is hereby granted without fee,
      43   * provided that the above copyright notice appear in all copies and
      44   * that both that copyright notice and this permission notice appear
      45   * in supporting documentation.  Silicon Graphics makes no
      46   * representations about the suitability of this software for any
      47   * purpose.  It is provided "as is" without express or implied warranty.
      48   */
      49  
      50  /** @file bits/stl_heap.h
      51   *  This is an internal header file, included by other library headers.
      52   *  Do not attempt to use it directly. @headername{queue}
      53   */
      54  
      55  #ifndef _STL_HEAP_H
      56  #define _STL_HEAP_H 1
      57  
      58  #include <debug/debug.h>
      59  #include <bits/move.h>
      60  #include <bits/predefined_ops.h>
      61  #include <bits/stl_iterator_base_funcs.h>
      62  
      63  namespace std _GLIBCXX_VISIBILITY(default)
      64  {
      65  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      66  
      67    /**
      68     * @defgroup heap_algorithms Heap
      69     * @ingroup sorting_algorithms
      70     */
      71  
      72    template<typename _RandomAccessIterator, typename _Distance,
      73  	   typename _Compare>
      74      _GLIBCXX20_CONSTEXPR
      75      _Distance
      76      __is_heap_until(_RandomAccessIterator __first, _Distance __n,
      77  		    _Compare& __comp)
      78      {
      79        _Distance __parent = 0;
      80        for (_Distance __child = 1; __child < __n; ++__child)
      81  	{
      82  	  if (__comp(__first + __parent, __first + __child))
      83  	    return __child;
      84  	  if ((__child & 1) == 0)
      85  	    ++__parent;
      86  	}
      87        return __n;
      88      }
      89  
      90    // __is_heap, a predicate testing whether or not a range is a heap.
      91    // This function is an extension, not part of the C++ standard.
      92    template<typename _RandomAccessIterator, typename _Distance>
      93      _GLIBCXX20_CONSTEXPR
      94      inline bool
      95      __is_heap(_RandomAccessIterator __first, _Distance __n)
      96      {
      97        __gnu_cxx::__ops::_Iter_less_iter __comp;
      98        return std::__is_heap_until(__first, __n, __comp) == __n;
      99      }
     100  
     101    template<typename _RandomAccessIterator, typename _Compare,
     102  	   typename _Distance>
     103      _GLIBCXX20_CONSTEXPR
     104      inline bool
     105      __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
     106      {
     107        typedef __decltype(__comp) _Cmp;
     108        __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
     109        return std::__is_heap_until(__first, __n, __cmp) == __n;
     110      }
     111  
     112    template<typename _RandomAccessIterator>
     113      _GLIBCXX20_CONSTEXPR
     114      inline bool
     115      __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
     116      { return std::__is_heap(__first, std::distance(__first, __last)); }
     117  
     118    template<typename _RandomAccessIterator, typename _Compare>
     119      _GLIBCXX20_CONSTEXPR
     120      inline bool
     121      __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     122  	      _Compare __comp)
     123      {
     124        return std::__is_heap(__first, _GLIBCXX_MOVE(__comp),
     125  			    std::distance(__first, __last));
     126      }
     127  
     128    // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
     129    // + is_heap and is_heap_until in C++0x.
     130  
     131    template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
     132  	   typename _Compare>
     133      _GLIBCXX20_CONSTEXPR
     134      void
     135      __push_heap(_RandomAccessIterator __first,
     136  		_Distance __holeIndex, _Distance __topIndex, _Tp __value,
     137  		_Compare& __comp)
     138      {
     139        _Distance __parent = (__holeIndex - 1) / 2;
     140        while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
     141  	{
     142  	  *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
     143  	  __holeIndex = __parent;
     144  	  __parent = (__holeIndex - 1) / 2;
     145  	}
     146        *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
     147      }
     148  
     149    /**
     150     *  @brief  Push an element onto a heap.
     151     *  @param  __first  Start of heap.
     152     *  @param  __last   End of heap + element.
     153     *  @ingroup heap_algorithms
     154     *
     155     *  This operation pushes the element at last-1 onto the valid heap
     156     *  over the range [__first,__last-1).  After completion,
     157     *  [__first,__last) is a valid heap.
     158    */
     159    template<typename _RandomAccessIterator>
     160      _GLIBCXX20_CONSTEXPR
     161      inline void
     162      push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
     163      {
     164        typedef typename iterator_traits<_RandomAccessIterator>::value_type
     165  	  _ValueType;
     166        typedef typename iterator_traits<_RandomAccessIterator>::difference_type
     167  	  _DistanceType;
     168  
     169        // concept requirements
     170        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     171  	    _RandomAccessIterator>)
     172        __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
     173        __glibcxx_requires_valid_range(__first, __last);
     174        __glibcxx_requires_irreflexive(__first, __last);
     175        __glibcxx_requires_heap(__first, __last - 1);
     176  
     177        __gnu_cxx::__ops::_Iter_less_val __comp;
     178        _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
     179        std::__push_heap(__first, _DistanceType((__last - __first) - 1),
     180  		       _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
     181      }
     182  
     183    /**
     184     *  @brief  Push an element onto a heap using comparison functor.
     185     *  @param  __first  Start of heap.
     186     *  @param  __last   End of heap + element.
     187     *  @param  __comp   Comparison functor.
     188     *  @ingroup heap_algorithms
     189     *
     190     *  This operation pushes the element at __last-1 onto the valid
     191     *  heap over the range [__first,__last-1).  After completion,
     192     *  [__first,__last) is a valid heap.  Compare operations are
     193     *  performed using comp.
     194    */
     195    template<typename _RandomAccessIterator, typename _Compare>
     196      _GLIBCXX20_CONSTEXPR
     197      inline void
     198      push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     199  	      _Compare __comp)
     200      {
     201        typedef typename iterator_traits<_RandomAccessIterator>::value_type
     202  	  _ValueType;
     203        typedef typename iterator_traits<_RandomAccessIterator>::difference_type
     204  	  _DistanceType;
     205  
     206        // concept requirements
     207        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     208  	    _RandomAccessIterator>)
     209        __glibcxx_requires_valid_range(__first, __last);
     210        __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
     211        __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
     212  
     213        __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
     214  	__cmp(_GLIBCXX_MOVE(__comp));
     215        _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
     216        std::__push_heap(__first, _DistanceType((__last - __first) - 1),
     217  		       _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
     218      }
     219  
     220    template<typename _RandomAccessIterator, typename _Distance,
     221  	   typename _Tp, typename _Compare>
     222      _GLIBCXX20_CONSTEXPR
     223      void
     224      __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
     225  		  _Distance __len, _Tp __value, _Compare __comp)
     226      {
     227        const _Distance __topIndex = __holeIndex;
     228        _Distance __secondChild = __holeIndex;
     229        while (__secondChild < (__len - 1) / 2)
     230  	{
     231  	  __secondChild = 2 * (__secondChild + 1);
     232  	  if (__comp(__first + __secondChild,
     233  		     __first + (__secondChild - 1)))
     234  	    __secondChild--;
     235  	  *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
     236  	  __holeIndex = __secondChild;
     237  	}
     238        if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
     239  	{
     240  	  __secondChild = 2 * (__secondChild + 1);
     241  	  *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
     242  						     + (__secondChild - 1)));
     243  	  __holeIndex = __secondChild - 1;
     244  	}
     245        __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
     246  	__cmp(_GLIBCXX_MOVE(__comp));
     247        std::__push_heap(__first, __holeIndex, __topIndex,
     248  		       _GLIBCXX_MOVE(__value), __cmp);
     249      }
     250  
     251    template<typename _RandomAccessIterator, typename _Compare>
     252      _GLIBCXX20_CONSTEXPR
     253      inline void
     254      __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     255  	       _RandomAccessIterator __result, _Compare& __comp)
     256      {
     257        typedef typename iterator_traits<_RandomAccessIterator>::value_type
     258  	_ValueType;
     259        typedef typename iterator_traits<_RandomAccessIterator>::difference_type
     260  	_DistanceType;
     261  
     262        _ValueType __value = _GLIBCXX_MOVE(*__result);
     263        *__result = _GLIBCXX_MOVE(*__first);
     264        std::__adjust_heap(__first, _DistanceType(0),
     265  			 _DistanceType(__last - __first),
     266  			 _GLIBCXX_MOVE(__value), __comp);
     267      }
     268  
     269    /**
     270     *  @brief  Pop an element off a heap.
     271     *  @param  __first  Start of heap.
     272     *  @param  __last   End of heap.
     273     *  @pre    [__first, __last) is a valid, non-empty range.
     274     *  @ingroup heap_algorithms
     275     *
     276     *  This operation pops the top of the heap.  The elements __first
     277     *  and __last-1 are swapped and [__first,__last-1) is made into a
     278     *  heap.
     279    */
     280    template<typename _RandomAccessIterator>
     281      _GLIBCXX20_CONSTEXPR
     282      inline void
     283      pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
     284      {
     285        // concept requirements
     286        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     287  	    _RandomAccessIterator>)
     288        __glibcxx_function_requires(_LessThanComparableConcept<
     289  	typename iterator_traits<_RandomAccessIterator>::value_type>)
     290        __glibcxx_requires_non_empty_range(__first, __last);
     291        __glibcxx_requires_valid_range(__first, __last);
     292        __glibcxx_requires_irreflexive(__first, __last);
     293        __glibcxx_requires_heap(__first, __last);
     294  
     295        if (__last - __first > 1)
     296  	{
     297  	  --__last;
     298  	  __gnu_cxx::__ops::_Iter_less_iter __comp;
     299  	  std::__pop_heap(__first, __last, __last, __comp);
     300  	}
     301      }
     302  
     303    /**
     304     *  @brief  Pop an element off a heap using comparison functor.
     305     *  @param  __first  Start of heap.
     306     *  @param  __last   End of heap.
     307     *  @param  __comp   Comparison functor to use.
     308     *  @ingroup heap_algorithms
     309     *
     310     *  This operation pops the top of the heap.  The elements __first
     311     *  and __last-1 are swapped and [__first,__last-1) is made into a
     312     *  heap.  Comparisons are made using comp.
     313    */
     314    template<typename _RandomAccessIterator, typename _Compare>
     315      _GLIBCXX20_CONSTEXPR
     316      inline void
     317      pop_heap(_RandomAccessIterator __first,
     318  	     _RandomAccessIterator __last, _Compare __comp)
     319      {
     320        // concept requirements
     321        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     322  	    _RandomAccessIterator>)
     323        __glibcxx_requires_valid_range(__first, __last);
     324        __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
     325        __glibcxx_requires_non_empty_range(__first, __last);
     326        __glibcxx_requires_heap_pred(__first, __last, __comp);
     327  
     328        if (__last - __first > 1)
     329  	{
     330  	  typedef __decltype(__comp) _Cmp;
     331  	  __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
     332  	  --__last;
     333  	  std::__pop_heap(__first, __last, __last, __cmp);
     334  	}
     335      }
     336  
     337    template<typename _RandomAccessIterator, typename _Compare>
     338      _GLIBCXX20_CONSTEXPR
     339      void
     340      __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     341  		_Compare& __comp)
     342      {
     343        typedef typename iterator_traits<_RandomAccessIterator>::value_type
     344  	  _ValueType;
     345        typedef typename iterator_traits<_RandomAccessIterator>::difference_type
     346  	  _DistanceType;
     347  
     348        if (__last - __first < 2)
     349  	return;
     350  
     351        const _DistanceType __len = __last - __first;
     352        _DistanceType __parent = (__len - 2) / 2;
     353        while (true)
     354  	{
     355  	  _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
     356  	  std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
     357  			     __comp);
     358  	  if (__parent == 0)
     359  	    return;
     360  	  __parent--;
     361  	}
     362      }
     363    
     364    /**
     365     *  @brief  Construct a heap over a range.
     366     *  @param  __first  Start of heap.
     367     *  @param  __last   End of heap.
     368     *  @ingroup heap_algorithms
     369     *
     370     *  This operation makes the elements in [__first,__last) into a heap.
     371    */
     372    template<typename _RandomAccessIterator>
     373      _GLIBCXX20_CONSTEXPR
     374      inline void
     375      make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
     376      {
     377        // concept requirements
     378        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     379  	    _RandomAccessIterator>)
     380        __glibcxx_function_requires(_LessThanComparableConcept<
     381  	    typename iterator_traits<_RandomAccessIterator>::value_type>)
     382        __glibcxx_requires_valid_range(__first, __last);
     383        __glibcxx_requires_irreflexive(__first, __last);
     384  
     385        __gnu_cxx::__ops::_Iter_less_iter __comp;
     386        std::__make_heap(__first, __last, __comp);
     387      }
     388  
     389    /**
     390     *  @brief  Construct a heap over a range using comparison functor.
     391     *  @param  __first  Start of heap.
     392     *  @param  __last   End of heap.
     393     *  @param  __comp   Comparison functor to use.
     394     *  @ingroup heap_algorithms
     395     *
     396     *  This operation makes the elements in [__first,__last) into a heap.
     397     *  Comparisons are made using __comp.
     398    */
     399    template<typename _RandomAccessIterator, typename _Compare>
     400      _GLIBCXX20_CONSTEXPR
     401      inline void
     402      make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     403  	      _Compare __comp)
     404      {
     405        // concept requirements
     406        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     407  	    _RandomAccessIterator>)
     408        __glibcxx_requires_valid_range(__first, __last);
     409        __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
     410  
     411        typedef __decltype(__comp) _Cmp;
     412        __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
     413        std::__make_heap(__first, __last, __cmp);
     414      }
     415  
     416    template<typename _RandomAccessIterator, typename _Compare>
     417      _GLIBCXX20_CONSTEXPR
     418      void
     419      __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     420  		_Compare& __comp)
     421      {
     422        while (__last - __first > 1)
     423  	{
     424  	  --__last;
     425  	  std::__pop_heap(__first, __last, __last, __comp);
     426  	}
     427      }
     428  
     429    /**
     430     *  @brief  Sort a heap.
     431     *  @param  __first  Start of heap.
     432     *  @param  __last   End of heap.
     433     *  @ingroup heap_algorithms
     434     *
     435     *  This operation sorts the valid heap in the range [__first,__last).
     436    */
     437    template<typename _RandomAccessIterator>
     438      _GLIBCXX20_CONSTEXPR
     439      inline void
     440      sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
     441      {
     442        // concept requirements
     443        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     444  	    _RandomAccessIterator>)
     445        __glibcxx_function_requires(_LessThanComparableConcept<
     446  	    typename iterator_traits<_RandomAccessIterator>::value_type>)
     447        __glibcxx_requires_valid_range(__first, __last);
     448        __glibcxx_requires_irreflexive(__first, __last);
     449        __glibcxx_requires_heap(__first, __last);
     450  
     451        __gnu_cxx::__ops::_Iter_less_iter __comp;
     452        std::__sort_heap(__first, __last, __comp);
     453      }
     454  
     455    /**
     456     *  @brief  Sort a heap using comparison functor.
     457     *  @param  __first  Start of heap.
     458     *  @param  __last   End of heap.
     459     *  @param  __comp   Comparison functor to use.
     460     *  @ingroup heap_algorithms
     461     *
     462     *  This operation sorts the valid heap in the range [__first,__last).
     463     *  Comparisons are made using __comp.
     464    */
     465    template<typename _RandomAccessIterator, typename _Compare>
     466      _GLIBCXX20_CONSTEXPR
     467      inline void
     468      sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     469  	      _Compare __comp)
     470      {
     471        // concept requirements
     472        __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
     473  	    _RandomAccessIterator>)
     474        __glibcxx_requires_valid_range(__first, __last);
     475        __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
     476        __glibcxx_requires_heap_pred(__first, __last, __comp);
     477  
     478        typedef __decltype(__comp) _Cmp;
     479        __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
     480        std::__sort_heap(__first, __last, __cmp);
     481      }
     482  
     483  #if __cplusplus >= 201103L
     484    /**
     485     *  @brief  Search the end of a heap.
     486     *  @param  __first  Start of range.
     487     *  @param  __last   End of range.
     488     *  @return  An iterator pointing to the first element not in the heap.
     489     *  @ingroup heap_algorithms
     490     *
     491     *  This operation returns the last iterator i in [__first, __last) for which
     492     *  the range [__first, i) is a heap.
     493    */
     494    template<typename _RandomAccessIterator>
     495      _GLIBCXX20_CONSTEXPR
     496      inline _RandomAccessIterator
     497      is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
     498      {
     499        // concept requirements
     500        __glibcxx_function_requires(_RandomAccessIteratorConcept<
     501  	    _RandomAccessIterator>)
     502        __glibcxx_function_requires(_LessThanComparableConcept<
     503  	    typename iterator_traits<_RandomAccessIterator>::value_type>)
     504        __glibcxx_requires_valid_range(__first, __last);
     505        __glibcxx_requires_irreflexive(__first, __last);
     506  
     507        __gnu_cxx::__ops::_Iter_less_iter __comp;
     508        return __first + 
     509  	std::__is_heap_until(__first, std::distance(__first, __last), __comp);
     510      }
     511  
     512    /**
     513     *  @brief  Search the end of a heap using comparison functor.
     514     *  @param  __first  Start of range.
     515     *  @param  __last   End of range.
     516     *  @param  __comp   Comparison functor to use.
     517     *  @return  An iterator pointing to the first element not in the heap.
     518     *  @ingroup heap_algorithms
     519     *
     520     *  This operation returns the last iterator i in [__first, __last) for which
     521     *  the range [__first, i) is a heap.  Comparisons are made using __comp.
     522    */
     523    template<typename _RandomAccessIterator, typename _Compare>
     524      _GLIBCXX20_CONSTEXPR
     525      inline _RandomAccessIterator
     526      is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
     527  		  _Compare __comp)
     528      {
     529        // concept requirements
     530        __glibcxx_function_requires(_RandomAccessIteratorConcept<
     531  	    _RandomAccessIterator>)
     532        __glibcxx_requires_valid_range(__first, __last);
     533        __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
     534  
     535        typedef __decltype(__comp) _Cmp;
     536        __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
     537        return __first
     538  	+ std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
     539      }
     540  
     541    /**
     542     *  @brief  Determines whether a range is a heap.
     543     *  @param  __first  Start of range.
     544     *  @param  __last   End of range.
     545     *  @return  True if range is a heap, false otherwise.
     546     *  @ingroup heap_algorithms
     547    */
     548    template<typename _RandomAccessIterator>
     549      _GLIBCXX20_CONSTEXPR
     550      inline bool
     551      is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
     552      { return std::is_heap_until(__first, __last) == __last; }
     553  
     554    /**
     555     *  @brief  Determines whether a range is a heap using comparison functor.
     556     *  @param  __first  Start of range.
     557     *  @param  __last   End of range.
     558     *  @param  __comp   Comparison functor to use.
     559     *  @return  True if range is a heap, false otherwise.
     560     *  @ingroup heap_algorithms
     561    */
     562    template<typename _RandomAccessIterator, typename _Compare>
     563      _GLIBCXX20_CONSTEXPR
     564      inline bool
     565      is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
     566  	    _Compare __comp)
     567      {
     568        // concept requirements
     569        __glibcxx_function_requires(_RandomAccessIteratorConcept<
     570  	    _RandomAccessIterator>)
     571        __glibcxx_requires_valid_range(__first, __last);
     572        __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
     573  
     574        const auto __dist = std::distance(__first, __last);
     575        typedef __decltype(__comp) _Cmp;
     576        __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
     577        return std::__is_heap_until(__first, __dist, __cmp) == __dist;
     578      }
     579  #endif
     580  
     581  _GLIBCXX_END_NAMESPACE_VERSION
     582  } // namespace
     583  
     584  #endif /* _STL_HEAP_H */