/* fsort- a smarter quicksort / Profezzorn */ /* Optimized for minimum amount of compares */ #include "global.h" #include "interpret.h" #include "object.h" #include "regexp.h" #include "exec.h" #include "simulate.h" static int (*cmpfun)(const void *, const void *); static void (*swapfun)(register void *, register void *); static long size; static char *tmp_area; #ifdef DEBUG static long elements; static void *first; static void ftest(void *a) { int e; e=(char *)a-(char *)first; if(a<first || (e % size) || (e/size)>=elements) fatal("Error in fsort.\n"); } #else #define ftest(X) #endif static void byteswap(register void *a,register void *b) { char foo; ftest(a); ftest(b); foo=*(char *)a; *(char *)a=*(char *)b; *(char *)b=foo; } static void shortswap(register void *a,register void *b) { short foo; ftest(a); ftest(b); foo=*(short *)a; *(short *)a=*(short *)b; *(short *)b=foo; } static void longswap(register void *a,register void *b) { long foo; ftest(a); ftest(b); foo=*(long *)a; *(long *)a=*(long *)b; *(long *)b=foo; } static void long2swap(register void *a,register void *b) { long foo; ftest(a); ftest(b); foo=((long *)a)[0]; ((long *)a)[0]=((long *)b)[0]; ((long *)b)[0]=foo; foo=((long *)a)[1]; ((long *)a)[1]=((long *)b)[1]; ((long *)b)[1]=foo; } static void fswap(register void *a,register void *b) { ftest(a); ftest(b); MEMCPY(tmp_area,a,size); MEMCPY(a,b,size); MEMCPY(b,tmp_area,size); } static void fsort2(register char *bas,register char *last) { register char *a,*b; register dum; ftest(bas); if(bas>=last) return; ftest(last); a=bas+size; if(a==last) { if((*cmpfun)(bas,last) > 0) swapfun(bas,last); return; } dum=(last-bas)>>1; dum-=dum % size; swapfun(bas,bas+dum); b=last; while(a<b) { while(a<=b && (*cmpfun)(a,bas) < 0) a+=size; while(a< b && (*cmpfun)(bas,b) < 0) b-=size; if(a<b) { swapfun(a,b); a+=size; if(b-a>size) b-=size; } } swapfun(bas,a-=size); fsort2(bas,a-=size); fsort2(b,last); } void fsort(base,elms,elmSize, cmpfunc) void *base; long elms; long elmSize; int (*cmpfunc)(const void *, const void *); { if(elms<=0) return; cmpfun=cmpfunc; size=elmSize; #ifdef DEBUG elements=elms; first=base; #endif switch(elmSize) { case sizeof(char): swapfun=byteswap; break; case sizeof(short): swapfun=shortswap; break; case sizeof(long): swapfun=longswap; break; case sizeof(long)*2: swapfun=long2swap; break; default: swapfun=fswap; tmp_area=(char *)alloca(elmSize); } fsort2((char *)base,((char *)base) + size * (elms - 1)); }