| 79074 |      1 | (*  Title:      Pure/General/bitset.ML
 | 
|  |      2 |     Author:     Makarius
 | 
|  |      3 | 
 | 
| 79080 |      4 | Compact representation of sets of integers.
 | 
| 79074 |      5 | *)
 | 
|  |      6 | 
 | 
|  |      7 | signature BITSET =
 | 
|  |      8 | sig
 | 
| 79080 |      9 |   type elem = int
 | 
| 79077 |     10 |   val make_elem: int * int -> elem  (*exception*)
 | 
|  |     11 |   val dest_elem: elem -> int * int
 | 
| 79074 |     12 |   type T
 | 
|  |     13 |   val empty: T
 | 
|  |     14 |   val build: (T -> T) -> T
 | 
|  |     15 |   val is_empty: T -> bool
 | 
| 79075 |     16 |   val fold: (elem -> 'a -> 'a) -> T -> 'a -> 'a
 | 
|  |     17 |   val fold_rev: (elem -> 'a -> 'a) -> T -> 'a -> 'a
 | 
|  |     18 |   val dest: T -> elem list
 | 
| 79079 |     19 |   val is_unique: T -> bool
 | 
| 79075 |     20 |   val min: T -> elem option
 | 
|  |     21 |   val max: T -> elem option
 | 
