signature IntSets = sig eqtype IntSet val emptyIntSet : IntSet val singleIntSet : int -> IntSet val fullIntSet : int -> IntSet val isEmptyIntSet : IntSet -> bool val inIntSet : int * IntSet -> bool val compareIntSets: IntSet * IntSet -> order val hashIntSet : IntSet -> word val addIntSet : int * IntSet -> IntSet val delIntSet : int * IntSet -> IntSet val cupIntSets : IntSet * IntSet -> IntSet val capIntSets : IntSet * IntSet -> IntSet val diffIntSets : IntSet * IntSet -> IntSet val IntSet2List : IntSet -> int list val IntList2Set : int list -> IntSet end structure IntSets : IntSets = struct structure W = Word32 val wordSize = W.wordSize type IntSet = W.word vector infix 7 << >> infix 6 && infix 5 || val op >> = W.>> val op << = W.<< val op && = W.andb val op || = W.orb val !! = W.notb fun normalize (vec:IntSet) = let val max = Vector.foldli (fn (i,w,max) => if w=0wx0 then i else max) 0 vec in VectorSlice.vector(VectorSlice.slice (vec,0,SOME max)) end val emptyIntSet = Vector.fromList nil : IntSet fun fullIntSet n = let val size = (n+wordSize-1) div wordSize val full = 0w0-0w1:W.word val bits = (n-1) mod wordSize+1 val last = full >> (Word.fromInt (wordSize-bits)) in Vector.tabulate(n div wordSize+1, fn i => if i if i=idx then mask else 0w0):IntSet end fun isEmptyIntSet vec = Vector.length vec=0 fun inIntSet(n,vec) = let val idx = n div wordSize in if idx>=Vector.length vec then false else let val mask = 0w1 << (Word.fromInt (n mod wordSize)) in Vector.sub(vec,idx) && mask <> 0w0 end end fun addIntSet(n,vec) = let val idx = n div wordSize val mask = 0w1 << (Word.fromInt (n mod wordSize)) val size = Vector.length vec in if size>idx then Vector.mapi (fn (i,x) => if i=idx then x||mask else x) vec else Vector.tabulate (idx+1,fn i => if i if i=idx then x && mask else x) vec end in normalize vec1 end fun capIntSets(vec1,vec2) = let val l12 = Int.min(Vector.length vec1,Vector.length vec2) val v12 = Vector.tabulate(l12,fn i => Vector.sub(vec1,i) && Vector.sub(vec2,i)) in normalize v12 end fun cupIntSets(vec1,vec2) = let val (l1,l2) = (Vector.length vec1,Vector.length vec2) val (shorter,longer,v) = if l1<=l2 then (l1,l2,vec2) else (l2,l1,vec1) in Vector.tabulate (longer,fn i => if i>=shorter then Vector.sub(v,i) else Vector.sub(vec1,i) || Vector.sub(vec2,i)) end fun diffIntSets(vec1,vec2) = let val (l1,l2) = (Vector.length vec1,Vector.length vec2) val vec1 = Vector.tabulate (l1,fn i => if i>=l2 then Vector.sub(vec1,i) else Vector.sub(vec1,i) && !!(Vector.sub(vec2,i))) in normalize vec1 end fun IntList2Set l = List.foldl addIntSet emptyIntSet l fun IntSet2List vec = let val size = Vector.length vec fun doOne (w,off,yet) = let fun doit (i,mask) = if i=wordSize then yet else if w&&mask=0w0 then doit(i+1,mask<<0wx1) else (off+i)::doit(i+1,mask<<0wx1) in doit(0,0wx1) end fun doAll i = if i>=size then nil else doOne(Vector.sub(vec,i),wordSize*i,(doAll (i+1))) in doAll 0 end fun compareIntSets (vec1,vec2:IntSet) = let val (l1,l2) = (Vector.length vec1,Vector.length vec2) val (l12,ifEq) = case Int.compare(l1,l2) of LESS => (l1,LESS) | order => (l2,order) fun doit i = if i>=l12 then ifEq else case W.compare(Vector.sub(vec1,i),Vector.sub(vec2,i)) of EQUAL => doit (i+1) | order => order in doit 0 end val intShift = case Int.precision of NONE => 0w0 | SOME x => Word.fromInt(Int.max(wordSize-x+1,0)) fun hashIntSet vec = case Vector.length vec of 0 => 0w0 | 1 => Word.fromInt(W.toInt(W.>>(Vector.sub(vec,0),intShift))) | l => Word.fromInt(W.toInt(W.>>(Vector.sub(vec,0)+Vector.sub(vec,l-1),intShift))) end