void ssort2(char **a, int n, int depth,int* index) { int d, r, partval; int Diff=0; char **pa, **pb, **pc, **pd, **pl, **pm, **pn, *t; //~ if (n < 10) { //~ inssort(a, n, depth); //~ return; //~ } pl = a; pm = a + (n/2); pn = a + (n-1); if (n > 30) { // On big arrays, pseudomedian of 9 d = (n/8); pl = med3(pl, pl+d, pl+2*d); pm = med3(pm-d, pm, pm+d); pn = med3(pn-2*d, pn-d, pn); } pm = med3(pl, pm, pn); Diff=pm-a; int *IndexA,*IndexB,*IndexC,*IndexD,*IndexN; swap2(a, pm); swap2Index(index,index+Diff); partval = ptr2char(a); pa = pb = a + 1; pc = pd = a + n-1; IndexA=IndexB=index+1; IndexC=IndexD=index+n-1; for (;;) { while (pb <= pc && (r = ptr2char(pb)-partval) <= 0) { if (r == 0) { swap2(pa, pb);swap2Index(IndexA, IndexB);pa++;IndexA++; } pb++; IndexB++; } while (pb <= pc && (r = ptr2char(pc)-partval) >= 0) { if (r == 0) { swap2(pc, pd); swap2Index(IndexC, IndexD);pd--;IndexD-- ;} pc--; IndexC--; } if (pb > pc) break; swap2(pb, pc); swap2Index(IndexB,IndexC); pb++; IndexB++; pc--; IndexC--; } pn = a + n; IndexN=index+n; r = min(pa-a, pb-pa); vecswap2(a, pb-r, r); vecswap2Index(index,IndexB-r,r); r = min(pd-pc, pn-pd-1); vecswap2(pb, pn-r, r); vecswap2Index(IndexB,IndexN-r,r); if ((r = pb-pa) > 1) ssort2(a, r, depth,index); if (ptr2char(a + r) != 0) ssort2(a + r, pa-a + pn-pd-1, depth+1,index+r); if ((r = pd-pc) > 1) ssort2(a + n-r, r, depth,index+n-r); }
/* Subroutine for sort_split, algorithm by Bentley & McIlroy.*/ int choose_pivot(const int_iter &p, int64_t n) { int_iter pl, pm, pn; int64_t s; pm=p+(n>>1); /* small arrays, middle element.*/ if (n>7) { pl=p; pn=p+n-1; if (n>40) { /* big arrays, pseudomedian of 9.*/ s=n>>3; pl=med3(pl, pl+s, pl+s+s); pm=med3(pm-s, pm, pm+s); pn=med3(pn-s-s, pn-s, pn); }
void rqsort(int *a, int n, double *x) { int *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r; if (n < 7) { /* Insertion sort on small arrays */ for (pm = a + 1; pm < a + n; pm++) for (pl = pm; pl > a && cmp(pl-1, pl, x) > 0; pl--) swap(pl, pl-1); return; } pm = a + (n/2); if (n > 7) { pl = a; pn = a + (n-1); if (n > 40) { /* On big arrays, pseudomedian of 9 */ d = (n/8); pl = med3(pl, pl+d, pl+2*d, x); pm = med3(pm-d, pm, pm+d, x); pn = med3(pn-2*d, pn-d, pn, x); } pm = med3(pl, pm, pn, x); /* On mid arrays, med of 3 */ } swap(a, pm); /* On tiny arrays, partition around middle */ pa = pb = a + 1; pc = pd = a + (n-1); for (;;) { while (pb <= pc && (r = cmp(pb, a, x)) <= 0) { if (r == 0) { swap(pa, pb); pa++; } pb++; } while (pb <= pc && (r = cmp(pc, a, x)) >= 0) { if (r == 0) { swap(pc, pd); pd--; } pc--; } if (pb > pc) break; swap(pb, pc); pb++; pc--; } pn = a + n; r = minimum(pa-a, pb-pa); vecswap(a, pb-r, r); r = minimum(pd-pc, pn-pd-1); vecswap(pb, pn-r, r); if ((r = pb-pa) > 1) rqsort(a, r, x); if ((r = pd-pc) > 1) rqsort(pn-r, r, x); }
int main() { float lux[SAMPLE_COUNT]; float moisture[SAMPLE_COUNT]; float lux_med; float moisture_med; int i; float median; // setup wiringpi spi wiringPiSPISetup(0, 1000000) ; // njl7502 (lux) for (i = SAMPLE_COUNT - 1; i >= 0; --i) { unsigned char data[] = {0b00000110, 0b00000000, 0b00000000}; // send and receive data with spi wiringPiSPIDataRW (0, data, sizeof(data)); // convert unit to lux lux[i] = (float)(((data[1] << 8) + data[2]) & 0x0FFF) * 1200.0f / 4096.0f; } // GROVE (moisture) for (i = SAMPLE_COUNT - 1; i >= 0; --i) { unsigned char data[] = {0b00000110, 0b01000000, 0b00000000}; // send and receive data with spi wiringPiSPIDataRW (0, data, sizeof(data)); // convert unit to lux moisture[i] = (float)(((data[1] << 8) + data[2]) & 0x0FFF) * 1930.0f / 4096.0f; } #if SAMPLE_COUNT == 3 lux_med = med3(lux); moisture_med = med3(moisture); #else # error "implement a function to find the median" #endif printf("illuminance: %.2f lux\n", lux_med); printf("moisture: %.2f %\n", moisture_med); return 0; }
void ssort2(unsigned char **a, int n, int depth) { int d, r, partval; unsigned char **pa, **pb, **pc, **pd, **pl, **pm, **pn, *t; if (n < 10) { inssort(a, n, depth); return; } pl = a; pm = a + (n/2); pn = a + (n-1); if (n > 30) { d = (n/8); pl = med3(pl, pl+d, pl+2*d); pm = med3(pm-d, pm, pm+d); pn = med3(pn-2*d, pn-d, pn); } pm = med3(pl, pm, pn); swap2(a, pm); partval = ptr2char(a); pa = pb = a + 1; pc = pd = a + n-1; for (;;) { while (pb <= pc && (r = ptr2char(pb)-partval) <= 0) { if (r == 0) { swap2(pa, pb); pa++; } pb++; } while (pb <= pc && (r = ptr2char(pc)-partval) >= 0) { if (r == 0) { swap2(pc, pd); pd--; } pc--; } if (pb > pc) break; swap2(pb, pc); pb++; pc--; } pn = a + n; r = min(pa-a, pb-pa); vecswap2(a, pb-r, r); r = min(pd-pc, pn-pd-1); vecswap2(pb, pn-r, r); if ((r = pb-pa) > 1) ssort2(a, r, depth); if (ptr2char(a + r) != 0) ssort2(a + r, pa-a + pn-pd-1, depth+1); if ((r = pd-pc) > 1) ssort2(a + n-r, r, depth); }
static Rboolean sm_split3(double *x, double *y, int n, Rboolean do_ends) { /* y[] := S(x[]) where S() = "sm_split3" */ int i, j; Rboolean chg = FALSE; for(i=0; i < n; i++) y[i] = x[i]; /* Colin Goodall doesn't do splits near ends in spl() in Statlib's "smoother" code !! */ if(do_ends && sptest(x, 1)) { chg = TRUE; y[1] = x[0]; y[2] = med3(x[2], x[3], 3*x[3] - 2*x[4]); } for(i=2; i < n-3; i++) if(sptest(x, i)) { /* plateau at x[i] == x[i+1] */ /* at left : */ if(-1 < (j = imed3(x[i ], x[i-1], 3*x[i-1] - 2*x[i-2]))) { y[i] = /* med3(.) = */ (j == 0)? x[i-1] : 3*x[i-1] - 2*x[i-2]; chg = y[i] != x[i]; } /* at right : */ if(-1 < (j = imed3(x[i+1], x[i+2], 3*x[i+2] - 2*x[i+3]))) { y[i+1] = /* med3(.) = */ (j == 0)? x[i+2] : 3*x[i+2] - 2*x[i+3]; chg = y[i+1] != x[i+1]; } } if(do_ends && sptest(x, n-3)) { chg = TRUE; y[n-2] = x[n-1]; y[n-3] = med3(x[n-3], x[n-4], 3*x[n-4] - 2*x[n-5]); } return(chg); }
void sort(Position *a, int left, int right){ static int tmp[3]; /* クイックソート(2次元座標) まずY座標を小さい順に上から並び替え、Y座標が同じ時はx座標が小さい方を上にする。 * a.x : ソートする配列(x) * a.y : ソートする配列(y) * left : ソートするデータの開始位置 * right : ソートするデータの終了位置 */ if (left < right) { int i = left, j = right; int pivot = med3((a + i)->s, ( a+ (i + (j - i) / 2) )->s, (a + j)->s); /* (i+j)/2ではオーバーフローしてしまう */ while (1) { /* (a+i)->s を pivot 以上と以下の集まりに分割する */ while ((a+i)->s < pivot) { i++; } /* (a+i)->s[i] >= pivot となる位置を検索 */ while (pivot < (a+j)->s) { j--; } /* (a+i)->s[j] <= pivot となる位置を検索 */ if (i >= j) { break; } hyouji(a, i, j);//表示関数 tmp[0] = (a+i)->s; (a+i)->s = (a+j)->s; (a+j)->s = tmp[0]; /* (a+i)->s[i],(a+i)->s[j] を交換 */ tmp[1] = (a+i)->y; (a+i)->y = (a+j)->y; (a+j)->y = tmp[1]; /* a[i],a[j] を交換 */ tmp[2] = (a+i)->x; (a+i)->x = (a+j)->x; (a+j)->x = tmp[2]; /* a[i],a[j] を交換 */ hyouji(a, i, j);//表示関数 i++; j--; } sort(a, left, i - 1); /* 分割した左を再帰的にソート */ sort(a, j + 1, right); /* 分割した右を再帰的にソート */ } }
void qsort ( /* SYNOPSIS */ void * a, size_t n, size_t es, int (* cmp)(const void *, const void *)) /* FUNCTION Sort the array a. It contains n elements of the size es. Elements are compares using the function cmp(). INPUTS a - The array to sort n - The number of elements in the array es - The size of a single element in the array cmp - The function which is called when two elements must be compared. The function gets the addresses of two elements of the array and must return 0 is both are equal, < 0 if the first element is less than the second and > 0 otherwise. RESULT None. NOTES EXAMPLE // Use this function to compare to stringpointers int cmp_strptr (const char ** sptr1, const char ** sptr2) { return strcmp (*sptr1, *sptr2); } // Sort an array of strings char ** strings; // fill the array strings = malloc (sizeof (char *)*4); strings[0] = strdup ("h"); strings[1] = strdup ("a"); strings[2] = strdup ("f"); strings[3] = strdup ("d"); // Sort it qsort (strings, sizeof (char *), 4, (void *)cmp_strptr); BUGS SEE ALSO strcmp(), strncmp(), memcmp(), strcasecmp(), strncasecmp() INTERNALS ******************************************************************************/ { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r, swaptype, swap_cnt; loop: SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pm = a + (n / 2) * es; if (n > 7) { pl = a; pn = a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = (char *)med3(pl, pl + d, pl + 2 * d, cmp); pm = (char *)med3(pm - d, pm, pm + d, cmp); pn = (char *)med3(pn - 2 * d, pn - d, pn, cmp); } pm = (char *)med3(pl, pm, pn, cmp); } swap(a, pm); pa = pb = a + es; pc = pd = a + (n - 1) * es; for (;;) { while (pb <= pc && (r = cmp(pb, a)) <= 0) { if (r == 0) { swap_cnt = 1; swap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (r = cmp(pc, a)) >= 0) { if (r == 0) { swap_cnt = 1; swap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; swap(pb, pc); swap_cnt = 1; pb += es; pc -= es; } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pn = a + n * es; r = min(pa - (char *)a, pb - pa); vecswap(a, pb - r, r); r = min(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) qsort(a, r / es, es, cmp); if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; goto loop; } /* qsort(pn - r, r / es, es, cmp);*/ }
void qsort_arg(void *a, size_t n, size_t es, qsort_arg_comparator cmp, void *arg) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r, swaptype, presorted; loop:SWAPINIT(a, es); if (n < 7) { for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl, arg) > 0; pl -= es) swap(pl, pl - es); return; } presorted = 1; for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) { if (cmp(pm - es, pm, arg) > 0) { presorted = 0; break; } } if (presorted) return; pm = (char *) a + (n / 2) * es; if (n > 7) { pl = (char *) a; pn = (char *) a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp, arg); pm = med3(pm - d, pm, pm + d, cmp, arg); pn = med3(pn - 2 * d, pn - d, pn, cmp, arg); } pm = med3(pl, pm, pn, cmp, arg); } swap(static_cast<char *>(a), pm); pa = pb = (char *) a + es; pc = pd = (char *) a + (n - 1) * es; for (;;) { while (pb <= pc && (r = cmp(pb, a, arg)) <= 0) { if (r == 0) { swap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (r = cmp(pc, a, arg)) >= 0) { if (r == 0) { swap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; swap(pb, pc); pb += es; pc -= es; } pn = (char *) a + n * es; r = Min(pa - (char *) a, pb - pa); vecswap(static_cast<char *>(a), pb - r, r); r = Min(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) qsort_arg(a, r / es, es, cmp, arg); if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; goto loop; } /* qsort_arg(pn - r, r / es, es, cmp, arg);*/ }
void qsort(void *a, size_t n, size_t es, cmp_t *cmp) #endif { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; size_t d, r; int cmp_result; int swaptype, swap_cnt; loop: SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pm = (char *)a + (n / 2) * es; if (n > 7) { pl = (char *)a; pn = (char *)a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); pm = med3(pm - d, pm, pm + d, cmp, thunk); pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); } pm = med3(pl, pm, pn, cmp, thunk); } swap(a, pm); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; for (;;) { while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { if (cmp_result == 0) { swap_cnt = 1; swap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { if (cmp_result == 0) { swap_cnt = 1; swap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; swap(pb, pc); swap_cnt = 1; pb += es; pc -= es; } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pn = (char *)a + n * es; r = min(pa - (char *)a, pb - pa); vecswap((char*)a, (char *)(pb - r), r); // !!! Ren/C: pn - pd - es => (long)(pn - pd - ps) for -Wsign-compare r = min(pd - pc, (long)(pn - pd - es)); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) #ifdef I_AM_QSORT_R qsort_r(a, r / es, es, thunk, cmp); #else qsort(a, r / es, es, cmp); #endif if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; goto loop; } /* qsort(pn - r, r / es, es, cmp);*/ }
void NS_QuickSort ( void *a, unsigned int n, unsigned int es, cmp_t *cmp, void *data ) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r, swaptype; loop: SWAPINIT(a, es); /* Use insertion sort when input is small */ if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0; pl -= es) swap(pl, pl - es); return; } /* Choose pivot */ pm = (char *)a + (n / 2) * es; if (n > 7) { pl = (char *)a; pn = (char *)a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp, data); pm = med3(pm - d, pm, pm + d, cmp, data); pn = med3(pn - 2 * d, pn - d, pn, cmp, data); } pm = med3(pl, pm, pn, cmp, data); } swap(a, pm); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; /* loop invariants: * [a, pa) = pivot * [pa, pb) < pivot * [pb, pc + es) unprocessed * [pc + es, pd + es) > pivot * [pd + es, pn) = pivot */ for (;;) { while (pb <= pc && (r = cmp(pb, a, data)) <= 0) { if (r == 0) { swap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (r = cmp(pc, a, data)) >= 0) { if (r == 0) { swap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; swap(pb, pc); pb += es; pc -= es; } /* Move pivot values */ pn = (char *)a + n * es; r = XPCOM_MIN(pa - (char *)a, pb - pa); vecswap(a, pb - r, r); r = XPCOM_MIN<size_t>(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); /* Recursively process partitioned items */ if ((r = pb - pa) > (int)es) NS_QuickSort(a, r / es, es, cmp, data); if ((r = pd - pc) > (int)es) { /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; goto loop; } /* NS_QuickSort(pn - r, r / es, es, cmp, data);*/ }
/*--------------------------------------------------------------------------*/ void sciqsort(char *a, char *tab, int flag, int n, int es, int es1, int (*cmp)(), int (*swapcode)(), int (*lswapcodeind)()) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; char *taba, *tabb, *tabc, *tabd, *tabl, *tabm, *tabn; int d, dind, r, r1, swap_cnt; loop: swap_cnt = 0; if (n < 7) /* Insertion sort on smallest arrays */ { for (pm = a + es, tabm = tab + es1 ; pm < (char *) a + n * es; pm += es, tabm += es1 ) { for (pl = pm, tabl = tabm ; pl > (char *) a && cmp(pl - es, pl, tabl - es1, tabl, flag) > 0; pl -= es, tabl -= es1) { swapind(tabl, tabl - es1); swap(pl, pl - es); } } return; } /*Determine the pivot */ pm = a + (n / 2) * es;/* Small arrays, middle element */ tabm = tab + (n / 2) * es1 ; pn = a + (n - 1) * es; tabn = tab + (n - 1) * es1; if (n > 7) { pl = a; tabl = tab; if (n > 40) /* Big arrays, pseudomedian of 9 */ { dind = (n / 8) * es1; d = (n / 8) * es; med3(pl, tabl, pl, pl + d, pl + 2 * d, tabl, tabl + dind, tabl + 2 * dind, cmp); med3(pm, tabm, pm - d, pm, pm + d, tabm - dind, tabm, tabm + dind, cmp); med3(pn, tabn, pn - 2 * d, pn - d, pn, tabn - 2 * dind, tabn - dind, tabn, cmp); } med3(pm, tabm, pl, pm, pn, tabl, tabm, tabn, cmp); } /* Put it at the first position */ /* Partionning */ if (cmp(pn, a, tabn, tab, flag)) { swapind(tab, tabn); swap(a, pn); } /* pointers on data array */ pa = pb = a + es;/* pa and pb start from the beginning of the array */ pc = pd = a + (n - 1) * es;/* pc and pd start from the end of the array */ /* similar pointers for index array */ taba = tabb = tab + es1; tabc = tabd = tab + (n - 1) * es1; /* here we have |a |pa | pc| |a |pb | pd| |*a | ? | ? | */ for (;;) { /* increase the pointer pb while it points on values lesser than the pivot (pointer a) */ while (pb <= pc && (r = cmp(pb, a, tabb, tab, flag)) <= 0) { if (r == 0) /*The pivot and value pointed to by pb are equal */ { /* store the equal value at the location pa and increase pa */ swap_cnt = 1; swapind(taba, tabb); taba += es1; swap(pa, pb); pa += es; } pb += es;/* next number */ tabb += es1; } /* here pb points on a value greater than the pivot */ /* decrease the pointer pc while it points on a value greater than the pivot (pointer a) */ while (pb <= pc && (r = cmp(pc, a, tabc, tab, flag)) >= 0) { if (r == 0) /*The pivot and value pointed to by pc are equal */ { /* store the equal value at the location pd and decrease pd */ swap_cnt = 1; swapind(tabc, tabd); tabd -= es1; swap(pc, pd); pd -= es; } pc -= es; tabc -= es1; } /* here pc points on a value lesser than the pivot */ if (pb > pc) { /* here we have |a |pa |pc|pb pd| $| | =*a | <*a | >*a | =*a $| */ /* partition is done */ break; } /*here pc points on a value lesser than the pivot and pb points on a value greater than the pivot swap the values */ swapind(tabb, tabc); tabb += es1; tabc -= es1; swap(pb, pc); swap_cnt = 1; /* increase pb and decrease pc */ pb += es; pc -= es; /* here we have |a |pa |pb pc| pd| $| | =*a | <*a | ? | >*a | =*a $| */ } if (swap_cnt == 0) /* Switch to insertion sort */ { for (pm = a + es, tabm = tab + es1 ; pm < (char *) a + n * es; pm += es, tabm += es1) { for (pl = pm, tabl = tabm ; pl > (char *) a && cmp(pl - es, pl, tabl - es1, tabl, flag) > 0; pl -= es, tabl -= es1) { swapind(tabl, tabl - es1); swap(pl, pl - es); } } return; } /* put the equal values in the middle */ pn = a + n * es; r = (int)Min(pa - (char *)a, pb - pa); vecswap(a, pb - r, r); tabn = tab + n * es1 ; r1 = (int)Min(taba - (char *) tab, tabb - taba); vecswapind(tab, tabb - r1, r1); r = (int)Min(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); r1 = (int)Min(tabd - tabc, tabn - tabd - es1 ); vecswapind(tabb, tabn - r1, r1); if ((r = (int)(pb - pa)) > es ) /* recall sciqsort for the lower part */ { sciqsort(a, tab, flag, r / es, es, es1, cmp, swapcode, lswapcodeind); } if ((r = (int)(pd - pc)) > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; tab = tabn - (tabd - tabc); n = r / es; goto loop; } }
void qsort( void *basep, size_t nrec, size_t rsiz, int (*cmp)(const void *, const void *)) { size_t i; /* temporary variable */ /* variables used by swap */ void (*swapf)(char *, char *, size_t); size_t loops; /* variables used by sort */ stk_t stack[8 * sizeof (nrec) + 1]; stk_t *sp; char *b_lim; /* bottom limit */ char *b_dup; /* bottom duplicate */ char *b_par; /* bottom partition */ char *t_lim; /* top limit */ char *t_dup; /* top duplicate */ char *t_par; /* top partition */ char *m1, *m2, *m3; /* median pointers */ uintptr_t d_bytelength; /* byte length of duplicate records */ int b_nrec; int t_nrec; int cv; /* results of compare (bottom / top) */ /* * choose a swap function based on alignment and size * * The qsort function sorts an array of fixed length records. * We have very limited knowledge about the data record itself. * It may be that the data record is in the array we are sorting * or it may be that the array contains pointers or indexes to * the actual data record and all that we are sorting is the indexes. * * The following decision will choose an optimal swap function * based on the size and alignment of the data records * swapp64 will swap 64 bit pointers * swapp32 will swap 32 bit pointers * swapi will swap an array of 32 bit integers * swapb will swap an array of 8 bit characters * * swapi and swapb will also require the variable loops to be set * to control the length of the array being swapped */ if ((((uintptr_t)basep & (sizeof (uint64_t) - 1)) == 0) && (rsiz == sizeof (uint64_t))) { loops = 1; swapf = (void (*)(char *, char *, size_t))swapp64; } else if ((((uintptr_t)basep & (sizeof (uint32_t) - 1)) == 0) && (rsiz == sizeof (uint32_t))) { loops = 1; swapf = (void (*)(char *, char *, size_t))swapp32; } else if ((((uintptr_t)basep & (sizeof (uint32_t) - 1)) == 0) && ((rsiz & (sizeof (uint32_t) - 1)) == 0)) { loops = rsiz / sizeof (int); swapf = (void (*)(char *, char *, size_t))swapi; } else { loops = rsiz; swapf = swapb; } /* * qsort is a partitioning sort * * the stack is the bookkeeping mechanism to keep track of all * the partitions. * * each sort pass takes one partition and sorts it into two partitions. * at the top of the loop we simply take the partition on the top * of the stack and sort it. See the comments at the bottom * of the loop regarding which partitions to add in what order. * * initially put the whole partition on the stack */ sp = stack; sp->b_lim = (char *)basep; sp->nrec = nrec; sp++; while (sp > stack) { sp--; b_lim = sp->b_lim; nrec = sp->nrec; /* * a linear insertion sort i faster than a qsort for * very small number of records (THRESH_L) * * if number records < threshold use linear insertion sort * * this also handles the special case where the partition * 0 or 1 records length. */ if (nrec < THRESH_L) { /* * Linear insertion sort */ t_par = b_lim; for (i = 1; i < nrec; i++) { t_par += rsiz; b_par = t_par; while (b_par > b_lim) { b_par -= rsiz; if ((*cmp)(b_par, b_par + rsiz) <= 0) { break; } (*swapf)(b_par, b_par + rsiz, loops); } } /* * a linear insertion sort will put all records * in their final position and will not create * subpartitions. * * therefore when the insertion sort is complete * just go to the top of the loop and get the * next partition to sort. */ continue; } /* quicksort */ /* * choose a pivot record * * Ideally the pivot record will divide the partition * into two equal parts. however we have to balance the * work involved in selecting the pivot record with the * expected benefit. * * The choice of pivot record depends on the number of * records in the partition * * for small partitions (nrec < THRESH_M3) * we just select the record in the middle of the partition * * if (nrec >= THRESH_M3 && nrec < THRESH_M9) * we select three values and choose the median of 3 * * if (nrec >= THRESH_M9) * then we use an approximate median of 9 * 9 records are selected and grouped in 3 groups of 3 * the median of each of these 3 groups is fed into another * median of 3 decision. * * Each median of 3 decision is 2 or 3 compares, * so median of 9 costs between 8 and 12 compares. * * i is byte distance between two consecutive samples * m2 will point to the pivot record */ if (nrec < THRESH_M3) { m2 = b_lim + (nrec / 2) * rsiz; } else if (nrec < THRESH_M9) { /* use median of 3 */ i = ((nrec - 1) / 2) * rsiz; m2 = med3(b_lim, b_lim + i, b_lim + 2 * i); } else { /* approx median of 9 */ i = ((nrec - 1) / 8) * rsiz; m1 = med3(b_lim, b_lim + i, b_lim + 2 * i); m2 = med3(b_lim + 3 * i, b_lim + 4 * i, b_lim + 5 * i); m3 = med3(b_lim + 6 * i, b_lim + 7 * i, b_lim + 8 * i); m2 = med3(m1, m2, m3); } /* * quick sort partitioning * * The partition limits are defined by bottom and top pointers * b_lim and t_lim. * * qsort uses a fairly standard method of moving the * partitioning pointers, b_par and t_par, to the middle of * the partition and exchanging records that are in the * wrong part of the partition. * * Two enhancements have been made to the basic algorithm. * One for handling duplicate records and one to minimize * the number of swaps. * * Two duplicate records pointers are (b_dup and t_dup) are * initially set to b_lim and t_lim. Each time a record * whose sort key value is equal to the pivot record is found * it will be swapped with the record pointed to by * b_dup or t_dup and the duplicate pointer will be * incremented toward the center. * When partitioning is complete, all the duplicate records * will have been collected at the upper and lower limits of * the partition and can easily be moved adjacent to the * pivot record. * * The second optimization is to minimize the number of swaps. * The pointer m2 points to the pivot record. * During partitioning, if m2 is ever equal to the partitioning * pointers, b_par or t_par, then b_par or t_par just moves * onto the next record without doing a compare. * If as a result of duplicate record detection, * b_dup or t_dup is ever equal to m2, * then m2 is changed to point to the duplicate record and * b_dup or t_dup is incremented with out swapping records. * * When partitioning is done, we may not have the same pivot * record that we started with, but we will have one with * an equal sort key. */ b_dup = b_par = b_lim; t_dup = t_par = t_lim = b_lim + rsiz * (nrec - 1); for (;;) { /* move bottom pointer up */ for (; b_par <= t_par; b_par += rsiz) { if (b_par == m2) { continue; } cv = cmp(b_par, m2); if (cv > 0) { break; } if (cv == 0) { if (b_dup == m2) { m2 = b_par; } else if (b_dup != b_par) { (*swapf)(b_dup, b_par, loops); } b_dup += rsiz; } } /* move top pointer down */ for (; b_par < t_par; t_par -= rsiz) { if (t_par == m2) { continue; } cv = cmp(t_par, m2); if (cv < 0) { break; } if (cv == 0) { if (t_dup == m2) { m2 = t_par; } else if (t_dup != t_par) { (*swapf)(t_dup, t_par, loops); } t_dup -= rsiz; } } /* break if we are done partitioning */ if (b_par >= t_par) { break; } /* exchange records at upper and lower break points */ (*swapf)(b_par, t_par, loops); b_par += rsiz; t_par -= rsiz; } /* * partitioning is now complete * * there are two termination conditions from the partitioning * loop above. Either b_par or t_par have crossed or * they are equal. * * we need to swap the pivot record to its final position * m2 could be in either the upper or lower partitions * or it could already be in its final position */ /* * R[b_par] > R[m2] * R[t_par] < R[m2] */ if (t_par < b_par) { if (m2 < t_par) { (*swapf)(m2, t_par, loops); m2 = b_par = t_par; } else if (m2 > b_par) { (*swapf)(m2, b_par, loops); m2 = t_par = b_par; } else { b_par = t_par = m2; } } else { if (m2 < t_par) { t_par = b_par = t_par - rsiz; } if (m2 != b_par) { (*swapf)(m2, b_par, loops); } m2 = t_par; } /* * move bottom duplicates next to pivot * optimized to eliminate overlap */ d_bytelength = b_dup - b_lim; if (b_par - b_dup < d_bytelength) { b_dup = b_lim + (b_par - b_dup); } while (b_dup > b_lim) { b_dup -= rsiz; b_par -= rsiz; (*swapf)(b_dup, b_par, loops); } b_par = m2 - d_bytelength; /* * move top duplicates next to pivot */ d_bytelength = t_lim - t_dup; if (t_dup - t_par < d_bytelength) { t_dup = t_lim - (t_dup - t_par); } while (t_dup < t_lim) { t_dup += rsiz; t_par += rsiz; (*swapf)(t_dup, t_par, loops); } t_par = m2 + d_bytelength; /* * when a qsort pass completes there are three partitions * 1) the lower contains all records less than pivot * 2) the upper contains all records greater than pivot * 3) the pivot partition contains all record equal to pivot * * all records in the pivot partition are in their final * position and do not need to be accounted for by the stack * * when adding partitions to the stack * it is important to add the largest partition first * to prevent stack overflow. * * calculate number of unsorted records in top and bottom * push resulting partitions on stack */ b_nrec = (b_par - b_lim) / rsiz; t_nrec = (t_lim - t_par) / rsiz; if (b_nrec < t_nrec) { sp->b_lim = t_par + rsiz; sp->nrec = t_nrec; sp++; sp->b_lim = b_lim; sp->nrec = b_nrec; sp++; } else { sp->b_lim = b_lim; sp->nrec = b_nrec; sp++; sp->b_lim = t_par + rsiz; sp->nrec = t_nrec; sp++; } } }
void base_quicksort7(unsigned int a[], int N) { int l, r; int i; int m; int il, ir; /* names follow pl, pm, and pn from bently/mcilroy. used ir instead of in */ stackinit(N); describe_predictor(&global_predictor[0], "i"); describe_predictor(&global_predictor[1], "j"); describe_predictor(&global_predictor[2], "partition end"); describe_predictor(&global_predictor[3], "insertion"); describe_predictor(&global_predictor[4], "median"); /* describe_predictor(&global_predictor[4], "median of 7 ab"); */ describe_predictor(&global_predictor[5], "median of 7 bc"); describe_predictor(&global_predictor[6], "median of 7 ac"); describe_predictor(&global_predictor[7], "median of 7 cb"); describe_predictor(&global_predictor[8], "median of 7 ca"); describe_predictor(&global_predictor[9], "median of 7 ab2"); describe_predictor(&global_predictor[10], "median of 7 bc2"); describe_predictor(&global_predictor[11], "median of 7 ac2"); describe_predictor(&global_predictor[12], "median of 7 cb2"); describe_predictor(&global_predictor[13], "median of 7 ca2"); describe_predictor(&global_predictor[14], "median of 3 cmp1"); describe_predictor(&global_predictor[15], "median of 3 cmp2"); describe_predictor(&global_predictor[16], "median of 3 cmp3"); r = N-1; l = 0; while(1) { int n = r - l; int n6 = n/6; int n3 = n/3; if (r - l <= THRESHHOLD) { if (stackempty()) break; l = pop(); r = pop(); continue; } /* pseudo - Median of 7 partitioning*/ m = (l+r)/2; if (n > 40) { il = med3(a, l, l + n6, l + n3); /* the 2 is for seperate branch predictors, as it's inlined */ ir = med3_2(a, r - n3, r - n6, r); exch(a[l], a[il]); exch(a[r], a[ir]); exch(a[m], a[r-1]); } pred_compexch(a[l], a[r-1], 14); pred_compexch(a[l], a[r], 15); pred_compexch(a[r-1], a[r], 16); i = partition(a,l+1,r-1); /* here is the bug */ /* then key is being copied more times than necessary. the reason for this is that it is not being removed when it is taken as the key */ /* instead, it is being put in place more than once */ /* example: i == 1, j == 10; key = a[1]; key < pivot, so key is swapped with a[2], the key is now in a[1] and a[2]. uh oh */ if (i-l > r-i) { push(i-1,l); l = i+1; } else { push(r,i+1); r = i-1; } } stackclear(); /* the +1 isnt immediately obvious. its because THRESHHOLD is the difference between l and r up above */ if (2*THRESHHOLD > N) insertion_sentinel(a,N); else insertion_sentinel(a,2*THRESHHOLD); insertion(a, N); /* add the predictors up */ add_predictor(&global_predictor[4], &global_predictor[5]); add_predictor(&global_predictor[4], &global_predictor[6]); add_predictor(&global_predictor[4], &global_predictor[7]); add_predictor(&global_predictor[4], &global_predictor[8]); add_predictor(&global_predictor[4], &global_predictor[9]); add_predictor(&global_predictor[4], &global_predictor[10]); add_predictor(&global_predictor[4], &global_predictor[11]); add_predictor(&global_predictor[4], &global_predictor[12]); add_predictor(&global_predictor[4], &global_predictor[13]); add_predictor(&global_predictor[4], &global_predictor[14]); add_predictor(&global_predictor[4], &global_predictor[15]); add_predictor(&global_predictor[4], &global_predictor[16]); init_predictor(&global_predictor[5]); init_predictor(&global_predictor[6]); init_predictor(&global_predictor[7]); init_predictor(&global_predictor[8]); init_predictor(&global_predictor[9]); init_predictor(&global_predictor[10]); init_predictor(&global_predictor[11]); init_predictor(&global_predictor[12]); init_predictor(&global_predictor[13]); init_predictor(&global_predictor[14]); init_predictor(&global_predictor[15]); init_predictor(&global_predictor[16]); }
//Stable sort of sequences void SArrayIndex::sort(quint32* x, int off, int len) { // Insertion sort on smallest arrays if (len < 7) { for (int i=off; i<len+off; i++){ for (int j=i; j > off && compare(x[j-1],x[j])>0; j--) { qSwap(x[j], x[j-1]); } } return; } // Choose a partition element, v quint32 m = off + len / 2; // Small arrays, middle element if (len > 7) { quint32 l = off; quint32 n = off + len - 1; if (len > 40) { // Big arrays, pseudo median of 9 quint32 s = len / 8; l = med3(x, l, l+s, l+2*s); m = med3(x, m-s, m, m+s); n = med3(x, n-2*s, n-s, n); } m = med3(x, l, m, n); // Mid-size, med of 3 } quint32 v = x[m]; // Establish Invariant: v* (<v)* (>v)* v* int a = off, b = off, c = off + len - 1, d = c; while(true) { int cr; while (b <= c && (cr = compare(v, x[b])) >= 0) { if (cr == 0) { qSwap(x[a],x[b]); a++; } b++; } while (c >= b && (cr = compare(x[c], v)) >=0 ) { if (cr == 0) { qSwap(x[c],x[d]); d--; } c--; } if (b > c) { break; } qSwap(x[b], x[c]); b++; c--; } // Swap partition elements back to middle int s, n = off + len; s = qMin(a-off, b-a ); vecswap(x, off, b-s, s); s = qMin(d-c, n-d-1); vecswap(x, b, n-s, s); // Recursively sort non-partition-elements if ((s = b-a) > 1) { sort(x, off, s); } if ((s = d-c) > 1) { sort(x, n-s, s); } }
/* ******************************************************** recursive multikey quicksort from Bentley-Sedgewick stops when text_depth reaches Shallow_depth_limit that is when we have found that the current set of strings have Shallow_limit chars in common ******************************************************** */ static void shallow_mkq(Int32 *a, int n, UChar *text_depth) { __inline__ void vecswap2(Int32 *a, Int32 *b, int n); int d, r, partval; Int32 *pa, *pb, *pc, *pd, *pl, *pm, *pn, t; UChar *next_depth; // ---- On small arrays use insertions sort if (n < Mk_qs_thresh) { shallow_inssort_lcp(a, n, text_depth); return; } // ----------- choose pivot -------------- repeat: pl = a; pm = a + (n/2); pn = a + (n-1); if (n > 30) { // On big arrays, pseudomedian of 9 d = (n/8); pl = med3(pl, pl+d, pl+2*d); pm = med3(pm-d, pm, pm+d); pn = med3(pn-2*d, pn-d, pn); } pm = med3(pl, pm, pn); swap2(a, pm); partval = ptr2char(a); pa = pb = a + 1; pc = pd = a + n-1; // -------- partition ----------------- for (;;) { while (pb <= pc && (r = ptr2char(pb)-partval) <= 0) { if (r == 0) { swap2(pa, pb); pa++; } pb++; } while (pb <= pc && (r = ptr2char(pc)-partval) >= 0) { if (r == 0) { swap2(pc, pd); pd--; } pc--; } if (pb > pc) break; swap2(pb, pc); pb++; pc--; } #if UNROLL if(pa>pd) { // all values were equal to partval: make it simpler if( (next_depth = text_depth+1) >= Shallow_text_limit) { helped_sort(a, n, next_depth-Text, Shallow_limit); return; } else { text_depth = next_depth; goto repeat; } } #endif // partition a[] into the values smaller, equal, and larger that partval pn = a + n; r = min(pa-a, pb-pa); vecswap2(a, pb-r, r); r = min(pd-pc, pn-pd-1); vecswap2(pb, pn-r, r); // --- sort smaller strings ------- if ((r = pb-pa) > 1) shallow_mkq(a, r, text_depth); // --- sort strings starting with partval ----- if( (next_depth = text_depth+1) < Shallow_text_limit) shallow_mkq(a + r, pa-pd+n-1, next_depth); else helped_sort(a + r, pa-pd+n-1, next_depth-Text, Shallow_limit); if ((r = pd-pc) > 1) shallow_mkq(a + n-r, r, text_depth); }
/* * simple approach for now; a better median-finding * may be preferable */ static T choose_pivot(T *low, T *high) { return med3(*low, *high, low[(high-low)/2UL]); }
void yaffs_qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r, swaptype, swap_cnt; register char *a = aa; loop: SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -= es) yswap(pl, pl - es); return; } pm = (char *)a + (n / 2) * es; if (n > 7) { pl = (char *)a; pn = (char *)a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp); pm = med3(pm - d, pm, pm + d, cmp); pn = med3(pn - 2 * d, pn - d, pn, cmp); } pm = med3(pl, pm, pn, cmp); } yswap(a, pm); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; for (;;) { while (pb <= pc && (r = cmp(pb, a)) <= 0) { if (r == 0) { swap_cnt = 1; yswap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (r = cmp(pc, a)) >= 0) { if (r == 0) { swap_cnt = 1; yswap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; yswap(pb, pc); swap_cnt = 1; pb += es; pc -= es; } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -= es) yswap(pl, pl - es); return; } pn = (char *)a + n * es; r = min(pa - (char *)a, pb - pa); vecswap(a, pb - r, r); r = min((long)(pd - pc), (long)(pn - pd - es)); vecswap(pb, pn - r, r); r = pb - pa; if (r > es) yaffs_qsort(a, r / es, es, cmp); r = pd - pc; if (r > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; goto loop; } /* yaffs_qsort(pn - r, r / es, es, cmp);*/ }
/* Subroutine for sort_split, algorithm by Bentley & McIlroy.*/ int choose_pivot(const int_iter &p, int64_t n) { int_iter pl, pm, pn; int64_t s; pm=p+(n>>1); /* small arrays, middle element.*/ if (n>7) { pl=p; pn=p+n-1; if (n>40) { /* big arrays, pseudomedian of 9.*/ s=n>>3; pl=med3(pl, pl+s, pl+s+s); pm=med3(pm-s, pm, pm+s); pn=med3(pn-s-s, pn-s, pn); } pm=med3(pl, pm, pn); /* midsize arrays, median of 3.*/ } return key(pm); } /* Sorting routine called for each unsorted group. Sorts the array of integers (suffix numbers) of length n starting at p. The algorithm is a ternary-split quicksort taken from Bentley & McIlroy, "Engineering a Sort Function", Software -- Practice and Experience 23(11), 1249-1265 (November 1993). This function is based on Program 7.*/ void sort_split(const int_iter &p, int64_t n) { int_iter pa, pb, pc, pd, pl, pm, pn; uint64_t f, v; int64_t s, t; if (n<7) { /* multi-selection sort smallest arrays.*/
void recast_qsort(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r, swaptype, swap_cnt; loop: SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pm = (char *)a + (n / 2) * es; if (n > 7) { pl = (char *)a; pn = (char *)a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); pm = med3(pm - d, pm, pm + d, cmp, thunk); pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); } pm = med3(pl, pm, pn, cmp, thunk); } swap((char *)a, pm); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; for (;;) { while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) { if (r == 0) { swap_cnt = 1; swap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) { if (r == 0) { swap_cnt = 1; swap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; swap(pb, pc); swap_cnt = 1; pb += es; pc -= es; } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pn = (char *)a + n * es; r = min(pa - (char *)a, pb - pa); vecswap((char *)a, pb - r, r); r = min(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) recast_qsort(a, r / es, es, thunk, cmp); if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; goto loop; } }
static void _pqsort(void *a, size_t n, size_t es, int (*cmp) (const void *, const void *), void *lrange, void *rrange) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; size_t d, r; int swaptype, cmp_result; loop: SWAPINIT(a, es); if (n < 7) { for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pm = (char *) a + (n / 2) * es; if (n > 7) { pl = (char *) a; pn = (char *) a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp); pm = med3(pm - d, pm, pm + d, cmp); pn = med3(pn - 2 * d, pn - d, pn, cmp); } pm = med3(pl, pm, pn, cmp); } swap(a, pm); pa = pb = (char *) a + es; pc = pd = (char *) a + (n - 1) * es; for (;;) { while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) { if (cmp_result == 0) { swap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) { if (cmp_result == 0) { swap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; swap(pb, pc); pb += es; pc -= es; } pn = (char *) a + n * es; r = min(pa - (char *) a, pb - pa); vecswap(a, pb - r, r); r = min((size_t)(pd - pc), pn - pd - es); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) { void *_l = a, *_r = ((unsigned char*)a)+r-1; if (!((lrange < _l && rrange < _l) || (lrange > _r && rrange > _r))) _pqsort(a, r / es, es, cmp, lrange, rrange); } if ((r = pd - pc) > es) { void *_l, *_r; /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; _l = a; _r = ((unsigned char*)a)+r-1; if (!((lrange < _l && rrange < _l) || (lrange > _r && rrange > _r))) goto loop; } /* qsort(pn - r, r / es, es, cmp);*/ }