|
Odamex
Setting the Standard in Multiplayer Doom
|
00001 /* $Id: qsort.h,v 1.5 2008-01-28 18:16:49 mjt Exp $ 00002 * Adopted from GNU glibc by Mjt. 00003 * See stdlib/qsort.c in glibc */ 00004 00005 /* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc. 00006 This file is part of the GNU C Library. 00007 Written by Douglas C. Schmidt (schmidt@ics.uci.edu). 00008 00009 The GNU C Library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 The GNU C Library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with the GNU C Library; if not, write to the Free 00021 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 00022 02111-1307 USA. */ 00023 00024 /* in-line qsort implementation. Differs from traditional qsort() routine 00025 * in that it is a macro, not a function, and instead of passing an address 00026 * of a comparison routine to the function, it is possible to inline 00027 * comparison routine, thus speeding up sorting a lot. 00028 * 00029 * Usage: 00030 * #include "iqsort.h" 00031 * #define islt(a,b) (strcmp((*a),(*b))<0) 00032 * char *arr[]; 00033 * int n; 00034 * QSORT(char*, arr, n, islt); 00035 * 00036 * The "prototype" and 4 arguments are: 00037 * QSORT(TYPE,BASE,NELT,ISLT) 00038 * 1) type of each element, TYPE, 00039 * 2) address of the beginning of the array, of type TYPE*, 00040 * 3) number of elements in the array, and 00041 * 4) comparision routine. 00042 * Array pointer and number of elements are referenced only once. 00043 * This is similar to a call 00044 * qsort(BASE,NELT,sizeof(TYPE),ISLT) 00045 * with the difference in last parameter. 00046 * Note the islt macro/routine (it receives pointers to two elements): 00047 * the only condition of interest is whenever one element is less than 00048 * another, no other conditions (greather than, equal to etc) are tested. 00049 * So, for example, to define integer sort, use: 00050 * #define islt(a,b) ((*a)<(*b)) 00051 * QSORT(int, arr, n, islt) 00052 * 00053 * The macro could be used to implement a sorting function (see examples 00054 * below), or to implement the sorting algorithm inline. That is, either 00055 * create a sorting function and use it whenever you want to sort something, 00056 * or use QSORT() macro directly instead a call to such routine. Note that 00057 * the macro expands to quite some code (compiled size of int qsort on x86 00058 * is about 700..800 bytes). 00059 * 00060 * Using this macro directly it isn't possible to implement traditional 00061 * qsort() routine, because the macro assumes sizeof(element) == sizeof(TYPE), 00062 * while qsort() allows element size to be different. 00063 * 00064 * Several ready-to-use examples: 00065 * 00066 * Sorting array of integers: 00067 * void int_qsort(int *arr, unsigned n) { 00068 * #define int_lt(a,b) ((*a)<(*b)) 00069 * QSORT(int, arr, n, int_lt); 00070 * } 00071 * 00072 * Sorting array of string pointers: 00073 * void str_qsort(char *arr[], unsigned n) { 00074 * #define str_lt(a,b) (strcmp((*a),(*b)) < 0) 00075 * QSORT(char*, arr, n, str_lt); 00076 * } 00077 * 00078 * Sorting array of structures: 00079 * 00080 * struct elt { 00081 * int key; 00082 * ... 00083 * }; 00084 * void elt_qsort(struct elt *arr, unsigned n) { 00085 * #define elt_lt(a,b) ((a)->key < (b)->key) 00086 * QSORT(struct elt, arr, n, elt_lt); 00087 * } 00088 * 00089 * And so on. 00090 */ 00091 00092 /* Swap two items pointed to by A and B using temporary buffer t. */ 00093 #define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) 00094 00095 /* Discontinue quicksort algorithm when partition gets below this size. 00096 This particular magic number was chosen to work best on a Sun 4/260. */ 00097 #define _QSORT_MAX_THRESH 4 00098 00099 /* Stack node declarations used to store unfulfilled partition obligations 00100 * (inlined in QSORT). 00101 typedef struct { 00102 QSORT_TYPE *_lo, *_hi; 00103 } qsort_stack_node; 00104 */ 00105 00106 /* The next 4 #defines implement a very fast in-line stack abstraction. */ 00107 /* The stack needs log (total_elements) entries (we could even subtract 00108 log(MAX_THRESH)). Since total_elements has type unsigned, we get as 00109 upper bound for log (total_elements): 00110 bits per byte (CHAR_BIT) * sizeof(unsigned). */ 00111 #define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) 00112 #define _QSORT_PUSH(top, low, high) \ 00113 (((top->_lo = (low)), (top->_hi = (high)), ++top)) 00114 #define _QSORT_POP(low, high, top) \ 00115 ((--top, (low = top->_lo), (high = top->_hi))) 00116 #define _QSORT_STACK_NOT_EMPTY (_stack < _top) 00117 00118 00119 /* Order size using quicksort. This implementation incorporates 00120 four optimizations discussed in Sedgewick: 00121 00122 1. Non-recursive, using an explicit stack of pointer that store the 00123 next array partition to sort. To save time, this maximum amount 00124 of space required to store an array of SIZE_MAX is allocated on the 00125 stack. Assuming a 32-bit (64 bit) integer for size_t, this needs 00126 only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). 00127 Pretty cheap, actually. 00128 00129 2. Chose the pivot element using a median-of-three decision tree. 00130 This reduces the probability of selecting a bad pivot value and 00131 eliminates certain extraneous comparisons. 00132 00133 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving 00134 insertion sort to order the MAX_THRESH items within each partition. 00135 This is a big win, since insertion sort is faster for small, mostly 00136 sorted array segments. 00137 00138 4. The larger of the two sub-partitions is always pushed onto the 00139 stack first, with the algorithm then concentrating on the 00140 smaller partition. This *guarantees* no more than log (total_elems) 00141 stack size is needed (actually O(1) in this case)! */ 00142 00143 /* The main code starts here... */ 00144 #define QSORT(QSORT_TYPE,QSORT_BASE,QSORT_NELT,QSORT_LT) \ 00145 { \ 00146 QSORT_TYPE *const _base = (QSORT_BASE); \ 00147 const unsigned _elems = (QSORT_NELT); \ 00148 QSORT_TYPE _hold; \ 00149 \ 00150 /* Don't declare two variables of type QSORT_TYPE in a single \ 00151 * statement: eg `TYPE a, b;', in case if TYPE is a pointer, \ 00152 * expands to `type* a, b;' wich isn't what we want. \ 00153 */ \ 00154 \ 00155 if (_elems > _QSORT_MAX_THRESH) { \ 00156 QSORT_TYPE *_lo = _base; \ 00157 QSORT_TYPE *_hi = _lo + _elems - 1; \ 00158 struct { \ 00159 QSORT_TYPE *_hi; QSORT_TYPE *_lo; \ 00160 } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; \ 00161 \ 00162 while (_QSORT_STACK_NOT_EMPTY) { \ 00163 QSORT_TYPE *_left_ptr; QSORT_TYPE *_right_ptr; \ 00164 \ 00165 /* Select median value from among LO, MID, and HI. Rearrange \ 00166 LO and HI so the three values are sorted. This lowers the \ 00167 probability of picking a pathological pivot value and \ 00168 skips a comparison for both the LEFT_PTR and RIGHT_PTR in \ 00169 the while loops. */ \ 00170 \ 00171 QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); \ 00172 \ 00173 if (QSORT_LT (_mid, _lo)) \ 00174 _QSORT_SWAP (_mid, _lo, _hold); \ 00175 if (QSORT_LT (_hi, _mid)) { \ 00176 _QSORT_SWAP (_mid, _hi, _hold); \ 00177 if (QSORT_LT (_mid, _lo)) \ 00178 _QSORT_SWAP (_mid, _lo, _hold); \ 00179 } \ 00180 \ 00181 _left_ptr = _lo + 1; \ 00182 _right_ptr = _hi - 1; \ 00183 \ 00184 /* Here's the famous ``collapse the walls'' section of quicksort. \ 00185 Gotta like those tight inner loops! They are the main reason \ 00186 that this algorithm runs much faster than others. */ \ 00187 do { \ 00188 while (QSORT_LT (_left_ptr, _mid)) \ 00189 ++_left_ptr; \ 00190 \ 00191 while (QSORT_LT (_mid, _right_ptr)) \ 00192 --_right_ptr; \ 00193 \ 00194 if (_left_ptr < _right_ptr) { \ 00195 _QSORT_SWAP (_left_ptr, _right_ptr, _hold); \ 00196 if (_mid == _left_ptr) \ 00197 _mid = _right_ptr; \ 00198 else if (_mid == _right_ptr) \ 00199 _mid = _left_ptr; \ 00200 ++_left_ptr; \ 00201 --_right_ptr; \ 00202 } \ 00203 else if (_left_ptr == _right_ptr) { \ 00204 ++_left_ptr; \ 00205 --_right_ptr; \ 00206 break; \ 00207 } \ 00208 } while (_left_ptr <= _right_ptr); \ 00209 \ 00210 /* Set up pointers for next iteration. First determine whether \ 00211 left and right partitions are below the threshold size. If so, \ 00212 ignore one or both. Otherwise, push the larger partition's \ 00213 bounds on the stack and continue sorting the smaller one. */ \ 00214 \ 00215 if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { \ 00216 if (_hi - _left_ptr <= _QSORT_MAX_THRESH) \ 00217 /* Ignore both small partitions. */ \ 00218 _QSORT_POP (_lo, _hi, _top); \ 00219 else \ 00220 /* Ignore small left partition. */ \ 00221 _lo = _left_ptr; \ 00222 } \ 00223 else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) \ 00224 /* Ignore small right partition. */ \ 00225 _hi = _right_ptr; \ 00226 else if (_right_ptr - _lo > _hi - _left_ptr) { \ 00227 /* Push larger left partition indices. */ \ 00228 _QSORT_PUSH (_top, _lo, _right_ptr); \ 00229 _lo = _left_ptr; \ 00230 } \ 00231 else { \ 00232 /* Push larger right partition indices. */ \ 00233 _QSORT_PUSH (_top, _left_ptr, _hi); \ 00234 _hi = _right_ptr; \ 00235 } \ 00236 } \ 00237 } \ 00238 \ 00239 /* Once the BASE array is partially sorted by quicksort the rest \ 00240 is completely sorted using insertion sort, since this is efficient \ 00241 for partitions below MAX_THRESH size. BASE points to the \ 00242 beginning of the array to sort, and END_PTR points at the very \ 00243 last element in the array (*not* one beyond it!). */ \ 00244 \ 00245 { \ 00246 QSORT_TYPE *const _end_ptr = _base + _elems - 1; \ 00247 QSORT_TYPE *_tmp_ptr = _base; \ 00248 register QSORT_TYPE *_run_ptr; \ 00249 QSORT_TYPE *_thresh; \ 00250 \ 00251 _thresh = _base + _QSORT_MAX_THRESH; \ 00252 if (_thresh > _end_ptr) \ 00253 _thresh = _end_ptr; \ 00254 \ 00255 /* Find smallest element in first threshold and place it at the \ 00256 array's beginning. This is the smallest array element, \ 00257 and the operation speeds up insertion sort's inner loop. */ \ 00258 \ 00259 for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) \ 00260 if (QSORT_LT (_run_ptr, _tmp_ptr)) \ 00261 _tmp_ptr = _run_ptr; \ 00262 \ 00263 if (_tmp_ptr != _base) \ 00264 _QSORT_SWAP (_tmp_ptr, _base, _hold); \ 00265 \ 00266 /* Insertion sort, running from left-hand-side \ 00267 * up to right-hand-side. */ \ 00268 \ 00269 _run_ptr = _base + 1; \ 00270 while (++_run_ptr <= _end_ptr) { \ 00271 _tmp_ptr = _run_ptr - 1; \ 00272 while (QSORT_LT (_run_ptr, _tmp_ptr)) \ 00273 --_tmp_ptr; \ 00274 \ 00275 ++_tmp_ptr; \ 00276 if (_tmp_ptr != _run_ptr) { \ 00277 QSORT_TYPE *_trav = _run_ptr + 1; \ 00278 while (--_trav >= _run_ptr) { \ 00279 QSORT_TYPE *_hi; QSORT_TYPE *_lo; \ 00280 _hold = *_trav; \ 00281 \ 00282 for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) \ 00283 *_hi = *_lo; \ 00284 *_hi = _hold; \ 00285 } \ 00286 } \ 00287 } \ 00288 } \ 00289 \ 00290 }