use core::ops::Add;
impl<RHS, T: Add<RHS> + Sized + Copy> BoundedAdd<RHS> for T where
<Self as Add<RHS>>::Output: PartialOrd
{
}
pub trait BoundedAdd<RHS>: Add<RHS> + Sized + Copy
where
<Self as Add<RHS>>::Output: PartialOrd,
{
fn bounded_add(
self,
rhs: RHS,
lower: <Self as Add<RHS>>::Output,
upper: <Self as Add<RHS>>::Output,
) -> <Self as Add<RHS>>::Output {
if lower > upper {
panic!("lower bound exceeds upper bound!");
}
let out = self + rhs;
if out < lower {
lower
} else if out > upper {
upper
} else {
out
}
}
}
impl<RHS, T: PartialOrd + BoundedAdd<RHS> + Add<RHS, Output = T>> BoundedAddAssign<RHS> for T {}
pub trait BoundedAddAssign<RHS>: BoundedAdd<RHS> + Add<RHS, Output = Self>
where
Self: PartialOrd,
{
fn bounded_add_assign(&mut self, rhs: RHS, lower: Self, upper: Self) {
*self = self.bounded_add(rhs, lower, upper);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bounded_add() {
assert_eq!(4.bounded_add(3, 0, 10), 7);
assert_eq!(4.bounded_add(3, 0, 6), 6);
assert_eq!(4.bounded_add(-5, 0, 6), 0);
let mut x = 3.0;
x.bounded_add_assign(4., 0., 5.);
assert!((4.999..5.001).contains(&x));
}
}