1use num_traits::ops::overflowing::OverflowingMul;
2use num_traits::{Bounded, Zero};
3
4use super::{maybe_panic, FixedUInt, MachineWord, PanicReason};
5
6impl<T: MachineWord, const N: usize> num_traits::ops::overflowing::OverflowingMul
7 for FixedUInt<T, N>
8{
9 fn overflowing_mul(&self, other: &Self) -> (Self, bool) {
10 Self::mul_impl::<true>(self, other)
11 }
12}
13
14impl<T: MachineWord, const N: usize> core::ops::Mul for FixedUInt<T, N> {
15 type Output = Self;
16 fn mul(self, other: Self) -> <Self as core::ops::Mul<Self>>::Output {
17 let res = self.overflowing_mul(&other);
18 if res.1 {
19 maybe_panic(PanicReason::Mul);
20 }
21 res.0
22 }
23}
24
25impl<T: MachineWord, const N: usize> core::ops::Mul<&'_ Self> for FixedUInt<T, N> {
26 type Output = Self;
27 fn mul(self, other: &Self) -> <Self as core::ops::Mul<Self>>::Output {
28 let res = self.overflowing_mul(other);
29 if res.1 {
30 maybe_panic(PanicReason::Mul);
31 }
32 res.0
33 }
34}
35
36impl<T: MachineWord, const N: usize> core::ops::Mul<FixedUInt<T, N>> for &FixedUInt<T, N> {
37 type Output = FixedUInt<T, N>;
38 fn mul(self, other: FixedUInt<T, N>) -> Self::Output {
39 let res = self.overflowing_mul(&other);
40 if res.1 {
41 maybe_panic(PanicReason::Mul);
42 }
43 res.0
44 }
45}
46
47impl<T: MachineWord, const N: usize> core::ops::Mul<Self> for &FixedUInt<T, N> {
48 type Output = FixedUInt<T, N>;
49 fn mul(self, other: Self) -> Self::Output {
50 let res = self.overflowing_mul(other);
51 if res.1 {
52 maybe_panic(PanicReason::Mul);
53 }
54 res.0
55 }
56}
57
58impl<T: MachineWord, const N: usize> core::ops::Mul<&Self> for &FixedUInt<T, N> {
59 type Output = FixedUInt<T, N>;
60 fn mul(self, other: &Self) -> Self::Output {
61 let res = self.overflowing_mul(other);
62 if res.1 {
63 maybe_panic(PanicReason::Mul);
64 }
65 res.0
66 }
67}
68
69impl<T: MachineWord, const N: usize> num_traits::WrappingMul for FixedUInt<T, N> {
70 fn wrapping_mul(&self, other: &Self) -> Self {
71 Self::mul_impl::<false>(self, other).0
72 }
73}
74
75impl<T: MachineWord, const N: usize> num_traits::CheckedMul for FixedUInt<T, N> {
76 fn checked_mul(&self, other: &Self) -> Option<Self> {
77 let res = self.overflowing_mul(other);
78 if res.1 {
79 None
80 } else {
81 Some(res.0)
82 }
83 }
84}
85
86impl<T: MachineWord, const N: usize> num_traits::ops::saturating::SaturatingMul
87 for FixedUInt<T, N>
88{
89 fn saturating_mul(&self, other: &Self) -> Self {
90 let res = self.overflowing_mul(other);
91 if res.1 {
92 Self::max_value()
93 } else {
94 res.0
95 }
96 }
97}
98
99impl<T: MachineWord, const N: usize> core::ops::MulAssign<Self> for FixedUInt<T, N> {
100 fn mul_assign(&mut self, other: Self) {
101 let res = self.overflowing_mul(&other);
102 *self = res.0;
103 if res.1 {
104 maybe_panic(PanicReason::Mul);
105 }
106 }
107}
108
109impl<T: MachineWord, const N: usize> core::ops::MulAssign<&'_ Self> for FixedUInt<T, N> {
110 fn mul_assign(&mut self, other: &Self) {
111 let res = self.overflowing_mul(other);
112 *self = res.0;
113 if res.1 {
114 maybe_panic(PanicReason::Mul);
115 }
116 }
117}
118
119impl<T: MachineWord, const N: usize> core::ops::Div for FixedUInt<T, N> {
120 type Output = Self;
121 fn div(self, other: Self) -> <Self as core::ops::Div<Self>>::Output {
122 if other.is_zero() {
123 maybe_panic(PanicReason::DivByZero)
124 }
125 Self::div_impl(&self, &other)
126 }
127}
128
129impl<T: MachineWord, const N: usize> core::ops::Div<&'_ Self> for FixedUInt<T, N> {
130 type Output = Self;
131 fn div(self, other: &Self) -> <Self as core::ops::Div<Self>>::Output {
132 if other.is_zero() {
133 maybe_panic(PanicReason::DivByZero)
134 }
135 Self::div_impl(&self, other)
136 }
137}
138
139impl<T: MachineWord, const N: usize> core::ops::Div<Self> for &FixedUInt<T, N> {
140 type Output = FixedUInt<T, N>;
141 fn div(self, other: Self) -> Self::Output {
142 if other.is_zero() {
143 maybe_panic(PanicReason::DivByZero)
144 }
145 Self::Output::div_impl(self, other)
146 }
147}
148
149impl<T: MachineWord, const N: usize> core::ops::Div<&Self> for &FixedUInt<T, N> {
150 type Output = FixedUInt<T, N>;
151 fn div(self, other: &Self) -> Self::Output {
152 if other.is_zero() {
153 maybe_panic(PanicReason::DivByZero)
154 }
155 Self::Output::div_impl(self, other)
156 }
157}
158
159impl<T: MachineWord, const N: usize> core::ops::Div<FixedUInt<T, N>> for &FixedUInt<T, N> {
160 type Output = FixedUInt<T, N>;
161 fn div(self, other: FixedUInt<T, N>) -> Self::Output {
162 if other.is_zero() {
163 maybe_panic(PanicReason::DivByZero)
164 }
165 Self::Output::div_impl(self, &other)
166 }
167}
168
169impl<T: MachineWord, const N: usize> num_traits::CheckedDiv for FixedUInt<T, N> {
170 fn checked_div(&self, other: &Self) -> Option<Self> {
171 if other.is_zero() {
172 None
173 } else {
174 Some(core::ops::Div::<Self>::div(*self, *other))
175 }
176 }
177}
178
179impl<T: MachineWord, const N: usize> core::ops::DivAssign<Self> for FixedUInt<T, N> {
180 fn div_assign(&mut self, other: Self) {
181 if other.is_zero() {
182 maybe_panic(PanicReason::DivByZero)
183 }
184 Self::div_assign_impl(self, &other);
185 }
186}
187
188impl<T: MachineWord, const N: usize> core::ops::DivAssign<&'_ Self> for FixedUInt<T, N> {
189 fn div_assign(&mut self, other: &Self) {
190 if other.is_zero() {
191 maybe_panic(PanicReason::DivByZero)
192 }
193 Self::div_assign_impl(self, other);
194 }
195}
196
197impl<T: MachineWord, const N: usize> core::ops::Rem for FixedUInt<T, N> {
198 type Output = Self;
199 fn rem(self, other: Self) -> Self {
200 if other.is_zero() {
201 maybe_panic(PanicReason::RemByZero)
202 }
203 self.div_rem(&other).1
204 }
205}
206
207impl<T: MachineWord, const N: usize> core::ops::Rem<&'_ Self> for FixedUInt<T, N> {
208 type Output = Self;
209 fn rem(self, other: &Self) -> Self {
210 if other.is_zero() {
211 maybe_panic(PanicReason::RemByZero)
212 }
213 self.div_rem(other).1
214 }
215}
216
217impl<T: MachineWord, const N: usize> core::ops::Rem<Self> for &FixedUInt<T, N> {
218 type Output = FixedUInt<T, N>;
219 fn rem(self, other: Self) -> Self::Output {
220 if other.is_zero() {
221 maybe_panic(PanicReason::RemByZero)
222 }
223 self.div_rem(other).1
224 }
225}
226
227impl<T: MachineWord, const N: usize> core::ops::Rem<&Self> for &FixedUInt<T, N> {
228 type Output = FixedUInt<T, N>;
229 fn rem(self, other: &Self) -> Self::Output {
230 if other.is_zero() {
231 maybe_panic(PanicReason::RemByZero)
232 }
233 self.div_rem(other).1
234 }
235}
236
237impl<T: MachineWord, const N: usize> num_traits::CheckedRem for FixedUInt<T, N> {
238 fn checked_rem(&self, other: &Self) -> Option<Self> {
239 if other.is_zero() {
240 None
241 } else {
242 Some(core::ops::Rem::<Self>::rem(*self, *other))
243 }
244 }
245}
246
247impl<T: MachineWord, const N: usize> core::ops::RemAssign<Self> for FixedUInt<T, N> {
248 fn rem_assign(&mut self, other: Self) {
249 if other.is_zero() {
250 maybe_panic(PanicReason::RemByZero)
251 }
252 *self = self.div_rem(&other).1;
253 }
254}
255
256impl<T: MachineWord, const N: usize> core::ops::RemAssign<&'_ Self> for FixedUInt<T, N> {
257 fn rem_assign(&mut self, other: &Self) {
258 if other.is_zero() {
259 maybe_panic(PanicReason::RemByZero)
260 }
261 *self = self.div_rem(other).1;
262 }
263}
264
265impl<T: MachineWord, const N: usize> core::ops::Rem<FixedUInt<T, N>> for &FixedUInt<T, N> {
266 type Output = FixedUInt<T, N>;
267 fn rem(self, other: FixedUInt<T, N>) -> Self::Output {
268 if other.is_zero() {
269 maybe_panic(PanicReason::RemByZero)
270 }
271 self.div_rem(&other).1
272 }
273}
274
275#[cfg(test)]
276mod tests {
277 use super::*;
278
279 #[test]
280 fn test_basic_mul() {
281 let a = FixedUInt::<u8, 2>::from(123u8);
282 let b = FixedUInt::<u8, 2>::from(234u8);
283 let c = a * b;
284 assert_eq!(c, FixedUInt::<u8, 2>::from(28782u16));
285 }
286
287 #[test]
288 fn test_mul_combinations() {
289 let a = FixedUInt::<u8, 2>::from(12u8);
290 let b = FixedUInt::<u8, 2>::from(3u8);
291 let expected = FixedUInt::<u8, 2>::from(36u8);
292
293 assert_eq!(a * b, expected);
295 assert_eq!(a * &b, expected);
297 assert_eq!(&a * b, expected);
299 assert_eq!(&a * &b, expected);
301 }
302
303 #[test]
304 fn test_div_combinations() {
305 let a = FixedUInt::<u8, 2>::from(36u8);
306 let b = FixedUInt::<u8, 2>::from(3u8);
307 let expected = FixedUInt::<u8, 2>::from(12u8);
308
309 assert_eq!(a / b, expected);
311 assert_eq!(a / &b, expected);
313 assert_eq!(&a / b, expected);
315 assert_eq!(&a / &b, expected);
317 }
318
319 #[test]
320 fn test_rem_combinations() {
321 let a = FixedUInt::<u8, 2>::from(37u8);
322 let b = FixedUInt::<u8, 2>::from(3u8);
323 let expected = FixedUInt::<u8, 2>::from(1u8); assert_eq!(a % b, expected);
327 assert_eq!(a % &b, expected);
329 assert_eq!(&a % b, expected);
331 assert_eq!(&a % &b, expected);
333 }
334}