123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659(* ********************************************************************************************** *
* MetaStack Solutions Ltd. *
* ********************************************************************************************** *
* BitMask Sets *
* ********************************************************************************************** *
* Copyright (c) 2013-17 MetaStack Solutions Ltd. *
* ********************************************************************************************** *
* Author: David Allsopp *
* 27-Dec-2013 *
* ********************************************************************************************** *
* Redistribution and use in source and binary forms, with or without modification, are permitted *
* provided that the following two conditions are met: *
* 1. Redistributions of source code must retain the above copyright notice, this list of *
* conditions and the following disclaimer. *
* 2. Neither the name of MetaStack Solutions Ltd. nor the names of its contributors may be *
* used to endorse or promote products derived from this software without specific prior *
* written permission. *
* *
* This software is provided by the Copyright Holder 'as is' and any express or implied *
* warranties, including, but not limited to, the implied warranties of merchantability and *
* fitness for a particular purpose are disclaimed. In no event shall the Copyright Holder be *
* liable for any direct, indirect, incidental, special, exemplary, or consequential damages *
* (including, but not limited to, procurement of substitute goods or services; loss of use, *
* data, or profits; or business interruption) however caused and on any theory of liability, *
* whether in contract, strict liability, or tort (including negligence or otherwise) arising in *
* any way out of the use of this software, even if advised of the possibility of such damage. *
* ********************************************************************************************** *)(* ********************************************************************************************** *
* Copied from header. *
* ********************************************************************************************** *)moduletypeS=sigincludeSet.Svalmap:(elt->elt)->t->tvalfilter_map:(elt->eltoption)->t->tvalmin_elt_opt:t->eltoptionvalmax_elt_opt:t->eltoptionvalchoose_opt:t->eltoptionvalfind:elt->t->eltvalfind_opt:elt->t->eltoptionvalfind_first:(elt->bool)->t->eltvalfind_first_opt:(elt->bool)->t->eltoptionvalfind_last:(elt->bool)->t->eltvalfind_last_opt:(elt->bool)->t->eltoptionvalof_list:eltlist->tvalto_seq_from:elt->t->eltSeq.tvalto_seq:t->eltSeq.tvaladd_seq:eltSeq.t->t->tvalof_seq:eltSeq.t->tvaldisjoint:t->t->boolvalto_rev_seq:t->eltSeq.ttypestoragevalinvalid:t->tendmoduletypeStorage=sigtypestoragevalzero:storagevalone:storagevallogand:storage->storage->storagevallogor:storage->storage->storagevallognot:storage->storagevalshift_left:storage->int->storagevalshift_right_logical:storage->int->storagevalcompare:storage->storage->intvaltoString:storage->stringendmoduletypeBitMask=sigincludeStoragetypetvalmask:storageend(* ********************************************************************************************** *
* Implementations of Storage for types int and int64. *
* ********************************************************************************************** *)moduleInt=structtypestorage=intletzero=0letone=1letshift_left=(lsl)letshift_right_logical=(lsr)letlogand=(land)letlogor=(lor)letlognot=lnotletcompare=comparelettoString=string_of_intendmoduleInt64=structtypestorage=int64letzero=0Lletone=1Lletshift_left=Int64.shift_leftletshift_right_logical=Int64.shift_right_logicalletlogand=Int64.logandletlogor=Int64.logorletlognot=Int64.lognotletcompare=Int64.comparelettoString=Int64.to_stringend(* ********************************************************************************************** *
* Make functor. *
* ********************************************************************************************** *)moduleMake(Mask:BitMask):sigincludeSwithtypestorage=Mask.storageandtypet=Mask.storageandtypeelt:=Mask.tvalcreate:storage->tend=structtypestorage=Mask.storagetypet=Mask.storage(* ****************************************************************************************** *
* Convert the supplied mask in the functor into the various required values. *
* ****************************************************************************************** *)let(storage_of_flag,shifts,shiftsInv,topbit,highest,lowest)=let(shifts,shiftsInv,topbit,highest,lowest)=letrecfshiftsInvtopbithighestlowestlci=letv=Mask.shift_leftMask.oneiinifi>0&&Mask.comparevMask.one=0then(List.revshiftsInv,shiftsInv,topbit,highest,lowest)elseifMask.compare(Mask.logandvMask.mask)Mask.zero<>0thenletshiftsInv=ifl>0then(c,l)::shiftsInvelseshiftsInvinifMask.comparelowestMask.zero=0thenfshiftsInv0vv00(succi)elsefshiftsInv(succtopbit)vlowest00(succi)elseifl>0thenfshiftsInvtopbithighestlowest(succl)c(succi)elsefshiftsInvtopbithighestlowest1(succtopbit)(succi)inf[](-1)Mask.zeroMask.zero000inletcompute_shiftshiftsoffset=letrecfa=function(point,amount)::shifts->ifoffset>=pointthenf(a+amount)shiftselsea|[]->ainfoffsetshiftsinlet(storage_of_flag,shifts)=matchshiftswith[]->((fun(flag:Mask.t)->Mask.shift_leftMask.one(Obj.magicflag:int)),[])|[(0,n)]->((fun(flag:Mask.t)->Mask.shift_leftMask.one(n+(Obj.magicflag:int))),[])|(0,n)::shifts->((fun(flag:Mask.t)->letshift=n+compute_shiftshifts(Obj.magicflag:int)inMask.shift_leftMask.oneshift),shifts)|_->((fun(flag:Mask.t)->Mask.shift_leftMask.one(compute_shiftshifts(Obj.magicflag:int))),shifts)in(storage_of_flag,shifts,shiftsInv,topbit,highest,lowest)(* ****************************************************************************************** *
* create, invalid, empty and is_empty are straightforward. *
* ****************************************************************************************** *)letcreatemask=maskletinvalidset=Mask.logand(Mask.lognotMask.mask)setletempty=Mask.zeroletis_emptyset=(Mask.comparesetMask.zero=0)(* ****************************************************************************************** *
* Another sequence of straightforward functions. *
* ****************************************************************************************** *)letmemflagset=Mask.compare(Mask.logandset(storage_of_flagflag))Mask.zero<>0letfindflagset=ifMask.compare(Mask.logandset(storage_of_flagflag))Mask.zero=0thenraiseNot_foundelseflagletfind_optflagset=ifMask.compare(Mask.logandset(storage_of_flagflag))Mask.zero=0thenNoneelseSomeflagletaddflagset=letset'=Mask.logorset(storage_of_flagflag)inifMask.comparesetset'=0thensetelseset'letof_listl=List.fold_left(funsf->addfs)emptylletsingleton=storage_of_flagletremoveflagset=letset'=Mask.logandset(Mask.lognot(storage_of_flagflag))inifMask.comparesetset'=0thensetelseset'letunion=Mask.logorletinter=Mask.logandletdisjointab=Mask.logandab=Mask.zeroletdiffab=Mask.logandb(Mask.lognota)letcompare=Mask.compareletequalab=Mask.compareab=0letsubsetab=Mask.compare(Mask.logandab)a=0(* ****************************************************************************************** *
* deltaShift and deltaShiftInv are used to calculate bit values for the iterators. *
* ****************************************************************************************** *)letdeltaShifti=function(point,amount)::shiftswheni>=point->(succamount,shifts)|_asshifts->(1,shifts)letdeltaShiftInvi=function(point,amount)::shiftswheni<point->(succamount,shifts)|_asshifts->(1,shifts)(* ****************************************************************************************** *
* The iterators count over the bit positions -- for the iterator itself, [i] is the *
* constructor number, [v] is the bit value for that constructor and [s] is the shifts. *
* ****************************************************************************************** *)letfind_firstgset=letset=Mask.logandsetMask.maskinletrecfivs=letelt=(Obj.magici:Mask.t)inifMask.compare(Mask.logandsetv)Mask.zero<>0&&gelttheneltelseifMask.comparevhighest=0thenraiseNot_foundelseleti=succiinlet(shift,s)=deltaShiftisinfi(Mask.shift_leftvshift)sinf0lowestshiftsletfind_first_optgset=letset=Mask.logandsetMask.maskinletrecfivs=letelt=(Obj.magici:Mask.t)inifMask.compare(Mask.logandsetv)Mask.zero<>0&&geltthenSomeeltelseifMask.comparevhighest=0thenNoneelseleti=succiinlet(shift,s)=deltaShiftisinfi(Mask.shift_leftvshift)sinf0lowestshiftsletfind_lastgset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.comparevMask.zero<>0thenletelt=(Obj.magici:Mask.t)inifMask.compare(Mask.logandvset)Mask.zero<>0&&gelttheneltelseleti=prediinlet(shift,s)=deltaShiftInvisinfi(Mask.shift_right_logicalvshift)selseraiseNot_foundinftopbithighestshiftsInvletfind_last_optgset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.comparevMask.zero<>0thenletelt=(Obj.magici:Mask.t)inifMask.compare(Mask.logandvset)Mask.zero<>0&&geltthenSomeeltelseleti=prediinlet(shift,s)=deltaShiftInvisinfi(Mask.shift_right_logicalvshift)selseNoneinftopbithighestshiftsInvletitergset=letset=Mask.logandsetMask.maskinletrecfivs=let_=ifMask.compare(Mask.logandsetv)Mask.zero<>0theng(Obj.magici:Mask.t)inifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfi(Mask.shift_leftvshift)sinf0lowestshiftsletfoldgsetacc=letset=Mask.logandsetMask.maskinletrecfaivs=leta=ifMask.compare(Mask.logandsetv)Mask.zero<>0theng(Obj.magici:Mask.t)aelseainifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfai(Mask.shift_leftvshift)selseainfacc0lowestshiftsletmapgset'=letset=Mask.logandset'Mask.maskinletrecfaivs=ifMask.comparevhighest<>0thenleta=ifMask.compare(Mask.logandsetv)Mask.zero<>0thenMask.logora(storage_of_flag(g(Obj.magici:Mask.t)))elseaandi=succiinlet(shift,s)=deltaShiftisinfai(Mask.shift_leftvshift)selseifMask.compareaset'=0thenset'elseainfMask.zero0lowestshiftsletfilter_mapgset'=letset=Mask.logandset'Mask.maskinletrecfaivs=ifMask.comparevhighest<>0thenleta=ifMask.compare(Mask.logandsetv)Mask.zero<>0thenmatchg(Obj.magici:Mask.t)withSomeflag->Mask.logora(storage_of_flagflag)|None->Mask.logandset(Mask.lognotv)elseaandi=succiinlet(shift,s)=deltaShiftisinfai(Mask.shift_leftvshift)selseifMask.compareaset'=0thenset'elseainfMask.zero0lowestshiftsletfor_allpset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.compare(Mask.logandsetv)Mask.zero=0||p(Obj.magici:Mask.t)thenifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfi(Mask.shift_leftvshift)selsetrueelsefalseinf0lowestshiftsletexistspset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.compare(Mask.logandsetv)Mask.zero=0||not(p(Obj.magici:Mask.t))thenifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfi(Mask.shift_leftvshift)selsefalseelsetrueinf0lowestshiftsletfilterpset=letset=Mask.logandsetMask.maskinletrecfaivs=leta=ifMask.compare(Mask.logandvset)Mask.zero<>0&&p(Obj.magici:Mask.t)thenMask.logoravelseainifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfai(Mask.shift_leftvshift)selseainfMask.zero0lowestshiftsletpartitionpset=letset=Mask.logandsetMask.maskinletrecf((l,r)asa)ivs=leta=ifMask.compare(Mask.logandvset)Mask.zero<>0thenifp(Obj.magici:Mask.t)then(Mask.logorlv,r)else(l,Mask.logorrv)elseainifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfai(Mask.shift_leftvshift)selseainf(Mask.zero,Mask.zero)0lowestshiftsletcardinalset=letset=Mask.logandsetMask.maskinletrecfaiv=leta=ifMask.compare(Mask.logandvset)Mask.zero<>0thensuccaelseainifMask.comparevhighest=0thenaelsefa(succi)(Mask.shift_leftv1)inf00lowestletelementsset=letset=Mask.logandsetMask.maskinletrecfaivs=ifMask.comparevMask.zero<>0thenleta=ifMask.compare(Mask.logandvset)Mask.zero<>0then(Obj.magici:Mask.t)::aelseaandi=prediinlet(shift,s)=deltaShiftInvisinfai(Mask.shift_right_logicalvshift)selseainf[]topbithighestshiftsInvletmin_eltset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.compare(Mask.logandvset)Mask.zero<>0then(Obj.magici:Mask.t)elseifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfi(Mask.shift_leftvshift)selseraiseNot_foundinf0lowestshiftsletmin_elt_optset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.compare(Mask.logandvset)Mask.zero<>0thenSome(Obj.magici:Mask.t)elseifMask.comparevhighest=0thenleti=succiinlet(shift,s)=deltaShiftisinfi(Mask.shift_leftvshift)selseNoneinf0lowestshiftsletmax_eltset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.comparevMask.zero<>0thenifMask.compare(Mask.logandvset)Mask.zero<>0then(Obj.magici:Mask.t)elseleti=prediinlet(shift,s)=deltaShiftInvisinfi(Mask.shift_right_logicalvshift)selseraiseNot_foundinftopbithighestshiftsInvletmax_elt_optset=letset=Mask.logandsetMask.maskinletrecfivs=ifMask.comparevMask.zero<>0thenifMask.compare(Mask.logandvset)Mask.zero<>0thenSome(Obj.magici:Mask.t)elseleti=prediinlet(shift,s)=deltaShiftInvisinfi(Mask.shift_right_logicalvshift)selseNoneinftopbithighestshiftsInvletchoose=min_eltletchoose_opt=min_elt_optletsplit(flag:Mask.t)set=letflag=(Obj.magicflag:int)andset=Mask.logandsetMask.maskinletrecf((l,p,r)asa)ivs=leta=ifMask.compare(Mask.logandvset)Mask.zero<>0thenletc=Stdlib.compareiflaginifc=0then(l,true,r)elseifc<0then(Mask.logorvl,p,r)else(l,p,Mask.logorvr)elseainifMask.comparevhighest<>0thenleti=succiinlet(shift,s)=deltaShiftisinfai(Mask.shift_leftvshift)selseainf(Mask.zero,false,Mask.zero)0lowestshiftsletto_seq_fromxset=letset=Mask.logandsetMask.maskandx=(Obj.magicx:int)inletrecfivs()=lettail=ifMask.comparevhighest=0thenSeq.emptyelseletj=succiinlet(shift,s)=deltaShiftjsinfj(Mask.shift_leftvshift)sinifi>=x&&Mask.compare(Mask.logandvset)Mask.zero<>0thenSeq.Cons((Obj.magici:Mask.t),tail)elsetail()inf0lowestshiftsletto_seqset=to_seq_from(Obj.magic0:Mask.t)setletto_rev_seqset=letset=Mask.logandsetMask.maskinletrecfivs()=lettail=ifMask.comparevMask.zero=0thenSeq.emptyelseletj=prediinlet(shift,s)=deltaShiftInvjsinfj(Mask.shift_right_logicalvshift)sinifMask.compare(Mask.logandvset)Mask.zero<>0thenSeq.Cons((Obj.magici:Mask.t),tail)elsetail()inftopbithighestshiftsInvletadd_seqsset=Seq.fold_left(funsetflag->addflagset)setsletof_seqs=add_seqsemptyend