123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647(**************************************************************************)(* *)(* Authors: *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* Benoît Montagu, projet Celtique, INRIA Rennes Bretagne Atlantique *)(* *)(* Copyright 1996 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)type(_,_)cmp=Lt:(_,_)cmp|Eq:('a,'a)cmp|Gt:(_,_)cmpmoduletypeDORDERED=sigtype_tvalcompare:'at->'bt->('a,'b)cmpendmoduletypeS_WITH_VALUE=sigtype'akeytype'avaluetypetvalempty:tvalis_empty:t->boolvalmem:'akey->t->boolvaladd:'akey->'avalue->t->tvalupdate:'akey->('avalueoption->'avalueoption)->t->tvalsingleton:'akey->'avalue->tvalremove:'akey->t->ttypepoly_merge={merge_fun:'a.'akey->'avalueoption->'avalueoption->'avalueoption;}[@@unboxed]valmerge:poly_merge->t->t->ttypepoly_union={union_fun:'a.'akey->'avalue->'avalue->'avalueoption;}[@@unboxed]valunion:poly_union->t->t->ttype'bpoly1={fun1:'a.'akey->'avalue->'b}[@@unboxed]type'bpoly2={fun2:'a.'akey->'avalue->'avalue->'b}[@@unboxed]valcompare:intpoly2->t->t->intvalequal:boolpoly2->t->t->boolvaliter:unitpoly1->t->unitvalfold:('b->'b)poly1->t->'b->'bvalfor_all:boolpoly1->t->boolvalexists:boolpoly1->t->boolvalfilter:boolpoly1->t->ttypepoly_filter_map={filter_map_fun:'a.'akey->'avalue->'avalueoption;}[@@unboxed]valfilter_map:poly_filter_map->t->tvalpartition:boolpoly1->t->t*tvalcardinal:t->inttypebinding=Binding:'akey*'avalue->bindingvalbindings:t->bindinglistvalmin_binding:t->bindingvalmin_binding_opt:t->bindingoptionvalmax_binding:t->bindingvalmax_binding_opt:t->bindingoptionvalchoose:t->bindingvalchoose_opt:t->bindingoptionvalsplit:'akey->t->t*'avalueoption*tvalfind:'akey->t->'avaluevalfind_opt:'akey->t->'avalueoptiontype'bpoly0={fun0:'a.'akey->'b}[@@unboxed]valfind_first:boolpoly0->t->bindingvalfind_first_opt:boolpoly0->t->bindingoptionvalfind_last:boolpoly0->t->bindingvalfind_last_opt:boolpoly0->t->bindingoptiontypepoly_mapi={mapi_fun:'a.'akey->'avalue->'avalue}[@@unboxed]valmapi:poly_mapi->t->tvalto_seq:t->bindingSeq.tvalto_rev_seq:t->bindingSeq.tvalto_seq_from:'akey->t->bindingSeq.tvaladd_seq:bindingSeq.t->t->tvalof_seq:bindingSeq.t->tendmoduletypeS=S_WITH_VALUEwithtype'avalue:='amoduletypeTYPE1=sigtype'atendmoduleMakeWithValue(Ord:DORDERED)(Val:TYPE1)=structtype'akey='aOrd.ttype'avalue='aVal.ttypet=|Empty|Node:{l:t;v:'akey;d:'avalue;r:t;h:int}->tletheight=functionEmpty->0|Node{h;_}->hletcreatelxdr=lethl=heightlandhr=heightrinNode{l;v=x;d;r;h=(ifhl>=hrthenhl+1elsehr+1)}letsingletonxd=Node{l=Empty;v=x;d;r=Empty;h=1}letballxdr=lethl=matchlwithEmpty->0|Node{h;_}->hinlethr=matchrwithEmpty->0|Node{h;_}->hinifhl>hr+2thenmatchlwith|Empty->invalid_arg"Dmap.bal"|Node{l=ll;v=lv;d=ld;r=lr;h=_}->(ifheightll>=heightlrthencreatelllvld(createlrxdr)elsematchlrwith|Empty->invalid_arg"Dmap.bal"|Node{l=lrl;v=lrv;d=lrd;r=lrr;h=_}->create(createlllvldlrl)lrvlrd(createlrrxdr))elseifhr>hl+2thenmatchrwith|Empty->invalid_arg"Dmap.bal"|Node{l=rl;v=rv;d=rd;r=rr;h=_}->(ifheightrr>=heightrlthencreate(createlxdrl)rvrdrrelsematchrlwith|Empty->invalid_arg"Dmap.bal"|Node{l=rll;v=rlv;d=rld;r=rlr;h=_}->create(createlxdrll)rlvrld(createrlrrvrdrr))elseNode{l;v=x;d;r;h=(ifhl>=hrthenhl+1elsehr+1)}letempty=Emptyletis_empty=functionEmpty->true|_->falseletrecadd:typea.akey->avalue->t->t=funxdata->function|Empty->Node{l=Empty;v=x;d=data;r=Empty;h=1}|Node{l;v;d;r;h}asm->(matchOrd.comparexvwith|Eq->ifd==datathenmelseNode{l;v=x;d=data;r;h}|Lt->letll=addxdatalinifl==llthenmelseballlvdr|Gt->letrr=addxdatarinifr==rrthenmelseballvdrr)typebinding=Binding:'akey*'avalue->bindingletrecfind:typea.akey->t->avalue=funx->function|Empty->raiseNot_found|Node{l;v;d;r;h=_}->(matchOrd.comparexvwithEq->d|Lt->findxl|Gt->findxr)type'bpoly0={fun0:'a.'akey->'b}[@@unboxed]type'bpoly1={fun1:'a.'akey->'avalue->'b}[@@unboxed]type'bpoly2={fun2:'a.'akey->'avalue->'avalue->'b}[@@unboxed]letrecfind_first_aux:typea.akey->avalue->boolpoly0->t->binding=funv0d0f->function|Empty->Binding(v0,d0)|Node{l;v;d;r;h=_}->iff.fun0vthenfind_first_auxvdflelsefind_first_auxv0d0frletrecfind_firstf=function|Empty->raiseNot_found|Node{l;v;d;r;h=_}->iff.fun0vthenfind_first_auxvdflelsefind_firstfrletrecfind_first_opt_aux:typea.akey->avalue->boolpoly0->t->bindingoption=funv0d0f->function|Empty->Some(Binding(v0,d0))|Node{l;v;d;r;h=_}->iff.fun0vthenfind_first_opt_auxvdflelsefind_first_opt_auxv0d0frletrecfind_first_optf=function|Empty->None|Node{l;v;d;r;h=_}->iff.fun0vthenfind_first_opt_auxvdflelsefind_first_optfrletrecfind_last_aux:typea.akey->avalue->boolpoly0->t->binding=funv0d0f->function|Empty->Binding(v0,d0)|Node{l;v;d;r;h=_}->iff.fun0vthenfind_last_auxvdfrelsefind_last_auxv0d0flletrecfind_lastf=function|Empty->raiseNot_found|Node{l;v;d;r;h=_}->iff.fun0vthenfind_last_auxvdfrelsefind_lastflletrecfind_last_opt_aux:typea.akey->avalue->boolpoly0->t->bindingoption=funv0d0f->function|Empty->Some(Binding(v0,d0))|Node{l;v;d;r;h=_}->iff.fun0vthenfind_last_opt_auxvdfrelsefind_last_opt_auxv0d0flletrecfind_last_optf=function|Empty->None|Node{l;v;d;r;h=_}->iff.fun0vthenfind_last_opt_auxvdfrelsefind_last_optflletrecfind_opt:typea.akey->t->avalueoption=funx->function|Empty->None|Node{l;v;d;r;h=_}->(matchOrd.comparexvwith|Eq->Somed|Lt->find_optxl|Gt->find_optxr)letrecmem:typea.akey->t->bool=funx->function|Empty->false|Node{l;v;r;d=_;h=_}->(matchOrd.comparexvwithEq->true|Lt->memxl|Gt->memxr)letrecmin_binding=function|Empty->raiseNot_found|Node{l=Empty;v;d;r=_;h=_}->Binding(v,d)|Node{l;v=_;d=_;r=_;h=_}->min_bindinglletrecmin_binding_opt=function|Empty->None|Node{l=Empty;v;d;r=_;h=_}->Some(Binding(v,d))|Node{l;v=_;d=_;r=_;h=_}->min_binding_optlletrecmax_binding=function|Empty->raiseNot_found|Node{v;d;r=Empty;l=_;h=_}->Binding(v,d)|Node{r;v=_;d=_;l=_;h=_}->max_bindingrletrecmax_binding_opt=function|Empty->None|Node{v;d;r=Empty;l=_;h=_}->Some(Binding(v,d))|Node{r;v=_;d=_;l=_;h=_}->max_binding_optrletrecremove_min_binding=function|Empty->invalid_arg"Map.remove_min_elt"|Node{l=Empty;r;v=_;d=_;h=_}->r|Node{l;v;d;r;h=_}->bal(remove_min_bindingl)vdrletmerget1t2=match(t1,t2)with|Empty,t->t|t,Empty->t|_,_->let(Binding(x,d))=min_bindingt2inbalt1xd(remove_min_bindingt2)letrecremove:typea.akey->t->t=funx->function|Empty->Empty|Node{l;v;d;r;h=_}asm->(matchOrd.comparexvwith|Eq->mergelr|Lt->letll=removexlinifl==llthenmelseballlvdr|Gt->letrr=removexrinifr==rrthenmelseballvdrr)letrecupdate:typea.akey->(avalueoption->avalueoption)->t->t=funxf->function|Empty->(matchfNonewith|None->Empty|Somedata->Node{l=Empty;v=x;d=data;r=Empty;h=1})|Node{l;v;d;r;h}asm->(matchOrd.comparexvwith|Eq->(matchf(Somed)with|None->mergelr|Somedata->ifd==datathenmelseNode{l;v=x;d=data;r;h})|Lt->letll=updatexflinifl==llthenmelseballlvdr|Gt->letrr=updatexfrinifr==rrthenmelseballvdrr)letreciterf=function|Empty->()|Node{l;v;d;r;h=_}->iterfl;f.fun1vd;iterfrtypepoly_mapi={mapi_fun:'a.'akey->'avalue->'avalue}[@@unboxed]letrecmapif=function|Empty->Empty|Node{l;v;d;r;h}->letl'=mapiflinletd'=f.mapi_funvdinletr'=mapifrinNode{l=l';v;d=d';r=r';h}letrecfoldfmaccu=matchmwith|Empty->accu|Node{l;v;d;r;h=_}->foldfr(f.fun1vd(foldflaccu))letrecfor_allp=function|Empty->true|Node{l;v;d;r;h=_}->p.fun1vd&&for_allpl&&for_allprletrecexistsp=function|Empty->false|Node{l;v;d;r;h=_}->p.fun1vd||existspl||existspr(* Beware: those two functions assume that the added k is *strictly*
smaller (or bigger) than all the present keys in the tree; it
does not test for equality with the current min (or max) key.
Indeed, they are only used during the "join" operation which
respects this precondition.
*)letrecadd_min_bindingkx=function|Empty->singletonkx|Node{l;v;d;r;h=_}->bal(add_min_bindingkxl)vdrletrecadd_max_bindingkx=function|Empty->singletonkx|Node{l;v;d;r;h=_}->ballvd(add_max_bindingkxr)(* Same as create and bal, but no assumptions are made on the
relative heights of l and r. *)letrecjoinlvdr=match(l,r)with|Empty,_->add_min_bindingvdr|_,Empty->add_max_bindingvdl|(Node{l=ll;v=lv;d=ld;r=lr;h=lh},Node{l=rl;v=rv;d=rd;r=rr;h=rh})->iflh>rh+2thenballllvld(joinlrvdr)elseifrh>lh+2thenbal(joinlvdrl)rvrdrrelsecreatelvdr(* Merge two trees l and r into one.
All elements of l must precede the elements of r.
No assumption on the heights of l and r. *)letconcatt1t2=match(t1,t2)with|Empty,t->t|t,Empty->t|_,_->let(Binding(x,d))=min_bindingt2injoint1xd(remove_min_bindingt2)letconcat_or_joint1vdt2=matchdwithSomed->joint1vdt2|None->concatt1t2letrecsplit:typea.akey->t->t*avalueoption*t=funx->function|Empty->(Empty,None,Empty)|Node{l;v;d;r;h=_}->(matchOrd.comparexvwith|Eq->(l,Somed,r)|Lt->letll,pres,rl=splitxlin(ll,pres,joinrlvdr)|Gt->letlr,pres,rr=splitxrin(joinlvdlr,pres,rr))typepoly_merge={merge_fun:'a.'akey->'avalueoption->'avalueoption->'avalueoption;}[@@unboxed]letrecmergefs1s2=match(s1,s2)with|Empty,Empty->Empty|Node{l=l1;v=v1;d=d1;r=r1;h=h1},_whenh1>=heights2->letl2,d2,r2=splitv1s2inconcat_or_join(mergefl1l2)v1(f.merge_funv1(Somed1)d2)(mergefr1r2)|_,Node{l=l2;v=v2;d=d2;r=r2;h=_}->letl1,d1,r1=splitv2s1inconcat_or_join(mergefl1l2)v2(f.merge_funv2d1(Somed2))(mergefr1r2)|_->assertfalsetypepoly_union={union_fun:'a.'akey->'avalue->'avalue->'avalueoption;}[@@unboxed]letrecunionfs1s2=match(s1,s2)with|Empty,s|s,Empty->s|(Node{l=l1;v=v1;d=d1;r=r1;h=h1},Node{l=l2;v=v2;d=d2;r=r2;h=h2})->(ifh1>=h2thenletl2,d2,r2=splitv1s2inletl=unionfl1l2andr=unionfr1r2inmatchd2with|None->joinlv1d1r|Somed2->concat_or_joinlv1(f.union_funv1d1d2)relseletl1,d1,r1=splitv2s1inletl=unionfl1l2andr=unionfr1r2inmatchd1with|None->joinlv2d2r|Somed1->concat_or_joinlv2(f.union_funv2d1d2)r)letrecfilterp=function|Empty->Empty|Node{l;v;d;r;h=_}asm->(* call [p] in the expected left-to-right order *)letl'=filterplinletpvd=p.fun1vdinletr'=filterprinifpvdthenifl==l'&&r==r'thenmelsejoinl'vdr'elseconcatl'r'typepoly_filter_map={filter_map_fun:'a.'akey->'avalue->'avalueoption;}[@@unboxed]letrecfilter_mapf=function|Empty->Empty|Node{l;v;d;r;h=_}->((* call [f] in the expected left-to-right order *)letl'=filter_mapflinletfvd=f.filter_map_funvdinletr'=filter_mapfrinmatchfvdwithSomed'->joinl'vd'r'|None->concatl'r')letrecpartitionp=function|Empty->(Empty,Empty)|Node{l;v;d;r;h=_}->(* call [p] in the expected left-to-right order *)letlt,lf=partitionplinletpvd=p.fun1vdinletrt,rf=partitionprinifpvdthen(joinltvdrt,concatlfrf)else(concatltrt,joinlfvdrf)typeenumeration=|End|More:'akey*'avalue*t*enumeration->enumerationletreccons_enumme=matchmwith|Empty->e|Node{l;v;d;r;h=_}->cons_enuml(More(v,d,r,e))letcomparecmpm1m2=letreccompare_auxe1e2=match(e1,e2)with|End,End->0|End,_->-1|_,End->1|More(v1,d1,r1,e1),More(v2,d2,r2,e2)->(matchOrd.comparev1v2with|Lt->-1|Gt->1|Eq->letc=cmp.fun2v1d1d2inifc<>0thencelsecompare_aux(cons_enumr1e1)(cons_enumr2e2))incompare_aux(cons_enumm1End)(cons_enumm2End)letequalcmpm1m2=letrecequal_auxe1e2=match(e1,e2)with|End,End->true|End,_->false|_,End->false|More(v1,d1,r1,e1),More(v2,d2,r2,e2)->(matchOrd.comparev1v2with|Eq->cmp.fun2v1d1d2&&equal_aux(cons_enumr1e1)(cons_enumr2e2)|_->false)inequal_aux(cons_enumm1End)(cons_enumm2End)letreccardinal=function|Empty->0|Node{l;r;v=_;d=_;h=_}->cardinall+1+cardinalrletrecbindings_auxaccu=function|Empty->accu|Node{l;v;d;r;h=_}->bindings_aux(Binding(v,d)::bindings_auxaccur)lletbindingss=bindings_aux[]sletchoose=min_bindingletchoose_opt=min_binding_optletadd_seqim=Seq.fold_left(funm(Binding(k,v))->addkvm)miletof_seqi=add_seqiemptyletrecseq_of_enum_c()=matchcwith|End->Seq.Nil|More(k,v,t,rest)->Seq.Cons(Binding(k,v),seq_of_enum_(cons_enumtrest))letto_seqm=seq_of_enum_(cons_enummEnd)letrecsnoc_enumse=matchswith|Empty->e|Node{l;v;d;r;h=_}->snoc_enumr(More(v,d,l,e))letrecrev_seq_of_enum_c()=matchcwith|End->Seq.Nil|More(k,v,t,rest)->Seq.Cons(Binding(k,v),rev_seq_of_enum_(snoc_enumtrest))letto_rev_seqc=rev_seq_of_enum_(snoc_enumcEnd)letto_seq_fromlowm=letrecaux:typea.akey->t->enumeration->enumeration=funlowmc->matchmwith|Empty->c|Node{l;v;d;r;_}->(matchOrd.comparevlowwith|Eq->More(v,d,r,c)|Lt->auxlowrc|Gt->auxlowl(More(v,d,r,c)))inseq_of_enum_(auxlowmEnd)endmoduleIdVal=structtype'at='aendmoduleMake(Ord:DORDERED):Swithtype'akey='aOrd.t=MakeWithValue(Ord)(IdVal)(** Functor that converts a [DORDERED] into an ordered type *)moduleToOrdered(X:DORDERED):sigtypet=Hide:'aX.t->tvalcompare:t->t->intend=structtypet=Hide:'aX.t->tletcompare(Hidex1)(Hidex2)=matchX.comparex1x2withLt->-1|Eq->0|Gt->1end(** Functor that creates a non-dependendent map for keys of a [DORDERED] type *)moduleMakeMap(X:DORDERED):Map.Swithtypekey=ToOrdered(X).tandtype'at='aMap.Make(ToOrdered(X)).t=structincludeMap.Make(ToOrdered(X))end(** Functor that creates a set of values of a [DORDERED] type *)moduleMakeSet(X:DORDERED):Set.Swithtypet=Set.Make(ToOrdered(X)).t=structincludeSet.Make(ToOrdered(X))end(** Functor that extends the indices of a [DORDERED] type, given some
type-level function *)moduleExtend(X:DORDERED)(F:sigtype!'atend):sigtype_t=Extend:'aX.t->'aF.ttvalcompare:'at->'bt->('a,'b)cmpend=structtype_t=Extend:'aX.t->'aF.ttletcompare(typeab)(Extendx1:at)(Extendx2:bt):(a,b)cmp=matchX.comparex1x2withLt->Lt|Eq->Eq|Gt->Gtend(** Functor that extends the indices of a [DORDERED] type by adding
some data to its left-hand side *)moduleExtendL(X:DORDERED)(Y:sigtypetend):sigtype_t=Extend:'aX.t->(Y.t*'a)tvalcompare:'at->'bt->('a,'b)cmpend=Extend(X)(structtype'at=Y.t*'aend)(** Functor that extends the indices of a [DORDERED] type by adding
some data to its right-hand side *)moduleExtendR(X:DORDERED)(Y:sigtypetend):sigtype_t=Extend:'aX.t->('a*Y.t)tvalcompare:'at->'bt->('a,'b)cmpend=Extend(X)(structtype'at='a*Y.tend)