void qsort_s(void *Base, size_t NumOfElements, size_t SizeOfElements, int (__cdecl *FuncCompare)(void *,const void *,const void *), void *Context) { if (!FuncCompare) return; const size_t size = NumOfElements * SizeOfElements; char buf[1024]; if (size < sizeof(buf)) { /* The temporary array fits on the small on-stack buffer. */ msort_with_tmp(Base, NumOfElements, SizeOfElements, FuncCompare, Context, buf); } else { /* It's somewhat large, so malloc it. */ char *tmp = malloc(size); if (tmp) { msort_with_tmp(Base, NumOfElements, SizeOfElements, FuncCompare, Context, tmp); free(tmp); } } }
static void msort_with_tmp (void *b, size_t n, size_t s, __compar_fn_t cmp, char *t) { char *tmp; char *b1, *b2; size_t n1, n2; if (n <= 1) return; n1 = n / 2; n2 = n - n1; b1 = b; b2 = (char *) b + (n1 * s); msort_with_tmp (b1, n1, s, cmp, t); msort_with_tmp (b2, n2, s, cmp, t); tmp = t; if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0) /* We are operating on aligned words. Use direct word stores. */ while (n1 > 0 && n2 > 0) { if ((*cmp) (b1, b2) <= 0) { --n1; *((op_t *) tmp)++ = *((op_t *) b1)++; } else { --n2; *((op_t *) tmp)++ = *((op_t *) b2)++; } } else while (n1 > 0 && n2 > 0) { if ((*cmp) (b1, b2) <= 0) { tmp = (char *) __mempcpy (tmp, b1, s); b1 += s; --n1; } else { tmp = (char *) __mempcpy (tmp, b2, s); b2 += s; --n2; } } if (n1 > 0) memcpy (tmp, b1, n1 * s); memcpy (b, t, (n - n2) * s); }
static void msort_with_tmp( void *Base, size_t NumElem, size_t SizeElem, int (*FuncCmp)(void *Ctx, const void *, const void *), void *Context, char *ExtTmp) { char *LocalTmp; char *b1, *b2; size_t n1, n2; if (NumElem <= 1) return; n1 = NumElem / 2; n2 = NumElem - n1; b1 = Base; b2 = (char *)Base + (n1 * SizeElem); msort_with_tmp(b1, n1, SizeElem, FuncCmp, Context, ExtTmp); msort_with_tmp(b2, n2, SizeElem, FuncCmp, Context, ExtTmp); LocalTmp = ExtTmp; while (n1 > 0 && n2 > 0) { if (FuncCmp(Context, b1, b2) <= 0) { memcpy(LocalTmp, b1, SizeElem); LocalTmp += SizeElem; b1 += SizeElem; --n1; } else { memcpy(LocalTmp, b2, SizeElem); LocalTmp += SizeElem; b2 += SizeElem; --n2; } } if (n1 > 0) memcpy(LocalTmp, b1, n1 * SizeElem); memcpy(Base, ExtTmp, (NumElem - n2) * SizeElem); }
void git_qsort(void *b, size_t n, size_t s, int (*cmp)(const void *, const void *)) { const size_t size = n * s; char buf[1024]; if (size < sizeof(buf)) { /* The temporary array fits on the small on-stack buffer. */ msort_with_tmp(b, n, s, cmp, buf); } else { /* It's somewhat large, so malloc it. */ char *tmp = xmalloc(size); msort_with_tmp(b, n, s, cmp, tmp); free(tmp); } }
static void msort_with_tmp(void *b, size_t n, size_t s, int (*cmp)(const void *, const void *), char *t) { char *tmp; char *b1, *b2; size_t n1, n2; if (n <= 1) return; n1 = n / 2; n2 = n - n1; b1 = b; b2 = (char *)b + (n1 * s); msort_with_tmp(b1, n1, s, cmp, t); msort_with_tmp(b2, n2, s, cmp, t); tmp = t; while (n1 > 0 && n2 > 0) { if (cmp(b1, b2) <= 0) { memcpy(tmp, b1, s); tmp += s; b1 += s; --n1; } else { memcpy(tmp, b2, s); tmp += s; b2 += s; --n2; } } if (n1 > 0) memcpy(tmp, b1, n1 * s); memcpy(b, t, (n - n2) * s); }
void qsort(void *base, size_t total_num, size_t size, int (*cmp)(const void *, const void *)) { size_t total_size = size * total_num; if(total_size < 1024) { msort_with_tmp(base, total_num, size, cmp, (char*)alloca(total_size) ); } else { char *tmp = (char*)malloc(size); if(tmp == NULL) { extern void _quicksort(void *base, size_t total_num, size_t size, int (*compare)(const void *, const void *) ); _quicksort(base, total_num, size, cmp); } else { msort_with_tmp(base, total_num, size, cmp, tmp ); free( tmp ); } } }
void msort_with_tmp(void *base, size_t num, size_t size, int (*compare)(const void *, const void *), char *t) { if( num <= 1) return; int num1 = num / 2; char *base1 = (char*)base; int num2 = num - num1; char *base2 = (char*)base + size * num1; msort_with_tmp(base1, num1, size, compare, t); msort_with_tmp(base2, num2, size, compare, t); char *tmp = t; while(num1 > 0 && num2 > 0) { if( (*compare)(base1, base2) <= 0) { memcpy(tmp, base1, size); base1 += size; --num1; } else { memcpy(tmp, base2, size); base2 += size; --num2; } tmp += size; } if(num1 > 0) memcpy(tmp, base1, num1 * size); //base1 | base2, base2's elem is tail and sorted memcpy(base, t, (num - num2) * size); }
static void msort_with_tmp (const struct msort_param *p, void *b, size_t n) { char *b1, *b2; size_t n1, n2; if (n <= 1) return; n1 = n / 2; n2 = n - n1; b1 = b; b2 = (char *) b + (n1 * p->s); msort_with_tmp (p, b1, n1); msort_with_tmp (p, b2, n2); char *tmp = p->t; const size_t s = p->s; __compar_d_fn_t cmp = p->cmp; void *arg = p->arg; switch (p->var) { case 0: while (n1 > 0 && n2 > 0) { if ((*cmp) (b1, b2, arg) <= 0) { *(uint32_t *) tmp = *(uint32_t *) b1; b1 += sizeof (uint32_t); --n1; } else { *(uint32_t *) tmp = *(uint32_t *) b2; b2 += sizeof (uint32_t); --n2; } tmp += sizeof (uint32_t); } break; case 1: while (n1 > 0 && n2 > 0) { if ((*cmp) (b1, b2, arg) <= 0) { *(uint64_t *) tmp = *(uint64_t *) b1; b1 += sizeof (uint64_t); --n1; } else { *(uint64_t *) tmp = *(uint64_t *) b2; b2 += sizeof (uint64_t); --n2; } tmp += sizeof (uint64_t); } break; case 2: while (n1 > 0 && n2 > 0) { unsigned long *tmpl = (unsigned long *) tmp; unsigned long *bl; tmp += s; if ((*cmp) (b1, b2, arg) <= 0) { bl = (unsigned long *) b1; b1 += s; --n1; } else { bl = (unsigned long *) b2; b2 += s; --n2; } while (tmpl < (unsigned long *) tmp) *tmpl++ = *bl++; } break; case 3: while (n1 > 0 && n2 > 0) { if ((*cmp) (*(const void **) b1, *(const void **) b2, arg) <= 0) { *(void **) tmp = *(void **) b1; b1 += sizeof (void *); --n1; } else { *(void **) tmp = *(void **) b2; b2 += sizeof (void *); --n2; } tmp += sizeof (void *); } break; default: while (n1 > 0 && n2 > 0) { if ((*cmp) (b1, b2, arg) <= 0) { tmp = (char *) __mempcpy (tmp, b1, s); b1 += s; --n1; } else { tmp = (char *) __mempcpy (tmp, b2, s); b2 += s; --n2; } } break; } if (n1 > 0) memcpy (tmp, b1, n1 * s); memcpy (b, p->t, (n - n2) * s); }
void qsort (void *b, size_t n, size_t s, __compar_fn_t cmp) { const size_t size = n * s; if (size < 1024) { void *buf = __alloca (size); /* The temporary array is small, so put it on the stack. */ msort_with_tmp (b, n, s, cmp, buf); } else { /* We should avoid allocating too much memory since this might have to be backed up by swap space. */ static long int phys_pages; static int pagesize; if (phys_pages == 0) { phys_pages = __sysconf (_SC_PHYS_PAGES); if (phys_pages == -1) /* Error while determining the memory size. So let's assume there is enough memory. Otherwise the implementer should provide a complete implementation of the `sysconf' function. */ phys_pages = (long int) (~0ul >> 1); /* The following determines that we will never use more than a quarter of the physical memory. */ phys_pages /= 4; pagesize = __sysconf (_SC_PAGESIZE); } /* Just a comment here. We cannot compute phys_pages * pagesize and compare the needed amount of memory against this value. The problem is that some systems might have more physical memory then can be represented with a `size_t' value (when measured in bytes. */ /* If the memory requirements are too high don't allocate memory. */ if (size / pagesize > phys_pages) _quicksort (b, n, s, cmp); else { /* It's somewhat large, so malloc it. */ int save = errno; char *tmp = malloc (size); if (tmp == NULL) { /* Couldn't get space, so use the slower algorithm that doesn't need a temporary array. */ __set_errno (save); _quicksort (b, n, s, cmp); } else { __set_errno (save); msort_with_tmp (b, n, s, cmp, tmp); free (tmp); } } }