xref: /freebsd/tools/tools/sortbench/sort_bench.c (revision b3e76948)
1d7d787c0SBrooks Davis /*-
2d7d787c0SBrooks Davis  * Copyright (c) 2017 Miles Fertel
3d7d787c0SBrooks Davis  * All rights reserved.
4d7d787c0SBrooks Davis  *
5d7d787c0SBrooks Davis  * Redistribution and use in source and binary forms, with or without
6d7d787c0SBrooks Davis  * modification, are permitted provided that the following conditions
7d7d787c0SBrooks Davis  * are met:
8d7d787c0SBrooks Davis  * 1. Redistributions of source code must retain the above copyright
9d7d787c0SBrooks Davis  *    notice, this list of conditions and the following disclaimer,
10d7d787c0SBrooks Davis  *    without modification.
11d7d787c0SBrooks Davis  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12d7d787c0SBrooks Davis  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13d7d787c0SBrooks Davis  *    redistribution must be conditioned upon including a substantially
14d7d787c0SBrooks Davis  *    similar Disclaimer requirement for further binary redistribution.
15d7d787c0SBrooks Davis  *
16d7d787c0SBrooks Davis  * NO WARRANTY
17d7d787c0SBrooks Davis  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18d7d787c0SBrooks Davis  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19d7d787c0SBrooks Davis  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20d7d787c0SBrooks Davis  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21d7d787c0SBrooks Davis  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22d7d787c0SBrooks Davis  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23d7d787c0SBrooks Davis  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24d7d787c0SBrooks Davis  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25d7d787c0SBrooks Davis  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26d7d787c0SBrooks Davis  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27d7d787c0SBrooks Davis  * THE POSSIBILITY OF SUCH DAMAGES.
28d7d787c0SBrooks Davis  */
29d7d787c0SBrooks Davis 
30d7d787c0SBrooks Davis #include <math.h>
31d7d787c0SBrooks Davis #include <stdio.h>
32d7d787c0SBrooks Davis #include <stdlib.h>
33d7d787c0SBrooks Davis #include <string.h>
34d7d787c0SBrooks Davis #include <sysexits.h>
35d7d787c0SBrooks Davis #include <unistd.h>
36d7d787c0SBrooks Davis 
37d7d787c0SBrooks Davis #ifdef WIKI
38d7d787c0SBrooks Davis #include "stdlib/wiki.c"
39d7d787c0SBrooks Davis #endif
40d7d787c0SBrooks Davis 
41d7d787c0SBrooks Davis /*
42d7d787c0SBrooks Davis  * Integer comparison function for stdlib sorting algorithms
43d7d787c0SBrooks Davis  */
44d7d787c0SBrooks Davis static int
sorthelp(const void * a,const void * b)45d7d787c0SBrooks Davis sorthelp(const void *a, const void *b)
46d7d787c0SBrooks Davis {
47d7d787c0SBrooks Davis 	if (*(int *)a > *(int *)b)
48d7d787c0SBrooks Davis 		return 1;
49d7d787c0SBrooks Davis 	if (*(int *)a < *(int *)b)
50d7d787c0SBrooks Davis 		return -1;
51d7d787c0SBrooks Davis 	return 0;
52d7d787c0SBrooks Davis }
53d7d787c0SBrooks Davis 
54d7d787c0SBrooks Davis #define NARGS 5
55d7d787c0SBrooks Davis 
56d7d787c0SBrooks Davis /*
57d7d787c0SBrooks Davis  * Enumerated types for the different types of tests and sorting algorithms
58d7d787c0SBrooks Davis  */
59d7d787c0SBrooks Davis enum test { RAND, SORT, PART, REV, INVALID_TEST };
60d7d787c0SBrooks Davis 
61d7d787c0SBrooks Davis #ifdef WIKI
62d7d787c0SBrooks Davis enum sort { MERGE, WIKI, QUICK, HEAP, INVALID_ALG };
63d7d787c0SBrooks Davis #else
64d7d787c0SBrooks Davis enum sort { MERGE, QUICK, HEAP, INVALID_ALG };
65d7d787c0SBrooks Davis #endif
66d7d787c0SBrooks Davis 
67d7d787c0SBrooks Davis /*
68d7d787c0SBrooks Davis  * Sort an array with the given algorithm
69d7d787c0SBrooks Davis  */
70d7d787c0SBrooks Davis static void
sort(int * testarray,int elts,enum sort s)71d7d787c0SBrooks Davis sort(int *testarray, int elts, enum sort s)
72d7d787c0SBrooks Davis {
73d7d787c0SBrooks Davis 	switch (s) {
74d7d787c0SBrooks Davis 	case MERGE:
75d7d787c0SBrooks Davis 		mergesort(testarray, (size_t)elts, sizeof(int), sorthelp);
76d7d787c0SBrooks Davis 		break;
77d7d787c0SBrooks Davis #ifdef WIKI
78d7d787c0SBrooks Davis 	case WIKI:
79d7d787c0SBrooks Davis 		WikiSort(testarray, (size_t)elts, sizeof(int), sorthelp);
80d7d787c0SBrooks Davis 		break;
81d7d787c0SBrooks Davis #endif
82d7d787c0SBrooks Davis 	case QUICK:
83d7d787c0SBrooks Davis 		qsort(testarray, (size_t)elts, sizeof(int), sorthelp);
84d7d787c0SBrooks Davis 		break;
85d7d787c0SBrooks Davis 	case HEAP:
86d7d787c0SBrooks Davis 		heapsort(testarray, (size_t)elts, sizeof(int), sorthelp);
87d7d787c0SBrooks Davis 		break;
88d7d787c0SBrooks Davis 	// Should never be reached
89d7d787c0SBrooks Davis 	case INVALID_ALG:
90d7d787c0SBrooks Davis 		exit(EX_DATAERR);
91d7d787c0SBrooks Davis 	}
92d7d787c0SBrooks Davis }
93d7d787c0SBrooks Davis 
94d7d787c0SBrooks Davis /*
95d7d787c0SBrooks Davis  * Sort an array of randomly generated integers
96d7d787c0SBrooks Davis  */
97d7d787c0SBrooks Davis static void
rand_bench(int elts,enum sort s)98d7d787c0SBrooks Davis rand_bench(int elts, enum sort s)
99d7d787c0SBrooks Davis {
100d7d787c0SBrooks Davis 	size_t size = sizeof(int) * elts;
101d7d787c0SBrooks Davis 	int *array = malloc(size);
102d7d787c0SBrooks Davis 	arc4random_buf(array, size);
103d7d787c0SBrooks Davis 	sort(array, elts, s);
104d7d787c0SBrooks Davis 	free(array);
105d7d787c0SBrooks Davis }
106d7d787c0SBrooks Davis 
107d7d787c0SBrooks Davis /*
108d7d787c0SBrooks Davis  * Sort an array of increasing integers
109d7d787c0SBrooks Davis  */
110d7d787c0SBrooks Davis static void
sort_bench(int elts,enum sort s)111d7d787c0SBrooks Davis sort_bench(int elts, enum sort s)
112d7d787c0SBrooks Davis {
113d7d787c0SBrooks Davis 	size_t size = sizeof(int) * elts;
114d7d787c0SBrooks Davis 	int *array = malloc(size);
115d7d787c0SBrooks Davis 	for (int i = 0; i < elts; i++) {
116d7d787c0SBrooks Davis 		array[i] = i;
117d7d787c0SBrooks Davis 	}
118d7d787c0SBrooks Davis 	sort(array, elts, s);
119d7d787c0SBrooks Davis 	free(array);
120d7d787c0SBrooks Davis }
121d7d787c0SBrooks Davis 
122d7d787c0SBrooks Davis /*
123d7d787c0SBrooks Davis  * Sort an array of partially increasing, partially random integers
124d7d787c0SBrooks Davis  */
125d7d787c0SBrooks Davis static void
partial_bench(int elts,enum sort s)126d7d787c0SBrooks Davis partial_bench(int elts, enum sort s)
127d7d787c0SBrooks Davis {
128d7d787c0SBrooks Davis 	size_t size = sizeof(int) * elts;
129d7d787c0SBrooks Davis 	int *array = malloc(size);
130d7d787c0SBrooks Davis 	for (int i = 0; i < elts; i++) {
131d7d787c0SBrooks Davis 		if (i <= elts / 2)
132d7d787c0SBrooks Davis 			array[i] = i;
133d7d787c0SBrooks Davis 		else
134d7d787c0SBrooks Davis 			array[i] = arc4random();
135d7d787c0SBrooks Davis 	}
136d7d787c0SBrooks Davis 	sort(array, elts, s);
137d7d787c0SBrooks Davis 	free(array);
138d7d787c0SBrooks Davis }
139d7d787c0SBrooks Davis 
140d7d787c0SBrooks Davis /*
141d7d787c0SBrooks Davis  * Sort an array of decreasing integers
142d7d787c0SBrooks Davis  */
143d7d787c0SBrooks Davis static void
reverse_bench(int elts,enum sort s)144d7d787c0SBrooks Davis reverse_bench(int elts, enum sort s)
145d7d787c0SBrooks Davis {
146d7d787c0SBrooks Davis 	size_t size = sizeof(int) * elts;
147d7d787c0SBrooks Davis 	int *array = malloc(size);
148d7d787c0SBrooks Davis 	for (int i = 0; i < elts; i++) {
149d7d787c0SBrooks Davis 		array[i] = elts - i;
150d7d787c0SBrooks Davis 	}
151d7d787c0SBrooks Davis 	sort(array, elts, s);
152d7d787c0SBrooks Davis 	free(array);
153d7d787c0SBrooks Davis }
154d7d787c0SBrooks Davis 
155d7d787c0SBrooks Davis static void
run_bench(enum sort s,enum test t,int runs,int elts)156d7d787c0SBrooks Davis run_bench(enum sort s, enum test t, int runs, int elts)
157d7d787c0SBrooks Davis {
158d7d787c0SBrooks Davis 	for (int i = 0; i < runs; i++) {
159d7d787c0SBrooks Davis 		switch (t) {
160d7d787c0SBrooks Davis 		case RAND:
161d7d787c0SBrooks Davis 			rand_bench(elts, s);
162d7d787c0SBrooks Davis 			break;
163d7d787c0SBrooks Davis 		case SORT:
164d7d787c0SBrooks Davis 			sort_bench(elts, s);
165d7d787c0SBrooks Davis 			break;
166d7d787c0SBrooks Davis 		case PART:
167d7d787c0SBrooks Davis 			partial_bench(elts, s);
168d7d787c0SBrooks Davis 			break;
169d7d787c0SBrooks Davis 		case REV:
170d7d787c0SBrooks Davis 			reverse_bench(elts, s);
171d7d787c0SBrooks Davis 			break;
172d7d787c0SBrooks Davis 		// Should never be reached
173d7d787c0SBrooks Davis 		case INVALID_TEST:
174d7d787c0SBrooks Davis 			exit(EX_DATAERR);
175d7d787c0SBrooks Davis 		}
176d7d787c0SBrooks Davis 	}
177d7d787c0SBrooks Davis }
178d7d787c0SBrooks Davis 
179d7d787c0SBrooks Davis static enum sort
parse_alg(char * alg)180d7d787c0SBrooks Davis parse_alg(char *alg)
181d7d787c0SBrooks Davis {
182d7d787c0SBrooks Davis 	if (strcmp(alg, "merge") == 0)
183d7d787c0SBrooks Davis 		return MERGE;
184d7d787c0SBrooks Davis #ifdef WIKI
185d7d787c0SBrooks Davis 	else if (strcmp(alg, "wiki") == 0)
186d7d787c0SBrooks Davis 		return WIKI;
187d7d787c0SBrooks Davis #endif
188d7d787c0SBrooks Davis 	else if (strcmp(alg, "quick") == 0)
189d7d787c0SBrooks Davis 		return QUICK;
190d7d787c0SBrooks Davis 	else if (strcmp(alg, "heap") == 0)
191d7d787c0SBrooks Davis 		return HEAP;
192d7d787c0SBrooks Davis 	else
193d7d787c0SBrooks Davis 		return INVALID_ALG;
194d7d787c0SBrooks Davis }
195d7d787c0SBrooks Davis 
196d7d787c0SBrooks Davis static enum test
parse_test(char * test)197d7d787c0SBrooks Davis parse_test(char *test)
198d7d787c0SBrooks Davis {
199d7d787c0SBrooks Davis 	if (strcmp(test, "rand") == 0)
200d7d787c0SBrooks Davis 		return RAND;
201d7d787c0SBrooks Davis 	else if (strcmp(test, "sort") == 0)
202d7d787c0SBrooks Davis 		return SORT;
203d7d787c0SBrooks Davis 	else if (strcmp(test, "part") == 0)
204d7d787c0SBrooks Davis 		return PART;
205d7d787c0SBrooks Davis 	else if (strcmp(test, "rev") == 0)
206d7d787c0SBrooks Davis 		return REV;
207d7d787c0SBrooks Davis 	else
208d7d787c0SBrooks Davis 		return INVALID_TEST;
209d7d787c0SBrooks Davis }
210d7d787c0SBrooks Davis 
211d7d787c0SBrooks Davis static void
usage(const char * progname)212d7d787c0SBrooks Davis usage(const char *progname)
213d7d787c0SBrooks Davis {
214d7d787c0SBrooks Davis 	printf("Usage:\n");
215d7d787c0SBrooks Davis 	printf("\t%s: [alg] [test] [runs] [elt_power]\n", progname);
216d7d787c0SBrooks Davis 	printf("\n");
217d7d787c0SBrooks Davis 	printf("Valid algs:\n");
218d7d787c0SBrooks Davis #ifdef WIKI
219d7d787c0SBrooks Davis 	printf("\theap merge quick wiki\n");
220d7d787c0SBrooks Davis #else
221d7d787c0SBrooks Davis 	printf("\theap merge quick\n");
222d7d787c0SBrooks Davis #endif
223d7d787c0SBrooks Davis 	printf("Valid tests:\n");
224d7d787c0SBrooks Davis 	printf("\trand sort part rev\n");
225d7d787c0SBrooks Davis 	printf("\trand: Random element array \n");
226d7d787c0SBrooks Davis 	printf("\tsort: Increasing order array \n");
227d7d787c0SBrooks Davis 	printf("\tpart: Partially ordered array\n");
228d7d787c0SBrooks Davis 	printf("\trev: Decreasing order array\n");
229d7d787c0SBrooks Davis 	printf("Run the algorithm [runs] times with 2^[elt_power] elements\n");
230d7d787c0SBrooks Davis 	exit(EX_USAGE);
231d7d787c0SBrooks Davis }
232d7d787c0SBrooks Davis 
233d7d787c0SBrooks Davis /*
234d7d787c0SBrooks Davis  * Runs a sorting algorithm with a provided data configuration according to
235d7d787c0SBrooks Davis  * command line arguments
236d7d787c0SBrooks Davis  */
237d7d787c0SBrooks Davis int
main(int argc,char * argv[])238d7d787c0SBrooks Davis main(int argc, char *argv[])
239d7d787c0SBrooks Davis {
240d7d787c0SBrooks Davis 	const char *progname = argv[0];
241d7d787c0SBrooks Davis 	int runs, elts;
242d7d787c0SBrooks Davis 	if (argc != NARGS)
243d7d787c0SBrooks Davis 		usage(progname);
244d7d787c0SBrooks Davis 
245d7d787c0SBrooks Davis 	enum sort s = parse_alg(argv[1]);
246d7d787c0SBrooks Davis 	if (s == INVALID_ALG)
247d7d787c0SBrooks Davis 		usage(progname);
248d7d787c0SBrooks Davis 
249d7d787c0SBrooks Davis 	enum test t = parse_test(argv[2]);
250d7d787c0SBrooks Davis 	if (t == INVALID_TEST)
251d7d787c0SBrooks Davis 		usage(progname);
252d7d787c0SBrooks Davis 
253d7d787c0SBrooks Davis 	runs = atoi(argv[3]);
254d7d787c0SBrooks Davis 	elts = pow(2, atoi(argv[4]));
255d7d787c0SBrooks Davis 
256d7d787c0SBrooks Davis 	run_bench(s, t, runs, elts);
257d7d787c0SBrooks Davis }
258