qsort.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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. #include <assert.h>
  29. void qsort (void *base,
  30. size_t nel,
  31. size_t width,
  32. int (*comp)(const void *, const void *))
  33. {
  34. size_t wgap, i, j, k;
  35. char *a, *b, tmp;
  36. /* Note: still conceivable that nel * width could overflow! */
  37. assert(width > 0);
  38. if (nel > 1) {
  39. for (wgap = 0; ++wgap < (nel-1)/3 ; wgap *= 3) {}
  40. wgap *= width;
  41. nel *= width; /* convert nel to 'wnel' */
  42. do {
  43. for (i = wgap; i < nel; i += width) {
  44. for (j = i - wgap; ;j -= wgap) {
  45. a = j + ((char *)base);
  46. b = a + wgap;
  47. if ( (*comp)(a, b) <= 0 ) {
  48. break;
  49. }
  50. k = width;
  51. do {
  52. tmp = *a;
  53. *a++ = *b;
  54. *b++ = tmp;
  55. } while ( --k );
  56. if (j < wgap) {
  57. break;
  58. }
  59. }
  60. }
  61. wgap = (wgap - width)/3;
  62. } while (wgap);
  63. }
  64. }