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