sort.odin 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. package slice
  2. import "intrinsics"
  3. _ :: intrinsics;
  4. ORD :: intrinsics.type_is_ordered;
  5. Ordering :: enum {
  6. Less = -1,
  7. Equal = 0,
  8. Greater = +1,
  9. }
  10. cmp :: proc(a, b: $E) -> Ordering where ORD(E) {
  11. switch {
  12. case a < b:
  13. return .Less;
  14. case a > b:
  15. return .Greater;
  16. }
  17. return .Equal;
  18. }
  19. cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) {
  20. return proc(a, b: E) -> Ordering {
  21. switch {
  22. case a < b:
  23. return .Less;
  24. case a > b:
  25. return .Greater;
  26. }
  27. return .Equal;
  28. };
  29. }
  30. // sort sorts a slice
  31. // This sort is not guaranteed to be stable
  32. sort :: proc(data: $T/[]$E) where ORD(E) {
  33. when size_of(E) != 0 {
  34. if n := len(data); n > 1 {
  35. _quick_sort(data, 0, n, _max_depth(n));
  36. }
  37. }
  38. }
  39. // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  40. // This sort is not guaranteed to be stable
  41. sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  42. when size_of(E) != 0 {
  43. if n := len(data); n > 1 {
  44. _quick_sort_less(data, 0, n, _max_depth(n), less);
  45. }
  46. }
  47. }
  48. sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  49. when size_of(E) != 0 {
  50. if n := len(data); n > 1 {
  51. _quick_sort_cmp(data, 0, n, _max_depth(n), cmp);
  52. }
  53. }
  54. }
  55. is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
  56. for i := len(array)-1; i > 0; i -= 1 {
  57. if array[i] < array[i-1] {
  58. return false;
  59. }
  60. }
  61. return true;
  62. }
  63. is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
  64. for i := len(array)-1; i > 0; i -= 1 {
  65. if less(array[i], array[i-1]) {
  66. return false;
  67. }
  68. }
  69. return true;
  70. }
  71. is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
  72. for i := len(array)-1; i > 0; i -= 1 {
  73. if cmp(array[i], array[i-1]) == .Equal {
  74. return false;
  75. }
  76. }
  77. return true;
  78. }
  79. reverse_sort :: proc(data: $T/[]$E) where ORD(E) {
  80. sort_by(data, proc(i, j: E) -> bool {
  81. return j < i;
  82. });
  83. }
  84. reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) where ORD(E) {
  85. context._internal = rawptr(less);
  86. sort_by(data, proc(i, j: E) -> bool {
  87. k := (proc(i, j: E) -> bool)(context._internal);
  88. return k(j, i);
  89. });
  90. }
  91. reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) where ORD(E) {
  92. context._internal = rawptr(cmp);
  93. sort_by_cmp(data, proc(i, j: E) -> Ordering {
  94. k := (proc(i, j: E) -> Ordering)(context._internal);
  95. return k(j, i);
  96. });
  97. }
  98. // TODO(bill): Should `sort_by_key` exist or is `sort_by` more than enough?
  99. sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  100. context._internal = rawptr(key);
  101. sort_by(data, proc(i, j: E) -> bool {
  102. k := (proc(E) -> K)(context._internal);
  103. return k(i) < k(j);
  104. });
  105. }
  106. reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  107. context._internal = rawptr(key);
  108. sort_by(data, proc(i, j: E) -> bool {
  109. k := (proc(E) -> K)(context._internal);
  110. return k(j) < k(i);
  111. });
  112. }
  113. is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K) {
  114. for i := len(array)-1; i > 0; i -= 1 {
  115. if key(array[i]) < key(array[i-1]) {
  116. return false;
  117. }
  118. }
  119. return true;
  120. }
  121. @(private)
  122. _max_depth :: proc(n: int) -> int { // 2*ceil(log2(n+1))
  123. depth: int;
  124. for i := n; i > 0; i >>= 1 {
  125. depth += 1;
  126. }
  127. return depth * 2;
  128. }
  129. @(private)
  130. _quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) {
  131. median3 :: proc(data: T, m1, m0, m2: int) {
  132. if data[m1] < data[m0] {
  133. swap(data, m1, m0);
  134. }
  135. if data[m2] < data[m1] {
  136. swap(data, m2, m1);
  137. if data[m1] < data[m0] {
  138. swap(data, m1, m0);
  139. }
  140. }
  141. }
  142. do_pivot :: proc(data: T, lo, hi: int) -> (midlo, midhi: int) {
  143. m := int(uint(lo+hi)>>1);
  144. if hi-lo > 40 {
  145. s := (hi-lo)/8;
  146. median3(data, lo, lo+s, lo+s*2);
  147. median3(data, m, m-s, m+s);
  148. median3(data, hi-1, hi-1-s, hi-1-s*2);
  149. }
  150. median3(data, lo, m, hi-1);
  151. pivot := lo;
  152. a, c := lo+1, hi-1;
  153. for ; a < c && data[a] < data[pivot]; a += 1 {
  154. }
  155. b := a;
  156. for {
  157. for ; b < c && !(data[pivot] < data[b]); b += 1 { // data[b] <= pivot
  158. }
  159. for ; b < c && data[pivot] < data[c-1]; c -=1 { // data[c-1] > pivot
  160. }
  161. if b >= c {
  162. break;
  163. }
  164. swap(data, b, c-1);
  165. b += 1;
  166. c -= 1;
  167. }
  168. protect := hi-c < 5;
  169. if !protect && hi-c < (hi-lo)/4 {
  170. dups := 0;
  171. if !(data[pivot] < data[hi-1]) {
  172. swap(data, c, hi-1);
  173. c += 1;
  174. dups += 1;
  175. }
  176. if !(data[b-1] < data[pivot]) {
  177. b -= 1;
  178. dups += 1;
  179. }
  180. if !(data[m] < data[pivot]) {
  181. swap(data, m, b-1);
  182. b -= 1;
  183. dups += 1;
  184. }
  185. protect = dups > 1;
  186. }
  187. if protect {
  188. for {
  189. for ; a < b && !(data[b-1] < data[pivot]); b -= 1 {
  190. }
  191. for ; a < b && data[a] < data[pivot]; a += 1 {
  192. }
  193. if a >= b {
  194. break;
  195. }
  196. swap(data, a, b-1);
  197. a += 1;
  198. b -= 1;
  199. }
  200. }
  201. swap(data, pivot, b-1);
  202. return b-1, c;
  203. }
  204. a, b, max_depth := a, b, max_depth;
  205. if b-a > 12 { // only use shell sort for lengths <= 12
  206. if max_depth == 0 {
  207. _heap_sort(data, a, b);
  208. return;
  209. }
  210. max_depth -= 1;
  211. mlo, mhi := do_pivot(data, a, b);
  212. if mlo-a < b-mhi {
  213. _quick_sort(data, a, mlo, max_depth);
  214. a = mhi;
  215. } else {
  216. _quick_sort(data, mhi, b, max_depth);
  217. b = mlo;
  218. }
  219. }
  220. if b-a > 1 {
  221. // Shell short with gap 6
  222. for i in a+6..<b {
  223. if data[i] < data[i-6] {
  224. swap(data, i, i-6);
  225. }
  226. }
  227. _insertion_sort(data, a, b);
  228. }
  229. }
  230. @(private)
  231. _insertion_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) {
  232. for i in a+1..<b {
  233. for j := i; j > a && data[j] < data[j-1]; j -= 1 {
  234. swap(data, j, j-1);
  235. }
  236. }
  237. }
  238. @(private)
  239. _heap_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) {
  240. sift_down :: proc(data: T, lo, hi, first: int) {
  241. root := lo;
  242. for {
  243. child := 2*root + 1;
  244. if child >= hi {
  245. break;
  246. }
  247. if child+1 < hi && data[first+child] < data[first+child+1] {
  248. child += 1;
  249. }
  250. if !(data[first+root] < data[first+child]) {
  251. return;
  252. }
  253. swap(data, first+root, first+child);
  254. root = child;
  255. }
  256. }
  257. first, lo, hi := a, 0, b-a;
  258. for i := (hi-1)/2; i >= 0; i -= 1 {
  259. sift_down(data, i, hi, first);
  260. }
  261. for i := hi-1; i >= 0; i -= 1 {
  262. swap(data, first, first+i);
  263. sift_down(data, lo, i, first);
  264. }
  265. }
  266. @(private)
  267. _quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E) -> bool) {
  268. median3 :: proc(data: T, m1, m0, m2: int, less: proc(i, j: E) -> bool) {
  269. if less(data[m1], data[m0]) {
  270. swap(data, m1, m0);
  271. }
  272. if less(data[m2], data[m1]) {
  273. swap(data, m2, m1);
  274. if less(data[m1], data[m0]) {
  275. swap(data, m1, m0);
  276. }
  277. }
  278. }
  279. do_pivot :: proc(data: T, lo, hi: int, less: proc(i, j: E) -> bool) -> (midlo, midhi: int) {
  280. m := int(uint(lo+hi)>>1);
  281. if hi-lo > 40 {
  282. s := (hi-lo)/8;
  283. median3(data, lo, lo+s, lo+s*2, less);
  284. median3(data, m, m-s, m+s, less);
  285. median3(data, hi-1, hi-1-s, hi-1-s*2, less);
  286. }
  287. median3(data, lo, m, hi-1, less);
  288. pivot := lo;
  289. a, c := lo+1, hi-1;
  290. for ; a < c && less(data[a], data[pivot]); a += 1 {
  291. }
  292. b := a;
  293. for {
  294. for ; b < c && !less(data[pivot], data[b]); b += 1 { // data[b] <= pivot
  295. }
  296. for ; b < c && less(data[pivot], data[c-1]); c -=1 { // data[c-1] > pivot
  297. }
  298. if b >= c {
  299. break;
  300. }
  301. swap(data, b, c-1);
  302. b += 1;
  303. c -= 1;
  304. }
  305. protect := hi-c < 5;
  306. if !protect && hi-c < (hi-lo)/4 {
  307. dups := 0;
  308. if !less(data[pivot], data[hi-1]) {
  309. swap(data, c, hi-1);
  310. c += 1;
  311. dups += 1;
  312. }
  313. if !less(data[b-1], data[pivot]) {
  314. b -= 1;
  315. dups += 1;
  316. }
  317. if !less(data[m], data[pivot]) {
  318. swap(data, m, b-1);
  319. b -= 1;
  320. dups += 1;
  321. }
  322. protect = dups > 1;
  323. }
  324. if protect {
  325. for {
  326. for ; a < b && !less(data[b-1], data[pivot]); b -= 1 {
  327. }
  328. for ; a < b && less(data[a], data[pivot]); a += 1 {
  329. }
  330. if a >= b {
  331. break;
  332. }
  333. swap(data, a, b-1);
  334. a += 1;
  335. b -= 1;
  336. }
  337. }
  338. swap(data, pivot, b-1);
  339. return b-1, c;
  340. }
  341. a, b, max_depth := a, b, max_depth;
  342. if b-a > 12 { // only use shell sort for lengths <= 12
  343. if max_depth == 0 {
  344. _heap_sort_less(data, a, b, less);
  345. return;
  346. }
  347. max_depth -= 1;
  348. mlo, mhi := do_pivot(data, a, b, less);
  349. if mlo-a < b-mhi {
  350. _quick_sort_less(data, a, mlo, max_depth, less);
  351. a = mhi;
  352. } else {
  353. _quick_sort_less(data, mhi, b, max_depth, less);
  354. b = mlo;
  355. }
  356. }
  357. if b-a > 1 {
  358. // Shell short with gap 6
  359. for i in a+6..<b {
  360. if less(data[i], data[i-6]) {
  361. swap(data, i, i-6);
  362. }
  363. }
  364. _insertion_sort_less(data, a, b, less);
  365. }
  366. }
  367. @(private)
  368. _insertion_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) {
  369. for i in a+1..<b {
  370. for j := i; j > a && less(data[j], data[j-1]); j -= 1 {
  371. swap(data, j, j-1);
  372. }
  373. }
  374. }
  375. @(private)
  376. _heap_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) {
  377. sift_down :: proc(data: T, lo, hi, first: int, less: proc(i, j: E) -> bool) {
  378. root := lo;
  379. for {
  380. child := 2*root + 1;
  381. if child >= hi {
  382. break;
  383. }
  384. if child+1 < hi && less(data[first+child], data[first+child+1]) {
  385. child += 1;
  386. }
  387. if !less(data[first+root], data[first+child]) {
  388. return;
  389. }
  390. swap(data, first+root, first+child);
  391. root = child;
  392. }
  393. }
  394. first, lo, hi := a, 0, b-a;
  395. for i := (hi-1)/2; i >= 0; i -= 1 {
  396. sift_down(data, i, hi, first, less);
  397. }
  398. for i := hi-1; i >= 0; i -= 1 {
  399. swap(data, first, first+i);
  400. sift_down(data, lo, i, first, less);
  401. }
  402. }
  403. @(private)
  404. _quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) -> Ordering) {
  405. median3 :: proc(data: T, m1, m0, m2: int, cmp: proc(i, j: E) -> Ordering) {
  406. if cmp(data[m1], data[m0]) == .Less {
  407. swap(data, m1, m0);
  408. }
  409. if cmp(data[m2], data[m1]) == .Less {
  410. swap(data, m2, m1);
  411. if cmp(data[m1], data[m0]) == .Less {
  412. swap(data, m1, m0);
  413. }
  414. }
  415. }
  416. do_pivot :: proc(data: T, lo, hi: int, cmp: proc(i, j: E) -> Ordering) -> (midlo, midhi: int) {
  417. m := int(uint(lo+hi)>>1);
  418. if hi-lo > 40 {
  419. s := (hi-lo)/8;
  420. median3(data, lo, lo+s, lo+s*2, cmp);
  421. median3(data, m, m-s, m+s, cmp);
  422. median3(data, hi-1, hi-1-s, hi-1-s*2, cmp);
  423. }
  424. median3(data, lo, m, hi-1, cmp);
  425. pivot := lo;
  426. a, c := lo+1, hi-1;
  427. for ; a < c && cmp(data[a], data[pivot]) == .Less; a += 1 {
  428. }
  429. b := a;
  430. for {
  431. for ; b < c && cmp(data[pivot], data[b]) >= .Equal; b += 1 { // data[b] <= pivot
  432. }
  433. for ; b < c && cmp(data[pivot], data[c-1]) == .Less; c -=1 { // data[c-1] > pivot
  434. }
  435. if b >= c {
  436. break;
  437. }
  438. swap(data, b, c-1);
  439. b += 1;
  440. c -= 1;
  441. }
  442. protect := hi-c < 5;
  443. if !protect && hi-c < (hi-lo)/4 {
  444. dups := 0;
  445. if cmp(data[pivot], data[hi-1]) != .Less {
  446. swap(data, c, hi-1);
  447. c += 1;
  448. dups += 1;
  449. }
  450. if cmp(data[b-1], data[pivot]) != .Less {
  451. b -= 1;
  452. dups += 1;
  453. }
  454. if cmp(data[m], data[pivot]) != .Less {
  455. swap(data, m, b-1);
  456. b -= 1;
  457. dups += 1;
  458. }
  459. protect = dups > 1;
  460. }
  461. if protect {
  462. for {
  463. for ; a < b && cmp(data[b-1], data[pivot]) >= .Equal; b -= 1 {
  464. }
  465. for ; a < b && cmp(data[a], data[pivot]) == .Less; a += 1 {
  466. }
  467. if a >= b {
  468. break;
  469. }
  470. swap(data, a, b-1);
  471. a += 1;
  472. b -= 1;
  473. }
  474. }
  475. swap(data, pivot, b-1);
  476. return b-1, c;
  477. }
  478. a, b, max_depth := a, b, max_depth;
  479. if b-a > 12 { // only use shell sort for lengths <= 12
  480. if max_depth == 0 {
  481. _heap_sort_cmp(data, a, b, cmp);
  482. return;
  483. }
  484. max_depth -= 1;
  485. mlo, mhi := do_pivot(data, a, b, cmp);
  486. if mlo-a < b-mhi {
  487. _quick_sort_cmp(data, a, mlo, max_depth, cmp);
  488. a = mhi;
  489. } else {
  490. _quick_sort_cmp(data, mhi, b, max_depth, cmp);
  491. b = mlo;
  492. }
  493. }
  494. if b-a > 1 {
  495. // Shell short with gap 6
  496. for i in a+6..<b {
  497. if cmp(data[i], data[i-6]) == .Less {
  498. swap(data, i, i-6);
  499. }
  500. }
  501. _insertion_sort_cmp(data, a, b, cmp);
  502. }
  503. }
  504. @(private)
  505. _insertion_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) {
  506. for i in a+1..<b {
  507. for j := i; j > a && cmp(data[j], data[j-1]) == .Less; j -= 1 {
  508. swap(data, j, j-1);
  509. }
  510. }
  511. }
  512. @(private)
  513. _heap_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) {
  514. sift_down :: proc(data: T, lo, hi, first: int, cmp: proc(i, j: E) -> Ordering) {
  515. root := lo;
  516. for {
  517. child := 2*root + 1;
  518. if child >= hi {
  519. break;
  520. }
  521. if child+1 < hi && cmp(data[first+child], data[first+child+1]) == .Less {
  522. child += 1;
  523. }
  524. if cmp(data[first+root], data[first+child]) >= .Equal {
  525. return;
  526. }
  527. swap(data, first+root, first+child);
  528. root = child;
  529. }
  530. }
  531. first, lo, hi := a, 0, b-a;
  532. for i := (hi-1)/2; i >= 0; i -= 1 {
  533. sift_down(data, i, hi, first, cmp);
  534. }
  535. for i := hi-1; i >= 0; i -= 1 {
  536. swap(data, first, first+i);
  537. sift_down(data, lo, i, first, cmp);
  538. }
  539. }