Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 2009 Matthew Fluet. |
2 | * Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh | |
3 | * Jagannathan, and Stephen Weeks. | |
4 | * | |
5 | * MLton is released under a BSD-style license. | |
6 | * See the file MLton-LICENSE for details. | |
7 | *) | |
8 | ||
9 | functor BitVectorSet (Element : sig | |
10 | include T | |
11 | val fromInt: int -> t | |
12 | val size: int | |
13 | val toInt: t -> int | |
14 | end) : SET = | |
15 | struct | |
16 | structure Element = Element | |
17 | ||
18 | structure Bin :> sig | |
19 | eqtype t | |
20 | val binSize: int | |
21 | val difference : t * t -> t | |
22 | val empty : t | |
23 | val equals : t * t -> bool | |
24 | val fold : t * 'a * (int * 'a -> 'a) -> 'a | |
25 | val intersect : t * t -> t | |
26 | val singleton : int -> t | |
27 | val union : t * t -> t | |
28 | end = | |
29 | struct | |
30 | open Word | |
31 | val binSize = wordSize | |
32 | ||
33 | val equals : t * t -> bool = op = | |
34 | val empty : t = 0wx0 | |
35 | fun singleton i = <<(0wx1, Word.fromInt i) | |
36 | val difference = fn (b1, b2) => andb (b1, notb b2) | |
37 | val intersect = fn (b1, b2) => andb (b1, b2) | |
38 | val union = fn (b1, b2) => orb (b1, b2) | |
39 | fun fold (w, a, f) | |
40 | = let | |
41 | fun loop (w, a, i) | |
42 | = if Int.< (i, wordSize) | |
43 | then let | |
44 | val a = if andb (w, 0wx1) <> 0wx0 | |
45 | then f (i, a) | |
46 | else a | |
47 | in | |
48 | loop (>>(w, 0wx1), a, Int.+ (i, 1)) | |
49 | end | |
50 | else a | |
51 | in | |
52 | loop (w, a, 0) | |
53 | end | |
54 | end | |
55 | type bin = Bin.t | |
56 | type t = bin vector | |
57 | type index = int (* position in t *) | |
58 | type slot = int (* position in bin *) | |
59 | type pos = index * slot | |
60 | ||
61 | val ltPos : pos * pos -> bool | |
62 | = fn ((index1, slot1), (index2, slot2)) => | |
63 | index1 < index2 orelse | |
64 | (index1 = index2 andalso slot1 < slot2) | |
65 | ||
66 | val intToPos : int -> pos | |
67 | = fn pos => (Int.quot (pos, Bin.binSize), Int.rem (pos, Bin.binSize)) | |
68 | val posToInt : pos -> int | |
69 | = fn (index, slot) => index * Bin.binSize + slot | |
70 | val slotToBin : slot -> bin = fn slot => Bin.singleton slot | |
71 | ||
72 | val eltToPos = intToPos o Element.toInt | |
73 | fun eltToPosBin x = let val pos as (index, slot) = eltToPos x | |
74 | in (pos, slotToBin slot) | |
75 | end | |
76 | val posToElt = Element.fromInt o posToInt | |
77 | ||
78 | val maxPos as (maxIndex,maxSlot) = intToPos (Element.size - 1) | |
79 | ||
80 | val empty : t = Vector.new (maxIndex + 1, Bin.empty) | |
81 | fun isEmpty (v : t) = Vector.forall (v, fn b => b = Bin.empty) | |
82 | fun singleton x = let val ((index,_), bin) = eltToPosBin x | |
83 | in Vector.tabulate (maxIndex + 1, fn i => | |
84 | if i = index | |
85 | then bin | |
86 | else Bin.empty) | |
87 | end | |
88 | fun contains (v, x) = let val ((index,_), bin) = eltToPosBin x | |
89 | in Bin.intersect (bin, Vector.sub (v, index)) <> Bin.empty | |
90 | end | |
91 | fun add (v, x) = let val ((index, _), bin) = eltToPosBin x | |
92 | in Vector.mapi (v, fn (i, b) => | |
93 | if i = index | |
94 | then Bin.union (bin, b) | |
95 | else b) | |
96 | end | |
97 | fun remove (v, x) = let val ((index, _), bin) = eltToPosBin x | |
98 | in Vector.mapi (v, fn (i, b) => | |
99 | if i = index | |
100 | then Bin.difference (b, bin) | |
101 | else b) | |
102 | end | |
103 | fun difference (v1, v2) | |
104 | = Vector.map2 (v1, v2, fn (b1, b2) => Bin.difference (b1, b2)) | |
105 | fun intersect (v1, v2) | |
106 | = Vector.map2 (v1, v2, fn (b1, b2) => Bin.intersect (b1, b2)) | |
107 | fun union (v1, v2) | |
108 | = Vector.map2 (v1, v2, fn (b1, b2) => Bin.union (b1, b2)) | |
109 | fun unions ss = List.fold (ss, empty, union) | |
110 | fun equals (v1, v2) = Vector.equals (v1, v2, Bin.equals) | |
111 | fun isSubsetEq (v1, v2) | |
112 | = Exn.withEscape | |
113 | (fn escape => | |
114 | Vector.fold2 | |
115 | (v1, v2, true, fn (b1, b2, a) => | |
116 | if Bin.difference (b1, b2) = Bin.empty | |
117 | then a | |
118 | else escape false)) | |
119 | fun isSubset (s1, s2) = isSubsetEq (s1, s2) andalso not (equals (s1, s2)) | |
120 | fun isSupersetEq (s1, s2) = isSubsetEq (s2, s1) | |
121 | fun isSuperset (s1, s2) = isSubset (s2, s1) | |
122 | ||
123 | fun areDisjoint (v1, v2) | |
124 | = Exn.withEscape | |
125 | (fn escape => | |
126 | Vector.fold2 | |
127 | (v1, v2, true, fn (b1, b2, a) => | |
128 | if Bin.intersect(b1, b2) = Bin.empty | |
129 | then a | |
130 | else escape false)) | |
131 | ||
132 | ||
133 | fun fold (v, a, f) | |
134 | = Vector.foldi | |
135 | (v, a, fn (i, b, a) => | |
136 | let | |
137 | val check = if i < maxIndex | |
138 | then fn s => true | |
139 | else fn s => s < maxSlot | |
140 | in | |
141 | Bin.fold (b, a, fn (s, a) => if check s | |
142 | then f (posToElt (i, s), a) | |
143 | else a) | |
144 | end) | |
145 | fun foreach (s, f) = fold (s, (), fn (x, ()) => f x) | |
146 | fun peekGen (s, no, f) | |
147 | = Exn.withEscape | |
148 | (fn escape => | |
149 | (foreach (s, fn x => | |
150 | case f x | |
151 | of NONE => () | |
152 | | SOME yes => escape yes) | |
153 | ; no ())) | |
154 | fun exists (s, p) = peekGen (s, | |
155 | fn () => false, | |
156 | fn x => if p x then SOME true else NONE) | |
157 | fun forall (s, p) = not (exists (s, not o p)) | |
158 | ||
159 | fun subsetSize (s, p) | |
160 | = fold (s, 0 : int, fn (x, a) => if p x then a + 1 else a) | |
161 | fun size s = subsetSize (s, fn _ => true) | |
162 | ||
163 | fun replace (s, f) = fold(s, empty, fn (x, s) => | |
164 | case f x | |
165 | of NONE => s | |
166 | | SOME x' => add (s, x')) | |
167 | fun map (s, f) = replace (s, fn x => SOME (f x)) | |
168 | fun subset (s, p) = replace (s, fn x => if p x then SOME x else NONE) | |
169 | fun partition (s, p) = let val yes = subset (s, p) | |
170 | in {yes = yes, no = difference (s, yes)} | |
171 | end | |
172 | ||
173 | fun fromList l = List.fold (l, empty, fn (x, s) => add (s, x)) | |
174 | fun toList s = fold (s, nil, op ::) | |
175 | fun layout s = List.layout Element.layout (toList s) | |
176 | ||
177 | val op + = union | |
178 | val op - = difference | |
179 | val op < = isSubset | |
180 | val op <= = isSubsetEq | |
181 | val op > = isSuperset | |
182 | val op >= = isSupersetEq | |
183 | ||
184 | fun power _ = Error.unimplemented "BitVectorSet.power" | |
185 | fun subsets _ = Error.unimplemented "BitVectorSet.subsets" | |
186 | end |