@@ -104,6 +104,242 @@ type hashmap<K, V> = obj {
104
104
105
105
/* Section: Operations */
106
106
107
+ mod chained {
108
+ type entry < copy K , copy V > = {
109
+ hash : uint ,
110
+ key : K ,
111
+ mutable value: V ,
112
+ mutable next: chain < K , V >
113
+ } ;
114
+
115
+ tag chain<copy K , copy V > {
116
+ present( @entry<K , V >) ;
117
+ absent;
118
+ }
119
+
120
+ type t < copy K , copy V > = {
121
+ mutable size: uint ,
122
+ mutable chains: [ mutable chain< K , V > ] ,
123
+ hasher : hashfn < K > ,
124
+ eqer : eqfn < K >
125
+ } ;
126
+
127
+ tag search_result<copy K , copy V > {
128
+ not_found ( uint) ;
129
+ found_first ( uint, @entry<K , V >) ;
130
+ found_after ( @entry<K , V >, @entry<K , V >) ;
131
+ }
132
+
133
+ fn search_rem < copy K , copy V > ( tbl : t < K , V > ,
134
+ k : K ,
135
+ h : uint ,
136
+ idx : uint ,
137
+ e_root : @entry < K , V > ) -> search_result < K , V > {
138
+ let e0 = e_root;
139
+ while true {
140
+ alt e0. next {
141
+ absent. {
142
+ ret not_found ( idx) ;
143
+ }
144
+ present ( e1) {
145
+ let e1_key = e1. key ; // Satisfy alias checker.
146
+ if e1. hash == h && tbl. eqer ( e1_key, k) {
147
+ ret found_after ( e0, e1) ;
148
+ } else {
149
+ e0 = e1;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ util:: unreachable ( ) ;
155
+ }
156
+
157
+ fn search_tbl < copy K , copy V > (
158
+ tbl : t < K , V > , k : K , h : uint ) -> search_result < K , V > {
159
+
160
+ let idx = h % vec:: len ( tbl. chains ) ;
161
+
162
+ alt tbl. chains [ idx] {
163
+ absent. {
164
+ ret not_found ( idx) ;
165
+ }
166
+ present ( e) {
167
+ let e_key = e. key ; // Satisfy alias checker.
168
+ if e. hash == h && tbl. eqer ( e_key, k) {
169
+ ret found_first ( idx, e) ;
170
+ } else {
171
+ ret search_rem ( tbl, k, h, idx, e) ;
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ fn insert_h < copy K , copy V > ( tbl : t < K , V > , k : K , v : V , hash : uint ) -> bool {
178
+ // internal routine: does not update size
179
+ alt search_tbl ( tbl, k, hash) {
180
+ not_found ( idx) {
181
+ let old_chain = tbl. chains [ idx] ;
182
+ tbl. chains [ idx] = present ( @{
183
+ hash: hash,
184
+ key: k,
185
+ mutable value: v,
186
+ mutable next: old_chain} ) ;
187
+ ret true;
188
+ }
189
+ found_first ( _, entry) {
190
+ entry. value = v;
191
+ ret false;
192
+ }
193
+ found_after ( _, entry) {
194
+ entry. value = v;
195
+ ret false
196
+ }
197
+ }
198
+ }
199
+
200
+ fn insert < copy K , copy V > ( tbl : t < K , V > , k : K , v : V ) -> bool {
201
+ tbl. size += 1 u;
202
+ ret insert_h( tbl, k, v, tbl. hasher ( k) ) ;
203
+ }
204
+
205
+ fn get < copy K , copy V > ( tbl : t < K , V > , k : K ) -> option:: t < V > {
206
+ alt search_tbl ( tbl, k, tbl. hasher ( k) ) {
207
+ not_found ( _) {
208
+ ret option:: none;
209
+ }
210
+
211
+ found_first ( _, entry) {
212
+ ret option:: some ( entry. value ) ;
213
+ }
214
+
215
+ found_after ( _, entry) {
216
+ ret option:: some ( entry. value ) ;
217
+ }
218
+ }
219
+ }
220
+
221
+ fn remove < copy K , copy V > ( tbl : t < K , V > , k : K ) -> option:: t < V > {
222
+ alt search_tbl ( tbl, k, tbl. hasher ( k) ) {
223
+ not_found ( _) {
224
+ ret option:: none;
225
+ }
226
+
227
+ found_first ( idx, entry) {
228
+ tbl. chains [ idx] = entry. next ;
229
+ ret option:: some ( entry. value ) ;
230
+ }
231
+
232
+ found_after ( eprev, entry) {
233
+ eprev. next = entry. next ;
234
+ ret option:: some ( entry. value ) ;
235
+ }
236
+ }
237
+ }
238
+
239
+ fn chains < copy K , copy V > ( nchains : uint ) -> [ mutable chain< K , V > ] {
240
+ ret vec:: init_elt_mut ( absent, nchains) ;
241
+ }
242
+
243
+ fn foreach_entry < copy K , copy V > ( chain0 : chain < K , V > ,
244
+ blk : block ( @entry < K , V > ) ) {
245
+ let chain = chain0;
246
+ while true {
247
+ alt chain {
248
+ absent. { ret; }
249
+ present ( entry) {
250
+ blk ( entry) ;
251
+ chain = entry. next ;
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ fn foreach_chain<copy K , copy V >( chains: [ const chain<K , V >] ,
258
+ blk : block( @entry<K , V >) ) {
259
+ let i = 0 u, n = vec:: len ( chains) ;
260
+ while i < n {
261
+ foreach_entry ( chains[ i] , blk) ;
262
+ i += 1 u;
263
+ }
264
+ }
265
+
266
+ fn rehash < copy K , copy V > ( tbl : t < K , V > ) {
267
+ let old_chains = tbl. chains ;
268
+ let n_old_chains = vec:: len ( old_chains) ;
269
+ let n_new_chains: uint = uint:: next_power_of_two ( n_old_chains + 1 u) ;
270
+ tbl. chains = chains ( n_new_chains) ;
271
+ foreach_chain ( old_chains) { |entry|
272
+ insert_h ( tbl, entry. key , entry. value , entry. hash ) ;
273
+ }
274
+ }
275
+
276
+ fn items < copy K , copy V > ( tbl : t < K , V > , blk : block ( K , V ) ) {
277
+ let tbl_chains = tbl. chains ; // Satisfy alias checker.
278
+ foreach_chain ( tbl_chains) { |entry|
279
+ let key = entry. key ;
280
+ let value = entry. value ;
281
+ blk ( key, value) ;
282
+ }
283
+ }
284
+
285
+ obj o<copy K , copy V >( tbl: @t<K , V >,
286
+ lf: float) {
287
+ fn size ( ) -> uint {
288
+ ret tbl. size ;
289
+ }
290
+
291
+ fn insert ( k : K , v : V ) -> bool {
292
+ let nchains = vec:: len ( tbl. chains ) ;
293
+ let load = ( tbl. size + 1 u as float ) / ( nchains as float ) ;
294
+ if load > lf {
295
+ rehash ( * tbl) ;
296
+ }
297
+ ret insert( * tbl, k, v) ;
298
+ }
299
+
300
+ fn contains_key ( k : K ) -> bool {
301
+ ret option:: is_some ( get ( * tbl, k) ) ;
302
+ }
303
+
304
+ fn get ( k : K ) -> V {
305
+ ret option:: get ( get ( * tbl, k) ) ;
306
+ }
307
+
308
+ fn find ( k : K ) -> option:: t < V > {
309
+ ret get ( * tbl, k) ;
310
+ }
311
+
312
+ fn remove ( k : K ) -> option:: t < V > {
313
+ ret remove ( * tbl, k) ;
314
+ }
315
+
316
+ fn rehash ( ) {
317
+ rehash ( * tbl) ;
318
+ }
319
+
320
+ fn items ( blk : block ( K , V ) ) {
321
+ items ( * tbl, blk) ;
322
+ }
323
+
324
+ fn keys ( blk : block ( K ) ) {
325
+ items ( * tbl) { |k, _v| blk ( k) }
326
+ }
327
+
328
+ fn values ( blk : block ( V ) ) {
329
+ items ( * tbl) { |_k, v| blk ( v) }
330
+ }
331
+ }
332
+
333
+ fn mk < copy K , copy V > ( hasher : hashfn < K > , eqer : eqfn < K > ) -> hashmap < K , V > {
334
+ let initial_capacity: uint = 32 u; // 2^5
335
+ let t = @{ mutable size: 0 u,
336
+ mutable chains: chains ( initial_capacity) ,
337
+ hasher: hasher,
338
+ eqer: eqer} ;
339
+ ret o( t, 0.75 ) ;
340
+ }
341
+ }
342
+
107
343
/*
108
344
Function: mk_hashmap
109
345
@@ -114,7 +350,7 @@ Parameters:
114
350
hasher - The hash function for key type K
115
351
eqer - The equality function for key type K
116
352
*/
117
- fn mk_hashmap < copy K , copy V > ( hasher : hashfn < K > , eqer : eqfn < K > )
353
+ fn mk_flat_hashmap < copy K , copy V > ( hasher : hashfn < K > , eqer : eqfn < K > )
118
354
-> hashmap < K , V > {
119
355
let initial_capacity: uint = 32 u; // 2^5
120
356
@@ -134,7 +370,7 @@ fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
134
370
// buckets before the resulting pair of hash functions no longer
135
371
// probes all buckets for a fixed key. Note that hashl is made to
136
372
// output odd numbers (hence coprime to the number of nbkts, which
137
- // is always a power of 2), so that all buckets are probed for a
373
+ // is always a power? of 2), so that all buckets are probed for a
138
374
// fixed key.
139
375
140
376
fn hashl ( n : u32 ) -> u32 { ret ( n >>> 16u32 ) * 2u32 + 1u32 ; }
@@ -293,6 +529,11 @@ fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
293
529
ret hashmap( hasher, eqer, bkts, initial_capacity, 0 u, load_factor) ;
294
530
}
295
531
532
+ fn mk_hashmap < copy K , copy V > ( hasher : hashfn < K > , eqer : eqfn < K > )
533
+ -> hashmap < K , V > {
534
+ ret chained:: mk ( hasher, eqer) ;
535
+ }
536
+
296
537
/*
297
538
Function: new_str_hash
298
539
0 commit comments