Skip to main content

fixed_bigint/heapless/
euclid.rs

1//! `const_num_traits::Euclid` / `CheckedEuclid` for `HeaplessBigInt<_, Nct>`.
2//!
3//! Unsigned: Euclidean div/rem are ordinary div/rem. Nct-only, like the
4//! division they build on; `checked_*` return `None` on a zero divisor.
5
6use super::HeaplessBigInt;
7use crate::MachineWord;
8use const_num_traits::{CarryingMul, CheckedEuclid, Euclid, Nct, Zero};
9
10impl<T, const CAP: usize> Euclid for HeaplessBigInt<T, CAP, Nct>
11where
12    T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
13{
14    type Output = Self;
15    fn div_euclid(self, v: Self) -> Self {
16        self / v
17    }
18    fn rem_euclid(self, v: Self) -> Self {
19        self % v
20    }
21    fn div_rem_euclid(self, v: Self) -> (Self, Self) {
22        self.div_rem(&v)
23    }
24}
25
26impl<T, const CAP: usize> CheckedEuclid for HeaplessBigInt<T, CAP, Nct>
27where
28    T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
29{
30    // Unsigned Euclidean == ordinary; delegate to the inherent checked div/rem
31    // so the zero-divisor guard lives in one tested place.
32    fn checked_div_euclid(self, v: Self) -> Option<Self> {
33        self.checked_div(&v)
34    }
35    fn checked_rem_euclid(self, v: Self) -> Option<Self> {
36        self.checked_rem(&v)
37    }
38    fn checked_div_rem_euclid(self, v: Self) -> Option<(Self, Self)> {
39        if v.is_zero() {
40            None
41        } else {
42            Some(self.div_rem(&v))
43        }
44    }
45}
46
47// `&Self` mirrors so `(&h).div_euclid(&g)` resolves without an explicit copy.
48impl<T, const CAP: usize> Euclid for &HeaplessBigInt<T, CAP, Nct>
49where
50    T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
51{
52    type Output = HeaplessBigInt<T, CAP, Nct>;
53    fn div_euclid(self, v: Self) -> Self::Output {
54        <HeaplessBigInt<T, CAP, Nct> as Euclid>::div_euclid(*self, *v)
55    }
56    fn rem_euclid(self, v: Self) -> Self::Output {
57        <HeaplessBigInt<T, CAP, Nct> as Euclid>::rem_euclid(*self, *v)
58    }
59    fn div_rem_euclid(self, v: Self) -> (Self::Output, Self::Output) {
60        <HeaplessBigInt<T, CAP, Nct> as Euclid>::div_rem_euclid(*self, *v)
61    }
62}
63
64impl<T, const CAP: usize> CheckedEuclid for &HeaplessBigInt<T, CAP, Nct>
65where
66    T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
67{
68    fn checked_div_euclid(self, v: Self) -> Option<<Self as Euclid>::Output> {
69        <HeaplessBigInt<T, CAP, Nct> as CheckedEuclid>::checked_div_euclid(*self, *v)
70    }
71    fn checked_rem_euclid(self, v: Self) -> Option<<Self as Euclid>::Output> {
72        <HeaplessBigInt<T, CAP, Nct> as CheckedEuclid>::checked_rem_euclid(*self, *v)
73    }
74    fn checked_div_rem_euclid(
75        self,
76        v: Self,
77    ) -> Option<(<Self as Euclid>::Output, <Self as Euclid>::Output)> {
78        <HeaplessBigInt<T, CAP, Nct> as CheckedEuclid>::checked_div_rem_euclid(*self, *v)
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::HeaplessBigInt;
85    use const_num_traits::{CheckedEuclid, Euclid};
86
87    type H = HeaplessBigInt<u8, 4>;
88
89    #[test]
90    fn byref_matches_value() {
91        let a = H::from(17u8);
92        let b = H::from(5u8);
93        assert_eq!(Euclid::div_euclid(&a, &b), Euclid::div_euclid(a, b));
94        assert_eq!(Euclid::rem_euclid(&a, &b), Euclid::rem_euclid(a, b));
95        assert_eq!(Euclid::div_rem_euclid(&a, &b), Euclid::div_rem_euclid(a, b));
96        assert_eq!(
97            CheckedEuclid::checked_div_euclid(&a, &b),
98            CheckedEuclid::checked_div_euclid(a, b)
99        );
100        assert_eq!(
101            CheckedEuclid::checked_rem_euclid(&a, &b),
102            CheckedEuclid::checked_rem_euclid(a, b)
103        );
104        assert_eq!(
105            CheckedEuclid::checked_div_rem_euclid(&a, &b),
106            CheckedEuclid::checked_div_rem_euclid(a, b)
107        );
108    }
109}