123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat a l'energie atomique et aux energies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It 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. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)(* ---------------------------------------------------------------------- *)(* --- Patricia Trees By L. Correnson & P. Baudin --- *)(* ---------------------------------------------------------------------- *)type'at=|Empty|Lfofint*'a|Brofint*'at*'at(* -------------------------------------------------------------------------- *)(* --- Bit library --- *)(* -------------------------------------------------------------------------- *)lethsb=lethsbp=ifpland2!=0then1else0inlethsbp=letn=plsr2inifn!=0then2+hsbnelsehsbpinlethsbp=letn=plsr4inifn!=0then4+hsbnelsehsbpinlethsb=Array.init256hsbinlethsbp=letn=plsr8inifn!=0then8+hsb.(n)elsehsb.(p)inlethsbp=letn=plsr16inifn!=0then16+hsbnelsehsbpinmatchSys.word_sizewith|32->hsb|64->(functionp->letn=plsr32inifn!=0then32+hsbnelsehsbp)|_->assertfalselethighest_bitx=1lsl(hsbx)letlowest_bitx=xland(-x)letdecode_maskp=lowest_bit(lnotp)(* -------------------------------------------------------------------------- *)(* --- Debug --- *)(* -------------------------------------------------------------------------- *)letpp_maskmfmtp=beginletbits=Array.make63falseinletlast=ref0infori=0to62doletu=1lsliinifulandp<>0thenbits.(i)<-true;ifu==mthenlast:=i;done;Format.pp_print_charfmt'*';fori=!last-1downto0doFormat.pp_print_charfmt(ifbits.(i)then'1'else'0');done;endletpp_bitsfmtk=beginletbits=Array.make63falseinletlast=ref0infori=0to62doif(1lsli)landk<>0then(bits.(i)<-true;ifi>!lastthenlast:=i);done;fori=!lastdownto0doFormat.pp_print_charfmt(ifbits.(i)then'1'else'0');done;endletrecpp_treetabfmt=function|Empty->()|Lf(k,_)->Format.fprintffmt"%sL%a=%d@\n"tabpp_bitskk|Br(p,l,r)->letnext=tab^" "inpp_treenextfmtl;Format.fprintffmt"%s@@%a@\n"tab(pp_mask(decode_maskp))p;pp_treenextfmtr(* -------------------------------------------------------------------------- *)(* --- Bit utilities --- *)(* -------------------------------------------------------------------------- *)letdecode_maskp=lowest_bit(lnotp)letbranching_bitp0p1=highest_bit(p0lxorp1)letmaskpm=(plor(m-1))land(lnotm)letzero_bit_intkm=(klandm)==0letzero_bitkp=zero_bit_intk(decode_maskp)letmatch_prefix_intkpm=(maskkm)==pletmatch_prefixkp=match_prefix_intkp(decode_maskp)letincluded_mask_intmn=(* m mask is strictly included into n *)(* can not use (m < n) when n is (1 lsl 62) = min_int < 0 *)(* must use (0 < (n-m) instead *)0>n-mletincluded_prefixpq=letm=decode_maskpinletn=decode_maskqinincluded_mask_intmn&&match_prefix_intqpm(* -------------------------------------------------------------------------- *)(* --- Smart Constructors --- *)(* -------------------------------------------------------------------------- *)letempty=Emptyletsingletonkx=Lf(k,x)letlfk=functionNone->Empty|Somex->Lf(k,x)(* good sharing *)letlf0kx't'=functionNone->Empty|Somex->ifx==x'thent'elseLf(k,x)(* good sharing *)letbr0pt0't1't'=function|Empty->t1'|t0->ift0'==t0thent'elseBr(p,t0,t1')(* good sharing *)letbr1pt0't1't'=function|Empty->t0'|t1->ift1'==t1thent'elseBr(p,t0',t1)letjoinpt0qt1=letm=branching_bitpqinletr=maskpminifzero_bitprthenBr(r,t0,t1)elseBr(r,t1,t0)(* t0 and t1 has different prefix, but best common prefix is unknown *)letgluet0t1=matcht0,t1with|Empty,t|t,Empty->t|(Lf(p,_)|Br(p,_,_)),(Lf(q,_)|Br(q,_,_))->joinpt0qt1letglue0t0t0't1't'=ift0==t0'thent'elsegluet0t1'letglue1t1t0't1't'=ift1==t1'thent'elsegluet0't1letglue01t0t1t0't1't'=ift0==t0'&&t1==t1'thent'elsegluet0t1letglue2t0t1t0't1't's0's1's'=ift0==s0'&&t1==s1'thens'elseift0==t0'&&t1==t1'thent'elsegluet0t1(* -------------------------------------------------------------------------- *)(* --- Access API --- *)(* -------------------------------------------------------------------------- *)letis_empty=function|Empty->true|Lf_|Br_->falseletsizet=letrecwalkn=function|Empty->n|Lf_->succn|Br(_,a,b)->walk(walkna)binwalk0tletrecmemk=function|Empty->false|Lf(i,_)->i=k|Br(p,t0,t1)->match_prefixkp&&memk(ifzero_bitkpthent0elset1)letrecfindqk=function|Empty->raiseNot_found|Lf(i,x)ast->ifk=ithen(x,t)elseraiseNot_found|Br(p,t0,t1)->ifmatch_prefixkpthenfindqk(ifzero_bitkpthent0elset1)elseraiseNot_foundletfindkm=fst(findqkm)(* -------------------------------------------------------------------------- *)(* --- Comparison --- *)(* -------------------------------------------------------------------------- *)letreccomparecmpst=ifs==tthen0elsematchs,twith|Empty,Empty->0|Empty,_->(-1)|_,Empty->1|Lf(i,x),Lf(j,y)->letck=Stdlib.compareijinifck=0thencmpxyelseck|Lf_,_->(-1)|_,Lf_->1|Br(p,s0,s1),Br(q,t0,t1)->letcp=Stdlib.comparepqinifcp<>0thencpelseletc0=comparecmps0t0inifc0<>0thenc0elsecomparecmps1t1letrecequaleqst=ifs==tthentrueelsematchs,twith|Empty,Empty->true|Empty,_->false|_,Empty->false|Lf(i,x),Lf(j,y)->i==j&&eqxy|Lf_,_->false|_,Lf_->false|Br(p,s0,s1),Br(q,t0,t1)->p==q&&equaleqs0t0&&equaleqs1t1(* -------------------------------------------------------------------------- *)(* --- Addition, Insert, Change, Remove --- *)(* -------------------------------------------------------------------------- *)(* good sharing *)letrecchangephikx=function|Emptyast->(matchphikxNonewith|None->t|Somew->Lf(k,w))|Lf(i,y)ast->ifi=kthenlf0kyt(phikx(Somey))else(matchphikxNonewith|None->t|Somew->lets=Lf(k,w)injoinksit)|Br(p,t0,t1)ast->ifmatch_prefixkpthen(* k belongs to tree *)ifzero_bitkpthenbr0pt0t1t(changephikxt0)(* k is in t0 *)elsebr1pt0t1t(changephikxt1)(* k is in t1 *)else(* k is disjoint from tree *)(matchphikxNonewith|None->t|Somew->lets=Lf(k,w)injoinkspt)(* good sharing *)letinsertfkx=change(fun_kx->function|None->Somex|Someold->Some(fkxold))kx(* good sharing *)letaddkx=change(fun_kx_old->Somex)kx(* good sharing *)letremovek=change(fun_k()_old->None)k()(* -------------------------------------------------------------------------- *)(* --- Map --- *)(* -------------------------------------------------------------------------- *)letmapiphi=letrecmapiphi=function|Empty->Empty|Lf(k,x)->Lf(k,phikx)|Br(p,t0,t1)->lett0=mapiphit0inlett1=mapiphit1inBr(p,t0,t1)infunction(* to be sorted *)|Empty->Empty|Lf(k,x)->Lf(k,phikx)|Br(p,t0,t1)whenp=max_int->lett1=mapiphit1inlett0=mapiphit0inBr(p,t0,t1)|Br(p,t0,t1)->lett0=mapiphit0inlett1=mapiphit1inBr(p,t0,t1)letmapphi=mapi(fun_x->phix)letmapfphi=letrecmapfphi=function|Empty->Empty|Lf(k,x)->lfk(phikx)|Br(_,t0,t1)->glue(mapfphit0)(mapfphit1)infunction(* to be sorted *)|Empty->Empty|Lf(k,x)->lfk(phikx)|Br(p,t0,t1)whenp=max_int->lett1=mapfphit1inlett0=mapfphit0ingluet0t1|Br(_,t0,t1)->lett0=mapfphit0inlett1=mapfphit1ingluet0t1(* good sharing *)letmapqphi=letrecmapqphi=function|Emptyast->t|Lf(k,x)ast->lf0kxt(phikx)|Br(_,t0,t1)ast->lett0'=mapqphit0inlett1'=mapqphit1inglue01t0't1't0t1tinfunction(* to be sorted *)|Emptyast->t|Lf(k,x)ast->lf0kxt(phikx)|Br(p,t0,t1)astwhenp=max_int->lett1'=mapqphit1inlett0'=mapqphit0inglue01t0't1't0t1t|Br(_,t0,t1)ast->lett0'=mapqphit0inlett1'=mapqphit1inglue01t0't1't0t1t(* good sharing *)letfilterfm=mapq(funkv->iffkvthenSomevelseNone)m(* good sharing *)letrecpartitionp=function|Emptyast->(t,t)|Lf(k,x)ast->ifpkxthent,EmptyelseEmpty,t|Br(_,t0,t1)ast->let(t0',u0')=partitionpt0inlet(t1',u1')=partitionpt1inift0'==t0&&t1'==t1then(t,u0')(* u0' and u1' are empty *)elseifu0'==t0&&u1'==t1then(t0',t)(* t0' and t1' are empty *)else(gluet0't1'),(glueu0'u1')(* good sharing *)letrecpartition_splitp=function|Emptyast->(t,t)|Lf(k,x)ast->letu,v=pkxin(lf0kxtu),(lf0kxtv)|Br(_,t0,t1)ast->lett0',u0'=partition_splitpt0inlett1',u1'=partition_splitpt1inift0'==t0&&t1'==t1then(t,u0')(* u0' and u1' are empty *)elseifu0'==t0&&u1'==t1then(t0',t)(* t0' and t1' are empty *)else(gluet0't1'),(glueu0'u1')(* -------------------------------------------------------------------------- *)(* --- Iter --- *)(* -------------------------------------------------------------------------- *)letiteriphi=letrecaux=function|Empty->()|Lf(k,x)->phikx|Br(_,t0,t1)->auxt0;auxt1infunction(* to be sorted *)|Empty->()|Lf(k,x)->phikx|Br(p,t0,t1)whenp=max_int->auxt1;auxt0|Br(_,t0,t1)->auxt0;auxt1letiterphi=iteri(fun_x->phix)letfoldiphite=(* increasing order *)letrecauxte=matchtwith|Empty->e|Lf(i,x)->phiixe|Br(_,t0,t1)->auxt1(auxt0e)inmatchtwith(* to be sorted *)|Empty->e|Lf(i,x)->phiixe|Br(p,t0,t1)whenp=max_int->auxt0(auxt1e)|Br(_,t0,t1)->auxt1(auxt0e)letfoldphi=foldi(fun_xe->phixe)letfolddphite=(* decreasing order *)letrecauxte=matchtwith|Empty->e|Lf(i,x)->phiixe|Br(_,t0,t1)->auxt0(auxt1e)inmatchtwith(* to be sorted *)|Empty->e|Lf(i,x)->phiixe|Br(p,t0,t1)whenp=max_int->auxt1(auxt0e)|Br(_,t0,t1)->auxt0(auxt1e)(* decreasing order on f to have the list in increasing order *)letmaplfm=foldd(funkva->(fkv)::a)m[]letfor_allphi=(* increasing order *)letrecaux=function|Empty->true|Lf(k,x)->phikx|Br(_,t0,t1)->auxt0&&auxt1infunction(* to be sorted *)|Empty->true|Lf(k,x)->phikx|Br(p,t0,t1)whenp=max_int->auxt1&&auxt0|Br(_,t0,t1)->auxt0&&auxt1letexistsphi=(* increasing order *)letrecaux=function|Empty->false|Lf(k,x)->phikx|Br(_,t0,t1)->auxt0||auxt1infunction(* to be sorted *)|Empty->false|Lf(k,x)->phikx|Br(p,t0,t1)whenp=max_int->auxt1||auxt0|Br(_,t0,t1)->auxt0||auxt1(* -------------------------------------------------------------------------- *)(* --- Inter --- *)(* -------------------------------------------------------------------------- *)letoccurit=trySome(findit)withNot_found->Noneletrecinterilf_phist=matchs,twith|Empty,_->Empty|_,Empty->Empty|Lf(i,x),Lf(j,y)->ifi=jthenlf_phiixyelseEmpty|Lf(i,x),Br_->(matchoccuritwithNone->Empty|Somey->lf_phiixy)|Br_,Lf(j,y)->(matchoccurjswithNone->Empty|Somex->lf_phijxy)|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)glue(interilf_phis0t0)(interilf_phis1t1)elseifincluded_prefixpqthen(* q contains p. Intersect t with a subtree of s *)ifzero_bitqptheninterilf_phis0t(* t has bit m = 0 => t is inside s0 *)elseinterilf_phis1t(* t has bit m = 1 => t is inside s1 *)elseifincluded_prefixqpthen(* p contains q. Intersect s with a subtree of t *)ifzero_bitpqtheninterilf_phist0(* s has bit n = 0 => s is inside t0 *)elseinterilf_phist1(* t has bit n = 1 => s is inside t1 *)else(* prefix disagree *)Emptyletinterphi=interi(funixy->Lf(i,phiixy))letinterfphi=interi(funixy->lfi(phiixy))(* good sharing with s *)letlfqphiixyst=matchphiixywithNone->Empty|Somew->ifw==xthenselseifw==ythentelseLf(i,w)letoccur0phiixst=trylet(y,t)=findqitinlfqphiixystwithNot_found->Emptyletoccur1phijyst=trylet(x,s)=findqjsinlfqphijxystwithNot_found->Empty(* good sharing with s *)letrecinterqphist=matchs,twith|Empty,_->s|_,Empty->t|Lf(i,x),Lf(j,y)->ifi=jthenlfqphiixystelseEmpty|Lf(i,x),Br_->occur0phiixst|Br_,Lf(j,y)->occur1phijyst|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)glue2(interqphis0t0)(interqphis1t1)s0s1st0t1telseifincluded_prefixpqthen(* q contains p. Intersect t with a subtree of s *)ifzero_bitqptheninterqphis0t(* t has bit m = 0 => t is inside s0 *)elseinterqphis1t(* t has bit m = 1 => t is inside s1 *)elseifincluded_prefixqpthen(* p contains q. Intersect s with a subtree of t *)ifzero_bitpqtheninterqphist0(* s has bit n = 0 => s is inside t0 *)elseinterqphist1(* t has bit n = 1 => s is inside t1 *)else(* prefix disagree *)Empty(* -------------------------------------------------------------------------- *)(* --- Union --- *)(* -------------------------------------------------------------------------- *)(* good sharing with s *)letbr2ups0's1's't0't1't't0t1=ifs0'==t0&&s1'==t1thens'elseift0'==t0&&t1'==t1thent'elseBr(p,t0,t1)(* good sharing with s *)letbr0upt0't1't't0=ift0'==t0thent'elseBr(p,t0,t1')letbr1upt0't1't't1=ift1'==t1thent'elseBr(p,t0',t1)(* good sharing with s *)letrecunionphist=matchs,twith|Empty,_->t|_,Empty->s|Lf(i,x),Lf(j,y)->ifi=jthenletw=phiixyinifw==xthenselseifw==ythentelseLf(i,w)elsejoinisjt|Lf(i,x),Br_->insertphiixt|Br_,Lf(j,y)->insert(funjyx->phijxy)jys|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)br2ups0s1st0t1t(unionphis0t0)(unionphis1t1)elseifincluded_prefixpqthen(* q contains p. Merge t with a subtree of s *)ifzero_bitqpthenbr0ups0s1s(unionphis0t)(* t has bit m = 0 => t is inside s0 *)elsebr1ups0s1s(unionphis1t)(* t has bit m = 1 => t is inside s1 *)elseifincluded_prefixqpthen(* p contains q. Merge s with a subtree of t *)ifzero_bitpqthenbr0uqt0t1t(unionphist0)(* s has bit n = 0 => s is inside t0 *)elsebr1uqt0t1t(unionphist1)(* t has bit n = 1 => s is inside t1 *)else(* prefix disagree *)joinpsqt(* -------------------------------------------------------------------------- *)(* --- Merge --- *)(* -------------------------------------------------------------------------- *)letmap1phis=mapf(funix->phii(Somex)None)sletmap2phit=mapf(funjy->phijNone(Somey))tletrecmergephist=matchs,twith|Empty,_->map2phit|_,Empty->map1phis|Lf(i,x),Lf(j,y)->ifi=jthenlfi(phii(Somex)(Somey))elseleta=lfi(phii(Somex)None)inletb=lfj(phijNone(Somey))inglueab|Lf(i,x),Br(q,t0,t1)->ifmatch_prefixiqthen(* leaf i is in tree t *)ifzero_bitiqthenglue(mergephist0)(map2phit1)(* s=i is in t0 *)elseglue(map2phit0)(mergephist1)(* s=i is in t1 *)else(* leaf i does not appear in t *)glue(lfi(phii(Somex)None))(map2phit)|Br(p,s0,s1),Lf(j,y)->ifmatch_prefixjpthen(* leaf j is in tree s *)ifzero_bitjpthenglue(mergephis0t)(map1phis1)(* t=j is in s0 *)elseglue(map1phis0)(mergephis1t)(* t=j is in s1 *)else(* leaf j does not appear in s *)glue(map1phis)(lfj(phijNone(Somey)))|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)glue(mergephis0t0)(mergephis1t1)elseifincluded_prefixpqthen(* q contains p. Merge t with a subtree of s *)ifzero_bitqpthen(* t has bit m = 0 => t is inside s0 *)glue(mergephis0t)(map1phis1)else(* t has bit m = 1 => t is inside s1 *)glue(map1phis0)(mergephis1t)elseifincluded_prefixqpthen(* p contains q. Merge s with a subtree of t *)ifzero_bitpqthen(* s has bit n = 0 => s is inside t0 *)glue(mergephist0)(map2phit1)else(* s has bit n = 1 => s is inside t1 *)glue(map2phit0)(mergephist1)elseglue(map1phis)(map2phit)(* good sharing with s *)letrecdiffqphist=matchs,twith|Empty,_->s|_,Empty->s|Lf(i,x),Lf(j,y)->ifi=jthenlfqphiixystelses|Lf(i,x),Br_->(matchoccuritwithNone->s|Somey->lfqphiixyst)|Br_,Lf(j,y)->change(funjyx->matchxwithNone->None|Somex->phijxy)jys|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)lett0'=(diffqphis0t0)inlett1'=(diffqphis1t1)inglue01t0't1's0s1selseifincluded_prefixpqthen(* q contains p. *)ifzero_bitqpthen(* t has bit m = 0 => t is inside s0 *)lets0'=(diffqphis0t)inglue0s0's0s1selse(* t has bit m = 1 => t is inside s1 *)lets1'=(diffqphis1t)inglue1s1's0s1selseifincluded_prefixqpthen(* p contains q. *)ifzero_bitpqthendiffqphist0(* s has bit n = 0 => s is inside t0 *)elsediffqphist1(* t has bit n = 1 => s is inside t1 *)else(* prefix disagree *)s(* -------------------------------------------------------------------------- *)(* --- Iter Kernel --- *)(* -------------------------------------------------------------------------- *)letreciterkphist=matchs,twith|Empty,_|_,Empty->()|Lf(i,x),Lf(j,y)->ifi=jthenphiixy|Lf(i,x),Br_->(matchoccuritwithNone->()|Somey->phiixy)|Br_,Lf(j,y)->(matchoccurjswithNone->()|Somex->phijxy)|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)(iterkphis0t0;iterkphis1t1)elseifincluded_prefixpqthen(* q contains p. Intersect t with a subtree of s *)ifzero_bitqptheniterkphis0t(* t has bit m = 0 => t is inside s0 *)elseiterkphis1t(* t has bit m = 1 => t is inside s1 *)elseifincluded_prefixqpthen(* p contains q. Intersect s with a subtree of t *)ifzero_bitpqtheniterkphist0(* s has bit n = 0 => s is inside t0 *)elseiterkphist1(* t has bit n = 1 => s is inside t1 *)else(* prefix disagree *)()(* -------------------------------------------------------------------------- *)(* --- Iter2 --- *)(* -------------------------------------------------------------------------- *)letiter21phis=iteri(funix->phii(Somex)None)sletiter22phit=iteri(funjy->phijNone(Somey))tletreciter2phist=matchs,twith|Empty,_->iter22phit|_,Empty->iter21phis|Lf(i,x),Lf(j,y)->ifi=jthenphii(Somex)(Somey)else(phii(Somex)None;phijNone(Somey))|Lf(i,x),Br(q,t0,t1)->ifmatch_prefixiqthen(* leaf i is in tree t *)ifzero_bitiqthen(iter2phist0;iter22phit1)(* s=i is in t0 *)else(iter22phit0;iter2phist1)(* s=i is in t1 *)else(* leaf i does not appear in t *)(phii(Somex)None;iter22phit)|Br(p,s0,s1),Lf(j,y)->ifmatch_prefixjpthen(* leaf j is in tree s *)ifzero_bitjpthen(iter2phis0t;iter21phis1)(* t=j is in s0 *)else(iter21phis0;iter2phis1t)(* t=j is in s1 *)else(* leaf j does not appear in s *)(iter21phis;phijNone(Somey))|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)(iter2phis0t0;iter2phis1t1)elseifincluded_prefixpqthen(* q contains p. Merge t with a subtree of s *)ifzero_bitqpthen(* t has bit m = 0 => t is inside s0 *)(iter2phis0t;iter21phis1)else(* t has bit m = 1 => t is inside s1 *)(iter21phis0;iter2phis1t)elseifincluded_prefixqpthen(* p contains q. Merge s with a subtree of t *)ifzero_bitpqthen(* s has bit n = 0 => s is inside t0 *)(iter2phist0;iter22phit1)else(* s has bit n = 1 => s is inside t1 *)(iter22phit0;iter2phist1)else(iter21phis;iter22phit)(* -------------------------------------------------------------------------- *)(* --- Intersects --- *)(* -------------------------------------------------------------------------- *)letrecintersectfphist=matchs,twith|Empty,_->false|_,Empty->false|Lf(i,x),Lf(j,y)->ifi=jthenphiixyelsefalse|Lf(i,x),Br_->(matchoccuritwithNone->false|Somey->phiixy)|Br_,Lf(j,y)->(matchoccurjswithNone->false|Somex->phijxy)|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)(intersectfphis0t0)||(intersectfphis1t1)elseifincluded_prefixpqthen(* q contains p. Intersect t with a subtree of s *)ifzero_bitqpthenintersectfphis0t(* t has bit m = 0 => t is inside s0 *)elseintersectfphis1t(* t has bit m = 1 => t is inside s1 *)elseifincluded_prefixqpthen(* p contains q. Intersect s with a subtree of t *)ifzero_bitpqthenintersectfphist0(* s has bit n = 0 => s is inside t0 *)elseintersectfphist1(* t has bit n = 1 => s is inside t1 *)else(* prefix disagree *)falseletintersectst=intersectf(fun_i_x_y->true)st(* -------------------------------------------------------------------------- *)(* --- Subset --- *)(* -------------------------------------------------------------------------- *)letrecsubsetfphist=matchs,twith|Empty,_->true|_,Empty->false|Lf(i,x),Lf(j,y)->ifi=jthenphiixyelsefalse|Lf(i,x),Br_->(matchoccuritwithNone->false|Somey->phiixy)|Br_,Lf_->false|Br(p,s0,s1),Br(q,t0,t1)->ifp==qthen(* prefixes agree *)(subsetfphis0t0&&subsetfphis1t1)elseifincluded_prefixpqthen(* q contains p: t is included in a (strict) subtree of s *)falseelseifincluded_prefixqpthen(* p contains q: s is included in a subtree of t *)ifzero_bitpqthensubsetfphist0(* s has bit n = 0 => s is inside t0 *)elsesubsetfphist1(* t has bit n = 1 => s is inside t1 *)else(* prefix disagree *)falseletsubset=subsetfletsubsetkst=subsetf(fun_i_x_y->true)st(* -------------------------------------------------------------------------- *)