1use super::addition::{__add2, add2};
2use super::subtraction::sub2;
3#[cfg(not(u64_digit))]
4use super::u32_from_u128;
5use super::{biguint_from_vec, cmp_slice, BigUint, IntDigits};
6
7use crate::big_digit::{self, BigDigit, DoubleBigDigit};
8use crate::Sign::{self, Minus, NoSign, Plus};
9use crate::{BigInt, UsizePromotion};
10
11use core::cmp::Ordering;
12use core::iter::Product;
13use core::ops::{Mul, MulAssign};
14use num_traits::{CheckedMul, FromPrimitive, One, Zero};
15
16#[inline]
17pub(super) fn mac_with_carry(
18 a: BigDigit,
19 b: BigDigit,
20 c: BigDigit,
21 acc: &mut DoubleBigDigit,
22) -> BigDigit {
23 *acc += DoubleBigDigit::from(a);
24 *acc += DoubleBigDigit::from(b) * DoubleBigDigit::from(c);
25 let lo = *acc as BigDigit;
26 *acc >>= big_digit::BITS;
27 lo
28}
29
30#[inline]
31fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
32 *acc += DoubleBigDigit::from(a) * DoubleBigDigit::from(b);
33 let lo = *acc as BigDigit;
34 *acc >>= big_digit::BITS;
35 lo
36}
37
38fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) {
41 if c == 0 {
42 return;
43 }
44
45 let mut carry = 0;
46 let (a_lo, a_hi) = acc.split_at_mut(b.len());
47
48 for (a, &b) in a_lo.iter_mut().zip(b) {
49 *a = mac_with_carry(*a, b, c, &mut carry);
50 }
51
52 let (carry_hi, carry_lo) = big_digit::from_doublebigdigit(carry);
53
54 let final_carry = if carry_hi == 0 {
55 __add2(a_hi, &[carry_lo])
56 } else {
57 __add2(a_hi, &[carry_hi, carry_lo])
58 };
59 assert_eq!(final_carry, 0, "carry overflow during multiplication!");
60}
61
62fn bigint_from_slice(slice: &[BigDigit]) -> BigInt {
63 BigInt::from(biguint_from_vec(slice.to_vec()))
64}
65
66#[allow(clippy::many_single_char_names)]
69fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) {
70 if let Some(&0) = b.first() {
72 if let Some(nz) = b.iter().position(|&d| d != 0) {
73 b = &b[nz..];
74 acc = &mut acc[nz..];
75 } else {
76 return;
77 }
78 }
79 if let Some(&0) = c.first() {
80 if let Some(nz) = c.iter().position(|&d| d != 0) {
81 c = &c[nz..];
82 acc = &mut acc[nz..];
83 } else {
84 return;
85 }
86 }
87
88 let acc = acc;
89 let (x, y) = if b.len() < c.len() { (b, c) } else { (c, b) };
90
91 if x.len() <= 32 {
103 for (i, xi) in x.iter().enumerate() {
105 mac_digit(&mut acc[i..], y, *xi);
106 }
107 } else if x.len() <= 256 {
108 let b = x.len() / 2;
172 let (x0, x1) = x.split_at(b);
173 let (y0, y1) = y.split_at(b);
174
175 let len = x1.len() + y1.len() + 1;
178 let mut p = BigUint { data: vec![0; len] };
179
180 mac3(&mut p.data, x1, y1);
182
183 p.normalize();
185
186 add2(&mut acc[b..], &p.data);
187 add2(&mut acc[b * 2..], &p.data);
188
189 p.data.truncate(0);
191 p.data.resize(len, 0);
192
193 mac3(&mut p.data, x0, y0);
195 p.normalize();
196
197 add2(acc, &p.data);
198 add2(&mut acc[b..], &p.data);
199
200 let (j0_sign, j0) = sub_sign(x1, x0);
203 let (j1_sign, j1) = sub_sign(y1, y0);
204
205 match j0_sign * j1_sign {
206 Plus => {
207 p.data.truncate(0);
208 p.data.resize(len, 0);
209
210 mac3(&mut p.data, &j0.data, &j1.data);
211 p.normalize();
212
213 sub2(&mut acc[b..], &p.data);
214 }
215 Minus => {
216 mac3(&mut acc[b..], &j0.data, &j1.data);
217 }
218 NoSign => (),
219 }
220 } else {
221 let i = y.len() / 3 + 1;
230
231 let x0_len = Ord::min(x.len(), i);
232 let x1_len = Ord::min(x.len() - x0_len, i);
233
234 let y0_len = i;
235 let y1_len = Ord::min(y.len() - y0_len, i);
236
237 let x0 = bigint_from_slice(&x[..x0_len]);
243 let x1 = bigint_from_slice(&x[x0_len..x0_len + x1_len]);
244 let x2 = bigint_from_slice(&x[x0_len + x1_len..]);
245
246 let y0 = bigint_from_slice(&y[..y0_len]);
248 let y1 = bigint_from_slice(&y[y0_len..y0_len + y1_len]);
249 let y2 = bigint_from_slice(&y[y0_len + y1_len..]);
250
251 let p = &x0 + &x2;
277
278 let q = &y0 + &y2;
280
281 let p2 = &p - &x1;
283
284 let q2 = &q - &y1;
286
287 let r0 = &x0 * &y0;
289
290 let r4 = &x2 * &y2;
292
293 let r1 = (p + x1) * (q + y1);
295
296 let r2 = &p2 * &q2;
298
299 let r3 = ((p2 + x2) * 2 - x0) * ((q2 + y2) * 2 - y0);
301
302 let mut comp3: BigInt = (r3 - &r1) / 3u32;
322 let mut comp1: BigInt = (r1 - &r2) >> 1;
323 let mut comp2: BigInt = r2 - &r0;
324 comp3 = ((&comp2 - comp3) >> 1) + (&r4 << 1);
325 comp2 += &comp1 - &r4;
326 comp1 -= &comp3;
327
328 for (j, result) in [&r0, &comp1, &comp2, &comp3, &r4].iter().enumerate().rev() {
343 match result.sign() {
344 Plus => add2(&mut acc[i * j..], result.digits()),
345 Minus => sub2(&mut acc[i * j..], result.digits()),
346 NoSign => {}
347 }
348 }
349 }
350}
351
352fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint {
353 let len = x.len() + y.len() + 1;
354 let mut prod = BigUint { data: vec![0; len] };
355
356 mac3(&mut prod.data, x, y);
357 prod.normalized()
358}
359
360fn scalar_mul(a: &mut BigUint, b: BigDigit) {
361 match b {
362 0 => a.set_zero(),
363 1 => {}
364 _ => {
365 if b.is_power_of_two() {
366 *a <<= b.trailing_zeros();
367 } else {
368 let mut carry = 0;
369 for a in a.data.iter_mut() {
370 *a = mul_with_carry(*a, b, &mut carry);
371 }
372 if carry != 0 {
373 a.data.push(carry as BigDigit);
374 }
375 }
376 }
377 }
378}
379
380fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) {
381 if let Some(&0) = a.last() {
383 a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)];
384 }
385 if let Some(&0) = b.last() {
386 b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)];
387 }
388
389 match cmp_slice(a, b) {
390 Ordering::Greater => {
391 let mut a = a.to_vec();
392 sub2(&mut a, b);
393 (Plus, biguint_from_vec(a))
394 }
395 Ordering::Less => {
396 let mut b = b.to_vec();
397 sub2(&mut b, a);
398 (Minus, biguint_from_vec(b))
399 }
400 Ordering::Equal => (NoSign, Zero::zero()),
401 }
402}
403
404macro_rules! impl_mul {
405 ($(impl<$($a:lifetime),*> Mul<$Other:ty> for $Self:ty;)*) => {$(
406 impl<$($a),*> Mul<$Other> for $Self {
407 type Output = BigUint;
408
409 #[inline]
410 fn mul(self, other: $Other) -> BigUint {
411 match (&*self.data, &*other.data) {
412 (&[], _) | (_, &[]) => BigUint::zero(),
414 (_, &[digit]) => self * digit,
416 (&[digit], _) => other * digit,
417 (x, y) => mul3(x, y),
419 }
420 }
421 }
422 )*}
423}
424impl_mul! {
425 impl<> Mul<BigUint> for BigUint;
426 impl<'b> Mul<&'b BigUint> for BigUint;
427 impl<'a> Mul<BigUint> for &'a BigUint;
428 impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint;
429}
430
431macro_rules! impl_mul_assign {
432 ($(impl<$($a:lifetime),*> MulAssign<$Other:ty> for BigUint;)*) => {$(
433 impl<$($a),*> MulAssign<$Other> for BigUint {
434 #[inline]
435 fn mul_assign(&mut self, other: $Other) {
436 match (&*self.data, &*other.data) {
437 (&[], _) => {},
439 (_, &[]) => self.set_zero(),
440 (_, &[digit]) => *self *= digit,
442 (&[digit], _) => *self = other * digit,
443 (x, y) => *self = mul3(x, y),
445 }
446 }
447 }
448 )*}
449}
450impl_mul_assign! {
451 impl<> MulAssign<BigUint> for BigUint;
452 impl<'a> MulAssign<&'a BigUint> for BigUint;
453}
454
455promote_unsigned_scalars!(impl Mul for BigUint, mul);
456promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign);
457forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u32> for BigUint, mul);
458forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u64> for BigUint, mul);
459forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u128> for BigUint, mul);
460
461impl Mul<u32> for BigUint {
462 type Output = BigUint;
463
464 #[inline]
465 fn mul(mut self, other: u32) -> BigUint {
466 self *= other;
467 self
468 }
469}
470impl MulAssign<u32> for BigUint {
471 #[inline]
472 fn mul_assign(&mut self, other: u32) {
473 scalar_mul(self, other as BigDigit);
474 }
475}
476
477impl Mul<u64> for BigUint {
478 type Output = BigUint;
479
480 #[inline]
481 fn mul(mut self, other: u64) -> BigUint {
482 self *= other;
483 self
484 }
485}
486impl MulAssign<u64> for BigUint {
487 #[cfg(not(u64_digit))]
488 #[inline]
489 fn mul_assign(&mut self, other: u64) {
490 if let Some(other) = BigDigit::from_u64(other) {
491 scalar_mul(self, other);
492 } else {
493 let (hi, lo) = big_digit::from_doublebigdigit(other);
494 *self = mul3(&self.data, &[lo, hi]);
495 }
496 }
497
498 #[cfg(u64_digit)]
499 #[inline]
500 fn mul_assign(&mut self, other: u64) {
501 scalar_mul(self, other);
502 }
503}
504
505impl Mul<u128> for BigUint {
506 type Output = BigUint;
507
508 #[inline]
509 fn mul(mut self, other: u128) -> BigUint {
510 self *= other;
511 self
512 }
513}
514
515impl MulAssign<u128> for BigUint {
516 #[cfg(not(u64_digit))]
517 #[inline]
518 fn mul_assign(&mut self, other: u128) {
519 if let Some(other) = BigDigit::from_u128(other) {
520 scalar_mul(self, other);
521 } else {
522 *self = match u32_from_u128(other) {
523 (0, 0, c, d) => mul3(&self.data, &[d, c]),
524 (0, b, c, d) => mul3(&self.data, &[d, c, b]),
525 (a, b, c, d) => mul3(&self.data, &[d, c, b, a]),
526 };
527 }
528 }
529
530 #[cfg(u64_digit)]
531 #[inline]
532 fn mul_assign(&mut self, other: u128) {
533 if let Some(other) = BigDigit::from_u128(other) {
534 scalar_mul(self, other);
535 } else {
536 let (hi, lo) = big_digit::from_doublebigdigit(other);
537 *self = mul3(&self.data, &[lo, hi]);
538 }
539 }
540}
541
542impl CheckedMul for BigUint {
543 #[inline]
544 fn checked_mul(&self, v: &BigUint) -> Option<BigUint> {
545 Some(self.mul(v))
546 }
547}
548
549impl_product_iter_type!(BigUint);
550
551#[test]
552fn test_sub_sign() {
553 use crate::BigInt;
554 use num_traits::Num;
555
556 fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt {
557 let (sign, val) = sub_sign(a, b);
558 BigInt::from_biguint(sign, val)
559 }
560
561 let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap();
562 let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap();
563 let a_i = BigInt::from(a.clone());
564 let b_i = BigInt::from(b.clone());
565
566 assert_eq!(sub_sign_i(&a.data, &b.data), &a_i - &b_i);
567 assert_eq!(sub_sign_i(&b.data, &a.data), &b_i - &a_i);
568}