10 static void *get_next(const void *a
)
12 return ((const struct line
*)a
)->next
;
15 static void set_next(void *a
, void *b
)
17 ((struct line
*)a
)->next
= b
;
20 static int compare_strings(const void *a
, const void *b
)
22 const struct line
*x
= a
, *y
= b
;
23 return strcmp(x
->text
, y
->text
);
26 static int sort_stdin(void)
28 struct line
*line
, *p
= NULL
, *lines
= NULL
;
29 struct strbuf sb
= STRBUF_INIT
;
31 while (!strbuf_getline(&sb
, stdin
)) {
32 line
= xmalloc(sizeof(struct line
));
33 line
->text
= strbuf_detach(&sb
, NULL
);
44 lines
= llist_mergesort(lines
, get_next
, set_next
, compare_strings
);
53 static void dist_sawtooth(int *arr
, int n
, int m
)
56 for (i
= 0; i
< n
; i
++)
60 static void dist_rand(int *arr
, int n
, int m
)
63 for (i
= 0; i
< n
; i
++)
67 static void dist_stagger(int *arr
, int n
, int m
)
70 for (i
= 0; i
< n
; i
++)
71 arr
[i
] = (i
* m
+ i
) % n
;
74 static void dist_plateau(int *arr
, int n
, int m
)
77 for (i
= 0; i
< n
; i
++)
78 arr
[i
] = (i
< m
) ? i
: m
;
81 static void dist_shuffle(int *arr
, int n
, int m
)
84 for (i
= j
= 0, k
= 1; i
< n
; i
++)
85 arr
[i
] = (rand() % m
) ? (j
+= 2) : (k
+= 2);
88 #define DIST(name) { #name, dist_##name }
92 void (*fn
)(int *arr
, int n
, int m
);
101 static void mode_copy(int *arr
, int n
)
106 static void mode_reverse(int *arr
, int n
)
109 for (i
= 0, j
= n
- 1; i
< j
; i
++, j
--)
110 SWAP(arr
[i
], arr
[j
]);
113 static void mode_reverse_1st_half(int *arr
, int n
)
115 mode_reverse(arr
, n
/ 2);
118 static void mode_reverse_2nd_half(int *arr
, int n
)
121 mode_reverse(arr
+ half
, n
- half
);
124 static int compare_ints(const void *av
, const void *bv
)
126 const int *ap
= av
, *bp
= bv
;
127 int a
= *ap
, b
= *bp
;
128 return (a
> b
) - (a
< b
);
131 static void mode_sort(int *arr
, int n
)
133 QSORT(arr
, n
, compare_ints
);
136 static void mode_dither(int *arr
, int n
)
139 for (i
= 0; i
< n
; i
++)
143 #define MODE(name) { #name, mode_##name }
147 void (*fn
)(int *arr
, int n
);
151 MODE(reverse_1st_half
),
152 MODE(reverse_2nd_half
),
157 static struct stats
{
158 int get_next
, set_next
, compare
;
166 static void *get_next_number(const void *a
)
169 return ((const struct number
*)a
)->next
;
172 static void set_next_number(void *a
, void *b
)
175 ((struct number
*)a
)->next
= b
;
178 static int compare_numbers(const void *av
, const void *bv
)
180 const struct number
*an
= av
, *bn
= bv
;
181 int a
= an
->value
, b
= bn
->value
;
183 return (a
> b
) - (a
< b
);
186 static void clear_numbers(struct number
*list
)
189 struct number
*next
= list
->next
;
195 static int test(const struct dist
*dist
, const struct mode
*mode
, int n
, int m
)
199 struct number
*curr
, *list
, **tail
;
208 for (i
= 0, tail
= &list
; i
< n
; i
++) {
209 curr
= xmalloc(sizeof(*curr
));
210 curr
->value
= arr
[i
];
217 stats
.get_next
= stats
.set_next
= stats
.compare
= 0;
218 list
= llist_mergesort(list
, get_next_number
, set_next_number
,
221 QSORT(arr
, n
, compare_ints
);
222 for (i
= 0, curr
= list
; i
< n
&& curr
; i
++, curr
= curr
->next
) {
223 if (arr
[i
] != curr
->value
)
225 if (curr
->next
&& curr
->value
== curr
->next
->value
&&
226 curr
->rank
>= curr
->next
->rank
)
230 verdict
= "too short";
232 verdict
= "too long";
233 } else if (!is_sorted
) {
234 verdict
= "not sorted";
235 } else if (!is_stable
) {
236 verdict
= "unstable";
242 printf("%-9s %-16s %8d %8d %8d %8d %8d %s\n",
243 dist
->name
, mode
->name
, n
, m
, stats
.get_next
, stats
.set_next
,
244 stats
.compare
, verdict
);
253 * A version of the qsort certification program from "Engineering a Sort
254 * Function" by Bentley and McIlroy, Software—Practice and Experience,
255 * Volume 23, Issue 11, 1249–1265 (November 1993).
257 static int run_tests(int argc
, const char **argv
)
259 const char *argv_default
[] = { "100", "1023", "1024", "1025" };
261 return run_tests(ARRAY_SIZE(argv_default
), argv_default
);
262 printf("%-9s %-16s %8s %8s %8s %8s %8s %s\n",
263 "distribut", "mode", "n", "m", "get_next", "set_next",
264 "compare", "verdict");
266 int i
, j
, m
, n
= strtol(*argv
++, NULL
, 10);
267 for (i
= 0; i
< ARRAY_SIZE(dist
); i
++) {
268 for (j
= 0; j
< ARRAY_SIZE(mode
); j
++) {
269 for (m
= 1; m
< 2 * n
; m
*= 2) {
270 if (test(&dist
[i
], &mode
[j
], n
, m
))
279 int cmd__mergesort(int argc
, const char **argv
)
281 if (argc
== 2 && !strcmp(argv
[1], "sort"))
283 if (argc
> 1 && !strcmp(argv
[1], "test"))
284 return run_tests(argc
- 2, argv
+ 2);
285 fprintf(stderr
, "usage: test-tool mergesort sort\n");
286 fprintf(stderr
, " or: test-tool mergesort test [<n>...]\n");