123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Random-Access Lists} *)(** A complete binary tree *)type+'atree=|Leafof'a|Nodeof'a*'atree*'atreeand+'at=|Nil|Consofint*'atree*'at(** Functional array of complete trees *)(** {2 Functions on trees} *)(** {2 Functions on lists of trees} *)letempty=Nilletreturnx=Cons(1,Leafx,Nil)letis_empty=function|Nil->true|Cons_->falseletrecget_exnli=matchlwith|Nil->invalid_arg"RAL.get"|Cons(size,t,_)wheni<size->tree_lookup_sizeti|Cons(size,_,l')->get_exnl'(i-size)andtree_lookup_sizeti=matcht,iwith|Leafx,0->x|Leaf_,_->invalid_arg"RAL.get"|Node(x,_,_),0->x|Node(_,t1,t2),_->letsize'=size/2inifi<=size'thentree_lookup_size't1(i-1)elsetree_lookup_size't2(i-1-size')letgetli=trySome(get_exnli)withInvalid_argument_->Noneletrecsetliv=matchlwith|Nil->invalid_arg"RAL.set"|Cons(size,t,l')wheni<size->Cons(size,tree_update_sizetiv,l')|Cons(size,t,l')->Cons(size,t,setl'(i-size)v)andtree_update_sizetiv=matcht,iwith|Leaf_,0->Leafv|Leaf_,_->invalid_arg"RAL.set"|Node(_,t1,t2),0->Node(v,t1,t2)|Node(x,t1,t2),_->letsize'=size/2inifi<=size'thenNode(x,tree_update_size't1(i-1)v,t2)elseNode(x,t1,tree_update_size't2(i-1-size')v)letconsxl=matchlwith|Cons(size1,t1,Cons(size2,t2,l'))whensize1=size2->Cons(1+size1+size2,Node(x,t1,t2),l')|_->Cons(1,Leafx,l)letcons'lx=consxllethdl=matchlwith|Nil->invalid_arg"RAL.hd"|Cons(_,Leafx,_)->x|Cons(_,Node(x,_,_),_)->xlettll=matchlwith|Nil->invalid_arg"RAL.tl"|Cons(_,Leaf_,l')->l'|Cons(size,Node(_,t1,t2),l')->letsize'=size/2inCons(size',t1,Cons(size',t2,l'))letfrontl=matchlwith|Nil->None|Cons(_,Leafx,tl)->Some(x,tl)|Cons(size,Node(x,t1,t2),l')->letsize'=size/2inSome(x,Cons(size',t1,Cons(size',t2,l')))letfront_exnl=matchlwith|Nil->invalid_arg"RAL.front_exn"|Cons(_,Leafx,tl)->x,tl|Cons(size,Node(x,t1,t2),l')->letsize'=size/2inx,Cons(size',t1,Cons(size',t2,l'))letrec_removeprefixli=letx,l'=front_exnlinifi=0thenList.fold_left(funlx->consxl)l'prefixelse_remove(x::prefix)l'(i-1)letremoveli=_remove[]liletrec_get_and_remove_exnprefixli=letx,l'=front_exnlinifi=0thenx,List.fold_left(funlx->consxl)l'prefixelse_get_and_remove_exn(x::prefix)l'(i-1)letget_and_remove_exnli=_get_and_remove_exn[]liletrec_map_treeft=matchtwith|Leafx->Leaf(fx)|Node(x,l,r)->Node(fx,_map_treefl,_map_treefr)letrecmap~fl=matchlwith|Nil->Nil|Cons(i,t,tl)->Cons(i,_map_treeft,map~ftl)letmapi~fl=letrecauxfil=matchlwith|Nil->Nil|Cons(size,t,tl)->Cons(size,aux_tf~sizeit,auxf(i+size)tl)andaux_tf~sizeit=matchtwith|Leafx->Leaf(fix)|Node(x,l,r)->letx=fixinletl=aux_tf~size:(size/2)(i+1)linNode(x,l,aux_tf~size:(size/2)(i+1+(size/2))r)inauxf0lletreclengthl=matchlwith|Nil->0|Cons(size,_,l')->size+lengthl'letreciter~fl=matchlwith|Nil->()|Cons(_,Leafx,l')->fx;iter~fl'|Cons(_,t,l')->iter_treetf;iter~fl'anditer_treetf=matchtwith|Leafx->fx|Node(x,t1,t2)->fx;iter_treet1f;iter_treet2fletiteri~fl=letrecauxfil=matchlwith|Nil->()|Cons(size,t,l')->aux_t~sizefit;auxf(i+size)l'andaux_tf~sizeit=matchtwith|Leafx->fix|Node(x,l,r)->fix;letsize'=size/2inaux_t~size:size'f(i+1)l;aux_t~size:size'f(i+1+size')rinauxf0lletrecfold~f~x:accl=matchlwith|Nil->acc|Cons(_,Leafx,l')->fold~f~x:(faccx)l'|Cons(_,t,l')->letacc'=fold_treetaccfinfold~f~x:acc'l'andfold_treetaccf=matchtwith|Leafx->faccx|Node(x,t1,t2)->letacc=faccxinletacc=fold_treet1accfinfold_treet2accfletrecfold_rev~f~x:accl=matchlwith|Nil->acc|Cons(_,Leafx,l')->f(fold_rev~f~x:accl')x|Cons(_,t,l')->letacc=fold_rev~f~x:accl'infold_tree_revtaccfandfold_tree_revtaccf=matchtwith|Leafx->faccx|Node(x,t1,t2)->letacc=fold_tree_revt2accfinletacc=fold_tree_revt1accfinfaccxletrev_map~fl=fold~f:(funaccx->cons(fx)acc)~x:emptylletrevl=fold~f:cons'~x:emptylletappendl1l2=fold_rev~f:(funl2x->consxl2)~x:l2l1letappend_tree_tl=fold_tree_revtlcons'letfilter~fl=fold_rev~f:(funaccx->iffxthenconsxaccelseacc)~x:emptylletfilter_map~fl=fold_rev~x:emptyl~f:(funaccx->matchfxwith|None->acc|Somey->consyacc)letflat_mapfl=fold_rev~x:emptyl~f:(funaccx->letl=fxinappendlacc)letflattenl=fold_rev~f:(funaccl->appendlacc)~x:emptylletappfunsl=fold_rev~x:emptyfuns~f:(funaccf->fold_rev~x:accl~f:(funaccx->cons(fx)acc))type'astack=|St_nil|St_listof'at*'astack|St_treeof'atree*'astackletrecstack_to_list=function|St_nil->Nil|St_list(l,st')->appendl(stack_to_listst')|St_tree(t,st')->append_tree_t(stack_to_listst')letrectakenl=matchlwith|Nil->Nil|Cons(size,t,tl)->ifsize<=nthenappend_tree_t(take(n-size)tl)elsetake_tree_~sizentandtake_tree_~sizent=matchtwith|_whenn=0->Nil|Leafx->consxNil|Node(x,l,r)->letsize'=size/2inifsize'<=n-1thenconsx(append_tree_l(take_tree_~size:size'(n-size'-1)r))elseconsx(take_tree_~size:size'(n-1)l)lettake_while~fl=(* st: stack of subtrees *)letrecauxpst=matchstwith|St_nil->Nil|St_list(Nil,st')->auxpst'|St_list(Cons(_,t,tl),st')->auxp(St_tree(t,St_list(tl,st')))|St_tree(Leafx,st')->ifpxthenconsx(auxpst')elseNil|St_tree(Node(x,l,r),st')->ifpxthenconsx(auxp(St_tree(l,St_tree(r,st'))))elseNilinauxf(St_list(l,St_nil))(* drop [n < size] elements from [t] *)letrecdrop_tree_~sizenttail=matchtwith|_whenn=0->tail|Leaf_->assert(n=1);tail|Node(_,left,right)->ifn=1thenappend_tree_left(append_tree_righttail)else(assert(sizemod2=1);letsize_sub=size/2in(* size of subtrees *)letn=n-1inifn=size_subthenappend_tree_righttail(* drop element and left tree *)elseifn<size_subthen(* drop element and part of left tree *)drop_tree_~size:size_subnleft(append_tree_righttail)else(* drop element, left tree, and part of right tree *)drop_tree_~size:size_sub(n-size_sub)righttail)letrecdropnl=matchlwith|_whenn=0->l|Nil->Nil|Cons(size,t,tl)->ifn>=sizethendrop(n-size)tlelsedrop_tree_~sizenttlletdrop_while~fl=letrecauxpst=matchstwith|St_nil->Nil|St_list(Nil,st')->auxpst'|St_list(Cons(_,t,tail),st')->auxp(St_tree(t,St_list(tail,st')))|St_tree(Leafx,st')->ifpxthenauxpst'elseconsx(stack_to_listst')|St_tree((Node(x,l,r)astree),st')->ifpxthenauxp(St_tree(l,St_tree(r,st')))elseappend_tree_tree(stack_to_listst')inauxf(St_list(l,St_nil))lettake_dropnl=takenl,dropnlletequal~eql1l2=letrecaux~eql1l2=matchl1,l2with|Nil,Nil->true|Cons(size1,t1,l1'),Cons(size2,t2,l2')->size1=size2&&aux_t~eqt1t2&&aux~eql1'l2'|Nil,Cons_|Cons_,Nil->falseandaux_t~eqt1t2=matcht1,t2with|Leafx,Leafy->eqxy|Node(x1,l1,r1),Node(x2,l2,r2)->eqx1x2&&aux_t~eql1l2&&aux_t~eqr1r2|Leaf_,Node_|Node_,Leaf_->falseinaux~eql1l2(** {2 Utils} *)letmakenx=letrecauxnaccx=ifn<=0thenaccelseaux(n-1)(consxacc)xinauxnemptyxletrepeatnl=letrecauxnlacc=ifn<=0thenaccelseaux(n-1)l(appendlacc)inauxnlemptyletrangeij=letrecauxijacc=ifi=jthenconsiaccelseifi<jthenauxi(j-1)(consjacc)elseauxi(j+1)(consjacc)inauxijemptyletrange_r_open_ij=ifi=jthenemptyelseifi<jthenrangei(j-1)elserangei(j+1)(** {2 Conversions} *)type'aiter=('a->unit)->unittype'agen=unit->'aoptionletadd_listll2=List.fold_left(funaccx->consxacc)l(List.revl2)letof_listl=add_listemptylletto_listl=fold_rev~f:(funaccx->x::acc)~x:[]lletadd_arrayla=Array.fold_rightconsalletof_arraya=add_arrayemptyaletto_arrayl=matchlwith|Nil->[||]|Cons(_,Leafx,_)|Cons(_,Node(x,_,_),_)->letlen=lengthlinletarr=Array.makelenxiniteri~f:(funix->Array.setarrix)l;arrletof_iters=letl=refemptyins(funx->l:=consx!l);rev!lletadd_iterls=letl1=refemptyins(funx->l1:=consx!l1);fold~f:(funaccx->consxacc)~x:l!l1letto_iterlyield=iter~f:yieldlletrecgen_iter_fg=matchg()with|None->()|Somex->fx;gen_iter_fgletadd_genlg=letl1=refemptyingen_iter_(funx->l1:=consx!l1)g;fold~f:(funaccx->consxacc)~x:l!l1letof_geng=add_genemptygletto_genl=letst=Stack.create()in(* stack for tree *)letl=reflin(* tail of list *)letrecnext()=ifStack.is_emptystthen(match!lwith|Nil->None|Cons(_,t,tl)->l:=tl;Stack.pushtst;next())else(matchStack.popstwith|Leafx->Somex|Node(x,l,r)->Stack.pushrst;Stack.pushlst;Somex)innextletrecof_list_map~fl=matchlwith|[]->empty|x::l'->lety=fxinconsy(of_list_map~fl')letcompare~cmpl1l2=letreccmp_gen~cmpg1g2=matchg1(),g2()with|None,None->0|Some_,None->1|None,Some_->-1|Somex,Somey->letc=cmpxyinifc<>0thencelsecmp_gen~cmpg1g2incmp_gen~cmp(to_genl1)(to_genl2)(** {2 Infix} *)moduleInfix=structlet(@+)=conslet(>>=)lf=flat_mapfllet(>|=)lf=map~fllet(<*>)=applet(--)=rangelet(--^)=range_r_open_endincludeInfix(** {2 IO} *)type'aprinter=Format.formatter->'a->unitletpp?(pp_sep=funfmt()->Format.fprintffmt",@ ")pp_itemfmtl=letfirst=reftrueiniterl~f:(funx->if!firstthenfirst:=falseelsepp_sepfmt();pp_itemfmtx);()