use super::{const_div, const_is_zero, FixedUInt, MachineWord};
use crate::const_numtraits::{ConstCheckedAdd, ConstDivCeil, ConstOne};
use crate::machineword::ConstMachineWord;
c0nst::c0nst! {
impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstDivCeil for FixedUInt<T, N> {
fn div_ceil(self, rhs: Self) -> Self {
match self.checked_div_ceil(rhs) {
Some(v) => v,
None => panic!("div_ceil: division by zero or overflow"),
}
}
fn checked_div_ceil(self, rhs: Self) -> Option<Self> {
if const_is_zero(&rhs.array) {
return None;
}
let mut quotient = self.array;
let remainder = const_div(&mut quotient, &rhs.array);
if const_is_zero(&remainder) {
Some(Self { array: quotient })
} else {
ConstCheckedAdd::checked_add(&Self { array: quotient }, &Self::one())
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_div_ceil() {
type U16 = FixedUInt<u8, 2>;
assert_eq!(
ConstDivCeil::div_ceil(U16::from(10u8), U16::from(5u8)),
U16::from(2u8)
);
assert_eq!(
ConstDivCeil::div_ceil(U16::from(10u8), U16::from(2u8)),
U16::from(5u8)
);
assert_eq!(
ConstDivCeil::div_ceil(U16::from(10u8), U16::from(3u8)),
U16::from(4u8)
); assert_eq!(
ConstDivCeil::div_ceil(U16::from(11u8), U16::from(3u8)),
U16::from(4u8)
); assert_eq!(
ConstDivCeil::div_ceil(U16::from(12u8), U16::from(3u8)),
U16::from(4u8)
);
assert_eq!(
ConstDivCeil::div_ceil(U16::from(0u8), U16::from(5u8)),
U16::from(0u8)
);
assert_eq!(
ConstDivCeil::div_ceil(U16::from(1u8), U16::from(5u8)),
U16::from(1u8)
); assert_eq!(
ConstDivCeil::div_ceil(U16::from(1u8), U16::from(1u8)),
U16::from(1u8)
);
}
#[test]
fn test_checked_div_ceil() {
type U16 = FixedUInt<u8, 2>;
assert_eq!(
ConstDivCeil::checked_div_ceil(U16::from(10u8), U16::from(3u8)),
Some(U16::from(4u8))
);
assert_eq!(
ConstDivCeil::checked_div_ceil(U16::from(10u8), U16::from(0u8)),
None
);
assert_eq!(
ConstDivCeil::checked_div_ceil(U16::from(65535u16), U16::from(2u16)),
Some(U16::from(32768u16))
);
assert_eq!(
ConstDivCeil::checked_div_ceil(U16::from(65535u16), U16::from(1u16)),
Some(U16::from(65535u16))
);
}
c0nst::c0nst! {
pub c0nst fn const_div_ceil<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
a: FixedUInt<T, N>,
b: FixedUInt<T, N>,
) -> FixedUInt<T, N> {
ConstDivCeil::div_ceil(a, b)
}
}
#[test]
fn test_const_div_ceil() {
type U16 = FixedUInt<u8, 2>;
assert_eq!(
const_div_ceil(U16::from(10u8), U16::from(3u8)),
U16::from(4u8)
);
#[cfg(feature = "nightly")]
{
const TEN: U16 = FixedUInt { array: [10, 0] };
const THREE: U16 = FixedUInt { array: [3, 0] };
const RESULT: U16 = const_div_ceil(TEN, THREE);
assert_eq!(RESULT, FixedUInt { array: [4, 0] });
}
}
}