Import OpenBSD sorting algorithms

OpenBSD's qsort() function is more secure than the ones used by
FreeBSD, NetBSD and MacOS. The best part is it goes faster too!
This change also imports the OpenBSD mergesort() and heapsort()
This commit is contained in:
Justine Tunney 2022-09-06 17:52:26 -07:00
parent dbf12c30b0
commit d861d2787b
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
11 changed files with 912 additions and 215 deletions

View file

@ -50,6 +50,42 @@ TEST(qsort, test) {
free(M);
}
BENCH(qsort, equivalence_random) {
size_t i;
size_t n = 1000;
long *a = gc(malloc(n * sizeof(long)));
long *b = gc(malloc(n * sizeof(long)));
long *c = gc(malloc(n * sizeof(long)));
for (i = 0; i < n; ++i) a[i] = lemur64();
memcpy(b, a, n * sizeof(long));
memcpy(c, a, n * sizeof(long));
qsort(b, n, sizeof(long), CompareLong);
heapsort(c, n, sizeof(long), CompareLong);
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
mergesort(c, n, sizeof(long), CompareLong);
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
smoothsort(c, n, sizeof(long), CompareLong);
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
}
BENCH(qsort, equivalence_reverse) {
size_t i;
size_t n = 1000;
long *a = gc(malloc(n * sizeof(long)));
long *b = gc(malloc(n * sizeof(long)));
long *c = gc(malloc(n * sizeof(long)));
for (i = 0; i < n; ++i) a[n - i - 1] = i;
memcpy(b, a, n * sizeof(long));
memcpy(c, a, n * sizeof(long));
qsort(b, n, sizeof(long), CompareLong);
heapsort(c, n, sizeof(long), CompareLong);
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
mergesort(c, n, sizeof(long), CompareLong);
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
smoothsort(c, n, sizeof(long), CompareLong);
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
}
BENCH(qsort, bench) {
size_t i;
size_t n = 1000;
@ -60,6 +96,10 @@ BENCH(qsort, bench) {
for (i = 0; i < n; ++i) p1[i] = i + ((lemur64() % 3) - 1);
EZBENCH2("qsort nearly", memcpy(p2, p1, n * sizeof(long)),
qsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("heapsort nearly", memcpy(p2, p1, n * sizeof(long)),
heapsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("mergesort nearly", memcpy(p2, p1, n * sizeof(long)),
mergesort(p2, n, sizeof(long), CompareLong));
EZBENCH2("smoothsort nearly", memcpy(p2, p1, n * sizeof(long)),
smoothsort(p2, n, sizeof(long), CompareLong));
@ -67,6 +107,10 @@ BENCH(qsort, bench) {
for (i = 0; i < n; ++i) p1[i] = n - i;
EZBENCH2("qsort reverse", memcpy(p2, p1, n * sizeof(long)),
qsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("heapsort reverse", memcpy(p2, p1, n * sizeof(long)),
heapsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("mergesort reverse", memcpy(p2, p1, n * sizeof(long)),
mergesort(p2, n, sizeof(long), CompareLong));
EZBENCH2("smoothsort reverse", memcpy(p2, p1, n * sizeof(long)),
smoothsort(p2, n, sizeof(long), CompareLong));
@ -74,6 +118,10 @@ BENCH(qsort, bench) {
rngset(p1, n * sizeof(long), 0, 0);
EZBENCH2("qsort random", memcpy(p2, p1, n * sizeof(long)),
qsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("heapsort random", memcpy(p2, p1, n * sizeof(long)),
heapsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("mergesort random", memcpy(p2, p1, n * sizeof(long)),
mergesort(p2, n, sizeof(long), CompareLong));
EZBENCH2("smoothsort random", memcpy(p2, p1, n * sizeof(long)),
smoothsort(p2, n, sizeof(long), CompareLong));
@ -84,6 +132,10 @@ BENCH(qsort, bench) {
}
EZBENCH2("qsort 2n", memcpy(p2, p1, n * sizeof(long)),
qsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("heapsort 2n", memcpy(p2, p1, n * sizeof(long)),
heapsort(p2, n, sizeof(long), CompareLong));
EZBENCH2("mergesort 2n", memcpy(p2, p1, n * sizeof(long)),
mergesort(p2, n, sizeof(long), CompareLong));
EZBENCH2("smoothsort 2n", memcpy(p2, p1, n * sizeof(long)),
smoothsort(p2, n, sizeof(long), CompareLong));
}