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