18 int (*compar)(
const void *,
const void *),
19 struct run ** runs,
size_t * num_runs) {
21 size_t runs_array_size = 0;
27 (*runs)->ordering = -1;
29 char * curr_element = base + size;
31 size_t * curr_count = &((*runs)->count);
33 for (
size_t i = 1; i < num; ++i) {
35 int order = compar(curr_element - size, curr_element);
37 if ((order == 0) || !((order < 0) ^ (curr_order < 0))) {
46 curr_count = &((*runs)[*num_runs].count);
47 (*runs)[*num_runs].count = 1;
48 (*runs)[*num_runs].ordering = order;
56static void merge(
char * base_a,
size_t num_a,
int a_ascending,
57 char * base_b,
size_t num_b,
int b_ascending,
59 int (*compar)(
const void *,
const void *),
62 char * curr_a = base_a + ((a_ascending)?0:((num_a - 1) * size));
63 char * curr_b = base_b + ((b_ascending)?0:((num_b - 1) * size));
64 int inc_a = (a_ascending)?(size):(-size);
65 int inc_b = (b_ascending)?(size):(-size);
66 char * end_a = curr_a + inc_a * num_a;
67 char * end_b = curr_b + inc_b * num_b;
69 while (curr_a != end_a && curr_b != end_b) {
73 if (compar(curr_a, curr_b) <= 0) {
81 memcpy(target, from, size);
85 size_t diff = (size_t)(end_a - curr_a);
87 memcpy(target, curr_a, diff);
91 diff = (size_t)(end_b - curr_b);
93 memcpy(target, curr_b, diff);
99 char * base,
size_t size,
int (*compar)(
const void *,
const void *),
100 struct run ** runs,
size_t * num_runs,
char * buffer) {
102 size_t num_merges = *num_runs >> 1;
104 struct run * curr_runs = *runs;
106 for (
size_t i = 0; i < num_merges; ++i) {
109 base + curr_runs[0].
count * size, curr_runs[1].
count,
110 curr_runs[1].
ordering < 0, size, compar, buffer);
112 base += (curr_runs[0].
count + curr_runs[1].
count) * size;
113 buffer += (curr_runs[0].
count + curr_runs[1].
count) * size;
115 (*runs)[i].count = curr_runs[0].
count + curr_runs[1].
count;
116 (*runs)[i].ordering = -1;
121 if ((*num_runs) & 1) {
123 (*runs)[num_merges] = (*runs)[*num_runs-1];
124 memcpy(buffer, base, (*runs)[num_merges].
count * size);
127 *num_runs = num_merges + ((*num_runs) & 1);
135 int (*compar)(
const void *,
const void *)) {
137 if (size == 0 || num == 0)
return;
142 char * buffer =
xmalloc(num * size);
146 while (num_runs > 1) {
147 merge_runs((
char*)base, size, compar, &runs, &num_runs, buffer);
148 merge_runs(buffer, size, compar, &runs, &num_runs, (
char*)base);
static void determine_runs(char *base, size_t num, size_t size, int(*compar)(const void *, const void *), struct run **runs, size_t *num_runs)
static void merge(char *base_a, size_t num_a, int a_ascending, char *base_b, size_t num_b, int b_ascending, size_t size, int(*compar)(const void *, const void *), char *target)
static void merge_runs(char *base, size_t size, int(*compar)(const void *, const void *), struct run **runs, size_t *num_runs, char *buffer)