diff --git a/lib/util/Ranges.v3 b/lib/util/Ranges.v3 index 5555230bf..0f2f3a8f2 100644 --- a/lib/util/Ranges.v3 +++ b/lib/util/Ranges.v3 @@ -76,4 +76,40 @@ component Ranges { } return i; } + // Performs binary search and returns the index. + def binarySearch(range: Range, val: T, lt: (T, T) -> bool) -> int { + var l = 0, r = range.length; + while (l < r) { + var mid = (l + r) >> 1; + var mid_val = range[mid]; + if (lt(val, mid_val)) r = mid - 1; + else if (lt(mid_val, val)) l = mid + 1; + else return mid; + } + return -1; + } + // Returns the *first* element that is *not less* than `val` in a sorted range. + def lowerbound(range: Range, val: T, lt: (T, T) -> bool) -> int { + var start = 0; + var count = range.length; + while (count > 0) { + var step = count >> 1; + var mid = start + step; + if (lt(range[mid], val)) { start = mid + 1; count -= step + 1; } + else count = step; + } + return start; + } + // Returns the *first* element that is *greater* than `val` in a sorted range. + def upperbound(range: Range, val: T, lt: (T, T) -> bool) -> int { + var start = 0; + var count = range.length; + while (count > 0) { + var step = count >> 1; + var mid = start + step; + if (!lt(val, range[mid])) { start = mid + 1; count -= step + 1; } + else count = step; + } + return start; + } }