sort.odin 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. package slice
  2. import "intrinsics"
  3. _ :: intrinsics;
  4. ORD :: intrinsics.type_is_ordered;
  5. // sort sorts a slice
  6. // This sort is not guaranteed to be stable
  7. sort :: proc(data: $T/[]$E) where ORD(E) {
  8. when size_of(E) != 0 {
  9. if n := len(data); n > 1 {
  10. _quick_sort(data, 0, n, _max_depth(n));
  11. }
  12. }
  13. }
  14. // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  15. // This sort is not guaranteed to be stable
  16. sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  17. when size_of(E) != 0 {
  18. if n := len(data); n > 1 {
  19. _quick_sort_proc(data, 0, n, _max_depth(n), less);
  20. }
  21. }
  22. }
  23. is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
  24. for i := len(array)-1; i > 0; i -= 1 {
  25. if array[i] < array[i-1] {
  26. return false;
  27. }
  28. }
  29. return true;
  30. }
  31. is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
  32. for i := len(array)-1; i > 0; i -= 1 {
  33. if less(array[i], array[i-1]) {
  34. return false;
  35. }
  36. }
  37. return true;
  38. }
  39. reverse_sort :: proc(data: $T/[]$E) where ORD(E) {
  40. sort_by(data, proc(i, j: E) -> bool {
  41. return j < i;
  42. });
  43. }
  44. // TODO(bill): Should `sort_by_key` exist or is `sort_by` more than enough?
  45. sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  46. context._internal = rawptr(key);
  47. sort_by(data, proc(i, j: E) -> bool {
  48. k := (proc(E) -> K)(context._internal);
  49. return k(i) < k(j);
  50. });
  51. }
  52. reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  53. context._internal = rawptr(key);
  54. sort_by(data, proc(i, j: E) -> bool {
  55. k := (proc(E) -> K)(context._internal);
  56. return k(j) < k(i);
  57. });
  58. }
  59. is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K) {
  60. for i := len(array)-1; i > 0; i -= 1 {
  61. if key(array[i]) < key(array[i-1]) {
  62. return false;
  63. }
  64. }
  65. return true;
  66. }
  67. @(private)
  68. _max_depth :: proc(n: int) -> int { // 2*ceil(log2(n+1))
  69. depth: int;
  70. for i := n; i > 0; i >>= 1 {
  71. depth += 1;
  72. }
  73. return depth * 2;
  74. }
  75. @(private)
  76. _quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) {
  77. median3 :: proc(data: T, m1, m0, m2: int) {
  78. if data[m1] < data[m0] {
  79. swap(data, m1, m0);
  80. }
  81. if data[m2] < data[m1] {
  82. swap(data, m2, m1);
  83. if data[m1] < data[m0] {
  84. swap(data, m1, m0);
  85. }
  86. }
  87. }
  88. do_pivot :: proc(data: T, lo, hi: int) -> (midlo, midhi: int) {
  89. m := int(uint(lo+hi)>>1);
  90. if hi-lo > 40 {
  91. s := (hi-lo)/8;
  92. median3(data, lo, lo+s, lo+s*2);
  93. median3(data, m, m-s, m+s);
  94. median3(data, hi-1, hi-1-s, hi-1-s*2);
  95. }
  96. median3(data, lo, m, hi-1);
  97. pivot := lo;
  98. a, c := lo+1, hi-1;
  99. for ; a < c && data[a] < data[pivot]; a += 1 {
  100. }
  101. b := a;
  102. for {
  103. for ; b < c && !(data[pivot] < data[b]); b += 1 { // data[b] <= pivot
  104. }
  105. for ; b < c && data[pivot] < data[c-1]; c -=1 { // data[c-1] > pivot
  106. }
  107. if b >= c {
  108. break;
  109. }
  110. swap(data, b, c-1);
  111. b += 1;
  112. c -= 1;
  113. }
  114. protect := hi-c < 5;
  115. if !protect && hi-c < (hi-lo)/4 {
  116. dups := 0;
  117. if !(data[pivot] < data[hi-1]) {
  118. swap(data, c, hi-1);
  119. c += 1;
  120. dups += 1;
  121. }
  122. if !(data[b-1] < data[pivot]) {
  123. b -= 1;
  124. dups += 1;
  125. }
  126. if !(data[m] < data[pivot]) {
  127. swap(data, m, b-1);
  128. b -= 1;
  129. dups += 1;
  130. }
  131. protect = dups > 1;
  132. }
  133. if protect {
  134. for {
  135. for ; a < b && !(data[b-1] < data[pivot]); b -= 1 {
  136. }
  137. for ; a < b && data[a] < data[pivot]; a += 1 {
  138. }
  139. if a >= b {
  140. break;
  141. }
  142. swap(data, a, b-1);
  143. a += 1;
  144. b -= 1;
  145. }
  146. }
  147. swap(data, pivot, b-1);
  148. return b-1, c;
  149. }
  150. a, b, max_depth := a, b, max_depth;
  151. if b-a > 12 { // only use shell sort for lengths <= 12
  152. if max_depth == 0 {
  153. _heap_sort(data, a, b);
  154. return;
  155. }
  156. max_depth -= 1;
  157. mlo, mhi := do_pivot(data, a, b);
  158. if mlo-a < b-mhi {
  159. _quick_sort(data, a, mlo, max_depth);
  160. a = mhi;
  161. } else {
  162. _quick_sort(data, mhi, b, max_depth);
  163. b = mlo;
  164. }
  165. }
  166. if b-a > 1 {
  167. // Shell short with gap 6
  168. for i in a+6..<b {
  169. if data[i] < data[i-6] {
  170. swap(data, i, i-6);
  171. }
  172. }
  173. _insertion_sort(data, a, b);
  174. }
  175. }
  176. @(private)
  177. _insertion_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) {
  178. for i in a+1..<b {
  179. for j := i; j > a && data[j] < data[j-1]; j -= 1 {
  180. swap(data, j, j-1);
  181. }
  182. }
  183. }
  184. @(private)
  185. _heap_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) {
  186. sift_down :: proc(data: T, lo, hi, first: int) {
  187. root := lo;
  188. for {
  189. child := 2*root + 1;
  190. if child >= hi {
  191. break;
  192. }
  193. if child+1 < hi && data[first+child] < data[first+child+1] {
  194. child += 1;
  195. }
  196. if !(data[first+root] < data[first+child]) {
  197. return;
  198. }
  199. swap(data, first+root, first+child);
  200. root = child;
  201. }
  202. }
  203. first, lo, hi := a, 0, b-a;
  204. for i := (hi-1)/2; i >= 0; i -= 1 {
  205. sift_down(data, i, hi, first);
  206. }
  207. for i := hi-1; i >= 0; i -= 1 {
  208. swap(data, first, first+i);
  209. sift_down(data, lo, i, first);
  210. }
  211. }
  212. @(private)
  213. _quick_sort_proc :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E) -> bool) {
  214. median3 :: proc(data: T, m1, m0, m2: int, less: proc(i, j: E) -> bool) {
  215. if less(data[m1], data[m0]) {
  216. swap(data, m1, m0);
  217. }
  218. if less(data[m2], data[m1]) {
  219. swap(data, m2, m1);
  220. if less(data[m1], data[m0]) {
  221. swap(data, m1, m0);
  222. }
  223. }
  224. }
  225. do_pivot :: proc(data: T, lo, hi: int, less: proc(i, j: E) -> bool) -> (midlo, midhi: int) {
  226. m := int(uint(lo+hi)>>1);
  227. if hi-lo > 40 {
  228. s := (hi-lo)/8;
  229. median3(data, lo, lo+s, lo+s*2, less);
  230. median3(data, m, m-s, m+s, less);
  231. median3(data, hi-1, hi-1-s, hi-1-s*2, less);
  232. }
  233. median3(data, lo, m, hi-1, less);
  234. pivot := lo;
  235. a, c := lo+1, hi-1;
  236. for ; a < c && less(data[a], data[pivot]); a += 1 {
  237. }
  238. b := a;
  239. for {
  240. for ; b < c && !less(data[pivot], data[b]); b += 1 { // data[b] <= pivot
  241. }
  242. for ; b < c && less(data[pivot], data[c-1]); c -=1 { // data[c-1] > pivot
  243. }
  244. if b >= c {
  245. break;
  246. }
  247. swap(data, b, c-1);
  248. b += 1;
  249. c -= 1;
  250. }
  251. protect := hi-c < 5;
  252. if !protect && hi-c < (hi-lo)/4 {
  253. dups := 0;
  254. if !less(data[pivot], data[hi-1]) {
  255. swap(data, c, hi-1);
  256. c += 1;
  257. dups += 1;
  258. }
  259. if !less(data[b-1], data[pivot]) {
  260. b -= 1;
  261. dups += 1;
  262. }
  263. if !less(data[m], data[pivot]) {
  264. swap(data, m, b-1);
  265. b -= 1;
  266. dups += 1;
  267. }
  268. protect = dups > 1;
  269. }
  270. if protect {
  271. for {
  272. for ; a < b && !less(data[b-1], data[pivot]); b -= 1 {
  273. }
  274. for ; a < b && less(data[a], data[pivot]); a += 1 {
  275. }
  276. if a >= b {
  277. break;
  278. }
  279. swap(data, a, b-1);
  280. a += 1;
  281. b -= 1;
  282. }
  283. }
  284. swap(data, pivot, b-1);
  285. return b-1, c;
  286. }
  287. a, b, max_depth := a, b, max_depth;
  288. if b-a > 12 { // only use shell sort for lengths <= 12
  289. if max_depth == 0 {
  290. _heap_sort_proc(data, a, b, less);
  291. return;
  292. }
  293. max_depth -= 1;
  294. mlo, mhi := do_pivot(data, a, b, less);
  295. if mlo-a < b-mhi {
  296. _quick_sort_proc(data, a, mlo, max_depth, less);
  297. a = mhi;
  298. } else {
  299. _quick_sort_proc(data, mhi, b, max_depth, less);
  300. b = mlo;
  301. }
  302. }
  303. if b-a > 1 {
  304. // Shell short with gap 6
  305. for i in a+6..<b {
  306. if less(data[i], data[i-6]) {
  307. swap(data, i, i-6);
  308. }
  309. }
  310. _insertion_sort_proc(data, a, b, less);
  311. }
  312. }
  313. @(private)
  314. _insertion_sort_proc :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) {
  315. for i in a+1..<b {
  316. for j := i; j > a && less(data[j], data[j-1]); j -= 1 {
  317. swap(data, j, j-1);
  318. }
  319. }
  320. }
  321. @(private)
  322. _heap_sort_proc :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) {
  323. sift_down :: proc(data: T, lo, hi, first: int, less: proc(i, j: E) -> bool) {
  324. root := lo;
  325. for {
  326. child := 2*root + 1;
  327. if child >= hi {
  328. break;
  329. }
  330. if child+1 < hi && less(data[first+child], data[first+child+1]) {
  331. child += 1;
  332. }
  333. if !less(data[first+root], data[first+child]) {
  334. return;
  335. }
  336. swap(data, first+root, first+child);
  337. root = child;
  338. }
  339. }
  340. first, lo, hi := a, 0, b-a;
  341. for i := (hi-1)/2; i >= 0; i -= 1 {
  342. sift_down(data, i, hi, first, less);
  343. }
  344. for i := hi-1; i >= 0; i -= 1 {
  345. swap(data, first, first+i);
  346. sift_down(data, lo, i, first, less);
  347. }
  348. }