use super::*;
use crate::std::*;
#[derive(Debug, Clone, Copy, Default)]
pub struct BoundedU<const MAX: usize, const WIDTH: usize = { clog2(MAX) }> {
value: U<WIDTH>,
}
impl<const MAX: usize, const WIDTH: usize> BoundedU<MAX, WIDTH> {
pub fn new(value: U<WIDTH>) -> Self {
Self { value }
}
pub fn incr(self) -> Self
where [(); WIDTH + 1]: {
let incr = (self.value + 1.into_u()).resize();
if incr == MAX.into_u() {
Self::default()
} else {
BoundedU { value: incr }
}
}
pub fn value(self) -> U<WIDTH> {
self.value
}
}
pub fn wrapping_add<const N: usize>(a: U<N>, b: U<N>, max: U<{ N + 1 }>) -> U<N> {
let out = if a.resize::<{ N + 1 }>() >= max - b.resize::<{ N + 1 }>() { a + b - max } else { a + b };
out.resize::<N>()
}
pub fn wrapping_inc<const N: usize>(value: U<N>, max: U<{ N + 1 }>) -> U<N> {
wrapping_add::<N>(value, U::from(1), max)
}
pub fn floor_add<const N: usize>(a: U<N>, b: U<N>, max: U<{ N + 1 }>) -> U<N> {
if a + b >= max {
0.into_u()
} else {
a.trunk_add(b)
}
}