interval/
interval.rs

1// Copyright 2015 Pierre Talbot (IRCAM)
2
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Closed and bounded generic interval.
10//!
11//! Let `D` be an ordered set and `{i,j} ∈ D`. The interval `I` whose bounds are `{i,j}` is defined as `I = {x ∈ D | i <= x <= j}` and is denoted as `[i..j]`. Only interval with bound types implementing `Num` and `Width` is currently available.
12//!
13//! Most of the operations in `gcollections::ops::*` are implemented. Intervals specific operations, proposed in `ops::*`, are also implemented. There is no `union` operation since this interval representation is not precise enough, and so an union could be over-approximated. For example, consider `[1..2] U [5..6]`, the only possible representation is `[1..6]` which is not exact by the definition of union of sets. However, this operation exists and is named `hull`.
14//!
15//! # Examples
16//!
17//! ```rust
18//! use crate::interval::Interval;
19//! use crate::interval::ops::*;
20//! use gcollections::ops::*;
21//!
22//! # fn main() {
23//! let a = Interval::new(0, 5);
24//! let b = Interval::singleton(10);
25//!
26//! let c = a.hull(&b);
27//! let d = c.difference(&a);
28//!
29//! assert_eq!(c, Interval::new(0,10));
30//! assert_eq!(d, Interval::new(6,10));
31//! # }
32//! ```
33//!
34//! # See also
35//! [interval set](../interval_set/index.html).
36
37use 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/// Closed interval (endpoints included).
48#[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
158/// `IsSingleton` and `IsEmpty` are defined automatically in `gcollections`.
159impl<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  // A - B is equivalent to A /\ ~B
413  // However the complement operation doesn't make sense here
414  // because it'd nearly always ends up to the whole integer interval.
415  // Instead we use this equivalence:
416  //   A - B is equivalent to:
417  //      A /\ [inf,B.lb-1]
418  //    \/
419  //      A /\ [B.ub+1, inf]
420  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
565// Adapted from the code found in the Rust compiler sources.
566// Rational: min_max was removed.
567fn 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      // `first` and `second` are the two next elements we want to look
581      // at.  We first compare `first` and `second` (#1). The smaller one
582      // is then compared to current minimum (#2). The larger one is
583      // compared to current maximum (#3). This way we do 3 comparisons
584      // for 2 elements.
585      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  // Caution: Consider `[0,1] * [3,5]`, the result `[0,5]` is an over-approximation.
617  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  // Caution: Consider `[0,1] * 3`, the result `[0,3]` is an over-approximation.
639  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    // For each cases (x, y, res)
831    // * x and y are the values
832    // * res is a tuple (r, sym) where
833    //    * r is true if x is a subset of y
834    //    * sym is true if y is a subset of x
835    let sym_cases = vec![
836      // ||
837      // |-|
838      (empty, zero,         (true, false)),
839      (invalid, zero,       (true, false)),
840      (empty, invalid,      (true, true)),
841      // ||
842      //|--|
843      (empty, i1_2,         (true, false)),
844      (empty, i0_10,        (true, false)),
845      (invalid, i1_2,       (true, false)),
846      //  |--|
847      // |----|
848      (i1_2, i0_10,         (true, false)),
849      // |--|
850      //     |--|
851      (i0_4, i5_10,         (false, false)),
852      // |--|
853      //    |--|
854      (i0_5, i5_10,         (false, false)),
855      // |---|
856      //   |---|
857      (im5_5, i0_10,        (false, false)),
858      // |--|
859      //         |--|
860      (i0_10, i20_30,       (false, false)),
861      // |--|
862      // |---|
863      (i0_10, i0_15,        (true, false)),
864      // |---|
865      //  |--|
866      (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    // For each cases (x, y, res)
889    // * x and y are the values
890    // * res is a tuple (r, sym) where
891    //    * r is true if x is a proper subset of y
892    //    * sym is true if y is a proper subset of x
893    let sym_cases = vec![
894      // ||
895      // |-|
896      (empty, zero,         (true, false)),
897      (invalid, zero,       (true, false)),
898      (empty, invalid,      (false, false)),
899      // ||
900      //|--|
901      (empty, i1_2,         (true, false)),
902      (empty, i0_10,        (true, false)),
903      (invalid, i1_2,       (true, false)),
904      //  |--|
905      // |----|
906      (i1_2, i0_10,         (true, false)),
907      // |--|
908      //     |--|
909      (i0_4, i5_10,         (false, false)),
910      // |--|
911      //    |--|
912      (i0_5, i5_10,         (false, false)),
913      // |---|
914      //   |---|
915      (im5_5, i0_10,        (false, false)),
916      // |--|
917      //         |--|
918      (i0_10, i20_30,       (false, false)),
919      // |--|
920      // |---|
921      (i0_10, i0_15,        (true, false)),
922      // |---|
923      //  |--|
924      (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    // For each cases (x, y, res)
947    // * x and y are the values
948    // * res is the expected result, which should be the same
949    // for x intersect y and y intersect x since the intersection
950    // is commutative.
951    let sym_cases = vec![
952      // ||
953      // |-|
954      (empty, zero,         empty),
955      (invalid, zero,       empty),
956      (empty, invalid,      empty),
957      // ||
958      //|--|
959      (empty, i1_2,         empty),
960      (empty, i0_10,        empty),
961      (invalid, i1_2,       empty),
962      //  |--|
963      // |----|
964      (i1_2, i0_10,         i1_2),
965      // |--|
966      //     |--|
967      (i0_4, i5_10,         empty),
968      // |--|
969      //    |--|
970      (i0_5, i5_10,         5.to_interval()),
971      // |---|
972      //   |---|
973      (im5_5, i0_10,        (0,5).to_interval()),
974      // |--|
975      //         |--|
976      (i0_10, i20_30,       empty),
977      // |--|
978      // |---|
979      (i0_10, i0_15,        i0_10),
980      // |---|
981      //  |--|
982      (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      // Interval /\ Value.
1014      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      // Interval /\ Option<T>
1019      assert!(x.intersection(&y) == r1, "Test#{}: {:?} intersection {:?} is not equal to {:?}", id, x, y, r1);
1020      // Option<T> /\ Interval
1021      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    // For each cases (x, y, res)
1036    // * x and y are the values
1037    // * res is the expected result, which should be the same
1038    // for the union hull of (x,y) or (y,x) since the union hull
1039    // is commutative.
1040    let sym_cases = vec![
1041      // ||
1042      // |-|
1043      (empty, zero,         zero),
1044      (invalid, zero,       zero),
1045      (empty, invalid,      empty),
1046      // ||
1047      //|--|
1048      (empty, i1_2,         i1_2),
1049      (empty, i0_10,        i0_10),
1050      (invalid, i1_2,       i1_2),
1051      //  |--|
1052      // |----|
1053      (i1_2, i0_10,         i0_10),
1054      // |--|
1055      //     |--|
1056      (i0_4, i5_10,         i0_10),
1057      // |--|
1058      //    |--|
1059      (i0_5, i5_10,         i0_10),
1060      // |---|
1061      //   |---|
1062      (im5_5, i0_10,        (-5,10).to_interval()),
1063      // |--|
1064      //         |--|
1065      (i0_10, i20_30,       (0,30).to_interval()),
1066      // |--|
1067      // |---|
1068      (i0_10, i0_15,        i0_15),
1069      // |---|
1070      //  |--|
1071      (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    // For each cases (x, y, res)
1094    // * x and y are the values
1095    // * res is the expected result, which should be the same
1096    // for x is disjoint of y and y is disjoint of x since the
1097    // disjoint operation is commutative.
1098    let sym_cases = vec![
1099      // ||
1100      // |-|
1101      (empty, zero,         true),
1102      (invalid, zero,       true),
1103      (empty, invalid,      true),
1104      // ||
1105      //|--|
1106      (empty, i1_2,         true),
1107      (empty, i0_10,        true),
1108      (invalid, i1_2,       true),
1109      //  |--|
1110      // |----|
1111      (i1_2, i0_10,         false),
1112      // |--|
1113      //     |--|
1114      (i0_4, i5_10,         true),
1115      // |--|
1116      //    |--|
1117      (i0_5, i5_10,         false),
1118      // |---|
1119      //   |---|
1120      (im5_5, i0_10,        false),
1121      // |--|
1122      //         |--|
1123      (i0_10, i20_30,       true),
1124      // |--|
1125      // |---|
1126      (i0_10, i0_15,        false),
1127      // |---|
1128      //  |--|
1129      (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    // For each cases (x, y, res)
1196    // * x and y are the values
1197    // * res is a tuple (r, sym) where
1198    //    * x diff y == r
1199    //    * y diff x == sym
1200    let sym_cases = vec![
1201      // ||
1202      // |-|
1203      (5, empty, zero,         (empty, zero)),
1204      (6, invalid, zero,       (empty, zero)),
1205      (7, empty, invalid,      (empty, empty)),
1206      // ||
1207      //|--|
1208      (8, empty, i1_2,         (empty, i1_2)),
1209      (9, empty, i0_10,        (empty, i0_10)),
1210      (10, invalid, i1_2,       (empty, i1_2)),
1211      //  |--|
1212      // |----|
1213      (11, i1_2, i0_10,         (empty, i0_10)),
1214      // |--|
1215      //     |--|
1216      (12, i0_4, i5_10,         (i0_4, i5_10)),
1217      // |--|
1218      //    |--|
1219      (13, i0_5, i5_10,         ((0,4).to_interval(), i6_10)),
1220      // |---|
1221      //   |---|
1222      (14, im5_5, i0_10,        (im5_m1, i6_10)),
1223      // |--|
1224      //         |--|
1225      (15, i0_10, i20_30,       (i0_10, i20_30)),
1226      // |--|
1227      // |---|
1228      (16, i0_10, i0_15,        (empty, (11,15).to_interval())),
1229      // |---|
1230      //  |--|
1231      (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      // Interval - Value.
1266      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      // Interval - Option<T>
1271      assert!(x.difference(&y) == r1, "Test#{}: {:?} difference {:?} is not equal to {:?}", id, x, y, r1);
1272      // Option<T> - Interval
1273      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    // For each cases (x, y, r1, r2, r3)
1314    // * x and y are the values
1315    // * r1,r2 and r3 are the results of `x + y`, `x - y` and `x * y`
1316    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    // For each cases (x, y, res)
1342    // * x and y are the values
1343    // * res is the result of `x + y`
1344    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      // ||
1350      // |-|
1351      (empty, zero,         empty),
1352      (invalid, zero,       empty),
1353      (empty, invalid,      empty),
1354      // ||
1355      //|--|
1356      (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    // For each cases (x, y, res)
1374    // * x and y are the values
1375    // * res is the result of `x - y`
1376    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      // ||
1382      // |-|
1383      (empty, zero,         empty),
1384      (invalid, zero,       empty),
1385      (empty, invalid,      empty),
1386      // ||
1387      //|--|
1388      (empty, i1_2,         empty),
1389      (empty, i0_10,        empty),
1390      (invalid, i1_2,       empty),
1391    ];
1392
1393    // For each cases (x, y, (res1, res2))
1394    // * x and y are the values
1395    // * res1 is the result of `x - y` and res2 of `y - x`
1396    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    // For each cases (x, y, res)
1419    // * x and y are the values
1420    // * res is the result of `x * y`
1421    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      // ||
1427      // |-|
1428      (empty, zero,         empty),
1429      (invalid, zero,       empty),
1430      (empty, invalid,      empty),
1431      // ||
1432      //|--|
1433      (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      /* data_a */  vec![empty, empty, whole, zero, zero,    zero,   i1_2, i0_10,  im5_5],
1457      /* data_b */  vec![zero,  whole, empty, zero, one,     i1_2,   i0_10,im5_5,  i6_10],
1458      /* a |= b*/   vec![True,  True,  False, True, Unknown, Unknown,True, Unknown,Unknown],
1459      /* a |_| b */ vec![empty, empty, empty, zero, empty,   empty,  i1_2, i0_5,   empty],
1460      /* a |-| b */ vec![zero,  whole, whole, zero, i0_1,    i0_2,   i0_10,im5_10, im5_10]
1461    );
1462    tester.test_all();
1463  }
1464}