defuse_num_utils/
mul_div.rs

1use core::ops::Mul;
2
3use bnum::{BInt, BUint, cast::As};
4
5pub trait CheckedMulDiv<RHS = Self>: Sized {
6    fn checked_mul_div(self, mul: RHS, div: RHS) -> Option<Self>;
7    fn checked_mul_div_ceil(self, mul: RHS, div: RHS) -> Option<Self>;
8    fn checked_mul_div_euclid(self, mul: RHS, div: RHS) -> Option<Self>;
9}
10
11macro_rules! impl_checked_mul_div {
12    ($t:ty as $h:ty) => {
13        impl CheckedMulDiv for $t {
14            #[inline]
15            fn checked_mul_div(self, mul: Self, div: Self) -> Option<Self> {
16                self.as_::<$h>()
17                    .mul(mul.as_::<$h>())
18                    .checked_div(div.as_::<$h>())?
19                    .try_into()
20                    .ok()
21            }
22
23            #[inline]
24            fn checked_mul_div_ceil(self, mul: Self, div: Self) -> Option<Self> {
25                if div == 0 {
26                    return None;
27                }
28                self.as_::<$h>()
29                    .mul(mul.as_::<$h>())
30                    .div_ceil(div.as_::<$h>())
31                    .try_into()
32                    .ok()
33            }
34
35            #[inline]
36            fn checked_mul_div_euclid(self, mul: Self, div: Self) -> Option<Self> {
37                if div == 0 {
38                    return None;
39                }
40                self.as_::<$h>()
41                    .mul(mul.as_::<$h>())
42                    .div_euclid(div.as_::<$h>())
43                    .try_into()
44                    .ok()
45            }
46        }
47    };
48}
49impl_checked_mul_div!(u8 as u16);
50impl_checked_mul_div!(u16 as u32);
51impl_checked_mul_div!(u32 as u64);
52impl_checked_mul_div!(u64 as u128);
53impl_checked_mul_div!(u128 as BUint<4>);
54
55// #![feature(int_roundings)]
56// const _: () = {
57//     impl_checked_mul_div!(i8 as i16);
58//     impl_checked_mul_div!(i16 as i32);
59//     impl_checked_mul_div!(i32 as i64);
60//     impl_checked_mul_div!(i64 as i128);
61// };
62impl_checked_mul_div!(i128 as BInt<4>);