use super::HeaplessBigInt;
use crate::MachineWord;
use const_num_traits::{Parity, Personality};
impl<T, const CAP: usize, P: Personality> Parity for HeaplessBigInt<T, CAP, P>
where
T: MachineWord + Parity,
{
fn is_odd(self) -> bool {
if self.len == 0 {
false
} else {
self.limbs[0].is_odd()
}
}
fn is_even(self) -> bool {
!self.is_odd()
}
}
impl<T, const CAP: usize, P: Personality> const_num_traits::ops::ct::CtParity
for HeaplessBigInt<T, CAP, P>
where
T: MachineWord + subtle::ConstantTimeEq,
{
fn ct_is_odd(&self) -> subtle::Choice {
if self.len == 0 {
return subtle::Choice::from(0);
}
let lsb = self.limbs[0] & <T as const_num_traits::ConstOne>::ONE;
!lsb.ct_eq(&<T as const_num_traits::ConstZero>::ZERO)
}
fn ct_is_even(&self) -> subtle::Choice {
!<Self as const_num_traits::ops::ct::CtParity>::ct_is_odd(self)
}
}
#[cfg(test)]
mod tests {
use super::HeaplessBigInt;
use const_num_traits::ops::ct::CtParity;
type H = HeaplessBigInt<u8, 4>;
#[test]
fn ct_parity_matches_value_parity() {
for v in [0u32, 1, 2, 3, 0xFFFF_FFFE, 0xFFFF_FFFF] {
let h = H::from(v);
assert_eq!(bool::from(h.ct_is_odd()), v & 1 == 1, "odd({v})");
assert_eq!(bool::from(h.ct_is_even()), v & 1 == 0, "even({v})");
}
}
}