let find_regions ?(max_gap=0) pred tal =
if any_overlap (List.map ~f:fst tal) then failwith "overlapping ranges not allowed";
let tal = List.sort ~cmp:(fun (u,_) (v,_) -> Order.totalify compare_positional u v) tal in
let insert (curr : (t * int) option) ans =
match curr with
| None -> ans
| Some (v,gap) ->
try (make v.lo (v.hi - gap))::ans
with Bad _ ->
failwithf "gap = %d, range = %s" gap (to_string v) () in
let rec loop (curr : (t * int) option) ans tal =
match tal with
| [] -> insert curr ans
| (t,a)::tal ->
match curr with
| None ->
let curr = if pred a then Some(t,0) else None in
loop curr ans tal
| Some (curr_v, curr_gap) ->
let extra_gap = t.lo - curr_v.hi - 1 in
let t,pred,tal =
if extra_gap > 0 then
make (curr_v.hi + 1) (t.lo - 1), false, ((t,a)::tal)
else
t, pred a, tal
in
let curr_v = make curr_v.lo t.hi in
let curr_gap = if pred then 0 else size t + curr_gap in
let curr = Some (curr_v, curr_gap) in
if curr_gap > max_gap
then loop None (insert curr ans) tal
else loop curr ans tal
in
List.rev (loop None [] tal)