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 #if defined(__GNUC__) && (__GNUC__ * 1000 + __GNUC_MINOR__ < 4002)
42 * This function sometimes triggers optimizer bugs in GCC 4.1.1 and
43 * possibly also earlier versions, leading to an assumption that tree[1]
44 * does not change during this function. We add an explicit memory barrier
45 * as a work-around. Ugh.
47 asm volatile ("" : : : "memory");
51 static inline void P(set_tree)(P(key) *keys, P(mwt_node) *tree, uns i, int val)
54 P(update_tree)(keys, tree, i);
57 static void P(multiway_merge)(struct sort_context *ctx UNUSED, struct sort_bucket **ins, struct sort_bucket *out)
67 struct fastbuf *fout = sbuck_write(out);
68 struct fastbuf *fins[num_ins];
70 P(mwt_node) tree[2*n2]; // A complete binary tree, leaves are input streams, each internal vertex contains a minimum of its sons
71 for (uns i=1; i<2*n2; i++)
72 tree[i] = (P(mwt_node)) { .i = -1 };
74 for (uns i=0; i<num_ins; i++)
76 fins[i] = sbuck_read(ins[i]);
77 if (P(read_key)(fins[i], &keys[i]))
78 P(set_tree)(keys, tree, n2+i, i);
84 P(key) *mkeys[num_ins], *key;
85 struct fastbuf *mfb[num_ins];
87 while (likely(tree[1].i >= 0))
92 /* The key is unique, so let's go through the fast path */
93 P(copy_data)(&keys[i], fins[i], fout);
94 if (unlikely(!P(read_key)(fins[i], &keys[i])))
96 P(update_tree)(keys, tree, n2+i);
108 P(set_tree)(keys, tree, n2+i, -1);
113 while (!P(compare)(key, &keys[i]));
115 P(copy_merged)(mkeys, mfb, m, fout);
117 for (uns j=0; j<m; j++)
120 if (likely(P(read_key)(fins[i], &keys[i])))
121 P(set_tree)(keys, tree, n2+i, i);
127 /* Simplified version which does not support any unification */
128 while (likely(tree[1].i >= 0))
131 P(key) UNUSED key = keys[i];
132 P(copy_data)(&keys[i], fins[i], fout);
133 if (unlikely(!P(read_key)(fins[i], &keys[i])))
135 P(update_tree)(keys, tree, n2+i);
136 #ifdef SORT_ASSERT_UNIQUE
137 ASSERT(tree[1].i < 0 || P(compare)(&key, &keys[tree[1].i]) < 0);