All variants of dividing BigUint by BigDigit

Allow the division to occur with either operand order and with any
combination of owned and borrowed arguments.
This commit is contained in:
Sam Cappleman-Lynes 2017-06-29 13:38:00 +01:00
parent 51408a9b3b
commit d0bfb54eee
2 changed files with 83 additions and 34 deletions

View File

@ -503,6 +503,8 @@ impl<'a, 'b> Div<&'b BigUint> for &'a BigUint {
} }
} }
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigUint, div);
impl Div<BigDigit> for BigUint { impl Div<BigDigit> for BigUint {
type Output = BigUint; type Output = BigUint;
@ -513,6 +515,20 @@ impl Div<BigDigit> for BigUint {
} }
} }
impl Div<BigUint> for BigDigit {
type Output = BigUint;
#[inline]
fn div(self, mut other: BigUint) -> BigUint {
other = other.normalize();
match other.data.len() {
0 => panic!(),
1 => From::from(self / other.data[0]),
_ => Zero::zero()
}
}
}
forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem); forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem);
impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint { impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint {
@ -525,13 +541,29 @@ impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint {
} }
} }
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigUint, rem);
impl Rem<BigDigit> for BigUint { impl Rem<BigDigit> for BigUint {
type Output = BigDigit; type Output = BigUint;
#[inline] #[inline]
fn rem(self, other: BigDigit) -> BigDigit { fn rem(self, other: BigDigit) -> BigUint {
let (_, r) = div_rem_digit(self, other); let (_, r) = div_rem_digit(self, other);
r From::from(r)
}
}
impl Rem<BigUint> for BigDigit {
type Output = BigUint;
#[inline]
fn rem(self, mut other: BigUint) -> BigUint {
other = other.normalize();
match other.data.len() {
0 => panic!(),
1 => From::from(self % other.data[0]),
_ => other
}
} }
} }

View File

