00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include "config.h"
00026 #endif
00027
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #include "myqsort.h"
00032
00033
00034 #define SWAP(a, b, size) \
00035 do \
00036 { \
00037 register size_t __size = (size); \
00038 register char *__a = (a), *__b = (b); \
00039 do \
00040 { \
00041 char __tmp = *__a; \
00042 *__a++ = *__b; \
00043 *__b++ = __tmp; \
00044 } while (--__size > 0); \
00045 } while (0)
00046
00047
00048
00049 #define MAX_THRESH 4
00050
00051
00052 typedef struct
00053 {
00054 char *lo;
00055 char *hi;
00056 } stack_node;
00057
00058
00059 #define STACK_SIZE (8 * sizeof(unsigned long int))
00060 #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
00061 #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
00062 #define STACK_NOT_EMPTY (stack < top)
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 void
00089 myqsort(void *const pbase, size_t total_elems, size_t size, myqsort_cmp cmp, void *data)
00090 {
00091 register char *base_ptr = (char *) pbase;
00092
00093
00094
00095 char *pivot_buffer = (char *) malloc (size);
00096 const size_t max_thresh = MAX_THRESH * size;
00097
00098 if (total_elems == 0) {
00099
00100 free(pivot_buffer);
00101 return;
00102 }
00103
00104 if (total_elems > MAX_THRESH)
00105 {
00106 char *lo = base_ptr;
00107 char *hi = &lo[size * (total_elems - 1)];
00108
00109 stack_node stack[STACK_SIZE];
00110 stack_node *top = stack + 1;
00111
00112 while (STACK_NOT_EMPTY)
00113 {
00114 char *left_ptr;
00115 char *right_ptr;
00116
00117 char *pivot = pivot_buffer;
00118
00119
00120
00121
00122
00123
00124 char *mid = lo + size * ((hi - lo) / size >> 1);
00125
00126 if ((*cmp) (data, (void *) mid, (void *) lo) < 0)
00127 SWAP (mid, lo, size);
00128 if ((*cmp) (data, (void *) hi, (void *) mid) < 0)
00129 SWAP (mid, hi, size);
00130 else
00131 goto jump_over;
00132 if ((*cmp) (data, (void *) mid, (void *) lo) < 0)
00133 SWAP (mid, lo, size);
00134 jump_over:;
00135 memcpy (pivot, mid, size);
00136 pivot = pivot_buffer;
00137
00138 left_ptr = lo + size;
00139 right_ptr = hi - size;
00140
00141
00142
00143
00144 do
00145 {
00146 while ((*cmp) (data, (void *) left_ptr, (void *) pivot) < 0)
00147 left_ptr += size;
00148
00149 while ((*cmp) (data, (void *) pivot, (void *) right_ptr) < 0)
00150 right_ptr -= size;
00151
00152 if (left_ptr < right_ptr)
00153 {
00154 SWAP (left_ptr, right_ptr, size);
00155 left_ptr += size;
00156 right_ptr -= size;
00157 }
00158 else if (left_ptr == right_ptr)
00159 {
00160 left_ptr += size;
00161 right_ptr -= size;
00162 break;
00163 }
00164 }
00165 while (left_ptr <= right_ptr);
00166
00167
00168
00169
00170
00171
00172 if ((size_t) (right_ptr - lo) <= max_thresh)
00173 {
00174 if ((size_t) (hi - left_ptr) <= max_thresh)
00175
00176 POP (lo, hi);
00177 else
00178
00179 lo = left_ptr;
00180 }
00181 else if ((size_t) (hi - left_ptr) <= max_thresh)
00182
00183 hi = right_ptr;
00184 else if ((right_ptr - lo) > (hi - left_ptr))
00185 {
00186
00187 PUSH (lo, right_ptr);
00188 lo = left_ptr;
00189 }
00190 else
00191 {
00192
00193 PUSH (left_ptr, hi);
00194 hi = right_ptr;
00195 }
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 #define min(x, y) ((x) < (y) ? (x) : (y))
00206
00207 {
00208 char *const end_ptr = &base_ptr[size * (total_elems - 1)];
00209 char *tmp_ptr = base_ptr;
00210 char *thresh = min(end_ptr, base_ptr + max_thresh);
00211 register char *run_ptr;
00212
00213
00214
00215
00216
00217 for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
00218 if ((*cmp) (data, (void *) run_ptr, (void *) tmp_ptr) < 0)
00219 tmp_ptr = run_ptr;
00220
00221 if (tmp_ptr != base_ptr)
00222 SWAP (tmp_ptr, base_ptr, size);
00223
00224
00225
00226 run_ptr = base_ptr + size;
00227 while ((run_ptr += size) <= end_ptr)
00228 {
00229 tmp_ptr = run_ptr - size;
00230 while ((*cmp) (data, (void *) run_ptr, (void *) tmp_ptr) < 0)
00231 tmp_ptr -= size;
00232
00233 tmp_ptr += size;
00234 if (tmp_ptr != run_ptr)
00235 {
00236 char *trav;
00237
00238 trav = run_ptr + size;
00239 while (--trav >= run_ptr)
00240 {
00241 char c = *trav;
00242 char *hi, *lo;
00243
00244 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
00245 *hi = *lo;
00246 *hi = c;
00247 }
00248 }
00249 }
00250 }
00251
00252 free(pivot_buffer);
00253 }