Add scalar division to BigInt

This commit is contained in:
Sam Cappleman-Lynes 2017-06-29 16:19:11 +01:00
parent 8b1288ea01
commit 9b0392d235
2 changed files with 93 additions and 0 deletions

View File

@ -508,6 +508,26 @@ impl<'a, 'b> Div<&'b BigInt> for &'a BigInt {
}
}
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigInt, div);
impl Div<BigDigit> for BigInt {
type Output = BigInt;
#[inline]
fn div(self, other: BigDigit) -> BigInt {
BigInt::from_biguint(self.sign, self.data / other)
}
}
impl Div<BigInt> for BigDigit {
type Output = BigInt;
#[inline]
fn div(self, other: BigInt) -> BigInt {
BigInt::from_biguint(other.sign, self / other.data)
}
}
forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem);
impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt {
@ -520,6 +540,26 @@ impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt {
}
}
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigInt, rem);
impl Rem<BigDigit> for BigInt {
type Output = BigInt;
#[inline]
fn rem(self, other: BigDigit) -> BigInt {
BigInt::from_biguint(self.sign, self.data % other)
}
}
impl Rem<BigInt> for BigDigit {
type Output = BigInt;
#[inline]
fn rem(self, other: BigInt) -> BigInt {
BigInt::from_biguint(Plus, self % other.data)
}
}
impl Neg for BigInt {
type Output = BigInt;

View File

@ -832,6 +832,59 @@ fn test_div_rem() {
}
}
#[test]
fn test_scalar_div_rem() {
fn check_sub(a: &BigInt, b: BigDigit, ans_q: &BigInt, ans_r: &BigInt) {
let (q, r) = (a / b, a % b);
if !r.is_zero() {
assert_eq!(r.sign, a.sign);
}
assert!(r.abs() <= From::from(b));
assert!(*a == b * &q + &r);
assert!(q == *ans_q);
assert!(r == *ans_r);
let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone());
assert_op!(a / b == ans_q);
assert_op!(a % b == ans_r);
}
fn check(a: &BigInt, b: BigDigit, q: &BigInt, r: &BigInt) {
check_sub(a, b, q, r);
check_sub(&a.neg(), b, &q.neg(), &r.neg());
}
for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let b = BigInt::from_slice(Plus, b_vec);
let c = BigInt::from_slice(Plus, c_vec);
if a_vec.len() == 1 && a_vec[0] != 0 {
let a = a_vec[0];
check(&c, a, &b, &Zero::zero());
}
if b_vec.len() == 1 && b_vec[0] != 0 {
let b = b_vec[0];
check(&c, b, &a, &Zero::zero());
}
}
for elm in DIV_REM_QUADRUPLES.iter() {
let (a_vec, b_vec, c_vec, d_vec) = *elm;
let a = BigInt::from_slice(Plus, a_vec);
let c = BigInt::from_slice(Plus, c_vec);
let d = BigInt::from_slice(Plus, d_vec);
if b_vec.len() == 1 && b_vec[0] != 0 {
let b = b_vec[0];
check(&a, b, &c, &d);
}
}
}
#[test]
fn test_checked_add() {
for elm in SUM_TRIPLES.iter() {