@ -692,22 +692,22 @@ fn test_add() {
#[test] #[test]
fn test_scalar_add() { fn test_scalar_add() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm; let (a_vec, b_vec, c_vec) = *elm;
let c = BigUint::from_slice(c_vec); let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
if a_vec.len() == 1 { if a_vec.len() == 1 {
let a = a_vec[0]; let a = a_vec[0];
let b = BigUint::from_slice(b_vec); assert_op!(a + b == c);
assert_op!(a + b == c); assert_op!(b + a == c);
assert_op!(b + a == c); }
}
if b_vec.len() == 1 { if b_vec.len() == 1 {
let a = BigUint::from_slice(a_vec); let b = b_vec[0];
let b = b_vec[0]; assert_op!(a + b == c);
assert_op!(a + b == c); assert_op!(b + a == c);
assert_op!(b + a == c);
} }
} }
} }
@ -729,24 +729,21 @@ fn test_sub() {
fn test_scalar_sub() { fn test_scalar_sub() {
for elm in SUM_TRIPLES.iter() { for elm in SUM_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm; let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
if a_vec.len() == 1 { if a_vec.len() == 1 {
let a = a_vec[0]; let a = a_vec[0];
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec);
assert_op!(c - a == b); assert_op!(c - a == b);
} }
if b_vec.len() == 1 { if b_vec.len() == 1 {
let a = BigUint::from_slice(a_vec);
let b = b_vec[0]; let b = b_vec[0];
let c = BigUint::from_slice(c_vec);
assert_op!(c - b == a); assert_op!(c - b == a);
} }
if c_vec.len() == 1 { if c_vec.len() == 1 {
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = c_vec[0]; let c = c_vec[0];
assert_op!(c - a == b); assert_op!(c - a == b);
assert_op!(c - b == a); assert_op!(c - b == a);
@ -792,6 +789,7 @@ const DIV_REM_QUADRUPLES: &'static [(&'static [BigDigit],
&'static [BigDigit], &'static [BigDigit],
&'static [BigDigit], &'static [BigDigit],
&'static [BigDigit])] = &[(&[1], &[2], &[], &[1]), &'static [BigDigit])] = &[(&[1], &[2], &[], &[1]),
(&[3], &[2], &[1], &[1]),
(&[1, 1], &[2], &[M / 2 + 1], &[1]), (&[1, 1], &[2], &[M / 2 + 1], &[1]),
(&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]), (&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]),
(&[0, 1], &[N1], &[1], &[1]), (&[0, 1], &[N1], &[1], &[1]),
@ -825,17 +823,17 @@ fn test_mul() {
fn test_scalar_mul() { fn test_scalar_mul() {
for elm in MUL_TRIPLES.iter() { for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm; let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec); let c = BigUint::from_slice(c_vec);
if a_vec.len() == 1 { if a_vec.len() == 1 {
let b = BigUint::from_slice(b_vec);
let a = a_vec[0]; let a = a_vec[0];
assert_op!(a * b == c); assert_op!(a * b == c);
assert_op!(b * a == c); assert_op!(b * a == c);
} }
if b_vec.len() == 1 { if b_vec.len() == 1 {
let a = BigUint::from_slice(a_vec);
let b = b_vec[0]; let b = b_vec[0];
assert_op!(a * b == c); assert_op!(a * b == c);
assert_op!(b * a == c); assert_op!(b * a == c);
@ -882,33 +880,52 @@ fn test_div_rem() {
fn test_scalar_div_rem() { fn test_scalar_div_rem() {
for elm in MUL_TRIPLES.iter() { for elm in MUL_TRIPLES.iter() {
let (a_vec, b_vec, c_vec) = *elm; let (a_vec, b_vec, c_vec) = *elm;
let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec); let c = BigUint::from_slice(c_vec);
if a_vec.len() == 1 && a_vec[0] != 0 { if a_vec.len() == 1 && a_vec[0] != 0 {
let a = a_vec[0]; let a = a_vec[0];
let b = BigUint::from_slice(b_vec); assert_op!(c / a == b);
assert!(c.clone() / a == b); assert_op!(c % a == Zero::zero());
assert!(c.clone() % a == Zero::zero());
} }
if b_vec.len() == 1 && b_vec[0] != 0 { if b_vec.len() == 1 && b_vec[0] != 0 {
let a = BigUint::from_slice(a_vec);
let b = b_vec[0]; let b = b_vec[0];
assert!(c.clone() / b == a); assert_op!(c / b == a);
assert!(c.clone() % b == Zero::zero()); assert_op!(c % b == Zero::zero());
}
if c_vec.len() == 1 {
let c = c_vec[0];
if !a.is_zero() {
assert_op!(c / a == b);
assert_op!(c % a == Zero::zero());
}
if !b.is_zero() {
assert_op!(c / b == a);
assert_op!(c % b == Zero::zero());
}
} }
} }
for elm in DIV_REM_QUADRUPLES.iter() { for elm in DIV_REM_QUADRUPLES.iter() {
let (a_vec, b_vec, c_vec, d_vec) = *elm; let (a_vec, b_vec, c_vec, d_vec) = *elm;
let a = BigUint::from_slice(a_vec); let a = BigUint::from_slice(a_vec);
let b = BigUint::from_slice(b_vec);
let c = BigUint::from_slice(c_vec); let c = BigUint::from_slice(c_vec);
let d = BigUint::from_slice(d_vec);
if b_vec.len() == 1 && b_vec[0] != 0 { if b_vec.len() == 1 && b_vec[0] != 0 {
let b = b_vec[0]; let b = b_vec[0];
let d = d_vec[0]; assert_op!(a / b == c);
assert!(a.clone() / b == c); assert_op!(a % b == d);
assert!(a.clone() % b == d); }
if a_vec.len() == 1 && !b.is_zero() {
let a = a_vec[0];
assert_op!(a / b == c);
assert_op!(a % b == d);
} }
} }
} }