1use gcollections::*;
38use gcollections::ops::*;
39use trilean::SKleene;
40use crate::ops::*;
41
42use std::ops::{Add, Sub, Mul};
43use std::cmp::{min, max};
44use std::fmt::{Formatter, Display, Error};
45use num_traits::{Zero, Num};
46
47#[derive(Debug, Copy, Clone)]
49pub struct Interval<Bound>
50{
51 lb: Bound,
52 ub: Bound
53}
54
55impl<Bound> IntervalKind for Interval<Bound> {}
56
57impl<Bound> Collection for Interval<Bound>
58{
59 type Item = Bound;
60}
61
62impl<Bound> Interval<Bound> where
63 Bound: Width + Num
64{
65 fn into_optional(self) -> Optional<Bound> {
66 if self.is_empty() { Optional::empty() }
67 else if self.is_singleton() { Optional::singleton(self.lb) }
68 else {
69 panic!("Only empty interval or singleton can be transformed into an option.");
70 }
71 }
72}
73
74impl<Bound: Width + Num> Eq for Interval<Bound> {}
75
76impl<Bound> PartialEq<Interval<Bound>> for Interval<Bound> where
77 Bound: Width + Num
78{
79 fn eq(&self, other: &Interval<Bound>) -> bool {
80 if self.is_empty() && other.is_empty() { true }
81 else { self.lb == other.lb && self.ub == other.ub }
82 }
83}
84
85impl<Bound> Interval<Bound> where
86 Bound: Clone
87{
88 fn low(&self) -> Bound {
89 self.lb.clone()
90 }
91 fn up(&self) -> Bound {
92 self.ub.clone()
93 }
94}
95
96impl<Bound> Interval<Bound> where
97 Bound: Width + Num
98{
99 fn min_lb(ub: Bound) -> Interval<Bound> {
100 Interval::new(<Bound as Width>::min_value(), ub)
101 }
102
103 fn max_ub(lb: Bound) -> Interval<Bound> {
104 Interval::new(lb, <Bound as Width>::max_value())
105 }
106}
107
108impl<Bound> Range for Interval<Bound> where
109 Bound: Width
110{
111 fn new(lb: Bound, ub: Bound) -> Interval<Bound> {
112 debug_assert!(lb >= <Bound as Width>::min_value(),
113 "Lower bound exceeds the minimum value of a bound.");
114 debug_assert!(ub <= <Bound as Width>::max_value(),
115 "Upper bound exceeds the maximum value of a bound.");
116 Interval { lb, ub }
117 }
118}
119
120impl<Bound> Bounded for Interval<Bound> where
121 Bound: Num + Width + Clone
122{
123 fn lower(&self) -> Bound {
124 debug_assert!(!self.is_empty(), "Cannot access lower bound on empty interval.");
125 self.low()
126 }
127
128 fn upper(&self) -> Bound {
129 debug_assert!(!self.is_empty(), "Cannot access upper bound on empty interval.");
130 self.up()
131 }
132}
133
134impl<Bound> Singleton for Interval<Bound> where
135 Bound: Width + Clone
136{
137 fn singleton(x: Bound) -> Interval<Bound> {
138 Interval::new(x.clone(), x)
139 }
140}
141
142impl<Bound> Empty for Interval<Bound> where
143 Bound: Width + Num
144{
145 fn empty() -> Interval<Bound> {
146 Interval::new(Bound::one(), Bound::zero())
147 }
148}
149
150impl<Bound> Whole for Interval<Bound> where
151 Bound: Width + Num
152{
153 fn whole() -> Interval<Bound> {
154 Interval::new(<Bound as Width>::min_value(), <Bound as Width>::max_value())
155 }
156}
157
158impl<Bound> Cardinality for Interval<Bound> where
160 Bound: Width + Num
161{
162 type Size = <Bound as Width>::Output;
163
164 fn size(&self) -> <Bound as Width>::Output {
165 if self.lb > self.ub { <<Bound as Width>::Output>::zero() }
166 else {
167 Bound::width(&self.lb, &self.ub)
168 }
169 }
170}
171
172impl<Bound> Disjoint for Interval<Bound> where
173 Bound: Width + Num
174{
175 fn is_disjoint(&self, other: &Interval<Bound>) -> bool {
176 self.is_empty() || other.is_empty()
177 || self.lb > other.ub || other.lb > self.ub
178 }
179}
180
181impl<Bound> Disjoint<Bound> for Interval<Bound> where
182 Bound: Num + Ord
183{
184 fn is_disjoint(&self, value: &Bound) -> bool {
185 !self.contains(value)
186 }
187}
188
189macro_rules! primitive_interval_disjoint
190{
191 ( $( $source:ty ),* ) =>
192 {$(
193 impl Disjoint<Interval<$source>> for $source
194 {
195 fn is_disjoint(&self, value: &Interval<$source>) -> bool {
196 value.is_disjoint(self)
197 }
198 }
199 )*}
200}
201
202primitive_interval_disjoint!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize);
203
204impl<Bound> Disjoint<Optional<Bound>> for Interval<Bound> where
205 Bound: Num + Ord
206{
207 fn is_disjoint(&self, value: &Optional<Bound>) -> bool {
208 value.as_ref().map_or(true, |x| self.is_disjoint(x))
209 }
210}
211
212macro_rules! optional_interval_disjoint
213{
214 ( $( $source:ty ),* ) =>
215 {$(
216 impl Disjoint<Interval<$source>> for Optional<$source>
217 {
218 fn is_disjoint(&self, value: &Interval<$source>) -> bool {
219 value.is_disjoint(self)
220 }
221 }
222 )*}
223}
224
225optional_interval_disjoint!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize);
226
227impl<Bound> Overlap for Interval<Bound> where
228 Bound: Width + Num
229{
230 fn overlap(&self, other: &Interval<Bound>) -> bool {
231 !self.is_disjoint(other)
232 }
233}
234
235impl<Bound> Overlap<Bound> for Interval<Bound> where
236 Bound: Width + Num
237{
238 fn overlap(&self, other: &Bound) -> bool {
239 !self.is_disjoint(other)
240 }
241}
242
243impl<Bound> Overlap<Optional<Bound>> for Interval<Bound> where
244 Bound: Width + Num
245{
246 fn overlap(&self, other: &Optional<Bound>) -> bool {
247 !self.is_disjoint(other)
248 }
249}
250
251macro_rules! primitive_interval_overlap
252{
253 ( $( $source:ty ),* ) =>
254 {$(
255 impl Overlap<Interval<$source>> for $source
256 {
257 fn overlap(&self, other: &Interval<$source>) -> bool {
258 !self.is_disjoint(other)
259 }
260 }
261 )*}
262}
263
264primitive_interval_overlap!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize);
265
266macro_rules! optional_interval_overlap
267{
268 ( $( $source:ty ),* ) =>
269 {$(
270 impl Overlap<Interval<$source>> for Optional<$source>
271 {
272 fn overlap(&self, other: &Interval<$source>) -> bool {
273 !self.is_disjoint(other)
274 }
275 }
276 )*}
277}
278
279optional_interval_overlap!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize);
280
281impl<Bound> Hull for Interval<Bound> where
282 Bound: Width + Num
283{
284 type Output = Interval<Bound>;
285
286 fn hull(&self, other: &Interval<Bound>) -> Interval<Bound> {
287 if self.is_empty() { other.clone() }
288 else if other.is_empty() { self.clone() }
289 else {
290 Interval::new(
291 min(self.low(), other.low()),
292 max(self.up(), other.up())
293 )
294 }
295 }
296}
297
298impl<Bound> Hull<Bound> for Interval<Bound> where
299 Bound: Width + Num
300{
301 type Output = Interval<Bound>;
302
303 fn hull(&self, other: &Bound) -> Interval<Bound> {
304 self.hull(&Interval::singleton(other.clone()))
305 }
306}
307
308macro_rules! primitive_interval_hull
309{
310 ( $( $source:ty ),* ) =>
311 {$(
312 impl Hull<Interval<$source>> for $source
313 {
314 type Output = Interval<$source>;
315
316 fn hull(&self, other: &Interval<$source>) -> Interval<$source> {
317 other.hull(self)
318 }
319 }
320 )*}
321}
322
323primitive_interval_hull!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize);
324
325impl<Bound> Contains for Interval<Bound> where
326 Bound: Ord
327{
328 fn contains(&self, value: &Bound) -> bool {
329 value >= &self.lb && value <= &self.ub
330 }
331}
332
333impl<Bound> Subset for Interval<Bound> where
334 Bound: Width + Num
335{
336 fn is_subset(&self, other: &Interval<Bound>) -> bool {
337 if self.is_empty() { true }
338 else {
339 self.lb >= other.lb && self.ub <= other.ub
340 }
341 }
342}
343
344impl<Bound> ProperSubset for Interval<Bound> where
345 Bound: Width + Num
346{
347 fn is_proper_subset(&self, other: &Interval<Bound>) -> bool {
348 self.is_subset(other) && self != other
349 }
350}
351
352impl<Bound> Intersection for Interval<Bound> where
353 Bound: Width + Num
354{
355 type Output = Interval<Bound>;
356
357 fn intersection(&self, other: &Interval<Bound>) -> Interval<Bound> {
358 Interval::new(
359 max(self.low(), other.low()),
360 min(self.up(), other.up())
361 )
362 }
363}
364
365impl<Bound> Intersection<Bound> for Interval<Bound> where
366 Bound: Width + Num
367{
368 type Output = Interval<Bound>;
369
370 fn intersection(&self, value: &Bound) -> Interval<Bound> {
371 if self.contains(value) {
372 Interval::singleton(value.clone())
373 }
374 else {
375 Interval::empty()
376 }
377 }
378}
379
380impl<Bound> Intersection<Optional<Bound>> for Interval<Bound> where
381 Bound: Width + Num
382{
383 type Output = Interval<Bound>;
384
385 fn intersection(&self, value: &Optional<Bound>) -> Interval<Bound> {
386 value.as_ref().map_or(Interval::empty(), |x| self.intersection(x))
387 }
388}
389
390macro_rules! optional_interval_intersection
391{
392 ( $( $source:ty ),* ) =>
393 {$(
394 impl Intersection<Interval<$source>> for Optional<$source>
395 {
396 type Output = Optional<$source>;
397
398 fn intersection(&self, other: &Interval<$source>) -> Optional<$source> {
399 self.as_ref().map_or(Optional::empty(), |x| other.intersection(x).into_optional())
400 }
401 }
402 )*}
403}
404
405optional_interval_intersection!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize);
406
407impl<Bound> Difference for Interval<Bound> where
408 Bound: Width + Num
409{
410 type Output = Interval<Bound>;
411
412 fn difference(&self, other: &Interval<Bound>) -> Interval<Bound> {
421 let left = self.intersection(&Interval::min_lb(other.low() - Bound::one()));
422 let right = self.intersection(&Interval::max_ub(other.up() + Bound::one()));
423 left.hull(&right)
424 }
425}
426
427impl<Bound> Difference<Bound> for Interval<Bound> where
428 Bound: Num + Clone
429{
430 type Output = Interval<Bound>;
431
432 fn difference(&self, value: &Bound) -> Interval<Bound> {
433 let mut this = self.clone();
434 if value == &this.lb {
435 this.lb = this.lb + Bound::one();
436 }
437 else if value == &this.ub {
438 this.ub = this.ub - Bound::one();
439 }
440 this
441 }
442}
443
444impl<Bound> Difference<Optional<Bound>> for Interval<Bound> where
445 Bound: Ord + Num + Clone
446{
447 type Output = Interval<Bound>;
448
449 fn difference(&self, value: &Optional<Bound>) -> Interval<Bound> {
450 value.as_ref().map_or_else(|| self.clone(), |x| self.difference(x))
451 }
452}
453
454macro_rules! optional_interval_difference
455{
456 ( $( $source:ty ),* ) =>
457 {$(
458 impl Difference<Interval<$source>> for Optional<$source>
459 {
460 type Output = Optional<$source>;
461
462 fn difference(&self, other: &Interval<$source>) -> Optional<$source> {
463 self.as_ref().map_or(Optional::empty(), |x|
464 if other.contains(x) { Optional::empty() }
465 else { Optional::singleton(x.clone()) }
466 )
467 }
468 }
469 )*}
470}
471
472optional_interval_difference!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize);
473
474impl<Bound> ShrinkLeft for Interval<Bound> where
475 Bound: Num + Width
476{
477 fn shrink_left(&self, lb: Bound) -> Interval<Bound> {
478 let mut this = self.clone();
479 if lb > this.lb {
480 this.lb = lb;
481 }
482 this
483 }
484}
485
486impl<Bound> ShrinkRight for Interval<Bound> where
487 Bound: Num + Width
488{
489 fn shrink_right(&self, ub: Bound) -> Interval<Bound> {
490 let mut this = self.clone();
491 if ub < this.ub {
492 this.ub = ub;
493 }
494 this
495 }
496}
497
498forward_all_binop!(impl<Bound: +Num+Width> Add for Interval<Bound>, add);
499
500impl<'a, 'b, Bound> Add<&'b Interval<Bound>> for &'a Interval<Bound> where
501 Bound: Num + Width
502{
503 type Output = Interval<Bound>;
504
505 fn add(self, other: &Interval<Bound>) -> Interval<Bound> {
506 if self.is_empty() || other.is_empty() {
507 Interval::empty()
508 } else {
509 Interval::new(self.lower() + other.lower(), self.upper() + other.upper())
510 }
511 }
512}
513
514forward_all_binop!(impl<Bound: +Num+Width+Clone> Add for Interval<Bound>, add, Bound);
515
516impl<'a, 'b, Bound> Add<&'b Bound> for &'a Interval<Bound> where
517 Bound: Num + Width + Clone
518{
519 type Output = Interval<Bound>;
520
521 fn add(self, other: &Bound) -> Interval<Bound> {
522 if self.is_empty() {
523 Interval::empty()
524 }
525 else {
526 Interval::new(self.lower() + other.clone(), self.upper() + other.clone())
527 }
528 }
529}
530
531forward_all_binop!(impl<Bound: +Num+Width> Sub for Interval<Bound>, sub);
532
533impl<'a, 'b, Bound> Sub<&'b Interval<Bound>> for &'a Interval<Bound> where
534 Bound: Num + Width
535{
536 type Output = Interval<Bound>;
537
538 fn sub(self, other: &Interval<Bound>) -> Interval<Bound> {
539 if self.is_empty() || other.is_empty() {
540 Interval::empty()
541 } else {
542 Interval::new(self.lower() - other.upper(), self.upper() - other.lower())
543 }
544 }
545}
546
547forward_all_binop!(impl<Bound: +Num+Width+Clone> Sub for Interval<Bound>, sub, Bound);
548
549impl<'a, 'b, Bound> Sub<&'b Bound> for &'a Interval<Bound> where
550 Bound: Num + Width + Clone
551{
552 type Output = Interval<Bound>;
553
554 fn sub(self, other: &Bound) -> Interval<Bound> {
555 if self.is_empty() {
556 Interval::empty()
557 } else {
558 Interval::new(self.lower() - other.clone(), self.upper() - other.clone())
559 }
560 }
561}
562
563forward_all_binop!(impl<Bound: +Num+Width> Mul for Interval<Bound>, mul);
564
565fn min_max<Iter, Item>(mut iter: Iter) -> (Item, Item) where
568 Iter: Iterator<Item=Item>,
569 Item: Ord
570{
571 debug_assert!(iter.size_hint().0 > 2,
572 "`min_max` expects an iterator (`iter`) yielding at least two elements.");
573 let (mut min, mut max) = {
574 let x = iter.next().unwrap();
575 let y = iter.next().unwrap();
576 if x <= y {(x, y)} else {(y, x)}
577 };
578
579 loop {
580 let first = match iter.next() {
586 None => break,
587 Some(x) => x
588 };
589 let second = match iter.next() {
590 None => {
591 if first < min {
592 min = first;
593 } else if first >= max {
594 max = first;
595 }
596 break;
597 }
598 Some(x) => x
599 };
600 if first <= second {
601 if first < min { min = first }
602 if second >= max { max = second }
603 } else {
604 if second < min { min = second }
605 if first >= max { max = first }
606 }
607 }
608 (min, max)
609}
610
611impl<'a, 'b, Bound> Mul<&'b Interval<Bound>> for &'a Interval<Bound> where
612 Bound: Num + Width
613{
614 type Output = Interval<Bound>;
615
616 fn mul(self, other: &Interval<Bound>) -> Interval<Bound> {
618 if self.is_empty() || other.is_empty() {
619 Interval::empty()
620 } else {
621 let (min, max) = min_max(vec![
622 self.lower() * other.lower(),
623 self.lower() * other.upper(),
624 self.upper() * other.lower(),
625 self.upper() * other.upper()].into_iter());
626 Interval::new(min, max)
627 }
628 }
629}
630
631forward_all_binop!(impl<Bound: +Num+Width+Clone> Mul for Interval<Bound>, mul, Bound);
632
633impl<'a, 'b, Bound> Mul<&'b Bound> for &'a Interval<Bound> where
634 Bound: Num + Width + Clone
635{
636 type Output = Interval<Bound>;
637
638 fn mul(self, other: &Bound) -> Interval<Bound> {
640 if self.is_empty() {
641 Interval::empty()
642 } else {
643 Interval::new(self.lower() * other.clone(), self.upper() * other.clone())
644 }
645 }
646}
647
648impl<Bound> Display for Interval<Bound> where
649 Bound: Display + Width + Num
650{
651 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
652 if self.is_empty() {
653 formatter.write_str("{}")
654 } else {
655 formatter.write_fmt(format_args!("[{}..{}]", self.lb, self.ub))
656 }
657 }
658}
659
660pub trait ToInterval<Bound>
661{
662 fn to_interval(self) -> Interval<Bound>;
663}
664
665impl<Bound> ToInterval<Bound> for Interval<Bound>
666{
667 fn to_interval(self) -> Interval<Bound> { self }
668}
669
670impl<Bound: Width+Num> ToInterval<Bound> for (Bound, Bound)
671{
672 fn to_interval(self) -> Interval<Bound> {
673 let (a, b) = self;
674 Interval::new(a, b)
675 }
676}
677
678impl<Bound: Width+Num> ToInterval<Bound> for ()
679{
680 fn to_interval(self) -> Interval<Bound> {
681 Interval::empty()
682 }
683}
684
685impl<Bound: Width+Num> ToInterval<Bound> for Bound
686{
687 fn to_interval(self) -> Interval<Bound> {
688 Interval::singleton(self)
689 }
690}
691
692impl<Bound> Join for Interval<Bound> where
693 Bound: Width + Num
694{
695 fn join(self, other: Interval<Bound>) -> Interval<Bound> {
696 self.intersection(&other)
697 }
698}
699
700impl<Bound> Meet for Interval<Bound> where
701 Bound: Width + Num
702{
703 fn meet(self, other: Interval<Bound>) -> Interval<Bound> {
704 self.hull(&other)
705 }
706}
707
708impl<Bound> Entailment for Interval<Bound> where
709 Bound: Width + Num
710{
711 fn entail(&self, other: &Interval<Bound>) -> SKleene {
712 if self.is_subset(other) {
713 SKleene::True
714 }
715 else if other.is_subset(self) {
716 SKleene::False
717 }
718 else {
719 SKleene::Unknown
720 }
721 }
722}
723
724impl<Bound> Top for Interval<Bound> where
725 Bound: Width + Num
726{
727 fn top() -> Interval<Bound> {
728 Interval::empty()
729 }
730}
731
732impl<Bound> Bot for Interval<Bound> where
733 Bound: Width + Num
734{
735 fn bot() -> Interval<Bound> {
736 Interval::whole()
737 }
738}
739
740#[allow(non_upper_case_globals)]
741#[cfg(test)]
742mod tests {
743 use super::*;
744
745 const empty: Interval<i32> = Interval {lb: 1, ub: 0};
746 const invalid: Interval<i32> = Interval {lb: 10, ub: -10};
747 const zero: Interval<i32> = Interval {lb: 0, ub: 0};
748 const one: Interval<i32> = Interval {lb: 1, ub: 1};
749 const ten: Interval<i32> = Interval {lb: 10, ub: 10};
750
751 const i0_1: Interval<i32> = Interval {lb: 0, ub: 1};
752 const i0_2: Interval<i32> = Interval {lb: 0, ub: 2};
753 const i1_2: Interval<i32> = Interval {lb: 1, ub: 2};
754 const i0_10: Interval<i32> = Interval {lb: 0, ub: 10};
755 const i1_10: Interval<i32> = Interval {lb: 1, ub: 10};
756 const i0_9: Interval<i32> = Interval {lb: 0, ub: 9};
757 const i0_15: Interval<i32> = Interval {lb: 0, ub: 15};
758 const im5_10: Interval<i32> = Interval {lb: -5, ub: 10};
759 const im5_m1: Interval<i32> = Interval {lb: -5, ub: -1};
760 const i5_10: Interval<i32> = Interval {lb: 5, ub: 10};
761 const i6_10: Interval<i32> = Interval {lb: 6, ub: 10};
762 const i0_5: Interval<i32> = Interval {lb: 0, ub: 5};
763 const i0_4: Interval<i32> = Interval {lb: 0, ub: 4};
764 const im5_5: Interval<i32> = Interval {lb: -5, ub: 5};
765 const i20_30: Interval<i32> = Interval {lb: 20, ub: 30};
766 const im30_m20: Interval<i32> = Interval {lb: -30, ub: -20};
767
768 #[test]
769 fn to_interval_id_test() {
770 let id = i1_2.clone().to_interval();
771 assert_eq!(i1_2, id);
772 assert_eq!(i1_2, Interval::new(1, 2));
773 }
774
775 #[test]
776 fn equality_test() {
777 assert_eq!(empty, empty);
778 assert_eq!(empty, invalid);
779 assert_eq!(invalid, empty);
780 assert_eq!(i1_2, i1_2);
781 }
782
783 #[test]
784 fn size_test() {
785 let whole_i32: Interval<i32> = Interval::whole();
786 let whole_u32: Interval<u32> = Interval::whole();
787
788 assert_eq!(zero.size(), 1);
789 assert_eq!(one.size(), 1);
790 assert_eq!(empty.size(), 0);
791 assert_eq!(invalid.size(), 0);
792
793 assert_eq!(i1_2.size(), 2);
794 assert_eq!(i0_10.size(), 11);
795 assert_eq!(im30_m20.size(), 11);
796
797 assert_eq!(whole_i32.size(), u32::max_value());
798 assert_eq!(whole_u32.size(), u32::max_value());
799 }
800
801 #[test]
802 fn contains_test() {
803 assert!(i1_2.contains(&1));
804 assert!(i1_2.contains(&2));
805 assert!(!i1_2.contains(&0));
806 assert!(!i1_2.contains(&3));
807
808 assert!(zero.contains(&0));
809 assert!(!zero.contains(&1));
810
811 assert!(!empty.contains(&0));
812 assert!(!empty.contains(&1));
813 assert!(!empty.contains(&5));
814 assert!(!empty.contains(&-5));
815
816 assert!(!invalid.contains(&0));
817 assert!(!invalid.contains(&-11));
818 assert!(!invalid.contains(&11));
819 }
820
821 #[test]
822 fn is_subset_test() {
823 let cases = vec![
824 (zero, zero, true),
825 (i1_2, i1_2, true),
826 (empty, empty, true),
827 (invalid, invalid, true)
828 ];
829
830 let sym_cases = vec![
836 (empty, zero, (true, false)),
839 (invalid, zero, (true, false)),
840 (empty, invalid, (true, true)),
841 (empty, i1_2, (true, false)),
844 (empty, i0_10, (true, false)),
845 (invalid, i1_2, (true, false)),
846 (i1_2, i0_10, (true, false)),
849 (i0_4, i5_10, (false, false)),
852 (i0_5, i5_10, (false, false)),
855 (im5_5, i0_10, (false, false)),
858 (i0_10, i20_30, (false, false)),
861 (i0_10, i0_15, (true, false)),
864 (im5_10, i0_10, (false, true))
867 ];
868
869 for (x,y,r) in cases.into_iter() {
870 assert!(x.is_subset(&y) == r, "{:?} is subset of {:?} is not equal to {:?}", x, y, r);
871 }
872
873 for (x,y,(r1,r2)) in sym_cases.into_iter() {
874 assert!(x.is_subset(&y) == r1, "{:?} is subset of {:?} is not equal to {:?}", x, y, r1);
875 assert!(y.is_subset(&x) == r2, "{:?} is subset of {:?} is not equal to {:?}", y, x, r2);
876 }
877 }
878
879 #[test]
880 fn is_proper_subset_test() {
881 let cases = vec![
882 (zero, zero, false),
883 (i1_2, i1_2, false),
884 (empty, empty, false),
885 (invalid, invalid, false)
886 ];
887
888 let sym_cases = vec![
894 (empty, zero, (true, false)),
897 (invalid, zero, (true, false)),
898 (empty, invalid, (false, false)),
899 (empty, i1_2, (true, false)),
902 (empty, i0_10, (true, false)),
903 (invalid, i1_2, (true, false)),
904 (i1_2, i0_10, (true, false)),
907 (i0_4, i5_10, (false, false)),
910 (i0_5, i5_10, (false, false)),
913 (im5_5, i0_10, (false, false)),
916 (i0_10, i20_30, (false, false)),
919 (i0_10, i0_15, (true, false)),
922 (im5_10, i0_10, (false, true))
925 ];
926
927 for (x,y,r) in cases.into_iter() {
928 assert!(x.is_proper_subset(&y) == r, "{:?} is proper subset of {:?} is not equal to {:?}", x, y, r);
929 }
930
931 for (x,y,(r1,r2)) in sym_cases.into_iter() {
932 assert!(x.is_proper_subset(&y) == r1, "{:?} is proper subset of {:?} is not equal to {:?}", x, y, r1);
933 assert!(y.is_proper_subset(&x) == r2, "{:?} is proper subset of {:?} is not equal to {:?}", y, x, r2);
934 }
935 }
936
937 #[test]
938 fn intersection_test() {
939 let cases = vec![
940 (zero, zero, zero),
941 (i1_2, i1_2, i1_2),
942 (empty, empty, empty),
943 (invalid, invalid, invalid)
944 ];
945
946 let sym_cases = vec![
952 (empty, zero, empty),
955 (invalid, zero, empty),
956 (empty, invalid, empty),
957 (empty, i1_2, empty),
960 (empty, i0_10, empty),
961 (invalid, i1_2, empty),
962 (i1_2, i0_10, i1_2),
965 (i0_4, i5_10, empty),
968 (i0_5, i5_10, 5.to_interval()),
971 (im5_5, i0_10, (0,5).to_interval()),
974 (i0_10, i20_30, empty),
977 (i0_10, i0_15, i0_10),
980 (im5_10, i0_10, i0_10)
983 ];
984
985 for (x,y,r) in cases.into_iter() {
986 assert!(x.intersection(&y) == r, "{:?} intersection {:?} is not equal to {:?}", x, y, r);
987 }
988
989 for (x,y,r) in sym_cases.into_iter() {
990 assert!(x.intersection(&y) == r, "{:?} intersection {:?} is not equal to {:?}", x, y, r);
991 assert!(y.intersection(&x) == r, "{:?} intersection {:?} is not equal to {:?}", y, x, r);
992 }
993 }
994
995 #[test]
996 fn intersection_value_optional_test() {
997 let cases = vec![
998 (1, empty, None, empty, None),
999 (2, invalid, None, empty, None),
1000 (3, empty, Some(1), empty, None),
1001 (4, i0_10, None, empty, None),
1002 (5, i0_10, Some(0), zero, Some(0)),
1003 (6, i0_10, Some(10), ten, Some(10)),
1004 (7, i0_10, Some(1), one, Some(1)),
1005 (8, i0_10, Some(-1), empty, None),
1006 (9, i0_10, Some(11), empty, None),
1007 (10, one, Some(0), empty, None),
1008 (11, one, Some(1), one, Some(1)),
1009 ];
1010 for (id,x,y,r1,r2) in cases.into_iter() {
1011 let y = y.map_or(Optional::empty(), |y| Optional::singleton(y));
1012 let r2 = r2.map_or(Optional::empty(), |r2| Optional::singleton(r2));
1013 if !y.is_empty() {
1015 assert!(x.intersection(y.as_ref().unwrap()) == r1,
1016 "Test#{}: {:?} intersection {:?} is not equal to {:?}", id, x, y.as_ref().unwrap(), r1);
1017 }
1018 assert!(x.intersection(&y) == r1, "Test#{}: {:?} intersection {:?} is not equal to {:?}", id, x, y, r1);
1020 assert!(y.intersection(&x) == r2, "Test#{}: {:?} intersection {:?} is not equal to {:?}", id, y, x, r2);
1022 }
1023 }
1024
1025
1026 #[test]
1027 fn hull_test() {
1028 let cases = vec![
1029 (zero, zero, zero),
1030 (i1_2, i1_2, i1_2),
1031 (empty, empty, empty),
1032 (invalid, invalid, invalid)
1033 ];
1034
1035 let sym_cases = vec![
1041 (empty, zero, zero),
1044 (invalid, zero, zero),
1045 (empty, invalid, empty),
1046 (empty, i1_2, i1_2),
1049 (empty, i0_10, i0_10),
1050 (invalid, i1_2, i1_2),
1051 (i1_2, i0_10, i0_10),
1054 (i0_4, i5_10, i0_10),
1057 (i0_5, i5_10, i0_10),
1060 (im5_5, i0_10, (-5,10).to_interval()),
1063 (i0_10, i20_30, (0,30).to_interval()),
1066 (i0_10, i0_15, i0_15),
1069 (im5_10, i0_10, im5_10)
1072 ];
1073
1074 for (x,y,r) in cases.into_iter() {
1075 assert!(x.hull(&y) == r, "{:?} hull {:?} is not equal to {:?}", x, y, r);
1076 }
1077
1078 for (x,y,r) in sym_cases.into_iter() {
1079 assert!(x.hull(&y) == r, "{:?} hull {:?} is not equal to {:?}", x, y, r);
1080 assert!(y.hull(&x) == r, "{:?} hull {:?} is not equal to {:?}", y, x, r);
1081 }
1082 }
1083
1084 #[test]
1085 fn is_disjoint_test() {
1086 let cases = vec![
1087 (zero, zero, false),
1088 (i1_2, i1_2, false),
1089 (empty, empty, true),
1090 (invalid, invalid, true)
1091 ];
1092
1093 let sym_cases = vec![
1099 (empty, zero, true),
1102 (invalid, zero, true),
1103 (empty, invalid, true),
1104 (empty, i1_2, true),
1107 (empty, i0_10, true),
1108 (invalid, i1_2, true),
1109 (i1_2, i0_10, false),
1112 (i0_4, i5_10, true),
1115 (i0_5, i5_10, false),
1118 (im5_5, i0_10, false),
1121 (i0_10, i20_30, true),
1124 (i0_10, i0_15, false),
1127 (im5_10, i0_10, false)
1130 ];
1131
1132 for (x,y,r) in cases.into_iter() {
1133 assert!(x.is_disjoint(&y) == r, "{:?} is disjoint of {:?} is not equal to {:?}", x, y, r);
1134 assert!(x.overlap(&y) == !r, "{:?} overlap {:?} is not equal to {:?}", x, y, r);
1135 }
1136
1137 for (x,y,r) in sym_cases.into_iter() {
1138 assert!(x.is_disjoint(&y) == r, "{:?} is disjoint of {:?} is not equal to {:?}", x, y, r);
1139 assert!(y.is_disjoint(&x) == r, "{:?} is disjoint of {:?} is not equal to {:?}", y, x, r);
1140 assert!(x.overlap(&y) == !r, "{:?} overlap {:?} is not equal to {:?}", x, y, r);
1141 assert!(y.overlap(&x) == !r, "{:?} overlap {:?} is not equal to {:?}", y, x, r);
1142 }
1143 }
1144
1145 fn is_disjoint_cases() -> Vec<(u32, Interval<i32>, i32, bool)> {
1146 vec![
1147 (1, empty, 0, true),
1148 (2, invalid, 0, true),
1149 (3, i0_4, -1, true),
1150 (4, i0_4, 0, false),
1151 (5, i0_4, 2, false),
1152 (6, i0_4, 3, false),
1153 (7, i0_4, 5, true)
1154 ]
1155 }
1156
1157 #[test]
1158 fn is_disjoint_bound_test() {
1159 let cases = is_disjoint_cases();
1160 for (id, x,y,r) in cases.into_iter() {
1161 assert!(x.is_disjoint(&y) == r, "Test#{}: {:?} is disjoint of {:?} is not equal to {:?}", id, x, y, r);
1162 assert!(y.is_disjoint(&x) == r, "Test#{}: {:?} is disjoint of {:?} is not equal to {:?}", id, y, x, r);
1163 assert!(x.overlap(&y) == !r, "Test#{}: {:?} overlap {:?} is not equal to {:?}", id, x, y, !r);
1164 assert!(y.overlap(&x) == !r, "Test#{}: {:?} overlap {:?} is not equal to {:?}", id, y, x, !r);
1165 }
1166 }
1167
1168 #[test]
1169 fn is_disjoint_option_test() {
1170 let mut cases: Vec<(u32, Interval<i32>, Optional<i32>, bool)> = is_disjoint_cases().into_iter()
1171 .map(|(id,a,b,e)| (id, a, Optional::singleton(b), e))
1172 .collect();
1173 cases.extend(vec![
1174 (8, empty, Optional::empty(), true),
1175 (9, invalid, Optional::empty(), true),
1176 (10, i0_4, Optional::empty(), true)
1177 ]);
1178 for (id, x,y,r) in cases.into_iter() {
1179 assert!(x.is_disjoint(&y) == r, "Test#{}: {:?} is disjoint of {:?} is not equal to {:?}", id, x, y, r);
1180 assert!(y.is_disjoint(&x) == r, "Test#{}: {:?} is disjoint of {:?} is not equal to {:?}", id, y, x, r);
1181 assert!(x.overlap(&y) == !r, "Test#{}: {:?} overlap {:?} is not equal to {:?}", id, x, y, !r);
1182 assert!(y.overlap(&x) == !r, "Test#{}: {:?} overlap {:?} is not equal to {:?}", id, y, x, !r);
1183 }
1184 }
1185
1186 #[test]
1187 fn difference_test() {
1188 let cases = vec![
1189 (1, zero, zero, empty),
1190 (2, i1_2, i1_2, empty),
1191 (3, empty, empty, empty),
1192 (4, invalid, invalid, empty)
1193 ];
1194
1195 let sym_cases = vec![
1201 (5, empty, zero, (empty, zero)),
1204 (6, invalid, zero, (empty, zero)),
1205 (7, empty, invalid, (empty, empty)),
1206 (8, empty, i1_2, (empty, i1_2)),
1209 (9, empty, i0_10, (empty, i0_10)),
1210 (10, invalid, i1_2, (empty, i1_2)),
1211 (11, i1_2, i0_10, (empty, i0_10)),
1214 (12, i0_4, i5_10, (i0_4, i5_10)),
1217 (13, i0_5, i5_10, ((0,4).to_interval(), i6_10)),
1220 (14, im5_5, i0_10, (im5_m1, i6_10)),
1223 (15, i0_10, i20_30, (i0_10, i20_30)),
1226 (16, i0_10, i0_15, (empty, (11,15).to_interval())),
1229 (17, im5_10, i0_10, (im5_m1, empty))
1232 ];
1233
1234 for (id,x,y,r) in cases.into_iter() {
1235 println!("Test #{}", id);
1236 assert!(x.difference(&y) == r, "{:?} difference {:?} is not equal to {:?}", x, y, r);
1237 }
1238
1239 for (id,x,y,(r1,r2)) in sym_cases.into_iter() {
1240 println!("Test #{}", id);
1241 assert!(x.difference(&y) == r1, "{:?} difference {:?} is not equal to {:?}", x, y, r1);
1242 assert!(y.difference(&x) == r2, "{:?} difference {:?} is not equal to {:?}", y, x, r2);
1243 }
1244 }
1245
1246 #[test]
1247 fn difference_value_option_test() {
1248 let cases = vec![
1249 (1, empty, None, empty, None),
1250 (2, invalid, None, empty, None),
1251 (3, empty, Some(1), empty, Some(1)),
1252 (4, i0_10, None, i0_10, None),
1253 (5, i0_10, Some(0), i1_10, None),
1254 (6, i0_10, Some(10), i0_9, None),
1255 (7, i0_10, Some(1), i0_10, None),
1256 (8, i0_10, Some(9), i0_10, None),
1257 (9, i0_10, Some(-1), i0_10, Some(-1)),
1258 (10, i0_10, Some(11), i0_10, Some(11)),
1259 (11, i0_10, Some(100),i0_10, Some(100)),
1260 (12, one, Some(1), empty, None),
1261 ];
1262 for (id,x,y,r1,r2) in cases.into_iter() {
1263 let y = y.map_or(Optional::empty(), |y| Optional::singleton(y));
1264 let r2 = r2.map_or(Optional::empty(), |r2| Optional::singleton(r2));
1265 if y.is_some() {
1267 assert!(x.difference(y.as_ref().unwrap()) == r1,
1268 "Test#{}: {:?} difference {:?} is not equal to {:?}", id, x, y.as_ref().unwrap(), r1);
1269 }
1270 assert!(x.difference(&y) == r1, "Test#{}: {:?} difference {:?} is not equal to {:?}", id, x, y, r1);
1272 assert!(y.difference(&x) == r2, "Test#{}: {:?} difference {:?} is not equal to {:?}", id, y, x, r2);
1274 }
1275 }
1276
1277 #[test]
1278 fn shrink_left_test() {
1279 let cases = vec![
1280 (i0_10, -5, i0_10),
1281 (i0_10, 0, i0_10),
1282 (i0_10, 1, i1_10),
1283 (i0_10, 5, i5_10),
1284 (i0_10, 10, ten),
1285 (i0_10, 11, empty),
1286 (i0_10, 100, empty),
1287 (empty, 0, empty)
1288 ];
1289 for (x,y,r) in cases.into_iter() {
1290 assert!(x.shrink_left(y) == r, "{:?} shrink_left {:?} is not equal to {:?}", x, y, r);
1291 }
1292 }
1293
1294 #[test]
1295 fn shrink_right_test() {
1296 let cases = vec![
1297 (i0_10, 15, i0_10),
1298 (i0_10, 10, i0_10),
1299 (i0_10, 9, i0_9),
1300 (i0_10, 5, i0_5),
1301 (i0_10, 0, zero),
1302 (i0_10, -1, empty),
1303 (i0_10, -100, empty),
1304 (empty, 0, empty)
1305 ];
1306 for (x,y,r) in cases.into_iter() {
1307 assert!(x.shrink_right(y) == r, "{:?} shrink_right {:?} is not equal to {:?}", x, y, r);
1308 }
1309 }
1310
1311 #[test]
1312 fn add_sub_mul_bound_test() {
1313 let cases = vec![
1317 (zero, 0, zero, zero, zero),
1318 (i1_2, 0, i1_2, i1_2, zero),
1319 (empty, 0, empty, empty, empty),
1320 (invalid, 0, empty, empty, empty),
1321 (zero, 1, one, (-1,-1).to_interval(), zero),
1322 (i1_2, 1, (2,3).to_interval(), (0,1).to_interval(), i1_2),
1323 (empty, 1, empty, empty, empty),
1324 (invalid, 1, empty, empty, empty),
1325 (zero, 3, (3,3).to_interval(), (-3,-3).to_interval(), zero),
1326 (i1_2, 3, (4,5).to_interval(), (-2,-1).to_interval(), (3, 6).to_interval()),
1327 (empty, 3, empty, empty, empty),
1328 (invalid, 3, empty, empty, empty),
1329 ];
1330
1331 for &(x,y,r1,r2,r3) in &cases {
1332 assert!(x + y == r1, "{:?} + {:?} is not equal to {:?}", x, y, r1);
1333 assert!(x - y == r2, "{:?} - {:?} is not equal to {:?}", x, y, r2);
1334 assert!(x * y == r3, "{:?} * {:?} is not equal to {:?}", x, y, r3);
1335 }
1336 }
1337
1338
1339 #[test]
1340 fn add_test() {
1341 let sym_cases = vec![
1345 (zero, zero, zero),
1346 (i1_2, i1_2, (2, 4).to_interval()),
1347 (empty, empty, empty),
1348 (invalid, invalid, empty),
1349 (empty, zero, empty),
1352 (invalid, zero, empty),
1353 (empty, invalid, empty),
1354 (empty, i1_2, empty),
1357 (empty, i0_10, empty),
1358 (invalid, i1_2, empty),
1359 (zero, i0_10, i0_10),
1360 (i1_2, i0_10, (1,12).to_interval()),
1361 (im5_10, i0_10, (-5,20).to_interval()),
1362 (im5_10, im30_m20, (-35,-10).to_interval())
1363 ];
1364
1365 for &(x,y,r) in &sym_cases {
1366 assert!(x + y == r, "{:?} + {:?} is not equal to {:?}", x, y, r);
1367 assert!(y + x == r, "{:?} + {:?} is not equal to {:?}", y, x, r);
1368 }
1369 }
1370
1371 #[test]
1372 fn sub_test() {
1373 let cases = vec![
1377 (zero, zero, zero),
1378 (i1_2, i1_2, (-1, 1).to_interval()),
1379 (empty, empty, empty),
1380 (invalid, invalid, empty),
1381 (empty, zero, empty),
1384 (invalid, zero, empty),
1385 (empty, invalid, empty),
1386 (empty, i1_2, empty),
1389 (empty, i0_10, empty),
1390 (invalid, i1_2, empty),
1391 ];
1392
1393 let sym_cases = vec![
1397 (zero, i0_10, ((-10,0), (0,10))),
1398 (i1_2, i0_10, ((-9,2), (-2, 9))),
1399 (im5_10, i0_10, ((-15,10), (-10, 15))),
1400 (im5_10, im30_m20, ((15,40), (-40,-15)))
1401 ];
1402
1403 for &(x,y,r) in &cases {
1404 assert!(x - y == r, "{:?} - {:?} is not equal to {:?}", x, y, r);
1405 assert!(y - x == r, "{:?} - {:?} is not equal to {:?}", y, x, r);
1406 }
1407
1408 for &(x,y,(r1, r2)) in &sym_cases {
1409 let r1 = r1.to_interval();
1410 let r2 = r2.to_interval();
1411 assert!(x - y == r1, "{:?} - {:?} is not equal to {:?}", x, y, r1);
1412 assert!(y - x == r2, "{:?} - {:?} is not equal to {:?}", y, x, r2);
1413 }
1414 }
1415
1416 #[test]
1417 fn mul_test() {
1418 let sym_cases = vec![
1422 (zero, zero, zero),
1423 (i1_2, i1_2, (1, 4).to_interval()),
1424 (empty, empty, empty),
1425 (invalid, invalid, empty),
1426 (empty, zero, empty),
1429 (invalid, zero, empty),
1430 (empty, invalid, empty),
1431 (empty, i1_2, empty),
1434 (empty, i0_10, empty),
1435 (invalid, i1_2, empty),
1436 (zero, i0_10, zero),
1437 (one, i0_10, i0_10),
1438 (i1_2, i0_10, (0,20).to_interval()),
1439 (im5_10, i0_10, (-50,100).to_interval()),
1440 (im5_10, im30_m20, (-300,150).to_interval())
1441 ];
1442
1443 for &(x,y,r) in &sym_cases {
1444 assert!(x * y == r, "{:?} * {:?} is not equal to {:?}", x, y, r);
1445 assert!(y * x == r, "{:?} * {:?} is not equal to {:?}", y, x, r);
1446 }
1447 }
1448
1449 #[test]
1450 fn test_lattice() {
1451 use gcollections::ops::lattice::test::*;
1452 use trilean::SKleene::*;
1453 let whole = Interval::<i32>::whole();
1454 let tester = LatticeTester::new(
1455 0,
1456 vec![empty, empty, whole, zero, zero, zero, i1_2, i0_10, im5_5],
1457 vec![zero, whole, empty, zero, one, i1_2, i0_10,im5_5, i6_10],
1458 vec![True, True, False, True, Unknown, Unknown,True, Unknown,Unknown],
1459 vec![empty, empty, empty, zero, empty, empty, i1_2, i0_5, empty],
1460 vec![zero, whole, whole, zero, i0_1, i0_2, i0_10,im5_10, im5_10]
1461 );
1462 tester.test_all();
1463 }
1464}