aboutsummaryrefslogtreecommitdiff
path: root/core/sort
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-05-21 20:47:52 +0100
committergingerBill <bill@gingerbill.org>2018-05-21 20:47:52 +0100
commit5b6770f3d297c0639bdbe8b1b029616c16669165 (patch)
tree79053a455efde40e77b4dc5ef1aa92f59c907523 /core/sort
parent718b80ba398b8980c37f79dded101bcf20d187d2 (diff)
Parse directories to be packages
Diffstat (limited to 'core/sort')
-rw-r--r--core/sort/sort.odin215
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);
+}