1use std::mem::take;
2
3use crate::timestamp::Timestamp;
4
5const SPLIT_COUNT: usize = 128;
6const BALANCE_THRESHOLD: usize = 3;
8
9pub struct SelfTimeTree<T> {
10 entries: Vec<SelfTimeEntry<T>>,
11 children: Option<Box<SelfTimeChildren<T>>>,
12 count: usize,
13}
14
15struct SelfTimeEntry<T> {
16 start: Timestamp,
17 end: Timestamp,
18 item: T,
19}
20
21struct SelfTimeChildren<T> {
22 left: SelfTimeTree<T>,
24 split_point: Timestamp,
25 right: SelfTimeTree<T>,
27 spanning_entries: usize,
29}
30
31impl<T> Default for SelfTimeTree<T> {
32 fn default() -> Self {
33 Self {
34 entries: Vec::new(),
35 children: None,
36 count: 0,
37 }
38 }
39}
40
41impl<T> SelfTimeTree<T> {
42 pub fn new() -> Self {
43 Self::default()
44 }
45
46 pub fn len(&self) -> usize {
47 self.count
48 }
49
50 pub fn insert(&mut self, start: Timestamp, end: Timestamp, item: T) {
51 self.count += 1;
52 self.entries.push(SelfTimeEntry { start, end, item });
53 self.check_for_split();
54 }
55
56 fn insert_without_check(&mut self, start: Timestamp, end: Timestamp, item: T) {
57 self.count += 1;
58 self.entries.push(SelfTimeEntry { start, end, item });
59 }
60
61 fn check_for_split(&mut self) {
62 if self.entries.len() >= SPLIT_COUNT {
63 let spanning_entries = if let Some(children) = &mut self.children {
64 children.spanning_entries
65 } else {
66 0
67 };
68 if self.entries.len() - spanning_entries >= SPLIT_COUNT {
69 self.split();
70 }
71 }
72 }
73
74 pub fn optimize(&mut self) {
75 if self.children.is_some() {
76 self.distribute_entries();
77 self.rebalance();
78 let children = self.children.as_mut().unwrap();
79 children.left.optimize();
80 children.right.optimize();
81 }
82 self.entries.shrink_to_fit();
83 }
84
85 fn split(&mut self) {
86 debug_assert!(!self.entries.is_empty());
87 self.distribute_entries();
88 self.rebalance();
89 }
90
91 fn distribute_entries(&mut self) {
92 if self.children.is_none() {
93 let (start, end) = self
94 .entries
95 .iter()
96 .fold((Timestamp::MAX, Timestamp::ZERO), |(lo, hi), e| {
97 (lo.min(e.start), hi.max(e.end))
98 });
99 let middle = (start + end) / 2;
100 self.children = Some(Box::new(SelfTimeChildren {
103 left: SelfTimeTree {
104 entries: Vec::with_capacity(SPLIT_COUNT / 2),
105 ..SelfTimeTree::default()
106 },
107 split_point: middle,
108 right: SelfTimeTree {
109 entries: Vec::with_capacity(SPLIT_COUNT / 2),
110 ..SelfTimeTree::default()
111 },
112 spanning_entries: 0,
113 }));
114 }
115 let Some(children) = &mut self.children else {
116 unreachable!();
117 };
118 let mut i = children.spanning_entries;
119 while i < self.entries.len() {
120 let SelfTimeEntry { start, end, .. } = self.entries[i];
121 if end <= children.split_point {
122 let SelfTimeEntry { start, end, item } = self.entries.swap_remove(i);
123 children.left.insert_without_check(start, end, item);
124 } else if start >= children.split_point {
125 let SelfTimeEntry { start, end, item } = self.entries.swap_remove(i);
126 children.right.insert_without_check(start, end, item);
127 } else {
128 self.entries.swap(i, children.spanning_entries);
129 children.spanning_entries += 1;
130 i += 1;
131 }
132 }
133 children.left.check_for_split();
134 children.right.check_for_split();
135 }
136
137 fn rebalance(&mut self) {
138 if let Some(box SelfTimeChildren {
139 left,
140 split_point,
141 right,
142 spanning_entries,
143 }) = &mut self.children
144 {
145 let SelfTimeTree {
146 count: left_count,
147 children: left_children,
148 entries: left_entries,
149 } = left;
150 let SelfTimeTree {
151 count: right_count,
152 children: right_children,
153 entries: right_entries,
154 } = right;
155 if *left_count > *right_count * BALANCE_THRESHOLD + *spanning_entries {
156 if let Some(box SelfTimeChildren {
163 left: left_left,
164 split_point: left_split_point,
165 right: left_right,
166 spanning_entries: _,
167 }) = left_children
168 {
169 *right = Self {
170 count: left_right.count + right.count,
171 entries: Vec::new(),
172 children: Some(Box::new(SelfTimeChildren {
173 left: take(left_right),
174 split_point: *split_point,
175 right: take(right),
176 spanning_entries: 0,
177 })),
178 };
179 *split_point = *left_split_point;
180 self.entries.append(left_entries);
181 *left = take(left_left);
182 *spanning_entries = 0;
183 self.distribute_entries();
184 }
185 } else if *right_count > *left_count * BALANCE_THRESHOLD + *spanning_entries {
186 if let Some(box SelfTimeChildren {
193 left: right_left,
194 split_point: right_split_point,
195 right: right_right,
196 spanning_entries: _,
197 }) = right_children
198 {
199 *left = Self {
200 count: left.count + right_left.count,
201 entries: Vec::new(),
202 children: Some(Box::new(SelfTimeChildren {
203 left: take(left),
204 split_point: *split_point,
205 right: take(right_left),
206 spanning_entries: 0,
207 })),
208 };
209 *split_point = *right_split_point;
210 self.entries.append(right_entries);
211 *right = take(right_right);
212 *spanning_entries = 0;
213 self.distribute_entries();
214 }
215 }
216 }
217 }
218
219 #[cfg(test)]
220 pub fn lookup_range_count(&self, start: Timestamp, end: Timestamp) -> Timestamp {
221 let mut total_count = Timestamp::ZERO;
222 for entry in &self.entries {
223 if entry.start <= end && entry.end >= start {
224 let start = std::cmp::max(entry.start, start);
225 let end = std::cmp::min(entry.end, end);
226 let span = end - start;
227 total_count += span;
228 }
229 }
230 if let Some(children) = &self.children {
231 if start <= children.split_point {
232 total_count += children.left.lookup_range_count(start, end);
233 }
234 if end >= children.split_point {
235 total_count += children.right.lookup_range_count(start, end);
236 }
237 }
238 total_count
239 }
240
241 pub fn lookup_range_corrected_time(&self, start: Timestamp, end: Timestamp) -> Timestamp {
242 #[derive(PartialEq, Eq, PartialOrd, Ord)]
243 enum Change {
244 Start,
245 End,
246 }
247 let mut current_count = 0;
248 let mut changes = Vec::new();
249 self.for_each_in_range(start, end, &mut |s, e, _| {
250 if s <= start {
251 current_count += 1;
252 } else {
253 changes.push((s, Change::Start));
254 }
255 if e < end {
256 changes.push((e, Change::End));
257 }
258 });
259
260 if changes.is_empty() {
263 if current_count == 0 {
264 return Timestamp::ZERO;
265 }
266 return Timestamp::from_value(*(end - start) / current_count);
267 }
268
269 changes.sort_unstable();
270 let mut factor_times_1000 = 0u64;
271 let mut current_ts = start;
272 for (ts, change) in changes {
273 if current_ts < ts {
274 let time_diff = ts - current_ts;
276 factor_times_1000 += *time_diff * 1000 / current_count;
277 current_ts = ts;
278 }
279 match change {
280 Change::Start => current_count += 1,
281 Change::End => current_count -= 1,
282 }
283 }
284 if current_ts < end {
285 let time_diff = end - current_ts;
286 factor_times_1000 += *time_diff * 1000 / current_count;
287 }
288 Timestamp::from_value(factor_times_1000 / 1000)
289 }
290
291 pub fn for_each_in_range(
292 &self,
293 start: Timestamp,
294 end: Timestamp,
295 f: &mut impl FnMut(Timestamp, Timestamp, &T),
296 ) {
297 for entry in &self.entries {
298 if entry.start <= end && entry.end >= start {
299 f(entry.start, entry.end, &entry.item);
300 }
301 }
302 if let Some(children) = &self.children {
303 if start <= children.split_point {
304 children.left.for_each_in_range(start, end, f);
305 }
306 if end >= children.split_point {
307 children.right.for_each_in_range(start, end, f);
308 }
309 }
310 }
311
312 pub fn for_each_in_range_optimize(
313 &mut self,
314 start: Timestamp,
315 end: Timestamp,
316 f: &mut impl FnMut(Timestamp, Timestamp, &T),
317 ) {
318 if self.children.is_some() {
319 self.distribute_entries();
320 self.rebalance();
321 }
322 for entry in &self.entries {
323 if entry.start <= end && entry.end >= start {
324 f(entry.start, entry.end, &entry.item);
325 }
326 }
327 if let Some(children) = &mut self.children {
328 if start <= children.split_point {
329 children.left.for_each_in_range_optimize(start, end, f);
330 }
331 if end >= children.split_point {
332 children.right.for_each_in_range_optimize(start, end, f);
333 }
334 }
335 }
336}
337
338#[cfg(test)]
339mod tests {
340 use super::*;
341
342 fn print_tree<T>(tree: &SelfTimeTree<T>, indent: usize) {
343 if let Some(children) = &tree.children {
344 println!(
345 "{}{} items (split at {}, {} overlapping, {} total)",
346 " ".repeat(indent),
347 tree.entries.len(),
348 children.split_point,
349 children.spanning_entries,
350 tree.count
351 );
352 print_tree(&children.left, indent + 2);
353 print_tree(&children.right, indent + 2);
354 } else {
355 println!(
356 "{}{} items ({} total)",
357 " ".repeat(indent),
358 tree.entries.len(),
359 tree.count
360 );
361 }
362 }
363
364 fn assert_balanced<T>(tree: &SelfTimeTree<T>) {
365 if let Some(children) = &tree.children {
366 let l = children.left.count;
367 let r = children.right.count;
368 let s = children.spanning_entries;
369 if (l > SPLIT_COUNT || r > SPLIT_COUNT)
370 && ((l > r * BALANCE_THRESHOLD + s) || (r > l * BALANCE_THRESHOLD + s))
371 {
372 print_tree(tree, 0);
373 panic!("Tree is not balanced");
374 }
375 assert_balanced(&children.left);
376 assert_balanced(&children.right);
377 }
378 }
379
380 #[test]
381 fn test_simple() {
382 let mut tree = SelfTimeTree::new();
383 let count = 10000;
384 for i in 0..count {
385 tree.insert(Timestamp::from_micros(i), Timestamp::from_micros(i + 1), i);
386 assert_eq!(tree.count, (i + 1) as usize);
387 assert_balanced(&tree);
388 }
389 assert_eq!(
390 tree.lookup_range_count(Timestamp::ZERO, Timestamp::from_micros(count)),
391 Timestamp::from_micros(count)
392 );
393 print_tree(&tree, 0);
394 assert_balanced(&tree);
395 }
396
397 #[test]
398 fn test_evenly() {
399 let mut tree = SelfTimeTree::new();
400 let count = 10000;
401 for a in 0..10 {
402 for b in 0..10 {
403 for c in 0..10 {
404 for d in 0..10 {
405 let i = d * 1000 + c * 100 + b * 10 + a;
406 tree.insert(Timestamp::from_micros(i), Timestamp::from_micros(i + 1), i);
407 assert_balanced(&tree);
408 }
409 }
410 }
411 }
412 assert_eq!(
413 tree.lookup_range_count(Timestamp::ZERO, Timestamp::from_micros(count)),
414 Timestamp::from_micros(count)
415 );
416 print_tree(&tree, 0);
417 assert_balanced(&tree);
418 }
419
420 #[test]
421 fn test_overlapping() {
422 let mut tree = SelfTimeTree::new();
423 let count = 10000;
424 for i in 0..count {
425 tree.insert(
426 Timestamp::from_micros(i),
427 Timestamp::from_micros(i + 100),
428 i,
429 );
430 assert_eq!(tree.count, (i + 1) as usize);
431 assert_balanced(&tree);
432 }
433 assert_eq!(
434 tree.lookup_range_count(Timestamp::ZERO, Timestamp::from_micros(count + 100)),
435 Timestamp::from_micros(count * 100)
436 );
437 print_tree(&tree, 0);
438 assert_balanced(&tree);
439 }
440
441 #[test]
442 fn test_overlapping_heavy() {
443 let mut tree = SelfTimeTree::new();
444 let count = 10000;
445 for i in 0..count {
446 tree.insert(
447 Timestamp::from_micros(i),
448 Timestamp::from_micros(i + 500),
449 i,
450 );
451 assert_eq!(tree.count, (i + 1) as usize);
452 }
453 assert_eq!(
454 tree.lookup_range_count(Timestamp::ZERO, Timestamp::from_micros(count + 500)),
455 Timestamp::from_micros(count * 500)
456 );
457 print_tree(&tree, 0);
458 assert_balanced(&tree);
459 }
460
461 #[test]
462 fn test_corrected_time_no_overlap() {
463 let tree: SelfTimeTree<u32> = SelfTimeTree::new();
465 let r = tree
466 .lookup_range_corrected_time(Timestamp::from_micros(0), Timestamp::from_micros(100));
467 assert_eq!(r, Timestamp::ZERO);
468 }
469
470 #[test]
471 fn test_corrected_time_single_interval() {
472 let mut tree = SelfTimeTree::new();
475 tree.insert(Timestamp::from_micros(0), Timestamp::from_micros(100), 0u32);
476 let r = tree
477 .lookup_range_corrected_time(Timestamp::from_micros(0), Timestamp::from_micros(100));
478 assert_eq!(r, Timestamp::from_micros(100));
479 }
480
481 #[test]
482 fn test_corrected_time_fast_path_full_containment() {
483 let mut tree = SelfTimeTree::new();
485 tree.insert(Timestamp::from_micros(0), Timestamp::from_micros(100), 0u32);
486 tree.insert(Timestamp::from_micros(5), Timestamp::from_micros(50), 1u32);
487 let r = tree
488 .lookup_range_corrected_time(Timestamp::from_micros(10), Timestamp::from_micros(20));
489 assert_eq!(r, Timestamp::from_micros(5));
490 }
491
492 #[test]
493 fn test_corrected_time_partial_overlap() {
494 let mut tree = SelfTimeTree::new();
503 tree.insert(Timestamp::from_micros(0), Timestamp::from_micros(100), 0u32);
504 tree.insert(Timestamp::from_micros(30), Timestamp::from_micros(70), 1u32);
505 let r = tree
506 .lookup_range_corrected_time(Timestamp::from_micros(0), Timestamp::from_micros(100));
507 assert_eq!(r, Timestamp::from_micros(80));
508 }
509}