2 * UCW Library -- Universal Sorter: Fixed-Size Internal Sorting 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 #define ASORT_PREFIX(x) SORT_PREFIX(array_##x)
11 #define ASORT_KEY_TYPE P(key)
12 #define ASORT_ELT(i) ary[i]
13 #define ASORT_LT(x,y) (P(compare)(&(x), &(y)) < 0)
14 #define ASORT_EXTRA_ARGS , P(key) *ary
15 #include "lib/arraysort.h"
17 static int P(internal_num_keys)(struct sort_context *ctx)
19 size_t bufsize = ctx->big_buf_half_size;
21 // When we promise unification, we have to reduce the number of records
22 // to be sure that both pointers and merged records fit in the 2nd half
23 // of the big_buf. So we eat as much memory as s-internal.h, but still
25 u64 maxkeys = bufsize / (sizeof(P(key)) + sizeof(void *));
27 u64 maxkeys = bufsize / sizeof(P(key));
29 return MIN(maxkeys, ~0U); // The number of records must fit in uns
32 static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct sort_bucket *bout, struct sort_bucket *bout_only)
34 sorter_alloc_buf(ctx);
35 struct fastbuf *in = sbuck_read(bin);
36 P(key) *buf = ctx->big_buf;
37 uns maxkeys = P(internal_num_keys)(ctx);
39 SORT_XTRACE(3, "s-fixint: Reading (maxkeys=%u)", maxkeys);
41 while (n < maxkeys && P(read_key)(in, &buf[n]))
46 SORT_XTRACE(3, "s-fixint: Sorting %u items", n);
47 P(array_sort)(n, buf);
49 SORT_XTRACE(3, "s-fixint: Writing");
50 struct fastbuf *out = sbuck_write((n < maxkeys) ? bout_only : bout);
52 uns merged UNUSED = 0;
53 for (uns i=0; i<n; i++)
56 if (i < n-1 && !P(compare)(&buf[i], &buf[i+1]))
58 P(key) **keys = ctx->big_buf_half;
62 while (!P(compare)(&buf[i], &buf[i+n]))
67 P(write_merged)(out, keys, NULL, n, keys+n);
73 #ifdef SORT_ASSERT_UNIQUE
74 ASSERT(i == n-1 || P(compare)(&buf[i], &buf[i+1]) < 0);
76 P(write_key)(out, &buf[i]);
79 SORT_XTRACE(3, "Merging reduced %d records", merged);
82 return (n == maxkeys);
86 P(internal_estimate)(struct sort_context *ctx, struct sort_bucket *b UNUSED)
88 return P(internal_num_keys)(ctx) * sizeof(P(key)) - 1; // -1 since if the buffer is full, we don't recognize EOF