let find_min_range ?(init_direction="fwd") v pred i =
if i < v.lo || i > v.hi then
invalid_arg (sprintf "%d not in range %s" i (to_string v))
;
let rec loop (dir:string) ans =
if pred ans then Some ans
else if equal ans v then None
else
match dir with
| "fwd" ->
let hi' = if ans.hi = v.hi then ans.hi else ans.hi+1 in
loop "rev" {ans with hi = hi'}
| "rev" ->
let lo' = if ans.lo = v.lo then ans.lo else ans.lo-1 in
loop "fwd" {ans with lo = lo'}
| _ -> invalid_arg (
sprintf
"valid directions are \"fwd\" or \"rev\" but given \"%s\""
dir
)
in loop init_direction {lo=i; hi=i}