123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497(******************************************************************************)(* *)(* Fix *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under the *)(* terms of the GNU Library General Public License version 2, with a *)(* special exception on linking, as described in the file LICENSE. *)(* *)(******************************************************************************)(* A suspension is used to represent a cardinal-that-may-still-be-unknown. *)type'ncardinal=Cardinal:intLazy.t->unitcardinal[@@ocaml.unboxed](* The function [cardinal] forces the cardinal to become fixed. *)letcardinal(typen)(Cardinalc:ncardinal)=Lazy.force_valcletis_val(typen)(Cardinall:ncardinal)=Lazy.is_valltype(_,_)eq=Refl:('a,'a)eqletassert_equal_cardinal(typenm)(n:ncardinal)(m:mcardinal):(n,m)eq=letCardinaln=ninletCardinalm=minifnot(Int.equal(Lazy.force_valn)(Lazy.force_valm))theninvalid_arg"Indexing.equal_cardinal: not equal";Reflletcheck_equal_cardinal(typenm)(n:ncardinal)(m:mcardinal):(n,m)eqoption=letCardinaln=ninletCardinalm=minifInt.equal(Lazy.force_valn)(Lazy.force_valm)thenSomeReflelseNonetype'nindex=intmoduletypeCARDINAL=sigtypenvaln:ncardinalend(* [Empty] and [Const] produce sets whose cardinal is known. *)moduleEmpty=structtypen=unitletn=Cardinal(lazy0)endmoduleUnit=structtypen=unitletn=Cardinal(lazy1)letelement=0end(**{!Opt} adds one element to a set. *)moduleOpt=structtype'nn=unitletnone:'nnindex=0letsome:'nindex->'nnindex=succletprj=function|0->None|i->Some(i-1)letis_nonex=x=noneletcardinal(typen)(Cardinaln:ncardinal)=ifLazy.is_valnthenletn=1+Lazy.force_valninCardinal(lazyn)elseCardinal(Lazy.mapsuccn)endtype'nopt='nOpt.nmoduleConst(X:sigvalcardinal:intend):CARDINAL=structtypen=unitlet()=assert(X.cardinal>=0)letn=Cardinal(lazyX.cardinal)endletconstc:(moduleCARDINAL)=assert(c>=0);(modulestructtypen=unitletn=Cardinal(lazyc)end)moduletypeUNSAFE_CARDINAL=sigtype'atmoduleConst(M:sigtypetvalcardinal:intend):CARDINALwithtypen=M.ttmoduleEq(M:sigtypetincludeCARDINALend):sigvaleq:(M.tt,M.n)eqendendmoduleUnsafe_cardinal():UNSAFE_CARDINAL=structtype'at=unitmoduleConst(M:sigtypetvalcardinal:intend)=structtypen=M.ttletn:ncardinal=Cardinal(lazy(M.cardinal))endmoduleEq(M:sigtypetincludeCARDINALend)=structleteq:(M.tt,M.n)eq=letCardinal_=M.ninReflendend(* [Gensym] produces a set whose cardinal is a priori unknown. A new reference
stores the current cardinal, which grows when [fresh()] is invoked. [fresh]
fails if the suspension [n] has been forced. *)moduleGensym()=structtypen=unitletcounter=ref0letn=Cardinal(lazy!counter)letfresh()=assert(not(is_valn));letresult=!counterinincrcounter;resultendtype('l,'r)either=|Lof'l|Rof'rmoduleSum=structtype(_,_)n=unitmoduletypeS=sigtypelandrtypenonrecn=(l,r)nincludeCARDINALwithtypen:=nvalinj_l:lindex->nindexvalinj_r:rindex->nindexvalprj:nindex->(lindex,rindex)eitherendmoduleMake(L:CARDINAL)(R:CARDINAL)=structtypel=L.ntyper=R.ntypenonrecn=(l,r)n(* The cardinal [l] of the left-hand set becomes fixed now (if it
wasn't already). We need it to be fixed for our injections and
projections to make sense. *)letl:int=cardinalL.n(* The right-hand set can remain open-ended. *)letr:rcardinal=R.nletn:ncardinal=(* We optimize the case where [r] is fixed already, but the code
in the [else] branch would work always. *)ifis_valrthenletn=l+cardinalrinCardinal(lazyn)elseCardinal(lazy(l+cardinalr))(* Injections. The two sets are numbered side by side. *)letinj_lx=xletinj_ry=l+y(* Projection. *)letprjx=ifx<lthenLxelseR(x-l)endletcardinal(typelr)(l:lcardinal)(r:rcardinal):(l,r)ncardinal=letc=cardinall+cardinalrinCardinal(lazyc)letinj_lx=xletinj_r(typelr)(Cardinall:lcardinal)(x:rindex)=Lazy.force_vall+xletprj(typelr)(Cardinall:lcardinal)(x:(l,r)nindex):(lindex,rindex)either=letl=Lazy.force_vallinifx<lthenLxelseR(x-l)letmake(typelr)(l:lcardinal)(r:rcardinal)=letmoduleL=structtypen=lletn=lendinletmoduleR=structtypen=rletn=rendin(moduleMake(L)(R):Swithtypel=landtyper=r)endmoduleProd=structtype(_,_)n=unitmoduletypeS=sigtypelandrtypenonrecn=(l,r)nincludeCARDINALwithtypen:=nvalinj:lindex->rindex->nindexvalprj:nindex->lindex*rindexendmoduleMake(L:CARDINAL)(R:CARDINAL)=structtypen=unittypel=L.ntyper=R.n(* The cardinal [l] of the left-hand set becomes fixed now (if it
wasn't already). We need it to be fixed for our injections and
projections to make sense. *)letl:int=cardinalL.n(* The right-hand set can remain open-ended. *)letr:rcardinal=R.nletn:ncardinal=(* We optimize the case where [r] is fixed already, but the code
in the [else] branch would work always. *)ifis_valrthenletn=l*cardinalrinCardinal(lazyn)elseCardinal(lazy(l*cardinalr))(* Injections. The two sets are numbered side by side. *)letinjxy=y*l+x(* Projection. *)letprjx=(xmodl,x/l)endletcardinal(typelr)(Cardinall:lcardinal)(Cardinalr:rcardinal):(l,r)ncardinal=letl=Lazy.force_vallinifLazy.is_valrthenletc=l*Lazy.force_valrinCardinal(lazyc)elseCardinal(lazy(l*Lazy.force_valr))letinj(typel)(Cardinall:lcardinal)lxrx=lx+rx*(Lazy.force_vall)letprj(typel)(Cardinall:lcardinal)x=letl=Lazy.force_vallin(xmodl,x/l)letmake(typelr)(l:lcardinal)(r:rcardinal)=letmoduleL=structtypen=lletn=lendinletmoduleR=structtypen=rletn=rendin(moduleMake(L)(R):Swithtypel=landtyper=r)endmoduleIndex=structtype'nt='nindexletof_int(n:'ncardinal)i:'nindex=letn=cardinalninifi<0||i>=ntheninvalid_arg"Index.of_int";iletto_inti=iletiter(n:'ncardinal)(yield:'nindex->unit)=letn=cardinalninfori=0ton-1doyieldidoneletrev_iter(n:'ncardinal)(yield:'nindex->unit)=letn=cardinalninfori=n-1downto0doyieldidoneletseq_initnf=ifn<0theninvalid_arg"seq_init: n < 0"elseifn=0thenSeq.emptyelseletj=n-1inletrecauxi()=ifi=jthenSeq.Cons(fi,Seq.empty)elseSeq.Cons(fi,aux(i+1))inaux0letinit_seq(n:'ncardinal)f=seq_init(cardinaln)fletrev_init_seq(n:'ncardinal)f=letn=cardinalninletn'=n-1inseq_initn(funi->f(n'-i))exceptionEnd_of_setletenumerate(n:'ncardinal):unit->'nindex=letn=cardinalninletnext=ref0infun()->leti=!nextinifn<=ithenraiseEnd_of_set;incrnext;iletrev_enumerate(n:'ncardinal):unit->'nindex=letn=cardinalninletnext=ref(n-1)infun()->leti=!nextinifi<0thenraiseEnd_of_set;decrnext;iletpred=function|0->None|i->Some(predi)letequal=Int.equalletcompare=Int.compareletminimum=Int.minletmaximum=Int.maxmoduleUnsafe=structmoduletypeT=sigtype'atendmoduletypeF=functor(X:T)->sigmoduletypeSendmoduleInt=structtype'at=intendmoduleIndex=IntmoduleCoerce(F:F)(X:F(Int).S):F(Index).S=Xendendtype('n,'a)vector=Vector:'aarray->(unit,'a)vector[@@ocaml.unboxed]moduleVector=structtype('n,'a)t=('n,'a)vectorletget(typen)(Vectora:(n,_)t)i=Array.unsafe_getailetset(typen)(Vectora:(n,_)t)ix=Array.unsafe_setaixletset_constix=setti(x::getti)letlength_as_int(typen)(Vectora:(n,_)vector)=Array.lengthaletlength(typen)(Vectora:(n,_)t):ncardinal=letn=Array.lengthainCardinal(lazyn)letempty:(Empty.n,_)t=Vector[||]letmake(typen)(Cardinaln:ncardinal)x:(n,_)t=Vector(Array.make(Lazy.force_valn)x)letmake'(typen)(Cardinaln:ncardinal)f:(n,_)t=matchLazy.force_valnwith|0->empty|n->Vector(Array.maken(f()))letinit(typen)(Cardinaln:ncardinal)f:(n,_)t=Vector(Array.init(Lazy.force_valn)f)letmap(typen)f(Vectora:(n,_)t):(n,_)t=Vector(Array.mapfa)letmapi(typen)f(Vectora:(n,_)t):(n,_)t=Vector(Array.mapifa)letcopy(typen)(Vectora:(n,_)t):(n,_)t=Vector(Array.copya)letequal(typen)eq(Vectora:(n,_)t)(Vectorb:(n,_)t)=letrecloopij=ifi=jthentrueelseifeq(Array.unsafe_getai)(Array.unsafe_getbi)thenloop(i+1)jelsefalseinloop0(Array.lengtha)letcompare(typen)cmp(Vectora:(n,_)t)(Vectorb:(n,_)t)=letrecloopij=ifi=jthen0elseletc=cmp(Array.unsafe_getai)(Array.unsafe_getbi)inifc<>0thencelseloop(i+1)jinloop0(Array.lengtha)letfor_all(typen)f(Vectora:(n,_)t)=Array.for_allfaletexists(typen)f(Vectora:(n,_)t)=Array.existsfaletiter(typen)f(Vectora:(n,_)t)=Array.iterfaletiteri(typen)f(Vectora:(n,_)t)=Array.iterifaletiter2(typen)f(Vectora:(n,_)t)(Vectorb:(n,_)t)=Array.iter2fabletfold_left(typen)facc(Vectora:(n,_)t)=Array.fold_leftfaccaletfold_left2(typen)facc(Vectora:(n,_)t)(Vectorb:(n,_)t)=letacc=refaccinfori=0toArray.lengtha-1doacc:=f!acca.(i)b.(i)done;!accletfold_lefti(typen)facc(Vectora:(n,_)t)=letacc=refaccinfori=0toArray.lengtha-1doacc:=f!accia.(i)done;!accletfold_lefti2(typen)facc(Vectora:(n,_)t)(Vectorb:(n,_)t)=letacc=refaccinfori=0toArray.lengtha-1doacc:=f!accia.(i)b.(i)done;!accletfold_right(typen)f(Vectora:(n,_)t)acc=Array.fold_rightfaaccletfold_right2(typen)f(Vectora:(n,_)t)(Vectorb:(n,_)t)acc=letacc=refaccinfori=Array.lengtha-1downto0doacc:=fa.(i)b.(i)!accdone;!accletfold_righti(typen)f(Vectora:(n,_)t)acc=letacc=refaccinfori=Array.lengtha-1downto0doacc:=fia.(i)!accdone;!accletfold_righti2(typen)f(Vectora:(n,_)t)(Vectorb:(n,_)t)acc=letacc=refaccinfori=Array.lengtha-1downto0doacc:=fia.(i)b.(i)!accdone;!accletrev_iteri(typen)f(Vectora:(n,_)t)=fori=Array.lengtha-1downto0dofia.(i)doneletas_array(typen)(Vectora:(n,_)t)=aletto_list(typen)(Vectora:(n,_)t)=Array.to_listaletcast_array(typen)(Cardinaln:ncardinal)arr:(n,_)t=ifLazy.force_valn<>Array.lengtharrtheninvalid_arg"Vector.cast_array: incorrect length";Vectorarrtype'apacked=Packed:(_,'a)vector->'apackedletof_arraya=Packed(Vectora)letof_listl=Packed(Vector(Array.of_listl))moduletypeV=sigtypentypeavalvector:(n,a)tendmoduleOf_array(A:sigtypeavalarray:aarrayend)=structtypen=unittypea=A.aletvector=VectorA.arrayendend