3 // Copyright (C) 2007, 2008 Free Software Foundation, Inc.
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
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.
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.
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
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.
36 // Written by Johannes Singler.
38 #ifndef _GLIBCXX_PARALLEL_LOSERTREE_H
39 #define _GLIBCXX_PARALLEL_LOSERTREE_H 1
43 #include <bits/stl_algobase.h>
44 #include <parallel/features.h>
45 #include <parallel/base.h>
47 namespace __gnu_parallel
50 #if _GLIBCXX_LOSER_TREE_EXPLICIT
52 /** @brief Guarded loser tree, copying the whole element into the
55 * Guarding is done explicitly through two flags per element, inf
56 * and sup This is a quite slow variant.
58 template<typename T
, typename Comparator
= std::less
<T
> >
59 class LoserTreeExplicit
64 // The relevant element.
67 // Is this an infimum or supremum element?
70 // Number of the sequence the element comes from.
74 unsigned int size
, offset
;
79 LoserTreeExplicit(unsigned int _size
, Comparator _comp
= std::less
<T
>())
84 losers
= new Loser
[size
];
85 for (unsigned int l
= 0; l
< size
; ++l
)
87 //losers[l].key = ... stays unset
89 losers
[l
].sup
= false;
90 //losers[l].source = -1; //sentinel
99 { return losers
[0].source
; }
102 insert_start(T key
, int source
, bool sup
)
105 for (unsigned int pos
= (offset
+ source
) / 2; pos
> 0; pos
/= 2)
107 if ((!inf
&& !losers
[pos
].inf
&& !sup
&& !losers
[pos
].sup
108 && comp(losers
[pos
].key
, key
)) || losers
[pos
].inf
|| sup
)
110 // The other one is smaller.
111 std::swap(losers
[pos
].key
, key
);
112 std::swap(losers
[pos
].inf
, inf
);
113 std::swap(losers
[pos
].sup
, sup
);
114 std::swap(losers
[pos
].source
, source
);
121 losers
[0].source
= source
;
128 delete_min_insert(T key
, bool sup
)
131 int source
= losers
[0].source
;
132 for (unsigned int pos
= (offset
+ source
) / 2; pos
> 0; pos
/= 2)
134 // The smaller one gets promoted.
135 if ((!inf
&& !losers
[pos
].inf
&& !sup
&& !losers
[pos
].sup
136 && comp(losers
[pos
].key
, key
))
137 || losers
[pos
].inf
|| sup
)
139 // The other one is smaller.
140 std::swap(losers
[pos
].key
, key
);
141 std::swap(losers
[pos
].inf
, inf
);
142 std::swap(losers
[pos
].sup
, sup
);
143 std::swap(losers
[pos
].source
, source
);
150 losers
[0].source
= source
;
154 insert_start_stable(T key
, int source
, bool sup
)
157 for (unsigned int pos
= (offset
+ source
) / 2; pos
> 0; pos
/= 2)
159 if ((!inf
&& !losers
[pos
].inf
&& !sup
&& !losers
[pos
].sup
160 && ((comp(losers
[pos
].key
, key
))
161 || (!comp(key
, losers
[pos
].key
)
162 && losers
[pos
].source
< source
)))
163 || losers
[pos
].inf
|| sup
)
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
);
176 losers
[0].source
= source
;
183 delete_min_insert_stable(T key
, bool sup
)
186 int source
= losers
[0].source
;
187 for (unsigned int pos
= (offset
+ source
) / 2; pos
> 0; pos
/= 2)
189 if ((!inf
&& !losers
[pos
].inf
&& !sup
&& !losers
[pos
].sup
190 && ((comp(losers
[pos
].key
, key
))
191 || (!comp(key
, losers
[pos
].key
)
192 && losers
[pos
].source
< source
)))
193 || losers
[pos
].inf
|| sup
)
195 std::swap(losers
[pos
].key
, key
);
196 std::swap(losers
[pos
].inf
, inf
);
197 std::swap(losers
[pos
].sup
, sup
);
198 std::swap(losers
[pos
].source
, source
);
205 losers
[0].source
= source
;
211 #if _GLIBCXX_LOSER_TREE
213 /** @brief Guarded loser tree, either copying the whole element into
214 * the tree structure, or looking up the element via the index.
216 * Guarding is done explicitly through one flag sup per element,
217 * inf is not needed due to a better initialization routine. This
218 * is a well-performing variant.
220 template<typename T
, typename Comparator
= std::less
<T
> >
231 unsigned int ik
, k
, offset
;
237 LoserTree(unsigned int _k
, Comparator _comp
= std::less
<T
>())
242 // Next greater power of 2.
243 k
= 1 << (log2(ik
- 1) + 1);
245 // Avoid default-constructing losers[].key
246 losers
= static_cast<Loser
*>(::operator new(2 * k
* sizeof(Loser
)));
247 for (unsigned int i
= ik
- 1; i
< k
; ++i
)
248 losers
[i
+ k
].sup
= true;
254 { ::operator delete(losers
); }
258 { return losers
[0].source
; }
261 insert_start(const T
& key
, int source
, bool sup
)
263 unsigned int pos
= k
+ source
;
267 // Construct all keys, so we can easily deconstruct them.
268 for (unsigned int i
= 0; i
< (2 * k
); ++i
)
269 ::new(&(losers
[i
].key
)) T(key
);
270 first_insert
= false;
273 ::new(&(losers
[pos
].key
)) T(key
);
275 losers
[pos
].sup
= sup
;
276 losers
[pos
].source
= source
;
280 init_winner (unsigned int root
)
288 unsigned int left
= init_winner (2 * root
);
289 unsigned int right
= init_winner (2 * root
+ 1);
290 if (losers
[right
].sup
291 || (!losers
[left
].sup
292 && !comp(losers
[right
].key
, losers
[left
].key
)))
294 // Left one is less or equal.
295 losers
[root
] = losers
[right
];
300 // Right one is less.
301 losers
[root
] = losers
[left
];
309 { losers
[0] = losers
[init_winner(1)]; }
311 // Do not pass const reference since key will be used as local variable.
313 delete_min_insert(T key
, bool sup
)
315 int source
= losers
[0].source
;
316 for (unsigned int pos
= (k
+ source
) / 2; pos
> 0; pos
/= 2)
318 // The smaller one gets promoted.
319 if (sup
|| (!losers
[pos
].sup
&& comp(losers
[pos
].key
, key
)))
321 // The other one is smaller.
322 std::swap(losers
[pos
].sup
, sup
);
323 std::swap(losers
[pos
].source
, source
);
324 std::swap(losers
[pos
].key
, key
);
329 losers
[0].source
= source
;
334 insert_start_stable(const T
& key
, int source
, bool sup
)
335 { return insert_start(key
, source
, sup
); }
338 init_winner_stable (unsigned int root
)
346 unsigned int left
= init_winner (2 * root
);
347 unsigned int right
= init_winner (2 * root
+ 1);
348 if (losers
[right
].sup
349 || (!losers
[left
].sup
350 && !comp(losers
[right
].key
, losers
[left
].key
)))
352 // Left one is less or equal.
353 losers
[root
] = losers
[right
];
358 // Right one is less.
359 losers
[root
] = losers
[left
];
367 { losers
[0] = losers
[init_winner_stable(1)]; }
369 // Do not pass const reference since key will be used as local variable.
371 delete_min_insert_stable(T key
, bool sup
)
373 int source
= losers
[0].source
;
374 for (unsigned int pos
= (k
+ source
) / 2; pos
> 0; pos
/= 2)
376 // The smaller one gets promoted, ties are broken by source.
377 if ( (sup
&& (!losers
[pos
].sup
|| losers
[pos
].source
< source
))
378 || (!sup
&& !losers
[pos
].sup
379 && ((comp(losers
[pos
].key
, key
))
380 || (!comp(key
, losers
[pos
].key
)
381 && losers
[pos
].source
< source
))))
383 // The other one is smaller.
384 std::swap(losers
[pos
].sup
, sup
);
385 std::swap(losers
[pos
].source
, source
);
386 std::swap(losers
[pos
].key
, key
);
391 losers
[0].source
= source
;
398 #if _GLIBCXX_LOSER_TREE_REFERENCE
400 /** @brief Guarded loser tree, either copying the whole element into
401 * the tree structure, or looking up the element via the index.
403 * Guarding is done explicitly through one flag sup per element,
404 * inf is not needed due to a better initialization routine. This
405 * is a well-performing variant.
407 template<typename T
, typename Comparator
= std::less
<T
> >
408 class LoserTreeReference
412 #define KEY(i) losers[i].key
413 #define KEY_SOURCE(i) key
415 #define KEY(i) keys[losers[i].source]
416 #define KEY_SOURCE(i) keys[i]
428 unsigned int ik
, k
, offset
;
436 LoserTreeReference(unsigned int _k
, Comparator _comp
= std::less
<T
>())
441 // Next greater power of 2.
442 k
= 1 << (log2(ik
- 1) + 1);
444 losers
= new Loser
[k
* 2];
448 for (unsigned int i
= ik
- 1; i
< k
; ++i
)
449 losers
[i
+ k
].sup
= true;
452 ~LoserTreeReference()
462 { return losers
[0].source
; }
465 insert_start(T key
, int source
, bool sup
)
467 unsigned int pos
= k
+ source
;
469 losers
[pos
].sup
= sup
;
470 losers
[pos
].source
= source
;
475 init_winner(unsigned int root
)
483 unsigned int left
= init_winner (2 * root
);
484 unsigned int right
= init_winner (2 * root
+ 1);
485 if ( losers
[right
].sup
||
486 (!losers
[left
].sup
&& !comp(KEY(right
), KEY(left
))))
488 // Left one is less or equal.
489 losers
[root
] = losers
[right
];
494 // Right one is less.
495 losers
[root
] = losers
[left
];
504 losers
[0] = losers
[init_winner(1)];
508 delete_min_insert(T key
, bool sup
)
510 int source
= losers
[0].source
;
511 for (unsigned int pos
= (k
+ source
) / 2; pos
> 0; pos
/= 2)
513 // The smaller one gets promoted.
514 if (sup
|| (!losers
[pos
].sup
&& comp(KEY(pos
), KEY_SOURCE(source
))))
516 // The other one is smaller.
517 std::swap(losers
[pos
].sup
, sup
);
518 std::swap(losers
[pos
].source
, source
);
520 std::swap(KEY(pos
), KEY_SOURCE(source
));
526 losers
[0].source
= source
;
528 KEY(0) = KEY_SOURCE(source
);
533 insert_start_stable(T key
, int source
, bool sup
)
534 { return insert_start(key
, source
, sup
); }
537 init_winner_stable(unsigned int root
)
545 unsigned int left
= init_winner (2 * root
);
546 unsigned int right
= init_winner (2 * root
+ 1);
547 if (losers
[right
].sup
548 || (!losers
[left
].sup
&& !comp(KEY(right
), KEY(left
))))
550 // Left one is less or equal.
551 losers
[root
] = losers
[right
];
556 // Right one is less.
557 losers
[root
] = losers
[left
];
565 { losers
[0] = losers
[init_winner_stable(1)]; }
568 delete_min_insert_stable(T key
, bool sup
)
570 int source
= losers
[0].source
;
571 for (unsigned int pos
= (k
+ source
) / 2; pos
> 0; pos
/= 2)
573 // The smaller one gets promoted, ties are broken by source.
574 if ((sup
&& (!losers
[pos
].sup
|| losers
[pos
].source
< source
))
575 || (!sup
&& !losers
[pos
].sup
576 && ((comp(KEY(pos
), KEY_SOURCE(source
)))
577 || (!comp(KEY_SOURCE(source
), KEY(pos
))
578 && losers
[pos
].source
< source
))))
580 // The other one is smaller.
581 std::swap(losers
[pos
].sup
, sup
);
582 std::swap(losers
[pos
].source
, source
);
584 std::swap(KEY(pos
), KEY_SOURCE(source
));
590 losers
[0].source
= source
;
592 KEY(0) = KEY_SOURCE(source
);
601 #if _GLIBCXX_LOSER_TREE_POINTER
603 /** @brief Guarded loser tree, either copying the whole element into
604 the tree structure, or looking up the element via the index.
605 * Guarding is done explicitly through one flag sup per element,
606 * inf is not needed due to a better initialization routine.
607 * This is a well-performing variant.
609 template<typename T
, typename Comparator
= std::less
<T
> >
610 class LoserTreePointer
620 unsigned int ik
, k
, offset
;
625 LoserTreePointer(unsigned int _k
, Comparator _comp
= std::less
<T
>())
630 // Next greater power of 2.
631 k
= 1 << (log2(ik
- 1) + 1);
633 losers
= new Loser
[k
* 2];
634 for (unsigned int i
= ik
- 1; i
< k
; ++i
)
635 losers
[i
+ k
].sup
= true;
643 { return losers
[0].source
; }
646 insert_start(const T
& key
, int source
, bool sup
)
648 unsigned int pos
= k
+ source
;
650 losers
[pos
].sup
= sup
;
651 losers
[pos
].source
= source
;
652 losers
[pos
].keyp
= &key
;
656 init_winner(unsigned int root
)
662 unsigned int left
= init_winner (2 * root
);
663 unsigned int right
= init_winner (2 * root
+ 1);
664 if (losers
[right
].sup
665 || (!losers
[left
].sup
666 && !comp(*losers
[right
].keyp
, *losers
[left
].keyp
)))
668 // Left one is less or equal.
669 losers
[root
] = losers
[right
];
674 // Right one is less.
675 losers
[root
] = losers
[left
];
683 { losers
[0] = losers
[init_winner(1)]; }
686 delete_min_insert(const T
& key
, bool sup
)
688 const T
* keyp
= &key
;
689 int source
= losers
[0].source
;
690 for (unsigned int pos
= (k
+ source
) / 2; pos
> 0; pos
/= 2)
692 // The smaller one gets promoted.
693 if (sup
|| (!losers
[pos
].sup
&& comp(*losers
[pos
].keyp
, *keyp
)))
695 // The other one is smaller.
696 std::swap(losers
[pos
].sup
, sup
);
697 std::swap(losers
[pos
].source
, source
);
698 std::swap(losers
[pos
].keyp
, keyp
);
703 losers
[0].source
= source
;
704 losers
[0].keyp
= keyp
;
708 insert_start_stable(const T
& key
, int source
, bool sup
)
709 { return insert_start(key
, source
, sup
); }
712 init_winner_stable(unsigned int root
)
720 unsigned int left
= init_winner (2 * root
);
721 unsigned int right
= init_winner (2 * root
+ 1);
722 if (losers
[right
].sup
723 || (!losers
[left
].sup
&& !comp(*losers
[right
].keyp
,
724 *losers
[left
].keyp
)))
726 // Left one is less or equal.
727 losers
[root
] = losers
[right
];
732 // Right one is less.
733 losers
[root
] = losers
[left
];
741 { losers
[0] = losers
[init_winner_stable(1)]; }
744 delete_min_insert_stable(const T
& key
, bool sup
)
746 const T
* keyp
= &key
;
747 int source
= losers
[0].source
;
748 for (unsigned int pos
= (k
+ source
) / 2; pos
> 0; pos
/= 2)
750 // The smaller one gets promoted, ties are broken by source.
751 if ( (sup
&& (!losers
[pos
].sup
|| losers
[pos
].source
< source
))
752 || (!sup
&& !losers
[pos
].sup
&&
753 ((comp(*losers
[pos
].keyp
, *keyp
))
754 || (!comp(*keyp
, *losers
[pos
].keyp
)
755 && losers
[pos
].source
< source
))))
757 // The other one is smaller.
758 std::swap(losers
[pos
].sup
, sup
);
759 std::swap(losers
[pos
].source
, source
);
760 std::swap(losers
[pos
].keyp
, keyp
);
765 losers
[0].source
= source
;
766 losers
[0].keyp
= keyp
;
772 #if _GLIBCXX_LOSER_TREE_UNGUARDED
774 /** @brief Unguarded loser tree, copying the whole element into the
777 * No guarding is done, therefore not a single input sequence must
778 * run empty. This is a very fast variant.
780 template<typename T
, typename Comparator
= std::less
<T
> >
781 class LoserTreeUnguarded
790 unsigned int ik
, k
, offset
;
791 unsigned int* mapping
;
796 map(unsigned int root
, unsigned int begin
, unsigned int end
)
798 if (begin
+ 1 == end
)
799 mapping
[begin
] = root
;
802 // Next greater or equal power of 2.
803 unsigned int left
= 1 << (log2(end
- begin
- 1));
804 map(root
* 2, begin
, begin
+ left
);
805 map(root
* 2 + 1, begin
+ left
, end
);
810 LoserTreeUnguarded(unsigned int _k
, Comparator _comp
= std::less
<T
>())
814 // Next greater or equal power of 2.
815 k
= 1 << (log2(ik
- 1) + 1);
817 losers
= new Loser
[k
+ ik
];
818 mapping
= new unsigned int[ik
];
822 ~LoserTreeUnguarded()
830 { return losers
[0].source
; }
833 insert_start(const T
& key
, int source
, bool)
835 unsigned int pos
= mapping
[source
];
836 losers
[pos
].source
= source
;
837 losers
[pos
].key
= key
;
841 init_winner(unsigned int root
, unsigned int begin
, unsigned int end
)
843 if (begin
+ 1 == end
)
844 return mapping
[begin
];
847 // Next greater or equal power of 2.
848 unsigned int division
= 1 << (log2(end
- begin
- 1));
849 unsigned int left
= init_winner(2 * root
, begin
, begin
+ division
);
851 init_winner(2 * root
+ 1, begin
+ division
, end
);
852 if (!comp(losers
[right
].key
, losers
[left
].key
))
854 // Left one is less or equal.
855 losers
[root
] = losers
[right
];
860 // Right one is less.
861 losers
[root
] = losers
[left
];
869 { losers
[0] = losers
[init_winner(1, 0, ik
)]; }
871 // Do not pass const reference since key will be used as local variable.
873 delete_min_insert(const T
& key
, bool)
876 T
& keyr
= losers
[0].key
;
877 int& source
= losers
[0].source
;
878 for (int pos
= mapping
[source
] / 2; pos
> 0; pos
/= 2)
880 // The smaller one gets promoted.
881 if (comp(losers
[pos
].key
, keyr
))
883 // The other one is smaller.
884 std::swap(losers
[pos
].source
, source
);
885 std::swap(losers
[pos
].key
, keyr
);
891 insert_start_stable(const T
& key
, int source
, bool)
892 { return insert_start(key
, source
, false); }
899 delete_min_insert_stable(const T
& key
, bool)
902 T
& keyr
= losers
[0].key
;
903 int& source
= losers
[0].source
;
904 for (int pos
= mapping
[source
] / 2; pos
> 0; pos
/= 2)
906 // The smaller one gets promoted, ties are broken by source.
907 if (comp(losers
[pos
].key
, keyr
)
908 || (!comp(keyr
, losers
[pos
].key
)
909 && losers
[pos
].source
< source
))
911 // The other one is smaller.
912 std::swap(losers
[pos
].source
, source
);
913 std::swap(losers
[pos
].key
, keyr
);
921 #if _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
923 /** @brief Unguarded loser tree, keeping only pointers to the
924 * elements in the tree structure.
926 * No guarding is done, therefore not a single input sequence must
927 * run empty. This is a very fast variant.
929 template<typename T
, typename Comparator
= std::less
<T
> >
930 class LoserTreePointerUnguarded
939 unsigned int ik
, k
, offset
;
940 unsigned int* mapping
;
944 void map(unsigned int root
, unsigned int begin
, unsigned int end
)
946 if (begin
+ 1 == end
)
947 mapping
[begin
] = root
;
950 // Next greater or equal power of 2.
951 unsigned int left
= 1 << (log2(end
- begin
- 1));
952 map(root
* 2, begin
, begin
+ left
);
953 map(root
* 2 + 1, begin
+ left
, end
);
958 LoserTreePointerUnguarded(unsigned int _k
,
959 Comparator _comp
= std::less
<T
>())
964 // Next greater power of 2.
965 k
= 1 << (log2(ik
- 1) + 1);
967 losers
= new Loser
[k
+ ik
];
968 mapping
= new unsigned int[ik
];
972 ~LoserTreePointerUnguarded()
980 { return losers
[0].source
; }
983 insert_start(const T
& key
, int source
, bool)
985 unsigned int pos
= mapping
[source
];
986 losers
[pos
].source
= source
;
987 losers
[pos
].keyp
= &key
;
991 init_winner(unsigned int root
, unsigned int begin
, unsigned int end
)
993 if (begin
+ 1 == end
)
994 return mapping
[begin
];
997 // Next greater or equal power of 2.
998 unsigned int division
= 1 << (log2(end
- begin
- 1));
999 unsigned int left
= init_winner(2 * root
, begin
, begin
+ division
);
1000 unsigned int right
= init_winner(2 * root
+ 1,
1001 begin
+ division
, end
);
1002 if (!comp(*losers
[right
].keyp
, *losers
[left
].keyp
))
1004 // Left one is less or equal.
1005 losers
[root
] = losers
[right
];
1010 // Right one is less.
1011 losers
[root
] = losers
[left
];
1019 { losers
[0] = losers
[init_winner(1, 0, ik
)]; }
1022 delete_min_insert(const T
& key
, bool)
1024 const T
* keyp
= &key
;
1025 int& source
= losers
[0].source
;
1026 for (int pos
= mapping
[source
] / 2; pos
> 0; pos
/= 2)
1028 // The smaller one gets promoted.
1029 if (comp(*losers
[pos
].keyp
, *keyp
))
1031 // The other one is smaller.
1032 std::swap(losers
[pos
].source
, source
);
1033 std::swap(losers
[pos
].keyp
, keyp
);
1037 losers
[0].keyp
= keyp
;
1041 insert_start_stable(const T
& key
, int source
, bool)
1042 { return insert_start(key
, source
, false); }
1049 delete_min_insert_stable(const T
& key
, bool)
1051 int& source
= losers
[0].source
;
1052 const T
* keyp
= &key
;
1053 for (int pos
= mapping
[source
] / 2; pos
> 0; pos
/= 2)
1055 // The smaller one gets promoted, ties are broken by source.
1056 if (comp(*losers
[pos
].keyp
, *keyp
)
1057 || (!comp(*keyp
, *losers
[pos
].keyp
)
1058 && losers
[pos
].source
< source
))
1060 // The other one is smaller.
1061 std::swap(losers
[pos
].source
, source
);
1062 std::swap(losers
[pos
].keyp
, keyp
);
1065 losers
[0].keyp
= keyp
;
1070 template<typename _ValueTp
, class Comparator
>
1071 struct loser_tree_traits
1073 #if _GLIBCXX_LOSER_TREE
1074 typedef LoserTree
<_ValueTp
, Comparator
> LT
;
1076 # if _GLIBCXX_LOSER_TREE_POINTER
1077 typedef LoserTreePointer
<_ValueTp
, Comparator
> LT
;
1079 # error Must define some type in losertree.h.
1084 template<typename _ValueTp
, class Comparator
>
1085 struct loser_tree_unguarded_traits
1087 #if _GLIBCXX_LOSER_TREE_UNGUARDED
1088 typedef LoserTreeUnguarded
<_ValueTp
, Comparator
> LT
;
1090 # if _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
1091 typedef LoserTreePointerUnguarded
<_ValueTp
, Comparator
> LT
;
1093 # error Must define some unguarded type in losertree.h.