2 * UCW Library -- Universal Sorter: Multi-Way Merge Module
4 * (c) 2007 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
10 typedef struct P(mwt_node) {
17 static inline void P(update_tree)(P(key) *keys, P(mwt_node) *tree, uns i)
22 tree[i] = tree[2*i+1];
23 else if (tree[2*i+1].i < 0)
27 int cmp = P(compare)(&keys[tree[2*i].i], &keys[tree[2*i+1].i]);
28 tree[i] = (cmp <= 0) ? tree[2*i] : tree[2*i+1];
35 * It is very tempting to stop as soon as the current node does not
36 * change, but it is wrong, because even if the stream index stored in
37 * the tree is the same, the actual key value can differ.
40 ASSERT(tree[1].i < 16);
43 static inline void P(set_tree)(P(key) *keys, P(mwt_node) *tree, uns i, int val)
46 P(update_tree)(keys, tree, i);
49 static void P(multiway_merge)(struct sort_context *ctx UNUSED, struct sort_bucket **ins, struct sort_bucket *out)
59 struct fastbuf *fout = sbuck_write(out);
60 struct fastbuf *fins[num_ins];
62 P(mwt_node) tree[2*n2]; // A complete binary tree, leaves are input streams, each internal vertex contains a minimum of its sons
63 for (uns i=1; i<2*n2; i++)
64 tree[i] = (P(mwt_node)) { .i = -1 };
66 for (uns i=0; i<num_ins; i++)
68 fins[i] = sbuck_read(ins[i]);
69 if (P(read_key)(fins[i], &keys[i]))
70 P(set_tree)(keys, tree, n2+i, i);
76 P(key) *mkeys[num_ins], *key;
77 struct fastbuf *mfb[num_ins];
79 while (likely(tree[1].i >= 0))
84 /* The key is unique, so let's go through the fast path */
85 P(copy_data)(&keys[i], fins[i], fout);
86 if (unlikely(!P(read_key)(fins[i], &keys[i])))
88 P(update_tree)(keys, tree, n2+i);
100 P(set_tree)(keys, tree, n2+i, -1);
105 while (!P(compare)(key, &keys[i]));
107 P(copy_merged)(mkeys, mfb, m, fout);
109 for (uns j=0; j<m; j++)
112 if (likely(P(read_key)(fins[i], &keys[i])))
113 P(set_tree)(keys, tree, n2+i, i);
119 /* Simplified version which does not support any unification */
120 while (likely(tree[1].i >= 0))
123 P(key) UNUSED key = keys[i];
124 P(copy_data)(&keys[i], fins[i], fout);
125 if (unlikely(!P(read_key)(fins[i], &keys[i])))
127 P(update_tree)(keys, tree, n2+i);
128 #ifdef SORT_ASSERT_UNIQUE
129 ASSERT(tree[1].i < 0 || P(compare)(&key, &keys[tree[1].i]) < 0);