diff options
| author | gingerBill <bill@gingerbill.org> | 2018-05-21 20:47:52 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2018-05-21 20:47:52 +0100 |
| commit | 5b6770f3d297c0639bdbe8b1b029616c16669165 (patch) | |
| tree | 79053a455efde40e77b4dc5ef1aa92f59c907523 /core/sort | |
| parent | 718b80ba398b8980c37f79dded101bcf20d187d2 (diff) | |
Parse directories to be packages
Diffstat (limited to 'core/sort')
| -rw-r--r-- | core/sort/sort.odin | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/core/sort/sort.odin b/core/sort/sort.odin new file mode 100644 index 000000000..f2e349b61 --- /dev/null +++ b/core/sort/sort.odin @@ -0,0 +1,215 @@ +package sort + +bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { + assert(f != nil); + count := len(array); + + init_j, last_j := 0, count-1; + + for { + init_swap, prev_swap := -1, -1; + + for j in init_j..last_j { + if f(array[j], array[j+1]) > 0 { + array[j], array[j+1] = array[j+1], array[j]; + prev_swap = j; + if init_swap == -1 do init_swap = j; + } + } + + if prev_swap == -1 do return; + + init_j = max(init_swap-1, 0); + last_j = prev_swap; + } +} + +bubble_sort :: proc(array: $A/[]$T) { + count := len(array); + + init_j, last_j := 0, count-1; + + for { + init_swap, prev_swap := -1, -1; + + for j in init_j..last_j { + if array[j] > array[j+1] { + array[j], array[j+1] = array[j+1], array[j]; + prev_swap = j; + if init_swap == -1 do init_swap = j; + } + } + + if prev_swap == -1 do return; + + init_j = max(init_swap-1, 0); + last_j = prev_swap; + } +} + +quick_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { + assert(f != nil); + a := array; + n := len(a); + if n < 2 do return; + + p := a[n/2]; + i, j := 0, n-1; + + loop: for { + for f(a[i], p) < 0 do i += 1; + for f(p, a[j]) < 0 do j -= 1; + + if i >= j do break loop; + + a[i], a[j] = a[j], a[i]; + i += 1; + j -= 1; + } + + quick_sort(a[0..i], f); + quick_sort(a[i..n], f); +} + +quick_sort :: proc(array: $A/[]$T) { + a := array; + n := len(a); + if n < 2 do return; + + p := a[n/2]; + i, j := 0, n-1; + + loop: for { + for a[i] < p do i += 1; + for p < a[j] do j -= 1; + + if i >= j do break loop; + + a[i], a[j] = a[j], a[i]; + i += 1; + j -= 1; + } + + quick_sort(a[0..i]); + quick_sort(a[i..n]); +} + +_log2 :: proc(n: int) -> int { + res := 0; + for ; n != 0; n >>= 1 do res += 1; + return res; +} + +merge_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { + merge_slices :: proc(arr1, arr2, out: A, f: proc(T, T) -> int) { + N1, N2 := len(arr1), len(arr2); + i, j := 0, 0; + for k in 0..N1+N2 { + if j == N2 || i < N1 && j < N2 && f(arr1[i], arr2[j]) < 0 { + out[k] = arr1[i]; + i += 1; + } else { + out[k] = arr2[j]; + j += 1; + } + } + } + + assert(f != nil); + + arr1 := array; + N := len(arr1); + arr2 := make([]T, N); + defer free(arr2); + + a, b, m, M := N/2, N, 1, _log2(N); + + for i in 0..M+1 { + for j in 0..a { + k := 2*j*m; + merge_slices(arr1[k..k+m], arr1[k+m..k+m+m], arr2[k..], f); + } + if N-b > m { + k := 2*a*m; + merge_slices(arr1[k..k+m], arr1[k+m..k+m+(N-b)&(m-1)], arr2[k..], f); + } else { + copy(arr2[b..N], arr1[b..N]); + } + arr1, arr2 = arr2, arr1; + m <<= 1; + a >>= 1; + b = a << uint(i) << 2; + } + + if M & 1 == 0 do copy(arr2, arr1); +} + +merge_sort :: proc(array: $A/[]$T) { + merge_slices :: proc(arr1, arr2, out: A) { + N1, N2 := len(arr1), len(arr2); + i, j := 0, 0; + for k in 0..N1+N2 { + if j == N2 || i < N1 && j < N2 && arr1[i] < arr2[j] { + out[k] = arr1[i]; + i += 1; + } else { + out[k] = arr2[j]; + j += 1; + } + } + } + + arr1 := array; + N := len(arr1); + arr2 := make([]T, N); + defer free(arr2); + + a, b, m, M := N/2, N, 1, _log2(N); + + for i in 0..M+1 { + for j in 0..a { + k := 2*j*m; + merge_slices(arr1[k..k+m], arr1[k+m..k+m+m], arr2[k..]); + } + if N-b > m { + k := 2*a*m; + merge_slices(arr1[k..k+m], arr1[k+m..k+m+(N-b)&(m-1)], arr2[k..]); + } else { + copy(arr2[b..N], arr1[b..N]); + } + arr1, arr2 = arr2, arr1; + m <<= 1; + a >>= 1; + b = a << uint(i) << 2; + } + + if M & 1 == 0 do copy(arr2, arr1); +} + + + +compare_ints :: proc(a, b: int) -> int { + switch delta := a - b; { + case delta < 0: return -1; + case delta > 0: return +1; + } + return 0; +} + +compare_f32s :: proc(a, b: f32) -> int { + switch delta := a - b; { + case delta < 0: return -1; + case delta > 0: return +1; + } + return 0; +} +compare_f64s :: proc(a, b: f64) -> int { + switch delta := a - b; { + case delta < 0: return -1; + case delta > 0: return +1; + } + return 0; +} +compare_strings :: proc(a, b: string) -> int { + return __string_cmp(a, b); +} |