| author | wenzelm |
| Sun, 10 Dec 2023 12:54:31 +0100 | |
| changeset 79230 | f3e7822deb1c |
| parent 79163 | 9ddcaca41ed2 |
| child 79249 | 718798653cf1 |
| permissions | -rw-r--r-- |
| 6118 | 1 |
(* Title: Pure/General/table.ML |
| 15014 | 2 |
Author: Markus Wenzel and Stefan Berghofer, TU Muenchen |
| 5015 | 3 |
|
| 16342 | 4 |
Generic tables. Efficient purely functional implementation using |
5 |
balanced 2-3 trees. |
|
| 5015 | 6 |
*) |
7 |
||
8 |
signature KEY = |
|
9 |
sig |
|
10 |
type key |
|
| 70586 | 11 |
val ord: key ord |
| 5015 | 12 |
end; |
13 |
||
14 |
signature TABLE = |
|
15 |
sig |
|
| 77731 | 16 |
structure Key: KEY |
| 5015 | 17 |
type key |
18 |
type 'a table |
|
19 |
exception DUP of key |
|
| 19031 | 20 |
exception SAME |
| 15014 | 21 |
exception UNDEF of key |
|
77780
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
22 |
val size: 'a table -> int |
| 5015 | 23 |
val empty: 'a table |
| 74232 | 24 |
val build: ('a table -> 'a table) -> 'a table
|
| 5015 | 25 |
val is_empty: 'a table -> bool |
| 39020 | 26 |
val map: (key -> 'a -> 'b) -> 'a table -> 'b table |
| 16446 | 27 |
val fold: (key * 'b -> 'a -> 'a) -> 'b table -> 'a -> 'a |
| 28334 | 28 |
val fold_rev: (key * 'b -> 'a -> 'a) -> 'b table -> 'a -> 'a |
| 5015 | 29 |
val dest: 'a table -> (key * 'a) list |
| 5681 | 30 |
val keys: 'a table -> key list |
| 52049 | 31 |
val min: 'a table -> (key * 'a) option |
32 |
val max: 'a table -> (key * 'a) option |
|
| 27508 | 33 |
val exists: (key * 'a -> bool) -> 'a table -> bool |
34 |
val forall: (key * 'a -> bool) -> 'a table -> bool |
|
| 74227 | 35 |
val get_first: (key * 'a -> 'b option) -> 'a table -> 'b option |
|
43792
d5803c3d537a
Table.lookup_key and Graph.get_entry allow to retrieve the original key, which is not necessarily identical to the given one;
wenzelm
parents:
39020
diff
changeset
|
36 |
val lookup_key: 'a table -> key -> (key * 'a) option |
| 31616 | 37 |
val lookup: 'a table -> key -> 'a option |
| 16887 | 38 |
val defined: 'a table -> key -> bool |
| 31209 | 39 |
val update: key * 'a -> 'a table -> 'a table |
40 |
val update_new: key * 'a -> 'a table -> 'a table (*exception DUP*) |
|
| 17179 | 41 |
val default: key * 'a -> 'a table -> 'a table |
| 56051 | 42 |
val map_entry: key -> ('a -> 'a) (*exception SAME*) -> 'a table -> 'a table
|
| 31209 | 43 |
val map_default: key * 'a -> ('a -> 'a) -> 'a table -> 'a table
|
|
23655
d2d1138e0ddc
replaced exception TableFun/GraphFun.DUPS by TableFun/GraphFun.DUP;
wenzelm
parents:
21065
diff
changeset
|
44 |
val make: (key * 'a) list -> 'a table (*exception DUP*) |
| 56051 | 45 |
val join: (key -> 'a * 'a -> 'a) (*exception SAME*) -> |
|
23655
d2d1138e0ddc
replaced exception TableFun/GraphFun.DUPS by TableFun/GraphFun.DUP;
wenzelm
parents:
21065
diff
changeset
|
46 |
'a table * 'a table -> 'a table (*exception DUP*) |
|
d2d1138e0ddc
replaced exception TableFun/GraphFun.DUPS by TableFun/GraphFun.DUP;
wenzelm
parents:
21065
diff
changeset
|
47 |
val merge: ('a * 'a -> bool) -> 'a table * 'a table -> 'a table (*exception DUP*)
|
| 77822 | 48 |
val joins: (key -> 'a * 'a -> 'a) (*exception SAME*) -> |
49 |
'a table list -> 'a table (*exception DUP*) |
|
50 |
val merges: ('a * 'a -> bool) -> 'a table list -> 'a table (*exception DUP*)
|
|
| 15665 | 51 |
val delete: key -> 'a table -> 'a table (*exception UNDEF*) |
| 15761 | 52 |
val delete_safe: key -> 'a table -> 'a table |
| 16466 | 53 |
val member: ('b * 'a -> bool) -> 'a table -> key * 'b -> bool
|
| 15761 | 54 |
val insert: ('a * 'a -> bool) -> key * 'a -> 'a table -> 'a table (*exception DUP*)
|
| 16139 | 55 |
val remove: ('b * 'a -> bool) -> key * 'b -> 'a table -> 'a table
|
| 18946 | 56 |
val lookup_list: 'a list table -> key -> 'a list |
| 31209 | 57 |
val cons_list: key * 'a -> 'a list table -> 'a list table |
| 19506 | 58 |
val insert_list: ('a * 'a -> bool) -> key * 'a -> 'a list table -> 'a list table
|
| 77981 | 59 |
val update_list: ('a * 'a -> bool) -> key * 'a -> 'a list table -> 'a list table
|
| 18946 | 60 |
val remove_list: ('b * 'a -> bool) -> key * 'b -> 'a list table -> 'a list table
|
61 |
val make_list: (key * 'a) list -> 'a list table |
|
62 |
val dest_list: 'a list table -> (key * 'a) list |
|
| 33162 | 63 |
val merge_list: ('a * 'a -> bool) -> 'a list table * 'a list table -> 'a list table
|
| 50234 | 64 |
type set = unit table |
| 63511 | 65 |
val insert_set: key -> set -> set |
| 67529 | 66 |
val remove_set: key -> set -> set |
|
59012
f4e9bd04e1d5
clarified Table.make_set: duplicate arguments are allowed, like Table.make_list or Scala Set() formation;
wenzelm
parents:
56051
diff
changeset
|
67 |
val make_set: key list -> set |
| 79163 | 68 |
val unsynchronized_cache: (key -> 'a) -> key -> 'a |
| 5015 | 69 |
end; |
70 |
||
|
31971
8c1b845ed105
renamed functor TableFun to Table, and GraphFun to Graph;
wenzelm
parents:
31621
diff
changeset
|
71 |
functor Table(Key: KEY): TABLE = |
| 5015 | 72 |
struct |
73 |
||
| 77733 | 74 |
(* keys *) |
75 |
||
| 77731 | 76 |
structure Key = Key; |
77 |
type key = Key.key; |
|
| 5015 | 78 |
|
| 77733 | 79 |
exception DUP of key; |
80 |
||
| 5015 | 81 |
|
| 77731 | 82 |
(* datatype *) |
| 5015 | 83 |
|
84 |
datatype 'a table = |
|
85 |
Empty | |
|
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
86 |
Leaf1 of key * 'a | |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
87 |
Leaf2 of (key * 'a) * (key * 'a) | |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
88 |
Leaf3 of (key * 'a) * (key * 'a) * (key * 'a) | |
| 5015 | 89 |
Branch2 of 'a table * (key * 'a) * 'a table | |
| 77800 | 90 |
Branch3 of 'a table * (key * 'a) * 'a table * (key * 'a) * 'a table | |
91 |
Size of int * 'a table; |
|
| 5015 | 92 |
|
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
93 |
fun make2 (Empty, e, Empty) = Leaf1 e |
|
77740
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
94 |
| make2 (Branch2 (Empty, e1, Empty), e2, right) = make2 (Leaf1 e1, e2, right) |
|
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
95 |
| make2 (left, e1, Branch2 (Empty, e2, Empty)) = make2 (left, e1, Leaf1 e2) |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
96 |
| make2 (Branch3 (Empty, e1, Empty, e2, Empty), e3, right) = make2 (Leaf2 (e1, e2), e3, right) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
97 |
| make2 (left, e1, Branch3 (Empty, e2, Empty, e3, Empty)) = make2 (left, e1, Leaf2 (e2, e3)) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
98 |
| make2 (Leaf1 e1, e2, Empty) = Leaf2 (e1, e2) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
99 |
| make2 (Empty, e1, Leaf1 e2) = Leaf2 (e1, e2) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
100 |
| make2 (Leaf1 e1, e2, Leaf1 e3) = Leaf3 (e1, e2, e3) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
101 |
| make2 (Leaf2 (e1, e2), e3, Empty) = Leaf3 (e1, e2, e3) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
102 |
| make2 (Empty, e1, Leaf2 (e2, e3)) = Leaf3 (e1, e2, e3) |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
103 |
| make2 arg = Branch2 arg; |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
104 |
|
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
105 |
fun make3 (Empty, e1, Empty, e2, Empty) = Leaf2 (e1, e2) |
|
77740
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
106 |
| make3 (Branch2 (Empty, e1, Empty), e2, mid, e3, right) = make3 (Leaf1 e1, e2, mid, e3, right) |
|
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
107 |
| make3 (left, e1, Branch2 (Empty, e2, Empty), e3, right) = make3 (left, e1, Leaf1 e2, e3, right) |
|
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
108 |
| make3 (left, e1, mid, e2, Branch2 (Empty, e3, Empty)) = make3 (left, e1, mid, e2, Leaf1 e3) |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
109 |
| make3 (Leaf1 e1, e2, Empty, e3, Empty) = Leaf3 (e1, e2, e3) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
110 |
| make3 (Empty, e1, Leaf1 e2, e3, Empty) = Leaf3 (e1, e2, e3) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
111 |
| make3 (Empty, e1, Empty, e2, Leaf1 e3) = Leaf3 (e1, e2, e3) |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
112 |
| make3 arg = Branch3 arg; |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
113 |
|
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
114 |
fun unmake (Leaf1 e) = Branch2 (Empty, e, Empty) |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
115 |
| unmake (Leaf2 (e1, e2)) = Branch3 (Empty, e1, Empty, e2, Empty) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
116 |
| unmake (Leaf3 (e1, e2, e3)) = Branch2 (Branch2 (Empty, e1, Empty), e2, Branch2 (Empty, e3, Empty)) |
| 77800 | 117 |
| unmake (Size (_, arg)) = arg |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
118 |
| unmake arg = arg; |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
119 |
|
| 5015 | 120 |
|
|
77780
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
121 |
(* size *) |
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
122 |
|
| 77800 | 123 |
(*literal copy from set.ML*) |
|
77780
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
124 |
local |
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
125 |
fun count Empty n = n |
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
126 |
| count (Leaf1 _) n = n + 1 |
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
127 |
| count (Leaf2 _) n = n + 2 |
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
128 |
| count (Leaf3 _) n = n + 3 |
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
129 |
| count (Branch2 (left, _, right)) n = count right (count left (n + 1)) |
| 77800 | 130 |
| count (Branch3 (left, _, mid, _, right)) n = count right (count mid (count left (n + 2))) |
131 |
| count (Size (m, _)) n = m + n; |
|
|
77802
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
132 |
|
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
133 |
fun box (Branch2 _) = 1 |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
134 |
| box (Branch3 _) = 1 |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
135 |
| box _ = 0; |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
136 |
|
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
137 |
fun bound arg b = |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
138 |
if b > 0 then |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
139 |
(case arg of |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
140 |
Branch2 (left, _, right) => |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
141 |
bound right (bound left (b - box left - box right)) |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
142 |
| Branch3 (left, _, mid, _, right) => |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
143 |
bound right (bound mid (bound left (b - box left - box mid - box right))) |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
144 |
| _ => b) |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
145 |
else b; |
|
77780
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
146 |
in |
|
77802
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
147 |
fun size arg = count arg 0; |
|
25c114e2528e
performance tuning: make_size accounts for boxes, i.e. pointer derefs required in "count";
wenzelm
parents:
77800
diff
changeset
|
148 |
fun make_size m arg = if bound arg 3 <= 0 then Size (m, arg) else arg; |
|
77780
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
149 |
end; |
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
150 |
|
|
97febdb6ee58
clarified signature: more uniform Table() vs. Set();
wenzelm
parents:
77768
diff
changeset
|
151 |
|
| 77743 | 152 |
(* empty *) |
| 5681 | 153 |
|
| 5015 | 154 |
val empty = Empty; |
155 |
||
| 74232 | 156 |
fun build (f: 'a table -> 'a table) = f empty; |
157 |
||
| 77800 | 158 |
(*literal copy from set.ML*) |
| 5015 | 159 |
fun is_empty Empty = true |
| 77800 | 160 |
| is_empty (Size (_, arg)) = is_empty arg |
| 5015 | 161 |
| is_empty _ = false; |
162 |
||
| 5681 | 163 |
|
164 |
(* map and fold combinators *) |
|
165 |
||
| 16657 | 166 |
fun map_table f = |
167 |
let |
|
| 79094 | 168 |
fun apply (k, x) = (k, f k x); |
169 |
||
| 16657 | 170 |
fun map Empty = Empty |
| 79094 | 171 |
| map (Leaf1 e) = Leaf1 (apply e) |
172 |
| map (Leaf2 (e1, e2)) = Leaf2 (apply e1, apply e2) |
|
173 |
| map (Leaf3 (e1, e2, e3)) = Leaf3 (apply e1, apply e2, apply e3) |
|
174 |
| map (Branch2 (left, e, right)) = |
|
175 |
Branch2 (map left, apply e, map right) |
|
176 |
| map (Branch3 (left, e1, mid, e2, right)) = |
|
177 |
Branch3 (map left, apply e1, map mid, apply e2, map right) |
|
| 77800 | 178 |
| map (Size (m, arg)) = Size (m, map arg); |
| 16657 | 179 |
in map end; |
| 5681 | 180 |
|
| 16657 | 181 |
fun fold_table f = |
182 |
let |
|
| 77813 | 183 |
fun fold Empty a = a |
184 |
| fold (Leaf1 e) a = f e a |
|
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
185 |
| fold (Leaf2 (e1, e2)) a = f e2 (f e1 a) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
186 |
| fold (Leaf3 (e1, e2, e3)) a = f e3 (f e2 (f e1 a)) |
| 77813 | 187 |
| fold (Branch2 (left, e, right)) a = |
188 |
fold right (f e (fold left a)) |
|
189 |
| fold (Branch3 (left, e1, mid, e2, right)) a = |
|
190 |
fold right (f e2 (fold mid (f e1 (fold left a)))) |
|
191 |
| fold (Size (_, arg)) a = fold arg a; |
|
| 16657 | 192 |
in fold end; |
| 5681 | 193 |
|
| 28334 | 194 |
fun fold_rev_table f = |
195 |
let |
|
| 77813 | 196 |
fun fold_rev Empty a = a |
197 |
| fold_rev (Leaf1 e) a = f e a |
|
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
198 |
| fold_rev (Leaf2 (e1, e2)) a = f e1 (f e2 a) |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
199 |
| fold_rev (Leaf3 (e1, e2, e3)) a = f e1 (f e2 (f e3 a)) |
| 77813 | 200 |
| fold_rev (Branch2 (left, e, right)) a = |
201 |
fold_rev left (f e (fold_rev right a)) |
|
202 |
| fold_rev (Branch3 (left, e1, mid, e2, right)) a = |
|
203 |
fold_rev left (f e1 (fold_rev mid (f e2 (fold_rev right a)))) |
|
204 |
| fold_rev (Size (_, arg)) a = fold_rev arg a; |
|
| 77732 | 205 |
in fold_rev end; |
| 28334 | 206 |
|
| 77768 | 207 |
fun dest tab = Library.build (fold_rev_table cons tab); |
208 |
fun keys tab = Library.build (fold_rev_table (cons o #1) tab); |
|
| 16192 | 209 |
|
| 27508 | 210 |
|
| 52049 | 211 |
(* min/max entries *) |
| 5015 | 212 |
|
| 52049 | 213 |
fun min Empty = NONE |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
214 |
| min (Leaf1 e) = SOME e |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
215 |
| min (Leaf2 (e, _)) = SOME e |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
216 |
| min (Leaf3 (e, _, _)) = SOME e |
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
217 |
| min (Branch2 (Empty, e, _)) = SOME e |
|
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
218 |
| min (Branch3 (Empty, e, _, _, _)) = SOME e |
| 52049 | 219 |
| min (Branch2 (left, _, _)) = min left |
| 77800 | 220 |
| min (Branch3 (left, _, _, _, _)) = min left |
221 |
| min (Size (_, arg)) = min arg; |
|
| 8409 | 222 |
|
| 52049 | 223 |
fun max Empty = NONE |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
224 |
| max (Leaf1 e) = SOME e |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
225 |
| max (Leaf2 (_, e)) = SOME e |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
226 |
| max (Leaf3 (_, _, e)) = SOME e |
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
227 |
| max (Branch2 (_, e, Empty)) = SOME e |
|
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
228 |
| max (Branch3 (_, _, _, e, Empty)) = SOME e |
| 52049 | 229 |
| max (Branch2 (_, _, right)) = max right |
| 77800 | 230 |
| max (Branch3 (_, _, _, _, right)) = max right |
231 |
| max (Size (_, arg)) = max arg; |
|
| 15665 | 232 |
|
| 5015 | 233 |
|
| 74227 | 234 |
(* exists and forall *) |
235 |
||
236 |
fun exists pred = |
|
237 |
let |
|
238 |
fun ex Empty = false |
|
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
239 |
| ex (Leaf1 e) = pred e |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
240 |
| ex (Leaf2 (e1, e2)) = pred e1 orelse pred e2 |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
241 |
| ex (Leaf3 (e1, e2, e3)) = pred e1 orelse pred e2 orelse pred e3 |
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
242 |
| ex (Branch2 (left, e, right)) = |
|
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
243 |
ex left orelse pred e orelse ex right |
|
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
244 |
| ex (Branch3 (left, e1, mid, e2, right)) = |
| 77800 | 245 |
ex left orelse pred e1 orelse ex mid orelse pred e2 orelse ex right |
246 |
| ex (Size (_, arg)) = ex arg; |
|
| 74227 | 247 |
in ex end; |
248 |
||
249 |
fun forall pred = not o exists (not o pred); |
|
250 |
||
251 |
||
| 31616 | 252 |
(* get_first *) |
253 |
||
|
35012
c3e3ac3ca091
removed unused "boundary" of Table/Graph.get_first;
wenzelm
parents:
33162
diff
changeset
|
254 |
fun get_first f = |
| 31616 | 255 |
let |
|
35012
c3e3ac3ca091
removed unused "boundary" of Table/Graph.get_first;
wenzelm
parents:
33162
diff
changeset
|
256 |
fun get Empty = NONE |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
257 |
| get (Leaf1 e) = f e |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
258 |
| get (Leaf2 (e1, e2)) = |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
259 |
(case f e1 of |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
260 |
NONE => f e2 |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
261 |
| some => some) |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
262 |
| get (Leaf3 (e1, e2, e3)) = |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
263 |
(case f e1 of |
|
77740
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
264 |
NONE => |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
265 |
(case f e2 of |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
266 |
NONE => f e3 |
|
77740
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
267 |
| some => some) |
|
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
268 |
| some => some) |
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
269 |
| get (Branch2 (left, e, right)) = |
|
35012
c3e3ac3ca091
removed unused "boundary" of Table/Graph.get_first;
wenzelm
parents:
33162
diff
changeset
|
270 |
(case get left of |
| 31616 | 271 |
NONE => |
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
272 |
(case f e of |
| 31616 | 273 |
NONE => get right |
274 |
| some => some) |
|
275 |
| some => some) |
|
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
276 |
| get (Branch3 (left, e1, mid, e2, right)) = |
|
35012
c3e3ac3ca091
removed unused "boundary" of Table/Graph.get_first;
wenzelm
parents:
33162
diff
changeset
|
277 |
(case get left of |
| 31616 | 278 |
NONE => |
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
279 |
(case f e1 of |
| 31616 | 280 |
NONE => |
|
35012
c3e3ac3ca091
removed unused "boundary" of Table/Graph.get_first;
wenzelm
parents:
33162
diff
changeset
|
281 |
(case get mid of |
| 31616 | 282 |
NONE => |
|
77727
b98edf66ca96
tuned names: "e" means "entry" in table.ML and "elem" in set.ML;
wenzelm
parents:
77721
diff
changeset
|
283 |
(case f e2 of |
| 31616 | 284 |
NONE => get right |
285 |
| some => some) |
|
286 |
| some => some) |
|
287 |
| some => some) |
|
| 77800 | 288 |
| some => some) |
289 |
| get (Size (_, arg)) = get arg; |
|
|
35012
c3e3ac3ca091
removed unused "boundary" of Table/Graph.get_first;
wenzelm
parents:
33162
diff
changeset
|
290 |
in get end; |
| 31616 | 291 |
|
292 |
||
| 79093 | 293 |
(* retrieve *) |
| 77742 | 294 |
|
| 79093 | 295 |
fun retrieve {result, no_result} tab (key: key) =
|
| 19031 | 296 |
let |
| 79093 | 297 |
fun compare (k, _) = Key.ord (key, k) |
298 |
fun result_equal e = if is_equal (compare e) then result e else no_result; |
|
| 77742 | 299 |
|
| 79093 | 300 |
fun find Empty = no_result |
301 |
| find (Leaf1 e) = result_equal e |
|
302 |
| find (Leaf2 (e1, e2)) = |
|
303 |
(case compare e1 of |
|
304 |
LESS => no_result |
|
305 |
| EQUAL => result e1 |
|
306 |
| GREATER => result_equal e2) |
|
307 |
| find (Leaf3 (e1, e2, e3)) = |
|
308 |
(case compare e2 of |
|
309 |
LESS => result_equal e1 |
|
310 |
| EQUAL => result e2 |
|
311 |
| GREATER => result_equal e3) |
|
312 |
| find (Branch2 (left, e, right)) = |
|
313 |
(case compare e of |
|
314 |
LESS => find left |
|
315 |
| EQUAL => result e |
|
316 |
| GREATER => find right) |
|
317 |
| find (Branch3 (left, e1, mid, e2, right)) = |
|
318 |
(case compare e1 of |
|
319 |
LESS => find left |
|
320 |
| EQUAL => result e1 |
|
| 19031 | 321 |
| GREATER => |
| 79093 | 322 |
(case compare e2 of |
323 |
LESS => find mid |
|
324 |
| EQUAL => result e2 |
|
325 |
| GREATER => find right)) |
|
326 |
| find (Size (_, arg)) = find arg; |
|
327 |
in find tab end; |
|
| 5015 | 328 |
|
| 79093 | 329 |
fun lookup tab key = retrieve {result = SOME o #2, no_result = NONE} tab key;
|
330 |
fun lookup_key tab key = retrieve {result = SOME, no_result = NONE} tab key;
|
|
331 |
fun defined tab key = retrieve {result = K true, no_result = false} tab key;
|
|
| 16887 | 332 |
|
| 5015 | 333 |
|
| 19031 | 334 |
(* modify *) |
| 5015 | 335 |
|
336 |
datatype 'a growth = |
|
337 |
Stay of 'a table | |
|
338 |
Sprout of 'a table * (key * 'a) * 'a table; |
|
339 |
||
| 15761 | 340 |
exception SAME; |
341 |
||
| 15665 | 342 |
fun modify key f tab = |
343 |
let |
|
| 79093 | 344 |
fun compare (k, _) = Key.ord (key, k) |
| 77742 | 345 |
|
| 77800 | 346 |
val inc = Unsynchronized.ref 0; |
| 79093 | 347 |
fun insert (k: key) = (k, f NONE) before ignore (Unsynchronized.inc inc); |
348 |
fun update (k: key, x) = (k, f (SOME x)); |
|
| 77800 | 349 |
|
| 79093 | 350 |
fun modfy Empty = Sprout (Empty, (insert key), Empty) |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
351 |
| modfy (t as Leaf1 _) = modfy (unmake t) |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
352 |
| modfy (t as Leaf2 _) = modfy (unmake t) |
|
77740
19c539f5d4d3
more compact data: approx. 0.85 .. 1.10 of plain list size;
wenzelm
parents:
77739
diff
changeset
|
353 |
| modfy (t as Leaf3 _) = modfy (unmake t) |
| 79093 | 354 |
| modfy (Branch2 (left, e, right)) = |
355 |
(case compare e of |
|
| 15665 | 356 |
LESS => |
357 |
(case modfy left of |
|
| 79093 | 358 |
Stay left' => Stay (make2 (left', e, right)) |
359 |
| Sprout (left1, e', left2) => Stay (make3 (left1, e', left2, e, right))) |
|
360 |
| EQUAL => Stay (make2 (left, update e, right)) |
|
| 15665 | 361 |
| GREATER => |
362 |
(case modfy right of |
|
| 79093 | 363 |
Stay right' => Stay (make2 (left, e, right')) |
364 |
| Sprout (right1, e', right2) => |
|
365 |
Stay (make3 (left, e, right1, e', right2)))) |
|
366 |
| modfy (Branch3 (left, e1, mid, e2, right)) = |
|
367 |
(case compare e1 of |
|
| 5015 | 368 |
LESS => |
| 15665 | 369 |
(case modfy left of |
| 79093 | 370 |
Stay left' => Stay (make3 (left', e1, mid, e2, right)) |
371 |
| Sprout (left1, e', left2) => |
|
372 |
Sprout (make2 (left1, e', left2), e1, make2 (mid, e2, right))) |
|
373 |
| EQUAL => Stay (make3 (left, update e1, mid, e2, right)) |
|
| 5015 | 374 |
| GREATER => |
| 79093 | 375 |
(case compare e2 of |
| 15665 | 376 |
LESS => |
377 |
(case modfy mid of |
|
| 79093 | 378 |
Stay mid' => Stay (make3 (left, e1, mid', e2, right)) |
379 |
| Sprout (mid1, e', mid2) => |
|
380 |
Sprout (make2 (left, e1, mid1), e', make2 (mid2, e2, right))) |
|
381 |
| EQUAL => Stay (make3 (left, e1, mid, update e2, right)) |
|
| 15665 | 382 |
| GREATER => |
383 |
(case modfy right of |
|
| 79093 | 384 |
Stay right' => Stay (make3 (left, e1, mid, e2, right')) |
| 15665 | 385 |
| Sprout (right1, q, right2) => |
| 79093 | 386 |
Sprout (make2 (left, e1, mid), e2, make2 (right1, q, right2))))) |
| 77800 | 387 |
| modfy (Size (_, arg)) = modfy arg; |
| 5015 | 388 |
|
| 77800 | 389 |
val tab' = |
|
77882
bb7238e7d2d9
minor performance tuning: avoid excessive (de)constructions for base cases;
wenzelm
parents:
77881
diff
changeset
|
390 |
(case tab of |
| 79093 | 391 |
Empty => Leaf1 (insert key) |
392 |
| Leaf1 e => |
|
393 |
(case compare e of |
|
394 |
LESS => Leaf2 (insert key, e) |
|
395 |
| EQUAL => Leaf1 (update e) |
|
396 |
| GREATER => Leaf2 (e, insert key)) |
|
397 |
| Leaf2 (e1, e2) => |
|
398 |
(case compare e1 of |
|
399 |
LESS => Leaf3 (insert key, e1, e2) |
|
400 |
| EQUAL => Leaf2 (update e1, e2) |
|
|
77882
bb7238e7d2d9
minor performance tuning: avoid excessive (de)constructions for base cases;
wenzelm
parents:
77881
diff
changeset
|
401 |
| GREATER => |
| 79093 | 402 |
(case compare e2 of |
403 |
LESS => Leaf3 (e1, insert key, e2) |
|
404 |
| EQUAL => Leaf2 (e1, update e2) |
|
405 |
| GREATER => Leaf3 (e1, e2, insert key))) |
|
|
77882
bb7238e7d2d9
minor performance tuning: avoid excessive (de)constructions for base cases;
wenzelm
parents:
77881
diff
changeset
|
406 |
| _ => |
|
bb7238e7d2d9
minor performance tuning: avoid excessive (de)constructions for base cases;
wenzelm
parents:
77881
diff
changeset
|
407 |
(case modfy tab of |
|
bb7238e7d2d9
minor performance tuning: avoid excessive (de)constructions for base cases;
wenzelm
parents:
77881
diff
changeset
|
408 |
Stay tab' => tab' |
|
bb7238e7d2d9
minor performance tuning: avoid excessive (de)constructions for base cases;
wenzelm
parents:
77881
diff
changeset
|
409 |
| Sprout br => make2 br)); |
| 15665 | 410 |
in |
| 77800 | 411 |
make_size (size tab + !inc) tab' |
412 |
end handle SAME => tab; |
|
| 5015 | 413 |
|
| 17412 | 414 |
fun update (key, x) tab = modify key (fn _ => x) tab; |
415 |
fun update_new (key, x) tab = modify key (fn NONE => x | SOME _ => raise DUP key) tab; |
|
| 17709 | 416 |
fun default (key, x) tab = modify key (fn NONE => x | SOME _ => raise SAME) tab; |
| 15761 | 417 |
fun map_entry key f = modify key (fn NONE => raise SAME | SOME x => f x); |
| 27783 | 418 |
fun map_default (key, x) f = modify key (fn NONE => f x | SOME y => f y); |
| 5015 | 419 |
|
420 |
||
| 15014 | 421 |
(* delete *) |
422 |
||
| 15665 | 423 |
exception UNDEF of key; |
424 |
||
425 |
local |
|
426 |
||
| 77735 | 427 |
fun compare NONE _ = LESS |
| 15665 | 428 |
| compare (SOME k1) (k2, _) = Key.ord (k1, k2); |
| 15014 | 429 |
|
| 77737 | 430 |
fun if_equal ord x y = if is_equal ord then x else y; |
| 15014 | 431 |
|
| 15531 | 432 |
fun del (SOME k) Empty = raise UNDEF k |
| 77735 | 433 |
| del NONE Empty = raise Match |
| 79094 | 434 |
| del NONE (Leaf1 e) = (e, (true, Empty)) |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
435 |
| del NONE (Leaf2 (e1, e2)) = (e1, (false, Leaf1 e2)) |
| 79094 | 436 |
| del k (Leaf1 e) = |
437 |
(case compare k e of |
|
438 |
EQUAL => (e, (true, Empty)) |
|
| 77721 | 439 |
| _ => raise UNDEF (the k)) |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
440 |
| del k (Leaf2 (e1, e2)) = |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
441 |
(case compare k e1 of |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
442 |
EQUAL => (e1, (false, Leaf1 e2)) |
| 77721 | 443 |
| _ => |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
444 |
(case compare k e2 of |
|
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
445 |
EQUAL => (e2, (false, Leaf1 e1)) |
| 77721 | 446 |
| _ => raise UNDEF (the k))) |
|
79092
06176f4e2e70
slightly more compact heap: better sharing of persistent tuples;
wenzelm
parents:
77981
diff
changeset
|
447 |
| del k (Leaf3 (e1, e2, e3)) = del k (Branch2 (Leaf1 e1, e2, Leaf1 e3)) |
| 77721 | 448 |
| del k (Branch2 (l, p, r)) = |
449 |
(case compare k p of |
|
450 |
LESS => |
|
451 |
(case del k l of |
|
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
452 |
(p', (false, l')) => (p', (false, make2 (l', p, r))) |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
453 |
| (p', (true, l')) => (p', case unmake r of |
| 77721 | 454 |
Branch2 (rl, rp, rr) => |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
455 |
(true, make3 (l', p, rl, rp, rr)) |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
456 |
| Branch3 (rl, rp, rm, rq, rr) => (false, make2 |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
457 |
(make2 (l', p, rl), rp, make2 (rm, rq, rr))))) |
| 77721 | 458 |
| ord => |
| 77737 | 459 |
(case del (if_equal ord NONE k) r of |
460 |
(p', (false, r')) => (p', (false, make2 (l, if_equal ord p' p, r'))) |
|
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
461 |
| (p', (true, r')) => (p', case unmake l of |
| 77721 | 462 |
Branch2 (ll, lp, lr) => |
| 77737 | 463 |
(true, make3 (ll, lp, lr, if_equal ord p' p, r')) |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
464 |
| Branch3 (ll, lp, lm, lq, lr) => (false, make2 |
| 77737 | 465 |
(make2 (ll, lp, lm), lq, make2 (lr, if_equal ord p' p, r')))))) |
| 77721 | 466 |
| del k (Branch3 (l, p, m, q, r)) = |
467 |
(case compare k q of |
|
468 |
LESS => |
|
469 |
(case compare k p of |
|
470 |
LESS => |
|
471 |
(case del k l of |
|
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
472 |
(p', (false, l')) => (p', (false, make3 (l', p, m, q, r))) |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
473 |
| (p', (true, l')) => (p', (false, case (unmake m, unmake r) of |
| 77721 | 474 |
(Branch2 (ml, mp, mr), Branch2 _) => |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
475 |
make2 (make3 (l', p, ml, mp, mr), q, r) |
| 77721 | 476 |
| (Branch3 (ml, mp, mm, mq, mr), _) => |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
477 |
make3 (make2 (l', p, ml), mp, make2 (mm, mq, mr), q, r) |
| 77721 | 478 |
| (Branch2 (ml, mp, mr), Branch3 (rl, rp, rm, rq, rr)) => |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
479 |
make3 (make2 (l', p, ml), mp, make2 (mr, q, rl), rp, |
|
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
480 |
make2 (rm, rq, rr))))) |
| 77721 | 481 |
| ord => |
| 77737 | 482 |
(case del (if_equal ord NONE k) m of |
| 77721 | 483 |
(p', (false, m')) => |
| 77737 | 484 |
(p', (false, make3 (l, if_equal ord p' p, m', q, r))) |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
485 |
| (p', (true, m')) => (p', (false, case (unmake l, unmake r) of |
| 77721 | 486 |
(Branch2 (ll, lp, lr), Branch2 _) => |
| 77737 | 487 |
make2 (make3 (ll, lp, lr, if_equal ord p' p, m'), q, r) |
| 77721 | 488 |
| (Branch3 (ll, lp, lm, lq, lr), _) => |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
489 |
make3 (make2 (ll, lp, lm), lq, |
| 77737 | 490 |
make2 (lr, if_equal ord p' p, m'), q, r) |
| 77721 | 491 |
| (_, Branch3 (rl, rp, rm, rq, rr)) => |
| 77737 | 492 |
make3 (l, if_equal ord p' p, make2 (m', q, rl), rp, |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
493 |
make2 (rm, rq, rr)))))) |
| 77721 | 494 |
| ord => |
| 77737 | 495 |
(case del (if_equal ord NONE k) r of |
| 77721 | 496 |
(q', (false, r')) => |
| 77737 | 497 |
(q', (false, make3 (l, p, m, if_equal ord q' q, r'))) |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
498 |
| (q', (true, r')) => (q', (false, case (unmake l, unmake m) of |
| 77721 | 499 |
(Branch2 _, Branch2 (ml, mp, mr)) => |
| 77737 | 500 |
make2 (l, p, make3 (ml, mp, mr, if_equal ord q' q, r')) |
| 77721 | 501 |
| (_, Branch3 (ml, mp, mm, mq, mr)) => |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
502 |
make3 (l, p, make2 (ml, mp, mm), mq, |
| 77737 | 503 |
make2 (mr, if_equal ord q' q, r')) |
| 77721 | 504 |
| (Branch3 (ll, lp, lm, lq, lr), Branch2 (ml, mp, mr)) => |
|
77736
570f1436fe0a
more compact representation of leaf nodes: only 1.10 .. 1.33 larger than plain list;
wenzelm
parents:
77735
diff
changeset
|
505 |
make3 (make2 (ll, lp, lm), lq, make2 (lr, p, ml), mp, |
| 77800 | 506 |
make2 (mr, if_equal ord q' q, r')))))) |
507 |
| del k (Size (_, arg)) = del k arg; |
|
| 15665 | 508 |
in |
509 |
||
| 77800 | 510 |
fun delete key tab = make_size (size tab - 1) (snd (snd (del (SOME key) tab))); |
|
44336
59ff5a93eef4
tuned Table.delete_safe: avoid potentially expensive attempt of delete;
wenzelm
parents:
43792
diff
changeset
|
511 |
fun delete_safe key tab = if defined tab key then delete key tab else tab; |
| 15014 | 512 |
|
| 15665 | 513 |
end; |
514 |
||
| 15014 | 515 |
|
| 19031 | 516 |
(* membership operations *) |
| 16466 | 517 |
|
518 |
fun member eq tab (key, x) = |
|
| 17412 | 519 |
(case lookup tab key of |
| 16466 | 520 |
NONE => false |
521 |
| SOME y => eq (x, y)); |
|
| 15761 | 522 |
|
523 |
fun insert eq (key, x) = |
|
524 |
modify key (fn NONE => x | SOME y => if eq (x, y) then raise SAME else raise DUP key); |
|
525 |
||
526 |
fun remove eq (key, x) tab = |
|
| 17412 | 527 |
(case lookup tab key of |
| 15761 | 528 |
NONE => tab |
529 |
| SOME y => if eq (x, y) then delete key tab else tab); |
|
530 |
||
531 |
||
| 19031 | 532 |
(* simultaneous modifications *) |
533 |
||
| 74266 | 534 |
fun make entries = build (fold update_new entries); |
| 5015 | 535 |
|
| 77781 | 536 |
fun join f (tab1, tab2) = |
|
55727
7e330ae052bb
optimize special case according to Library.merge (see also 8fbc355100f2, 520872460b7b);
wenzelm
parents:
52049
diff
changeset
|
537 |
let |
|
7e330ae052bb
optimize special case according to Library.merge (see also 8fbc355100f2, 520872460b7b);
wenzelm
parents:
52049
diff
changeset
|
538 |
fun add (key, y) tab = modify key (fn NONE => y | SOME x => f key (x, y)) tab; |
|
7e330ae052bb
optimize special case according to Library.merge (see also 8fbc355100f2, 520872460b7b);
wenzelm
parents:
52049
diff
changeset
|
539 |
in |
| 77781 | 540 |
if pointer_eq (tab1, tab2) then tab1 |
541 |
else if is_empty tab1 then tab2 |
|
542 |
else fold_table add tab2 tab1 |
|
|
55727
7e330ae052bb
optimize special case according to Library.merge (see also 8fbc355100f2, 520872460b7b);
wenzelm
parents:
52049
diff
changeset
|
543 |
end; |
| 12287 | 544 |
|
| 19031 | 545 |
fun merge eq = join (fn key => fn xy => if eq xy then raise SAME else raise DUP key); |
| 5015 | 546 |
|
| 77822 | 547 |
fun joins f tabs = Library.foldl (join f) (empty, tabs); |
548 |
fun merges eq tabs = Library.foldl (merge eq) (empty, tabs); |
|
549 |
||
| 5015 | 550 |
|
| 19031 | 551 |
(* list tables *) |
| 15761 | 552 |
|
| 18946 | 553 |
fun lookup_list tab key = these (lookup tab key); |
| 25391 | 554 |
|
555 |
fun cons_list (key, x) tab = modify key (fn NONE => [x] | SOME xs => x :: xs) tab; |
|
| 5015 | 556 |
|
| 77981 | 557 |
fun modify_list key f = |
558 |
modify key (fn arg => |
|
559 |
let |
|
560 |
val xs = the_default [] arg; |
|
561 |
val ys = f xs; |
|
562 |
in if pointer_eq (xs, ys) then raise SAME else ys end); |
|
563 |
||
564 |
fun insert_list eq (key, x) = modify_list key (Library.insert eq x); |
|
565 |
fun update_list eq (key, x) = modify_list key (Library.update eq x); |
|
| 25391 | 566 |
|
| 18946 | 567 |
fun remove_list eq (key, x) tab = |
| 77981 | 568 |
map_entry key (fn xs => |
569 |
(case Library.remove eq x xs of |
|
570 |
[] => raise UNDEF key |
|
571 |
| ys => if pointer_eq (xs, ys) then raise SAME else ys)) tab |
|
| 15761 | 572 |
handle UNDEF _ => delete key tab; |
| 5015 | 573 |
|
| 74266 | 574 |
fun make_list args = build (fold_rev cons_list args); |
|
19482
9f11af8f7ef9
tuned basic list operators (flat, maps, map_filter);
wenzelm
parents:
19073
diff
changeset
|
575 |
fun dest_list tab = maps (fn (key, xs) => map (pair key) xs) (dest tab); |
| 77973 | 576 |
fun merge_list eq = |
| 77975 | 577 |
join (fn _ => fn xy => if eq_list eq xy then raise SAME else Library.merge eq xy); |
| 5015 | 578 |
|
579 |
||
| 74227 | 580 |
(* set operations *) |
| 50234 | 581 |
|
582 |
type set = unit table; |
|
583 |
||
| 67529 | 584 |
fun insert_set x = default (x, ()); |
585 |
fun remove_set x : set -> set = delete_safe x; |
|
| 74266 | 586 |
fun make_set xs = build (fold insert_set xs); |
| 50234 | 587 |
|
588 |
||
| 79163 | 589 |
(* cache *) |
590 |
||
591 |
fun unsynchronized_cache f = |
|
592 |
let val cache = Unsynchronized.ref empty in |
|
593 |
fn x => |
|
594 |
(case lookup (! cache) x of |
|
595 |
SOME result => Exn.release result |
|
596 |
| NONE => |
|
597 |
let |
|
598 |
val result = Exn.result f x; |
|
599 |
val _ = Unsynchronized.change cache (update (x, result)); |
|
600 |
in Exn.release result end) |
|
601 |
end; |
|
602 |
||
603 |
||
|
47980
c81801f881b3
simplified Poly/ML setup -- 5.3.0 is now the common base-line;
wenzelm
parents:
44336
diff
changeset
|
604 |
(* ML pretty-printing *) |
|
38635
f76ad0771f67
added ML toplevel pretty-printing for tables, using dummy for anything other than Poly/ML 5.3.0 (or later);
wenzelm
parents:
35012
diff
changeset
|
605 |
|
|
f76ad0771f67
added ML toplevel pretty-printing for tables, using dummy for anything other than Poly/ML 5.3.0 (or later);
wenzelm
parents:
35012
diff
changeset
|
606 |
val _ = |
|
62819
d3ff367a16a0
careful export of type-dependent functions, without losing their special status;
wenzelm
parents:
62503
diff
changeset
|
607 |
ML_system_pp (fn depth => fn pretty => fn tab => |
| 62503 | 608 |
ML_Pretty.to_polyml |
|
38635
f76ad0771f67
added ML toplevel pretty-printing for tables, using dummy for anything other than Poly/ML 5.3.0 (or later);
wenzelm
parents:
35012
diff
changeset
|
609 |
(ML_Pretty.enum "," "{" "}"
|
| 62503 | 610 |
(ML_Pretty.pair |
|
62819
d3ff367a16a0
careful export of type-dependent functions, without losing their special status;
wenzelm
parents:
62503
diff
changeset
|
611 |
(ML_Pretty.from_polyml o ML_system_pretty) |
| 62503 | 612 |
(ML_Pretty.from_polyml o pretty)) |
|
38635
f76ad0771f67
added ML toplevel pretty-printing for tables, using dummy for anything other than Poly/ML 5.3.0 (or later);
wenzelm
parents:
35012
diff
changeset
|
613 |
(dest tab, depth))); |
|
f76ad0771f67
added ML toplevel pretty-printing for tables, using dummy for anything other than Poly/ML 5.3.0 (or later);
wenzelm
parents:
35012
diff
changeset
|
614 |
|
|
f76ad0771f67
added ML toplevel pretty-printing for tables, using dummy for anything other than Poly/ML 5.3.0 (or later);
wenzelm
parents:
35012
diff
changeset
|
615 |
|
| 5681 | 616 |
(*final declarations of this structure!*) |
| 39020 | 617 |
val map = map_table; |
| 16446 | 618 |
val fold = fold_table; |
| 28334 | 619 |
val fold_rev = fold_rev_table; |
| 5015 | 620 |
|
621 |
end; |
|
622 |
||
|
31971
8c1b845ed105
renamed functor TableFun to Table, and GraphFun to Graph;
wenzelm
parents:
31621
diff
changeset
|
623 |
structure Inttab = Table(type key = int val ord = int_ord); |
|
8c1b845ed105
renamed functor TableFun to Table, and GraphFun to Graph;
wenzelm
parents:
31621
diff
changeset
|
624 |
structure Symtab = Table(type key = string val ord = fast_string_ord); |
|
8c1b845ed105
renamed functor TableFun to Table, and GraphFun to Graph;
wenzelm
parents:
31621
diff
changeset
|
625 |
structure Symreltab = Table(type key = string * string |
|
30647
ef8f46c3158a
added Symreltab (binary relations of symbols) instance of TableFun
haftmann
parents:
30290
diff
changeset
|
626 |
val ord = prod_ord fast_string_ord fast_string_ord); |