1use crate::Bound;
14
15#[derive(PartialEq, Debug, Clone)]
32pub struct AtomicInterval<T> {
33 left: Bound<T>,
34 right: Bound<T>,
35}
36
37
38impl<T: ToString> ToString for AtomicInterval<T> {
40 fn to_string(&self) -> String {
45 match (&self.left, &self.right) {
46 (Bound::Included(l), Bound::Included(r)) => format!("[{}, {}]", l.to_string(), r.to_string()),
47 (Bound::Included(l), Bound::Excluded(r)) => format!("[{}, {})", l.to_string(), r.to_string()),
48 (Bound::Excluded(l), Bound::Included(r)) => format!("({}, {}]", l.to_string(), r.to_string()),
49 (Bound::Excluded(l), Bound::Excluded(r)) => format!("({}, {})", l.to_string(), r.to_string()),
50 }
51 }
52}
53
54
55impl<T: Clone + PartialOrd> AtomicInterval<T> {
57 pub fn open(left: T, right: T) -> Self {
66 if left >= right {
67 panic!("The following condition must be valid: `left < right`");
68 }
69 AtomicInterval { left: Bound::Excluded(left), right: Bound::Excluded(right) }
70 }
71
72 pub fn closed(left: T, right: T) -> Self {
81 if left >= right {
82 panic!("The following condition must be valid: `left < right`");
83 }
84 AtomicInterval { left: Bound::Included(left), right: Bound::Included(right) }
85 }
86
87 pub fn open_closed(left: T, right: T) -> Self {
96 if left >= right {
97 panic!("The following condition must be valid: `left < right`");
98 }
99 AtomicInterval { left: Bound::Excluded(left), right: Bound::Included(right) }
100 }
101
102 pub fn closed_open(left: T, right: T) -> Self {
111 if left >= right {
112 panic!("The following condition must be valid: `left < right`");
113 }
114 AtomicInterval { left: Bound::Included(left), right: Bound::Excluded(right) }
115 }
116
117 pub fn point(value: T) -> Self {
125 AtomicInterval { left: Bound::Included(value.clone()), right: Bound::Included(value) }
126 }
127}
128
129
130impl<T> AtomicInterval<T> {
131 pub fn left(&self) -> &Bound<T> {
136 &self.left
137 }
138
139 pub fn right(&self) -> &Bound<T> {
144 &self.right
145 }
146}
147
148impl <T: PartialOrd> AtomicInterval<T> {
150 pub fn is_superset (&self, other: &AtomicInterval<T>) -> bool {
169 match (&self.left, &self.right, &other.left, &other.right) {
170 (Bound::Included(l1), Bound::Excluded(r1), _, Bound::Included(r2)) => l1 <= other.left.value() && r1 > r2,
171 (Bound::Excluded(l1), Bound::Included(r1), Bound::Included(l2), _) => l1 < l2 && r1 >= other.right.value(),
172 (Bound::Excluded(l1), Bound::Excluded(r1), Bound::Included(l2), Bound::Included(r2)) => l1 < l2 && r1 > r2,
173 (_, _, _, _) => self.left.value() <= other.left.value() && self.right.value() >= other.right.value(),
174 }
175 }
176
177 pub fn is_subset (&self, other: &AtomicInterval<T>) -> bool {
196 other.is_superset(self)
197 }
198
199 pub fn is_overlapping (&self, other: &AtomicInterval<T>) -> bool {
218 let cond1_overlapping = match (&self.left, &self.right, &other.left) {
220 (Bound::Included(l1), Bound::Included(r1), _) => other.left.value() >= l1 && other.left.value() <= r1,
221 (Bound::Included(l1), Bound::Excluded(r1), Bound::Included(l2)) => l2 >= l1 && l2 < r1,
222 (Bound::Included(l1), Bound::Excluded(r1), Bound::Excluded(l2)) => l2 >= l1 && l2 <= r1,
223 (Bound::Excluded(l1), Bound::Included(r1), Bound::Included(l2)) => l2 > l1 && l2 <= r1,
224 (Bound::Excluded(l1), Bound::Included(r1), Bound::Excluded(l2)) => l2 >= l1 && l2 <= r1,
225 (Bound::Excluded(l1), Bound::Excluded(r1), Bound::Included(l2)) => l2 > l1 && l2 < r1,
226 (Bound::Excluded(l1), Bound::Excluded(r1), Bound::Excluded(l2)) => l2 >= l1 && l2 <= r1,
227 };
228 let cond2_overlapping = match (&self.left, &self.right, &other.right) {
230 (Bound::Included(l1), Bound::Included(r1), _) => other.right.value() >= l1 && other.right.value() <= r1,
231 (Bound::Included(l1), Bound::Excluded(r1), Bound::Included(r2)) => r2 > l1 && r2 <= r1,
232 (Bound::Included(l1), Bound::Excluded(r1), Bound::Excluded(r2)) => r2 >= l1 && r2 <= r1,
233 (Bound::Excluded(l1), Bound::Included(r1), Bound::Included(r2)) => r2 >= l1 && r2 < r1,
234 (Bound::Excluded(l1), Bound::Included(r1), Bound::Excluded(r2)) => r2 >= l1 && r2 <= r1,
235 (Bound::Excluded(l1), Bound::Excluded(r1), Bound::Included(r2)) => r2 > l1 && r2 < r1,
236 (Bound::Excluded(l1), Bound::Excluded(r1), Bound::Excluded(r2)) => r2 >= l1 && r2 <= r1,
237 };
238 return cond1_overlapping || cond2_overlapping;
240 }
241
242 pub fn is_adjacent(&self, other: &AtomicInterval<T>) -> bool {
260 let cond1_adjacent = match (&self.left, &other.right) {
262 (Bound::Excluded(_), Bound::Excluded(_)) => false,
263 (Bound::Included(_), Bound::Included(_)) => false,
264 (_, _) => self.left.value() == other.right.value(),
265 };
266 let cond2_adjacent = match (&self.right, &other.left) {
268 (Bound::Excluded(_), Bound::Excluded(_)) => false,
269 (Bound::Included(_), Bound::Included(_)) => false,
270 (_, _) => self.right.value() == other.left.value(),
271 };
272
273 return cond1_adjacent || cond2_adjacent;
274 }
275
276 pub fn is_disjoint(&self, other: &AtomicInterval<T>) -> bool {
295 let cond1_disjoint = match (&self.left, &other.right) {
297 (Bound::Included(l1), Bound::Included(r2)) => l1 > r2,
298 (_, _) => return self.right.value() <= other.left.value(),
299 };
300
301 let cond2_disjoint = match (&self.right, &other.left) {
303 (Bound::Included(r1), Bound::Included(l2)) => r1 < l2,
304 (_, _) => return self.left.value() >= other.right.value(),
305 };
306
307 return cond1_disjoint || cond2_disjoint;
308 }
309}
310
311impl <T: PartialOrd + Clone> AtomicInterval<T> {
312 pub fn union(a: &AtomicInterval<T>, b: &AtomicInterval<T>) -> Vec<AtomicInterval<T>> {
335 if a.is_overlapping(b) || a.is_adjacent(b) {
336 let left = if a.left.value() <= b.left.value() {
337 a.left.clone()
338 } else {
339 b.left.clone()
340 };
341 let right = if a.right.value() >= b.right.value() {
342 a.right.clone()
343 } else {
344 b.right.clone()
345 };
346 vec![AtomicInterval { left, right }]
347 } else {
348 vec![]
349 }
350 }
351
352 pub fn intersection(&self, other: &Self) -> Vec<Self> {
374 if self.is_disjoint(other) {
376 return vec![];
377 }
378
379 let left = if self.left.value() > other.left.value() {
381 self.left.clone()
382 } else {
383 other.left.clone()
384 };
385
386 let right = if self.right.value() < other.right.value() {
388 self.right.clone()
389 } else {
390 other.right.clone()
391 };
392
393 if left.value() == right.value() {
395 return match (left, right) {
396 (Bound::Included(val), Bound::Included(_)) => {
397 vec![ AtomicInterval { left: Bound::Included(val.clone()), right: Bound::Included(val) } ]
398 }
399 _ => vec![],
400 };
401 }
402
403 vec![ AtomicInterval { left, right } ]
405 }
406
407 pub fn difference(&self, other: &Self) -> Vec<Self> {
428 if self.is_disjoint(other) {
430 return vec![self.clone()];
431 } else if self.is_subset(other) {
432 return vec![];
433 }
434
435 let intersection_vec = self.intersection(other);
437 let intersection = intersection_vec.first().expect("No intersection found!");
438
439 let mut result = Vec::new();
440
441 if intersection.left.value() > self.left.value() {
443 let left_interval = AtomicInterval {
444 left: self.left.clone(),
445 right: match &intersection.left {
446 Bound::Included(val) => Bound::Excluded(val.clone()),
447 Bound::Excluded(val) => Bound::Excluded(val.clone()),
448 },
449 };
450 if left_interval.left.value() < left_interval.right.value() {
452 result.push(left_interval);
453 }
454 }
455
456 if intersection.right.value() < self.right.value() {
458 let right_interval = AtomicInterval {
459 left: match &intersection.right {
460 Bound::Included(val) => Bound::Excluded(val.clone()),
461 Bound::Excluded(val) => Bound::Excluded(val.clone()),
462 },
463 right: self.right.clone(),
464 };
465 if right_interval.left.value() < right_interval.right.value() {
467 result.push(right_interval);
468 }
469 }
470
471 result
472 }
473
474}
475
476#[cfg(test)]
477mod tests {
478 use super::*;
479
480 #[test]
481 fn test_open_interval() {
482 let interval = AtomicInterval::open(1, 5);
483 assert_eq!(interval.left, Bound::Excluded(1));
484 assert_eq!(interval.right, Bound::Excluded(5));
485 }
486
487 #[test]
488 fn test_closed_interval() {
489 let interval = AtomicInterval::closed(1, 5);
490 assert_eq!(interval.left, Bound::Included(1));
491 assert_eq!(interval.right, Bound::Included(5));
492 }
493
494 #[test]
495 fn test_open_closed_interval() {
496 let interval = AtomicInterval::open_closed(1, 5);
497 assert_eq!(interval.left, Bound::Excluded(1));
498 assert_eq!(interval.right, Bound::Included(5));
499 }
500
501 #[test]
502 fn test_closed_open_interval() {
503 let interval = AtomicInterval::closed_open(1, 5);
504 assert_eq!(interval.left, Bound::Included(1));
505 assert_eq!(interval.right, Bound::Excluded(5));
506 }
507
508 #[test]
509 fn test_point_interval() {
510 let interval = AtomicInterval::point(1);
511 assert_eq!(interval.left, Bound::Included(1));
512 assert_eq!(interval.right, Bound::Included(1));
513 }
514
515 #[test]
516 fn test_is_overlapping() {
517 let interval1 = AtomicInterval::closed(1, 5);
518 let interval2 = AtomicInterval::closed(4, 6);
519 assert!(interval1.is_overlapping(&interval2));
520 }
521
522 #[test]
523 fn test_is_adjacent() {
524 let interval1 = AtomicInterval::closed(1, 5);
525 let interval2 = AtomicInterval::open_closed(5, 10);
526 assert!(interval1.is_adjacent(&interval2));
527 }
528
529 #[test]
530 fn test_is_disjoint() {
531 let interval1 = AtomicInterval::closed(1, 5);
532 let interval2 = AtomicInterval::closed(6, 10);
533 assert!(interval1.is_disjoint(&interval2));
534 }
535
536 #[test]
537 fn test_is_subset() {
538 let interval1 = AtomicInterval::closed(2, 4);
539 let interval2 = AtomicInterval::closed(1, 5);
540 assert!(interval1.is_subset(&interval2));
541 }
542
543 #[test]
544 fn test_is_superset() {
545 let interval1 = AtomicInterval::closed(1, 5);
546 let interval2 = AtomicInterval::closed(2, 4);
547 assert!(interval1.is_superset(&interval2));
548 }
549
550 #[test]
551 fn test_union_overlapping_intervals() {
552 let interval1 = AtomicInterval::closed(1, 5);
553 let interval2 = AtomicInterval::closed(4, 7);
554 let merged = AtomicInterval::union(&interval1, &interval2);
555 assert_eq!(merged.len(), 1);
556 assert_eq!(merged.first().unwrap(), &AtomicInterval::closed(1, 7));
557 }
558
559 #[test]
560 fn test_union_adjacent_intervals() {
561 let interval1 = AtomicInterval::closed(1, 5);
562 let interval2 = AtomicInterval::closed(5, 7);
563 let merged = AtomicInterval::union(&interval1, &interval2);
564 assert_eq!(merged.len(), 1);
565 assert_eq!(merged.first().unwrap(), &AtomicInterval::closed(1, 7));
566 }
567
568 #[test]
569 fn test_union_disjoint_intervals() {
570 let interval1 = AtomicInterval::closed(1, 5);
571 let interval2 = AtomicInterval::closed(6, 7);
572 let merged = AtomicInterval::union(&interval1, &interval2);
573 assert_eq!(merged.len(), 0);
574 }
575
576 #[test]
577 fn test_intersection_between_two_overlapping_intervals() {
578 let interval1 = AtomicInterval::closed(1, 5);
579 let interval2 = AtomicInterval::closed(3, 7);
580 let intersection = interval1.intersection(&interval2);
581 assert_eq!(intersection.len(), 1);
582 assert_eq!(intersection.first().unwrap(), &AtomicInterval::closed(3, 5));
583 }
584
585 #[test]
586 fn test_intersection_between_two_disjoint_intervals() {
587 let interval1 = AtomicInterval::closed(1, 3);
588 let interval2 = AtomicInterval::closed(4, 7);
589 let intersection = interval1.intersection(&interval2);
590 assert_eq!(intersection.len(), 0);
591 }
592
593 #[test]
594 fn test_intersection_between_two_adjacent_intervals() {
595 let interval1 = AtomicInterval::closed(1, 5);
596 let interval2 = AtomicInterval::open(5, 7);
597 let intersection = interval1.intersection(&interval2);
598 assert_eq!(intersection.len(), 0);
599 }
600
601 #[test]
602 fn test_difference_between_two_overlapping_intervals() {
603 let interval1 = AtomicInterval::closed(1, 5);
604 let interval2 = AtomicInterval::closed(3, 7);
605 let difference = interval1.difference(&interval2);
606 assert_eq!(difference.len(), 1);
607 assert_eq!(difference[0], AtomicInterval::closed_open(1, 3));
608 }
609
610 #[test]
611 fn test_difference_between_subset_and_superset_interval() {
612 let interval1 = AtomicInterval::closed(1, 5);
613 let interval2 = AtomicInterval::closed(2, 4);
614 let difference = interval1.difference(&interval2);
615 assert_eq!(difference.len(), 2);
616 assert_eq!(difference[0], AtomicInterval::closed_open(1, 2));
617 assert_eq!(difference[1], AtomicInterval::open_closed(4, 5));
618 }
619
620 #[test]
621 fn test_difference_between_two_disjoint_intervals() {
622 let interval1 = AtomicInterval::closed(1, 3);
623 let interval2 = AtomicInterval::closed(4, 7);
624 let difference = interval1.difference(&interval2);
625 assert_eq!(difference.len(), 1);
626 assert_eq!(difference[0], AtomicInterval::closed(1, 3));
627 }
628
629 #[test]
630 fn test_difference_between_two_adjacent_intervals() {
631 let interval1 = AtomicInterval::closed(1, 5);
632 let interval2 = AtomicInterval::open(5, 7);
633 let difference = interval1.difference(&interval2);
634 assert_eq!(difference.len(), 1);
635 assert_eq!(difference[0], AtomicInterval::closed(1, 5));
636 }
637}