fixed_bigint/heapless/
parity.rs1use super::HeaplessBigInt;
9use crate::MachineWord;
10use const_num_traits::{Parity, Personality};
11
12impl<T, const CAP: usize, P: Personality> Parity for HeaplessBigInt<T, CAP, P>
13where
14 T: MachineWord + Parity,
15{
16 fn is_odd(self) -> bool {
17 if self.len == 0 {
18 false
19 } else {
20 self.limbs[0].is_odd()
21 }
22 }
23
24 fn is_even(self) -> bool {
25 !self.is_odd()
26 }
27}
28
29impl<T, const CAP: usize, P: Personality> const_num_traits::ops::ct::CtParity
34 for HeaplessBigInt<T, CAP, P>
35where
36 T: MachineWord + subtle::ConstantTimeEq,
37{
38 fn ct_is_odd(&self) -> subtle::Choice {
39 if self.len == 0 {
40 return subtle::Choice::from(0);
41 }
42 let lsb = self.limbs[0] & <T as const_num_traits::ConstOne>::ONE;
43 !lsb.ct_eq(&<T as const_num_traits::ConstZero>::ZERO)
44 }
45
46 fn ct_is_even(&self) -> subtle::Choice {
47 !<Self as const_num_traits::ops::ct::CtParity>::ct_is_odd(self)
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::HeaplessBigInt;
54 use const_num_traits::ops::ct::CtParity;
55
56 type H = HeaplessBigInt<u8, 4>;
57
58 #[test]
59 fn ct_parity_matches_value_parity() {
60 for v in [0u32, 1, 2, 3, 0xFFFF_FFFE, 0xFFFF_FFFF] {
61 let h = H::from(v);
62 assert_eq!(bool::from(h.ct_is_odd()), v & 1 == 1, "odd({v})");
63 assert_eq!(bool::from(h.ct_is_even()), v & 1 == 0, "even({v})");
64 }
65 }
66}