Add support for modular division with negative divisors.
This commit is contained in:
@@ -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);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user