/* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */ /* fsort- a smarter quicksort /Hubbe */ /* Optimized for minimum amount of compares */ #include "global.h" #include "pike_error.h" #include "fsort.h" #include "pike_embed.h" #include "pike_macros.h" #define CMP(X,Y) ( (*cmpfun)((void *)(X),(void *)(Y)) ) #define EXTRA_ARGS ,fsortfun cmpfun #define XARGS ,cmpfun #define ID fsort_1 #define TYPE B1_T #include "fsort_template.h" #undef ID #undef TYPE #ifdef B2_T #define ID fsort_2 #define TYPE B2_T #include "fsort_template.h" #undef ID #undef TYPE #endif #ifdef B4_T #define ID fsort_4 #define TYPE B4_T #include "fsort_template.h" #undef ID #undef TYPE #endif #ifdef B8_T #define ID fsort_8 #define TYPE B8_T #include "fsort_template.h" #undef ID #undef TYPE #endif #ifdef B16_T #define ID fsort_16 #define TYPE B16_T #include "fsort_template.h" #undef ID #undef TYPE #endif #undef EXTRA_ARGS #undef XARGS #define EXTRA_ARGS , fsortfun cmpfun, char *tmp_area, long size #define XARGS , cmpfun, tmp_area, size #define SWAP(X,Y) do { \ memcpy(tmp_area,X,size); \ memcpy(X,Y,size); \ memcpy(Y,tmp_area,size); \ } while(0) #define STEP(X,Y) ((X)+(Y)*size) #define TYPE char #define ID fsort_n #define TMP_AREA #include "fsort_template.h" #undef ID #undef TYPE #undef EXTRA_ARGS #undef XARGS PMOD_EXPORT void fsort(void *base, long elms, long elmSize, fsortfun cmpfunc) { if(elms<=0) return; #ifdef HANDLES_UNALIGNED_MEMORY_ACCESS switch(elmSize) #else switch( (((size_t)base) % elmSize) ? 0 : elmSize ) #endif { case 1: fsort_1(( B1_T *)base,(elms-1)+( B1_T *)base, cmpfunc); break; #ifdef B2_T case 2: fsort_2(( B2_T *)base,(elms-1)+( B2_T *)base, cmpfunc); break; #endif #ifdef B4_T case 4: fsort_4(( B4_T *)base,(elms-1)+( B4_T *)base, cmpfunc); break; #endif #ifdef B8_T case 8: fsort_8(( B8_T *)base,(elms-1)+( B8_T *)base, cmpfunc); break; #endif #ifdef B16_T case 16: fsort_16((B16_T *)base,(elms-1)+(B16_T *)base, cmpfunc); break; #endif default: { /* NOTE: We need to put the alloca'd value in a variable, * otherwise cc/HPUX will generate broken code. * Hmm, that didn't work, but reordering the arguments, * putting size last seems to have fixed the problem... * /grubba hunting compiler bugs 2002-09-03 */ char *buf = alloca(elmSize); fsort_n((char *)base,((char *)base) + elmSize * (elms - 1), cmpfunc, buf, elmSize); } } }