From 617c782161f204d22c7530bebd5e36889ec44718 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Tue, 12 Mar 2019 13:41:05 +0100 Subject: [PATCH] RRB tree: use size table after pushing a sparse node to the left If the node we push to the left is not completely dense, then we convert to a size table. Previously this was only done for nodes of level > 1. Now the cases for level == 1 and level > 1 share some logic, this could be refactored in future. Fixes #77 --- src/nodes/rrb.rs | 7 +++++++ src/vector/mod.rs | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/nodes/rrb.rs b/src/nodes/rrb.rs index 49d81f2..0e15d4f 100644 --- a/src/nodes/rrb.rs +++ b/src/nodes/rrb.rs @@ -597,6 +597,13 @@ impl Node { // more space in existing chunks. To keep the middle dense, we // do not add it here. if !chunk.is_empty() { + if side == Left && chunk.len() < NODE_SIZE { + if let Entry::Nodes(ref mut size, _) = self.children { + if let Size::Size(value) = *size { + *size = Size::table_from_size(level, value); + } + } + } self.push_size(side, chunk.len()); self.push_child_node(side, Ref::new(Node::from_chunk(0, chunk))); } diff --git a/src/vector/mod.rs b/src/vector/mod.rs index b150ae5..98d7144 100644 --- a/src/vector/mod.rs +++ b/src/vector/mod.rs @@ -2616,6 +2616,20 @@ mod test { } } + #[test] + fn issue_77() { + let mut x = Vector::new(); + for _ in 0..44 { x.push_back(0); } + for _ in 0..20 { x.insert(0, 0); } + x.insert(1, 0); + for _ in 0..441 { x.push_back(0); } + for _ in 0..58 { x.insert(0, 0); } + x.insert(514, 0); + for _ in 0..73 { x.push_back(0); } + for _ in 0..10 { x.insert(0, 0); } + x.insert(514, 0); + } + proptest! { #[test] fn iter(ref vec in vec(i32::ANY, 0..1000)) {