PR libstdc++/33489 continued.
[gcc.git] / libstdc++-v3 / include / parallel / losertree.h
1 // -*- C++ -*-
2
3 // Copyright (C) 2007 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 terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2, or (at your option) any later
9 // version.
10
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19 // MA 02111-1307, USA.
20
21 // As a special exception, you may use this file as part of a free
22 // software library without restriction. Specifically, if other files
23 // instantiate templates or use macros or inline functions from this
24 // file, or you compile this file and link it with other files to
25 // produce an executable, this file does not by itself cause the
26 // resulting executable to be covered by the GNU General Public
27 // License. This exception does not however invalidate any other
28 // reasons why the executable file might be covered by the GNU General
29 // Public License.
30
31 /** @file parallel/losertree.h
32 * @brief Many generic loser tree variants.
33 * This file is a GNU parallel extension to the Standard C++ Library.
34 */
35
36 // Written by Johannes Singler.
37
38 #ifndef _GLIBCXX_PARALLEL_LOSERTREE_H
39 #define _GLIBCXX_PARALLEL_LOSERTREE_H 1
40
41 #include <functional>
42
43 #include <bits/stl_algobase.h>
44 #include <parallel/features.h>
45 #include <parallel/base.h>
46
47 namespace __gnu_parallel
48 {
49
50 #if _GLIBCXX_LOSER_TREE_EXPLICIT
51
52 /** @brief Guarded loser tree, copying the whole element into the
53 * tree structure.
54 *
55 * Guarding is done explicitly through two flags per element, inf
56 * and sup This is a quite slow variant.
57 */
58 template<typename T, typename Comparator = std::less<T> >
59 class LoserTreeExplicit
60 {
61 private:
62 struct Loser
63 {
64 // The relevant element.
65 T key;
66
67 // Is this an infimum or supremum element?
68 bool inf, sup;
69
70 // Number of the sequence the element comes from.
71 int source;
72 };
73
74 unsigned int size, offset;
75 Loser* losers;
76 Comparator comp;
77
78 public:
79 inline LoserTreeExplicit(unsigned int _size, Comparator _comp = std::less<T>()) : comp(_comp)
80 {
81 size = _size;
82 offset = size;
83 losers = new Loser[size];
84 for (unsigned int l = 0; l < size; l++)
85 {
86 //losers[l].key = ... stays unset
87 losers[l].inf = true;
88 losers[l].sup = false;
89 //losers[l].source = -1; //sentinel
90 }
91 }
92
93 inline ~LoserTreeExplicit()
94 { delete[] losers; }
95
96 inline void
97 print() { }
98
99 inline int
100 get_min_source()
101 { return losers[0].source; }
102
103 inline void
104 insert_start(T key, int source, bool sup)
105 {
106 bool inf = false;
107 for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
108 {
109 if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup && comp(losers[pos].key, key)) || losers[pos].inf || sup)
110 {
111 // The other one is smaller.
112 std::swap(losers[pos].key, key);
113 std::swap(losers[pos].inf, inf);
114 std::swap(losers[pos].sup, sup);
115 std::swap(losers[pos].source, source);
116 }
117 }
118
119 losers[0].key = key;
120 losers[0].inf = inf;
121 losers[0].sup = sup;
122 losers[0].source = source;
123 }
124
125 inline void
126 init() { }
127
128 inline void
129 delete_min_insert(T key, bool sup)
130 {
131 bool inf = false;
132 int source = losers[0].source;
133 for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
134 {
135 // The smaller one gets promoted.
136 if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup
137 && comp(losers[pos].key, key))
138 || losers[pos].inf || sup)
139 {
140 // The other one is smaller.
141 std::swap(losers[pos].key, key);
142 std::swap(losers[pos].inf, inf);
143 std::swap(losers[pos].sup, sup);
144 std::swap(losers[pos].source, source);
145 }
146 }
147
148 losers[0].key = key;
149 losers[0].inf = inf;
150 losers[0].sup = sup;
151 losers[0].source = source;
152 }
153
154 inline void
155 insert_start_stable(T key, int source, bool sup)
156 {
157 bool inf = false;
158 for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
159 {
160 if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup &&
161 ((comp(losers[pos].key, key)) ||
162 (!comp(key, losers[pos].key) && losers[pos].source < source)))
163 || losers[pos].inf || sup)
164 {
165 // Take next key.
166 std::swap(losers[pos].key, key);
167 std::swap(losers[pos].inf, inf);
168 std::swap(losers[pos].sup, sup);
169 std::swap(losers[pos].source, source);
170 }
171 }
172
173 losers[0].key = key;
174 losers[0].inf = inf;
175 losers[0].sup = sup;
176 losers[0].source = source;
177 }
178
179 inline void
180 init_stable() { }
181
182 inline void
183 delete_min_insert_stable(T key, bool sup)
184 {
185 bool inf = false;
186 int source = losers[0].source;
187 for (unsigned int pos = (offset + source) / 2; pos > 0; pos /= 2)
188 {
189 if ((!inf && !losers[pos].inf && !sup && !losers[pos].sup
190 && ((comp(losers[pos].key, key)) ||
191 (!comp(key, losers[pos].key) && losers[pos].source < source)))
192 || losers[pos].inf || sup)
193 {
194 std::swap(losers[pos].key, key);
195 std::swap(losers[pos].inf, inf);
196 std::swap(losers[pos].sup, sup);
197 std::swap(losers[pos].source, source);
198 }
199 }
200
201 losers[0].key = key;
202 losers[0].inf = inf;
203 losers[0].sup = sup;
204 losers[0].source = source;
205 }
206 };
207
208 #endif
209
210 #if _GLIBCXX_LOSER_TREE
211
212 /** @brief Guarded loser tree, either copying the whole element into
213 * the tree structure, or looking up the element via the index.
214 *
215 * Guarding is done explicitly through one flag sup per element,
216 * inf is not needed due to a better initialization routine. This
217 * is a well-performing variant.
218 */
219 template<typename T, typename Comparator = std::less<T> >
220 class LoserTree
221 {
222 private:
223 struct Loser
224 {
225 bool sup;
226 int source;
227 T key;
228 };
229
230 unsigned int ik, k, offset;
231 Loser* losers;
232 Comparator comp;
233
234 public:
235 inline LoserTree(unsigned int _k, Comparator _comp = std::less<T>())
236 : comp(_comp)
237 {
238 ik = _k;
239
240 // Next greater power of 2.
241 k = 1 << (log2(ik - 1) + 1);
242 offset = k;
243 losers = new Loser[k * 2];
244 for (unsigned int i = ik - 1; i < k; i++)
245 losers[i + k].sup = true;
246 }
247
248 inline ~LoserTree()
249 { delete[] losers; }
250
251 void
252 print()
253 {
254 for (unsigned int i = 0; i < (k * 2); i++)
255 printf("%d %d from %d, %d\n", i, losers[i].key,
256 losers[i].source, losers[i].sup);
257 }
258
259 inline int
260 get_min_source()
261 { return losers[0].source; }
262
263 inline void
264 insert_start(const T& key, int source, bool sup)
265 {
266 unsigned int pos = k + source;
267
268 losers[pos].sup = sup;
269 losers[pos].source = source;
270 losers[pos].key = key;
271 }
272
273 unsigned int
274 init_winner (unsigned int root)
275 {
276 if (root >= k)
277 {
278 return root;
279 }
280 else
281 {
282 unsigned int left = init_winner (2 * root);
283 unsigned int right = init_winner (2 * root + 1);
284 if (losers[right].sup ||
285 (!losers[left].sup && !comp(losers[right].key, losers[left].key)))
286 {
287 // Left one is less or equal.
288 losers[root] = losers[right];
289 return left;
290 }
291 else
292 { // Right one is less.
293 losers[root] = losers[left];
294 return right;
295 }
296 }
297 }
298
299 inline void
300 init()
301 { losers[0] = losers[init_winner(1)]; }
302
303 // Do not pass const reference since key will be used as local variable.
304 inline void
305 delete_min_insert(T key, bool sup)
306 {
307 int source = losers[0].source;
308 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
309 {
310 // The smaller one gets promoted.
311 if (sup || (!losers[pos].sup && comp(losers[pos].key, key)))
312 {
313 // The other one is smaller.
314 std::swap(losers[pos].sup, sup);
315 std::swap(losers[pos].source, source);
316 std::swap(losers[pos].key, key);
317 }
318 }
319
320 losers[0].sup = sup;
321 losers[0].source = source;
322 losers[0].key = key;
323 }
324
325 inline void
326 insert_start_stable(const T& key, int source, bool sup)
327 { return insert_start(key, source, sup); }
328
329 unsigned int
330 init_winner_stable (unsigned int root)
331 {
332 if (root >= k)
333 {
334 return root;
335 }
336 else
337 {
338 unsigned int left = init_winner (2 * root);
339 unsigned int right = init_winner (2 * root + 1);
340 if ( losers[right].sup ||
341 (!losers[left].sup && !comp(losers[right].key, losers[left].key)))
342 {
343 // Left one is less or equal.
344 losers[root] = losers[right];
345 return left;
346 }
347 else
348 {
349 // Right one is less.
350 losers[root] = losers[left];
351 return right;
352 }
353 }
354 }
355
356 inline void
357 init_stable()
358 { losers[0] = losers[init_winner_stable(1)]; }
359
360 // Do not pass const reference since key will be used as local variable.
361 inline void
362 delete_min_insert_stable(T key, bool sup)
363 {
364 int source = losers[0].source;
365 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
366 {
367 // The smaller one gets promoted, ties are broken by source.
368 if ( (sup && (!losers[pos].sup || losers[pos].source < source)) ||
369 (!sup && !losers[pos].sup &&
370 ((comp(losers[pos].key, key)) ||
371 (!comp(key, losers[pos].key) && losers[pos].source < source))))
372 {
373 // The other one is smaller.
374 std::swap(losers[pos].sup, sup);
375 std::swap(losers[pos].source, source);
376 std::swap(losers[pos].key, key);
377 }
378 }
379
380 losers[0].sup = sup;
381 losers[0].source = source;
382 losers[0].key = key;
383 }
384 };
385
386 #endif
387
388 #if _GLIBCXX_LOSER_TREE_REFERENCE
389
390 /** @brief Guarded loser tree, either copying the whole element into
391 * the tree structure, or looking up the element via the index.
392 *
393 * Guarding is done explicitly through one flag sup per element,
394 * inf is not needed due to a better initialization routine. This
395 * is a well-performing variant.
396 */
397 template<typename T, typename Comparator = std::less<T> >
398 class LoserTreeReference
399 {
400 #undef COPY
401 #ifdef COPY
402 #define KEY(i) losers[i].key
403 #define KEY_SOURCE(i) key
404 #else
405 #define KEY(i) keys[losers[i].source]
406 #define KEY_SOURCE(i) keys[i]
407 #endif
408 private:
409 struct Loser
410 {
411 bool sup;
412 int source;
413 #ifdef COPY
414 T key;
415 #endif
416 };
417
418 unsigned int ik, k, offset;
419 Loser* losers;
420 #ifndef COPY
421 T* keys;
422 #endif
423 Comparator comp;
424
425 public:
426 inline LoserTreeReference(unsigned int _k, Comparator _comp = std::less<T>()) : comp(_comp)
427 {
428 ik = _k;
429
430 // Next greater power of 2.
431 k = 1 << (log2(ik - 1) + 1);
432 offset = k;
433 losers = new Loser[k * 2];
434 #ifndef COPY
435 keys = new T[ik];
436 #endif
437 for (unsigned int i = ik - 1; i < k; i++)
438 losers[i + k].sup = true;
439 }
440
441 inline ~LoserTreeReference()
442 {
443 delete[] losers;
444 #ifndef COPY
445 delete[] keys;
446 #endif
447 }
448
449 void
450 print()
451 {
452 for (unsigned int i = 0; i < (k * 2); i++)
453 printf("%d %d from %d, %d\n", i, KEY(i), losers[i].source, losers[i].sup);
454 }
455
456 inline int
457 get_min_source()
458 { return losers[0].source; }
459
460 inline void
461 insert_start(T key, int source, bool sup)
462 {
463 unsigned int pos = k + source;
464
465 losers[pos].sup = sup;
466 losers[pos].source = source;
467 KEY(pos) = key;
468 }
469
470 unsigned int
471 init_winner(unsigned int root)
472 {
473 if (root >= k)
474 {
475 return root;
476 }
477 else
478 {
479 unsigned int left = init_winner (2 * root);
480 unsigned int right = init_winner (2 * root + 1);
481 if ( losers[right].sup ||
482 (!losers[left].sup && !comp(KEY(right), KEY(left))))
483 {
484 // Left one is less or equal.
485 losers[root] = losers[right];
486 return left;
487 }
488 else
489 {
490 // Right one is less.
491 losers[root] = losers[left];
492 return right;
493 }
494 }
495 }
496
497 inline void
498 init()
499 {
500 losers[0] = losers[init_winner(1)];
501 }
502
503 inline void
504 delete_min_insert(T key, bool sup)
505 {
506 int source = losers[0].source;
507 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
508 {
509 // The smaller one gets promoted.
510 if (sup || (!losers[pos].sup && comp(KEY(pos), KEY_SOURCE(source))))
511 {
512 // The other one is smaller.
513 std::swap(losers[pos].sup, sup);
514 std::swap(losers[pos].source, source);
515 #ifdef COPY
516 std::swap(KEY(pos), KEY_SOURCE(source));
517 #endif
518 }
519 }
520
521 losers[0].sup = sup;
522 losers[0].source = source;
523 #ifdef COPY
524 KEY(0) = KEY_SOURCE(source);
525 #endif
526 }
527
528 inline void
529 insert_start_stable(T key, int source, bool sup)
530 { return insert_start(key, source, sup); }
531
532 unsigned int
533 init_winner_stable(unsigned int root)
534 {
535 if (root >= k)
536 {
537 return root;
538 }
539 else
540 {
541 unsigned int left = init_winner (2 * root);
542 unsigned int right = init_winner (2 * root + 1);
543 if (losers[right].sup
544 || (!losers[left].sup && !comp(KEY(right), KEY(left))))
545 {
546 // Left one is less or equal.
547 losers[root] = losers[right];
548 return left;
549 }
550 else
551 {
552 // Right one is less.
553 losers[root] = losers[left];
554 return right;
555 }
556 }
557 }
558
559 inline void
560 init_stable()
561 { losers[0] = losers[init_winner_stable(1)]; }
562
563 inline void
564 delete_min_insert_stable(T key, bool sup)
565 {
566 int source = losers[0].source;
567 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
568 {
569 // The smaller one gets promoted, ties are broken by source.
570 if ( (sup && (!losers[pos].sup || losers[pos].source < source)) ||
571 (!sup && !losers[pos].sup &&
572 ((comp(KEY(pos), KEY_SOURCE(source))) ||
573 (!comp(KEY_SOURCE(source), KEY(pos)) && losers[pos].source < source))))
574 {
575 // The other one is smaller.
576 std::swap(losers[pos].sup, sup);
577 std::swap(losers[pos].source, source);
578 #ifdef COPY
579 std::swap(KEY(pos), KEY_SOURCE(source));
580 #endif
581 }
582 }
583
584 losers[0].sup = sup;
585 losers[0].source = source;
586 #ifdef COPY
587 KEY(0) = KEY_SOURCE(source);
588 #endif
589 }
590 };
591 #undef KEY
592 #undef KEY_SOURCE
593
594 #endif
595
596 #if _GLIBCXX_LOSER_TREE_POINTER
597
598 /** @brief Guarded loser tree, either copying the whole element into
599 the tree structure, or looking up the element via the index.
600 * Guarding is done explicitly through one flag sup per element,
601 * inf is not needed due to a better initialization routine.
602 * This is a well-performing variant.
603 */
604 template<typename T, typename Comparator = std::less<T> >
605 class LoserTreePointer
606 {
607 private:
608 struct Loser
609 {
610 bool sup;
611 int source;
612 const T* keyp;
613 };
614
615 unsigned int ik, k, offset;
616 Loser* losers;
617 Comparator comp;
618
619 public:
620 inline LoserTreePointer(unsigned int _k, Comparator _comp = std::less<T>()) : comp(_comp)
621 {
622 ik = _k;
623
624 // Next greater power of 2.
625 k = 1 << (log2(ik - 1) + 1);
626 offset = k;
627 losers = new Loser[k * 2];
628 for (unsigned int i = ik - 1; i < k; i++)
629 losers[i + k].sup = true;
630 }
631
632 inline ~LoserTreePointer()
633 { delete[] losers; }
634
635 void
636 print()
637 {
638 for (unsigned int i = 0; i < (k * 2); i++)
639 printf("%d %d from %d, %d\n", i, losers[i].keyp, losers[i].source, losers[i].sup);
640 }
641
642 inline int
643 get_min_source()
644 { return losers[0].source; }
645
646 inline void
647 insert_start(const T& key, int source, bool sup)
648 {
649 unsigned int pos = k + source;
650
651 losers[pos].sup = sup;
652 losers[pos].source = source;
653 losers[pos].keyp = &key;
654 }
655
656 unsigned int
657 init_winner(unsigned int root)
658 {
659 if (root >= k)
660 {
661 return root;
662 }
663 else
664 {
665 unsigned int left = init_winner (2 * root);
666 unsigned int right = init_winner (2 * root + 1);
667 if ( losers[right].sup ||
668 (!losers[left].sup && !comp(*losers[right].keyp, *losers[left].keyp)))
669 {
670 // Left one is less or equal.
671 losers[root] = losers[right];
672 return left;
673 }
674 else
675 {
676 // Right one is less.
677 losers[root] = losers[left];
678 return right;
679 }
680 }
681 }
682
683 inline void
684 init()
685 { losers[0] = losers[init_winner(1)]; }
686
687 inline void
688 delete_min_insert(const T& key, bool sup)
689 {
690 const T* keyp = &key;
691 int source = losers[0].source;
692 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
693 {
694 // The smaller one gets promoted.
695 if (sup || (!losers[pos].sup && comp(*losers[pos].keyp, *keyp)))
696 {
697 // The other one is smaller.
698 std::swap(losers[pos].sup, sup);
699 std::swap(losers[pos].source, source);
700 std::swap(losers[pos].keyp, keyp);
701 }
702 }
703
704 losers[0].sup = sup;
705 losers[0].source = source;
706 losers[0].keyp = keyp;
707 }
708
709 inline void
710 insert_start_stable(const T& key, int source, bool sup)
711 { return insert_start(key, source, sup); }
712
713 unsigned int
714 init_winner_stable(unsigned int root)
715 {
716 if (root >= k)
717 {
718 return root;
719 }
720 else
721 {
722 unsigned int left = init_winner (2 * root);
723 unsigned int right = init_winner (2 * root + 1);
724 if (losers[right].sup
725 || (!losers[left].sup && !comp(*losers[right].keyp,
726 *losers[left].keyp)))
727 {
728 // Left one is less or equal.
729 losers[root] = losers[right];
730 return left;
731 }
732 else
733 {
734 // Right one is less.
735 losers[root] = losers[left];
736 return right;
737 }
738 }
739 }
740
741 inline void
742 init_stable()
743 { losers[0] = losers[init_winner_stable(1)]; }
744
745 inline void
746 delete_min_insert_stable(const T& key, bool sup)
747 {
748 const T* keyp = &key;
749 int source = losers[0].source;
750 for (unsigned int pos = (k + source) / 2; pos > 0; pos /= 2)
751 {
752 // The smaller one gets promoted, ties are broken by source.
753 if ( (sup && (!losers[pos].sup || losers[pos].source < source)) ||
754 (!sup && !losers[pos].sup &&
755 ((comp(*losers[pos].keyp, *keyp)) ||
756 (!comp(*keyp, *losers[pos].keyp)
757 && losers[pos].source < source))))
758 {
759 // The other one is smaller.
760 std::swap(losers[pos].sup, sup);
761 std::swap(losers[pos].source, source);
762 std::swap(losers[pos].keyp, keyp);
763 }
764 }
765
766 losers[0].sup = sup;
767 losers[0].source = source;
768 losers[0].keyp = keyp;
769 }
770 };
771
772 #endif
773
774 #if _GLIBCXX_LOSER_TREE_UNGUARDED
775
776 /** @brief Unguarded loser tree, copying the whole element into the
777 * tree structure.
778 *
779 * No guarding is done, therefore not a single input sequence must
780 * run empty. This is a very fast variant.
781 */
782 template<typename T, typename Comparator = std::less<T> >
783 class LoserTreeUnguarded
784 {
785 private:
786 struct Loser
787 {
788 int source;
789 T key;
790 };
791
792 unsigned int ik, k, offset;
793 unsigned int* mapping;
794 Loser* losers;
795 Comparator comp;
796
797 void
798 map(unsigned int root, unsigned int begin, unsigned int end)
799 {
800 if (begin + 1 == end)
801 mapping[begin] = root;
802 else
803 {
804 // Next greater or equal power of 2.
805 unsigned int left = 1 << (log2(end - begin - 1));
806 map(root * 2, begin, begin + left);
807 map(root * 2 + 1, begin + left, end);
808 }
809 }
810
811 public:
812 inline LoserTreeUnguarded(unsigned int _k, Comparator _comp = std::less<T>()) : comp(_comp)
813 {
814 ik = _k;
815 // Next greater or equal power of 2.
816 k = 1 << (log2(ik - 1) + 1);
817 offset = k;
818 losers = new Loser[k + ik];
819 mapping = new unsigned int[ik];
820 map(1, 0, ik);
821 }
822
823 inline ~LoserTreeUnguarded()
824 {
825 delete[] losers;
826 delete[] mapping;
827 }
828
829 void
830 print()
831 {
832 for (unsigned int i = 0; i < k + ik; i++)
833 printf("%d %d from %d\n", i, losers[i].key, losers[i].source);
834 }
835
836 inline int
837 get_min_source()
838 { return losers[0].source; }
839
840 inline void
841 insert_start(const T& key, int source, bool)
842 {
843 unsigned int pos = mapping[source];
844 losers[pos].source = source;
845 losers[pos].key = key;
846 }
847
848 unsigned int
849 init_winner(unsigned int root, unsigned int begin, unsigned int end)
850 {
851 if (begin + 1 == end)
852 return mapping[begin];
853 else
854 {
855 // Next greater or equal power of 2.
856 unsigned int division = 1 << (log2(end - begin - 1));
857 unsigned int left = init_winner(2 * root, begin, begin + division);
858 unsigned int right = init_winner(2 * root + 1, begin + division, end);
859 if (!comp(losers[right].key, losers[left].key))
860 {
861 // Left one is less or equal.
862 losers[root] = losers[right];
863 return left;
864 }
865 else
866 {
867 // Right one is less.
868 losers[root] = losers[left];
869 return right;
870 }
871 }
872 }
873
874 inline void
875 init()
876 { losers[0] = losers[init_winner(1, 0, ik)]; }
877
878 // Do not pass const reference since key will be used as local variable.
879 inline void
880 delete_min_insert(const T& key, bool)
881 {
882 losers[0].key = key;
883 T& keyr = losers[0].key;
884 int& source = losers[0].source;
885 for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
886 {
887 // The smaller one gets promoted.
888 if (comp(losers[pos].key, keyr))
889 {
890 // The other one is smaller.
891 std::swap(losers[pos].source, source);
892 std::swap(losers[pos].key, keyr);
893 }
894 }
895 }
896
897 inline void
898 insert_start_stable(const T& key, int source, bool)
899 { return insert_start(key, source, false); }
900
901 inline void
902 init_stable()
903 { init(); }
904
905 inline void
906 delete_min_insert_stable(const T& key, bool)
907 {
908 losers[0].key = key;
909 T& keyr = losers[0].key;
910 int& source = losers[0].source;
911 for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
912 {
913 // The smaller one gets promoted, ties are broken by source.
914 if (comp(losers[pos].key, keyr)
915 || (!comp(keyr, losers[pos].key) && losers[pos].source < source))
916 {
917 // The other one is smaller.
918 std::swap(losers[pos].source, source);
919 std::swap(losers[pos].key, keyr);
920 }
921 }
922 }
923 };
924
925 #endif
926
927 #if _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
928
929 /** @brief Unguarded loser tree, keeping only pointers to the
930 * elements in the tree structure.
931 *
932 * No guarding is done, therefore not a single input sequence must
933 * run empty. This is a very fast variant.
934 */
935 template<typename T, typename Comparator = std::less<T> >
936 class LoserTreePointerUnguarded
937 {
938 private:
939 struct Loser
940 {
941 int source;
942 const T* keyp;
943 };
944
945 unsigned int ik, k, offset;
946 unsigned int* mapping;
947 Loser* losers;
948 Comparator comp;
949
950 void map(unsigned int root, unsigned int begin, unsigned int end)
951 {
952 if (begin + 1 == end)
953 mapping[begin] = root;
954 else
955 {
956 // Next greater or equal power of 2.
957 unsigned int left = 1 << (log2(end - begin - 1));
958 map(root * 2, begin, begin + left);
959 map(root * 2 + 1, begin + left, end);
960 }
961 }
962
963 public:
964 inline LoserTreePointerUnguarded(unsigned int _k, Comparator _comp = std::less<T>()) : comp(_comp)
965 {
966 ik = _k;
967
968 // Next greater power of 2.
969 k = 1 << (log2(ik - 1) + 1);
970 offset = k;
971 losers = new Loser[k + ik];
972 mapping = new unsigned int[ik];
973 map(1, 0, ik);
974 }
975
976 inline ~LoserTreePointerUnguarded()
977 {
978 delete[] losers;
979 delete[] mapping;
980 }
981
982 void
983 print()
984 {
985 for (unsigned int i = 0; i < k + ik; i++)
986 printf("%d %d from %d\n", i, *losers[i].keyp, losers[i].source);
987 }
988
989 inline int
990 get_min_source()
991 { return losers[0].source; }
992
993 inline void
994 insert_start(const T& key, int source, bool)
995 {
996 unsigned int pos = mapping[source];
997 losers[pos].source = source;
998 losers[pos].keyp = &key;
999 }
1000
1001 unsigned int
1002 init_winner(unsigned int root, unsigned int begin, unsigned int end)
1003 {
1004 if (begin + 1 == end)
1005 return mapping[begin];
1006 else
1007 {
1008 // Next greater or equal power of 2.
1009 unsigned int division = 1 << (log2(end - begin - 1));
1010 unsigned int left = init_winner(2 * root, begin, begin + division);
1011 unsigned int right = init_winner(2 * root + 1, begin + division, end);
1012 if (!comp(*losers[right].keyp, *losers[left].keyp))
1013 {
1014 // Left one is less or equal.
1015 losers[root] = losers[right];
1016 return left;
1017 }
1018 else
1019 {
1020 // Right one is less.
1021 losers[root] = losers[left];
1022 return right;
1023 }
1024 }
1025 }
1026
1027 inline void
1028 init()
1029 {
1030 losers[0] = losers[init_winner(1, 0, ik)];
1031 }
1032
1033 inline void
1034 delete_min_insert(const T& key, bool)
1035 {
1036 const T* keyp = &key;
1037 int& source = losers[0].source;
1038 for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
1039 {
1040 // The smaller one gets promoted.
1041 if (comp(*losers[pos].keyp, *keyp))
1042 {
1043 // The other one is smaller.
1044 std::swap(losers[pos].source, source);
1045 std::swap(losers[pos].keyp, keyp);
1046 }
1047 }
1048
1049 losers[0].keyp = keyp;
1050 }
1051
1052 inline void
1053 insert_start_stable(const T& key, int source, bool)
1054 { return insert_start(key, source, false); }
1055
1056 inline void
1057 init_stable()
1058 { init(); }
1059
1060 inline void
1061 delete_min_insert_stable(const T& key, bool)
1062 {
1063 int& source = losers[0].source;
1064 const T* keyp = &key;
1065 for (int pos = mapping[source] / 2; pos > 0; pos /= 2)
1066 {
1067 // The smaller one gets promoted, ties are broken by source.
1068 if (comp(*losers[pos].keyp, *keyp)
1069 || (!comp(*keyp, *losers[pos].keyp)
1070 && losers[pos].source < source))
1071 {
1072 // The other one is smaller.
1073 std::swap(losers[pos].source, source);
1074 std::swap(losers[pos].keyp, keyp);
1075 }
1076 }
1077 losers[0].keyp = keyp;
1078 }
1079 };
1080 #endif
1081
1082 template<typename _ValueTp, class Comparator>
1083 struct loser_tree_traits
1084 {
1085 #if _GLIBCXX_LOSER_TREE
1086 typedef LoserTree<_ValueTp, Comparator> LT;
1087 #else
1088 # if _GLIBCXX_LOSER_TREE_POINTER
1089 typedef LoserTreePointer<_ValueTp, Comparator> LT;
1090 # else
1091 # error Must define some type in losertree.h.
1092 # endif
1093 #endif
1094 };
1095
1096 template<typename _ValueTp, class Comparator>
1097 struct loser_tree_traits_unguarded
1098 {
1099 #if _GLIBCXX_LOSER_TREE_UNGUARDED
1100 typedef LoserTreeUnguarded<_ValueTp, Comparator> LT;
1101 #else
1102 # if _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
1103 typedef LoserTreePointerUnguarded<_ValueTp, Comparator> LT;
1104 # else
1105 # error Must define some type in losertree.h.
1106 # endif
1107 #endif
1108 };
1109
1110 }
1111
1112 #endif