Skip to main content

fixed_bigint/fixeduint/
euclid.rs

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