Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file range.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200typet={lo:int;hi:int}[@@derivingcompare,sexp]letmakelohi=iflo<=hithenOk{lo;hi}else(error"lower bound larger than upper bound"(lo,hi)[%sexp_of:int*int])letmake_unsafelohi={lo;hi}letsizev=v.hi-v.lo+1letequaluv=compareuv=0letmembertk=t.lo<=k&&k<=t.hiletto_stringt=String.concat["[";string_of_intt.lo;", ";string_of_intt.hi;"]"]letto_listv=List.init(sizev)~f:((+)v.lo)letoverlapuv=(minu.hiv.hi)-(maxu.lov.lo)+1letgapuv=-(overlapuv)letunionuv=ifoverlapuv<0then`Disjoint(u,v)else`Joint{lo=minu.lov.lo;hi=maxu.hiv.hi}letintersectuv=letl=maxu.lov.loinleth=minu.hiv.hiinifl<=hthenSome{lo=l;hi=h}elseNoneletstrict_beforeuv=u.lo<v.lo&&u.hi<v.hiletstrict_afteruv=strict_beforevuletbeforeuv=strict_beforeuv||equaluvletafteruv=beforevuletcompare_positionaluv=ifequaluvthenSome0elseifstrict_beforeuvthenSome(-1)elseifstrict_afteruvthenSome1elseNoneletsubsetuv=u.lo>=v.lo&&u.hi<=v.hiletsupersetuv=subsetvuletstrict_subsetuv=subsetuv&¬(equaluv)letstrict_supersetuv=strict_subsetvuletcompare_containmentuv=ifequaluvthenSome0elseifstrict_subsetuvthenSome(-1)elseifstrict_supersetuvthenSome1elseNoneletany_overlaptl=lettl=List.sorttl~compare:(funuv->Int.compareu.lov.lo)inletreclooptl=matchtlwith|[]|_::[]->false|u::v::tl->v.lo<=u.hi||loop(v::tl)inlooptlletall_positionalvl=letcompareuv=matchcompare_containmentuvwith|Somex->x|None->matchcompare_positionaluvwith|Somex->x|None->assertfalseinletvl=List.sort~comparevlinletrecloopvl=matchvlwith|[]|_::[]->true|u::v::vl->(beforeuv)&&loop(v::vl)inloopvlletmax_gap_of_positionalvl=letcompareuv=matchcompare_containmentuvwith|Somex->x|None->matchcompare_positionaluvwith|Somex->x|None->assertfalseinletvl=List.sort~comparevlinletrecloopansvl=matchvlwith|[]|_::[]->ans|u::v::vl->ifbeforeuvthenloop(maxans(gapuv))(v::vl)elsefailwith(sprintf"ranges %s and %s not positionally comparable"(to_stringu)(to_stringv))inmatchvlwith|[]|_::[]->failwith"given fewer than two ranges"|u::v::vl->loop(gapuv)(v::vl)letfind_min_range?(init_direction="fwd")vpredi=ifi<v.lo||i>v.hitheninvalid_arg(sprintf"%d not in range %s"i(to_stringv));letrecloop(dir:string)ans=ifpredansthenSomeanselseifequalansvthenNoneelsematchdirwith|"fwd"->lethi'=ifans.hi=v.hithenans.hielseans.hi+1inloop"rev"{answithhi=hi'}|"rev"->letlo'=ifans.lo=v.lothenans.loelseans.lo-1inloop"fwd"{answithlo=lo'}|_->invalid_arg(sprintf"valid directions are \"fwd\" or \"rev\" but given \"%s\""dir)inloopinit_direction{lo=i;hi=i}letexpand_assoc_listtal=letans=Caml.Hashtbl.create100inletinsert(t,a)=fori=t.lotot.hidoletprev=tryCaml.Hashtbl.findansiwithCaml.Not_found->[]inCaml.Hashtbl.replaceansi(a::prev)doneinlet()=List.iter~f:inserttalinletans=Caml.Hashtbl.fold(funkeyvalueans->(key,value)::ans)ans[]inList.rev(List.map~f:(fun(i,al)->i,List.reval)ans)letfind_regions?(max_gap=0)predtal=ifany_overlap(List.map~f:fsttal)thenfailwith"overlapping ranges not allowed";lettal=List.sorttal~compare:(fun(u,_)(v,_)->matchcompare_positionaluvwith|Somex->x|None->assertfalse)in(* see below for meaning of [curr] *)letinsert(curr:(t*int)option)ans=matchcurrwith|None->ans|Some(v,gap)->letx=v.loinlety=v.hi-gapinifx<=ythen{lo=x;hi=y}::anselsefailwithf"gap = %d, range = %s"gap(to_stringv)()in(* curr = Some (v,gap) means [v] is region built up thus far,
* with last [gap] elements failing pred, [0 <= gap <= max_gap].
* curr = None means no region currently being built *)letrecloop(curr:(t*int)option)anstal=matchtalwith|[]->insertcurrans|(t,a)::tal->matchcurrwith|None->letcurr=ifpredathenSome(t,0)elseNoneinloopcurranstal|Some(curr_v,curr_gap)->letextra_gap=t.lo-curr_v.hi-1inlett,pred,tal=ifextra_gap>0then{lo=(curr_v.hi+1);hi=(t.lo-1)},false,((t,a)::tal)elset,preda,talinletcurr_v={lo=curr_v.lo;hi=t.hi}inletcurr_gap=ifpredthen0elsesizet+curr_gapinletcurr=Some(curr_v,curr_gap)inifcurr_gap>max_gapthenloopNone(insertcurrans)talelseloopcurranstalinList.rev(loopNone[]tal)letrecmake_randomt=letmax=t.hi-t.lo+1inletlo=t.lo+Random.intmaxinlethi=t.lo+Random.intmaxiniflo<=hithen{lo;hi}elsemake_randomt