]>
git.saurik.com Git - apple/libc.git/blob - tests/qsort_perf.c
2 * Randomized test for qsort() routine.
4 * Includes code derived from stdlib/FreeBSD/qsort.c and the copyright header
5 * in that file applies.
13 #include <darwintest.h>
14 #include <darwintest_utils.h>
16 static void qsort1(void *aa
, size_t n
, size_t es
,
17 int (*cmp
)(const void *, const void *));
20 cmp_int(const void *aa
, const void *bb
)
31 T_DECL(qsort_perf
, "qsort perf test", T_META_CHECK_LEAKS(NO
))
36 uint64_t time_elapsed
;
41 for (i
= 0; i
< k
; i
++) {
44 for (i
= k
; i
< nelm
; i
++) {
48 bcopy(save
, arr
, sizeof(arr
));
49 dt_timer_start("25-75 (qsort)");
50 qsort(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
51 time_elapsed
= dt_timer_stop("25-75 (qsort)");
52 T_LOG("25-75 (qsort): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
53 for (i
= 1; i
< nelm
; i
++) {
54 if(arr
[i
- 1] > arr
[i
]) {
55 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
60 bcopy(save
, arr
, sizeof(arr
));
61 dt_timer_start("25-75 (Bentley)");
62 qsort1(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
63 time_elapsed
= dt_timer_stop("25-75 (Bentley)");
64 T_LOG("25-75 (Bentley): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
65 for (i
= 1; i
< nelm
; i
++) {
66 if(arr
[i
- 1] > arr
[i
]) {
67 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
74 for (i
= 0; i
< k
; i
++) {
77 for (i
= k
; i
< nelm
; i
++) {
81 bcopy(save
, arr
, sizeof(arr
));
82 dt_timer_start("50-50 (qsort)");
83 qsort(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
84 time_elapsed
= dt_timer_stop("50-50 (qsort)");
85 T_LOG("50-50 (qsort): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
86 for (i
= 1; i
< nelm
; i
++) {
87 if(arr
[i
- 1] > arr
[i
]) {
88 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
93 bcopy(save
, arr
, sizeof(arr
));
94 dt_timer_start("50-50 (Bentley)");
95 qsort1(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
96 time_elapsed
= dt_timer_stop("50-50 (Bentley)");
97 T_LOG("50-50 (Bentley): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
98 for (i
= 1; i
< nelm
; i
++) {
99 if(arr
[i
- 1] > arr
[i
]) {
100 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
105 // ----- median-of-3 killer -----
108 for (i
= 1; i
<= k
; i
++) {
113 save
[k
+ i
- 1] = 2 * i
;
116 bcopy(save
, arr
, sizeof(arr
));
117 dt_timer_start("median-of-3 killer (qsort)");
118 qsort(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
119 time_elapsed
= dt_timer_stop("median-of-3 killer (qsort)");
120 T_LOG("median-of-3 (qsort): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
121 for (i
= 1; i
< nelm
; i
++) {
122 if(arr
[i
- 1] > arr
[i
]) {
123 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
127 bcopy(save
, arr
, sizeof(arr
));
128 dt_timer_start("median-of-3 killer (Bentley)");
129 qsort1(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
130 time_elapsed
= dt_timer_stop("median-of-3 killer (Bentley)");
131 T_LOG("median-of-3 (Bentley): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
132 for (i
= 1; i
< nelm
; i
++) {
133 if(arr
[i
- 1] > arr
[i
]) {
134 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
138 // ----- random -----
140 for (i
= 0; i
< nelm
; i
++) {
144 bcopy(save
, arr
, sizeof(arr
));
145 dt_timer_start("random (qsort)");
146 qsort(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
147 time_elapsed
= dt_timer_stop("random (qsort)");
148 T_LOG("random (qsort): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
149 for (i
= 1; i
< nelm
; i
++) {
150 if(arr
[i
- 1] > arr
[i
]) {
151 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
156 bcopy(save
, arr
, sizeof(arr
));
157 dt_timer_start("random (Bentley)");
158 qsort1(arr
, nelm
, sizeof(arr
[0]), cmp_int
);
159 time_elapsed
= dt_timer_stop("random (Bentley)");
160 T_LOG("random (Bentley): %lld ms", time_elapsed
/ NSEC_PER_MSEC
);
161 for (i
= 1; i
< nelm
; i
++) {
162 if(arr
[i
- 1] > arr
[i
]) {
163 T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i
- 1, arr
[i
- 1], i
, arr
[i
]);
167 T_PASS("All tests completed successfully.");
170 /* qsort1 -- qsort interface implemented by faster quicksort */
172 #define SWAPINIT(a, es) swaptype = \
173 (a - (char*) 0) % sizeof(long) || es % sizeof(long) ? 2 : \
174 es == sizeof(long) ? 0 : 1;
175 #define swapcode(TYPE, parmi, parmj, n) { \
176 long i = (n) / sizeof(TYPE); \
177 register TYPE *pi = (TYPE *) (parmi); \
178 register TYPE *pj = (TYPE *) (parmj); \
180 register TYPE t = *pi; \
185 static void swapfunc(char *a
, char *b
, int n
, int swaptype
)
186 { if (swaptype
<= 1) swapcode(long, a
, b
, n
)
187 else swapcode(char, a
, b
, n
)
190 if (swaptype == 0) { \
191 long t = * (long *) (a); \
192 * (long *) (a) = * (long *) (b); \
193 * (long *) (b) = t; \
195 swapfunc(a, b, es, swaptype)
196 #define vecswap(a, b, n) if (n > 0) swapfunc(a, b, n, swaptype)
198 #define min(x, y) ((x)<=(y) ? (x) : (y))
200 static char *med3(char *a
, char *b
, char *c
, int (*cmp
)(const void *, const void *))
202 return cmp(a
, b
) < 0 ?
203 (cmp(b
, c
) < 0 ? b
: (cmp(a
, c
) < 0 ? c
: a
) )
204 : (cmp(b
, c
) > 0 ? b
: (cmp(a
, c
) < 0 ? a
: c
) );
208 qsort1(void *aa
, size_t n
, size_t es
,
209 int (*cmp
)(const void *, const void *))
211 char *pa
, *pb
, *pc
, *pd
, *pl
, *pm
, *pn
;
216 if (n
< 7) { /* Insertion sort on small arrays */
217 for (pm
= a
+ es
; pm
< a
+ n
*es
; pm
+= es
)
218 for (pl
= pm
; pl
> a
&& cmp(pl
-es
, pl
) > 0; pl
-= es
)
226 if (n
> 40) { /* On big arrays, pseudomedian of 9 */
228 pl
= med3(pl
, pl
+d
, pl
+2*d
, cmp
);
229 pm
= med3(pm
-d
, pm
, pm
+d
, cmp
);
230 pn
= med3(pn
-2*d
, pn
-d
, pn
, cmp
);
232 pm
= med3(pl
, pm
, pn
, cmp
); /* On mid arrays, med of 3 */
234 swap(a
, pm
); /* On tiny arrays, partition around middle */
236 pc
= pd
= a
+ (n
-1)*es
;
238 while (pb
<= pc
&& (r
= cmp(pb
, a
)) <= 0) {
239 if (r
== 0) { swap(pa
, pb
); pa
+= es
; }
242 while (pb
<= pc
&& (r
= cmp(pc
, a
)) >= 0) {
243 if (r
== 0) { swap(pc
, pd
); pd
-= es
; }
252 r
= min(pa
-a
, pb
-pa
); vecswap(a
, pb
-r
, r
);
253 r
= min(pd
-pc
, pn
-pd
-es
); vecswap(pb
, pn
-r
, r
);
254 if ((r
= pb
-pa
) > es
) qsort1(a
, r
/es
, es
, cmp
);
255 if ((r
= pd
-pc
) > es
) qsort1(pn
-r
, r
/es
, es
, cmp
);