1 (* Copyright (C) 2009 Matthew Fluet.
2 * Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
9 functor HashedUniqueSet(structure Set : SET
10 structure Element : sig include T val hash : t -> word end
11 sharing type Set.Element.t = Element.t) : SET =
15 structure Element = Element
16 val hash = Element.hash
18 fun index (w: word, mask: word): int
19 = Word.toInt (Word.andb (w, mask))
21 datatype t = T of {buckets: Set.t vector,
24 fun stats' {buckets, mask}
28 fn (s', (size, min, max)) => let
32 SOME (Option.fold(min,n,Int.min)),
33 SOME (Option.fold(max,n,Int.max)))
37 val T (ref {buckets, mask}) = s
39 stats' {buckets = buckets, mask = mask}
42 fun grow {buckets, mask}
45 val mask = Word.orb (0wx1, Word.<<(mask, 0wx1))
46 val high = Word.andb (mask, Word.notb mask')
48 val n = Vector.length buckets
51 = (#1 o Vector.unfoldi)
57 of h::t => (h, (t, b))
58 | _ => Error.bug "HashedUniqueSet.grow"
61 of h::t => (h, (t, true))
62 | _ => Error.bug "HashedUniqueSet.grow"
66 (Vector.sub(buckets, i),
67 fn x => Word.andb(high, hash x) = 0wx0)
72 {buckets = buckets, mask = mask}
75 fun shrink {buckets, mask}
77 val mask = Word.>>(mask, 0wx1)
79 val n = (Vector.length buckets) div 2
82 = (#1 o Vector.unfoldi)
86 val s1 = Vector.sub(buckets, i)
87 val s2 = Vector.sub(buckets, i + n)
92 {buckets = buckets, mask = mask}
95 fun T' {buckets, mask}
97 val (size,min,max) = stats' {buckets = buckets, mask = mask}
98 val max = case max of SOME max => max | NONE => ~1
99 val n = Vector.length buckets
102 then T (ref (grow {buckets = buckets, mask = mask}))
103 else if max < n div 2 andalso n > 2
104 then T (ref (shrink {buckets = buckets, mask = mask}))
105 else T (ref {buckets = buckets, mask = mask})
108 fun coerce (s1 as T (s1' as ref (s1'' as {buckets = buckets1, mask = mask1})),
109 s2 as T (s2' as ref (s2'' as {buckets = buckets2, mask = mask2})))
112 else if mask1 < mask2
113 then (s1' := grow s1'';
115 else (s2' := grow s2'';
122 val buckets = Vector.new2 (Set.empty, Set.empty)
124 T (ref {buckets = buckets,
131 = if Word.andb(mask, hash x) = 0wx0
132 then Vector.new2 (Set.singleton x, Set.empty)
133 else Vector.new2 (Set.empty, Set.singleton x)
135 T (ref {buckets = buckets,
142 val T (ref {buckets, mask}) = s
144 vw(buckets, fn s' => sw s')
146 fun walk2 (vw, sw) (s1, s2)
148 val _ = coerce (s1, s2)
149 val T (ref {buckets = buckets1, mask}) = s1
150 val T (ref {buckets = buckets2, mask}) = s2
152 vw(buckets1, buckets2, fn (s1', s2') => sw (s1', s2'))
155 val areDisjoint = walk2 (Vector.forall2, Set.areDisjoint)
156 val equals = walk2 (Vector.forall2, Set.equals)
157 fun exists (s, p) = walk1 (Vector.exists, fn s' => Set.exists(s', p)) s
158 fun forall (s, p) = walk1 (Vector.forall, fn s' => Set.forall(s', p)) s
159 fun foreach (s, f) = walk1 (Vector.foreach, fn s' => Set.foreach(s', f)) s
163 val T (ref {buckets, mask}) = s
166 = (#1 o Vector.unfoldi)
167 (Vector.length buckets,
170 val s' = Vector.sub(buckets, i)
175 T' {buckets = buckets, mask = mask}
177 fun build2 sb (s1, s2)
179 val _ = coerce (s1, s2)
180 val T (ref {buckets = buckets1, mask}) = s1
181 val T (ref {buckets = buckets2, mask}) = s2
184 = (#1 o Vector.unfoldi)
185 (Vector.length buckets1,
188 val s1' = Vector.sub(buckets1, i)
189 val s2' = Vector.sub(buckets2, i)
194 T' {buckets = buckets, mask = mask}
197 val difference = build2 Set.-
198 val intersect = build2 Set.intersect
199 fun subset (s, p) = build1 (fn s' => Set.subset(s', p)) s
200 val union = build2 Set.+
201 fun unions [] = empty
203 | unions [s1,s2] = union(s1, s2)
204 | unions (s1::s2::ss) = unions(union(s1,s2)::ss)
209 val T (ref {buckets, mask}) = s
211 Set.contains(Vector.sub(buckets, index(hash x, mask)), x)
217 val T (ref {buckets, mask}) = s
218 val ix = index(hash x, mask)
220 = (#1 o Vector.unfoldi)
221 (Vector.length buckets,
225 val s' = Vector.sub(buckets, i)
228 then (Set.add(s', x), ())
232 T' {buckets = buckets,
236 = if not (contains(s, x))
239 val T (ref {buckets, mask}) = s
240 val ix = index(hash x, mask)
242 = (#1 o Vector.unfoldi)
243 (Vector.length buckets,
247 val s' = Vector.sub(buckets, i)
250 then (Set.remove(s', x), ())
254 T' {buckets = buckets,
259 val T (ref {buckets, mask}) = s
260 val n = Vector.length buckets
267 val {yes = yes', no = no'} = Set.partition (s', p)
273 = (#1 o Vector.unfoldi)
278 | _ => Error.bug "HashedUniqueSet.partition.yes")
280 = (#1 o Vector.unfoldi)
285 | _ => Error.bug "HashedUniqueSet.partition.no")
287 {yes = T' {buckets = yes, mask = mask},
288 no = T' {buckets = no, mask = mask}}
294 val T (ref {buckets, mask}) = s
299 fn (s', b) => Set.fold(s', b, f))
302 fun fromList l = List.fold(l, empty, fn (x, s) => add(s, x))
303 fun toList s = fold(s, [], op ::)
304 fun map (s, f) = fold(s, empty, fn (x, s) => add(s, f x))
306 = fold(s, empty, fn (x, s) => case f x
308 | SOME x' => add(s, x'))
309 fun subsetSize (s, p)
310 = fold(s, 0: int, fn (x, n) => if p x then n + 1 else n)
311 fun size s = subsetSize(s, fn _ => true)
314 fun layout s = List.layout Element.layout (toList s)
316 fun power s = Error.bug "HashedUniqueSet.power"
317 fun subsets (s, n) = Error.bug "HashedUniqueSet.subsets"
319 fun isEmpty s = size s = 0
320 fun isSubsetEq (s1, s2) = size (difference (s1, s2)) = 0
321 fun isSubset (s1, s2) = (size s1 <> size s2) andalso isSubsetEq(s1, s2)
322 fun isSupersetEq (s1, s2) = isSubsetEq(s2, s1)
323 fun isSuperset (s1, s2) = isSubset(s2, s1)
326 val op - = difference
328 val op <= = isSubsetEq
329 val op > = isSuperset
330 val op >= = isSupersetEq