diff --git a/core/sort/sort.odin b/core/sort/sort.odin index dadb0d309..a992fe04c 100644 --- a/core/sort/sort.odin +++ b/core/sort/sort.odin @@ -286,3 +286,44 @@ compare_strings :: proc(a, b: string) -> int { y := transmute(mem.Raw_String)b; return mem.compare_byte_ptrs(x.data, y.data, min(x.len, y.len)); } + + +binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool) + where intrinsics.type_is_ordered(T) #no_bounds_check { + + + n := len(array); + switch n { + case 0: + return -1, false; + case 1: + if array[0] == key { + return 0, true; + } + return -1, false; + } + + lo, hi := 0, n-1; + + for array[hi] != array[lo] && key >= array[lo] && key <= array[hi] { + when intrinsics.type_is_ordered_numeric(T) { + // NOTE(bill): This is technically interpolation search + m := lo + int((key - array[lo]) * T(hi - lo) / (array[hi] - array[lo])); + } else { + m := (lo + hi)/2; + } + switch { + case array[m] < key: + lo = m + 1; + case key < array[m]: + hi = m - 1; + case: + return m, true; + } + } + + if key == array[lo] { + return lo, true; + } + return -1, false; +} diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index f908e6ecd..28b453d06 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -7,6 +7,7 @@ import "core:thread" import "core:time" import "core:reflect" import "core:runtime" +import "core:sort" import "intrinsics" @@ -1978,7 +1979,19 @@ pure_procedures :: proc() { } main :: proc() { - when true { + x := [?]f32{1, 1, 5, 6, 7, 8, 9, 10, 15, 15}; + i, ok := sort.binary_search(x[:], 7); + fmt.println(x); + fmt.println(i, ok); + + y := [?]string{"apple", "hello", "goodbye", "what?"}; + sort.quick_sort(y[:]); + j, y_ok := sort.binary_search(y[:], "goodbye"); + fmt.println(y); + fmt.println(j, y_ok); + + + when false { the_basics(); control_flow(); named_proc_return_parameters();