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