123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171openStrongtypeset=inttype'aset_array='aarraytypeloc=inttype'aloc_array='aarraytype'at={mutableset_count:set;element:'aFinite.eltloc_array;location:locarray;(* L *)set_of:setarray;(* S *)first:locset_array;(* F *)past:locset_array;(* P *)marked:intset_array;(* M *)mutableworklist:setlist;}letcreate(typea)?partition(set:aFinite.set)=letidx=xinletundefined=0inletn=Finite.Set.cardinalsetinlett={set_count=ifn=0then0else1;element=Finite.Array.to_array(Finite.Array.all_elementsset);location=Array.initnid;set_of=Array.maken0;first=Array.makenundefined;past=Array.makenundefined;marked=Array.make(n+1)0;worklist=[]}inbeginmatchpartitionwith|None->ifn>0then(t.first.(0)<-0;t.past.(0)<-n;);|Somecmp->Array.sortcmpt.element;letpart=reft.element.(0)int.first.(0)<-0;letset_count=ref0infori=0ton-1doletelt=t.element.(i)inifcmp!partelt<>0then(t.past.(!set_count)<-i;incrset_count;t.first.(!set_count)<-i;part:=elt);t.set_of.((elt:>int))<-!set_count;t.location.((elt:>int))<-idone;t.past.(!set_count)<-n;t.set_count<-!set_count+1;end;tletmark(t:'at)element=letelement':'aFinite.elt:>int=elementinletset=t.set_of.(element')inifset>-1then(letloc_unmarked=t.first.(set)+t.marked.(set)inletloc=t.location.(element')inifloc>=loc_unmarkedthen((*prerr_endline ("marking " ^ string_of_int element' ^
" (in set " ^ string_of_int set ^ ")");*)ifloc>loc_unmarkedthen(letelt_unmarked=t.element.(loc_unmarked)int.element.(loc)<-elt_unmarked;t.location.((elt_unmarked:_Finite.elt:>int))<-loc;t.element.(loc_unmarked)<-element;t.location.(element')<-loc_unmarked;);ift.marked.(set)=0thent.worklist<-set::t.worklist;t.marked.(set)<-t.marked.(set)+1))letsplitt=letworklist=t.worklistint.worklist<-[];List.iter(funset->letj=t.first.(set)+t.marked.(set)inifj=t.past.(set)thent.marked.(set)<-0else(ift.marked.(set)<=t.past.(set)-jthen(t.first.(t.set_count)<-t.first.(set);t.past.(t.set_count)<-j;t.first.(set)<-j;)else(t.past.(t.set_count)<-t.past.(set);t.first.(t.set_count)<-j;t.past.(set)<-j;);fori=t.first.(t.set_count)tot.past.(t.set_count)-1dot.set_of.((t.element.(i):_Finite.elt:>int))<-t.set_countdone;t.marked.(set)<-0;t.marked.(t.set_count)<-0;t.set_count<-t.set_count+1))worklistletdiscard_unmarkedt=t.worklist<-[];forset=0tot.set_count-1doletfirst_unmarked=t.first.(set)+t.marked.(set)infori=first_unmarkedtot.past.(set)-1doletelt=(t.element.(i):_Finite.elt:>int)in(*prerr_endline ("discarding " ^ string_of_int elt);*)t.set_of.(elt)<--1done;t.past.(set)<-first_unmarked;t.marked.(set)<-0doneletdiscardtf=forset=0tot.set_count-1dofori=t.first.(set)tot.past.(set)-1doletelt=t.element.(i)inifnot(felt)thenmarkteltdonedone;discard_unmarkedtletset_countt=t.set_countletset_of(t:'at)elt=t.set_of.((elt:'aFinite.elt:>int))letchoosetset=assert(t.first.(set)<t.past.(set));t.element.(t.first.(set))letchoose_opttset=ift.first.(set)<t.past.(set)thenSomet.element.(t.first.(set))elseNoneletiter_elementstsetf=fori=t.first.(set)tot.past.(set)-1doft.element.(i)doneletiter_marked_elementstsetf=letlast=ref(t.first.(set)-1)inwhile!last<t.first.(set)+t.marked.(set)-1doletgoal=t.first.(set)+t.marked.(set)-1infori=!last+1togoaldoft.element.(i)done;last:=goaldoneletmarked_setst=t.worklistletclear_markst=letworklist=t.worklistint.worklist<-[];List.iter(funset->t.marked.(set)<-0)worklistletis_firsttn=letn=(n:'nFinite.elt:>int)inlets=t.set_of.(n)inletloc=t.location.(n)in(s>-1&&loc=t.first.(s)&&loc<t.past.(s))