00001
00002
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
00040
00041
00042
00043
00044
00045
00046 #include "c.h"
00047
00048
00049 static char *med3(char *a, char *b, char *c,
00050 qsort_arg_comparator cmp, void *arg);
00051 static void swapfunc(char *, char *, size_t, int);
00052
00053
00054
00055
00056
00057
00058
00059
00060 #define swapcode(TYPE, parmi, parmj, n) \
00061 do { \
00062 size_t i = (n) / sizeof (TYPE); \
00063 TYPE *pi = (TYPE *)(void *)(parmi); \
00064 TYPE *pj = (TYPE *)(void *)(parmj); \
00065 do { \
00066 TYPE t = *pi; \
00067 *pi++ = *pj; \
00068 *pj++ = t; \
00069 } while (--i > 0); \
00070 } while (0)
00071
00072 #define SWAPINIT(a, es) swaptype = ((char *)(a) - (char *)0) % sizeof(long) || \
00073 (es) % sizeof(long) ? 2 : (es) == sizeof(long)? 0 : 1;
00074
00075 static void
00076 swapfunc(char *a, char *b, size_t n, int swaptype)
00077 {
00078 if (swaptype <= 1)
00079 swapcode(long, a, b, n);
00080 else
00081 swapcode(char, a, b, n);
00082 }
00083
00084 #define swap(a, b) \
00085 if (swaptype == 0) { \
00086 long t = *(long *)(void *)(a); \
00087 *(long *)(void *)(a) = *(long *)(void *)(b); \
00088 *(long *)(void *)(b) = t; \
00089 } else \
00090 swapfunc(a, b, es, swaptype)
00091
00092 #define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n), swaptype)
00093
00094 static char *
00095 med3(char *a, char *b, char *c, qsort_arg_comparator cmp, void *arg)
00096 {
00097 return cmp(a, b, arg) < 0 ?
00098 (cmp(b, c, arg) < 0 ? b : (cmp(a, c, arg) < 0 ? c : a))
00099 : (cmp(b, c, arg) > 0 ? b : (cmp(a, c, arg) < 0 ? a : c));
00100 }
00101
00102 void
00103 qsort_arg(void *a, size_t n, size_t es, qsort_arg_comparator cmp, void *arg)
00104 {
00105 char *pa,
00106 *pb,
00107 *pc,
00108 *pd,
00109 *pl,
00110 *pm,
00111 *pn;
00112 int d,
00113 r,
00114 swaptype,
00115 presorted;
00116
00117 loop:SWAPINIT(a, es);
00118 if (n < 7)
00119 {
00120 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
00121 for (pl = pm; pl > (char *) a && cmp(pl - es, pl, arg) > 0;
00122 pl -= es)
00123 swap(pl, pl - es);
00124 return;
00125 }
00126 presorted = 1;
00127 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
00128 {
00129 if (cmp(pm - es, pm, arg) > 0)
00130 {
00131 presorted = 0;
00132 break;
00133 }
00134 }
00135 if (presorted)
00136 return;
00137 pm = (char *) a + (n / 2) * es;
00138 if (n > 7)
00139 {
00140 pl = (char *) a;
00141 pn = (char *) a + (n - 1) * es;
00142 if (n > 40)
00143 {
00144 d = (n / 8) * es;
00145 pl = med3(pl, pl + d, pl + 2 * d, cmp, arg);
00146 pm = med3(pm - d, pm, pm + d, cmp, arg);
00147 pn = med3(pn - 2 * d, pn - d, pn, cmp, arg);
00148 }
00149 pm = med3(pl, pm, pn, cmp, arg);
00150 }
00151 swap(a, pm);
00152 pa = pb = (char *) a + es;
00153 pc = pd = (char *) a + (n - 1) * es;
00154 for (;;)
00155 {
00156 while (pb <= pc && (r = cmp(pb, a, arg)) <= 0)
00157 {
00158 if (r == 0)
00159 {
00160 swap(pa, pb);
00161 pa += es;
00162 }
00163 pb += es;
00164 }
00165 while (pb <= pc && (r = cmp(pc, a, arg)) >= 0)
00166 {
00167 if (r == 0)
00168 {
00169 swap(pc, pd);
00170 pd -= es;
00171 }
00172 pc -= es;
00173 }
00174 if (pb > pc)
00175 break;
00176 swap(pb, pc);
00177 pb += es;
00178 pc -= es;
00179 }
00180 pn = (char *) a + n * es;
00181 r = Min(pa - (char *) a, pb - pa);
00182 vecswap(a, pb - r, r);
00183 r = Min(pd - pc, pn - pd - es);
00184 vecswap(pb, pn - r, r);
00185 if ((r = pb - pa) > es)
00186 qsort_arg(a, r / es, es, cmp, arg);
00187 if ((r = pd - pc) > es)
00188 {
00189
00190 a = pn - r;
00191 n = r / es;
00192 goto loop;
00193 }
00194
00195 }