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 self / v
12 }
13
14 fn rem_euclid(self, v: Self) -> Self {
15 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 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}