From 9bdace0396b3f4e7a24fb7808ebc184053f6ae78 Mon Sep 17 00:00:00 2001 From: Ivan Kalinin Date: Sat, 8 Jun 2024 22:19:51 +0200 Subject: [PATCH] fix: somehow use the correct direction for `Dict::get_prev/next` --- src/dict/mod.rs | 8 +++- src/dict/typed.rs | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/dict/mod.rs b/src/dict/mod.rs index b75880d3..b0d7c8be 100644 --- a/src/dict/mod.rs +++ b/src/dict/mod.rs @@ -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. diff --git a/src/dict/typed.rs b/src/dict/typed.rs index ea22dc84..dd7b873f 100644 --- a/src/dict/typed.rs +++ b/src/dict/typed.rs @@ -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::::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::::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::::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::::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::::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]