15 #ifndef STXXL_LOSERTREE_HEADER
16 #define STXXL_LOSERTREE_HEADER
19 #include <stxxl/bits/noncopyable.h>
20 #include <stxxl/bits/common/utils.h>
21 #include <stxxl/bits/verbose.h>
24 __STXXL_BEGIN_NAMESPACE
26 template <
typename run_cursor_type,
27 typename run_cursor_cmp_type>
28 class loser_tree :
private noncopyable
33 run_cursor_type * current;
34 run_cursor_cmp_type cmp;
36 int_type init_winner(int_type root)
44 int_type left = init_winner(2 * root);
45 int_type right = init_winner(2 * root + 1);
46 if (cmp(current[left], current[right]))
60 typedef typename run_cursor_type::prefetcher_type prefetcher_type;
61 typedef typename run_cursor_type::value_type value_type;
66 run_cursor_cmp_type c) : cmp(c)
69 logK = log2_ceil(nruns);
70 int_type kReg = k = (1 << logK);
72 STXXL_VERBOSE2(
"loser_tree: logK=" << logK <<
" nruns=" << nruns <<
" K=" << kReg);
74 #ifdef STXXL_SORT_SINGLE_PREFETCHER
75 current =
new run_cursor_type[kReg];
76 run_cursor_type::set_prefetcher(p);
78 current =
new run_cursor_type[kReg];
79 for (i = 0; i < kReg; ++i)
80 current[i].prefetcher() = p;
82 entry =
new int_type[(kReg << 1)];
84 for (i = 0; i < nruns; ++i)
86 current[i].buffer = p->pull_block();
91 for (i = nruns; i < kReg; ++i)
93 current[i].make_inf();
97 entry[0] = init_winner(1);
105 void swap(loser_tree & obj)
107 std::swap(logK, obj.logK);
109 std::swap(entry, obj.entry);
110 std::swap(current, obj.current);
111 std::swap(cmp, obj.cmp);
115 template <
unsigned LogK>
116 void multi_merge_unrolled(value_type * out_first, value_type * out_last)
118 run_cursor_type * currentE, * winnerE;
119 int_type * regEntry = entry;
120 int_type winnerIndex = regEntry[0];
122 while (LIKELY(out_first != out_last))
124 winnerE = current + winnerIndex;
125 *(out_first) = winnerE->current();
131 #define TreeStep(L) \
134 currentE = current + \
135 regEntry[(winnerIndex + (1 << LogK)) >> (((int(LogK - L) + 1) >= 0) ? ((LogK - L) + 1) : 0)]; \
136 if (cmp(*currentE, *winnerE)) \
138 std::swap(regEntry[(winnerIndex + (1 << LogK)) \
139 >> (((int(LogK - L) + 1) >= 0) ? ((LogK - L) + 1) : 0)], winnerIndex); \
140 winnerE = currentE; \
158 regEntry[0] = winnerIndex;
161 void multi_merge_unrolled_0(value_type * out_first, value_type * out_last)
163 while (LIKELY(out_first != out_last))
165 *out_first = current->current();
171 void multi_merge_k(value_type * out_first, value_type * out_last)
173 run_cursor_type * currentE, * winnerE;
175 int_type winnerIndex = entry[0];
177 while (LIKELY(out_first != out_last))
179 winnerE = current + winnerIndex;
180 *(out_first) = winnerE->current();
185 for (int_type i = (winnerIndex + kReg) >> 1; i > 0; i >>= 1)
187 currentE = current + entry[i];
189 if (cmp(*currentE, *winnerE))
191 std::swap(entry[i], winnerIndex);
197 entry[0] = winnerIndex;
201 void multi_merge(value_type * out_first, value_type * out_last)
206 multi_merge_unrolled_0(out_first, out_last);
209 multi_merge_unrolled<1>(out_first, out_last);
212 multi_merge_unrolled<2>(out_first, out_last);
215 multi_merge_unrolled<3>(out_first, out_last);
218 multi_merge_unrolled<4>(out_first, out_last);
221 multi_merge_unrolled<5>(out_first, out_last);
224 multi_merge_unrolled<6>(out_first, out_last);
227 multi_merge_unrolled<7>(out_first, out_last);
230 multi_merge_unrolled<8>(out_first, out_last);
233 multi_merge_unrolled<9>(out_first, out_last);
236 multi_merge_unrolled<10>(out_first, out_last);
239 multi_merge_k(out_first, out_last);
245 __STXXL_END_NAMESPACE
249 template <
typename run_cursor_type,
250 typename run_cursor_cmp_type>
251 void swap(stxxl::loser_tree<run_cursor_type, run_cursor_cmp_type> & a,
252 stxxl::loser_tree<run_cursor_type, run_cursor_cmp_type> & b)
258 #endif // !STXXL_LOSERTREE_HEADER