123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173(*
* Hashcons -- a hashconsing library
* Copyright (C) 2011 Batteries Included Development Team
*
* This library is free software; 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; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)(* Most of this code is lifted from J.-C. Fillâtre and S. Conchon's
implementation:
http://www.lri.fr/~filliatr/ftp/ocaml/ds/hashcons.ml
*)moduleInt=BatIntmoduleSys=BatSysmoduleHashtbl=BatHashtblmoduleArray=BatArray##V>=5##modulePervasives=Stdlibtype'ahobj={obj:'a;tag:int;hcode:int;}type'at='ahobjletcompareho1ho2=Int.compareho1.tagho2.tagletgentag=lettags=ref0infun()->incrtags;!tagsmodule typeTable=sigtypekeytypetvalcreate :int->tvalclear:t->unitvalhashcons:t->key->keyhobjval iter:(keyhobj->unit)->t->unitvalfold:(keyhobj->'a->'a)->t->'a->'avalcount:t->intendmoduleMakeTable (HT:Hashtbl.HashedType):Tablewithtypekey=HT.t=structtypekey=HT.ttypedata=HT.thobjtypet={mutabletable:dataWeak.tarray;mutable totsize :int;(* sum of the bucket sizes *)mutablelimit:int;(* max ratio totsize/table length *)}letemptybucket=Weak.create0letcreatesz=letsz=Pervasives.min(Pervasives.maxsz7)(Sys.max_array_length-1)in{table=Array.makeszemptybucket;totsize=0;limit=3}letcleart=Array.modify(fun_->emptybucket)t.table;t.totsize<-0;t.limit<-3letfoldftinit=letrecfold_bucketibaccu=ifi>=Weak.lengthbthenaccuelsematch Weak.getbiwith|Somev->fold_bucket(i+1)b(fvaccu)|None->fold_bucket(i+1)baccuinArray.fold_right(fold_bucket0)t.tableinitletiterft=letreciter_bucketib=ifi>=Weak.lengthbthen()elsematchWeak.getbiwith|Somev->fv;iter_bucket(i+1)b|None->iter_bucket(i+1)binArray.iter(iter_bucket0)t.tablelet countt=letreccount_bucketibaccu=ifi>=Weak.lengthbthenaccuelsecount_bucket (i+1)b(accu+(ifWeak.checkbithen1else0))inArray.fold_right(count_bucket0)t.table0letnext_szn=Pervasives.min(3*n/2+3)(Sys.max_array_length-1)letrecresizet=letoldlen=Array.lengtht.tableinletnewlen=next_szoldleninifnewlen>oldlenthenbeginletnewt=createnewleninnewt.limit<-t.limit+100;(* prevent resizing of newt *)iter(addnewt)t;t.table<-newt.table;t.limit<-t.limit+2;endandaddtd=letindex=d.hcodemod(Array.lengtht.table)inletbucket=t.table.(index)inletsz=Weak.lengthbucketinletrecloop i=ifi>=szthenbeginletnewsz=Pervasives.min(sz+3)(Sys.max_array_length-1)inifnewsz<=szthenfailwith "Hashcons.Make: hash bucket cannot grow more";letnewbucket=Weak.createnewszinWeak.blitbucket0newbucket 0sz;Weak.set newbucketi(Somed);t.table.(index)<-newbucket;t.totsize <-t.totsize+(newsz-sz);ift.totsize>t.limit*Array.lengtht.tablethenresizet;endelsebeginifWeak.checkbucketithenloop (i+1)elseWeak.setbucketi(Somed)endinloop0lethashconstd=lethcode=(HT.hashd)land Pervasives.max_intinletindex=hcodemod(Array.lengtht.table)inletbucket=t.table.(index)inletsz=Weak.lengthbucketinletrecloop i=ifi>=szthenbeginlethdata={hcode=hcode ;tag=gentag();obj=d}inaddthdata;hdataendelsebeginmatchWeak.get_copybucketiwith|SomevwhenHT.equalv.objd->beginmatchWeak.getbucketiwith|Somev->v|None->loop(i+1)end|_->loop(i+1)endinloop0endmoduleH=structlethc0_h=hlethc0x=x.hcodelethc1_xh=x+19*hlethc1x=hc1_x.hcodeend