123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384(**************************************************************************)(* *)(* Copyright (C) Jean-Christophe Filliatre *)(* *)(* This software is free software; you can redistribute it and/or *)(* modify it under the terms of the GNU Lesser General Public *)(* License version 2.1, with the special exception on linking *)(* described in file LICENSE. *)(* *)(* This software is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)(* *)(**************************************************************************)(*s Maps of integers implemented as Patricia trees, following Chris
Okasaki and Andrew Gill's paper {\em Fast Mergeable Integer Maps}
({\tt\small http://www.cs.columbia.edu/\~{}cdo/papers.html\#ml98maps}).
See the documentation of module [Ptset] which is also based on the
same data-structure. *)typekey=inttype'at=|Empty|Leafofint*'a|Branchofint*int*'at*'atletempty=Emptyletis_emptyt=t=Emptyletzero_bitkm=(klandm)==0letrecmemk=function|Empty->false|Leaf(j,_)->k==j|Branch(_,m,l,r)->memk(ifzero_bitkmthenlelser)letrecfindk=function|Empty->raiseNot_found|Leaf(j,x)->ifk==jthenxelseraiseNot_found|Branch(_,m,l,r)->findk(ifzero_bitkmthenlelser)letfind_optkm=trySome(findkm)withNot_found->None(* Note: find_first/last have to look in both subtrees
as these are little-endian Patricia trees *)letrecfind_first_optf=function|Empty->None|Leaf(j,x)->iffjthenSome(j,x)elseNone|Branch(_,_,l,r)->matchfind_first_optfl,find_first_optfrwith|Some(lk,lv),Some(rk,rv)->iflk<rkthenSome(lk,lv)elseSome(rk,rv)|Somev,None|None,Somev->Somev|None,None->Noneletfind_firstf=function|Empty->raiseNot_found|Leaf(j,x)->iffjthen(j,x)elseraiseNot_found|Branch(_,_,l,r)->matchfind_first_optfl,find_first_optfrwith|Some(lk,lv),Some(rk,rv)->iflk<rkthen(lk,lv)else(rk,rv)|Somev,None|None,Somev->v|None,None->raiseNot_foundletrecfind_last_optf=function|Empty->None|Leaf(j,x)->iffjthenSome(j,x)elseNone|Branch(_,_,l,r)->matchfind_last_optfl,find_last_optfrwith|Some(lk,lv),Some(rk,rv)->iflk>rkthenSome(lk,lv)elseSome(rk,rv)|Somev,None|None,Somev->Somev|None,None->Noneletfind_lastf=function|Empty->raiseNot_found|Leaf(j,x)->iffjthen(j,x)elseraiseNot_found|Branch(_,_,l,r)->matchfind_last_optfl,find_last_optfrwith|Some(lk,lv),Some(rk,rv)->iflk>rkthen(lk,lv)else(rk,rv)|Somev,None|None,Somev->v|None,None->raiseNot_foundletlowest_bitx=xland(-x)letbranching_bitp0p1=lowest_bit(p0lxorp1)letmaskpm=pland(m-1)letjoin(p0,t0,p1,t1)=letm=branching_bitp0p1inifzero_bitp0mthenBranch(maskp0m,m,t0,t1)elseBranch(maskp0m,m,t1,t0)letmatch_prefixkpm=(maskkm)==pletaddkxt=letrecins=function|Empty->Leaf(k,x)|Leaf(j,_)ast->ifj==kthenLeaf(k,x)elsejoin(k,Leaf(k,x),j,t)|Branch(p,m,t0,t1)ast->ifmatch_prefixkpmthenifzero_bitkmthenBranch(p,m,inst0,t1)elseBranch(p,m,t0,inst1)elsejoin(k,Leaf(k,x),p,t)ininstletsingletonkv=addkvemptyletbranch=function|(_,_,Empty,t)->t|(_,_,t,Empty)->t|(p,m,t0,t1)->Branch(p,m,t0,t1)letremovekt=letrecrmv=function|Empty->Empty|Leaf(j,_)ast->ifk==jthenEmptyelset|Branch(p,m,t0,t1)ast->ifmatch_prefixkpmthenifzero_bitkmthenbranch(p,m,rmvt0,t1)elsebranch(p,m,t0,rmvt1)elsetinrmvtletreccardinal=function|Empty->0|Leaf_->1|Branch(_,_,t0,t1)->cardinalt0+cardinalt1letreciterf=function|Empty->()|Leaf(k,x)->fkx|Branch(_,_,t0,t1)->iterft0;iterft1letrecmapf=function|Empty->Empty|Leaf(k,x)->Leaf(k,fx)|Branch(p,m,t0,t1)->Branch(p,m,mapft0,mapft1)letrecmapif=function|Empty->Empty|Leaf(k,x)->Leaf(k,fkx)|Branch(p,m,t0,t1)->Branch(p,m,mapift0,mapift1)letrecfoldfsaccu=matchswith|Empty->accu|Leaf(k,x)->fkxaccu|Branch(_,_,t0,t1)->foldft0(foldft1accu)letrecfor_allp=function|Empty->true|Leaf(k,v)->pkv|Branch(_,_,t0,t1)->for_allpt0&&for_allpt1letrecexistsp=function|Empty->false|Leaf(k,v)->pkv|Branch(_,_,t0,t1)->existspt0||existspt1letrecfilterpr=function|Empty->Empty|Leaf(k,v)ast->ifprkvthentelseEmpty|Branch(p,m,t0,t1)->branch(p,m,filterprt0,filterprt1)letrecfilter_mappr=function|Empty->Empty|Leaf(k,v)->(matchprkvwithSomev'->Leaf(k,v')|None->Empty)|Branch(p,m,t0,t1)->branch(p,m,filter_mapprt0,filter_mapprt1)letpartitionps=letrecpart(t,fasacc)=function|Empty->acc|Leaf(k,v)->ifpkvthen(addkvt,f)else(t,addkvf)|Branch(_,_,t0,t1)->part(partacct0)t1inpart(Empty,Empty)sletrecchoose=function|Empty->raiseNot_found|Leaf(k,v)->(k,v)|Branch(_,_,t0,_)->chooset0(* we know that [t0] is non-empty *)letrecchoose_opt=function|Empty->None|Leaf(k,v)->Some(k,v)|Branch(_,_,t0,_)->choose_optt0(* we know that [t0] is non-empty *)letsplitxm=letcollkv(l,b,r)=ifk<xthenaddkvl,b,relseifk>xthenl,b,addkvrelsel,Somev,rinfoldcollm(empty,None,empty)letrecmin_binding=function|Empty->raiseNot_found|Leaf(k,v)->(k,v)|Branch(_,_,s,t)->let(ks,_)asbs=min_bindingsinlet(kt,_)asbt=min_bindingtinifks<ktthenbselsebtletrecmin_binding_opt=function|Empty->None|Leaf(k,v)->Some(k,v)|Branch(_,_,s,t)->match(min_binding_opts,min_binding_optt)with|None,None->None|None,bt->bt|bs,None->bs|(Some(ks,_)asbs),(Some(kt,_)asbt)->ifks<ktthenbselsebtletrecmax_binding=function|Empty->raiseNot_found|Leaf(k,v)->(k,v)|Branch(_,_,s,t)->let(ks,_)asbs=max_bindingsinlet(kt,_)asbt=max_bindingtinifks>ktthenbselsebtletrecmax_binding_opt=function|Empty->None|Leaf(k,v)->Some(k,v)|Branch(_,_,s,t)->matchmax_binding_opts,max_binding_opttwith|None,None->None|None,bt->bt|bs,None->bs|(Some(ks,_)asbs),(Some(kt,_)asbt)->ifks>ktthenbselsebtletbindingsm=fold(funkvacc->(k,v)::acc)m[](* we order constructors as Empty < Leaf < Branch *)letcomparecmpt1t2=letreccompare_auxt1t2=matcht1,t2with|Empty,Empty->0|Empty,_->-1|_,Empty->1|Leaf(k1,x1),Leaf(k2,x2)->letc=comparek1k2inifc<>0thencelsecmpx1x2|Leaf_,Branch_->-1|Branch_,Leaf_->1|Branch(p1,m1,l1,r1),Branch(p2,m2,l2,r2)->letc=comparep1p2inifc<>0thencelseletc=comparem1m2inifc<>0thencelseletc=compare_auxl1l2inifc<>0thencelsecompare_auxr1r2incompare_auxt1t2letequaleqt1t2=letrecequal_auxt1t2=matcht1,t2with|Empty,Empty->true|Leaf(k1,x1),Leaf(k2,x2)->k1=k2&&eqx1x2|Branch(p1,m1,l1,r1),Branch(p2,m2,l2,r2)->p1=p2&&m1=m2&&equal_auxl1l2&&equal_auxr1r2|_->falseinequal_auxt1t2letmergefm1m2=letaddmk=functionNone->m|Somev->addkvmin(* first consider all bindings in m1 *)letm=fold(funk1v1m->addmk1(fk1(Somev1)(find_optk1m2)))m1emptyin(* then bindings in m2 that are not in m1 *)fold(funk2v2m->ifmemk2m1thenmelseaddmk2(fk2None(Somev2)))m2mletupdatexfm=matchf(find_optxm)with|None->removexm|Somez->addxzmletunsigned_ltnm=n>=0&&(m<0||n<m)letrecunionf=function|Empty,t->t|t,Empty->t|Leaf(k,v1),t->updatek(functionNone->Somev1|Somev2->fkv1v2)t|t,Leaf(k,v2)->updatek(functionNone->Somev2|Somev1->fkv1v2)t|(Branch(p,m,s0,s1)ass),(Branch(q,n,t0,t1)ast)->ifm==n&&match_prefixqpmthen(* The trees have the same prefix. Merge the subtrees. *)branch(p,m,unionf(s0,t0),unionf(s1,t1))elseifunsigned_ltmn&&match_prefixqpmthen(* [q] contains [p]. Merge [t] with a subtree of [s]. *)ifzero_bitqmthenbranch(p,m,unionf(s0,t),s1)elsebranch(p,m,s0,unionf(s1,t))elseifunsigned_ltnm&&match_prefixpqnthen(* [p] contains [q]. Merge [s] with a subtree of [t]. *)ifzero_bitpnthenbranch(q,n,unionf(s,t0),t1)elsebranch(q,n,t0,unionf(s,t1))else(* The prefixes disagree. *)join(p,s,q,t)letunionfst=unionf(s,t)letto_seqm=letrecprepend_seqms=matchmwith|Empty->s|Leaf(k,v)->fun()->Seq.Cons((k,v),s)|Branch(_,_,l,r)->prepend_seql(prepend_seqrs)inprepend_seqmSeq.emptyletto_seq_fromkm=letrecprepend_seqms=matchmwith|Empty->s|Leaf(key,v)->ifkey>=kthenfun()->Seq.Cons((key,v),s)elses|Branch(_,_,l,r)->prepend_seql(prepend_seqrs)inprepend_seqmSeq.emptyletadd_seqsm=Seq.fold_left(funm(k,v)->addkvm)msletof_seqs=Seq.fold_left(funm(k,v)->addkvm)emptys(************************************************************* *)letfind_unifiableskt=letsol=ref[]inletrecaux=function|Empty->()|Leaf(j,x)->ifklandj==kthensol:=x::!sol|Branch(_,m,l,r)->ifzero_bitkmthen(auxr;auxl)elseauxrinauxt;!solletto_lists=letrecelements_auxacc=function|Empty->acc|Leaf(k,x)->(k,x)::acc|Branch(_,_,l,r)->elements_aux(elements_auxaccl)rinList.sort(fun(k1,_)(k2,_)->Stdlib.comparek1k2)(elements_aux[]s)letppffmtm=letl=to_listminElpi_util.Util.(pplist(pp_pairInt.ppf)" "fmtl)letshowfm=letb=Buffer.create20inletfmt=Format.formatter_of_bufferbinppffmtm;Buffer.contentsb