Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / libstdc++-v3 / include / bits / stl_heap.h
1 // Heap implementation -*- C++ -*-
2
3 // Copyright (C) 2001-2015 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
62 namespace std _GLIBCXX_VISIBILITY(default)
63 {
64 _GLIBCXX_BEGIN_NAMESPACE_VERSION
65
66   /**
67    * @defgroup heap_algorithms Heap
68    * @ingroup sorting_algorithms
69    */
70
71   template<typename _RandomAccessIterator, typename _Distance,
72            typename _Compare>
73     _Distance
74     __is_heap_until(_RandomAccessIterator __first, _Distance __n,
75                     _Compare __comp)
76     {
77       _Distance __parent = 0;
78       for (_Distance __child = 1; __child < __n; ++__child)
79         {
80           if (__comp(__first + __parent, __first + __child))
81             return __child;
82           if ((__child & 1) == 0)
83             ++__parent;
84         }
85       return __n;
86     }
87
88   // __is_heap, a predicate testing whether or not a range is a heap.
89   // This function is an extension, not part of the C++ standard.
90   template<typename _RandomAccessIterator, typename _Distance>
91     inline bool
92     __is_heap(_RandomAccessIterator __first, _Distance __n)
93     {
94       return std::__is_heap_until(__first, __n,
95                         __gnu_cxx::__ops::__iter_less_iter()) == __n;
96     }
97
98   template<typename _RandomAccessIterator, typename _Compare,
99            typename _Distance>
100     inline bool
101     __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
102     {
103       return std::__is_heap_until(__first, __n,
104         __gnu_cxx::__ops::__iter_comp_iter(__comp)) == __n;
105     }
106
107   template<typename _RandomAccessIterator>
108     inline bool
109     __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
110     { return std::__is_heap(__first, std::distance(__first, __last)); }
111
112   template<typename _RandomAccessIterator, typename _Compare>
113     inline bool
114     __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
115               _Compare __comp)
116     { return std::__is_heap(__first, __comp, std::distance(__first, __last)); }
117
118   // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
119   // + is_heap and is_heap_until in C++0x.
120
121   template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
122            typename _Compare>
123     void
124     __push_heap(_RandomAccessIterator __first,
125                 _Distance __holeIndex, _Distance __topIndex, _Tp __value,
126                 _Compare __comp)
127     {
128       _Distance __parent = (__holeIndex - 1) / 2;
129       while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
130         {
131           *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
132           __holeIndex = __parent;
133           __parent = (__holeIndex - 1) / 2;
134         }
135       *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
136     }
137
138   /**
139    *  @brief  Push an element onto a heap.
140    *  @param  __first  Start of heap.
141    *  @param  __last   End of heap + element.
142    *  @ingroup heap_algorithms
143    *
144    *  This operation pushes the element at last-1 onto the valid heap
145    *  over the range [__first,__last-1).  After completion,
146    *  [__first,__last) is a valid heap.
147   */
148   template<typename _RandomAccessIterator>
149     inline void
150     push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
151     {
152       typedef typename iterator_traits<_RandomAccessIterator>::value_type
153           _ValueType;
154       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
155           _DistanceType;
156
157       // concept requirements
158       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
159             _RandomAccessIterator>)
160       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
161       __glibcxx_requires_valid_range(__first, __last);
162       __glibcxx_requires_heap(__first, __last - 1);
163
164       _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
165       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
166                        _DistanceType(0), _GLIBCXX_MOVE(__value),
167                        __gnu_cxx::__ops::__iter_less_val());
168     }
169
170   /**
171    *  @brief  Push an element onto a heap using comparison functor.
172    *  @param  __first  Start of heap.
173    *  @param  __last   End of heap + element.
174    *  @param  __comp   Comparison functor.
175    *  @ingroup heap_algorithms
176    *
177    *  This operation pushes the element at __last-1 onto the valid
178    *  heap over the range [__first,__last-1).  After completion,
179    *  [__first,__last) is a valid heap.  Compare operations are
180    *  performed using comp.
181   */
182   template<typename _RandomAccessIterator, typename _Compare>
183     inline void
184     push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
185               _Compare __comp)
186     {
187       typedef typename iterator_traits<_RandomAccessIterator>::value_type
188           _ValueType;
189       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
190           _DistanceType;
191
192       // concept requirements
193       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
194             _RandomAccessIterator>)
195       __glibcxx_requires_valid_range(__first, __last);
196       __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
197
198       _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
199       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
200                        _DistanceType(0), _GLIBCXX_MOVE(__value),
201                        __gnu_cxx::__ops::__iter_comp_val(__comp));
202     }
203
204   template<typename _RandomAccessIterator, typename _Distance,
205            typename _Tp, typename _Compare>
206     void
207     __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
208                   _Distance __len, _Tp __value, _Compare __comp)
209     {
210       const _Distance __topIndex = __holeIndex;
211       _Distance __secondChild = __holeIndex;
212       while (__secondChild < (__len - 1) / 2)
213         {
214           __secondChild = 2 * (__secondChild + 1);
215           if (__comp(__first + __secondChild,
216                      __first + (__secondChild - 1)))
217             __secondChild--;
218           *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
219           __holeIndex = __secondChild;
220         }
221       if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
222         {
223           __secondChild = 2 * (__secondChild + 1);
224           *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
225                                                      + (__secondChild - 1)));
226           __holeIndex = __secondChild - 1;
227         }
228       std::__push_heap(__first, __holeIndex, __topIndex, 
229                        _GLIBCXX_MOVE(__value),
230                        __gnu_cxx::__ops::__iter_comp_val(__comp));
231     }
232
233   template<typename _RandomAccessIterator, typename _Compare>
234     inline void
235     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
236                _RandomAccessIterator __result, _Compare __comp)
237     {
238       typedef typename iterator_traits<_RandomAccessIterator>::value_type
239         _ValueType;
240       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
241         _DistanceType;
242
243       _ValueType __value = _GLIBCXX_MOVE(*__result);
244       *__result = _GLIBCXX_MOVE(*__first);
245       std::__adjust_heap(__first, _DistanceType(0),
246                          _DistanceType(__last - __first),
247                          _GLIBCXX_MOVE(__value), __comp);
248     }
249
250   /**
251    *  @brief  Pop an element off a heap.
252    *  @param  __first  Start of heap.
253    *  @param  __last   End of heap.
254    *  @pre    [__first, __last) is a valid, non-empty range.
255    *  @ingroup heap_algorithms
256    *
257    *  This operation pops the top of the heap.  The elements __first
258    *  and __last-1 are swapped and [__first,__last-1) is made into a
259    *  heap.
260   */
261   template<typename _RandomAccessIterator>
262     inline void
263     pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
264     {
265       typedef typename iterator_traits<_RandomAccessIterator>::value_type
266         _ValueType;
267
268       // concept requirements
269       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
270             _RandomAccessIterator>)
271       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
272       __glibcxx_requires_non_empty_range(__first, __last);
273       __glibcxx_requires_valid_range(__first, __last);
274       __glibcxx_requires_heap(__first, __last);
275
276       if (__last - __first > 1)
277         {
278           --__last;
279           std::__pop_heap(__first, __last, __last,
280                           __gnu_cxx::__ops::__iter_less_iter());
281         }
282     }
283
284   /**
285    *  @brief  Pop an element off a heap using comparison functor.
286    *  @param  __first  Start of heap.
287    *  @param  __last   End of heap.
288    *  @param  __comp   Comparison functor to use.
289    *  @ingroup heap_algorithms
290    *
291    *  This operation pops the top of the heap.  The elements __first
292    *  and __last-1 are swapped and [__first,__last-1) is made into a
293    *  heap.  Comparisons are made using comp.
294   */
295   template<typename _RandomAccessIterator, typename _Compare>
296     inline void
297     pop_heap(_RandomAccessIterator __first,
298              _RandomAccessIterator __last, _Compare __comp)
299     {
300       // concept requirements
301       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
302             _RandomAccessIterator>)
303       __glibcxx_requires_valid_range(__first, __last);
304       __glibcxx_requires_non_empty_range(__first, __last);
305       __glibcxx_requires_heap_pred(__first, __last, __comp);
306
307       if (__last - __first > 1)
308         {
309           --__last;
310           std::__pop_heap(__first, __last, __last,
311                           __gnu_cxx::__ops::__iter_comp_iter(__comp));
312         }
313     }
314
315   template<typename _RandomAccessIterator, typename _Compare>
316     void
317     __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
318                 _Compare __comp)
319     {
320       typedef typename iterator_traits<_RandomAccessIterator>::value_type
321           _ValueType;
322       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
323           _DistanceType;
324
325       if (__last - __first < 2)
326         return;
327
328       const _DistanceType __len = __last - __first;
329       _DistanceType __parent = (__len - 2) / 2;
330       while (true)
331         {
332           _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
333           std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
334                              __comp);
335           if (__parent == 0)
336             return;
337           __parent--;
338         }
339     }
340   
341   /**
342    *  @brief  Construct a heap over a range.
343    *  @param  __first  Start of heap.
344    *  @param  __last   End of heap.
345    *  @ingroup heap_algorithms
346    *
347    *  This operation makes the elements in [__first,__last) into a heap.
348   */
349   template<typename _RandomAccessIterator>
350     inline void
351     make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
352     {
353       // concept requirements
354       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
355             _RandomAccessIterator>)
356       __glibcxx_function_requires(_LessThanComparableConcept<
357             typename iterator_traits<_RandomAccessIterator>::value_type>)
358       __glibcxx_requires_valid_range(__first, __last);
359
360       std::__make_heap(__first, __last,
361                        __gnu_cxx::__ops::__iter_less_iter());
362     }
363
364   /**
365    *  @brief  Construct a heap over a range using comparison functor.
366    *  @param  __first  Start of heap.
367    *  @param  __last   End of heap.
368    *  @param  __comp   Comparison functor to use.
369    *  @ingroup heap_algorithms
370    *
371    *  This operation makes the elements in [__first,__last) into a heap.
372    *  Comparisons are made using __comp.
373   */
374   template<typename _RandomAccessIterator, typename _Compare>
375     inline void
376     make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
377               _Compare __comp)
378     {
379       // concept requirements
380       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
381             _RandomAccessIterator>)
382       __glibcxx_requires_valid_range(__first, __last);
383
384       std::__make_heap(__first, __last,
385                        __gnu_cxx::__ops::__iter_comp_iter(__comp));
386     }
387
388   template<typename _RandomAccessIterator, typename _Compare>
389     void
390     __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
391                 _Compare __comp)
392     {
393       while (__last - __first > 1)
394         {
395           --__last;
396           std::__pop_heap(__first, __last, __last, __comp);
397         }
398     }
399
400   /**
401    *  @brief  Sort a heap.
402    *  @param  __first  Start of heap.
403    *  @param  __last   End of heap.
404    *  @ingroup heap_algorithms
405    *
406    *  This operation sorts the valid heap in the range [__first,__last).
407   */
408   template<typename _RandomAccessIterator>
409     inline void
410     sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
411     {
412       // concept requirements
413       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
414             _RandomAccessIterator>)
415       __glibcxx_function_requires(_LessThanComparableConcept<
416             typename iterator_traits<_RandomAccessIterator>::value_type>)
417       __glibcxx_requires_valid_range(__first, __last);
418       __glibcxx_requires_heap(__first, __last);
419
420       std::__sort_heap(__first, __last,
421                        __gnu_cxx::__ops::__iter_less_iter());
422     }
423
424   /**
425    *  @brief  Sort a heap using comparison functor.
426    *  @param  __first  Start of heap.
427    *  @param  __last   End of heap.
428    *  @param  __comp   Comparison functor to use.
429    *  @ingroup heap_algorithms
430    *
431    *  This operation sorts the valid heap in the range [__first,__last).
432    *  Comparisons are made using __comp.
433   */
434   template<typename _RandomAccessIterator, typename _Compare>
435     inline void
436     sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
437               _Compare __comp)
438     {
439       // concept requirements
440       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
441             _RandomAccessIterator>)
442       __glibcxx_requires_valid_range(__first, __last);
443       __glibcxx_requires_heap_pred(__first, __last, __comp);
444
445       std::__sort_heap(__first, __last,
446                        __gnu_cxx::__ops::__iter_comp_iter(__comp));
447     }
448
449 #if __cplusplus >= 201103L
450   /**
451    *  @brief  Search the end of a heap.
452    *  @param  __first  Start of range.
453    *  @param  __last   End of range.
454    *  @return  An iterator pointing to the first element not in the heap.
455    *  @ingroup heap_algorithms
456    *
457    *  This operation returns the last iterator i in [__first, __last) for which
458    *  the range [__first, i) is a heap.
459   */
460   template<typename _RandomAccessIterator>
461     inline _RandomAccessIterator
462     is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
463     {
464       // concept requirements
465       __glibcxx_function_requires(_RandomAccessIteratorConcept<
466             _RandomAccessIterator>)
467       __glibcxx_function_requires(_LessThanComparableConcept<
468             typename iterator_traits<_RandomAccessIterator>::value_type>)
469       __glibcxx_requires_valid_range(__first, __last);
470
471       return __first + 
472         std::__is_heap_until(__first, std::distance(__first, __last),
473                              __gnu_cxx::__ops::__iter_less_iter());
474     }
475
476   /**
477    *  @brief  Search the end of a heap using comparison functor.
478    *  @param  __first  Start of range.
479    *  @param  __last   End of range.
480    *  @param  __comp   Comparison functor to use.
481    *  @return  An iterator pointing to the first element not in the heap.
482    *  @ingroup heap_algorithms
483    *
484    *  This operation returns the last iterator i in [__first, __last) for which
485    *  the range [__first, i) is a heap.  Comparisons are made using __comp.
486   */
487   template<typename _RandomAccessIterator, typename _Compare>
488     inline _RandomAccessIterator
489     is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
490                   _Compare __comp)
491     {
492       // concept requirements
493       __glibcxx_function_requires(_RandomAccessIteratorConcept<
494             _RandomAccessIterator>)
495       __glibcxx_requires_valid_range(__first, __last);
496
497       return __first
498         + std::__is_heap_until(__first, std::distance(__first, __last),
499                                __gnu_cxx::__ops::__iter_comp_iter(__comp));
500     }
501
502   /**
503    *  @brief  Determines whether a range is a heap.
504    *  @param  __first  Start of range.
505    *  @param  __last   End of range.
506    *  @return  True if range is a heap, false otherwise.
507    *  @ingroup heap_algorithms
508   */
509   template<typename _RandomAccessIterator>
510     inline bool
511     is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
512     { return std::is_heap_until(__first, __last) == __last; }
513
514   /**
515    *  @brief  Determines whether a range is a heap using comparison functor.
516    *  @param  __first  Start of range.
517    *  @param  __last   End of range.
518    *  @param  __comp   Comparison functor to use.
519    *  @return  True if range is a heap, false otherwise.
520    *  @ingroup heap_algorithms
521   */
522   template<typename _RandomAccessIterator, typename _Compare>
523     inline bool
524     is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
525             _Compare __comp)
526     { return std::is_heap_until(__first, __last, __comp) == __last; }
527 #endif
528
529 _GLIBCXX_END_NAMESPACE_VERSION
530 } // namespace
531
532 #endif /* _STL_HEAP_H */