Skip to main content

fixed_bigint/fixeduint/
euclid.rs

1use num_traits::{CheckedEuclid, Euclid};
2
3use super::{FixedUInt, MachineWord};
4use crate::const_numtraits::{ConstCheckedEuclid, ConstEuclid, ConstZero};
5use crate::machineword::ConstMachineWord;
6
7c0nst::c0nst! {
8    impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstEuclid for FixedUInt<T, N> {
9        fn div_euclid(&self, v: &Self) -> Self {
10            // For unsigned integers, Euclidean division is the same as regular division
11            *self / *v
12        }
13
14        fn rem_euclid(&self, v: &Self) -> Self {
15            // For unsigned integers, Euclidean remainder is the same as regular remainder
16            *self % *v
17        }
18    }
19
20    impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstCheckedEuclid for FixedUInt<T, N> {
21        fn checked_div_euclid(&self, v: &Self) -> Option<Self> {
22            if v.is_zero() {
23                None
24            } else {
25                Some(*self / *v)
26            }
27        }
28
29        fn checked_rem_euclid(&self, v: &Self) -> Option<Self> {
30            if v.is_zero() {
31                None
32            } else {
33                Some(*self % *v)
34            }
35        }
36    }
37}
38
39// num_traits::Euclid - uses direct operators (no const bounds needed)
40impl<T: MachineWord, const N: usize> Euclid for FixedUInt<T, N> {
41    fn div_euclid(&self, v: &Self) -> Self {
42        self / v
43    }
44
45    fn rem_euclid(&self, v: &Self) -> Self {
46        self % v
47    }
48}
49
50// num_traits::CheckedEuclid - uses direct checked calls (no const bounds needed)
51impl<T: MachineWord, const N: usize> CheckedEuclid for FixedUInt<T, N> {
52    fn checked_div_euclid(&self, v: &Self) -> Option<Self> {
53        num_traits::CheckedDiv::checked_div(self, v)
54    }
55
56    fn checked_rem_euclid(&self, v: &Self) -> Option<Self> {
57        num_traits::CheckedRem::checked_rem(self, v)
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64    use crate::machineword::ConstMachineWord;
65
66    #[test]
67    fn test_div_euclid() {
68        use num_traits::Euclid;
69        let a = FixedUInt::<u8, 2>::from(100u8);
70        let b = FixedUInt::<u8, 2>::from(30u8);
71        assert_eq!(Euclid::div_euclid(&a, &b), 3u8.into());
72        assert_eq!(Euclid::rem_euclid(&a, &b), 10u8.into());
73    }
74
75    #[test]
76    fn test_checked_div_euclid() {
77        use num_traits::CheckedEuclid;
78        let a = FixedUInt::<u8, 2>::from(100u8);
79        let b = FixedUInt::<u8, 2>::from(30u8);
80        assert_eq!(CheckedEuclid::checked_div_euclid(&a, &b), Some(3u8.into()));
81        assert_eq!(CheckedEuclid::checked_rem_euclid(&a, &b), Some(10u8.into()));
82
83        // Test division by zero
84        let zero = FixedUInt::<u8, 2>::from(0u8);
85        assert_eq!(CheckedEuclid::checked_div_euclid(&a, &zero), None);
86        assert_eq!(CheckedEuclid::checked_rem_euclid(&a, &zero), None);
87    }
88
89    c0nst::c0nst! {
90        pub c0nst fn const_div_euclid<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
91            a: &FixedUInt<T, N>,
92            b: &FixedUInt<T, N>,
93        ) -> FixedUInt<T, N> {
94            ConstEuclid::div_euclid(a, b)
95        }
96
97        pub c0nst fn const_rem_euclid<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
98            a: &FixedUInt<T, N>,
99            b: &FixedUInt<T, N>,
100        ) -> FixedUInt<T, N> {
101            ConstEuclid::rem_euclid(a, b)
102        }
103
104        pub c0nst fn const_checked_div_euclid<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
105            a: &FixedUInt<T, N>,
106            b: &FixedUInt<T, N>,
107        ) -> Option<FixedUInt<T, N>> {
108            ConstCheckedEuclid::checked_div_euclid(a, b)
109        }
110
111        pub c0nst fn const_checked_rem_euclid<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
112            a: &FixedUInt<T, N>,
113            b: &FixedUInt<T, N>,
114        ) -> Option<FixedUInt<T, N>> {
115            ConstCheckedEuclid::checked_rem_euclid(a, b)
116        }
117    }
118
119    #[test]
120    fn test_const_euclid() {
121        let a = FixedUInt::<u8, 2>::from(100u8);
122        let b = FixedUInt::<u8, 2>::from(30u8);
123        assert_eq!(const_div_euclid(&a, &b), 3u8.into());
124        assert_eq!(const_rem_euclid(&a, &b), 10u8.into());
125        assert_eq!(const_checked_div_euclid(&a, &b), Some(3u8.into()));
126        assert_eq!(const_checked_rem_euclid(&a, &b), Some(10u8.into()));
127
128        #[cfg(feature = "nightly")]
129        {
130            const A: FixedUInt<u8, 2> = FixedUInt { array: [100, 0] };
131            const B: FixedUInt<u8, 2> = FixedUInt { array: [30, 0] };
132            const DIV_RESULT: FixedUInt<u8, 2> = const_div_euclid(&A, &B);
133            const REM_RESULT: FixedUInt<u8, 2> = const_rem_euclid(&A, &B);
134            const CHECKED_DIV: Option<FixedUInt<u8, 2>> = const_checked_div_euclid(&A, &B);
135            const CHECKED_REM: Option<FixedUInt<u8, 2>> = const_checked_rem_euclid(&A, &B);
136            assert_eq!(DIV_RESULT, FixedUInt { array: [3, 0] });
137            assert_eq!(REM_RESULT, FixedUInt { array: [10, 0] });
138            assert_eq!(CHECKED_DIV, Some(FixedUInt { array: [3, 0] }));
139            assert_eq!(CHECKED_REM, Some(FixedUInt { array: [10, 0] }));
140        }
141    }
142}