123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184(***********************************************************************)(* *)(* Weaktbl *)(* *)(* (C) 2007 by Zheng Li (li@pps.jussieu.fr) *)(* *)(* This program is free software; you can redistribute it and/or *)(* modify it under the terms of the GNU Lesser General Public *)(* License version 2.1 as published by the Free Software Foundation, *)(* with the special exception on linking described in file LICENSE. *)(* *)(* This program 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 Library General Public License for more details. *)(* *)(***********************************************************************)(* weak stack, for ordering purpose *)moduleStack=structtype'at={mutabledata:'aWeak.t;mutablelength:int;mutablecursor:int}letcreaten=letlen=minn(Sys.max_array_length-1)in{data=Weak.createlen;length=len;cursor=0}letiterfs=fori=s.cursor-1downto0domatchWeak.gets.dataiwithSomex->fx|_->()doneletlengths=(* resize by the way, since it's invoked by push *)letflag=reffalseandpt=ref0infori=0tos.cursor-1domatchWeak.gets.dataiwith|Some_asd->if!flagthenWeak.sets.data!ptd;incrpt|None->flag:=truedone;s.cursor<-!pt;s.cursorletcopys=lets'=creates.lengthinWeak.blits.data0s'.data0s.cursor;s'.cursor<-s.cursor;s'letrecpushxs=ifs.cursor<s.lengththen(Weak.sets.datas.cursor(Somex);s.cursor<-s.cursor+1)elseletlen=lengthsiniflen>=s.length/3&&len<s.length*2/3thenpushxselseletlen'=min(len*3/2+2)(Sys.max_array_length-1)iniflen'=lenthenfailwith"Weaktbl.Stack.push: stack cannot grow"elseletdata'=Weak.createlen'inWeak.blits.data0data'0s.cursor;s.data<-data';s.length<-len';pushxsletrecpops=ifs.cursor<=0thenraiseNot_found;s.cursor<-s.cursor-1;matchWeak.gets.datas.cursorwithSomex->x|None->popsletrectops=ifs.cursor<=0thenraiseNot_found;matchWeak.gets.data(s.cursor-1)with|Somex->x|None->s.cursor<-s.cursor-1;topsletis_emptys=(* stop as earlier as we can *)tryiter(fun_->raiseNot_found)s;truewithNot_found->falseendmoduletypeHashedType=sigtypetvalequal:t->t->boolvalhash:t->intendmoduletypeS=sigtypekeytype'atvalcreate:int->'atvalclear:'at->unitvalreset:'at->unitvalcopy:'at->'atvaladd:'at->key->'a->unitvalremove:'at->key->unitvalfind:'at->key->'avalfind_opt:'at->key->'aoptionvalfind_all:'at->key->'alistvalreplace:'at->key->'a->unitvalmem:'at->key->boolvaliter:(key->'a->unit)->'at->unitvalfilter_map_inplace:(key->'a->'aoption)->'at->unitvalfold:(key->'a->'b->'b)->'at->'b->'bvallength:'at->int##V>=4##valstats:'at->Hashtbl.statisticsendopenObj(* Recover polymorphism from standard monomorphic (Weak)Hashtbl *)moduleMake(H:HashedType):Swithtypekey=H.t=structtypebox=H.tWeak.tletenboxk=letw=Weak.create1inWeak.setw0(Somek);wletunboxbk=Weak.getbk0typebind=box*tletbind_newkv=enboxk,reprvtypecls=bindStack.tletcls_newbd=letcls=Stack.create1inStack.pushbdcls;clsletdummyk=cls_new(bind_newk())letrectop_bindcls=let(bk,v)asbind=Stack.topclsinmatchunboxbkwith|Somek->k,(objv)|_->assert(bind==Stack.popcls);top_bindclslettop_keycls=fst(top_bindcls)andtop_valuecls=snd(top_bindcls)letall_bindcls=letl=ref[]inletf(bk,v)=matchunboxbkwith|Somek->l:=(k,objv)::!l|_->()inStack.iterfcls;List.rev!lletall_keycls=List.mapfst(all_bindcls)andall_valuecls=List.mapsnd(all_bindcls)moduleHX=structtypet=clslethashx=tryH.hash(top_keyx)withNot_found->0letequalxy=tryH.equal(top_keyx)(top_keyy)withNot_found->falseendmoduleW=Weak.Make(HX)typekey=H.tand'at=W.tletcreate=W.createandclear=W.clearletfind_alltblkey=tryall_value(W.findtbl(dummykey))withNot_found->[]letfindtblkey=top_value(W.findtbl(dummykey))letfind_opttblkey=trySome(findtblkey)withNot_found->Noneletaddtblkeydata=letbd=bind_newkeydatainletcls=tryletc=W.findtbl(dummykey)inStack.pushbdc;cwithNot_found->letc=cls_newbdinW.addtblc;cinletfinal_=ignorebd;ignoreclsintryGc.finalisefinalkeywithInvalid_argument_->Gc.finalisefinalbd;Gc.finalisefinalclsletremovetblkey=tryignore(Stack.pop(W.findtbl(dummykey)))withNot_found->()letreplacetblkeydata=removetblkey;addtblkeydataletmemtblkey=tryignore(findtblkey);truewithNot_found->falseletiterftbl=letf'(bk,v)=matchunboxbkwithSomek->fk(objv)|None->()inW.iter(Stack.iterf')tblletfoldftblaccu=letr=refaccuinletf'kv=r:=fkv!riniterf'tbl;!rletlengthtbl=W.fold(funcls->(+)(Stack.lengthcls))tbl0letcopytbl=lettbl'=W.create(W.counttbl*3/2+2)inW.iter(funcls->W.addtbl'(Stack.copycls))tbl;tbl'letstats_=assertfalseletreset_=assertfalseletfilter_map_inplaceftbl=letdelta=ref[]initer(funkv->matchfkvwith|Somev'whenv'==v->()|other->delta:=(k,other)::!delta)tbl;lethandle_delta=function|(k,None)->removetblk|(k,Somev)->removetblk;addtblkvinList.iterhandle_delta!deltaendmoduleStdHash=Make(structtypet=Obj.tletequalxy=(comparexy)=0lethash=Hashtbl.hashend)openStdHashtype('a,'b)t='bStdHash.tletcreate=createandclear=clearandcopy=copyandlength=lengthletaddtblk=addtbl(reprk)letremovetblk=removetbl(reprk)letfindtblk=findtbl(reprk)letfind_alltblk=find_alltbl(reprk)letreplacetblk=replacetbl(reprk)letmemtblk=memtbl(reprk)letiterf=iter(funkd->f(objk)d)letfoldf=fold(funkda->f(objk)da)