1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
#[derive(Debug, PartialEq, Eq, Clone)] pub enum BoundType { Inclusive, Exclusive, } use std::cmp::Ordering; use std::ops::Add; use std::ops::Mul; use std::ops::Neg; #[derive(Debug, Eq, PartialEq, Clone)] pub struct Bound<T> { pub bound_type: BoundType, pub value: T, } impl<T: Ord> Bound<T> { pub fn upper_bound_max(a: Self, b: Self) -> Self { if a.is_upper_bound_max(&b) { a } else { b } } pub fn is_upper_bound_max(&self, other: &Self) -> bool { match self.value.cmp(&other.value) { Ordering::Greater => true, Ordering::Less => false, Ordering::Equal => self.bound_type == BoundType::Inclusive, } } pub fn lower_bound_min(a: Self, b: Self) -> Self { if a.is_lower_bound_min(&b) { a } else { b } } pub fn is_lower_bound_min(&self, other: &Self) -> bool { match self.value.cmp(&other.value) { Ordering::Greater => false, Ordering::Less => true, Ordering::Equal => self.bound_type == BoundType::Inclusive, } } } impl<T> Bound<T> { pub fn inclusive(value: T) -> Bound<T> { Bound { bound_type: BoundType::Inclusive, value, } } pub fn exclusive(value: T) -> Bound<T> { Bound { bound_type: BoundType::Exclusive, value, } } pub fn to_exclusive(self) -> Bound<T> { Bound::exclusive(self.value) } pub fn combine<F: FnOnce(T, T) -> T>(self, other: Self, func: F) -> Self { let bound_type = if self.bound_type == BoundType::Exclusive || other.bound_type == BoundType::Exclusive { BoundType::Exclusive } else { BoundType::Inclusive }; Bound { bound_type, value: func(self.value, other.value), } } } impl<T: Neg<Output = T>> Neg for Bound<T> { type Output = Self; fn neg(self) -> Self::Output { Bound { bound_type: self.bound_type, value: -self.value, } } } impl<T: Add<T, Output = T>> Add for Bound<T> { type Output = Self; fn add(self, other: Self) -> Self::Output { self.combine(other, Add::add) } } impl<T: Mul<T, Output = T>> Mul for Bound<T> { type Output = Self; fn mul(self, other: Self) -> Self::Output { self.combine(other, Mul::mul) } }