00001
00032 #include "util.h"
00033
00034 #ifndef lint
00035 static char rcsid[] UNUSED = "$Id: qsort.c,v 1.5 2002/08/25 05:30:13 fabio Exp $";
00036 #endif
00037
00038 #define THRESH 4
00039 #define MTHRESH 6
00040
00041 static int (*qcmp)(const void *, const void *);
00042
00043 static int qsz;
00044 static int thresh;
00045 static int mthresh;
00046 static void qst ARGS((char *base, char *max));
00047
00048
00049
00050
00051
00052 #undef min
00053 #undef max
00054
00069 void
00070 qsort(
00071 void *vbase,
00072 size_t n,
00073 size_t size,
00074 int (*compar)(const void *, const void *))
00075 {
00076 register char c, *i, *j, *lo, *hi;
00077 char *min, *max, *base;
00078
00079 if (n <= 1)
00080 return;
00081 base = (char *) vbase;
00082 qsz = size;
00083 qcmp = compar;
00084 thresh = qsz * THRESH;
00085 mthresh = qsz * MTHRESH;
00086 max = base + n * qsz;
00087 if (n >= THRESH) {
00088 qst(base, max);
00089 hi = base + thresh;
00090 } else {
00091 hi = max;
00092 }
00093
00094
00095
00096
00097
00098
00099 for (j = lo = base; (lo += qsz) < hi; )
00100 if ((*qcmp)(j, lo) > 0)
00101 j = lo;
00102 if (j != base) {
00103
00104 for (i = base, hi = base + qsz; i < hi; ) {
00105 c = *j;
00106 *j++ = *i;
00107 *i++ = c;
00108 }
00109 }
00110
00111
00112
00113
00114
00115
00116
00117 for (min = base; (hi = min += qsz) < max; ) {
00118 while ((*qcmp)(hi -= qsz, min) > 0)
00119 ;
00120 if ((hi += qsz) != min) {
00121 for (lo = min + qsz; --lo >= min; ) {
00122 c = *lo;
00123 for (i = j = lo; (j -= qsz) >= hi; i = j)
00124 *i = *j;
00125 *i = c;
00126 }
00127 }
00128 }
00129 }
00130
00131
00132
00133
00134
00155 static void
00156 qst(char *base, char *max)
00157 {
00158 register char c, *i, *j, *jj;
00159 register int ii;
00160 char *mid, *tmp;
00161 int lo, hi;
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 lo = max - base;
00173 do {
00174 mid = i = base + qsz * ((lo / qsz) >> 1);
00175 if (lo >= mthresh) {
00176 j = ((*qcmp)((jj = base), i) > 0 ? jj : i);
00177 if ((*qcmp)(j, (tmp = max - qsz)) > 0) {
00178
00179 j = (j == jj ? i : jj);
00180 if ((*qcmp)(j, tmp) < 0)
00181 j = tmp;
00182 }
00183 if (j != i) {
00184 ii = qsz;
00185 do {
00186 c = *i;
00187 *i++ = *j;
00188 *j++ = c;
00189 } while (--ii);
00190 }
00191 }
00192
00193
00194
00195 for (i = base, j = max - qsz; ; ) {
00196 while (i < mid && (*qcmp)(i, mid) <= 0)
00197 i += qsz;
00198 while (j > mid) {
00199 if ((*qcmp)(mid, j) <= 0) {
00200 j -= qsz;
00201 continue;
00202 }
00203 tmp = i + qsz;
00204 if (i == mid) {
00205
00206 mid = jj = j;
00207 } else {
00208
00209 jj = j;
00210 j -= qsz;
00211 }
00212 goto swap;
00213 }
00214 if (i == mid) {
00215 break;
00216 } else {
00217
00218 jj = mid;
00219 tmp = mid = i;
00220 j -= qsz;
00221 }
00222 swap:
00223 ii = qsz;
00224 do {
00225 c = *i;
00226 *i++ = *jj;
00227 *jj++ = c;
00228 } while (--ii);
00229 i = tmp;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239 i = (j = mid) + qsz;
00240 if ((lo = j - base) <= (hi = max - i)) {
00241 if (lo >= thresh)
00242 qst(base, j);
00243 base = i;
00244 lo = hi;
00245 } else {
00246 if (hi >= thresh)
00247 qst(i, max);
00248 max = j;
00249 }
00250 } while (lo >= thresh);
00251 }