@@ -4,16 +4,11 @@ Sendable hash maps. Very much a work in progress.
4
4
5
5
*/
6
6
7
+ import cmp:: Eq ;
8
+ import hash:: Hash ;
9
+ import to_bytes:: IterBytes ;
7
10
8
- /**
9
- * A function that returns a hash of a value
10
- *
11
- * The hash should concentrate entropy in the lower bits.
12
- */
13
- type HashFn < K > = pure fn~( K ) -> uint ;
14
- type EqFn < K > = pure fn~( K , K ) -> bool ;
15
-
16
- trait SendMap < K , V : copy > {
11
+ trait SendMap < K : Eq Hash , V : copy > {
17
12
// FIXME(#3148) ^^^^ once find_ref() works, we can drop V:copy
18
13
19
14
fn insert ( & mut self , +k : K , +v : V ) -> bool ;
@@ -34,14 +29,14 @@ mod linear {
34
29
export LinearMap , linear_map, linear_map_with_capacity, public_methods;
35
30
36
31
const initial_capacity: uint = 32 u; // 2^5
37
- struct Bucket < K , V > {
32
+ struct Bucket < K : Eq Hash , V > {
38
33
hash : uint ;
39
34
key: K ;
40
35
value: V ;
41
36
}
42
- struct LinearMap < K , V > {
43
- hashfn : pure fn~ ( x : & K ) -> uint ;
44
- eqfn : pure fn~ ( x : & K , y : & K ) -> bool ;
37
+ struct LinearMap < K : Eq Hash , V > {
38
+ k0 : u64 ;
39
+ k1 : u64 ;
45
40
resize_at: uint;
46
41
size: uint;
47
42
buckets: ~[ Option <Bucket <K , V >>] ;
@@ -58,28 +53,29 @@ mod linear {
58
53
( ( capacity as float ) * 3. / 4. ) as uint
59
54
}
60
55
61
- fn LinearMap < K , V > (
62
- +hashfn : pure fn~( x : & K ) -> uint ,
63
- +eqfn : pure fn~( x : & K , y : & K ) -> bool ) -> LinearMap < K , V > {
64
-
65
- linear_map_with_capacity ( hashfn, eqfn, 32 )
56
+ fn LinearMap < K : Eq Hash , V > ( ) -> LinearMap < K , V > {
57
+ linear_map_with_capacity ( 32 )
66
58
}
67
59
68
- fn linear_map_with_capacity < K , V > (
69
- +hashfn : pure fn~( x : & K ) -> uint ,
70
- +eqfn : pure fn~( x : & K , y : & K ) -> bool ,
60
+ fn linear_map_with_capacity < K : Eq Hash , V > (
71
61
initial_capacity : uint ) -> LinearMap < K , V > {
62
+ let r = rand:: Rng ( ) ;
63
+ linear_map_with_capacity_and_keys ( r. gen_u64 ( ) , r. gen_u64 ( ) ,
64
+ initial_capacity)
65
+ }
72
66
67
+ fn linear_map_with_capacity_and_keys < K : Eq Hash , V > (
68
+ k0 : u64 , k1 : u64 ,
69
+ initial_capacity : uint ) -> LinearMap < K , V > {
73
70
LinearMap {
74
- hashfn : hashfn,
75
- eqfn : eqfn,
71
+ k0 : k0, k1 : k1,
76
72
resize_at : resize_at ( initial_capacity) ,
77
73
size : 0 ,
78
74
buckets : vec:: from_fn ( initial_capacity, |_i| None )
79
75
}
80
76
}
81
77
82
- priv impl < K , V > LinearMap < K , V > {
78
+ priv impl < K : Hash IterBytes Eq , V > LinearMap < K , V > {
83
79
#[ inline( always) ]
84
80
pure fn to_bucket ( & const self ,
85
81
h : uint ) -> uint {
@@ -123,7 +119,7 @@ mod linear {
123
119
pure fn bucket_for_key ( & const self ,
124
120
buckets : & [ Option < Bucket < K , V > > ] ,
125
121
k : & K ) -> SearchResult {
126
- let hash = self . hashfn ( k ) ;
122
+ let hash = k . hash_keyed ( self . k0 , self . k1 ) as uint ;
127
123
self . bucket_for_key_with_hash ( buckets, hash, k)
128
124
}
129
125
@@ -134,7 +130,7 @@ mod linear {
134
130
k : & K ) -> SearchResult {
135
131
let _ = for self . bucket_sequence( hash) |i| {
136
132
match buckets[ i] {
137
- Some ( bkt) => if bkt. hash == hash && self . eqfn ( k , & bkt. key ) {
133
+ Some ( bkt) => if bkt. hash == hash && * k == bkt. key {
138
134
return FoundEntry ( i) ;
139
135
} ,
140
136
None => return FoundHole ( i)
@@ -204,7 +200,7 @@ mod linear {
204
200
}
205
201
}
206
202
207
- impl < K , V > LinearMap < K , V > {
203
+ impl < K : Hash IterBytes Eq , V > LinearMap < K , V > {
208
204
fn insert ( & mut self , +k : K , +v : V ) -> bool {
209
205
if self . size >= self . resize_at {
210
206
// n.b.: We could also do this after searching, so
@@ -216,7 +212,7 @@ mod linear {
216
212
self . expand ( ) ;
217
213
}
218
214
219
- let hash = self . hashfn ( & k ) ;
215
+ let hash = k . hash_keyed ( self . k0 , self . k1 ) as uint ;
220
216
self . insert_internal ( hash, k, v)
221
217
}
222
218
@@ -319,7 +315,7 @@ mod linear {
319
315
}
320
316
}
321
317
322
- impl < K , V : copy > LinearMap < K , V > {
318
+ impl < K : Hash IterBytes Eq , V : copy > LinearMap < K , V > {
323
319
fn find ( & const self , k : & K ) -> Option < V > {
324
320
match self . bucket_for_key ( self . buckets , k) {
325
321
FoundEntry ( idx) => {
@@ -346,17 +342,17 @@ mod linear {
346
342
347
343
}
348
344
349
- impl < K : copy , V : copy > LinearMap < K , V > {
345
+ impl < K : Hash IterBytes Eq copy, V : copy > LinearMap < K , V > {
350
346
fn each ( & self , blk : fn ( +K , +V ) -> bool ) {
351
347
self . each_ref ( |k, v| blk ( copy * k, copy * v) ) ;
352
348
}
353
349
}
354
- impl < K : copy , V > LinearMap < K , V > {
350
+ impl < K : Hash IterBytes Eq copy, V > LinearMap < K , V > {
355
351
fn each_key ( & self , blk : fn ( +K ) -> bool ) {
356
352
self . each_key_ref ( |k| blk ( copy * k) ) ;
357
353
}
358
354
}
359
- impl < K , V : copy > LinearMap < K , V > {
355
+ impl < K : Hash IterBytes Eq , V : copy > LinearMap < K , V > {
360
356
fn each_value ( & self , blk : fn ( +V ) -> bool ) {
361
357
self . each_value_ref ( |v| blk ( copy * v) ) ;
362
358
}
@@ -368,11 +364,8 @@ mod test {
368
364
369
365
import linear:: LinearMap ;
370
366
371
- pure fn uint_hash ( x : & uint ) -> uint { * x }
372
- pure fn uint_eq ( x : & uint , y : & uint ) -> bool { * x == * y }
373
-
374
367
fn int_linear_map < V > ( ) -> LinearMap < uint , V > {
375
- return LinearMap ( uint_hash , uint_eq ) ;
368
+ return LinearMap ( ) ;
376
369
}
377
370
378
371
#[ test]
@@ -395,7 +388,7 @@ mod test {
395
388
396
389
#[ test]
397
390
fn conflicts ( ) {
398
- let mut m = ~linear:: linear_map_with_capacity ( uint_hash , uint_eq , 4 ) ;
391
+ let mut m = ~linear:: linear_map_with_capacity ( 4 ) ;
399
392
assert m. insert ( 1 , 2 ) ;
400
393
assert m. insert ( 5 , 3 ) ;
401
394
assert m. insert ( 9 , 4 ) ;
@@ -406,7 +399,7 @@ mod test {
406
399
407
400
#[ test]
408
401
fn conflict_remove ( ) {
409
- let mut m = ~linear:: linear_map_with_capacity ( uint_hash , uint_eq , 4 ) ;
402
+ let mut m = ~linear:: linear_map_with_capacity ( 4 ) ;
410
403
assert m. insert ( 1 , 2 ) ;
411
404
assert m. insert ( 5 , 3 ) ;
412
405
assert m. insert ( 9 , 4 ) ;
@@ -417,7 +410,7 @@ mod test {
417
410
418
411
#[ test]
419
412
fn empty ( ) {
420
- let mut m = ~linear:: linear_map_with_capacity ( uint_hash , uint_eq , 4 ) ;
413
+ let mut m = ~linear:: linear_map_with_capacity ( 4 ) ;
421
414
assert m. insert ( 1 , 2 ) ;
422
415
assert !m. is_empty ( ) ;
423
416
assert m. remove ( & 1 ) ;
@@ -426,7 +419,7 @@ mod test {
426
419
427
420
#[ test]
428
421
fn iterate ( ) {
429
- let mut m = linear:: linear_map_with_capacity ( uint_hash , uint_eq , 4 ) ;
422
+ let mut m = linear:: linear_map_with_capacity ( 4 ) ;
430
423
for uint:: range( 0 , 32 ) |i| {
431
424
assert ( & mut m) . insert( i, i* 2 ) ;
432
425
}
0 commit comments