1use super::{
2 FixedUInt, MachineWord, PanicReason, const_ct_select, const_div_rem, const_mul, maybe_panic_if,
3};
4use crate::machineword::ConstMachineWord;
5use const_num_traits::{
6 Bounded, CheckedDiv, CheckedMul, CheckedRem, OverflowingMul, SaturatingMul, WrappingMul, Zero,
7};
8use const_num_traits::{Nct, Personality, PersonalityTag};
9
10#[cfg(feature = "num-traits")]
11impl<T: MachineWord, const N: usize, P: Personality> num_traits::ops::overflowing::OverflowingMul
12 for FixedUInt<T, N, P>
13{
14 fn overflowing_mul(&self, other: &Self) -> (Self, bool) {
15 <&Self as OverflowingMul>::overflowing_mul(self, other)
16 }
17}
18
19c0nst::c0nst! {
20 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> OverflowingMul for FixedUInt<T, N, P> {
21 type Output = FixedUInt<T, N, P>;
22 fn overflowing_mul(self, other: Self) -> (Self, bool) {
23 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::WORD_BITS);
24 (Self::from_array(array), overflow)
25 }
26 }
27
28 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> WrappingMul for FixedUInt<T, N, P> {
29 type Output = FixedUInt<T, N, P>;
30 fn wrapping_mul(self, other: Self) -> Self {
31 let (array, _) = const_mul::<T, N, false, P>(&self.array, &other.array, Self::WORD_BITS);
32 Self::from_array(array)
33 }
34 }
35
36 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> CheckedMul for FixedUInt<T, N, P> {
37 type Output = FixedUInt<T, N, P>;
38 fn checked_mul(self, other: Self) -> Option<Self> {
39 let (res, overflow) = <Self as OverflowingMul>::overflowing_mul(self, other);
40 if overflow { None } else { Some(res) }
41 }
42 }
43
44 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> SaturatingMul for FixedUInt<T, N, P> {
45 type Output = FixedUInt<T, N, P>;
46 fn saturating_mul(self, other: Self) -> Self {
47 let (res, overflow) = <Self as OverflowingMul>::overflowing_mul(self, other);
48 match P::TAG {
49 PersonalityTag::Nct => if overflow { <Self as Bounded>::max_value() } else { res },
50 PersonalityTag::Ct => const_ct_select(res, <Self as Bounded>::max_value(), overflow as u8),
51 }
52 }
53 }
54
55 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> OverflowingMul for &FixedUInt<T, N, P> {
66 type Output = FixedUInt<T, N, P>;
67 fn overflowing_mul(self, other: Self) -> (FixedUInt<T, N, P>, bool) {
68 let (array, overflow) = const_mul::<T, N, true, P>(
69 &self.array,
70 &other.array,
71 FixedUInt::<T, N, P>::WORD_BITS,
72 );
73 (FixedUInt::from_array(array), overflow)
74 }
75 }
76
77 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> WrappingMul for &FixedUInt<T, N, P> {
78 type Output = FixedUInt<T, N, P>;
79 fn wrapping_mul(self, other: Self) -> FixedUInt<T, N, P> {
80 let (array, _overflow) = const_mul::<T, N, false, P>(
81 &self.array,
82 &other.array,
83 FixedUInt::<T, N, P>::WORD_BITS,
84 );
85 FixedUInt::from_array(array)
86 }
87 }
88
89 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> CheckedMul for &FixedUInt<T, N, P> {
90 type Output = FixedUInt<T, N, P>;
91 fn checked_mul(self, other: Self) -> Option<FixedUInt<T, N, P>> {
92 let (res, overflow) = <Self as OverflowingMul>::overflowing_mul(self, other);
93 if overflow { None } else { Some(res) }
94 }
95 }
96
97 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> SaturatingMul for &FixedUInt<T, N, P> {
98 type Output = FixedUInt<T, N, P>;
99 fn saturating_mul(self, other: Self) -> FixedUInt<T, N, P> {
100 let (res, overflow) = <Self as OverflowingMul>::overflowing_mul(self, other);
101 if overflow {
102 <FixedUInt<T, N, P> as Bounded>::max_value()
103 } else {
104 res
105 }
106 }
107 }
108}
109
110c0nst::c0nst! {
111 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> core::ops::Mul for FixedUInt<T, N, P> {
112 type Output = Self;
113 fn mul(self, other: Self) -> Self::Output {
114 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::WORD_BITS);
115 maybe_panic_if::<P>(overflow, PanicReason::Mul);
116 Self::from_array(array)
117 }
118 }
119
120 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> core::ops::Mul<&FixedUInt<T, N, P>> for FixedUInt<T, N, P> {
121 type Output = Self;
122 fn mul(self, other: &FixedUInt<T, N, P>) -> Self::Output {
123 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::WORD_BITS);
124 maybe_panic_if::<P>(overflow, PanicReason::Mul);
125 Self::from_array(array)
126 }
127 }
128
129 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> core::ops::Mul<FixedUInt<T, N, P>> for &FixedUInt<T, N, P> {
130 type Output = FixedUInt<T, N, P>;
131 fn mul(self, other: FixedUInt<T, N, P>) -> Self::Output {
132 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::Output::WORD_BITS);
133 maybe_panic_if::<P>(overflow, PanicReason::Mul);
134 FixedUInt::from_array(array)
135 }
136 }
137
138 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> core::ops::Mul<&FixedUInt<T, N, P>> for &FixedUInt<T, N, P> {
139 type Output = FixedUInt<T, N, P>;
140 fn mul(self, other: &FixedUInt<T, N, P>) -> Self::Output {
141 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::Output::WORD_BITS);
142 maybe_panic_if::<P>(overflow, PanicReason::Mul);
143 FixedUInt::from_array(array)
144 }
145 }
146
147 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> core::ops::Mul<&&FixedUInt<T, N, P>> for &FixedUInt<T, N, P> {
148 type Output = FixedUInt<T, N, P>;
149 fn mul(self, other: &&FixedUInt<T, N, P>) -> Self::Output {
150 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::Output::WORD_BITS);
151 maybe_panic_if::<P>(overflow, PanicReason::Mul);
152 FixedUInt::from_array(array)
153 }
154 }
155
156 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> core::ops::MulAssign for FixedUInt<T, N, P> {
157 fn mul_assign(&mut self, other: Self) {
158 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::WORD_BITS);
159 maybe_panic_if::<P>(overflow, PanicReason::Mul);
160 *self = Self::from_array(array);
161 }
162 }
163
164 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> core::ops::MulAssign<&FixedUInt<T, N, P>> for FixedUInt<T, N, P> {
165 fn mul_assign(&mut self, other: &FixedUInt<T, N, P>) {
166 let (array, overflow) = const_mul::<T, N, true, P>(&self.array, &other.array, Self::WORD_BITS);
167 maybe_panic_if::<P>(overflow, PanicReason::Mul);
168 *self = Self::from_array(array);
169 }
170 }
171}
172
173#[cfg(feature = "num-traits")]
175impl<T: MachineWord, const N: usize, P: Personality> num_traits::WrappingMul
176 for FixedUInt<T, N, P>
177{
178 fn wrapping_mul(&self, other: &Self) -> Self {
179 <&Self as WrappingMul>::wrapping_mul(self, other)
180 }
181}
182
183#[cfg(feature = "num-traits")]
184impl<T: MachineWord, const N: usize, P: Personality> num_traits::CheckedMul for FixedUInt<T, N, P> {
185 fn checked_mul(&self, other: &Self) -> Option<Self> {
186 <&Self as CheckedMul>::checked_mul(self, other)
187 }
188}
189
190#[cfg(feature = "num-traits")]
191impl<T: MachineWord, const N: usize, P: Personality> num_traits::ops::saturating::SaturatingMul
192 for FixedUInt<T, N, P>
193{
194 fn saturating_mul(&self, other: &Self) -> Self {
195 <&Self as SaturatingMul>::saturating_mul(self, other)
196 }
197}
198
199c0nst::c0nst! {
200 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Div for FixedUInt<T, N, Nct> {
201 type Output = Self;
202 fn div(self, other: Self) -> Self::Output {
203 Self::from_array(const_div_rem(&self.array, &other.array).0)
204 }
205 }
206
207 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Div<&FixedUInt<T, N, Nct>> for FixedUInt<T, N, Nct> {
208 type Output = Self;
209 fn div(self, other: &FixedUInt<T, N, Nct>) -> Self::Output {
210 Self::from_array(const_div_rem(&self.array, &other.array).0)
211 }
212 }
213
214 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Div<FixedUInt<T, N, Nct>> for &FixedUInt<T, N, Nct> {
215 type Output = FixedUInt<T, N, Nct>;
216 fn div(self, other: FixedUInt<T, N, Nct>) -> Self::Output {
217 Self::Output::from_array(const_div_rem(&self.array, &other.array).0)
218 }
219 }
220
221 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Div<&FixedUInt<T, N, Nct>> for &FixedUInt<T, N, Nct> {
222 type Output = FixedUInt<T, N, Nct>;
223 fn div(self, other: &FixedUInt<T, N, Nct>) -> Self::Output {
224 Self::Output::from_array(const_div_rem(&self.array, &other.array).0)
225 }
226 }
227
228 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::DivAssign for FixedUInt<T, N, Nct> {
229 fn div_assign(&mut self, other: Self) {
230 self.array = const_div_rem(&self.array, &other.array).0;
231 }
232 }
233
234 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::DivAssign<&FixedUInt<T, N, Nct>> for FixedUInt<T, N, Nct> {
235 fn div_assign(&mut self, other: &FixedUInt<T, N, Nct>) {
236 self.array = const_div_rem(&self.array, &other.array).0;
237 }
238 }
239}
240
241c0nst::c0nst! {
242 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> CheckedDiv for FixedUInt<T, N, Nct> {
243 type Output = FixedUInt<T, N, Nct>;
244 fn checked_div(self, other: Self) -> Option<Self> {
245 if <Self as Zero>::is_zero(&other) {
246 None
247 } else {
248 Some(self / other)
249 }
250 }
251 }
252
253 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> CheckedDiv for &FixedUInt<T, N, Nct> {
254 type Output = FixedUInt<T, N, Nct>;
255 fn checked_div(self, other: Self) -> Option<FixedUInt<T, N, Nct>> {
256 <FixedUInt<T, N, Nct> as CheckedDiv>::checked_div(FixedUInt::from_array(self.array), FixedUInt::from_array(other.array))
257 }
258 }
259}
260
261#[cfg(feature = "num-traits")]
262impl<T: MachineWord, const N: usize> num_traits::CheckedDiv for FixedUInt<T, N, Nct> {
263 fn checked_div(&self, other: &Self) -> Option<Self> {
264 <&Self as CheckedDiv>::checked_div(self, other)
265 }
266}
267
268c0nst::c0nst! {
269 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Rem for FixedUInt<T, N, Nct> {
270 type Output = Self;
271 fn rem(self, other: Self) -> Self::Output {
272 Self::from_array(const_div_rem(&self.array, &other.array).1)
273 }
274 }
275
276 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Rem<&FixedUInt<T, N, Nct>> for FixedUInt<T, N, Nct> {
277 type Output = Self;
278 fn rem(self, other: &FixedUInt<T, N, Nct>) -> Self::Output {
279 Self::from_array(const_div_rem(&self.array, &other.array).1)
280 }
281 }
282
283 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Rem<FixedUInt<T, N, Nct>> for &FixedUInt<T, N, Nct> {
284 type Output = FixedUInt<T, N, Nct>;
285 fn rem(self, other: FixedUInt<T, N, Nct>) -> Self::Output {
286 Self::Output::from_array(const_div_rem(&self.array, &other.array).1)
287 }
288 }
289
290 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::Rem<&FixedUInt<T, N, Nct>> for &FixedUInt<T, N, Nct> {
291 type Output = FixedUInt<T, N, Nct>;
292 fn rem(self, other: &FixedUInt<T, N, Nct>) -> Self::Output {
293 Self::Output::from_array(const_div_rem(&self.array, &other.array).1)
294 }
295 }
296
297 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::RemAssign for FixedUInt<T, N, Nct> {
298 fn rem_assign(&mut self, other: Self) {
299 self.array = const_div_rem(&self.array, &other.array).1;
300 }
301 }
302
303 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> core::ops::RemAssign<&FixedUInt<T, N, Nct>> for FixedUInt<T, N, Nct> {
304 fn rem_assign(&mut self, other: &FixedUInt<T, N, Nct>) {
305 self.array = const_div_rem(&self.array, &other.array).1;
306 }
307 }
308}
309
310c0nst::c0nst! {
311 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> CheckedRem for FixedUInt<T, N, Nct> {
312 type Output = FixedUInt<T, N, Nct>;
313 fn checked_rem(self, other: Self) -> Option<Self> {
314 if <Self as Zero>::is_zero(&other) {
315 None
316 } else {
317 Some(self % other)
318 }
319 }
320 }
321
322 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> CheckedRem for &FixedUInt<T, N, Nct> {
323 type Output = FixedUInt<T, N, Nct>;
324 fn checked_rem(self, other: Self) -> Option<FixedUInt<T, N, Nct>> {
325 <FixedUInt<T, N, Nct> as CheckedRem>::checked_rem(FixedUInt::from_array(self.array), FixedUInt::from_array(other.array))
326 }
327 }
328}
329
330#[cfg(feature = "num-traits")]
331impl<T: MachineWord, const N: usize> num_traits::CheckedRem for FixedUInt<T, N, Nct> {
332 fn checked_rem(&self, other: &Self) -> Option<Self> {
333 <&Self as CheckedRem>::checked_rem(self, other)
334 }
335}
336
337#[cfg(test)]
339c0nst::c0nst! {
340 pub c0nst fn const_wrapping_mul<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(
341 a: &FixedUInt<T, N, P>,
342 b: &FixedUInt<T, N, P>
343 ) -> FixedUInt<T, N, P> {
344 <FixedUInt<T, N, P> as WrappingMul>::wrapping_mul(*a, *b)
345 }
346
347 pub c0nst fn const_checked_mul<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(
348 a: &FixedUInt<T, N, P>,
349 b: &FixedUInt<T, N, P>
350 ) -> Option<FixedUInt<T, N, P>> {
351 <FixedUInt<T, N, P> as CheckedMul>::checked_mul(*a, *b)
352 }
353
354 pub c0nst fn const_saturating_mul<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(
355 a: &FixedUInt<T, N, P>,
356 b: &FixedUInt<T, N, P>
357 ) -> FixedUInt<T, N, P> {
358 <FixedUInt<T, N, P> as SaturatingMul>::saturating_mul(*a, *b)
359 }
360
361 pub c0nst fn const_overflowing_mul<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(
362 a: &FixedUInt<T, N, P>,
363 b: &FixedUInt<T, N, P>
364 ) -> (FixedUInt<T, N, P>, bool) {
365 <FixedUInt<T, N, P> as OverflowingMul>::overflowing_mul(*a, *b)
366 }
367
368 pub c0nst fn const_checked_div<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
369 a: &FixedUInt<T, N, Nct>,
370 b: &FixedUInt<T, N, Nct>
371 ) -> Option<FixedUInt<T, N, Nct>> {
372 <FixedUInt<T, N, Nct> as CheckedDiv>::checked_div(*a, *b)
373 }
374
375 pub c0nst fn const_checked_rem<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
376 a: &FixedUInt<T, N, Nct>,
377 b: &FixedUInt<T, N, Nct>
378 ) -> Option<FixedUInt<T, N, Nct>> {
379 <FixedUInt<T, N, Nct> as CheckedRem>::checked_rem(*a, *b)
380 }
381}
382
383impl<T, const N: usize, P: Personality> const_num_traits::ops::ct::CtCheckedMul
390 for FixedUInt<T, N, P>
391where
392 T: MachineWord,
393{
394 fn ct_checked_mul(&self, v: &Self) -> subtle::CtOption<Self> {
395 let (val, overflow) = <&Self as OverflowingMul>::overflowing_mul(self, v);
396 subtle::CtOption::new(val, subtle::Choice::from(!overflow as u8))
397 }
398}
399
400#[cfg(test)]
401#[allow(clippy::op_ref)]
404mod tests {
405 use super::*;
406
407 #[test]
408 fn test_basic_mul() {
409 let a = FixedUInt::<u8, 2>::from(123u8);
410 let b = FixedUInt::<u8, 2>::from(234u8);
411 let c = a * b;
412 assert_eq!(c, FixedUInt::<u8, 2>::from(28782u16));
413 }
414
415 #[test]
416 fn test_mul_combinations() {
417 let a = FixedUInt::<u8, 2>::from(12u8);
418 let b = FixedUInt::<u8, 2>::from(3u8);
419 let expected = FixedUInt::<u8, 2>::from(36u8);
420
421 assert_eq!(a * b, expected);
423 assert_eq!(a * &b, expected);
425 assert_eq!(&a * b, expected);
427 assert_eq!(&a * &b, expected);
429 }
430
431 #[test]
432 fn test_div_combinations() {
433 let a = FixedUInt::<u8, 2>::from(36u8);
434 let b = FixedUInt::<u8, 2>::from(3u8);
435 let expected = FixedUInt::<u8, 2>::from(12u8);
436
437 assert_eq!(a / b, expected);
439 assert_eq!(a / &b, expected);
441 assert_eq!(&a / b, expected);
443 assert_eq!(&a / &b, expected);
445 }
446
447 #[test]
448 fn test_rem_combinations() {
449 let a = FixedUInt::<u8, 2>::from(37u8);
450 let b = FixedUInt::<u8, 2>::from(3u8);
451 let expected = FixedUInt::<u8, 2>::from(1u8); assert_eq!(a % b, expected);
455 assert_eq!(a % &b, expected);
457 assert_eq!(&a % b, expected);
459 assert_eq!(&a % &b, expected);
461 }
462
463 #[test]
464 fn test_const_mul_traits() {
465 let a = FixedUInt::<u8, 2>::from(12u8);
466 let b = FixedUInt::<u8, 2>::from(3u8);
467 let expected = FixedUInt::<u8, 2>::from(36u8);
468
469 assert_eq!(const_wrapping_mul(&a, &b), expected);
471
472 assert_eq!(const_checked_mul(&a, &b), Some(expected));
474
475 assert_eq!(const_saturating_mul(&a, &b), expected);
477
478 let (result, overflow) = const_overflowing_mul(&a, &b);
480 assert_eq!(result, expected);
481 assert!(!overflow);
482
483 let large = FixedUInt::<u8, 2>::from(256u16); assert_eq!(const_checked_mul(&large, &large), None);
488
489 let saturated = const_saturating_mul(&large, &large);
491 assert_eq!(saturated, FixedUInt::<u8, 2>::from(0xFFFFu16));
492
493 let (_, overflow) = const_overflowing_mul(&large, &large);
495 assert!(overflow);
496
497 #[cfg(feature = "nightly")]
498 {
499 const A: FixedUInt<u8, 2> = FixedUInt::from_array([12, 0]);
500 const B: FixedUInt<u8, 2> = FixedUInt::from_array([3, 0]);
501
502 const WRAPPING_RESULT: FixedUInt<u8, 2> = const_wrapping_mul(&A, &B);
503 assert_eq!(WRAPPING_RESULT.array, [36, 0]);
504
505 const CHECKED_RESULT: Option<FixedUInt<u8, 2>> = const_checked_mul(&A, &B);
506 assert!(CHECKED_RESULT.is_some());
507
508 const SATURATING_RESULT: FixedUInt<u8, 2> = const_saturating_mul(&A, &B);
509 assert_eq!(SATURATING_RESULT.array, [36, 0]);
510
511 const OVERFLOWING_RESULT: (FixedUInt<u8, 2>, bool) = const_overflowing_mul(&A, &B);
512 assert_eq!(OVERFLOWING_RESULT.0.array, [36, 0]);
513 assert!(!OVERFLOWING_RESULT.1);
514 }
515 }
516
517 #[test]
518 fn test_const_checked_div_rem() {
519 let a = FixedUInt::<u8, 2>::from(36u8);
520 let b = FixedUInt::<u8, 2>::from(5u8);
521 let zero = FixedUInt::<u8, 2>::from(0u8);
522
523 assert_eq!(
525 const_checked_div(&a, &b),
526 Some(FixedUInt::<u8, 2>::from(7u8))
527 ); assert_eq!(const_checked_div(&a, &zero), None);
531
532 assert_eq!(
534 const_checked_rem(&a, &b),
535 Some(FixedUInt::<u8, 2>::from(1u8))
536 ); assert_eq!(const_checked_rem(&a, &zero), None);
540
541 #[cfg(feature = "nightly")]
542 {
543 const A: FixedUInt<u8, 2> = FixedUInt::from_array([36, 0]);
544 const B: FixedUInt<u8, 2> = FixedUInt::from_array([5, 0]);
545 const ZERO: FixedUInt<u8, 2> = FixedUInt::from_array([0, 0]);
546
547 const CHECKED_DIV_OK: Option<FixedUInt<u8, 2>> = const_checked_div(&A, &B);
548 const CHECKED_DIV_ZERO: Option<FixedUInt<u8, 2>> = const_checked_div(&A, &ZERO);
549 const CHECKED_REM_OK: Option<FixedUInt<u8, 2>> = const_checked_rem(&A, &B);
550 const CHECKED_REM_ZERO: Option<FixedUInt<u8, 2>> = const_checked_rem(&A, &ZERO);
551
552 assert_eq!(CHECKED_DIV_OK, Some(FixedUInt::from_array([7, 0])));
553 assert_eq!(CHECKED_DIV_ZERO, None);
554 assert_eq!(CHECKED_REM_OK, Some(FixedUInt::from_array([1, 0])));
555 assert_eq!(CHECKED_REM_ZERO, None);
556 }
557 }
558
559 #[test]
560 fn ct_checked_mul_masks_overflow() {
561 use const_num_traits::ops::ct::CtCheckedMul;
562 type U16 = FixedUInt<u8, 2>;
563 let ok = U16::from(100u8).ct_checked_mul(&U16::from(50u8));
564 assert!(bool::from(ok.is_some()));
565 assert_eq!(ok.unwrap(), U16::from(5000u16));
566 let bad = U16::from(1000u16).ct_checked_mul(&U16::from(1000u16));
568 assert!(!bool::from(bad.is_some()));
569 }
570}