|  |     22 |   val get_first: (elem -> 'a option) -> T -> 'a option
 | 
|  |     23 |   val exists: (elem -> bool) -> T -> bool
 | 
|  |     24 |   val forall: (elem -> bool) -> T -> bool
 | 
|  |     25 |   val member: T -> elem -> bool
 | 
| 79074 |     26 |   val subset: T * T -> bool
 | 
|  |     27 |   val eq_set: T * T -> bool
 | 
| 79075 |     28 |   val insert: elem -> T -> T
 | 
|  |     29 |   val make: elem list -> T
 | 
| 79074 |     30 |   val merge: T * T -> T
 | 
|  |     31 |   val merges: T list -> T
 | 
| 79075 |     32 |   val remove: elem -> T -> T
 | 
| 79074 |     33 |   val subtract: T -> T -> T
 | 
| 79075 |     34 |   val restrict: (elem -> bool) -> T -> T
 | 
| 79074 |     35 |   val inter: T -> T -> T
 | 
|  |     36 |   val union: T -> T -> T
 | 
|  |     37 | end;
 | 
|  |     38 | 
 | 
|  |     39 | structure Bitset: BITSET =
 | 
|  |     40 | struct
 | 
|  |     41 | 
 | 
|  |     42 | (* bits and words *)
 | 
|  |     43 | 
 | 
|  |     44 | exception BAD of int;
 | 
|  |     45 | 
 | 
|  |     46 | val word_size = Word.wordSize;
 | 
|  |     47 | 
 | 
|  |     48 | val min_bit = 0;
 | 
|  |     49 | val max_bit = word_size - 1;
 | 
|  |     50 | fun check_bit n = min_bit <= n andalso n <= max_bit;
 | 
|  |     51 | 
 | 
|  |     52 | fun make_bit n = if check_bit n then Word.<< (0w1, Word.fromInt n) else raise BAD n;
 | 
|  |     53 | val mimimum_bit = make_bit min_bit;
 | 
|  |     54 | val maximum_bit = make_bit max_bit;
 | 
|  |     55 | 
 | 
|  |     56 | fun add_bits v w = Word.orb (v, w);
 | 
|  |     57 | fun del_bits v w = Word.andb (Word.notb v, w);
 | 
|  |     58 | fun incl_bits v w = add_bits v w = w;
 | 
|  |     59 | 
 | 
|  |     60 | fun fold_bits f w =
 | 
|  |     61 |   let
 | 
| 79080 |     62 |     fun app n b a = if incl_bits b w then f n a else a;
 | 
| 79074 |     63 |     fun bits n b a =
 | 
| 79080 |     64 |       if n = max_bit then app n b a
 | 
|  |     65 |       else bits (n + 1) (Word.<< (b, 0w1)) (app n b a);
 | 
| 79074 |     66 |   in bits min_bit mimimum_bit end;
 | 
|  |     67 | 
 | 
|  |     68 | fun fold_rev_bits f w =
 | 
|  |     69 |   let
 | 
| 79080 |     70 |     fun app n b a = if incl_bits b w then f n a else a;
 | 
| 79074 |     71 |     fun bits n b a =
 | 
| 79080 |     72 |       if n = min_bit then app n b a
 | 
|  |     73 |       else bits (n - 1) (Word.>> (b, 0w1)) (app n b a);
 | 
| 79074 |     74 |   in bits max_bit maximum_bit end;
 | 
|  |     75 | 
 | 
|  |     76 | 
 | 
|  |     77 | (* datatype *)
 | 
|  |     78 | 
 | 
| 79080 |     79 | type elem = int;
 | 
| 79075 |     80 | 
 | 
| 79077 |     81 | fun make_elem (m, n) : elem = if check_bit n then m * word_size + n else raise BAD n;
 | 
| 79075 |     82 | fun dest_elem (x: elem) = Integer.div_mod x word_size;
 | 
|  |     83 | 
 | 
| 79074 |     84 | datatype T = Bitset of word Inttab.table;
 | 
|  |     85 | 
 | 
| 79075 |     86 | 
 | 
|  |     87 | (* empty *)
 | 
|  |     88 | 
 | 
| 79074 |     89 | val empty = Bitset Inttab.empty;
 | 
|  |     90 | 
 | 
|  |     91 | fun build (f: T -> T) = f empty;
 | 
|  |     92 | 
 | 
|  |     93 | fun is_empty (Bitset t) = Inttab.is_empty t;
 | 
|  |     94 | 
 | 
|  |     95 | 
 | 
|  |     96 | (* fold combinators *)
 | 
|  |     97 | 
 | 
|  |     98 | fun fold_set f (Bitset t) =
 | 
|  |     99 |   Inttab.fold (fn (m, w) =>
 | 
| 79077 |    100 |     (if m < 0 then fold_rev_bits else fold_bits) (fn n => f (make_elem (m, n))) w) t;
 | 
| 79074 |    101 | 
 | 
|  |    102 | fun fold_rev_set f (Bitset t) =
 | 
|  |    103 |   Inttab.fold_rev (fn (m, w) =>
 | 
| 79077 |    104 |     (if m < 0 then fold_bits else fold_rev_bits) (fn n => f (make_elem (m, n))) w) t;
 | 
| 79074 |    105 | 
 | 
|  |    106 | val dest = Library.build o fold_rev_set cons;
 | 
|  |    107 | 
 | 
| 79079 |    108 | fun is_unique (set as Bitset t) =
 | 
|  |    109 |   is_empty set orelse
 | 
|  |    110 |   Inttab.size t = 1 andalso fold_set (fn _ => Integer.add 1) set 0 = 1;
 | 
|  |    111 | 
 | 
| 79074 |    112 | 
 | 
|  |    113 | (* min/max entries *)
 | 
|  |    114 | 
 | 
|  |    115 | fun min (Bitset t) =
 | 
|  |    116 |   Inttab.min t |> Option.map (fn (m, w) =>
 | 
| 79077 |    117 |     make_elem (m, fold_bits Integer.min w max_bit));
 | 
| 79074 |    118 | 
 | 
|  |    119 | fun max (Bitset t) =
 | 
|  |    120 |   Inttab.max t |> Option.map (fn (m, w) =>
 | 
| 79077 |    121 |     make_elem (m, fold_bits Integer.max w min_bit));
 | 
| 79074 |    122 | 
 | 
|  |    123 | 
 | 
|  |    124 | (* linear search *)
 | 
|  |    125 | 
 | 
|  |    126 | fun get_first f set =
 | 
|  |    127 |   let exception FOUND of 'a in
 | 
|  |    128 |     fold_set (fn x => fn a => (case f x of SOME b => raise FOUND b | NONE => a)) set NONE
 | 
|  |    129 |       handle FOUND b => SOME b
 | 
|  |    130 |   end;
 | 
|  |    131 | 
 | 
|  |    132 | fun exists pred = is_some o get_first (fn x => if pred x then SOME x else NONE);
 | 
|  |    133 | fun forall pred = not o exists (not o pred);
 | 
|  |    134 | 
 | 
|  |    135 | 
 | 
|  |    136 | (* member *)
 | 
|  |    137 | 
 | 
|  |    138 | fun member (Bitset t) x =
 | 
| 79075 |    139 |   let val (m, n) = dest_elem x in
 | 
| 79074 |    140 |     (case Inttab.lookup t m of
 | 
|  |    141 |       NONE => false
 | 
|  |    142 |     | SOME w => incl_bits (make_bit n) w)
 | 
|  |    143 |   end;
 | 
|  |    144 | 
 | 
|  |    145 | 
 | 
|  |    146 | (* subset *)
 | 
|  |    147 | 
 | 
|  |    148 | fun subset (Bitset t1, Bitset t2) =
 | 
|  |    149 |   pointer_eq (t1, t2) orelse
 | 
|  |    150 |     Inttab.size t1 <= Inttab.size t2 andalso
 | 
|  |    151 |     t1 |> Inttab.forall (fn (m, w1) =>
 | 
|  |    152 |       (case Inttab.lookup t2 m of
 | 
|  |    153 |         NONE => false
 | 
|  |    154 |       | SOME w2 => incl_bits w1 w2));
 | 
|  |    155 | 
 | 
|  |    156 | fun eq_set (set1, set2) =
 | 
|  |    157 |   pointer_eq (set1, set2) orelse subset (set1, set2) andalso subset (set2, set1);
 | 
|  |    158 | 
 | 
|  |    159 | 
 | 
|  |    160 | (* insert *)
 | 
|  |    161 | 
 | 
|  |    162 | fun insert x (Bitset t) =
 | 
| 79075 |    163 |   let val (m, n) = dest_elem x
 | 
| 79074 |    164 |   in Bitset (Inttab.map_default (m, 0w0) (add_bits (make_bit n)) t) end;
 | 
|  |    165 | 
 | 
|  |    166 | fun make xs = build (fold insert xs);
 | 
|  |    167 | 
 | 
|  |    168 | 
 | 
|  |    169 | (* merge *)
 | 
|  |    170 | 
 | 
|  |    171 | fun join_bits (w1, w2) =
 | 
|  |    172 |   let val w = add_bits w2 w1
 | 
|  |    173 |   in if w = w1 then raise Inttab.SAME else w end;
 | 
|  |    174 | 
 | 
|  |    175 | fun merge (set1 as Bitset t1, set2 as Bitset t2) =
 | 
|  |    176 |   if pointer_eq (set1, set2) then set1
 | 
|  |    177 |   else if is_empty set1 then set2
 | 
|  |    178 |   else if is_empty set2 then set1
 | 
|  |    179 |   else Bitset (Inttab.join (K join_bits) (t1, t2));
 | 
|  |    180 | 
 | 
|  |    181 | fun merges sets = Library.foldl merge (empty, sets);
 | 
|  |    182 | 
 | 
|  |    183 | 
 | 
|  |    184 | (* remove *)
 | 
|  |    185 | 
 | 
|  |    186 | fun remove x (set as Bitset t) =
 | 
| 79075 |    187 |   let val (m, n) = dest_elem x in
 | 
| 79074 |    188 |     (case Inttab.lookup t m of
 | 
|  |    189 |       NONE => set
 | 
|  |    190 |     | SOME w =>
 | 
|  |    191 |         let val w' = del_bits (make_bit n) w in
 | 
|  |    192 |           if w = w' then set
 | 
|  |    193 |           else if w' = 0w0 then Bitset (Inttab.delete m t)
 | 
|  |    194 |           else Bitset (Inttab.update (m, w') t)
 | 
|  |    195 |         end)
 | 
|  |    196 |   end;
 | 
|  |    197 | 
 | 
|  |    198 | val subtract = fold_set remove;
 | 
|  |    199 | 
 | 
|  |    200 | 
 | 
|  |    201 | (* conventional set operations *)
 | 
|  |    202 | 
 | 
|  |    203 | fun restrict pred set =
 | 
|  |    204 |   fold_set (fn x => not (pred x) ? remove x) set set;
 | 
|  |    205 | 
 | 
|  |    206 | fun inter set1 set2 =
 | 
|  |    207 |   if pointer_eq (set1, set2) then set1
 | 
|  |    208 |   else if is_empty set1 orelse is_empty set2 then empty
 | 
|  |    209 |   else restrict (member set1) set2;
 | 
|  |    210 | 
 | 
|  |    211 | fun union set1 set2 = merge (set2, set1);
 | 
|  |    212 | 
 | 
|  |    213 | 
 | 
|  |    214 | (* ML pretty-printing *)
 | 
|  |    215 | 
 | 
|  |    216 | val _ =
 | 
|  |    217 |   ML_system_pp (fn depth => fn _ => fn set =>
 | 
|  |    218 |     ML_Pretty.to_polyml
 | 
|  |    219 |       (ML_Pretty.enum "," "{" "}" (ML_Pretty.from_polyml o ML_system_pretty) (dest set, depth)));
 | 
|  |    220 | 
 | 
|  |    221 | 
 | 
|  |    222 | (*final declarations of this structure!*)
 | 
|  |    223 | val fold = fold_set;
 | 
|  |    224 | val fold_rev = fold_rev_set;
 | 
|  |    225 | 
 | 
|  |    226 | end;
 |