use super::{FixedUInt, MachineWord};
use crate::machineword::ConstMachineWord;
use const_num_traits::Nct;
use const_num_traits::{CheckedAdd, MultipleOf, NextMultipleOf, Zero};
c0nst::c0nst! {
c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> MultipleOf for FixedUInt<T, N, Nct> {
fn is_multiple_of(self, rhs: Self) -> bool {
if <Self as Zero>::is_zero(&rhs) {
false
} else {
<Self as Zero>::is_zero(&(self % rhs))
}
}
}
c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> NextMultipleOf for FixedUInt<T, N, Nct> {
fn next_multiple_of(self, rhs: Self) -> Self {
match self.checked_next_multiple_of(rhs) {
Some(v) => v,
None => panic!("next_multiple_of: rhs is zero or result overflows"),
}
}
fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
if rhs.is_zero() {
return None;
}
let rem = self % rhs;
if rem.is_zero() {
Some(self)
} else {
let add = rhs - rem;
CheckedAdd::checked_add(self, add)
}
}
}
c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> MultipleOf for &FixedUInt<T, N, Nct> {
fn is_multiple_of(self, rhs: Self) -> bool {
<FixedUInt<T, N, Nct> as MultipleOf>::is_multiple_of(*self, *rhs)
}
}
c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> NextMultipleOf for &FixedUInt<T, N, Nct> {
fn next_multiple_of(self, rhs: Self) -> FixedUInt<T, N, Nct> {
<FixedUInt<T, N, Nct> as NextMultipleOf>::next_multiple_of(*self, *rhs)
}
fn checked_next_multiple_of(self, rhs: Self) -> Option<FixedUInt<T, N, Nct>> {
<FixedUInt<T, N, Nct> as NextMultipleOf>::checked_next_multiple_of(*self, *rhs)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_multiple_of() {
type U16 = FixedUInt<u8, 2>;
assert!(MultipleOf::is_multiple_of(U16::from(0u8), U16::from(5u8)));
assert!(MultipleOf::is_multiple_of(U16::from(10u8), U16::from(5u8)));
assert!(MultipleOf::is_multiple_of(U16::from(15u8), U16::from(5u8)));
assert!(!MultipleOf::is_multiple_of(U16::from(11u8), U16::from(5u8)));
assert!(MultipleOf::is_multiple_of(
U16::from(100u8),
U16::from(10u8)
));
assert!(!MultipleOf::is_multiple_of(
U16::from(101u8),
U16::from(10u8)
));
assert!(!MultipleOf::is_multiple_of(U16::from(10u8), U16::from(0u8)));
}
#[test]
fn test_next_multiple_of() {
type U16 = FixedUInt<u8, 2>;
assert_eq!(
NextMultipleOf::next_multiple_of(U16::from(10u8), U16::from(5u8)),
U16::from(10u8)
);
assert_eq!(
NextMultipleOf::next_multiple_of(U16::from(0u8), U16::from(5u8)),
U16::from(0u8)
);
assert_eq!(
NextMultipleOf::next_multiple_of(U16::from(11u8), U16::from(5u8)),
U16::from(15u8)
);
assert_eq!(
NextMultipleOf::next_multiple_of(U16::from(12u8), U16::from(5u8)),
U16::from(15u8)
);
assert_eq!(
NextMultipleOf::next_multiple_of(U16::from(14u8), U16::from(5u8)),
U16::from(15u8)
);
assert_eq!(
NextMultipleOf::next_multiple_of(U16::from(101u8), U16::from(10u8)),
U16::from(110u8)
);
}
#[test]
fn test_checked_next_multiple_of() {
type U16 = FixedUInt<u8, 2>;
assert_eq!(
NextMultipleOf::checked_next_multiple_of(U16::from(11u8), U16::from(5u8)),
Some(U16::from(15u8))
);
assert_eq!(
NextMultipleOf::checked_next_multiple_of(U16::from(10u8), U16::from(0u8)),
None
);
let large = U16::from(65530u16);
assert_eq!(
NextMultipleOf::checked_next_multiple_of(large, U16::from(10u8)),
Some(large)
);
let large2 = U16::from(65531u16);
assert_eq!(
NextMultipleOf::checked_next_multiple_of(large2, U16::from(10u8)),
None
); }
c0nst::c0nst! {
pub c0nst fn const_is_multiple_of<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
a: &FixedUInt<T, N, Nct>,
b: &FixedUInt<T, N, Nct>,
) -> bool {
MultipleOf::is_multiple_of(*a, *b)
}
pub c0nst fn const_next_multiple_of<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
a: FixedUInt<T, N, Nct>,
b: FixedUInt<T, N, Nct>,
) -> FixedUInt<T, N, Nct> {
NextMultipleOf::next_multiple_of(a, b)
}
}
#[test]
fn test_const_multiple() {
type U16 = FixedUInt<u8, 2>;
assert!(const_is_multiple_of(&U16::from(10u8), &U16::from(5u8)));
assert_eq!(
const_next_multiple_of(U16::from(11u8), U16::from(5u8)),
U16::from(15u8)
);
#[cfg(feature = "nightly")]
{
const TEN: U16 = FixedUInt::from_array([10, 0]);
const FIVE: U16 = FixedUInt::from_array([5, 0]);
const IS_MULT: bool = const_is_multiple_of(&TEN, &FIVE);
assert!(IS_MULT);
const ELEVEN: U16 = FixedUInt::from_array([11, 0]);
const NEXT: U16 = const_next_multiple_of(ELEVEN, FIVE);
assert_eq!(NEXT, FixedUInt::from_array([15, 0]));
}
}
}