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