Add support for modular division with negative divisors.

This commit is contained in:
2018-12-30 17:14:52 -08:00
parent 130a87ef43
commit c55a1956d4
2 changed files with 3 additions and 9 deletions

View File

@@ -11,10 +11,9 @@ macro_rules! moddiv_impls {
impl ModDiv for $sname { impl ModDiv for $sname {
fn moddiv(&self, divisor: &Self, phi: &Self) -> Self fn moddiv(&self, divisor: &Self, phi: &Self) -> Self
{ {
assert!(!divisor.is_negative());
let safe_divisor = divisor % phi; let safe_divisor = divisor % phi;
let unsigned_i = safe_divisor.value.modinv(&phi.value).expect("no modular inverse of moddiv divisor"); let unsigned_i = safe_divisor.value.modinv(&phi.value).expect("no modular inverse of moddiv divisor");
let i = $sname::new(false, unsigned_i); let i = $sname::new(divisor.negative, unsigned_i);
let selfi = i * self; let selfi = i * self;
$sname::from( selfi % $dbl::from(phi) ) $sname::from( selfi % $dbl::from(phi) )
} }
@@ -50,12 +49,6 @@ macro_rules! generate_moddiv_tests {
let m = $sname::new(*negm, $tname::from_bytes(mbytes)); let m = $sname::new(*negm, $tname::from_bytes(mbytes));
let c = $sname::new(*negc, $tname::from_bytes(cbytes)); let c = $sname::new(*negc, $tname::from_bytes(cbytes));
let res = a.moddiv(&b, &m); let res = a.moddiv(&b, &m);
println!("-------------");
println!("a: {:x}", a);
println!("b: {:x}", b);
println!("m: {:x}", m);
println!("c: {:x}", c);
println!("r: {:x}", res);
assert_eq!(c, res); assert_eq!(c, res);
}); });
}; };

View File

@@ -38,6 +38,7 @@ testDatabase = [
(SignedCmp, "sigcmp", "signed compare", sigcmpTest), (SignedCmp, "sigcmp", "signed compare", sigcmpTest),
(SignedMul, "sigmul", "signed multiply", sigmulTest), (SignedMul, "sigmul", "signed multiply", sigmulTest),
(SignedDiv, "sigdiv", "signed division", sigdivTest), (SignedDiv, "sigdiv", "signed division", sigdivTest),
(SignedModInv,"smodinv", "signed modular inversion",smodinvTest),
(SignedShift, "sigshiftr", "signed shift right", sigshiftrTest), (SignedShift, "sigshiftr", "signed shift right", sigshiftrTest),
(SignedShift, "sigshiftl", "signed shift left", sigshiftlTest), (SignedShift, "sigshiftl", "signed shift left", sigshiftlTest),
(SignedSub, "sigsub", "signed subtraction", sigsubTest), (SignedSub, "sigsub", "signed subtraction", sigsubTest),
@@ -287,7 +288,7 @@ moddivTest :: Test
moddivTest size memoryIn = moddivTest size memoryIn =
let attempt memory0 = let attempt memory0 =
let (a, memory1) = genSign (generateNum memory0 "a" size) let (a, memory1) = genSign (generateNum memory0 "a" size)
(b, memory2) = generateNum memory1 "b" size (b, memory2) = genSign (generateNum memory1 "b" size)
(m, memory3) = generateNum memory2 "m" size (m, memory3) = generateNum memory2 "m" size
maybe_res = divmod a b m maybe_res = divmod a b m
in case maybe_res of in case maybe_res of