1use gcollections::kind::*;
12use num_integer::Integer;
13use num_traits::Bounded as NumBounded;
14use num_traits::Unsigned;
15
16pub trait Hull<RHS = Self> {
18 type Output;
19 fn hull(&self, rhs: &RHS) -> Self::Output;
20}
21
22pub trait Range: Collection {
24 fn new(lb: Self::Item, ub: Self::Item) -> Self;
25}
26
27pub trait Whole {
29 fn whole() -> Self;
30}
31
32pub trait Width: Ord + Clone {
34 type Output: Unsigned + Integer + Clone;
35
36 fn min_value() -> Self;
38 fn max_value() -> Self;
40 fn width(lower: &Self, upper: &Self) -> Self::Output;
42}
43
44macro_rules! unsigned_width_impl
45{
46 ( $( $t: ty ),* ) =>
47 {$(
48 impl Width for $t
49 {
50 type Output = $t;
51
52 fn max_value() -> $t {
53 <$t as NumBounded>::max_value() - 1
54 }
55
56 fn min_value() -> $t {
57 <$t as NumBounded>::min_value()
58 }
59
60 fn width(lower: &$t, upper: &$t) -> $t {
61 let lower = *lower;
62 let upper = *upper;
63 debug_assert!(upper <= <$t as Width>::max_value(),
64 "Width cannot be represented because the value exceeds the maximum value allowed.");
65 debug_assert!(lower <= upper);
66 upper - lower + 1
67 }
68 }
69 )*}
70}
71
72macro_rules! signed_width_impl
73{
74 ( $( $t: ty, $u: ty ),* ) =>
75 {$(
76 impl Width for $t
77 {
78 type Output = $u;
79
80 fn max_value() -> $t {
81 <$t as NumBounded>::max_value()
82 }
83
84 fn min_value() -> $t {
85 <$t as NumBounded>::min_value() + 1
86 }
87
88 fn width(lower: &$t, upper: &$t) -> $u {
89 let lower = *lower;
90 let upper = *upper;
91 debug_assert!(lower >= <$t as Width>::min_value(),
92 "Width cannot be represented because the value exceeds the minimum value allowed.");
93 debug_assert!(lower <= upper);
94 let size =
95 if lower < 0 && upper > 0 {
97 (-lower as $u) + (upper as $u)
98 } else {
99 (upper - lower) as $u
100 };
101 size + 1
102 }
103 }
104 )*}
105}
106
107unsigned_width_impl!(u8, u16, u32, u64, usize);
108signed_width_impl!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
109
110#[allow(non_upper_case_globals)]
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::interval::*;
115 use gcollections::ops::*;
116
117 #[test]
118 fn strict_shrink_left() {
119 let empty: Interval<u32> = Interval::empty();
120 let i0_10: Interval<u32> = Interval::new(0, 10);
121 let i2_10: Interval<u32> = Interval::new(2, 10);
122
123 let ub = u32::max_value();
124 assert_eq!(i0_10.strict_shrink_left(ub), empty);
125 assert_eq!(i0_10.strict_shrink_left(10u32), empty);
126 assert_eq!(i0_10.strict_shrink_left(1u32), i2_10);
127 }
128
129 #[test]
130 fn strict_shrink_right() {
131 let empty: Interval<u32> = Interval::empty();
132 let i0_10: Interval<u32> = Interval::new(0, 10);
133 let i0_8: Interval<u32> = Interval::new(0, 8);
134
135 let lb = u32::min_value();
136 assert_eq!(i0_10.strict_shrink_right(lb), empty);
137 assert_eq!(i0_10.strict_shrink_right(0u32), empty);
138 assert_eq!(i0_10.strict_shrink_right(9u32), i0_8);
139 }
140}