mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Reimplement binary_search_by to be simpler
This commit is contained in:
+11
-29
@@ -163,38 +163,20 @@ binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
|||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
binary_search_by :: proc(array: $A/[]$T, key: T, f: proc(T, T) -> Ordering) -> (index: int, found: bool) #no_bounds_check {
|
binary_search_by :: proc(array: $A/[]$T, key: T, f: proc(T, T) -> Ordering) -> (index: int, found: bool) #no_bounds_check {
|
||||||
// INVARIANTS:
|
n := len(array)
|
||||||
// - 0 <= left <= (left + size = right) <= len(array)
|
left, right := 0, n
|
||||||
// - f returns .Less for everything in array[:left]
|
|
||||||
// - f returns .Greater for everything in array[right:]
|
|
||||||
size := len(array)
|
|
||||||
left := 0
|
|
||||||
right := size
|
|
||||||
|
|
||||||
for left < right {
|
for left < right {
|
||||||
mid := left + size / 2
|
mid := int(uint(left+right) >> 1)
|
||||||
|
if f(array[mid], key) == .Less {
|
||||||
// Steps to verify this is in-bounds:
|
left = mid+1
|
||||||
// 1. We note that `size` is strictly positive due to the loop condition
|
} else {
|
||||||
// 2. Therefore `size/2 < size`
|
// .Equal or .Greater
|
||||||
// 3. Adding `left` to both sides yields `(left + size/2) < (left + size)`
|
right = mid
|
||||||
// 4. We know from the invariant that `left + size <= len(array)`
|
|
||||||
// 5. Therefore `left + size/2 < self.len()`
|
|
||||||
cmp := f(key, array[mid])
|
|
||||||
|
|
||||||
left = mid + 1 if cmp == .Less else left
|
|
||||||
right = mid if cmp == .Greater else right
|
|
||||||
|
|
||||||
switch cmp {
|
|
||||||
case .Equal: return mid, true
|
|
||||||
case .Less: right = mid
|
|
||||||
case .Greater: left = mid + 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size = right - left
|
|
||||||
}
|
}
|
||||||
|
// left == right
|
||||||
return left, false
|
// f(array[left-1], key) == .Less (if left > 0)
|
||||||
|
return left, left < n && f(array[left], key) == .Equal
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
|
|||||||
Reference in New Issue
Block a user