oxihuman_core/
interval_query.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct Interval<V: Clone> {
10 pub lo: f64,
11 pub hi: f64,
12 pub val: V,
13}
14
15impl<V: Clone> Interval<V> {
16 pub fn new(lo: f64, hi: f64, val: V) -> Self {
18 Interval {
19 lo: lo.min(hi),
20 hi: lo.max(hi),
21 val,
22 }
23 }
24
25 pub fn overlaps(&self, qlo: f64, qhi: f64) -> bool {
27 self.lo <= qhi && self.hi >= qlo
28 }
29}
30
31#[derive(Debug, Clone)]
33struct INode<V: Clone> {
34 interval: Interval<V>,
35 max_hi: f64,
36 left: Option<Box<INode<V>>>,
37 right: Option<Box<INode<V>>>,
38}
39
40impl<V: Clone> INode<V> {
41 fn new(interval: Interval<V>) -> Box<Self> {
42 let hi = interval.hi;
43 Box::new(INode {
44 interval,
45 max_hi: hi,
46 left: None,
47 right: None,
48 })
49 }
50
51 fn update_max(&mut self) {
52 self.max_hi = self.interval.hi;
53 if let Some(l) = &self.left {
54 if l.max_hi > self.max_hi {
55 self.max_hi = l.max_hi;
56 }
57 }
58 if let Some(r) = &self.right {
59 if r.max_hi > self.max_hi {
60 self.max_hi = r.max_hi;
61 }
62 }
63 }
64
65 fn insert(node: Option<Box<INode<V>>>, interval: Interval<V>) -> Box<INode<V>> {
66 let Some(mut n) = node else {
67 return INode::new(interval);
68 };
69 let mid = (n.interval.lo + n.interval.hi) / 2.0;
70 let new_mid = (interval.lo + interval.hi) / 2.0;
71 if new_mid <= mid {
72 n.left = Some(Self::insert(n.left.take(), interval));
73 } else {
74 n.right = Some(Self::insert(n.right.take(), interval));
75 }
76 n.update_max();
77 n
78 }
79
80 fn query<'a>(&'a self, qlo: f64, qhi: f64, result: &mut Vec<&'a Interval<V>>) {
81 if self.max_hi < qlo {
82 return;
83 }
84 if let Some(l) = &self.left {
85 l.query(qlo, qhi, result);
86 }
87 if self.interval.overlaps(qlo, qhi) {
88 result.push(&self.interval);
89 }
90 if self.interval.lo <= qhi {
91 if let Some(r) = &self.right {
92 r.query(qlo, qhi, result);
93 }
94 }
95 }
96}
97
98pub struct IntervalQueryTree<V: Clone> {
100 root: Option<Box<INode<V>>>,
101 count: usize,
102}
103
104impl<V: Clone> IntervalQueryTree<V> {
105 pub fn new() -> Self {
107 IntervalQueryTree {
108 root: None,
109 count: 0,
110 }
111 }
112
113 pub fn insert(&mut self, lo: f64, hi: f64, val: V) {
115 let iv = Interval::new(lo, hi, val);
116 self.root = Some(INode::insert(self.root.take(), iv));
117 self.count += 1;
118 }
119
120 pub fn query(&self, qlo: f64, qhi: f64) -> Vec<&Interval<V>> {
122 let mut result = Vec::new();
123 if let Some(r) = &self.root {
124 r.query(qlo, qhi, &mut result);
125 }
126 result
127 }
128
129 pub fn len(&self) -> usize {
131 self.count
132 }
133
134 pub fn is_empty(&self) -> bool {
136 self.count == 0
137 }
138}
139
140impl<V: Clone> Default for IntervalQueryTree<V> {
141 fn default() -> Self {
142 Self::new()
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_insert_and_query_overlap() {
152 let mut t: IntervalQueryTree<u32> = IntervalQueryTree::new();
153 t.insert(1.0, 5.0, 1);
154 let res = t.query(3.0, 4.0);
155 assert!(!res.is_empty() );
156 }
157
158 #[test]
159 fn test_no_overlap() {
160 let mut t: IntervalQueryTree<u32> = IntervalQueryTree::new();
161 t.insert(1.0, 2.0, 1);
162 let res = t.query(5.0, 6.0);
163 assert!(res.is_empty() );
164 }
165
166 #[test]
167 fn test_len() {
168 let mut t: IntervalQueryTree<u32> = IntervalQueryTree::new();
169 t.insert(0.0, 1.0, 0);
170 t.insert(2.0, 3.0, 1);
171 assert_eq!(t.len(), 2);
172 }
173
174 #[test]
175 fn test_is_empty() {
176 let t: IntervalQueryTree<u32> = IntervalQueryTree::new();
177 assert!(t.is_empty());
178 }
179
180 #[test]
181 fn test_multiple_overlaps() {
182 let mut t: IntervalQueryTree<u32> = IntervalQueryTree::new();
183 t.insert(0.0, 10.0, 0);
184 t.insert(5.0, 15.0, 1);
185 t.insert(12.0, 20.0, 2);
186 let res = t.query(6.0, 13.0);
187 assert_eq!(res.len(), 3);
189 }
190
191 #[test]
192 fn test_point_query() {
193 let mut t: IntervalQueryTree<u32> = IntervalQueryTree::new();
194 t.insert(1.0, 5.0, 10);
195 t.insert(6.0, 9.0, 20);
196 let res = t.query(3.0, 3.0);
197 assert_eq!(res.len(), 1 );
198 }
199
200 #[test]
201 fn test_interval_overlap_method() {
202 let iv = Interval::new(1.0, 5.0, ());
203 assert!(iv.overlaps(4.0, 6.0) );
204 assert!(!iv.overlaps(6.0, 8.0) );
205 }
206
207 #[test]
208 fn test_reversed_lo_hi_normalized() {
209 let iv = Interval::new(5.0, 1.0, 42u32);
210 assert!(iv.lo < iv.hi );
211 }
212
213 #[test]
214 fn test_default() {
215 let t: IntervalQueryTree<u32> = IntervalQueryTree::default();
216 assert!(t.is_empty());
217 }
218}