reweb3_num/bint/
checked.rs

1macro_rules! checked_ilog {
2    ($method: ident $(, $base: ident: $ty: ty)?) => {
3        #[doc = doc::checked::$method!(I)]
4        #[must_use = doc::must_use_op!()]
5        #[inline]
6        pub const fn $method(self $(, $base: $ty)?) -> Option<ExpType> {
7            if self.is_negative() {
8                None
9            } else {
10                self.bits.$method($($base)?)
11            }
12        }
13    }
14}
15
16use crate::doc;
17use crate::int::checked::tuple_to_option;
18use crate::ExpType;
19
20macro_rules! checked {
21    ($BUint: ident, $BInt: ident, $Digit: ident) => {
22        #[doc = doc::checked::impl_desc!()]
23        impl<const N: usize> $BInt<N> {
24            #[doc = doc::checked::checked_add!(I)]
25            #[must_use = doc::must_use_op!()]
26            #[inline]
27            pub const fn checked_add(self, rhs: Self) -> Option<Self> {
28                tuple_to_option(self.overflowing_add(rhs))
29            }
30
31            #[doc = doc::checked::checked_add_unsigned!(I)]
32            #[must_use = doc::must_use_op!()]
33            #[inline]
34            pub const fn checked_add_unsigned(self, rhs: $BUint<N>) -> Option<Self> {
35                tuple_to_option(self.overflowing_add_unsigned(rhs))
36            }
37
38            #[doc = doc::checked::checked_sub!(I)]
39            #[must_use = doc::must_use_op!()]
40            #[inline]
41            pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
42                tuple_to_option(self.overflowing_sub(rhs))
43            }
44
45            #[doc = doc::checked::checked_sub_unsigned!(I)]
46            #[must_use = doc::must_use_op!()]
47            #[inline]
48            pub const fn checked_sub_unsigned(self, rhs: $BUint<N>) -> Option<Self> {
49                tuple_to_option(self.overflowing_sub_unsigned(rhs))
50            }
51
52            #[doc = doc::checked::checked_mul!(I)]
53            #[must_use = doc::must_use_op!()]
54            #[inline]
55            pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
56                tuple_to_option(self.overflowing_mul(rhs))
57            }
58
59            #[doc = doc::checked::checked_div!(I)]
60            #[must_use = doc::must_use_op!()]
61            #[inline]
62            pub const fn checked_div(self, rhs: Self) -> Option<Self> {
63                if rhs.is_zero() {
64                    None
65                } else {
66                    tuple_to_option(self.overflowing_div(rhs))
67                }
68            }
69
70            #[doc = doc::checked::checked_div_euclid!(I)]
71            #[must_use = doc::must_use_op!()]
72            #[inline]
73            pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
74                if rhs.is_zero() {
75                    None
76                } else {
77                    tuple_to_option(self.overflowing_div_euclid(rhs))
78                }
79            }
80
81            #[doc = doc::checked::checked_rem!(I)]
82            #[must_use = doc::must_use_op!()]
83            #[inline]
84            pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
85                if rhs.is_zero() {
86                    None
87                } else {
88                    tuple_to_option(self.overflowing_rem(rhs))
89                }
90            }
91
92            #[doc = doc::checked::checked_rem_euclid!(I)]
93            #[must_use = doc::must_use_op!()]
94            #[inline]
95            pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
96                if rhs.is_zero() {
97                    None
98                } else {
99                    tuple_to_option(self.overflowing_rem_euclid(rhs))
100                }
101            }
102
103            #[doc = doc::checked::checked_neg!(I)]
104            #[must_use = doc::must_use_op!()]
105            #[inline]
106            pub const fn checked_neg(self) -> Option<Self> {
107                tuple_to_option(self.overflowing_neg())
108            }
109
110            #[doc = doc::checked::checked_shl!(I)]
111            #[must_use = doc::must_use_op!()]
112            #[inline]
113            pub const fn checked_shl(self, rhs: ExpType) -> Option<Self> {
114                tuple_to_option(self.overflowing_shl(rhs))
115            }
116
117            #[doc = doc::checked::checked_shr!(I)]
118            #[must_use = doc::must_use_op!()]
119            #[inline]
120            pub const fn checked_shr(self, rhs: ExpType) -> Option<Self> {
121                tuple_to_option(self.overflowing_shr(rhs))
122            }
123
124            #[doc = doc::checked::checked_abs!(I)]
125            #[must_use = doc::must_use_op!()]
126            #[inline]
127            pub const fn checked_abs(self) -> Option<Self> {
128                tuple_to_option(self.overflowing_abs())
129            }
130
131            #[doc = doc::checked::checked_pow!(I)]
132            #[must_use = doc::must_use_op!()]
133            #[inline]
134            pub const fn checked_pow(self, pow: ExpType) -> Option<Self> {
135                match self.unsigned_abs().checked_pow(pow) {
136                    Some(u) => {
137                        let out = Self::from_bits(u);
138                        let neg = self.is_negative();
139                        if !neg || pow & 1 == 0 {
140                            if out.is_negative() {
141                                None
142                            } else {
143                                Some(out)
144                            }
145                        } else {
146                            let out = out.wrapping_neg();
147                            if !out.is_negative() {
148                                None
149                            } else {
150                                Some(out)
151                            }
152                        }
153                    }
154                    None => None,
155                }
156            }
157
158            #[doc = doc::checked::checked_next_multiple_of!(I)]
159            #[must_use = doc::must_use_op!()]
160            #[inline]
161            pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
162                if rhs.is_zero() {
163                    return None;
164                }
165                let rem = self.wrapping_rem_euclid(rhs);
166                if rem.is_zero() {
167                    return Some(self);
168                }
169                if rem.is_negative() == rhs.is_negative() {
170                    self.checked_add(rhs.wrapping_sub(rem))
171                } else {
172                    self.checked_sub(rem)
173                }
174            }
175
176            #[doc = doc::checked::checked_ilog!(I)]
177            #[must_use = doc::must_use_op!()]
178            #[inline]
179            pub const fn checked_ilog(self, base: Self) -> Option<ExpType> {
180                if base.is_negative() || self.is_negative() {
181                    None
182                } else {
183                    self.to_bits().checked_ilog(base.to_bits())
184                }
185            }
186
187            checked_ilog!(checked_ilog2);
188            checked_ilog!(checked_ilog10);
189        }
190    };
191}
192
193crate::macro_impl!(checked);