xref: /openbsd-src/gnu/gcc/libstdc++-v3/include/bits/stl_heap.h (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert // Heap implementation -*- C++ -*-
2*404b540aSrobert 
3*404b540aSrobert // Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
4*404b540aSrobert //
5*404b540aSrobert // This file is part of the GNU ISO C++ Library.  This library is free
6*404b540aSrobert // software; you can redistribute it and/or modify it under the
7*404b540aSrobert // terms of the GNU General Public License as published by the
8*404b540aSrobert // Free Software Foundation; either version 2, or (at your option)
9*404b540aSrobert // any later version.
10*404b540aSrobert 
11*404b540aSrobert // This library is distributed in the hope that it will be useful,
12*404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*404b540aSrobert // GNU General Public License for more details.
15*404b540aSrobert 
16*404b540aSrobert // You should have received a copy of the GNU General Public License along
17*404b540aSrobert // with this library; see the file COPYING.  If not, write to the Free
18*404b540aSrobert // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19*404b540aSrobert // USA.
20*404b540aSrobert 
21*404b540aSrobert // As a special exception, you may use this file as part of a free software
22*404b540aSrobert // library without restriction.  Specifically, if other files instantiate
23*404b540aSrobert // templates or use macros or inline functions from this file, or you compile
24*404b540aSrobert // this file and link it with other files to produce an executable, this
25*404b540aSrobert // file does not by itself cause the resulting executable to be covered by
26*404b540aSrobert // the GNU General Public License.  This exception does not however
27*404b540aSrobert // invalidate any other reasons why the executable file might be covered by
28*404b540aSrobert // the GNU General Public License.
29*404b540aSrobert 
30*404b540aSrobert /*
31*404b540aSrobert  *
32*404b540aSrobert  * Copyright (c) 1994
33*404b540aSrobert  * Hewlett-Packard Company
34*404b540aSrobert  *
35*404b540aSrobert  * Permission to use, copy, modify, distribute and sell this software
36*404b540aSrobert  * and its documentation for any purpose is hereby granted without fee,
37*404b540aSrobert  * provided that the above copyright notice appear in all copies and
38*404b540aSrobert  * that both that copyright notice and this permission notice appear
39*404b540aSrobert  * in supporting documentation.  Hewlett-Packard Company makes no
40*404b540aSrobert  * representations about the suitability of this software for any
41*404b540aSrobert  * purpose.  It is provided "as is" without express or implied warranty.
42*404b540aSrobert  *
43*404b540aSrobert  * Copyright (c) 1997
44*404b540aSrobert  * Silicon Graphics Computer Systems, Inc.
45*404b540aSrobert  *
46*404b540aSrobert  * Permission to use, copy, modify, distribute and sell this software
47*404b540aSrobert  * and its documentation for any purpose is hereby granted without fee,
48*404b540aSrobert  * provided that the above copyright notice appear in all copies and
49*404b540aSrobert  * that both that copyright notice and this permission notice appear
50*404b540aSrobert  * in supporting documentation.  Silicon Graphics makes no
51*404b540aSrobert  * representations about the suitability of this software for any
52*404b540aSrobert  * purpose.  It is provided "as is" without express or implied warranty.
53*404b540aSrobert  */
54*404b540aSrobert 
55*404b540aSrobert /** @file stl_heap.h
56*404b540aSrobert  *  This is an internal header file, included by other library headers.
57*404b540aSrobert  *  You should not attempt to use it directly.
58*404b540aSrobert  */
59*404b540aSrobert 
60*404b540aSrobert #ifndef _STL_HEAP_H
61*404b540aSrobert #define _STL_HEAP_H 1
62*404b540aSrobert 
63*404b540aSrobert #include <debug/debug.h>
64*404b540aSrobert 
_GLIBCXX_BEGIN_NAMESPACE(std)65*404b540aSrobert _GLIBCXX_BEGIN_NAMESPACE(std)
66*404b540aSrobert 
67*404b540aSrobert   // is_heap, a predicate testing whether or not a range is
68*404b540aSrobert   // a heap.  This function is an extension, not part of the C++
69*404b540aSrobert   // standard.
70*404b540aSrobert   template<typename _RandomAccessIterator, typename _Distance>
71*404b540aSrobert     bool
72*404b540aSrobert     __is_heap(_RandomAccessIterator __first, _Distance __n)
73*404b540aSrobert     {
74*404b540aSrobert       _Distance __parent = 0;
75*404b540aSrobert       for (_Distance __child = 1; __child < __n; ++__child)
76*404b540aSrobert 	{
77*404b540aSrobert 	  if (__first[__parent] < __first[__child])
78*404b540aSrobert 	    return false;
79*404b540aSrobert 	  if ((__child & 1) == 0)
80*404b540aSrobert 	    ++__parent;
81*404b540aSrobert 	}
82*404b540aSrobert       return true;
83*404b540aSrobert     }
84*404b540aSrobert 
85*404b540aSrobert   template<typename _RandomAccessIterator, typename _Distance,
86*404b540aSrobert            typename _StrictWeakOrdering>
87*404b540aSrobert     bool
__is_heap(_RandomAccessIterator __first,_StrictWeakOrdering __comp,_Distance __n)88*404b540aSrobert     __is_heap(_RandomAccessIterator __first, _StrictWeakOrdering __comp,
89*404b540aSrobert 	      _Distance __n)
90*404b540aSrobert     {
91*404b540aSrobert       _Distance __parent = 0;
92*404b540aSrobert       for (_Distance __child = 1; __child < __n; ++__child)
93*404b540aSrobert 	{
94*404b540aSrobert 	  if (__comp(__first[__parent], __first[__child]))
95*404b540aSrobert 	    return false;
96*404b540aSrobert 	  if ((__child & 1) == 0)
97*404b540aSrobert 	    ++__parent;
98*404b540aSrobert 	}
99*404b540aSrobert       return true;
100*404b540aSrobert     }
101*404b540aSrobert 
102*404b540aSrobert   template<typename _RandomAccessIterator>
103*404b540aSrobert     bool
__is_heap(_RandomAccessIterator __first,_RandomAccessIterator __last)104*404b540aSrobert     __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
105*404b540aSrobert     { return std::__is_heap(__first, std::distance(__first, __last)); }
106*404b540aSrobert 
107*404b540aSrobert   template<typename _RandomAccessIterator, typename _StrictWeakOrdering>
108*404b540aSrobert     bool
__is_heap(_RandomAccessIterator __first,_RandomAccessIterator __last,_StrictWeakOrdering __comp)109*404b540aSrobert     __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
110*404b540aSrobert 	    _StrictWeakOrdering __comp)
111*404b540aSrobert     { return std::__is_heap(__first, __comp, std::distance(__first, __last)); }
112*404b540aSrobert 
113*404b540aSrobert   // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap.
114*404b540aSrobert 
115*404b540aSrobert   template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
116*404b540aSrobert     void
__push_heap(_RandomAccessIterator __first,_Distance __holeIndex,_Distance __topIndex,_Tp __value)117*404b540aSrobert     __push_heap(_RandomAccessIterator __first,
118*404b540aSrobert 		_Distance __holeIndex, _Distance __topIndex, _Tp __value)
119*404b540aSrobert     {
120*404b540aSrobert       _Distance __parent = (__holeIndex - 1) / 2;
121*404b540aSrobert       while (__holeIndex > __topIndex && *(__first + __parent) < __value)
122*404b540aSrobert 	{
123*404b540aSrobert 	  *(__first + __holeIndex) = *(__first + __parent);
124*404b540aSrobert 	  __holeIndex = __parent;
125*404b540aSrobert 	  __parent = (__holeIndex - 1) / 2;
126*404b540aSrobert 	}
127*404b540aSrobert       *(__first + __holeIndex) = __value;
128*404b540aSrobert     }
129*404b540aSrobert 
130*404b540aSrobert   /**
131*404b540aSrobert    *  @brief  Push an element onto a heap.
132*404b540aSrobert    *  @param  first  Start of heap.
133*404b540aSrobert    *  @param  last   End of heap + element.
134*404b540aSrobert    *  @ingroup heap
135*404b540aSrobert    *
136*404b540aSrobert    *  This operation pushes the element at last-1 onto the valid heap over the
137*404b540aSrobert    *  range [first,last-1).  After completion, [first,last) is a valid heap.
138*404b540aSrobert   */
139*404b540aSrobert   template<typename _RandomAccessIterator>
140*404b540aSrobert     inline void
push_heap(_RandomAccessIterator __first,_RandomAccessIterator __last)141*404b540aSrobert     push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
142*404b540aSrobert     {
143*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::value_type
144*404b540aSrobert 	  _ValueType;
145*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
146*404b540aSrobert 	  _DistanceType;
147*404b540aSrobert 
148*404b540aSrobert       // concept requirements
149*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
150*404b540aSrobert 	    _RandomAccessIterator>)
151*404b540aSrobert       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
152*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
153*404b540aSrobert       //      __glibcxx_requires_heap(__first, __last - 1);
154*404b540aSrobert 
155*404b540aSrobert       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
156*404b540aSrobert 		       _DistanceType(0), _ValueType(*(__last - 1)));
157*404b540aSrobert     }
158*404b540aSrobert 
159*404b540aSrobert   template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
160*404b540aSrobert 	    typename _Compare>
161*404b540aSrobert     void
__push_heap(_RandomAccessIterator __first,_Distance __holeIndex,_Distance __topIndex,_Tp __value,_Compare __comp)162*404b540aSrobert     __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
163*404b540aSrobert 		_Distance __topIndex, _Tp __value, _Compare __comp)
164*404b540aSrobert     {
165*404b540aSrobert       _Distance __parent = (__holeIndex - 1) / 2;
166*404b540aSrobert       while (__holeIndex > __topIndex
167*404b540aSrobert 	     && __comp(*(__first + __parent), __value))
168*404b540aSrobert 	{
169*404b540aSrobert 	  *(__first + __holeIndex) = *(__first + __parent);
170*404b540aSrobert 	  __holeIndex = __parent;
171*404b540aSrobert 	  __parent = (__holeIndex - 1) / 2;
172*404b540aSrobert 	}
173*404b540aSrobert       *(__first + __holeIndex) = __value;
174*404b540aSrobert     }
175*404b540aSrobert 
176*404b540aSrobert   /**
177*404b540aSrobert    *  @brief  Push an element onto a heap using comparison functor.
178*404b540aSrobert    *  @param  first  Start of heap.
179*404b540aSrobert    *  @param  last   End of heap + element.
180*404b540aSrobert    *  @param  comp   Comparison functor.
181*404b540aSrobert    *  @ingroup heap
182*404b540aSrobert    *
183*404b540aSrobert    *  This operation pushes the element at last-1 onto the valid heap over the
184*404b540aSrobert    *  range [first,last-1).  After completion, [first,last) is a valid heap.
185*404b540aSrobert    *  Compare operations are performed using comp.
186*404b540aSrobert   */
187*404b540aSrobert   template<typename _RandomAccessIterator, typename _Compare>
188*404b540aSrobert     inline void
push_heap(_RandomAccessIterator __first,_RandomAccessIterator __last,_Compare __comp)189*404b540aSrobert     push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
190*404b540aSrobert 	      _Compare __comp)
191*404b540aSrobert     {
192*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::value_type
193*404b540aSrobert 	  _ValueType;
194*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
195*404b540aSrobert 	  _DistanceType;
196*404b540aSrobert 
197*404b540aSrobert       // concept requirements
198*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
199*404b540aSrobert 	    _RandomAccessIterator>)
200*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
201*404b540aSrobert       __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
202*404b540aSrobert 
203*404b540aSrobert       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
204*404b540aSrobert 		       _DistanceType(0), _ValueType(*(__last - 1)), __comp);
205*404b540aSrobert     }
206*404b540aSrobert 
207*404b540aSrobert   template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
208*404b540aSrobert     void
__adjust_heap(_RandomAccessIterator __first,_Distance __holeIndex,_Distance __len,_Tp __value)209*404b540aSrobert     __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
210*404b540aSrobert 		  _Distance __len, _Tp __value)
211*404b540aSrobert     {
212*404b540aSrobert       const _Distance __topIndex = __holeIndex;
213*404b540aSrobert       _Distance __secondChild = 2 * __holeIndex + 2;
214*404b540aSrobert       while (__secondChild < __len)
215*404b540aSrobert 	{
216*404b540aSrobert 	  if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
217*404b540aSrobert 	    __secondChild--;
218*404b540aSrobert 	  *(__first + __holeIndex) = *(__first + __secondChild);
219*404b540aSrobert 	  __holeIndex = __secondChild;
220*404b540aSrobert 	  __secondChild = 2 * (__secondChild + 1);
221*404b540aSrobert 	}
222*404b540aSrobert       if (__secondChild == __len)
223*404b540aSrobert 	{
224*404b540aSrobert 	  *(__first + __holeIndex) = *(__first + (__secondChild - 1));
225*404b540aSrobert 	  __holeIndex = __secondChild - 1;
226*404b540aSrobert 	}
227*404b540aSrobert       std::__push_heap(__first, __holeIndex, __topIndex, __value);
228*404b540aSrobert     }
229*404b540aSrobert 
230*404b540aSrobert   template<typename _RandomAccessIterator, typename _Tp>
231*404b540aSrobert     inline void
__pop_heap(_RandomAccessIterator __first,_RandomAccessIterator __last,_RandomAccessIterator __result,_Tp __value)232*404b540aSrobert     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
233*404b540aSrobert 	       _RandomAccessIterator __result, _Tp __value)
234*404b540aSrobert     {
235*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
236*404b540aSrobert 	_Distance;
237*404b540aSrobert       *__result = *__first;
238*404b540aSrobert       std::__adjust_heap(__first, _Distance(0), _Distance(__last - __first),
239*404b540aSrobert 			 __value);
240*404b540aSrobert     }
241*404b540aSrobert 
242*404b540aSrobert   /**
243*404b540aSrobert    *  @brief  Pop an element off a heap.
244*404b540aSrobert    *  @param  first  Start of heap.
245*404b540aSrobert    *  @param  last   End of heap.
246*404b540aSrobert    *  @ingroup heap
247*404b540aSrobert    *
248*404b540aSrobert    *  This operation pops the top of the heap.  The elements first and last-1
249*404b540aSrobert    *  are swapped and [first,last-1) is made into a heap.
250*404b540aSrobert   */
251*404b540aSrobert   template<typename _RandomAccessIterator>
252*404b540aSrobert     inline void
pop_heap(_RandomAccessIterator __first,_RandomAccessIterator __last)253*404b540aSrobert     pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
254*404b540aSrobert     {
255*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::value_type
256*404b540aSrobert 	_ValueType;
257*404b540aSrobert 
258*404b540aSrobert       // concept requirements
259*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
260*404b540aSrobert 	    _RandomAccessIterator>)
261*404b540aSrobert       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
262*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
263*404b540aSrobert       __glibcxx_requires_heap(__first, __last);
264*404b540aSrobert 
265*404b540aSrobert       std::__pop_heap(__first, __last - 1, __last - 1,
266*404b540aSrobert 		      _ValueType(*(__last - 1)));
267*404b540aSrobert     }
268*404b540aSrobert 
269*404b540aSrobert   template<typename _RandomAccessIterator, typename _Distance,
270*404b540aSrobert 	   typename _Tp, typename _Compare>
271*404b540aSrobert     void
__adjust_heap(_RandomAccessIterator __first,_Distance __holeIndex,_Distance __len,_Tp __value,_Compare __comp)272*404b540aSrobert     __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
273*404b540aSrobert 		  _Distance __len, _Tp __value, _Compare __comp)
274*404b540aSrobert     {
275*404b540aSrobert       const _Distance __topIndex = __holeIndex;
276*404b540aSrobert       _Distance __secondChild = 2 * __holeIndex + 2;
277*404b540aSrobert       while (__secondChild < __len)
278*404b540aSrobert 	{
279*404b540aSrobert 	  if (__comp(*(__first + __secondChild),
280*404b540aSrobert 		     *(__first + (__secondChild - 1))))
281*404b540aSrobert 	    __secondChild--;
282*404b540aSrobert 	  *(__first + __holeIndex) = *(__first + __secondChild);
283*404b540aSrobert 	  __holeIndex = __secondChild;
284*404b540aSrobert 	  __secondChild = 2 * (__secondChild + 1);
285*404b540aSrobert 	}
286*404b540aSrobert       if (__secondChild == __len)
287*404b540aSrobert 	{
288*404b540aSrobert 	  *(__first + __holeIndex) = *(__first + (__secondChild - 1));
289*404b540aSrobert 	  __holeIndex = __secondChild - 1;
290*404b540aSrobert 	}
291*404b540aSrobert       std::__push_heap(__first, __holeIndex, __topIndex, __value, __comp);
292*404b540aSrobert     }
293*404b540aSrobert 
294*404b540aSrobert   template<typename _RandomAccessIterator, typename _Tp, typename _Compare>
295*404b540aSrobert     inline void
__pop_heap(_RandomAccessIterator __first,_RandomAccessIterator __last,_RandomAccessIterator __result,_Tp __value,_Compare __comp)296*404b540aSrobert     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
297*404b540aSrobert 	       _RandomAccessIterator __result, _Tp __value, _Compare __comp)
298*404b540aSrobert     {
299*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
300*404b540aSrobert 	_Distance;
301*404b540aSrobert       *__result = *__first;
302*404b540aSrobert       std::__adjust_heap(__first, _Distance(0), _Distance(__last - __first),
303*404b540aSrobert 			 __value, __comp);
304*404b540aSrobert     }
305*404b540aSrobert 
306*404b540aSrobert   /**
307*404b540aSrobert    *  @brief  Pop an element off a heap using comparison functor.
308*404b540aSrobert    *  @param  first  Start of heap.
309*404b540aSrobert    *  @param  last   End of heap.
310*404b540aSrobert    *  @param  comp   Comparison functor to use.
311*404b540aSrobert    *  @ingroup heap
312*404b540aSrobert    *
313*404b540aSrobert    *  This operation pops the top of the heap.  The elements first and last-1
314*404b540aSrobert    *  are swapped and [first,last-1) is made into a heap.  Comparisons are
315*404b540aSrobert    *  made using comp.
316*404b540aSrobert   */
317*404b540aSrobert   template<typename _RandomAccessIterator, typename _Compare>
318*404b540aSrobert     inline void
pop_heap(_RandomAccessIterator __first,_RandomAccessIterator __last,_Compare __comp)319*404b540aSrobert     pop_heap(_RandomAccessIterator __first,
320*404b540aSrobert 	     _RandomAccessIterator __last, _Compare __comp)
321*404b540aSrobert     {
322*404b540aSrobert       // concept requirements
323*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
324*404b540aSrobert 	    _RandomAccessIterator>)
325*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
326*404b540aSrobert       __glibcxx_requires_heap_pred(__first, __last, __comp);
327*404b540aSrobert 
328*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::value_type
329*404b540aSrobert 	_ValueType;
330*404b540aSrobert       std::__pop_heap(__first, __last - 1, __last - 1,
331*404b540aSrobert 		      _ValueType(*(__last - 1)), __comp);
332*404b540aSrobert     }
333*404b540aSrobert 
334*404b540aSrobert   /**
335*404b540aSrobert    *  @brief  Construct a heap over a range.
336*404b540aSrobert    *  @param  first  Start of heap.
337*404b540aSrobert    *  @param  last   End of heap.
338*404b540aSrobert    *  @ingroup heap
339*404b540aSrobert    *
340*404b540aSrobert    *  This operation makes the elements in [first,last) into a heap.
341*404b540aSrobert   */
342*404b540aSrobert   template<typename _RandomAccessIterator>
343*404b540aSrobert     void
make_heap(_RandomAccessIterator __first,_RandomAccessIterator __last)344*404b540aSrobert     make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
345*404b540aSrobert     {
346*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::value_type
347*404b540aSrobert 	  _ValueType;
348*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
349*404b540aSrobert 	  _DistanceType;
350*404b540aSrobert 
351*404b540aSrobert       // concept requirements
352*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
353*404b540aSrobert 	    _RandomAccessIterator>)
354*404b540aSrobert       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
355*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
356*404b540aSrobert 
357*404b540aSrobert       if (__last - __first < 2)
358*404b540aSrobert 	return;
359*404b540aSrobert 
360*404b540aSrobert       const _DistanceType __len = __last - __first;
361*404b540aSrobert       _DistanceType __parent = (__len - 2) / 2;
362*404b540aSrobert       while (true)
363*404b540aSrobert 	{
364*404b540aSrobert 	  std::__adjust_heap(__first, __parent, __len,
365*404b540aSrobert 			     _ValueType(*(__first + __parent)));
366*404b540aSrobert 	  if (__parent == 0)
367*404b540aSrobert 	    return;
368*404b540aSrobert 	  __parent--;
369*404b540aSrobert 	}
370*404b540aSrobert     }
371*404b540aSrobert 
372*404b540aSrobert   /**
373*404b540aSrobert    *  @brief  Construct a heap over a range using comparison functor.
374*404b540aSrobert    *  @param  first  Start of heap.
375*404b540aSrobert    *  @param  last   End of heap.
376*404b540aSrobert    *  @param  comp   Comparison functor to use.
377*404b540aSrobert    *  @ingroup heap
378*404b540aSrobert    *
379*404b540aSrobert    *  This operation makes the elements in [first,last) into a heap.
380*404b540aSrobert    *  Comparisons are made using comp.
381*404b540aSrobert   */
382*404b540aSrobert   template<typename _RandomAccessIterator, typename _Compare>
383*404b540aSrobert     inline void
make_heap(_RandomAccessIterator __first,_RandomAccessIterator __last,_Compare __comp)384*404b540aSrobert     make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
385*404b540aSrobert 	      _Compare __comp)
386*404b540aSrobert     {
387*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::value_type
388*404b540aSrobert 	  _ValueType;
389*404b540aSrobert       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
390*404b540aSrobert 	  _DistanceType;
391*404b540aSrobert 
392*404b540aSrobert       // concept requirements
393*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
394*404b540aSrobert 	    _RandomAccessIterator>)
395*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
396*404b540aSrobert 
397*404b540aSrobert       if (__last - __first < 2)
398*404b540aSrobert 	return;
399*404b540aSrobert 
400*404b540aSrobert       const _DistanceType __len = __last - __first;
401*404b540aSrobert       _DistanceType __parent = (__len - 2) / 2;
402*404b540aSrobert       while (true)
403*404b540aSrobert 	{
404*404b540aSrobert 	  std::__adjust_heap(__first, __parent, __len,
405*404b540aSrobert 			     _ValueType(*(__first + __parent)), __comp);
406*404b540aSrobert 	  if (__parent == 0)
407*404b540aSrobert 	    return;
408*404b540aSrobert 	  __parent--;
409*404b540aSrobert 	}
410*404b540aSrobert     }
411*404b540aSrobert 
412*404b540aSrobert   /**
413*404b540aSrobert    *  @brief  Sort a heap.
414*404b540aSrobert    *  @param  first  Start of heap.
415*404b540aSrobert    *  @param  last   End of heap.
416*404b540aSrobert    *  @ingroup heap
417*404b540aSrobert    *
418*404b540aSrobert    *  This operation sorts the valid heap in the range [first,last).
419*404b540aSrobert   */
420*404b540aSrobert   template<typename _RandomAccessIterator>
421*404b540aSrobert     void
sort_heap(_RandomAccessIterator __first,_RandomAccessIterator __last)422*404b540aSrobert     sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
423*404b540aSrobert     {
424*404b540aSrobert       // concept requirements
425*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
426*404b540aSrobert 	    _RandomAccessIterator>)
427*404b540aSrobert       __glibcxx_function_requires(_LessThanComparableConcept<
428*404b540aSrobert 	    typename iterator_traits<_RandomAccessIterator>::value_type>)
429*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
430*404b540aSrobert       //      __glibcxx_requires_heap(__first, __last);
431*404b540aSrobert 
432*404b540aSrobert       while (__last - __first > 1)
433*404b540aSrobert 	std::pop_heap(__first, _RandomAccessIterator(__last--));
434*404b540aSrobert     }
435*404b540aSrobert 
436*404b540aSrobert   /**
437*404b540aSrobert    *  @brief  Sort a heap using comparison functor.
438*404b540aSrobert    *  @param  first  Start of heap.
439*404b540aSrobert    *  @param  last   End of heap.
440*404b540aSrobert    *  @param  comp   Comparison functor to use.
441*404b540aSrobert    *  @ingroup heap
442*404b540aSrobert    *
443*404b540aSrobert    *  This operation sorts the valid heap in the range [first,last).
444*404b540aSrobert    *  Comparisons are made using comp.
445*404b540aSrobert   */
446*404b540aSrobert   template<typename _RandomAccessIterator, typename _Compare>
447*404b540aSrobert     void
sort_heap(_RandomAccessIterator __first,_RandomAccessIterator __last,_Compare __comp)448*404b540aSrobert     sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
449*404b540aSrobert 	      _Compare __comp)
450*404b540aSrobert     {
451*404b540aSrobert       // concept requirements
452*404b540aSrobert       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
453*404b540aSrobert 	    _RandomAccessIterator>)
454*404b540aSrobert       __glibcxx_requires_valid_range(__first, __last);
455*404b540aSrobert       __glibcxx_requires_heap_pred(__first, __last, __comp);
456*404b540aSrobert 
457*404b540aSrobert       while (__last - __first > 1)
458*404b540aSrobert 	std::pop_heap(__first, _RandomAccessIterator(__last--), __comp);
459*404b540aSrobert     }
460*404b540aSrobert 
461*404b540aSrobert _GLIBCXX_END_NAMESPACE
462*404b540aSrobert 
463*404b540aSrobert #endif /* _STL_HEAP_H */
464