range_filters/
x_fast_trie.rs

1use crate::Key;
2use crate::binary_search_tree::BinarySearchTreeGroup;
3use dashmap::DashMap;
4use std::fmt;
5use std::sync::{Arc, RwLock, Weak};
6
7pub const ROOT_KEY: Key = 67;
8
9#[derive(Debug)]
10pub struct XFastTrie {
11    pub levels: Vec<XFastLevel>,
12    // representatives
13    // pub reps: HashMap<Key, Arc<RwLock<RepNode>>>,
14    pub head_rep: Option<Arc<RwLock<RepNode>>>,
15    pub tail_rep: Option<Arc<RwLock<RepNode>>>,
16
17    // no. of levels = no. of bits in the keys
18    pub no_levels: usize,
19}
20
21#[derive(Debug, Default, Clone)]
22pub struct XFastLevel {
23    pub table: DashMap<Key, XFastValue>,
24}
25
26#[derive(Debug, Default, Clone)]
27pub struct XFastValue {
28    pub left_child: Option<Arc<RwLock<XFastValue>>>,
29    pub right_child: Option<Arc<RwLock<XFastValue>>>,
30
31    // pub representative: Option<Arc<RwLock<RepNode>>>
32    pub min_rep: Option<Arc<RwLock<RepNode>>>,
33    pub max_rep: Option<Arc<RwLock<RepNode>>>,
34}
35
36#[derive(Debug, Default, Clone)]
37pub struct RepNode {
38    pub key: Key,
39    pub left: Option<Weak<RwLock<RepNode>>>,
40    pub right: Option<Weak<RwLock<RepNode>>>,
41    pub bst_group: Option<Arc<RwLock<BinarySearchTreeGroup>>>,
42}
43
44impl XFastTrie {
45    pub fn new(no_levels: usize) -> Self {
46        let mut levels = Vec::with_capacity(no_levels + 1);
47        let root = XFastLevel::default();
48
49        // insert the root level
50        // use a random key for the root level
51        root.table.insert(ROOT_KEY, XFastValue::default());
52        levels.push(root);
53        for _ in 1..=no_levels {
54            let new_level = XFastLevel::default();
55            levels.push(new_level);
56        }
57        Self {
58            levels,
59            head_rep: None,
60            tail_rep: None,
61            no_levels: no_levels,
62        }
63    }
64
65    pub fn len(&self) -> usize {
66        let mut count = 0;
67        if let Some(head) = &self.head_rep {
68            let mut current = Some(head.clone());
69            while let Some(node) = current {
70                count += 1;
71                if let Ok(n) = node.read() {
72                    current = n.right.as_ref().and_then(|w| w.upgrade());
73                } else {
74                    break;
75                }
76            }
77        }
78        count
79    }
80
81    // find length of longest prefix of key
82    fn find_longest_prefix_length(&self, key: Key) -> usize {
83        // check if tree is empty
84        if self.levels[1].table.is_empty() {
85            return 0;
86        }
87
88        let mut low = 0;
89        let mut high = self.no_levels;
90
91        while low < high {
92            let mid = (low + high + 1) / 2;
93            let prefix = key >> (self.no_levels - mid);
94            if self.levels[mid as usize].table.contains_key(&prefix) {
95                // println!("prefix: {} found at level {}", prefix, mid);
96                low = mid;
97            } else {
98                high = mid - 1;
99                // println!("prefix: {} not found at level {}, searching in level {}", prefix, mid, high);
100            }
101        }
102
103        low as usize
104    }
105
106    pub fn predecessor(&self, key: Key) -> Option<Arc<RwLock<RepNode>>> {
107        // empty trie
108        if self.levels[1].table.is_empty() {
109            return None;
110        }
111
112        let longest_prefix_length = self.find_longest_prefix_length(key);
113
114        if longest_prefix_length == 0 && key >> (self.no_levels - 1) == 1 {
115            // find the max representative of the root level
116            if let Some(root_value) = self.levels[1].table.get(&0) {
117                return Some(root_value.max_rep.clone()?);
118            }
119        } else if longest_prefix_length == 0 && key >> (self.no_levels - 1) == 0 {
120            return None;
121        }
122
123        let prefix = key >> (self.no_levels - longest_prefix_length);
124
125        let x_fast_value = self.levels[longest_prefix_length as usize]
126            .table
127            .get(&prefix)?;
128
129        if let Some(representative) = &x_fast_value.max_rep {
130            if let Ok(rep) = representative.read() {
131                if rep.key <= key {
132                    return Some(representative.clone());
133                }
134            }
135        }
136        if let Some(representative) = &x_fast_value.min_rep {
137            if let Ok(rep) = representative.read() {
138                if rep.key <= key {
139                    return Some(representative.clone());
140                } else {
141                    // need to find predecessor by traversing left
142                    if let Some(left_weak) = &rep.left {
143                        return left_weak.upgrade();
144                    } else {
145                        return None;
146                    }
147                }
148            }
149        }
150
151        None
152    }
153
154    pub fn successor(&self, key: Key) -> Option<Arc<RwLock<RepNode>>> {
155        // empty trie
156        if self.levels[1].table.is_empty() {
157            return None;
158        }
159
160        let longest_prefix_length = self.find_longest_prefix_length(key);
161
162        if longest_prefix_length == 0 && key >> (self.no_levels - 1) == 1 {
163            return None;
164        } else if longest_prefix_length == 0 && key >> (self.no_levels - 1) == 0 {
165            // find the min representative of the root level
166            if let Some(root_value) = self.levels[1].table.get(&1) {
167                return Some(root_value.min_rep.clone()?);
168            }
169        }
170
171        let prefix = key >> (self.no_levels - longest_prefix_length);
172
173        let x_fast_value = self.levels[longest_prefix_length as usize]
174            .table
175            .get(&prefix)?;
176
177        if let Some(representative) = &x_fast_value.min_rep {
178            if let Ok(rep) = representative.read() {
179                if rep.key >= key {
180                    return Some(representative.clone());
181                }
182            }
183        }
184
185        if let Some(representative) = &x_fast_value.max_rep {
186            if let Ok(rep) = representative.read() {
187                if rep.key >= key {
188                    return Some(representative.clone());
189                } else {
190                    // need to find successor by traversing right
191                    if let Some(right_weak) = &rep.right {
192                        return right_weak.upgrade();
193                    } else {
194                        return None;
195                    }
196                }
197            }
198        }
199
200        None
201    }
202
203    //  TODO: support variable length keys
204    pub fn lookup(&self, key: Key) -> Option<Arc<RwLock<RepNode>>> {
205        let x_fast_value = self.levels[self.no_levels as usize].table.get(&key)?;
206        if let Some(min_rep) = &x_fast_value.min_rep {
207            if let Ok(min_rep_guard) = min_rep.read() {
208                assert_eq!(min_rep_guard.key, key);
209            }
210        }
211        x_fast_value.min_rep.clone()
212    }
213
214    // insert a key into the x-fast trie
215    pub fn insert(&mut self, key: Key) {
216        // step 1: find the longest prefix length
217        let longest_prefix_length = self.find_longest_prefix_length(key);
218
219        // println!("longest_prefix_length: {}", longest_prefix_length);
220
221        let predecessor = self.predecessor(key);
222        let successor = self.successor(key);
223
224        // step 2: create representative
225        let representative = Arc::new(RwLock::new(RepNode {
226            key,
227            left: None,
228            right: None,
229            bst_group: None,
230        }));
231
232        // step 3: create child prefixes from longest_prefix_length+1 to no_levels
233        for prefix_length in (longest_prefix_length + 1)..=self.no_levels {
234            let prefix = key >> (self.no_levels - prefix_length);
235            let new_x_fast_value = XFastValue {
236                left_child: None,
237                right_child: None,
238                min_rep: Some(representative.clone()),
239                max_rep: Some(representative.clone()),
240            };
241            self.levels[prefix_length as usize]
242                .table
243                .insert(prefix, new_x_fast_value.clone());
244
245            // update parent's child pointers
246            if prefix_length > 1 {
247                let parent_prefix = key >> (self.no_levels - (prefix_length - 1));
248                if let Some(mut parent_value) = self.levels[(prefix_length - 1) as usize]
249                    .table
250                    .get_mut(&parent_prefix)
251                {
252                    let bit = (key >> (self.no_levels - prefix_length)) & 1;
253                    if bit == 0 {
254                        parent_value.left_child =
255                            Some(Arc::new(RwLock::new(new_x_fast_value.clone())));
256                    } else {
257                        parent_value.right_child =
258                            Some(Arc::new(RwLock::new(new_x_fast_value.clone())));
259                    }
260                }
261            } else {
262                // update root level child pointers
263                if let Some(mut root_value) = self.levels[0].table.get_mut(&ROOT_KEY) {
264                    let bit = key >> (self.no_levels - prefix_length);
265                    if bit == 0 {
266                        root_value.left_child =
267                            Some(Arc::new(RwLock::new(new_x_fast_value.clone())));
268                    } else {
269                        root_value.right_child =
270                            Some(Arc::new(RwLock::new(new_x_fast_value.clone())));
271                    }
272                }
273            }
274        }
275
276        // step 4: update all prefixes' parents' min and max representatives
277        if longest_prefix_length > 0 {
278            for prefix_length in (1..=self.no_levels - 1).rev() {
279                let prefix = key >> (self.no_levels - prefix_length);
280                let mut x_fast_value = self.levels[prefix_length as usize]
281                    .table
282                    .get_mut(&prefix)
283                    .unwrap();
284
285                let rep_key = representative.read().unwrap().key;
286
287                let should_update_min = x_fast_value
288                    .min_rep
289                    .as_ref()
290                    .and_then(|m| m.read().ok())
291                    .map(|m| rep_key < m.key)
292                    .unwrap_or(false);
293
294                let should_update_max = x_fast_value
295                    .max_rep
296                    .as_ref()
297                    .and_then(|m| m.read().ok())
298                    .map(|m| rep_key > m.key)
299                    .unwrap_or(false);
300
301                if should_update_min {
302                    x_fast_value.min_rep = Some(representative.clone());
303                }
304                if should_update_max {
305                    x_fast_value.max_rep = Some(representative.clone());
306                }
307            }
308        }
309
310        // step 5: update linked list pointers
311        // update predecessor's right pointer
312        if let Some(pred) = &predecessor {
313            if let Ok(mut pred_guard) = pred.write() {
314                pred_guard.right = Some(Arc::downgrade(&representative));
315            }
316        }
317
318        // update successor's left pointer
319        if let Some(succ) = &successor {
320            if let Ok(mut succ_guard) = succ.write() {
321                succ_guard.left = Some(Arc::downgrade(&representative));
322            }
323        }
324
325        // set representative's pointers
326        if let Ok(mut rep_guard) = representative.write() {
327            rep_guard.left = predecessor.as_ref().map(|p| Arc::downgrade(p));
328            rep_guard.right = successor.map(|s| Arc::downgrade(&s));
329            rep_guard.bst_group = Some(Arc::new(RwLock::new(BinarySearchTreeGroup::default())));
330        }
331
332        // step 6: update head and tail representatives
333        let should_update_head = if let Some(head_rep) = &self.head_rep {
334            if let Ok(head) = head_rep.read() {
335                head.key > key
336            } else {
337                false
338            }
339        } else {
340            // first key being inserted
341            true
342        };
343
344        if should_update_head {
345            self.head_rep = Some(representative.clone());
346        }
347
348        let should_update_tail = if let Some(tail_rep) = &self.tail_rep {
349            if let Ok(tail) = tail_rep.read() {
350                tail.key < key
351            } else {
352                false
353            }
354        } else {
355            // first key being inserted
356            true
357        };
358
359        if should_update_tail {
360            self.tail_rep = Some(representative.clone());
361        }
362    }
363
364    pub fn pretty_print(&self) {
365        print!("{}", self);
366    }
367
368    fn format_linked_list(start: &Arc<RwLock<RepNode>>, f: &mut fmt::Formatter) -> fmt::Result {
369        if let Ok(node) = start.read() {
370            write!(f, "  {} ", node.key)?;
371
372            if let Some(right_weak) = &node.right {
373                if let Some(right_arc) = right_weak.upgrade() {
374                    write!(f, "→ ")?;
375                    Self::format_linked_list_helper(&right_arc, f)?;
376                }
377            }
378            writeln!(f)?;
379        }
380        Ok(())
381    }
382
383    fn format_linked_list_helper(
384        node: &Arc<RwLock<RepNode>>,
385        f: &mut fmt::Formatter,
386    ) -> fmt::Result {
387        if let Ok(node_guard) = node.read() {
388            write!(f, "{} ", node_guard.key)?;
389
390            if let Some(right_weak) = &node_guard.right {
391                if let Some(right_arc) = right_weak.upgrade() {
392                    write!(f, "→ ")?;
393                    Self::format_linked_list_helper(&right_arc, f)?;
394                }
395            }
396        }
397        Ok(())
398    }
399}
400
401impl fmt::Display for XFastTrie {
402    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403        writeln!(f, "\n=== X-Fast Trie Structure ===")?;
404
405        writeln!(f, "\nRepresentatives (Linked List):")?;
406        if let Some(head) = &self.head_rep {
407            Self::format_linked_list(head, f)?;
408        } else {
409            writeln!(f, "  Empty")?;
410        }
411
412        writeln!(f, "\nTrie Levels:")?;
413        for (level, x_fast_level) in self.levels.iter().enumerate() {
414            if !x_fast_level.table.is_empty() {
415                writeln!(f, "  Level {} (prefix length {}):", level, level)?;
416                let mut entries: Vec<_> = x_fast_level.table.iter().collect();
417                entries.sort_by_key(|entry| *entry.key());
418
419                for entry in entries {
420                    let prefix = entry.key();
421                    let value = entry.value();
422                    let prefix_str = if level == 0 {
423                        "ε".to_string()
424                    } else {
425                        format!("{:0width$b}", prefix, width = level)
426                    };
427
428                    write!(f, "    {}: ", prefix_str)?;
429
430                    if let Some(min_rep) = &value.min_rep {
431                        if let Ok(rep_guard) = min_rep.read() {
432                            write!(f, "min_rep→{} ", rep_guard.key)?;
433                        }
434                    }
435                    if let Some(max_rep) = &value.max_rep {
436                        if let Ok(rep_guard) = max_rep.read() {
437                            write!(f, "max_rep→{} ", rep_guard.key)?;
438                        }
439                    }
440                    if value.left_child.is_some() {
441                        write!(f, "L ")?;
442                    }
443                    if value.right_child.is_some() {
444                        write!(f, "R ")?;
445                    }
446
447                    writeln!(f)?;
448                }
449            }
450        }
451
452        writeln!(f, "\n=== End Structure ===\n")?;
453        Ok(())
454    }
455}
456
457#[cfg(test)]
458mod tests {
459    use super::*;
460
461    #[test]
462    fn test_single_insert() {
463        let mut trie = XFastTrie::new(8);
464        trie.insert(42);
465
466        // verify head and tail are set
467        assert!(trie.head_rep.is_some());
468        assert!(trie.tail_rep.is_some());
469
470        if let Some(head) = &trie.head_rep {
471            if let Ok(head_guard) = head.read() {
472                assert_eq!(head_guard.key, 42);
473            }
474        }
475    }
476
477    #[test]
478    fn test_multiple_inserts() {
479        let mut trie = XFastTrie::new(8);
480        let keys = vec![10, 5, 15, 3, 12];
481
482        for key in &keys {
483            trie.insert(*key);
484        }
485
486        // verify head is smallest, tail is largest
487        if let Some(head) = &trie.head_rep {
488            if let Ok(head_guard) = head.read() {
489                assert_eq!(head_guard.key, 3);
490            }
491        }
492
493        if let Some(tail) = &trie.tail_rep {
494            if let Ok(tail_guard) = tail.read() {
495                assert_eq!(tail_guard.key, 15);
496            }
497        }
498    }
499
500    #[test]
501    fn test_predecessor() {
502        let mut trie = XFastTrie::new(8);
503        let keys = vec![10, 20, 30, 40];
504
505        for key in &keys {
506            trie.insert(*key);
507        }
508
509        // test predecessor queries
510        if let Some(pred) = trie.predecessor(25) {
511            if let Ok(pred_guard) = pred.read() {
512                assert_eq!(pred_guard.key, 20);
513            }
514        }
515
516        if let Some(pred) = trie.predecessor(35) {
517            if let Ok(pred_guard) = pred.read() {
518                assert_eq!(pred_guard.key, 30);
519            }
520        }
521
522        // test exact match
523        if let Some(pred) = trie.predecessor(30) {
524            if let Ok(pred_guard) = pred.read() {
525                assert_eq!(pred_guard.key, 30);
526            }
527        }
528    }
529
530    #[test]
531    fn test_successor() {
532        let mut trie = XFastTrie::new(8);
533        let keys = vec![10, 20, 30, 40];
534
535        for key in &keys {
536            trie.insert(*key);
537        }
538
539        // test successor queries
540        if let Some(succ) = trie.successor(25) {
541            if let Ok(succ_guard) = succ.read() {
542                assert_eq!(succ_guard.key, 30);
543            }
544        }
545
546        if let Some(succ) = trie.successor(15) {
547            if let Ok(succ_guard) = succ.read() {
548                assert_eq!(succ_guard.key, 20);
549            }
550        }
551    }
552
553    #[test]
554    fn test_lookup() {
555        let mut trie = XFastTrie::new(8);
556        let keys = vec![10, 5, 15, 3, 12];
557
558        for key in &keys {
559            trie.insert(*key);
560        }
561
562        for key in &keys {
563            assert!(trie.lookup(*key).is_some());
564            if let Some(lookup) = trie.lookup(*key) {
565                if let Ok(lookup_guard) = lookup.read() {
566                    assert_eq!(lookup_guard.key, *key);
567                }
568            }
569        }
570    }
571
572    #[test]
573    fn test_edge_cases() {
574        let mut trie = XFastTrie::new(8);
575
576        // predecessor of empty trie
577        assert!(trie.predecessor(10).is_none());
578
579        // insert single key
580        trie.insert(50);
581
582        // predecessor of smaller value
583        assert!(trie.predecessor(10).is_none());
584
585        // successor of larger value
586        assert!(trie.successor(100).is_none());
587    }
588
589    // helper function to verify min/max representatives at a given level and prefix
590    fn verify_min_max(
591        trie: &XFastTrie,
592        level: usize,
593        prefix: Key,
594        expected_min: Key,
595        expected_max: Key,
596    ) {
597        let value = trie.levels[level]
598            .table
599            .get(&prefix)
600            .expect(&format!("prefix {} not found at level {}", prefix, level));
601
602        if let Some(min_rep) = &value.min_rep {
603            if let Ok(rep_guard) = min_rep.read() {
604                assert_eq!(
605                    rep_guard.key, expected_min,
606                    "Level {}, prefix {}: expected min_rep={}, got {}",
607                    level, prefix, expected_min, rep_guard.key
608                );
609            }
610        } else {
611            panic!("Level {}, prefix {}: min_rep is None", level, prefix);
612        }
613
614        if let Some(max_rep) = &value.max_rep {
615            if let Ok(rep_guard) = max_rep.read() {
616                assert_eq!(
617                    rep_guard.key, expected_max,
618                    "Level {}, prefix {}: expected max_rep={}, got {}",
619                    level, prefix, expected_max, rep_guard.key
620                );
621            }
622        } else {
623            panic!("Level {}, prefix {}: max_rep is None", level, prefix);
624        }
625    }
626
627    #[test]
628    fn test_min_max_values_comprehensive() {
629        let mut trie = XFastTrie::new(8);
630        let keys = vec![10, 5, 15, 3, 12];
631
632        for key in &keys {
633            trie.insert(*key);
634        }
635
636        // Level 1
637        verify_min_max(&trie, 1, 0b0, 3, 15);
638
639        // Level 2
640        verify_min_max(&trie, 2, 0b00, 3, 15);
641
642        // Level 3
643        verify_min_max(&trie, 3, 0b000, 3, 15);
644
645        // Level 4
646        verify_min_max(&trie, 4, 0b0000, 3, 15);
647
648        // Level 5
649        verify_min_max(&trie, 5, 0b00000, 3, 5);
650        verify_min_max(&trie, 5, 0b00001, 10, 15);
651
652        // Level 6
653        verify_min_max(&trie, 6, 0b000000, 3, 3);
654        verify_min_max(&trie, 6, 0b000001, 5, 5);
655        verify_min_max(&trie, 6, 0b000010, 10, 10);
656        verify_min_max(&trie, 6, 0b000011, 12, 15);
657
658        // Level 7
659        verify_min_max(&trie, 7, 0b0000001, 3, 3);
660        verify_min_max(&trie, 7, 0b0000010, 5, 5);
661        verify_min_max(&trie, 7, 0b0000101, 10, 10);
662        verify_min_max(&trie, 7, 0b0000110, 12, 12);
663        verify_min_max(&trie, 7, 0b0000111, 15, 15);
664
665        // Level 8 (leaf level)
666        verify_min_max(&trie, 8, 0b00000011, 3, 3);
667        verify_min_max(&trie, 8, 0b00000101, 5, 5);
668        verify_min_max(&trie, 8, 0b00001010, 10, 10);
669        verify_min_max(&trie, 8, 0b00001100, 12, 12);
670        verify_min_max(&trie, 8, 0b00001111, 15, 15);
671    }
672
673    #[test]
674    fn test_min_max_single_key() {
675        let mut trie = XFastTrie::new(8);
676        trie.insert(42); // 42 = 0b00101010
677
678        // all nodes should have min_rep=42 and max_rep=42
679        // Level 1: prefix 0
680        verify_min_max(&trie, 1, 0b0, 42, 42);
681
682        // Level 2: prefix 00
683        verify_min_max(&trie, 2, 0b00, 42, 42);
684
685        // Level 3: prefix 001
686        verify_min_max(&trie, 3, 0b001, 42, 42);
687
688        // Level 4: prefix 0010
689        verify_min_max(&trie, 4, 0b0010, 42, 42);
690
691        // Level 5: prefix 00101
692        verify_min_max(&trie, 5, 0b00101, 42, 42);
693
694        // Level 6: prefix 001010
695        verify_min_max(&trie, 6, 0b001010, 42, 42);
696
697        // Level 7: prefix 0010101
698        verify_min_max(&trie, 7, 0b0010101, 42, 42);
699
700        // Level 8: prefix 00101010
701        verify_min_max(&trie, 8, 0b00101010, 42, 42);
702    }
703
704    #[test]
705    fn test_min_max_adjacent_keys() {
706        let mut trie = XFastTrie::new(8);
707        trie.insert(8); // 0b00001000
708        trie.insert(9); // 0b00001001
709
710        // these keys differ only in the last bit, so they share prefix up to level 7
711        verify_min_max(&trie, 1, 0b0, 8, 9);
712        verify_min_max(&trie, 2, 0b00, 8, 9);
713        verify_min_max(&trie, 3, 0b000, 8, 9);
714        verify_min_max(&trie, 4, 0b0000, 8, 9);
715        verify_min_max(&trie, 5, 0b00001, 8, 9);
716        verify_min_max(&trie, 6, 0b000010, 8, 9);
717        verify_min_max(&trie, 7, 0b0000100, 8, 9);
718
719        // leaf level - each key has its own entry
720        verify_min_max(&trie, 8, 0b00001000, 8, 8);
721        verify_min_max(&trie, 8, 0b00001001, 9, 9);
722    }
723
724    #[test]
725    fn test_min_max_sequential_insertion() {
726        let mut trie = XFastTrie::new(8);
727
728        // insert in increasing order
729        for key in [1, 2, 3, 4, 5] {
730            trie.insert(key);
731        }
732
733        // verify that min is always 1 and max is always 5 at top levels
734        // Level 1: all keys share prefix 0
735        verify_min_max(&trie, 1, 0b0, 1, 5);
736
737        // Level 8: each leaf has equal min and max
738        verify_min_max(&trie, 8, 0b00000001, 1, 1);
739        verify_min_max(&trie, 8, 0b00000010, 2, 2);
740        verify_min_max(&trie, 8, 0b00000011, 3, 3);
741        verify_min_max(&trie, 8, 0b00000100, 4, 4);
742        verify_min_max(&trie, 8, 0b00000101, 5, 5);
743    }
744
745    #[test]
746    fn test_min_max_reverse_insertion() {
747        let mut trie = XFastTrie::new(8);
748
749        // insert in decreasing order
750        for key in [5, 4, 3, 2, 1] {
751            trie.insert(key);
752        }
753
754        // min/max should be the same regardless of insertion order
755        verify_min_max(&trie, 1, 0b0, 1, 5);
756
757        // leaf level
758        verify_min_max(&trie, 8, 0b00000001, 1, 1);
759        verify_min_max(&trie, 8, 0b00000101, 5, 5);
760    }
761
762    #[test]
763    fn test_min_max_sparse_keys() {
764        let mut trie = XFastTrie::new(16);
765
766        // insert sparse keys with large gaps
767        trie.insert(1); // 0b0000000000000001
768        trie.insert(128); // 0b0000000010000000
769        trie.insert(255); // 0b0000000011111111
770        trie.insert(64); // 0b0000000001000000
771
772        // at level 1, keys all share prefix 0
773        verify_min_max(&trie, 1, 0b0, 1, 255);
774
775        // at level 9, keys diverge
776        verify_min_max(&trie, 9, 0b000000000, 1, 64);
777        verify_min_max(&trie, 9, 0b000000001, 128, 255);
778
779        // leaf level - each key has its own entry
780        verify_min_max(&trie, 16, 0b0000000000000001, 1, 1);
781        verify_min_max(&trie, 16, 0b0000000001000000, 64, 64);
782        verify_min_max(&trie, 16, 0b0000000010000000, 128, 128);
783        verify_min_max(&trie, 16, 0b0000000011111111, 255, 255);
784    }
785}