1use crate::digit;
2use crate::doc;
3use crate::errors::div_zero;
4use crate::int::checked::tuple_to_option;
5use crate::ExpType;
6
7macro_rules! checked {
8 ($BUint: ident, $BInt: ident, $Digit: ident) => {
9 #[doc = doc::checked::impl_desc!()]
10 impl<const N: usize> $BUint<N> {
11 #[doc = doc::checked::checked_add!(U)]
12 #[must_use = doc::must_use_op!()]
13 #[inline]
14 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
15 tuple_to_option(self.overflowing_add(rhs))
16 }
17
18 #[doc = doc::checked::checked_add_signed!(U)]
19 #[must_use = doc::must_use_op!()]
20 #[inline]
21 pub const fn checked_add_signed(self, rhs: $BInt<N>) -> Option<Self> {
22 tuple_to_option(self.overflowing_add_signed(rhs))
23 }
24
25 #[doc = doc::checked::checked_sub!(U)]
26 #[must_use = doc::must_use_op!()]
27 #[inline]
28 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
29 tuple_to_option(self.overflowing_sub(rhs))
30 }
31
32 #[doc = doc::checked::checked_mul!(U)]
33 #[must_use = doc::must_use_op!()]
34 #[inline]
35 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
36 tuple_to_option(self.overflowing_mul(rhs))
37 }
38
39 pub(crate) const fn div_rem_digit(self, rhs: $Digit) -> (Self, $Digit) {
40 let mut out = Self::ZERO;
41 let mut rem: $Digit = 0;
42 let mut i = N;
43 while i > 0 {
44 i -= 1;
45 let (q, r) = digit::$Digit::div_rem_wide(self.digits[i], rem, rhs);
46 rem = r;
47 out.digits[i] = q;
48 }
49 (out, rem)
50 }
51 const fn basecase_div_rem(self, mut v: Self, n: usize) -> (Self, Self) {
52 let mut q = Self::ZERO;
55 let m = self.last_digit_index() + 1 - n;
56 let shift = v.digits[n - 1].leading_zeros() as ExpType;
57
58 v = unsafe { Self::unchecked_shl_internal(v, shift) }; struct Remainder<const M: usize> {
61 first: $Digit,
62 rest: [$Digit; M],
63 }
64 impl<const M: usize> Remainder<M> {
65 const fn digit(&self, index: usize) -> $Digit {
66 if index == 0 {
67 self.first
68 } else {
69 self.rest[index - 1]
70 }
71 }
72 const fn shr(self, shift: ExpType) -> $BUint<M> {
73 let mut out = $BUint::ZERO;
74 let mut i = 0;
75 while i < M {
76 out.digits[i] = self.digit(i) >> shift;
77 i += 1;
78 }
79 if shift > 0 {
80 i = 0;
81 while i < M {
82 out.digits[i] |=
83 self.rest[i] << (digit::$Digit::BITS as ExpType - shift);
84 i += 1;
85 }
86 }
87 out
88 }
89 const fn new(uint: $BUint<M>, shift: ExpType) -> Self {
90 let first = uint.digits[0] << shift;
91 let rest = uint.wrapping_shr(digit::$Digit::BITS - shift);
92 Self {
93 first,
94 rest: rest.digits,
95 }
96 }
97 const fn sub(
131 mut self,
132 rhs: Mul<M>,
133 start: usize,
134 range: usize,
135 ) -> (Self, bool) {
136 let mut borrow = false;
137 let mut i = 0;
138 while i <= range {
139 let (sub, overflow) = digit::$Digit::borrowing_sub(
140 self.digit(i + start),
141 rhs.digit(i),
142 borrow,
143 );
144 if start == 0 && i == 0 {
145 self.first = sub;
146 } else {
147 self.rest[i + start - 1] = sub;
148 }
149 borrow = overflow;
150 i += 1;
151 }
152 (self, borrow)
153 }
154 const fn add(mut self, rhs: $BUint<M>, start: usize, range: usize) -> Self {
155 let mut carry = false;
156 let mut i = 0;
157 while i < range {
158 let (sum, overflow) = digit::$Digit::carrying_add(
159 self.digit(i + start),
160 rhs.digits[i],
161 carry,
162 );
163 if start == 0 && i == 0 {
164 self.first = sum;
165 } else {
166 self.rest[i + start - 1] = sum;
167 }
168 carry = overflow;
169 i += 1;
170 }
171 if carry {
172 if start == 0 && range == 0 {
173 self.first = self.first.wrapping_add(1);
174 } else {
175 self.rest[range + start - 1] =
176 self.rest[range + start - 1].wrapping_add(1);
177 }
178 }
179 self
180 }
181 }
182
183 #[derive(Clone, Copy)]
184 struct Mul<const M: usize> {
185 last: $Digit,
186 rest: [$Digit; M],
187 }
188 impl<const M: usize> Mul<M> {
189 const fn new(uint: $BUint<M>, rhs: $Digit) -> Self {
190 let mut rest = [0; M];
191 let mut carry: $Digit = 0;
192 let mut i = 0;
193 while i < M {
194 let (prod, c) =
195 digit::$Digit::carrying_mul(uint.digits[i], rhs, carry, 0);
196 carry = c;
197 rest[i] = prod;
198 i += 1;
199 }
200 Self { last: carry, rest }
201 }
202 const fn digit(&self, index: usize) -> $Digit {
203 if index == M {
204 self.last
205 } else {
206 self.rest[index]
207 }
208 }
209 }
210
211 let v_n_m1 = v.digits[n - 1];
212 let v_n_m2 = v.digits[n - 2];
213
214 let mut u = Remainder::new(self, shift);
215
216 let mut j = m + 1; while j > 0 {
218 j -= 1; let u_jn = u.digit(j + n);
221
222 #[inline]
223 const fn tuple_gt(a: ($Digit, $Digit), b: ($Digit, $Digit)) -> bool {
224 a.1 > b.1 || a.1 == b.1 && a.0 > b.0
225 }
226
227 let mut q_hat = if u_jn < v_n_m1 {
229 let (mut q_hat, r_hat) =
230 digit::$Digit::div_rem_wide(u.digit(j + n - 1), u_jn, v_n_m1); if tuple_gt(
233 digit::$Digit::widening_mul(q_hat, v_n_m2),
234 (u.digit(j + n - 2), r_hat as $Digit),
235 ) {
236 q_hat -= 1;
237
238 if let Some(r_hat) = r_hat.checked_add(v_n_m1) {
239 if tuple_gt(
241 digit::$Digit::widening_mul(q_hat, v_n_m2),
242 (u.digit(j + n - 2), r_hat as $Digit),
243 ) {
244 q_hat -= 1;
245 }
246 }
247 }
248 q_hat
249 } else {
250 $Digit::MAX
252 };
253 let (u_new, overflow) = u.sub(Mul::new(v, q_hat), j, n); u = u_new;
255
256 if overflow {
257 q_hat -= 1;
259 u = u.add(v, j, n);
260 }
261 q.digits[j] = q_hat;
262 }
263 (q, u.shr(shift))
264 }
265
266 #[inline]
267 pub(crate) const fn div_rem_unchecked(self, rhs: Self) -> (Self, Self) {
268 use core::cmp::Ordering;
269
270 if self.is_zero() {
271 return (Self::ZERO, Self::ZERO);
272 }
273
274 match self.cmp(&rhs) {
275 Ordering::Less => (Self::ZERO, self),
276 Ordering::Equal => (Self::ONE, Self::ZERO),
277 Ordering::Greater => {
278 let ldi = rhs.last_digit_index();
279 if ldi == 0 {
280 let (div, rem) = self.div_rem_digit(rhs.digits[0]);
281 (div, Self::from_digit(rem))
282 } else {
283 self.basecase_div_rem(rhs, ldi + 1)
284 }
285 }
286 }
287 }
288
289 #[inline]
290 pub(crate) const fn div_rem(self, rhs: Self) -> (Self, Self) {
291 if rhs.is_zero() {
292 div_zero!()
293 } else {
294 self.div_rem_unchecked(rhs)
295 }
296 }
297
298 #[doc = doc::checked::checked_div!(U)]
299 #[must_use = doc::must_use_op!()]
300 #[inline]
301 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
302 if rhs.is_zero() {
303 None
304 } else {
305 Some(self.div_rem_unchecked(rhs).0)
306 }
307 }
308
309 #[doc = doc::checked::checked_div_euclid!(U)]
310 #[must_use = doc::must_use_op!()]
311 #[inline]
312 pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
313 self.checked_div(rhs)
314 }
315
316 #[doc = doc::checked::checked_rem!(U)]
317 #[must_use = doc::must_use_op!()]
318 #[inline]
319 pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
320 if rhs.is_zero() {
321 None
322 } else {
323 Some(self.div_rem_unchecked(rhs).1)
324 }
325 }
326
327 #[doc = doc::checked::checked_rem_euclid!(U)]
328 #[must_use = doc::must_use_op!()]
329 #[inline]
330 pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
331 self.checked_rem(rhs)
332 }
333
334 #[doc = doc::checked::checked_neg!(U)]
335 #[must_use = doc::must_use_op!()]
336 #[inline]
337 pub const fn checked_neg(self) -> Option<Self> {
338 if self.is_zero() {
339 Some(self)
340 } else {
341 None
342 }
343 }
344
345 #[doc = doc::checked::checked_shl!(U)]
346 #[must_use = doc::must_use_op!()]
347 #[inline]
348 pub const fn checked_shl(self, rhs: ExpType) -> Option<Self> {
349 if rhs >= Self::BITS {
350 None
351 } else {
352 unsafe { Some(Self::unchecked_shl_internal(self, rhs)) }
353 }
354 }
355
356 #[doc = doc::checked::checked_shr!(U)]
357 #[must_use = doc::must_use_op!()]
358 #[inline]
359 pub const fn checked_shr(self, rhs: ExpType) -> Option<Self> {
360 if rhs >= Self::BITS {
361 None
362 } else {
363 unsafe { Some(Self::unchecked_shr_internal(self, rhs)) }
364 }
365 }
366
367 #[doc = doc::checked::checked_pow!(U)]
368 #[must_use = doc::must_use_op!()]
369 #[inline]
370 pub const fn checked_pow(mut self, mut pow: ExpType) -> Option<Self> {
371 if pow == 0 {
373 return Some(Self::ONE);
374 }
375 let mut y = Self::ONE;
376 while pow > 1 {
377 if pow & 1 == 1 {
378 y = match self.checked_mul(y) {
379 Some(m) => m,
380 None => return None,
381 };
382 }
383 self = match self.checked_mul(self) {
384 Some(m) => m,
385 None => return None,
386 };
387 pow >>= 1;
388 }
389 self.checked_mul(y)
390 }
391
392 #[doc = doc::checked::checked_next_multiple_of!(U)]
393 #[must_use = doc::must_use_op!()]
394 #[inline]
395 pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
396 match self.checked_rem(rhs) {
397 Some(rem) => {
398 if rem.is_zero() {
399 Some(self)
401 } else {
402 self.checked_add(rhs.sub(rem))
404 }
405 }
406 None => None,
407 }
408 }
409
410 #[doc = doc::checked::checked_ilog2!(U)]
411 #[must_use = doc::must_use_op!()]
412 #[inline]
413 pub const fn checked_ilog2(self) -> Option<ExpType> {
414 self.bits().checked_sub(1)
415 }
416
417 #[inline]
418 const fn iilog(m: ExpType, b: Self, k: Self) -> (ExpType, Self) {
419 if b.gt(&k) {
421 (m, k)
422 } else {
423 let (new, q) = Self::iilog(m << 1, b.mul(b), k.div_rem_unchecked(b).0);
424 if b.gt(&q) {
425 (new, q)
426 } else {
427 (new + m, q.div(b))
428 }
429 }
430 }
431
432 #[doc = doc::checked::checked_ilog10!(U)]
433 #[must_use = doc::must_use_op!()]
434 #[inline]
435 pub const fn checked_ilog10(self) -> Option<ExpType> {
436 if self.is_zero() {
437 return None;
438 }
439 if Self::TEN.gt(&self) {
440 return Some(0);
441 }
442 Some(Self::iilog(1, Self::TEN, self.div_rem_digit(10).0).0)
443 }
444
445 #[doc = doc::checked::checked_ilog!(U)]
446 #[must_use = doc::must_use_op!()]
447 #[inline]
448 pub const fn checked_ilog(self, base: Self) -> Option<ExpType> {
449 use core::cmp::Ordering;
450 match base.cmp(&Self::TWO) {
451 Ordering::Less => None,
452 Ordering::Equal => self.checked_ilog2(),
453 Ordering::Greater => {
454 if self.is_zero() {
455 return None;
456 }
457 if base.gt(&self) {
458 return Some(0);
459 }
460 Some(Self::iilog(1, base, self.div(base)).0)
461 }
462 }
463 }
464
465 #[doc = doc::checked::checked_next_power_of_two!(U 256)]
466 #[must_use = doc::must_use_op!()]
467 #[inline]
468 pub const fn checked_next_power_of_two(self) -> Option<Self> {
469 if self.is_power_of_two() {
470 return Some(self);
471 }
472 let bits = self.bits();
473 if bits == Self::BITS {
474 return None;
475 }
476 Some(Self::power_of_two(bits))
477 }
478 }
479 };
480}
481
482crate::macro_impl!(checked);