2 * UCW Library -- Optimized Array Sorter
4 * (c) 2003--2007 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
11 * This is a generator of routines for sorting arrays, very similar to the one
15 * FIXME: Note on thread-safety
17 * So much for advocacy, there are the parameters (those marked with [*]
20 * ASORT_PREFIX(x) [*] add a name prefix (used on all global names
21 * defined by the sorter)
22 * ASORT_KEY_TYPE [*] data type of a single array entry key
23 * ASORT_LT(x,y) x < y for ASORT_TYPE (default: "x<y")
24 * ASORT_THRESHOLD threshold for switching between quicksort and insertsort
25 * ASORT_PAGE_ALIGNED the array is guaranteed to be aligned to a multiple of CPU_PAGE_SIZE
27 * ASORT_SWAP FIXME: probably keep private
29 * After including this file, a function
30 * ASORT_KEY_TYPE *ASORT_PREFIX(sort)(ASORT_KEY_TYPE *array, uns num_elts, ASORT_KEY_TYPE *buf, uns hash_bits)
31 * is declared and all parameter macros are automatically undef'd.
34 #include "lib/sorter/common.h"
36 #define Q(x) ASORT_PREFIX(x)
38 typedef ASORT_KEY_TYPE Q(key);
41 #define ASORT_LT(x,y) ((x) < (y))
45 #define ASORT_SWAP(i,j) do { Q(key) tmp = array[i]; array[i]=array[j]; array[j]=tmp; } while (0)
48 #ifndef ASORT_THRESHOLD
49 #define ASORT_THRESHOLD 8 /* Guesswork and experimentation */
52 static void Q(raw_sort)(Q(key) *array, uns array_size)
54 struct stk { int l, r; } stack[8*sizeof(uns)];
55 int l, r, left, right, m;
62 /* QuickSort with optimizations a'la Sedgewick, but stop at ASORT_THRESHOLD */
65 right = array_size - 1;
71 if (ASORT_LT(array[m], array[l]))
73 if (ASORT_LT(array[r], array[m]))
76 if (ASORT_LT(array[m], array[l]))
82 while (ASORT_LT(array[l], pivot))
84 while (ASORT_LT(pivot, array[r]))
99 if ((r - left) >= ASORT_THRESHOLD && (right - l) >= ASORT_THRESHOLD)
101 /* Both partitions ok => push the larger one */
102 if ((r - left) > (right - l))
116 else if ((r - left) >= ASORT_THRESHOLD)
118 /* Left partition OK, right undersize */
121 else if ((right - l) >= ASORT_THRESHOLD)
123 /* Right partition OK, left undersize */
128 /* Both partitions undersize => pop */
138 * We have a partially sorted array, finish by insertsort. Inspired
139 * by qsort() in GNU libc.
142 /* Find minimal element which will serve as a barrier */
143 r = MIN(array_size, ASORT_THRESHOLD);
146 if (ASORT_LT(array[l], array[m]))
151 for (m=1; m<(int)array_size; m++)
154 while (ASORT_LT(array[m], array[l-1]))
164 static Q(key) *Q(sort)(Q(key) *array, uns num_elts, Q(key) *buffer, uns hash_bits)
168 Q(raw_sort)(array, num_elts);
174 #undef ASORT_KEY_TYPE
177 #undef ASORT_THRESHOLD
178 #undef ASORT_PAGE_ALIGNED