@@ -51,6 +51,7 @@ pub mod linear {
5151 FoundEntry ( uint ) , FoundHole ( uint ) , TableFull
5252 }
5353
54+ #[ inline( always) ]
5455 pure fn resize_at ( capacity : uint ) -> uint {
5556 ( ( capacity as float ) * 3. / 4. ) as uint
5657 }
@@ -76,10 +77,8 @@ pub mod linear {
7677 priv impl < K : Hash IterBytes Eq , V > LinearMap < K , V > {
7778 #[ inline( always) ]
7879 pure fn to_bucket ( & self , h : uint ) -> uint {
79- // FIXME(#3041) borrow a more sophisticated technique here from
80- // Gecko, for example borrowing from Knuth, as Eich so
81- // colorfully argues for here:
82- // https://bugzilla.mozilla.org/show_bug.cgi?id=743107#c22
80+ // A good hash function with entropy spread over all of the
81+ // bits is assumed. SipHash is more than good enough.
8382 h % self . buckets . len ( )
8483 }
8584
@@ -128,12 +127,19 @@ pub mod linear {
128127 TableFull
129128 }
130129
131- /// Expands the capacity of the array and re-inserts each
132- /// of the existing buckets.
130+ /// Expand the capacity of the array to the next power of two
131+ /// and re-insert each of the existing buckets.
132+ #[ inline( always) ]
133133 fn expand ( & mut self ) {
134+ let new_capacity = self . buckets . len ( ) * 2 ;
135+ self . resize ( new_capacity) ;
136+ }
137+
138+ /// Expands the capacity of the array and re-insert each of the
139+ /// existing buckets.
140+ fn resize ( & mut self , new_capacity : uint ) {
134141 let old_capacity = self . buckets . len ( ) ;
135- let new_capacity = old_capacity * 2 ;
136- self . resize_at = ( ( new_capacity as float ) * 3.0 / 4.0 ) as uint ;
142+ self . resize_at = resize_at ( new_capacity) ;
137143
138144 let mut old_buckets = vec:: from_fn ( new_capacity, |_| None ) ;
139145 self . buckets <-> old_buckets;
@@ -333,6 +339,14 @@ pub mod linear {
333339 linear_map_with_capacity(INITIAL_CAPACITY)
334340 }
335341
342+ /// Reserve space for at least `n` elements in the hash table.
343+ fn reserve_at_least(&mut self, n: uint) {
344+ if n > self.buckets.len() {
345+ let buckets = n * 4 / 3 + 1;
346+ self.resize(uint::next_power_of_two(buckets));
347+ }
348+ }
349+
336350 fn pop(&mut self, k: &K) -> Option<V> {
337351 let hash = k.hash_keyed(self.k0, self.k1) as uint;
338352 self.pop_internal(hash, k)
@@ -564,6 +578,11 @@ pub mod linear {
564578 pub impl < T : Hash IterBytes Eq > LinearSet < T > {
565579 /// Create an empty LinearSet
566580 static fn new( ) -> LinearSet <T > { LinearSet { map: LinearMap :: new( ) } }
581+
582+ /// Reserve space for at least `n` elements in the hash table.
583+ fn reserve_at_least ( & mut self , n : uint ) {
584+ self . map . reserve_at_least ( n)
585+ }
567586 }
568587}
569588
0 commit comments