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