00001
00002 #ifndef __APPLE__
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #if defined(LIBC_SCCS) && !defined(lint)
00040 static char sccsid[] = "@(#)merge.c 8.2 (Berkeley) 2/14/94";
00041 #endif
00042
00043
00044
00045
00046
00047
00048
00049
00050 #define NATURAL
00051 #define THRESHOLD 16
00052
00053
00054
00055
00056
00057 #include "system.h"
00058
00059 #define ISIZE sizeof(int)
00060 #define PSIZE sizeof(unsigned char *)
00061 #define ICOPY_LIST(src, dst, last) \
00062 do \
00063 *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
00064 while(src < last)
00065 #define ICOPY_ELT(src, dst, i) \
00066 do \
00067 *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
00068 while (i -= ISIZE)
00069
00070 #define CCOPY_LIST(src, dst, last) \
00071 do \
00072 *dst++ = *src++; \
00073 while (src < last)
00074 #define CCOPY_ELT(src, dst, i) \
00075 do \
00076 *dst++ = *src++; \
00077 while (i -= 1)
00078
00079
00080
00081
00082
00083
00084
00085 #define EVAL(p) (unsigned char **) \
00086 ((unsigned char *)0 + \
00087 (((unsigned char *)p + PSIZE - 1 - (unsigned char *) 0) & ~(PSIZE - 1)))
00088
00089 #define swap(a, b) { \
00090 s = b; \
00091 i = size; \
00092 do { \
00093 tmp = *a; *a++ = *s; *s++ = tmp; \
00094 } while (--i); \
00095 a -= size; \
00096 }
00097 #define reverse(bot, top) { \
00098 s = top; \
00099 do { \
00100 i = size; \
00101 do { \
00102 tmp = *bot; *bot++ = *s; *s++ = tmp; \
00103 } while (--i); \
00104 s -= size2; \
00105 } while(bot < s); \
00106 }
00107
00108
00109
00110
00111
00112 static void
00113 insertionsort(unsigned char *a, size_t n, size_t size,
00114 int (*cmp) (const void *, const void *))
00115
00116 {
00117 u_char *ai, *s, *t, *u, tmp;
00118 int i;
00119
00120 for (ai = a+size; --n >= 1; ai += size)
00121 for (t = ai; t > a; t -= size) {
00122 u = t - size;
00123 if (cmp(u, t) <= 0)
00124 break;
00125 swap(u, t);
00126 }
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 static void
00136 setup(unsigned char *list1, unsigned char *list2,
00137 size_t n, size_t size, int (*cmp) (const void *, const void *))
00138
00139 {
00140 int i, length, size2, tmp, sense;
00141 unsigned char *f1, *f2, *s, *l2, *last, *p2;
00142
00143 size2 = size*2;
00144 if (n <= 5) {
00145 insertionsort(list1, n, size, cmp);
00146 *EVAL(list2) = (unsigned char*) list2 + n*size;
00147 return;
00148 }
00149
00150
00151
00152
00153 i = 4 + (n & 1);
00154 insertionsort(list1 + (n - i) * size, i, size, cmp);
00155 last = list1 + size * (n - i);
00156 *EVAL(list2 + (last - list1)) = list2 + n * size;
00157
00158 #ifdef NATURAL
00159 p2 = list2;
00160 f1 = list1;
00161 sense = (cmp(f1, f1 + size) > 0);
00162 for (; f1 < last; sense = !sense) {
00163 length = 2;
00164
00165 for (f2 = f1 + size2; f2 < last; f2 += size2) {
00166 if ((cmp(f2, f2+ size) > 0) != sense)
00167 break;
00168 length += 2;
00169 }
00170 if (length < THRESHOLD) {
00171 do {
00172 p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
00173 if (sense > 0)
00174 swap (f1, f1 + size);
00175 } while ((f1 += size2) < f2);
00176 } else {
00177 l2 = f2;
00178 for (f2 = f1 + size2; f2 < l2; f2 += size2) {
00179 if ((cmp(f2-size, f2) > 0) != sense) {
00180 p2 = *EVAL(p2) = f2 - list1 + list2;
00181 if (sense > 0)
00182 reverse(f1, f2-size);
00183 f1 = f2;
00184 }
00185 }
00186 if (sense > 0)
00187 reverse (f1, f2-size);
00188 f1 = f2;
00189 if (f2 < last || cmp(f2 - size, f2) > 0)
00190 p2 = *EVAL(p2) = f2 - list1 + list2;
00191 else
00192 p2 = *EVAL(p2) = list2 + n*size;
00193 }
00194 }
00195 #else
00196 for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
00197 p2 = *EVAL(p2) = p2 + size2;
00198 if (cmp (f1, f1 + size) > 0)
00199 swap(f1, f1 + size);
00200 }
00201 #endif
00202 }
00203
00204
00205
00206
00207 int
00208 mergesort(void *base, size_t nmemb, size_t size,
00209 int (*cmp) (const void *, const void *))
00210 {
00211 register int i, sense;
00212 int big, iflag;
00213 register unsigned char *f1, *f2, *t, *b, *q, *l1, *l2;
00214
00215 register unsigned char *tp2;
00216
00217 unsigned char *list2;
00218
00219 unsigned char *list1;
00220 unsigned char *p2, *p, *last, **p1;
00221
00222 if (size < PSIZE / 2) {
00223 errno = EINVAL;
00224 return (-1);
00225 }
00226
00227 if (nmemb == 0)
00228 return (0);
00229
00230
00231
00232
00233
00234 iflag = 0;
00235 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
00236 iflag = 1;
00237
00238 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
00239 return (-1);
00240
00241 list1 = base;
00242 setup(list1, list2, nmemb, size, cmp);
00243 last = list2 + nmemb * size;
00244 i = big = 0;
00245
00246 while (*EVAL(list2) != last) {
00247 l2 = list1;
00248 p1 = EVAL(list1);
00249 for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
00250 p2 = *EVAL(p2);
00251 f1 = l2;
00252 f2 = l1 = list1 + (p2 - list2);
00253 if (p2 != last)
00254 p2 = *EVAL(p2);
00255 l2 = list1 + (p2 - list2);
00256 while (f1 < l1 && f2 < l2) {
00257 if ((*cmp)(f1, f2) <= 0) {
00258 q = f2;
00259 b = f1, t = l1;
00260 sense = -1;
00261 } else {
00262 q = f1;
00263 b = f2, t = l2;
00264 sense = 0;
00265 }
00266 if (!big) {
00267 while ((b += size) < t && cmp(q, b) >sense)
00268 if (++i == 6) {
00269 big = 1;
00270 goto EXPONENTIAL;
00271 }
00272 } else {
00273
00274 EXPONENTIAL: for (i = size; ; i <<= 1)
00275 if ((p = (b + i)) >= t) {
00276 if ((p = t - size) > b &&
00277 (*cmp)(q, p) <= sense)
00278 t = p;
00279 else
00280 b = p;
00281 break;
00282 } else if ((*cmp)(q, p) <= sense) {
00283 t = p;
00284 if (i == size)
00285 big = 0;
00286 goto FASTCASE;
00287 } else
00288 b = p;
00289
00290 while (t > b+size) {
00291 i = (((t - b) / size) >> 1) * size;
00292 if ((*cmp)(q, p = b + i) <= sense)
00293 t = p;
00294 else
00295 b = p;
00296 }
00297 goto COPY;
00298 FASTCASE: while (i > size)
00299 if ((*cmp)(q,
00300 p = b + (i >>= 1)) <= sense)
00301 t = p;
00302 else
00303 b = p;
00304
00305
00306 COPY: b = t;
00307 }
00308 i = size;
00309 if (q == f1) {
00310 if (iflag) {
00311 ICOPY_LIST(f2, tp2, b);
00312 ICOPY_ELT(f1, tp2, i);
00313 } else {
00314 CCOPY_LIST(f2, tp2, b);
00315 CCOPY_ELT(f1, tp2, i);
00316 }
00317 } else {
00318 if (iflag) {
00319 ICOPY_LIST(f1, tp2, b);
00320 ICOPY_ELT(f2, tp2, i);
00321 } else {
00322 CCOPY_LIST(f1, tp2, b);
00323 CCOPY_ELT(f2, tp2, i);
00324 }
00325 }
00326 }
00327 if (f2 < l2) {
00328 if (iflag)
00329 ICOPY_LIST(f2, tp2, l2);
00330 else
00331 CCOPY_LIST(f2, tp2, l2);
00332 } else if (f1 < l1) {
00333 if (iflag)
00334 ICOPY_LIST(f1, tp2, l1);
00335 else
00336 CCOPY_LIST(f1, tp2, l1);
00337 }
00338 *p1 = l2;
00339 }
00340
00341 tp2 = list1;
00342 list1 = list2;
00343 list2 = tp2;
00344
00345 last = list2 + nmemb*size;
00346 }
00347
00348 if (base == list2) {
00349 memmove(list2, list1, nmemb*size);
00350 list2 = list1;
00351 }
00352
00353 free(list2);
00354
00355 return (0);
00356 }
00357 #else
00358
00359 #endif
00360