174 lines
4.7 KiB
Standard ML
174 lines
4.7 KiB
Standard ML
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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<size-1 then full else last):IntSet
|
|
end
|
|
|
|
fun singleIntSet n =
|
|
let
|
|
val idx = n div wordSize
|
|
val mask = 0w1 << (Word.fromInt (n mod wordSize))
|
|
in
|
|
Vector.tabulate(idx+1,fn 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<size then Vector.sub(vec,i) else if i=idx then mask else 0w0)
|
|
end
|
|
|
|
fun delIntSet(n,vec) =
|
|
let
|
|
val idx = n div wordSize
|
|
val size = Vector.length vec
|
|
val vec1 = if size<=idx then vec
|
|
else let val mask = !! (0w1 << (Word.fromInt (n mod wordSize)))
|
|
in Vector.mapi
|
|
(fn (i,x) => 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
|