123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898(*BEGIN INJECTIVITY*)type!+'at=(*ELSE*)type+'at=(*END*)|Nil|Leafof{mutablemark:int;v:'a;}|Joinof{mutablemark:int;l:'at;r:'at;}type'aseq='atletempty=Nillet elementv=Leaf{mark=0;v}letmask_bits=2letmaxiab:int=ifb>athenbelsealetrank=function|Nil->0|Leaf t->ift.mark<>0theninvalid_arg"Lwd_seq.rank: node is marked";0|Joint->ift.marklandmask_bits<>0theninvalid_arg"Lwd_seq.rank: nodeismarked";t.marklsrmask_bitsletconcatab=matcha,bwith|Nil,x|x,Nil->x|l,r->Join{mark=(maxi(rankl)(rankr)+1)lslmask_bits;l;r}type('a,'b)view=|Empty|Elementof'a|Concatof'b*'bletview=function|Nil->Empty|Leaft->Elementt.v|Joint->Concat(t.l,t.r)module Balanced:sigtype'at=private'aseqvalempty:'atvalelement:'a->'atvalconcat:'at->'at->'atvalview:'at->('a,'at)viewend=structtype'at='aseqletempty=emptyletelement=elementletchecklr=abs(l-r)<=1letrecnode_leftlr=letml=ranklinletmr=rankrinifcheckmlmrthenconcatlrelsematchlwith|Nil|Leaf_->assertfalse|Joint->ifcheck(rankt.l)mlthenconcatt.l(node_leftt.rr)elsematcht.rwith|Nil|Leaf_->assertfalse|Jointr->lettrr=node_lefttr.rrinifcheck(1+maxi(rankt.l)(ranktr.l))(ranktrr)thenconcat(concatt.ltr.l)trrelseconcat t.l(concattr.ltrr)letrecnode_rightlr=letml=ranklinletmr=rankrinifcheckmrmlthenconcatlrelsematchrwith|Nil|Leaf_->assertfalse|Joint->ifcheck(rankt.r)mrthenconcat(node_rightlt.l)t.relsematcht.lwith|Nil|Leaf_->assertfalse|Jointl->lettll=node_rightltl.linifcheck(1+maxi(ranktl.r)(rankt.r))(ranktll)thenconcattll(concattl.rt.r)elseconcat(concattlltl.r)t.rlet concatlr=letml=ranklinletmr=rankrinifcheckmlmrthenconcatlrelseifml<=mrthennode_rightlrelsenode_leftlrletview=viewendmodule Marking:sigtype mark=(*private*)intvalis_shared:mark->boolvalis_not_shared:mark->boolvalis_none:mark->boolvalis_both:mark->boolvalis_old:mark->boolvalis_new:mark->bool(*val has_old : mark -> bool*)(*val has_new : mark -> bool*)valset_both :mark->markvalunmark :mark->markvalget_index:mark->intvalwith_index_new:int->marktypestatsvalmarked:stats->intvalshared:stats->intvalblocked:stats->inttype traversalvalold_stats:traversal ->statsvalnew_stats:traversal->statsvalunsafe_traverse :old_root:_seq->new_root:_seq->traversalvalrestore:_seq->unitend=structtypemark=intletmask_none=0letmask_old=1letmask_new=2letmask_both=3letis_sharedm=m=-1letis_not_sharedm=m<>-1letis_nonem=mland mask_both=mask_noneletis_bothm=mland mask_both=mask_bothletis_oldm=mland mask_both=mask_oldletis_newm=mlandmask_both=mask_new(*let has_old m = m land mask_old <> 0*)(*let has_new m = m land mask_new <> 0*)letset_bothm=mlormask_bothletget_indexm=mlsrmask_bitsletwith_index_newindex=(indexlslmask_bits)lormask_newletunmarkm=mlandlnotmask_bothtypestats={mutablemarked:int;mutableshared:int;mutableblocked:int;}letmarkeds=s.markedletshareds=s.sharedletblockeds=s.blockedletmk_stats()={marked=0;shared=0;blocked=0}letnew_markedstats=stats.marked<-stats.marked+1letnew_sharedstats=stats.shared<-stats.shared+1letnew_blockedstats=stats.blocked<-stats.blocked+1letrecblockstatsmask=function|Nil->()|Leaft'->letmark=t'.markinifmarklandmask_both<>mask_both&&marklandmask_both<>0then(ifmarklandmask=0thennew_markedstatselseassertfalse;new_blockedstats;t'.mark<-marklormask_both)|Joint'->letmark=t'.markinifmarklandmask_both<>mask_both&&marklandmask_both<>0then(ifmarklandmask=0thennew_markedstatselseassertfalse;new_blockedstats;t'.mark<- marklormask_both;block statsmaskt'.l;blockstats maskt'.r;)letenqueuestatsqmask=function|Nil->()|Leaft'->letmark=t'.markinifmarklandmask=0then((* Not yet seen *)new_markedstats;ifmarklandmask_both<>0then((* Newly shared, clear mask *)t'.mark<--1;new_blockedstats;new_sharedstats;)elset'.mark<-marklormask;);ifmark<>-1&&marklandmask_both=mask_boththen(t'.mark<--1;new_sharedstats)|Joint'ast->letmark=t'.markinifmarklandmask=0then((* Not yet seen *)new_markedstats;ifmarklandmask_both<>0then((* Newly shared, clear mask *)t'.mark<--1;new_blockedstats;new_sharedstats;blockstatsmaskt'.l;blockstatsmaskt'.r;)else((* First mark *)t'.mark<-marklormask;Queue.push tq));ifmark<>-1&&marklandmask_both=mask_boththen(t'.mark<--1;new_shared stats)letdequeuestatsqmask=matchQueue.popqwith|Joint->ift.marklandmask_both =maskthen(enqueuestatsqmaskt.l;enqueuestatsqmaskt.r;)|_->assertfalselettraverse1 statsqmask=whilenot(Queue.is_emptyq)dodequeuestatsqmaskdoneletrectraversesoldsnewqoldqnew=ifQueue.is_emptyqoldthentraverse1snewqnewmask_newelseifQueue.is_emptyqnewthentraverse1soldqoldmask_oldelse(dequeue soldqoldmask_old;dequeue snewqnewmask_new;traversesoldsnewqoldqnew)typetraversal ={old_stats:stats;new_stats:stats;}let old_statstr=tr.old_statsletnew_statstr=tr.new_statsletunsafe_traverse~old_root~new_root=letold_stats=mk_stats()inletnew_stats=mk_stats()inletold_queue=Queue.create()inletnew_queue =Queue.create()inenqueueold_statsold_queuemask_oldold_root;enqueuenew_statsnew_queuemask_newnew_root;traverseold_statsnew_statsold_queuenew_queue;{old_stats;new_stats}letrestore=function|Nil->()|Leaft->t.mark<-0|Joint->t.mark<-(maxi(rankt.l)(rankt.r)+1)lslmask_bitsend(* Marks go through many states.
A mark is usually split in two parts:
- the mask, made of the two least significant bits
- the index is an unsigned integer formed of all the remaining bits
The exception is the distinguished mask with value -1 (all bits set to 1)
that denote a "locked" node.
When the mask is 0, the index denotes the rank of the node: the depth of
the tree rooted at this node.
When the mask is non-zero, the index meaning is left to the traversal
algorithm.
Restoring the mark sets the mask to 0 and the indext to the rank,
but is only possible when the children of the node are themselves restored.
*)moduleReducer=structtype(+'a,'b)xform=|XEmpty|XLeafof{a:'at;mutableb:'boption;}|XJoinof{a:'at;mutableb:'boption;l:('a,'b)xform;r:('a,'b)xform;}type('a,'b)unmark_state={dropped:'boptionarray;mutabledropped_leaf:int;mutabledropped_join:int;shared :'aseq array;shared_x:('a,'b)xform listarray;mutableshared_index:int;}letnext_shared_indexst=letresult=st.shared_indexinst.shared_index<-result+1;resultletrecunblock=function|XEmpty->()|XLeaf{a=Nil|Join_;_}->assertfalse|XJoin{a=Nil|Leaf_;_}->assertfalse|XLeaf{a=Leaft';_}->letmark=t'.markinifMarking.is_not_sharedmark&&Marking.is_bothmarkthent'.mark<-Marking.unmarkmark;|XJoin{a=Joint';l;r;_}->letmark=t'.markinifMarking.is_not_sharedmark&&Marking.is_bothmarkthen(t'.mark<-Marking.unmarkmark;unblockl;unblockr)letrecunmark_oldst=function|XEmpty->()|XLeaf{a=Nil|Join_;_}->assertfalse|XJoin{a=Nil|Leaf_;_}->assertfalse|XLeaf {a=Leaft'asa;b}ast->let mark=t'.markinifMarking.is_oldmarkthen(letdropped_leaf =st.dropped_leafinifdropped_leaf>-1then(st.dropped.(dropped_leaf)<-b;st.dropped_leaf<-dropped_leaf+1;assert(st.dropped_leaf<=st.dropped_join););t'.mark<-Marking.unmarkmark)elseifMarking.is_sharedmarkthen(letindex=next_shared_indexstinst.shared.(index)<-a;st.shared_x.(index)<-[t];t'.mark<-Marking.with_index_newindex;)else ifMarking.is_newmarkthen(letindex=Marking.get_indexmarkinst.shared_x.(index)<-t::st.shared_x.(index);)elseifMarking.is_bothmarkthen(assertfalse(*t'.mark <- mark land lnotboth_mask*))|XJoin{a=Join t'asa;l;r;b}ast->letmark=t'.markinif Marking.is_sharedmarkthen(letindex=next_shared_indexstinst.shared.(index)<-a;st.shared_x.(index)<-[t];t'.mark<-Marking.with_index_newindex;unblockl;unblockr;)elseifMarking.is_oldmarkthen(ifst.dropped_join >-1then(letdropped_join =st.dropped_join -1inst.dropped.(dropped_join)<-b;st.dropped_join <-dropped_join;assert(st.dropped_leaf<=st.dropped_join););t'.mark <-Marking.unmarkmark;unmark_oldstl;unmark_old str;)else ifMarking.is_newmarkthen(letindex=marklsrmask_bitsinst.shared_x.(index)<-t::st.shared_x.(index);)elseifMarking.is_bothmarkthen(assertfalse)letprepare_sharedst=fori=0tost.shared_index-1dobeginmatchst.shared.(i)with|Nil->()|Leaft->t.mark<-Marking.set_botht.mark|Joint->t.mark<-Marking.set_botht.markend;matchst.shared_x.(i)with|[]-> assertfalse|[_]-> ()|xs->st.shared_x.(i)<-List.revxsdoneletrecunmark_newst=function|Nil ->XEmpty|Leaft'ast->letmark=t'.markinifMarking.is_not_sharedmark&&Marking.is_bothmarkthen(let index=marklsrmask_bitsinmatchst.shared_x.(index)with|[]-> XLeaf{a=t;b=None}|x::xs->st.shared_x.(index)<-xs;x)else(t'.mark<-0;XLeaf{a=t;b=None})|Joint'ast->letmark=t'.mark inifmark=-1then(letindex=next_shared_indexstint'.mark<-0;st.shared.(index)<-t;letl=unmark_newstt'.linletr=unmark_newstt'.rinXJoin{a=t;b=None;l;r})elseifMarking.is_bothmarkthen(let index=marklsrmask_bitsinmatchst.shared_x.(index)with|[]->assertfalse|x::xs->st.shared_x.(index)<-xs;ifxs==[]thent'.mark<-0;x)else(t'.mark<-Marking.unmarkt'.mark;letl=unmark_newstt'.linletr=unmark_newstt'.rinXJoin{a=t;b=None;l;r})type'bdropped={leaves:int;table:'boptionarray;extra_leaf:'blist;extra_join:'blist;}letno_dropped={leaves=0;table=[||];extra_leaf=[];extra_join =[]}letdiffget_droppedxoldtnew=matchxold,tnewwith|XEmpty,Nil->no_dropped,XEmpty|(XLeaf{a;_}|XJoin {a;_}),_whena==tnew-> no_dropped,xold|_->lettraversal=Marking.unsafe_traverse~old_root:(matchxoldwith|XEmpty->empty|(XLeaf{a;_}|XJoin{a;_})->a)~new_root:tnewinletsold =Marking.old_statstraversal inletsnew=Marking.new_statstraversalinletnb_dropped=Marking.markedsold-(Marking.blockedsold+Marking.blockedsnew)inletnb_shared=Marking.sharedsold+Marking.sharedsnewinletst={dropped =ifget_droppedthenArray.makenb_droppedNoneelse[||];dropped_leaf=ifget_droppedthen0else-1;dropped_join=ifget_droppedthennb_droppedelse-1;shared=Array.makenb_sharedNil;shared_x=Array.makenb_shared[];shared_index=0;}in(*Printf.eprintf "sold.shared:%d sold.marked:%d sold.blocked:%d\n%!"
sold.shared sold.marked sold.blocked;
Printf.eprintf "snew.shared:%d snew.marked:%d snew.blocked:%d\n%!"
snew.shared snew.marked snew.blocked;*)unmark_oldstxold;assert(st.dropped_leaf=st.dropped_join);prepare_sharedst;letresult=unmark_newsttnewin(*Printf.eprintf "new_computed:%d%!\n" !new_computed;*)fori=st.shared_index-1downto0doMarking.restorest.shared.(i)done;ifget_droppedthen(letxleaf=ref[]inletxjoin=ref[]infori=0tost.shared_index-1doList.iter(function|XLeaf{b=Someb;_}->xleaf:=b::!xleaf|XJoin{b=Someb;_}->xjoin:=b:: !xjoin|_->())st.shared_x.(i)done;({leaves=st.dropped_leaf;table =st.dropped;extra_leaf =!xleaf;extra_join=!xjoin},result))elseno_dropped,resulttype('a,'b)map_reduce={map:'a->'b;reduce:'b->'b->'b;}letevalmap_reduce=function|XEmpty->None|other->letrecaux=function|XEmpty|XLeaf{a=Nil|Join_;_}->assertfalse|XLeaf{b=Someb;_}|XJoin{b=Someb;_}->b|XLeaf ({a=Leaft';_}ast)->letresult=map_reduce.mapt'.vint.b<-Someresult;result|XJoint->letl=auxt.landr=auxt.rinletresult=map_reduce.reducelrint.b<-Someresult;resultinSome(auxother)type('a,'b)reducer=('a,'b)map_reduce *('a,'b)xformletmake~map~reduce=({map;reduce},XEmpty)letreduce(map_reduce,tree:_reducer)=evalmap_reduce treeletupdate (map_reduce,old_tree:_reducer)new_tree:_reducer=let_,tree=difffalseold_treenew_treein(map_reduce,tree)letupdate_and_get_dropped(map_reduce,old_tree:_reducer)new_tree:_dropped*_reducer =letdropped,tree=difftrueold_tree new_treein(dropped,(map_reduce,tree))letfold_dropped kindfdropped acc =letacc=refaccinletstart,bound=matchkindwith|`All->0,Array.length dropped.table|`Map->0,dropped.leaves|`Reduce->dropped.leaves,Array.lengthdropped.tableinfori=starttobound-1domatchdropped.table.(i)with|None->()|Somex->acc:=fx!accdone;!accend(* Lwd interface *)letrecpure_map_reducemapreduce=function|Nil->assertfalse|Leaft->mapt.v|Joint->reduce(pure_map_reducemapreducet.l)(pure_map_reduce mapreducet.r)let fold~map~reduceseq=matchLwd.is_pureseqwith|Some Nil->Lwd.pureNone|Someother->Lwd.pure(Some(pure_map_reducemapreduceother))|None->letreducer=ref (Reducer.make~map~reduce)inLwd.mapseq~f:beginfunseq->letreducer' =Reducer.update!reducerseqinreducer :=reducer';Reducer.reducereducer'endletfold_monoidmap(zero,reduce)seq=matchLwd.is_pureseqwith|Some Nil->Lwd.purezero|Some other ->Lwd.pure(pure_map_reducemap reduceother)|None->letreducer=ref (Reducer.make~map~reduce)inLwd.mapseq~f:beginfunseq->letreducer' =Reducer.update!reducerseqinreducer:=reducer';matchReducer.reducereducer'with|None ->zero|Somex->xendletmonoid=(empty,concat)lettransform_listlsf=Lwd_utils.map_reducefmonoidlsletof_listls=transform_listlselementletrecof_sub_arrayfarrij=ifj<ithenemptyelseifj=ithenfarr.(i)elseletk=i+(j-i)/2inconcat(of_sub_arrayfarrik)(of_sub_arrayfarr(k+1)j)lettransform_arrayarrf=of_sub_arrayfarr0(Array.lengtharr-1)letof_arrayarr=transform_arrayarrelementletto_listx=let recfoldxacc=matchxwith|Nil->acc|Leaft->t.v::acc|Joint->foldt.l(foldt.racc)infoldx[]letto_arrayx=letreccount=function|Nil->0|Leaf_->1|Join t->countt.l+countt.rinmatchcount xwith|0->[||]|n->letrecfirst=function|Nil->assertfalse|Leaft->t.v|Joint->firstt.linletfirst=firstxinletarr=Array.makenfirstinletrecfoldi=function|Nil->i|Leaft->arr.(i)<-t.v;i+1|Joint->leti=foldit.linleti=foldit.riniinlet_:int=fold0xinarrletlwd_empty:'atLwd.t=Lwd.pureNilletlwd_monoid:'a.'atLwd.tLwd_utils.monoid=(lwd_empty,funxy->Lwd.map2~f:concatxy)letmapfseq=fold_monoid(funx->element(fx))monoidseqletfilterfseq=fold_monoid(funx->iffxthenelementxelseempty)monoidseqletfilter_mapfseq=letselectx=matchfxwith|Somey->elementy|None ->emptyinfold_monoid selectmonoidseqletbind(seq:'aseq Lwd.t)(f:'a->'bseqLwd.t):'bseqLwd.t=Lwd.join(fold_monoidflwd_monoidseq)letseq_bind(seq:'aseqLwd.t)(f:'a->'bseq):'bseqLwd.t=fold_monoid fmonoidseqletlift(seq:'aLwd.tseqLwd.t):'aseqLwd.t=bindseq(Lwd.map~f:element)moduleBalancedTree:sigtype'at=|Leaf|Nodeof{rank:int;l:'at;x:int*'aseq;r:'at;mutableseq:'aseq;}valleaf:'at(*val node : 'a t -> int * 'a seq -> 'a t -> 'a t*)val insert:cmp:('a->'a->int)->int->'aseq->'at->'at(*val union : cmp:('a -> 'a -> int) -> 'a t -> 'a t -> 'a t*)end=structtype'at=|Leaf|Nodeof{rank:int;l:'at;x:int*'aseq;r:'at;mutableseq:'aseq;}letleaf=Leafletrank=function|Leaf->0|Node t->t.rankletchecklr=abs(l-r)<=1letnodelxr=Node{l;x;r;seq=empty;rank=maxi(rankl)(rankr)+1}letrecnode_leftlxr=letml=ranklinletmr=rankrinifcheckmlmrthennodelxrelsematchlwith|Leaf->assertfalse|Nodet->ifcheck(rankt.l)mlthennodet.lt.x(node_leftt.rxr)elsematcht.rwith|Leaf->assertfalse|Nodetr->lettrr=node_lefttr.rxrinifcheck(1+maxi(rankt.l)(ranktr.l))(ranktrr)thennode(nodet.lt.xtr.l)tr.xtrrelsenodet.lt.x(nodetr.ltr.xtrr)letrecnode_rightlxr=letml=ranklinletmr=rankrinifcheckmrmlthennodelxrelsematchrwith|Leaf->assertfalse|Nodet->ifcheck(rankt.r)mrthennode(node_rightlxt.l)t.xt.relsematcht.lwith|Leaf->assertfalse|Node tl->lettll=node_rightlxtl.linifcheck(1+maxi(ranktl.r)(rank t.r))(ranktll)thennodetlltl.x(nodetl.rt.xt.r)elsenode(nodetlltl.xtl.r)t.xt.rlet nodelxr=letml=ranklinletmr=rankrinifcheckmlmrthennodelxrelseifml<=mrthennode_rightlxrelsenode_leftlxrletrecjoinlr=matchl,rwith|Leaf,t|t,Leaf->t|Nodetl,Nodetr->if tl.rank<= tr.rankthennode(joinltr.l)tr.xtr.relsenodetl.ltl.x(jointl.rr)letget_element=function|Nil|Join_->assertfalse|Leaf{v;_}->v(*let rec split ~cmp k = function
| Leaf -> Leaf, 0, Leaf
| Node t ->
let c = cmp k (get_element (snd (t.x))) in
if c < 0 then
let l', v', r' = split ~cmp k t.l in
l', v', join r' t.r
else if c > 0 then
let l', v', r' = split ~cmp k t.r in
join t.l l', v', r'
else
(t.l, fst t.x, t.r)
let rec union ~cmp t1 t2 =
match t1, t2 with
| Leaf, t | t, Leaf -> t
| Node t1, t2 ->
let m1, k1 = t1.x in
let l2, m2, r2 = split ~cmp (get_element k1) t2 in
let l' = union ~cmp t1.l l2 in
let r' = union ~cmp t1.r r2 in
let m = m1 + m2 in
if m = 0 then
join l' r'
else (
assert (m > 0);
nodel'(m, k1) r';
)
*)letinsert~cmp m1st=assert(m1<>0);letrecaux=function|Leaf->nodeLeaf(m1,s)Leaf|Nodet->letm2,x=t.xinletc=cmp(get_elements)(get_elementx)inifc=0thenletm=m1+m2inifm=0thenjoint.lt.relsenodet.l(m,x)t.relseifc<0thenletl'=auxt.linnodel't.xt.relseletr'=auxt.rinnodet.lt.xr'inauxtendletrecseq_of_tree=function|BalancedTree.Leaf->empty|BalancedTree.Nodet->matcht.seqwith|Nil->letsl=seq_of_treet.linletsr=seq_of_treet.rinassert(fstt.x>0);letseq=concatsl(concat(sndt.x)sr)int.seq<-seq;seq|seq-> seqletsort_uniqcmpseq=letprevious_seq=refemptyinletprevious_tree=refBalancedTree.leafinletfnew_seq=letold_seq=!previous_seqinletold_tree=!previous_treeinlet_=Marking.unsafe_traverse~old_root:old_seq~new_root:new_seqinletrecunblock=function|Nil->()|Leaft->t.mark <-Marking.unmarkt.mark|Jointasseq->letmark=t.markinunblockt.l;unblockt.r;ifMarking.is_shared markthen(Marking.restoreseq;)elseifMarking.is_bothmarkthen(t.mark<-Marking.unmarkmark;)elseassert(Marking.is_nonemark)inletrecunmark_newtree=function|Nil->tree|Leaftasseq->letmark=t.markint.mark<-0;ifMarking.is_new markthenBalancedTree.insert~cmp(+1)seqtreeelse(assert (Marking.is_bothmark||Marking.is_nonemark);tree)|Jointasseq->let mark=t.markinifMarking.is_newmarkthen(t.mark<-Marking.unmarkmark;unmark_new(unmark_newtreet.l)t.r)else(unblockseq;tree)inletrecunmark_oldtree=function|Nil->tree|Leaftasseq->letmark=t.markint.mark<-0;ifMarking.is_old markthenBalancedTree.insert~cmp(-1)seqtreeelse(assert (Marking.is_bothmark||Marking.is_nonemark);tree)|Jointasseq->let mark=t.markinifMarking.is_oldmarkthen(t.mark<-Marking.unmarkmark;unmark_old(unmark_oldtreet.l)t.r)else(unblockseq;tree)inletnew_tree =unmark_old(unmark_newold_treenew_seq)old_seqinprevious_seq :=new_seq;previous_tree :=new_tree;seq_of_treenew_treeinLwd.mapseq~f