123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554open!Importopen!Int.Replace_polymorphic_comparemoduleCore_time=Import_time.TimemoduleStable=structmoduleV1=structmoduleT=structtype'at=|Intervalof'a*'a|Empty[@@derivingbin_io,of_sexp,variants,compare,hash]type'ainterval='at[@@derivingbin_io,of_sexp,compare,hash]letinterval_of_sexpa_of_sexpsexp=tryinterval_of_sexpa_of_sexpsexp(* for backwards compatibility *)with_exn->matchsexpwith|Sexp.List[]->Empty|Sexp.List[lb;ub]->Interval(a_of_sexplb,a_of_sexpub)|Sexp.Atom_|Sexp.List_->of_sexp_error"Interval.t_of_sexp: expected pair or empty list"sexpletsexp_of_intervalsexp_of_at=matchtwith|Empty->Sexp.List[]|Interval(lb,ub)->Sexp.List[sexp_of_alb;sexp_of_aub]endopenTtype'at='ainterval[@@derivingsexp,bin_io,compare,hash]moduleFloat=structmoduleT=structtypet=floatinterval[@@derivingsexp,bin_io,compare,hash]endincludeTincludeComparator.Stable.V1.Make(T)endmoduleInt=structmoduleT=structtypet=intinterval[@@derivingsexp,bin_io,compare,hash]endincludeTincludeComparator.Stable.V1.Make(T)endmoduleTime=structmoduleT=structtypet=Core_time.Stable.V1.tinterval[@@derivingsexp,bin_io,compare]endincludeTincludeComparator.Stable.V1.Make(T)endmoduleTime_ns=structmoduleT=structtypet=Core_time_ns.Stable.V1.tinterval[@@derivingsexp,bin_io,compare]endincludeTincludeComparator.Stable.V1.Make(T)endmoduleOfday=structmoduleT=structtypet=Core_time.Stable.Ofday.V1.tinterval[@@derivingsexp,bin_io,compare,hash]endincludeTincludeComparator.Stable.V1.Make(T)endmodulePrivate=structincludeTletto_floatt=tletto_intt=tletto_ofdayt=tletto_timet=tendendendopenStable.V1.TmoduletypeBound=sigtype'aboundvalcompare:'abound->'abound->intval(>=):'abound->'abound->boolval(<=):'abound->'abound->boolval(=):'abound->'abound->boolval(>):'abound->'abound->boolval(<):'abound->'abound->boolval(<>):'abound->'abound->boolendmoduleRaw_make(T:Bound)=structmoduleT=structincludeTlet_=(<>)(* Prevent unused value warning for "<>" *)letmaxxy=ifT.(>=)xythenxelseyletminxy=ifT.(<=)xythenxelseyendmoduleInterval=structletempty=Emptyletis_malformed=function|Empty->false|Interval(x,y)->T.(>)xyletempty_cvt=function|Empty->Empty|Interval(x,y)asi->ifT.(>)xythenEmptyelseiletcreatexy=(* if x > y, then this is just the Empty interval. *)empty_cvt(Interval(x,y))letintersecti1i2=matchi1,i2with|Empty,_|_,Empty->Empty|Interval(l1,u1),Interval(l2,u2)->empty_cvt(Interval(T.maxl1l2,T.minu1u2))letis_empty=functionEmpty->true|_->falseletis_empty_or_singleton=function|Empty->true|Interval(x,y)->T.(=)xyletbounds=functionEmpty->None|Interval(l,u)->Some(l,u)letlbound=functionEmpty->None|Interval(l,_)->Somelletubound=functionEmpty->None|Interval(_,u)->Someuletbounds_exn=function|Empty->invalid_arg"Interval.bounds_exn: empty interval"|Interval(l,u)->(l,u)letlbound_exn=function|Empty->invalid_arg"Interval.lbound_exn: empty interval"|Interval(l,_)->lletubound_exn=function|Empty->invalid_arg"Interval.ubound_exn: empty interval"|Interval(_,u)->uletcompare_valueix=matchiwith|Empty->`Interval_is_empty|Interval(l,u)->ifT.(<)xlthen`BelowelseifT.(>)xuthen`Aboveelse`Withinletcontainsix=Poly.(=)(compare_valueix)`Withinletboundix=matchiwith|Empty->None|Interval(l,u)->letbounded_value=ifT.(<)xlthenlelseifT.(<)uxthenuelsexinSomebounded_valueletis_superseti1~of_:i2=matchi1,i2with|Interval(l1,u1),Interval(l2,u2)->T.(<=)l1l2&&T.(>=)u1u2|_,Empty->true|Empty,Interval(_,_)->falseletis_subseti1~of_:i2=is_superseti2~of_:i1letmapt~f=matchtwith|Empty->Empty|Interval(l,u)->empty_cvt(Interval(fl,fu));;letinterval_comparet1t2=matcht1,t2with|Empty,Empty->0|Empty,Interval_->-1|Interval_,Empty->1|Interval(l1,u1),Interval(l2,u2)->letc=T.comparel1l2inifInt.(<>)c0thencelseT.compareu1u2;;letare_disjoint_gen~are_disjointintervals=letintervals=Array.of_listintervalsintryfori=0toArray.lengthintervals-1doforj=i+1toArray.lengthintervals-1doifnot(are_disjointintervals.(i)intervals.(j))thenraiseExitdonedone;truewithExit->falseletare_disjointintervals=are_disjoint_genintervals~are_disjoint:(funi1i2->is_empty(intersecti1i2))letare_disjoint_as_open_intervalsintervals=are_disjoint_genintervals~are_disjoint:(funi1i2->is_empty_or_singleton(intersecti1i2))letlist_intersectilist1ilist2=ifnot(are_disjointilist1)||not(are_disjointilist2)theninvalid_arg"Interval.list_intersect: non-disjoint input list";letpairs=List.cartesian_productilist1ilist2inList.filter_mappairs~f:(fun(i1,i2)->leti=intersecti1i2inifis_emptyithenNoneelseSomei)lethalf_open_intervals_are_a_partitionintervals=letintervals=List.filter~f:(funx->not(is_emptyx))intervalsinletintervals=List.sort~compare:interval_compareintervalsin(* requires sorted list of intervals *)letrecis_partitiona=function|[]->true|b::tl->T.(=)(ubound_exna)(lbound_exnb)&&is_partitionbtlinmatchintervalswith|[]->true|x::xs->is_partitionxxsletconvex_hullintervals=List.foldintervals~init:empty~f:(funi1i2->(* Compute the convex hull of two intervals *)matchboundsi1,boundsi2with|None,_->i2|_,None->i1|Some(l1,u1),Some(l2,u2)->create(T.minl1l2)(T.maxu1u2))endmoduleSet=structletcreate_from_intervalsintervals=letintervals=List.filterintervals~f:(funi->not(Interval.is_emptyi))inletintervals=letlbi=Interval.lbound_exniinList.sortintervals~compare:(funii'->T.compare(lbi)(lbi'))inifnot(Interval.are_disjointintervals)thenfailwith"Interval_set.create: intervals were not disjoint"elseintervals;;letcreatepair_list=letintervals=List.mappair_list~f:(fun(lbound,ubound)->Interval.createlboundubound)increate_from_intervalsintervals;;letcontains_set~container~contained=List.for_allcontained~f:(funcontained_interval->List.existscontainer~f:(funcontainer_interval->Interval.is_supersetcontainer_interval~of_:contained_interval))letcontainstx=List.existst~f:(funinterval->Interval.containsintervalx)letubound_exnt=matchtwith|[]->invalid_arg"Interval_set.ubound called on empty set"|_->Interval.ubound_exn(List.last_exnt)letlbound_exnt=matchtwith|[]->invalid_arg"Interval_set.lbound called on empty set"|_->Interval.lbound_exn(List.hd_exnt)letuboundt=matchList.lasttwith|None->None|Somei->matchInterval.uboundiwith|None->assertfalse|Somex->Somexletlboundt=matchList.hdtwith|None->None|Somei->matchInterval.lboundiwith|None->assertfalse|Somex->Somexendendtype'at='ainterval[@@derivingbin_io,sexp,compare,hash]type'abound_='amoduleC=Raw_make(structtype'abound='aincludePolyend)includeC.Intervallett_of_sexpa_of_sexps=lett=t_of_sexpa_of_sexpsinifis_malformedtthenof_sexp_error"Interval.t_of_sexp error: malformed input"s;t;;moduleSet=structtype'at='aintervallist[@@derivingbin_io,sexp,compare,hash]includeC.SetendmoduleMake(Bound:sigtypet[@@derivingbin_io,sexp,hash]includeComparable.Swithtypet:=tend)=structtypet=Bound.tinterval[@@derivingbin_io,sexp,compare,hash]type'at_=ttypeinterval=t[@@derivingbin_io,sexp]typebound=Bound.ttype'abound_=boundmoduleC=Raw_make(structtype'abound=Bound.tletcompare=Bound.compareinclude(Bound:Comparable.Infixwithtypet:=Bound.t)end)includeC.Intervalletto_poly(t:t)=tlett_of_sexps=lett=t_of_sexpsinifis_malformedtthenfailwithf"Interval.Make.t_of_sexp error: malformed input %s"(Sexp.to_strings)()elset;;moduleSet=structtypet=intervallist[@@derivingsexp,bin_io]type'at_=tincludeC.Setletto_poly(t:t)=tendendmoduletypeS1=Interval_intf.S1moduletypeS=Interval_intf.Swithtype'apoly_t:='atwithtype'apoly_set:='aSet.tmoduletypeS_time=Interval_intf.S_timewithtype'apoly_t:='atwithtype'apoly_set:='aSet.tmoduleFloat=Make(Float)moduleOfday=Make(Core_time.Ofday)moduleOfday_ns=Make(Core_time_ns.Ofday)moduleInt=structincludeMake(Int)letlengtht=matchtwith|Empty->0|Interval(lo,hi)->letlen=1+hi-loin(* If [hi] and [lo] are far enough apart (e.g. if [lo <= 0] and
[hi = Int.max_value]), [len] will overlow. *)iflen<0thenfailwiths"interval length not representable"t[%sexp_of:t];lenletgetti=letfail()=failwiths"index out of bounds"(i,t)[%sexp_of:int*t]inmatchtwith|Empty->fail()|Interval(lo,hi)->ifi<0thenfail();letx=lo+iinifx<lo||x>hithenfail();xletitert~f=matchtwith|Empty->()|Interval(lo,hi)->forx=lotohidofxdoneletfold=letrecfold_interval~lo~hi~acc~f=iflo=hithenfacchielsefold_interval~lo:(lo+1)~hi~acc:(facclo)~finfunt~init~f->matchtwith|Empty->init|Interval(lo,hi)->fold_interval~lo~hi~acc:init~fmoduleFor_container=Container.Make0(structtypenonrect=tmoduleElt=Intletiter=`Customiterletfold=foldletlength=`Customlengthend)letexists=For_container.existsletfor_all=For_container.for_allletsum=For_container.sumletcount=For_container.countletfind=For_container.findletfind_map=For_container.find_mapletto_list=For_container.to_listletto_array=For_container.to_arrayletfold_result=For_container.fold_resultletfold_until=For_container.fold_untilletmin_eltt~compare=ifnot(phys_equalcompareInt.compare)thenFor_container.min_eltt~compareelselboundtletmax_eltt~compare=ifnot(phys_equalcompareInt.compare)thenFor_container.max_eltt~compareelseuboundtletmemtx=ifnot(phys_equalequalInt.equal)thenFor_container.memtxelsecontainstx(* Note that we use zero-based indexing here, because that's what Binary_searchable
requires, even though at the end we want to export functions that use the natural
bounds of the interval. *)moduleFor_binary_search=Binary_searchable.Make(structtypenonrect=ttypenonrecelt=boundletlength=lengthletget=getend)letbinary_search?pos?lent~comparewhichelt=letzero_based_pos=Option.mappos~f:(funx->x-lbound_exnt)inletzero_based_result=For_binary_search.binary_search?pos:zero_based_pos?lent~comparewhicheltinOption.mapzero_based_result~f:(funx->x+lbound_exnt)letbinary_search_segmented?pos?lent~segment_ofwhich=letzero_based_pos=Option.mappos~f:(funx->x-lbound_exnt)inletzero_based_result=For_binary_search.binary_search_segmented?pos:zero_based_pos?lent~segment_ofwhichinOption.mapzero_based_result~f:(funx->x+lbound_exnt)modulePrivate=structletget=getendendmoduletypeTime_bound=sigtypet[@@derivingbin_io,sexp,compare,hash]includeComparable.Swithtypet:=tmoduleOfday:sigtypetendmoduleZone:sigtypetvallocal:tLazy.tendvaloccurrence:[`First_after_or_at|`Last_before_or_at]->t->ofday:Ofday.t->zone:Zone.t->tendmoduleMake_time(Time:Time_bound)=structincludeMake(Time)letcreate_ending_after?zone(open_ofday,close_ofday)~now=letzone=matchzonewith|None->Lazy.forceTime.Zone.local|Somez->zinletclose_time=Time.occurrence`First_after_or_atnow~zone~ofday:close_ofdayinletopen_time=Time.occurrence`Last_before_or_atclose_time~zone~ofday:open_ofdayincreateopen_timeclose_timeletcreate_ending_before?zone(open_ofday,close_ofday)~ubound=letzone=matchzonewith|None->Lazy.forceTime.Zone.local|Somez->zinletclose_time=Time.occurrence`Last_before_or_atubound~zone~ofday:close_ofdayinletopen_time=Time.occurrence`Last_before_or_atclose_time~zone~ofday:open_ofdayincreateopen_timeclose_timeendmoduleTime=Make_time(Core_time)moduleTime_ns=Make_time(Core_time_ns)