123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Imperative deque} *)type'acell=|Oneof'a|Twoof'a*'a|Threeof'a*'a*'a(** A cell holding a small number of elements *)type'ainner_node={mutablecell:'acell;mutablenext:'ainner_node;mutableprev:'ainner_node;}type'anode=|Empty|Nodeof'ainner_node(** Linked list of cells.
invariant: only the first and last cells are allowed to
be anything but [Three] (all the intermediate ones are [Three])
*)type'at={mutablecur:'anode;mutablesize:int;}(** The deque, a double linked list of cells *)exceptionEmptyletcreate()={cur=Empty;size=0}letclearq=q.cur<-Empty;q.size<-0;()letincr_size_d=d.size<-d.size+1letdecr_size_d=d.size<-d.size-1letbool_eq(a:bool)b=Stdlib.(=)abletis_emptyd=letres=d.size=0inassert(bool_eqres(d.cur=Empty));resletpush_frontdx=incr_size_d;matchd.curwith|Empty->letrecnode={cell=Onex;prev=node;next=node}ind.cur<-Nodenode|Noden->(matchn.cellwith|Oney->n.cell<-Two(x,y)|Two(y,z)->n.cell<-Three(x,y,z)|Three_->letnode={cell=Onex;prev=n.prev;next=n}inn.prev.next<-node;n.prev<-node;d.cur<-Nodenode(* always point to first node *))letpush_backdx=incr_size_d;matchd.curwith|Empty->letrecnode={cell=Onex;prev=node;next=node}ind.cur<-Nodenode|Nodecur->letn=cur.previn(* last node *)(matchn.cellwith|Oney->n.cell<-Two(y,x)|Two(y,z)->n.cell<-Three(y,z,x)|Three_->letelt={cell=Onex;next=cur;prev=n}inn.next<-elt;cur.prev<-elt)letpeek_front_optd=matchd.curwith|Empty->None|Nodecur->(matchcur.cellwith|Onex->Somex|Two(x,_)->Somex|Three(x,_,_)->Somex)letpeek_frontd=matchpeek_front_optdwith|None->raiseEmpty|Somex->xletpeek_back_optd=matchd.curwith|Empty->None|Nodecur->(matchcur.prev.cellwith|Onex->Somex|Two(_,x)->Somex|Three(_,_,x)->Somex)letpeek_backd=matchpeek_back_optdwith|None->raiseEmpty|Somex->xlettake_back_node_n=matchn.cellwith|Onex->true,x|Two(x,y)->n.cell<-Onex;false,y|Three(x,y,z)->n.cell<-Two(x,y);false,zletremove_node_n=letnext=n.nextinn.prev.next<-next;next.prev<-n.prevlettake_back_optd=matchd.curwith|Empty->None|Nodecur->ifStdlib.(==)curcur.prevthen((* only one cell *)decr_size_d;letis_zero,x=take_back_node_curinifis_zerothend.cur<-Empty;Somex)else(letn=cur.previnletis_zero,x=take_back_node_nindecr_size_d;(* remove previous node *)ifis_zerothenremove_node_n;Somex)lettake_backd=matchtake_back_optdwith|None->raiseEmpty|Somex->xlettake_front_node_n=matchn.cellwith|Onex->true,x|Two(x,y)->n.cell<-Oney;false,x|Three(x,y,z)->n.cell<-Two(y,z);false,xlettake_front_optd=matchd.curwith|Empty->None|Nodecur->ifStdlib.(==)cur.prevcurthen((* only one cell *)decr_size_d;letis_zero,x=take_front_node_curinifis_zerothend.cur<-Empty;Somex)else(decr_size_d;letis_zero,x=take_front_node_curinifis_zerothen(cur.prev.next<-cur.next;cur.next.prev<-cur.prev;d.cur<-Nodecur.next);Somex)lettake_frontd=matchtake_front_optdwith|None->raiseEmpty|Somex->xletremove_backd=ignore(take_back_optd)letremove_frontd=ignore(take_front_optd)letupdate_frontdf=matchd.curwith|Empty->()|Nodecur->(matchcur.cellwith|Onex->(matchfxwith|None->ifStdlib.(!=)cur.prevcurthen(cur.prev.next<-cur.next;cur.next.prev<-cur.prev;d.cur<-Nodecur.next)elsed.cur<-Empty|Somex->cur.cell<-Onex)|Two(x,y)->(matchfxwith|None->cur.cell<-Oney|Somex->cur.cell<-Two(x,y))|Three(x,y,z)->(matchfxwith|None->cur.cell<-Two(y,z)|Somex->cur.cell<-Three(x,y,z)))letupdate_backdf=matchd.curwith|Empty->()|Nodecur->letn=cur.previn(matchn.cellwith|Onex->(matchfxwith|None->ifStdlib.(!=)cur.prevcurthenremove_node_nelsed.cur<-Empty|Somex->n.cell<-Onex)|Two(x,y)->(matchfywith|None->n.cell<-Onex|Somey->n.cell<-Two(x,y))|Three(x,y,z)->(matchfzwith|None->n.cell<-Two(x,y)|Somez->n.cell<-Three(x,y,z)))letiterfd=letreciterf~firstn=(matchn.cellwith|Onex->fx|Two(x,y)->fx;fy|Three(x,y,z)->fx;fy;fz);ifn.next!=firsttheniterf~firstn.nextinmatchd.curwith|Empty->()|Nodecur->iterf~first:curcurletappend_front~intoq=iter(push_frontinto)qletappend_back~intoq=iter(push_backinto)qletfoldfaccd=letrecaux~firstfaccn=letacc=matchn.cellwith|Onex->faccx|Two(x,y)->f(faccx)y|Three(x,y,z)->f(f(faccx)y)zinifStdlib.(==)n.nextfirstthenaccelseaux~firstfaccn.nextinmatchd.curwith|Empty->acc|Nodecur->aux~first:curfacccurletlengthd=d.sizetype'aiter=('a->unit)->unittype'agen=unit->'aoptionletadd_iter_backqseq=seq(funx->push_backqx)letadd_iter_frontqseq=seq(funx->push_frontqx)letof_iterseq=letdeque=create()inseq(funx->push_backdequex);dequeletto_iterdk=iterkdletof_listl=letq=create()inList.iter(push_backq)l;qletto_rev_listq=fold(funlx->x::l)[]qletto_listq=List.rev(to_rev_listq)letsize_cell_=function|One_->1|Two_->2|Three_->3(* filter over a cell *)letfilter_cell_f=function|Onexasc->iffxthenSomecelseNone|Two(x,y)asc->letfx=fxinletfy=fyin(matchfx,fywith|true,true->Somec|true,false->Some(Onex)|false,true->Some(Oney)|_->None)|Three(x,y,z)asc->letfx=fxinletfy=fyinletfz=fzin(matchfx,fy,fzwith|true,true,true->Somec|true,true,false->Some(Two(x,y))|true,false,true->Some(Two(x,z))|true,false,false->Some(Onex)|false,true,true->Some(Two(y,z))|false,true,false->Some(Oney)|false,false,true->Some(Onez)|false,false,false->None)letfilter_in_place(d:_t)f:unit=(* update size, compute new cell *)letupdate_local_n=d.size<-d.size-size_cell_n.cell;matchfilter_cell_fn.cellwith|None->None|Somenasnew_cell->d.size<-d.size+size_cell_n;new_cellinletrecloop~stop_atn:unit=ifn!=stop_atthen(letn_prev=n.previnletn_next=n.nextinletnew_cell=update_local_nin(* merge into previous cell *)(matchn_prev.cell,new_cellwith|_,None->remove_node_n|Three_,Somenew_cell->n.cell<-new_cell|Onex,Some(Oney)->remove_node_n;n_prev.cell<-Two(x,y)|Onex,Some(Two(y,z))|Two(x,y),Some(Onez)->remove_node_n;n_prev.cell<-Three(x,y,z)|Onex,Some(Three(y,z,w))|Two(x,y),Some(Two(z,w))->n_prev.cell<-Three(x,y,z);n.cell<-Onew|Two(x,y),Some(Three(z,w1,w2))->n_prev.cell<-Three(x,y,z);n.cell<-Two(w1,w2));loop~stop_atn_next)inletrecnew_first_cell~stop_atn=ifn!=stop_atthen(matchupdate_local_nwith|None->new_first_cell~stop_atn.next|Somec->n.cell<-c;Somen)elseNoneinmatchd.curwith|Empty->()|Nodecur->(* special case for first cell *)(matchupdate_local_curwith|None->(matchnew_first_cell~stop_at:curcur.nextwith|None->d.cur<-Empty|Somen->cur.prev.next<-n;n.prev<-cur.prev;d.cur<-Noden;loop~stop_at:nn.next)|Somec->cur.cell<-c;loop~stop_at:curcur.next)letfilterfq=letq'=create()initer(funx->iffxthenpush_backq'x)q;q'letfilter_mapfq=letq'=create()initer(funx->matchfxwith|None->()|Somey->push_backq'y)q;q'letrecgen_iter_fg=matchg()with|None->()|Somex->fx;gen_iter_fgletof_geng=letq=create()ingen_iter_(funx->push_backqx)g;qletto_genq=matchq.curwith|Empty->fun()->None|Nodecur->letfirst=curinletcell=ref(Somecur.cell)inletcur=refcurinletrecnext()=match!cellwith|NonewhenStdlib.(==)!cur.nextfirst->None|None->(* go to next node *)letn=!curincur:=n.next;cell:=Somen.next.cell;next()|Some(Onex)->cell:=None;Somex|Some(Two(x,y))->cell:=Some(Oney);Somex|Some(Three(x,y,z))->cell:=Some(Two(y,z));Somexinnext(* naive implem of copy, for now *)letcopyd=letd'=create()initer(funx->push_backd'x)d;d'letequal~eqab=letrecauxeqab=matcha(),b()with|None,None->true|None,Some_|Some_,None->false|Somex,Somey->eqxy&&auxeqabinauxeq(to_gena)(to_genb)letcompare~cmpab=letrecauxcmpab=matcha(),b()with|None,None->0|None,Some_->-1|Some_,None->1|Somex,Somey->letc=cmpxyinifc=0thenauxcmpabelsecinauxcmp(to_gena)(to_genb)type'aprinter=Format.formatter->'a->unitletpppp_xoutd=letfirst=reftrueinFormat.fprintfout"@[<hov2>deque {";iter(funx->if!firstthenfirst:=falseelseFormat.fprintfout";@ ";pp_xoutx)d;Format.fprintfout"}@]"