Skip to content

Commit

Permalink
fix: somehow use the correct direction for Dict::get_prev/next
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexagon committed Jun 8, 2024
1 parent 41cfd24 commit 9bdace0
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/dict/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,8 +847,12 @@ pub fn dict_find_owned(
std::cmp::Ordering::Less => {
// LCP is less than prefix, an edge to slice was found
if lcp_len < prefix.remaining_bits() {
// Stop searching for the value with the first divergent bit
break Leaf::Divergence(Branch::from(ok!(key.get_bit(lcp_len))));
let mut next_branch = Branch::from(ok!(key.get_bit(lcp_len)));
if signed && stack.is_empty() && lcp_len == 0 {
next_branch = next_branch.reversed();
}

break Leaf::Divergence(next_branch);
}

// The key contains the entire prefix, but there are still some bits left.
Expand Down
104 changes: 104 additions & 0 deletions src/dict/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,110 @@ mod tests {

assert_eq!(dict.get_prev(100, true).unwrap(), Some((20, 20)));
assert_eq!(dict.get_or_prev(100, true).unwrap(), Some((20, 20)));

// All negative
let mut dict = Dict::<i32, i32>::new();
for i in -10..=-5 {
dict.set(i, i).unwrap();
}

assert_eq!(dict.get_prev(-20, true).unwrap(), None);
assert_eq!(dict.get_or_prev(-20, true).unwrap(), None);
assert_eq!(dict.get_prev(-10, true).unwrap(), None);
assert_eq!(dict.get_or_prev(-10, true).unwrap(), Some((-10, -10)));

assert_eq!(dict.get_next(-20, true).unwrap(), Some((-10, -10)));
assert_eq!(dict.get_or_next(-20, true).unwrap(), Some((-10, -10)));
assert_eq!(dict.get_next(-10, true).unwrap(), Some((-9, -9)));
assert_eq!(dict.get_or_next(-10, true).unwrap(), Some((-10, -10)));

assert_eq!(dict.get_prev(-7, true).unwrap(), Some((-8, -8)));
assert_eq!(dict.get_or_prev(-7, true).unwrap(), Some((-7, -7)));
assert_eq!(dict.get_next(-7, true).unwrap(), Some((-6, -6)));
assert_eq!(dict.get_or_next(-7, true).unwrap(), Some((-7, -7)));

assert_eq!(dict.get_prev(-5, true).unwrap(), Some((-6, -6)));
assert_eq!(dict.get_or_prev(-5, true).unwrap(), Some((-5, -5)));
assert_eq!(dict.get_prev(-4, true).unwrap(), Some((-5, -5)));
assert_eq!(dict.get_or_prev(-4, true).unwrap(), Some((-5, -5)));

assert_eq!(dict.get_next(-5, true).unwrap(), None);
assert_eq!(dict.get_or_next(-5, true).unwrap(), Some((-5, -5)));
assert_eq!(dict.get_next(-4, true).unwrap(), None);
assert_eq!(dict.get_or_next(-4, true).unwrap(), None);

assert_eq!(dict.get_next(0, true).unwrap(), None);
assert_eq!(dict.get_or_next(0, true).unwrap(), None);
assert_eq!(dict.get_next(1, true).unwrap(), None);
assert_eq!(dict.get_or_next(1, true).unwrap(), None);

// All positive
let mut dict = Dict::<i32, i32>::new();
for i in 5..=10 {
dict.set(i, i).unwrap();
}

assert_eq!(dict.get_prev(-1, true).unwrap(), None);
assert_eq!(dict.get_or_prev(-1, true).unwrap(), None);
assert_eq!(dict.get_prev(0, true).unwrap(), None);
assert_eq!(dict.get_or_prev(0, true).unwrap(), None);

assert_eq!(dict.get_next(4, true).unwrap(), Some((5, 5)));
assert_eq!(dict.get_or_next(4, true).unwrap(), Some((5, 5)));
assert_eq!(dict.get_next(5, true).unwrap(), Some((6, 6)));
assert_eq!(dict.get_or_next(5, true).unwrap(), Some((5, 5)));

assert_eq!(dict.get_prev(7, true).unwrap(), Some((6, 6)));
assert_eq!(dict.get_or_prev(7, true).unwrap(), Some((7, 7)));
assert_eq!(dict.get_next(7, true).unwrap(), Some((8, 8)));
assert_eq!(dict.get_or_next(7, true).unwrap(), Some((7, 7)));

assert_eq!(dict.get_prev(10, true).unwrap(), Some((9, 9)));
assert_eq!(dict.get_or_prev(10, true).unwrap(), Some((10, 10)));
assert_eq!(dict.get_prev(11, true).unwrap(), Some((10, 10)));
assert_eq!(dict.get_or_prev(11, true).unwrap(), Some((10, 10)));

assert_eq!(dict.get_next(10, true).unwrap(), None);
assert_eq!(dict.get_or_next(10, true).unwrap(), Some((10, 10)));
assert_eq!(dict.get_next(11, true).unwrap(), None);
assert_eq!(dict.get_or_next(11, true).unwrap(), None);

assert_eq!(dict.get_prev(20, true).unwrap(), Some((10, 10)));
assert_eq!(dict.get_or_prev(20, true).unwrap(), Some((10, 10)));
assert_eq!(dict.get_next(20, true).unwrap(), None);
assert_eq!(dict.get_or_next(20, true).unwrap(), None);

// Single positive on edge
let mut dict = Dict::<i32, i32>::new();
dict.set(0, 0).unwrap();

assert_eq!(dict.get_prev(0, true).unwrap(), None);
assert_eq!(dict.get_or_prev(0, true).unwrap(), Some((0, 0)));
assert_eq!(dict.get_next(-1, true).unwrap(), Some((0, 0)));
assert_eq!(dict.get_or_next(-1, true).unwrap(), Some((0, 0)));

// Single negative on edge
let mut dict = Dict::<i32, i32>::new();
dict.set(-1, -1).unwrap();

assert_eq!(dict.get_prev(0, true).unwrap(), Some((-1, -1)));
assert_eq!(dict.get_or_prev(0, true).unwrap(), Some((-1, -1)));
assert_eq!(dict.get_next(-1, true).unwrap(), None);
assert_eq!(dict.get_or_next(-1, true).unwrap(), Some((-1, -1)));
}

#[test]
fn get_signed_next() {
let cell = Boc::decode_base64("te6ccgEBCwEAaAACAskDAQIBIAQCAgHOCAgCASAEBAIBIAUFAgEgBgYCASAHBwIBIAgIAgEgCQkBAwDgCgBoQgBAJTazb04k/ooV5DE4d+ixdwixajACdzkuZVb6ymgnqyHc1lAAAAAAAAAAAAAAAAAAAA==").unwrap();
let dict = Dict::<i16, Cell>::from_raw(Some(cell));

for item in dict.iter() {
let (key, cell) = item.unwrap();
println!("{key}, {}", cell.display_root());
}

let res = dict.get_next(-1, true).unwrap();
println!("{res:?}");
}

#[test]
Expand Down

0 comments on commit 9bdace0

Please sign in to comment.