1
0

qsort.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /* Copyright (C) 2011 by Valentin Ochs
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. /* Minor changes by Rich Felker for integration in musl, 2011-04-27. */
  22. /* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1).
  23. Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */
  24. #define _BSD_SOURCE
  25. #include <stdint.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include "atomic.h"
  29. #define ntz(x) a_ctz_l((x))
  30. typedef int (*cmpfun)(const void *, const void *, void *);
  31. static inline int pntz(size_t p[2]) {
  32. int r = ntz(p[0] - 1);
  33. if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
  34. return r;
  35. }
  36. return 0;
  37. }
  38. static void cycle(size_t width, unsigned char* ar[], int n)
  39. {
  40. unsigned char tmp[256];
  41. size_t l;
  42. int i;
  43. if(n < 2) {
  44. return;
  45. }
  46. ar[n] = tmp;
  47. while(width) {
  48. l = sizeof(tmp) < width ? sizeof(tmp) : width;
  49. memcpy(ar[n], ar[0], l);
  50. for(i = 0; i < n; i++) {
  51. memcpy(ar[i], ar[i + 1], l);
  52. ar[i] += l;
  53. }
  54. width -= l;
  55. }
  56. }
  57. /* shl() and shr() need n > 0 */
  58. static inline void shl(size_t p[2], int n)
  59. {
  60. if(n >= 8 * sizeof(size_t)) {
  61. n -= 8 * sizeof(size_t);
  62. p[1] = p[0];
  63. p[0] = 0;
  64. }
  65. p[1] <<= n;
  66. p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
  67. p[0] <<= n;
  68. }
  69. static inline void shr(size_t p[2], int n)
  70. {
  71. if(n >= 8 * sizeof(size_t)) {
  72. n -= 8 * sizeof(size_t);
  73. p[0] = p[1];
  74. p[1] = 0;
  75. }
  76. p[0] >>= n;
  77. p[0] |= p[1] << (sizeof(size_t) * 8 - n);
  78. p[1] >>= n;
  79. }
  80. static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[])
  81. {
  82. unsigned char *rt, *lf;
  83. unsigned char *ar[14 * sizeof(size_t) + 1];
  84. int i = 1;
  85. ar[0] = head;
  86. while(pshift > 1) {
  87. rt = head - width;
  88. lf = head - width - lp[pshift - 2];
  89. if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) {
  90. break;
  91. }
  92. if(cmp(lf, rt, arg) >= 0) {
  93. ar[i++] = lf;
  94. head = lf;
  95. pshift -= 1;
  96. } else {
  97. ar[i++] = rt;
  98. head = rt;
  99. pshift -= 2;
  100. }
  101. }
  102. cycle(width, ar, i);
  103. }
  104. static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[])
  105. {
  106. unsigned char *stepson,
  107. *rt, *lf;
  108. size_t p[2];
  109. unsigned char *ar[14 * sizeof(size_t) + 1];
  110. int i = 1;
  111. int trail;
  112. p[0] = pp[0];
  113. p[1] = pp[1];
  114. ar[0] = head;
  115. while(p[0] != 1 || p[1] != 0) {
  116. stepson = head - lp[pshift];
  117. if(cmp(stepson, ar[0], arg) <= 0) {
  118. break;
  119. }
  120. if(!trusty && pshift > 1) {
  121. rt = head - width;
  122. lf = head - width - lp[pshift - 2];
  123. if(cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) {
  124. break;
  125. }
  126. }
  127. ar[i++] = stepson;
  128. head = stepson;
  129. trail = pntz(p);
  130. shr(p, trail);
  131. pshift += trail;
  132. trusty = 0;
  133. }
  134. if(!trusty) {
  135. cycle(width, ar, i);
  136. sift(head, width, cmp, arg, pshift, lp);
  137. }
  138. }
  139. void __qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg)
  140. {
  141. size_t lp[12*sizeof(size_t)];
  142. size_t i, size = width * nel;
  143. unsigned char *head, *high;
  144. size_t p[2] = {1, 0};
  145. int pshift = 1;
  146. int trail;
  147. if (!size) return;
  148. head = base;
  149. high = head + size - width;
  150. /* Precompute Leonardo numbers, scaled by element width */
  151. for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++);
  152. while(head < high) {
  153. if((p[0] & 3) == 3) {
  154. sift(head, width, cmp, arg, pshift, lp);
  155. shr(p, 2);
  156. pshift += 2;
  157. } else {
  158. if(lp[pshift - 1] >= high - head) {
  159. trinkle(head, width, cmp, arg, p, pshift, 0, lp);
  160. } else {
  161. sift(head, width, cmp, arg, pshift, lp);
  162. }
  163. if(pshift == 1) {
  164. shl(p, 1);
  165. pshift = 0;
  166. } else {
  167. shl(p, pshift - 1);
  168. pshift = 1;
  169. }
  170. }
  171. p[0] |= 1;
  172. head += width;
  173. }
  174. trinkle(head, width, cmp, arg, p, pshift, 0, lp);
  175. while(pshift != 1 || p[0] != 1 || p[1] != 0) {
  176. if(pshift <= 1) {
  177. trail = pntz(p);
  178. shr(p, trail);
  179. pshift += trail;
  180. } else {
  181. shl(p, 2);
  182. pshift -= 2;
  183. p[0] ^= 7;
  184. shr(p, 1);
  185. trinkle(head - lp[pshift] - width, width, cmp, arg, p, pshift + 1, 1, lp);
  186. shl(p, 1);
  187. p[0] |= 1;
  188. trinkle(head - width, width, cmp, arg, p, pshift, 1, lp);
  189. }
  190. head -= width;
  191. }
  192. }
  193. weak_alias(__qsort_r, qsort_r);