sort.odin 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package slice
  2. Ordering :: enum {
  3. Less = -1,
  4. Equal = 0,
  5. Greater = +1,
  6. }
  7. @(require_results)
  8. cmp :: proc(a, b: $E) -> Ordering where ORD(E) {
  9. switch {
  10. case a < b:
  11. return .Less
  12. case a > b:
  13. return .Greater
  14. }
  15. return .Equal
  16. }
  17. @(require_results)
  18. cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) {
  19. return proc(a, b: E) -> Ordering {
  20. switch {
  21. case a < b:
  22. return .Less
  23. case a > b:
  24. return .Greater
  25. }
  26. return .Equal
  27. }
  28. }
  29. // sort sorts a slice
  30. // This sort is not guaranteed to be stable
  31. sort :: proc(data: $T/[]$E) where ORD(E) {
  32. when size_of(E) != 0 {
  33. if n := len(data); n > 1 {
  34. _quick_sort_general(data, 0, n, _max_depth(n), struct{}{}, .Ordered)
  35. }
  36. }
  37. }
  38. sort_by_indices :: proc{ sort_by_indices_allocate, _sort_by_indices}
  39. sort_by_indices_allocate :: proc(data: $T/[]$E, indices: []int, allocator := context.allocator) -> (sorted: T) {
  40. assert(len(data) == len(indices))
  41. sorted = make(T, len(data), allocator)
  42. for v, i in indices {
  43. sorted[i] = data[v]
  44. }
  45. return
  46. }
  47. _sort_by_indices :: proc(data, sorted: $T/[]$E, indices: []int) {
  48. assert(len(data) == len(indices))
  49. assert(len(data) == len(sorted))
  50. for v, i in indices {
  51. sorted[i] = data[v]
  52. }
  53. }
  54. sort_by_indices_overwrite :: proc(data: $T/[]$E, indices: []int) {
  55. assert(len(data) == len(indices))
  56. temp := make([]E, len(data), context.allocator)
  57. defer delete(temp)
  58. for v, i in indices {
  59. temp[i] = data[v]
  60. }
  61. swap_with_slice(data, temp)
  62. }
  63. // sort sorts a slice and returns a slice of the original indices
  64. // This sort is not guaranteed to be stable
  65. sort_with_indices :: proc(data: $T/[]$E, allocator := context.allocator) -> (indices: []int) where ORD(E) {
  66. indices = make([]int, len(data), allocator)
  67. when size_of(E) != 0 {
  68. if n := len(data); n > 1 {
  69. for _, idx in indices {
  70. indices[idx] = idx
  71. }
  72. _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), struct{}{}, .Ordered)
  73. }
  74. return indices
  75. }
  76. return indices
  77. }
  78. // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  79. // This sort is not guaranteed to be stable
  80. sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  81. when size_of(E) != 0 {
  82. if n := len(data); n > 1 {
  83. _quick_sort_general(data, 0, n, _max_depth(n), less, .Less)
  84. }
  85. }
  86. }
  87. // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  88. // This sort is not guaranteed to be stable
  89. sort_by_with_indices :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool, allocator := context.allocator) -> (indices : []int) {
  90. indices = make([]int, len(data), allocator)
  91. when size_of(E) != 0 {
  92. if n := len(data); n > 1 {
  93. for _, idx in indices {
  94. indices[idx] = idx
  95. }
  96. _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), less, .Less)
  97. return indices
  98. }
  99. }
  100. return indices
  101. }
  102. sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  103. when size_of(E) != 0 {
  104. if n := len(data); n > 1 {
  105. _quick_sort_general(data, 0, n, _max_depth(n), cmp, .Cmp)
  106. }
  107. }
  108. }
  109. // stable_sort sorts a slice
  110. stable_sort :: proc(data: $T/[]$E) where ORD(E) {
  111. when size_of(E) != 0 {
  112. if n := len(data); n > 1 {
  113. _stable_sort_general(data, struct{}{}, .Ordered)
  114. }
  115. }
  116. }
  117. // stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  118. stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  119. when size_of(E) != 0 {
  120. if n := len(data); n > 1 {
  121. _stable_sort_general(data, less, .Less)
  122. }
  123. }
  124. }
  125. stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  126. when size_of(E) != 0 {
  127. if n := len(data); n > 1 {
  128. _stable_sort_general(data, cmp, .Cmp)
  129. }
  130. }
  131. }
  132. @(require_results)
  133. is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
  134. for i := len(array)-1; i > 0; i -= 1 {
  135. if array[i] < array[i-1] {
  136. return false
  137. }
  138. }
  139. return true
  140. }
  141. @(require_results)
  142. is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
  143. for i := len(array)-1; i > 0; i -= 1 {
  144. if less(array[i], array[i-1]) {
  145. return false
  146. }
  147. }
  148. return true
  149. }
  150. is_sorted_by_cmp :: is_sorted_cmp
  151. @(require_results)
  152. is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
  153. for i := len(array)-1; i > 0; i -= 1 {
  154. if cmp(array[i], array[i-1]) == .Less {
  155. return false
  156. }
  157. }
  158. return true
  159. }
  160. reverse_sort :: proc(data: $T/[]$E) where ORD(E) {
  161. sort_by(data, proc(i, j: E) -> bool {
  162. return j < i
  163. })
  164. }
  165. reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  166. context._internal = rawptr(less)
  167. sort_by(data, proc(i, j: E) -> bool {
  168. k := (proc(i, j: E) -> bool)(context._internal)
  169. return k(j, i)
  170. })
  171. }
  172. reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  173. context._internal = rawptr(cmp)
  174. sort_by_cmp(data, proc(i, j: E) -> Ordering {
  175. k := (proc(i, j: E) -> Ordering)(context._internal)
  176. return k(j, i)
  177. })
  178. }
  179. // TODO(bill): Should `sort_by_key` exist or is `sort_by` more than enough?
  180. sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  181. context._internal = rawptr(key)
  182. sort_by(data, proc(i, j: E) -> bool {
  183. k := (proc(E) -> K)(context._internal)
  184. return k(i) < k(j)
  185. })
  186. }
  187. reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  188. context._internal = rawptr(key)
  189. sort_by(data, proc(i, j: E) -> bool {
  190. k := (proc(E) -> K)(context._internal)
  191. return k(j) < k(i)
  192. })
  193. }
  194. @(require_results)
  195. is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K) {
  196. for i := len(array)-1; i > 0; i -= 1 {
  197. if key(array[i]) < key(array[i-1]) {
  198. return false
  199. }
  200. }
  201. return true
  202. }
  203. @(private, require_results)
  204. _max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1))
  205. for i := n; i > 0; i >>= 1 {
  206. depth += 1
  207. }
  208. return depth * 2
  209. }