|
1 | 1 | use super::addition::{__add2, add2};
|
2 |
| -use super::subtraction::{sub2, sub_sign}; |
| 2 | +use super::subtraction::sub2; |
3 | 3 | #[cfg(not(u64_digit))]
|
4 | 4 | use super::u32_from_u128;
|
5 |
| -use super::{biguint_from_vec, BigUint}; |
| 5 | +use super::{biguint_from_vec, cmp_slice, BigUint}; |
6 | 6 |
|
7 | 7 | use crate::big_digit::{self, BigDigit, DoubleBigDigit};
|
8 |
| -use crate::bigint::Sign::{Minus, NoSign, Plus}; |
| 8 | +use crate::Sign::{self, Minus, NoSign, Plus}; |
9 | 9 | use crate::{BigInt, UsizePromotion};
|
10 | 10 |
|
| 11 | +use core::cmp::Ordering; |
11 | 12 | use core::iter::Product;
|
12 | 13 | use core::ops::{Mul, MulAssign};
|
13 |
| -use num_traits::{CheckedMul, One}; |
| 14 | +use num_traits::{CheckedMul, One, Zero}; |
14 | 15 |
|
15 | 16 | #[inline]
|
16 | 17 | pub(super) fn mac_with_carry(
|
@@ -335,6 +336,26 @@ fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit {
|
335 | 336 | carry as BigDigit
|
336 | 337 | }
|
337 | 338 |
|
| 339 | +fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { |
| 340 | + // Normalize: |
| 341 | + a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; |
| 342 | + b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; |
| 343 | + |
| 344 | + match cmp_slice(a, b) { |
| 345 | + Ordering::Greater => { |
| 346 | + let mut a = a.to_vec(); |
| 347 | + sub2(&mut a, b); |
| 348 | + (Plus, biguint_from_vec(a)) |
| 349 | + } |
| 350 | + Ordering::Less => { |
| 351 | + let mut b = b.to_vec(); |
| 352 | + sub2(&mut b, a); |
| 353 | + (Minus, biguint_from_vec(b)) |
| 354 | + } |
| 355 | + Ordering::Equal => (NoSign, Zero::zero()), |
| 356 | + } |
| 357 | +} |
| 358 | + |
338 | 359 | forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul);
|
339 | 360 | forward_val_assign!(impl MulAssign for BigUint, mul_assign);
|
340 | 361 |
|
@@ -465,3 +486,22 @@ impl CheckedMul for BigUint {
|
465 | 486 | }
|
466 | 487 |
|
467 | 488 | impl_product_iter_type!(BigUint);
|
| 489 | + |
| 490 | +#[test] |
| 491 | +fn test_sub_sign() { |
| 492 | + use crate::BigInt; |
| 493 | + use num_traits::Num; |
| 494 | + |
| 495 | + fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt { |
| 496 | + let (sign, val) = sub_sign(a, b); |
| 497 | + BigInt::from_biguint(sign, val) |
| 498 | + } |
| 499 | + |
| 500 | + let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap(); |
| 501 | + let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap(); |
| 502 | + let a_i = BigInt::from(a.clone()); |
| 503 | + let b_i = BigInt::from(b.clone()); |
| 504 | + |
| 505 | + assert_eq!(sub_sign_i(&a.data[..], &b.data[..]), &a_i - &b_i); |
| 506 | + assert_eq!(sub_sign_i(&b.data[..], &a.data[..]), &b_i - &a_i); |
| 507 | +} |
0 commit comments