1use super::addition::{__add2, add2};
2use super::subtraction::sub2;
3use super::{biguint_from_vec, cmp_slice, BigUint, IntDigits};
4
5use crate::big_digit::{self, BigDigit, DoubleBigDigit};
6use crate::Sign::{self, Minus, NoSign, Plus};
7use crate::{BigInt, UsizePromotion};
8
9use core::cmp::Ordering;
10use core::iter::Product;
11use core::ops::{Mul, MulAssign};
12use num_traits::{CheckedMul, FromPrimitive, One, Zero};
13
14#[inline]
15pub(super) fn mac_with_carry(
16 a: BigDigit,
17 b: BigDigit,
18 c: BigDigit,
19 acc: &mut DoubleBigDigit,
20) -> BigDigit {
21 *acc += DoubleBigDigit::from(a);
22 *acc += DoubleBigDigit::from(b) * DoubleBigDigit::from(c);
23 let lo = *acc as BigDigit;
24 *acc >>= big_digit::BITS;
25 lo
26}
27
28#[inline]
29fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
30 *acc += DoubleBigDigit::from(a) * DoubleBigDigit::from(b);
31 let lo = *acc as BigDigit;
32 *acc >>= big_digit::BITS;
33 lo
34}
35
36fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) {
39 if c == 0 {
40 return;
41 }
42
43 let mut carry = 0;
44 let (a_lo, a_hi) = acc.split_at_mut(b.len());
45
46 for (a, &b) in a_lo.iter_mut().zip(b) {
47 *a = mac_with_carry(*a, b, c, &mut carry);
48 }
49
50 let (carry_hi, carry_lo) = big_digit::from_doublebigdigit(carry);
51
52 let final_carry = if carry_hi == 0 {
53 __add2(a_hi, &[carry_lo])
54 } else {
55 __add2(a_hi, &[carry_hi, carry_lo])
56 };
57 match (&final_carry, &0) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::Some(format_args!("carry overflow during multiplication!")));
}
}
};assert_eq!(final_carry, 0, "carry overflow during multiplication!");
58}
59
60fn bigint_from_slice(slice: &[BigDigit]) -> BigInt {
61 BigInt::from(biguint_from_vec(slice.to_vec()))
62}
63
64#[allow(clippy::many_single_char_names)]
67fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) {
68 if let Some(&0) = b.first() {
70 if let Some(nz) = b.iter().position(|&d| d != 0) {
71 b = &b[nz..];
72 acc = &mut acc[nz..];
73 } else {
74 return;
75 }
76 }
77 if let Some(&0) = c.first() {
78 if let Some(nz) = c.iter().position(|&d| d != 0) {
79 c = &c[nz..];
80 acc = &mut acc[nz..];
81 } else {
82 return;
83 }
84 }
85
86 let acc = acc;
87 let (x, y) = if b.len() < c.len() { (b, c) } else { (c, b) };
88
89 if x.len() <= 32 {
102 for (i, xi) in x.iter().enumerate() {
104 mac_digit(&mut acc[i..], y, *xi);
105 }
106 } else if x.len() * 2 <= y.len() {
107 let m2 = y.len() / 2;
160 let (low2, high2) = y.split_at(m2);
161
162 mac3(acc, x, low2);
164 mac3(&mut acc[m2..], x, high2);
165 } else if x.len() <= 256 {
166 let b = x.len() / 2;
230 let (x0, x1) = x.split_at(b);
231 let (y0, y1) = y.split_at(b);
232
233 let len = x1.len() + y1.len() + 1;
236 let mut p = BigUint { data: ::alloc::vec::from_elem(0, len)vec![0; len] };
237
238 mac3(&mut p.data, x1, y1);
240
241 p.normalize();
243
244 add2(&mut acc[b..], &p.data);
245 add2(&mut acc[b * 2..], &p.data);
246
247 p.data.truncate(0);
249 p.data.resize(len, 0);
250
251 mac3(&mut p.data, x0, y0);
253 p.normalize();
254
255 add2(acc, &p.data);
256 add2(&mut acc[b..], &p.data);
257
258 let (j0_sign, j0) = sub_sign(x1, x0);
261 let (j1_sign, j1) = sub_sign(y1, y0);
262
263 match j0_sign * j1_sign {
264 Plus => {
265 p.data.truncate(0);
266 p.data.resize(len, 0);
267
268 mac3(&mut p.data, &j0.data, &j1.data);
269 p.normalize();
270
271 sub2(&mut acc[b..], &p.data);
272 }
273 Minus => {
274 mac3(&mut acc[b..], &j0.data, &j1.data);
275 }
276 NoSign => (),
277 }
278 } else {
279 let i = y.len() / 3 + 1;
288
289 let x0_len = Ord::min(x.len(), i);
290 let x1_len = Ord::min(x.len() - x0_len, i);
291
292 let y0_len = i;
293 let y1_len = Ord::min(y.len() - y0_len, i);
294
295 let x0 = bigint_from_slice(&x[..x0_len]);
301 let x1 = bigint_from_slice(&x[x0_len..x0_len + x1_len]);
302 let x2 = bigint_from_slice(&x[x0_len + x1_len..]);
303
304 let y0 = bigint_from_slice(&y[..y0_len]);
306 let y1 = bigint_from_slice(&y[y0_len..y0_len + y1_len]);
307 let y2 = bigint_from_slice(&y[y0_len + y1_len..]);
308
309 let p = &x0 + &x2;
335
336 let q = &y0 + &y2;
338
339 let p2 = &p - &x1;
341
342 let q2 = &q - &y1;
344
345 let r0 = &x0 * &y0;
347
348 let r4 = &x2 * &y2;
350
351 let r1 = (p + x1) * (q + y1);
353
354 let r2 = &p2 * &q2;
356
357 let r3 = ((p2 + x2) * 2 - x0) * ((q2 + y2) * 2 - y0);
359
360 let mut comp3: BigInt = (r3 - &r1) / 3u32;
380 let mut comp1: BigInt = (r1 - &r2) >> 1;
381 let mut comp2: BigInt = r2 - &r0;
382 comp3 = ((&comp2 - comp3) >> 1) + (&r4 << 1);
383 comp2 += &comp1 - &r4;
384 comp1 -= &comp3;
385
386 for (j, result) in [&r0, &comp1, &comp2, &comp3, &r4].iter().enumerate().rev() {
401 match result.sign() {
402 Plus => add2(&mut acc[i * j..], result.digits()),
403 Minus => sub2(&mut acc[i * j..], result.digits()),
404 NoSign => {}
405 }
406 }
407 }
408}
409
410fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint {
411 let len = x.len() + y.len() + 1;
412 let mut prod = BigUint { data: ::alloc::vec::from_elem(0, len)vec![0; len] };
413
414 mac3(&mut prod.data, x, y);
415 prod.normalized()
416}
417
418fn scalar_mul(a: &mut BigUint, b: BigDigit) {
419 match b {
420 0 => a.set_zero(),
421 1 => {}
422 _ => {
423 if b.is_power_of_two() {
424 *a <<= b.trailing_zeros();
425 } else {
426 let mut carry = 0;
427 for a in a.data.iter_mut() {
428 *a = mul_with_carry(*a, b, &mut carry);
429 }
430 if carry != 0 {
431 a.data.push(carry as BigDigit);
432 }
433 }
434 }
435 }
436}
437
438fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) {
439 if let Some(&0) = a.last() {
441 a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)];
442 }
443 if let Some(&0) = b.last() {
444 b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)];
445 }
446
447 match cmp_slice(a, b) {
448 Ordering::Greater => {
449 let mut a = a.to_vec();
450 sub2(&mut a, b);
451 (Plus, biguint_from_vec(a))
452 }
453 Ordering::Less => {
454 let mut b = b.to_vec();
455 sub2(&mut b, a);
456 (Minus, biguint_from_vec(b))
457 }
458 Ordering::Equal => (NoSign, BigUint::ZERO),
459 }
460}
461
462macro_rules! impl_mul {
463 ($(impl Mul<$Other:ty> for $Self:ty;)*) => {$(
464 impl Mul<$Other> for $Self {
465 type Output = BigUint;
466
467 #[inline]
468 fn mul(self, other: $Other) -> BigUint {
469 match (&*self.data, &*other.data) {
470 (&[], _) | (_, &[]) => BigUint::ZERO,
472 (_, &[digit]) => self * digit,
474 (&[digit], _) => other * digit,
475 (x, y) => mul3(x, y),
477 }
478 }
479 }
480 )*}
481}
482impl Mul<&BigUint> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint {
match (&*self.data, &*other.data) {
(&[], _) | (_, &[]) => BigUint::ZERO,
(_, &[digit]) => self * digit,
(&[digit], _) => other * digit,
(x, y) => mul3(x, y),
}
}
}impl_mul! {
483 impl Mul<BigUint> for BigUint;
484 impl Mul<BigUint> for &BigUint;
485 impl Mul<&BigUint> for BigUint;
486 impl Mul<&BigUint> for &BigUint;
487}
488
489macro_rules! impl_mul_assign {
490 ($(impl MulAssign<$Other:ty> for BigUint;)*) => {$(
491 impl MulAssign<$Other> for BigUint {
492 #[inline]
493 fn mul_assign(&mut self, other: $Other) {
494 match (&*self.data, &*other.data) {
495 (&[], _) => {},
497 (_, &[]) => self.set_zero(),
498 (_, &[digit]) => *self *= digit,
500 (&[digit], _) => *self = other * digit,
501 (x, y) => *self = mul3(x, y),
503 }
504 }
505 }
506 )*}
507}
508impl MulAssign<&BigUint> for BigUint {
#[inline]
fn mul_assign(&mut self, other: &BigUint) {
match (&*self.data, &*other.data) {
(&[], _) => {}
(_, &[]) => self.set_zero(),
(_, &[digit]) => *self *= digit,
(&[digit], _) => *self = other * digit,
(x, y) => *self = mul3(x, y),
}
}
}impl_mul_assign! {
509 impl MulAssign<BigUint> for BigUint;
510 impl MulAssign<&BigUint> for BigUint;
511}
512
513impl Mul<&usize> for BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &usize) -> BigUint { Mul::mul(self, *other) }
}
impl Mul<BigUint> for &usize {
type Output = BigUint;
#[inline]
fn mul(self, other: BigUint) -> BigUint { Mul::mul(*self, other) }
}
impl Mul<usize> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: usize) -> BigUint { Mul::mul(self.clone(), other) }
}
impl Mul<&BigUint> for usize {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint { Mul::mul(self, other.clone()) }
}
impl Mul<&usize> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &usize) -> BigUint { Mul::mul(self.clone(), *other) }
}
impl Mul<&BigUint> for &usize {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint {
Mul::mul(*self, other.clone())
}
}
impl Mul<usize> for BigUint {
type Output = BigUint;
#[allow(clippy :: cast_lossless)]
#[inline]
fn mul(self, other: usize) -> BigUint {
Mul::mul(self, other as UsizePromotion)
}
}
impl Mul<BigUint> for usize {
type Output = BigUint;
#[allow(clippy :: cast_lossless)]
#[inline]
fn mul(self, other: BigUint) -> BigUint {
Mul::mul(self as UsizePromotion, other)
}
}promote_unsigned_scalars!(impl Mul for BigUint, mul);
514impl MulAssign<usize> for BigUint {
#[allow(clippy :: cast_lossless)]
#[inline]
fn mul_assign(&mut self, other: usize) {
self.mul_assign(other as UsizePromotion);
}
}promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign);
515impl Mul<BigUint> for u32 {
type Output = BigUint;
#[inline]
fn mul(self, other: BigUint) -> BigUint { Mul::mul(other, self) }
}
impl Mul<&u32> for BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &u32) -> BigUint { Mul::mul(self, *other) }
}
impl Mul<BigUint> for &u32 {
type Output = BigUint;
#[inline]
fn mul(self, other: BigUint) -> BigUint { Mul::mul(*self, other) }
}
impl Mul<u32> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: u32) -> BigUint { Mul::mul(self.clone(), other) }
}
impl Mul<&BigUint> for u32 {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint { Mul::mul(self, other.clone()) }
}
impl Mul<&u32> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &u32) -> BigUint { Mul::mul(self.clone(), *other) }
}
impl Mul<&BigUint> for &u32 {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint {
Mul::mul(*self, other.clone())
}
}forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u32> for BigUint, mul);
516impl Mul<BigUint> for u64 {
type Output = BigUint;
#[inline]
fn mul(self, other: BigUint) -> BigUint { Mul::mul(other, self) }
}
impl Mul<&u64> for BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &u64) -> BigUint { Mul::mul(self, *other) }
}
impl Mul<BigUint> for &u64 {
type Output = BigUint;
#[inline]
fn mul(self, other: BigUint) -> BigUint { Mul::mul(*self, other) }
}
impl Mul<u64> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: u64) -> BigUint { Mul::mul(self.clone(), other) }
}
impl Mul<&BigUint> for u64 {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint { Mul::mul(self, other.clone()) }
}
impl Mul<&u64> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &u64) -> BigUint { Mul::mul(self.clone(), *other) }
}
impl Mul<&BigUint> for &u64 {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint {
Mul::mul(*self, other.clone())
}
}forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u64> for BigUint, mul);
517impl Mul<BigUint> for u128 {
type Output = BigUint;
#[inline]
fn mul(self, other: BigUint) -> BigUint { Mul::mul(other, self) }
}
impl Mul<&u128> for BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &u128) -> BigUint { Mul::mul(self, *other) }
}
impl Mul<BigUint> for &u128 {
type Output = BigUint;
#[inline]
fn mul(self, other: BigUint) -> BigUint { Mul::mul(*self, other) }
}
impl Mul<u128> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: u128) -> BigUint { Mul::mul(self.clone(), other) }
}
impl Mul<&BigUint> for u128 {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint { Mul::mul(self, other.clone()) }
}
impl Mul<&u128> for &BigUint {
type Output = BigUint;
#[inline]
fn mul(self, other: &u128) -> BigUint { Mul::mul(self.clone(), *other) }
}
impl Mul<&BigUint> for &u128 {
type Output = BigUint;
#[inline]
fn mul(self, other: &BigUint) -> BigUint {
Mul::mul(*self, other.clone())
}
}forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u128> for BigUint, mul);
518
519impl Mul<u32> for BigUint {
520 type Output = BigUint;
521
522 #[inline]
523 fn mul(mut self, other: u32) -> BigUint {
524 self *= other;
525 self
526 }
527}
528impl MulAssign<u32> for BigUint {
529 #[inline]
530 fn mul_assign(&mut self, other: u32) {
531 scalar_mul(self, other as BigDigit);
532 }
533}
534
535impl Mul<u64> for BigUint {
536 type Output = BigUint;
537
538 #[inline]
539 fn mul(mut self, other: u64) -> BigUint {
540 self *= other;
541 self
542 }
543}
544impl MulAssign<u64> for BigUint {
545 cfg_digit!(
546 #[inline]
547 fn mul_assign(&mut self, other: u64) {
548 if let Some(other) = BigDigit::from_u64(other) {
549 scalar_mul(self, other);
550 } else {
551 let (hi, lo) = big_digit::from_doublebigdigit(other);
552 *self = mul3(&self.data, &[lo, hi]);
553 }
554 }
555
556 #[inline]
557 fn mul_assign(&mut self, other: u64) {
558 scalar_mul(self, other);
559 }
560 );
561}
562
563impl Mul<u128> for BigUint {
564 type Output = BigUint;
565
566 #[inline]
567 fn mul(mut self, other: u128) -> BigUint {
568 self *= other;
569 self
570 }
571}
572
573impl MulAssign<u128> for BigUint {
574 cfg_digit!(
575 #[inline]
576 fn mul_assign(&mut self, other: u128) {
577 if let Some(other) = BigDigit::from_u128(other) {
578 scalar_mul(self, other);
579 } else {
580 *self = match super::u32_from_u128(other) {
581 (0, 0, c, d) => mul3(&self.data, &[d, c]),
582 (0, b, c, d) => mul3(&self.data, &[d, c, b]),
583 (a, b, c, d) => mul3(&self.data, &[d, c, b, a]),
584 };
585 }
586 }
587
588 #[inline]
589 fn mul_assign(&mut self, other: u128) {
590 if let Some(other) = BigDigit::from_u128(other) {
591 scalar_mul(self, other);
592 } else {
593 let (hi, lo) = big_digit::from_doublebigdigit(other);
594 *self = mul3(&self.data, &[lo, hi]);
595 }
596 }
597 );
598}
599
600impl CheckedMul for BigUint {
601 #[inline]
602 fn checked_mul(&self, v: &BigUint) -> Option<BigUint> {
603 Some(self.mul(v))
604 }
605}
606
607impl<T> Product<T> for BigUint where BigUint: Mul<T, Output = BigUint> {
fn product<I>(iter: I) -> Self where I: Iterator<Item = T> {
iter.fold(One::one(), <BigUint>::mul)
}
}impl_product_iter_type!(BigUint);
608
609#[test]
610fn test_sub_sign() {
611 use crate::BigInt;
612 use num_traits::Num;
613
614 fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt {
615 let (sign, val) = sub_sign(a, b);
616 BigInt::from_biguint(sign, val)
617 }
618
619 let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap();
620 let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap();
621 let a_i = BigInt::from(a.clone());
622 let b_i = BigInt::from(b.clone());
623
624 assert_eq!(sub_sign_i(&a.data, &b.data), &a_i - &b_i);
625 assert_eq!(sub_sign_i(&b.data, &a.data), &b_i - &a_i);
626}