mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 00:31:34 +11:00
Allow for resizing
This commit is contained in:
parent
8d976b49bc
commit
a9115c23e8
|
@ -37,9 +37,9 @@ struct NodeStorage<K, V>(Vec<Option<Node<K, V>>>);
|
||||||
|
|
||||||
impl<K, V> NodeStorage<K, V> {
|
impl<K, V> NodeStorage<K, V> {
|
||||||
fn with_size(capacity: usize) -> Self {
|
fn with_size(capacity: usize) -> Self {
|
||||||
let next_power_of_2 = find_next_power_of_2(capacity);
|
assert!(capacity.is_power_of_two(), "Capacity must be a power of 2");
|
||||||
|
|
||||||
Self(iter::repeat_with(|| None).take(next_power_of_2).collect())
|
Self(iter::repeat_with(|| None).take(capacity).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
|
@ -140,6 +140,35 @@ impl<K, V> HashMap<K, V> {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.number_of_elements
|
self.number_of_elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resize(&mut self, new_size: usize) {
|
||||||
|
assert!(
|
||||||
|
new_size >= self.nodes.len(),
|
||||||
|
"Can only increase the size of a hash map"
|
||||||
|
);
|
||||||
|
if new_size == self.nodes.len() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_node_storage = NodeStorage::with_size(new_size);
|
||||||
|
let mut new_max_distance_to_initial_bucket = 0;
|
||||||
|
let number_of_elements = self.number_of_elements;
|
||||||
|
|
||||||
|
for node in self.nodes.0.drain(..) {
|
||||||
|
if let Some(node) = node {
|
||||||
|
new_max_distance_to_initial_bucket = new_node_storage.insert_new(
|
||||||
|
node.key,
|
||||||
|
node.value,
|
||||||
|
node.hash,
|
||||||
|
number_of_elements,
|
||||||
|
new_max_distance_to_initial_bucket,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.nodes = new_node_storage;
|
||||||
|
self.max_distance_to_initial_bucket = new_max_distance_to_initial_bucket;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn fast_mod(len: usize, hash: HashType) -> usize {
|
const fn fast_mod(len: usize, hash: HashType) -> usize {
|
||||||
|
@ -147,15 +176,6 @@ const fn fast_mod(len: usize, hash: HashType) -> usize {
|
||||||
(hash as usize) & (len - 1)
|
(hash as usize) & (len - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn find_next_power_of_2(n: usize) -> usize {
|
|
||||||
let mut next_power_of_2 = 1;
|
|
||||||
while next_power_of_2 <= n {
|
|
||||||
next_power_of_2 *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_power_of_2
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V> HashMap<K, V>
|
impl<K, V> HashMap<K, V>
|
||||||
where
|
where
|
||||||
K: Eq,
|
K: Eq,
|
||||||
|
@ -193,6 +213,10 @@ where
|
||||||
return Some(old_value);
|
return Some(old_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.nodes.len() * 85 / 100 <= self.number_of_elements {
|
||||||
|
self.resize(self.nodes.len() * 2);
|
||||||
|
}
|
||||||
|
|
||||||
self.max_distance_to_initial_bucket = self.nodes.insert_new(
|
self.max_distance_to_initial_bucket = self.nodes.insert_new(
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
|
@ -345,4 +369,17 @@ mod test {
|
||||||
assert_eq!(num_found, 8);
|
assert_eq!(num_found, 8);
|
||||||
assert_eq!(max_found, 7);
|
assert_eq!(max_found, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test_case]
|
||||||
|
fn can_insert_more_than_initial_capacity(_gba: &mut Gba) {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
|
for i in 0..65 {
|
||||||
|
map.put(i, i % 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..65 {
|
||||||
|
assert_eq!(map.get(&i), Some(&(i % 4)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue