sort.odin 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package slice
  2. Ordering :: enum {
  3. Less = -1,
  4. Equal = 0,
  5. Greater = +1,
  6. }
  7. cmp :: proc(a, b: $E) -> Ordering where ORD(E) {
  8. switch {
  9. case a < b:
  10. return .Less
  11. case a > b:
  12. return .Greater
  13. }
  14. return .Equal
  15. }
  16. cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) {
  17. return proc(a, b: E) -> Ordering {
  18. switch {
  19. case a < b:
  20. return .Less
  21. case a > b:
  22. return .Greater
  23. }
  24. return .Equal
  25. }
  26. }
  27. // sort sorts a slice
  28. // This sort is not guaranteed to be stable
  29. sort :: proc(data: $T/[]$E) where ORD(E) {
  30. when size_of(E) != 0 {
  31. if n := len(data); n > 1 {
  32. _quick_sort_general(data, 0, n, _max_depth(n), struct{}{}, .Ordered)
  33. }
  34. }
  35. }
  36. // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  37. // This sort is not guaranteed to be stable
  38. sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  39. when size_of(E) != 0 {
  40. if n := len(data); n > 1 {
  41. _quick_sort_general(data, 0, n, _max_depth(n), less, .Less)
  42. }
  43. }
  44. }
  45. sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  46. when size_of(E) != 0 {
  47. if n := len(data); n > 1 {
  48. _quick_sort_general(data, 0, n, _max_depth(n), cmp, .Cmp)
  49. }
  50. }
  51. }
  52. // stable_sort sorts a slice
  53. stable_sort :: proc(data: $T/[]$E) where ORD(E) {
  54. when size_of(E) != 0 {
  55. if n := len(data); n > 1 {
  56. _stable_sort_general(data, struct{}{}, .Ordered)
  57. }
  58. }
  59. }
  60. // stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  61. stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  62. when size_of(E) != 0 {
  63. if n := len(data); n > 1 {
  64. _stable_sort_general(data, less, .Less)
  65. }
  66. }
  67. }
  68. stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  69. when size_of(E) != 0 {
  70. if n := len(data); n > 1 {
  71. _stable_sort_general(data, cmp, .Cmp)
  72. }
  73. }
  74. }
  75. is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
  76. for i := len(array)-1; i > 0; i -= 1 {
  77. if array[i] < array[i-1] {
  78. return false
  79. }
  80. }
  81. return true
  82. }
  83. is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
  84. for i := len(array)-1; i > 0; i -= 1 {
  85. if less(array[i], array[i-1]) {
  86. return false
  87. }
  88. }
  89. return true
  90. }
  91. is_sorted_by_cmp :: is_sorted_cmp
  92. is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
  93. for i := len(array)-1; i > 0; i -= 1 {
  94. if cmp(array[i], array[i-1]) == .Less {
  95. return false
  96. }
  97. }
  98. return true
  99. }
  100. reverse_sort :: proc(data: $T/[]$E) where ORD(E) {
  101. sort_by(data, proc(i, j: E) -> bool {
  102. return j < i
  103. })
  104. }
  105. reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) where ORD(E) {
  106. context._internal = rawptr(less)
  107. sort_by(data, proc(i, j: E) -> bool {
  108. k := (proc(i, j: E) -> bool)(context._internal)
  109. return k(j, i)
  110. })
  111. }
  112. reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) where ORD(E) {
  113. context._internal = rawptr(cmp)
  114. sort_by_cmp(data, proc(i, j: E) -> Ordering {
  115. k := (proc(i, j: E) -> Ordering)(context._internal)
  116. return k(j, i)
  117. })
  118. }
  119. // TODO(bill): Should `sort_by_key` exist or is `sort_by` more than enough?
  120. sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  121. context._internal = rawptr(key)
  122. sort_by(data, proc(i, j: E) -> bool {
  123. k := (proc(E) -> K)(context._internal)
  124. return k(i) < k(j)
  125. })
  126. }
  127. reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  128. context._internal = rawptr(key)
  129. sort_by(data, proc(i, j: E) -> bool {
  130. k := (proc(E) -> K)(context._internal)
  131. return k(j) < k(i)
  132. })
  133. }
  134. is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K) {
  135. for i := len(array)-1; i > 0; i -= 1 {
  136. if key(array[i]) < key(array[i-1]) {
  137. return false
  138. }
  139. }
  140. return true
  141. }
  142. @(private)
  143. _max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1))
  144. for i := n; i > 0; i >>= 1 {
  145. depth += 1
  146. }
  147. return depth * 2
  148. }