qsort.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /* +++Date last modified: 05-Jul-1997 */
  2. /*
  3. ** ssort() -- Fast, small, qsort()-compatible Shell sort
  4. **
  5. ** by Ray Gardner, public domain 5/90
  6. */
  7. /*
  8. * Manuel Novoa III Dec 2000
  9. *
  10. * There were several problems with the qsort code contained in uClibc.
  11. * It assumed sizeof(int) was 2 and sizeof(long) was 4. It then had three
  12. * seperate quiicksort routines based on the width of the data passed: 2, 4,
  13. * or anything else <= 128. If the width was > 128, it returned -1 (although
  14. * qsort should not return a value) and did no sorting. On i386 with
  15. * -Os -fomit-frame-pointer -ffunction-sections, the text segment of qsort.o
  16. * was 1358 bytes, with an additional 4 bytes in bss.
  17. *
  18. * I decided to completely replace the existing code with a small
  19. * implementation of a shell sort. It is a drop-in replacement for the
  20. * standard qsort and, with the same gcc flags as above, the text segment
  21. * size on i386 is only 183 bytes.
  22. *
  23. * Grabbed original file rg_ssort.c from snippets.org.
  24. * Modified original code to avoid possible overflow in wgap calculation.
  25. * Modified wgap calculation in loop and eliminated variables gap and wnel.
  26. */
  27. #include <stdlib.h>
  28. void qsort (void *base,
  29. size_t nel,
  30. size_t width,
  31. int (*comp)(const void *, const void *))
  32. {
  33. size_t wgap, i, j, k;
  34. char *a, *b, tmp;
  35. #if 0
  36. /* Note: still conceivable that nel * width could overflow! */
  37. assert(width > 0);
  38. #endif
  39. if (nel > 1) {
  40. for (wgap = 0; ++wgap < (nel-1)/3 ; wgap *= 3) {}
  41. wgap *= width;
  42. nel *= width; /* convert nel to 'wnel' */
  43. do {
  44. for (i = wgap; i < nel; i += width) {
  45. for (j = i - wgap; ;j -= wgap) {
  46. a = j + ((char *)base);
  47. b = a + wgap;
  48. if ( (*comp)(a, b) <= 0 ) {
  49. break;
  50. }
  51. k = width;
  52. do {
  53. tmp = *a;
  54. *a++ = *b;
  55. *b++ = tmp;
  56. } while ( --k );
  57. if (j < wgap) {
  58. break;
  59. }
  60. }
  61. }
  62. wgap = (wgap - width)/3;
  63. } while (wgap);
  64. }
  65. }