2 * sgen-qsort.c: Quicksort.
5 * Mark Probst <mark.probst@gmail.com>
7 * Copyright (C) 2013 Xamarin Inc
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License 2.0 as published by the Free Software Foundation;
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License 2.0 along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "metadata/sgen-gc.h"
29 #define ELEM(i) (((unsigned char*)base) + ((i) * width))
30 #define SWAP(i,j) do { \
31 size_t __i = (i), __j = (j); \
33 memcpy (swap_tmp, ELEM (__i), width); \
34 memcpy (ELEM (__i), ELEM (__j), width); \
35 memcpy (ELEM (__j), swap_tmp, width); \
40 partition (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*), unsigned char *pivot_tmp, unsigned char *swap_tmp)
42 size_t pivot_idx = nel >> 1;
45 memcpy (pivot_tmp, ELEM (pivot_idx), width);
46 SWAP (pivot_idx, nel - 1);
48 for (i = 0; i < nel - 1; ++i) {
49 if (compar (ELEM (i), pivot_tmp) <= 0) {
59 qsort_rec (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*), unsigned char *pivot_tmp, unsigned char *swap_tmp)
66 pivot_idx = partition (base, nel, width, compar, pivot_tmp, swap_tmp);
67 qsort_rec (base, pivot_idx, width, compar, pivot_tmp, swap_tmp);
69 qsort_rec (ELEM (pivot_idx + 1), nel - pivot_idx - 1, width, compar, pivot_tmp, swap_tmp);
73 sgen_qsort (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*))
75 unsigned char pivot_tmp [width];
76 unsigned char swap_tmp [width];
78 qsort_rec (base, nel, width, compar, pivot_tmp, swap_tmp);
81 #ifdef SGEN_QSORT_TEST
84 compare_ints (const void *pa, const void *pb)
86 int a = *(const int*)pa;
87 int b = *(const int*)pb;
101 compare_teststructs (const void *pa, const void *pb)
103 int a = ((const teststruct_t*)pa)->key;
104 int b = ((const teststruct_t*)pb)->key;
116 compare_sorts (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*))
118 size_t len = nel * width;
119 void *b1 = malloc (len);
120 void *b2 = malloc (len);
122 memcpy (b1, base, len);
123 memcpy (b2, base, len);
125 qsort (b1, nel, width, compar);
126 sgen_qsort (b2, nel, width, compar);
128 assert (!memcmp (b1, b2, len));
138 for (i = 0; i < 4000; ++i) {
142 for (j = 0; j < i; ++j)
144 compare_sorts (a, i, sizeof (int), compare_ints);
148 for (i = 0; i < 2000; ++i) {
149 teststruct_t a [200];
151 for (j = 0; j < 200; ++j) {
152 a [j].key = random ();
153 a [j].val = random ();
156 compare_sorts (a, 200, sizeof (teststruct_t), compare_teststructs);