diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 833a7af59570..18cae4d55b76 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -353,211 +353,6 @@ mod chained { } } -/* -Function: mk_flat_hashmap - -Construct a "flat" hashmap, meaning that there are -not chains per buckets, but rather we search a sequence -of buckets for each key. - -Warning: it is unclear to me that this code is correct -on 32-bit processors. Check out the 'hash-tearing' code -in hash() and the comment surrounding it. - Niko - -Parameters: - -hasher - The hash function for key type K -eqer - The equality function for key type K -*/ -fn mk_flat_hashmap(hasher: hashfn, eqer: eqfn) - -> hashmap { - let initial_capacity: uint = 32u; // 2^5 - - let load_factor: util::rational = {num: 3, den: 4}; - tag bucket { nil; deleted; some(K, V); } - fn make_buckets(nbkts: uint) -> [mutable bucket] { - ret vec::init_elt_mut::>(nil::, nbkts); - } - // Derive two hash functions from the one given by taking the upper - // half and lower half of the uint bits. Our bucket probing - // sequence is then defined by - // - // hash(key, i) := hashl(key) * i + hashr(key) for i = 0, 1, 2, ... - // - // Tearing the hash function apart this way is kosher in practice - // as, assuming 32-bit uints, the table would have to be at 2^32 - // buckets before the resulting pair of hash functions no longer - // probes all buckets for a fixed key. Note that hashl is made to - // output odd numbers (hence coprime to the number of nbkts, which - // is always a power? of 2), so that all buckets are probed for a - // fixed key. - - fn hashl(n: uint) -> uint { ret (n >>> 16u) * 2u + 1u; } - fn hashr(n: uint) -> uint { ret 0x0000_ffff_u & n; } - fn hash(h: uint, nbkts: uint, i: uint) -> uint { - ret (hashl(h) * i + hashr(h)) % nbkts; - } - - /** - * We attempt to never call this with a full table. If we do, it - * will fail. - */ - fn insert_common(hasher: hashfn, eqer: eqfn, - bkts: [mutable bucket], - nbkts: uint, key: K, val: V) -> bool { - let i: uint = 0u; - let h = hasher(key); - while i < nbkts { - let j: uint = hash(h, nbkts, i); - alt bkts[j] { - some(k, _) { - // Copy key to please alias analysis. - - let k_ = k; - if eqer(key, k_) { - log("map updated", "i", i, "h", h, "nbkts", nbkts); - bkts[j] = some(k_, val); - ret false; - } - i += 1u; - } - _ { - log("map inserted", "i", i, "h", h, "nbkts", nbkts); - bkts[j] = some(key, val); - ret true; - } - } - } - fail; // full table - } - fn find_common(hasher: hashfn, eqer: eqfn, - bkts: [mutable bucket], - nbkts: uint, key: K) -> option::t { - let i: uint = 0u; - let h = hasher(key); - while i < nbkts { - let j: uint = hash(h, nbkts, i); - alt bkts[j] { - some(k, v) { - // Copy to please alias analysis. - let k_ = k; - let v_ = v; - if eqer(key, k_) { - log("map present", "i", i, "h", h, "nbkts", nbkts); - ret option::some(v_); - } - } - nil. { - log("map absent", "i", i, "h", h, "nbkts", nbkts); - ret option::none; - } - deleted. { } - } - i += 1u; - } - ret option::none; - } - fn rehash(hasher: hashfn, eqer: eqfn, - oldbkts: [mutable bucket], - _noldbkts: uint, - newbkts: [mutable bucket], - nnewbkts: uint) { - for b: bucket in oldbkts { - alt b { - some(k_, v_) { - let k = k_; - let v = v_; - insert_common(hasher, eqer, newbkts, nnewbkts, k, v); - } - _ { } - } - } - } - obj hashmap(hasher: hashfn, - eqer: eqfn, - mutable bkts: [mutable bucket], - mutable nbkts: uint, - mutable nelts: uint, - lf: util::rational) { - fn size() -> uint { ret nelts; } - fn insert(key: K, val: V) -> bool { - let load: util::rational = - {num: nelts + 1u as int, den: nbkts as int}; - if !util::rational_leq(load, lf) { - let nnewbkts: uint = uint::next_power_of_two(nbkts + 1u); - let newbkts = make_buckets(nnewbkts); - rehash(hasher, eqer, bkts, nbkts, newbkts, nnewbkts); - bkts = newbkts; - nbkts = nnewbkts; - } - if insert_common(hasher, eqer, bkts, nbkts, key, val) { - nelts += 1u; - ret true; - } - ret false; - } - fn contains_key(key: K) -> bool { - ret alt find_common(hasher, eqer, bkts, nbkts, key) { - option::some(_) { true } - _ { false } - }; - } - fn get(key: K) -> V { - ret alt find_common(hasher, eqer, bkts, nbkts, key) { - option::some(val) { val } - _ { fail } - }; - } - fn find(key: K) -> option::t { - be find_common(hasher, eqer, bkts, nbkts, key); - } - fn remove(key: K) -> option::t { - let i: uint = 0u; - let h = hasher(key); - while i < nbkts { - let j: uint = hash(h, nbkts, i); - alt bkts[j] { - some(k, v) { - let k_ = k; - let vo = option::some(v); - if eqer(key, k_) { - bkts[j] = deleted; - nelts -= 1u; - ret vo; - } - } - deleted. { } - nil. { ret option::none; } - } - i += 1u; - } - ret option::none; - } - fn rehash() { - let newbkts = make_buckets(nbkts); - rehash(hasher, eqer, bkts, nbkts, newbkts, nbkts); - bkts = newbkts; - } - fn items(it: block(K, V)) { - for b in bkts { - alt b { some(k, v) { it(copy k, copy v); } _ { } } - } - } - fn keys(it: block(K)) { - for b in bkts { - alt b { some(k, _) { it(copy k); } _ { } } - } - } - fn values(it: block(V)) { - for b in bkts { - alt b { some(_, v) { it(copy v); } _ { } } - } - } - } - let bkts = make_buckets(initial_capacity); - ret hashmap(hasher, eqer, bkts, initial_capacity, 0u, load_factor); -} - /* Function: mk_hashmap