Modular inverse computation.

This commit is contained in:
2018-10-26 21:28:48 -07:00
parent 89e2dfc6ef
commit 45f7df00d8
17 changed files with 36115 additions and 36063 deletions

View File

@@ -229,7 +229,7 @@ generateInvocs = do
SignedShift -> hPutStrLn hndl ("shift_impls!(I" ++ show size ++ ", U" ++ show size ++ ");") SignedShift -> hPutStrLn hndl ("shift_impls!(I" ++ show size ++ ", U" ++ show size ++ ");")
SignedSub -> hPutStrLn hndl ("subtraction_impls!(I" ++ show size ++ ", I" ++ show (size + 64) ++ ", U" ++ show (size + 64) ++ ");") SignedSub -> hPutStrLn hndl ("subtraction_impls!(I" ++ show size ++ ", I" ++ show (size + 64) ++ ", U" ++ show (size + 64) ++ ");")
EGCD -> hPutStrLn hndl ("egcd_impls!(I" ++ show (size + 64) ++ ", U" ++ show size ++ ", I" ++ show size ++ ");") EGCD -> hPutStrLn hndl ("egcd_impls!(I" ++ show (size + 64) ++ ", U" ++ show size ++ ", I" ++ show size ++ ");")
ModInv -> hPutStrLn hndl ("modinv_impls!(I" ++ show size ++ ");") ModInv -> hPutStrLn hndl ("modinv_impls!(U" ++ show size ++ ", I" ++ show (size + 64) ++ ", U" ++ show (size + 64) ++ ");")
SigConvert v -> hPutStrLn hndl ("conversion_impls!(I" ++ show size ++ ", U" ++ show size ++ ", I" ++ show v ++ ", U" ++ show v ++ ");") SigConvert v -> hPutStrLn hndl ("conversion_impls!(I" ++ show size ++ ", U" ++ show size ++ ", I" ++ show v ++ ", U" ++ show v ++ ");")
_ -> return () _ -> return ()
hPutStrLn hndl "" hPutStrLn hndl ""
@@ -243,7 +243,7 @@ generateInvocs = do
generateSigTestBlock hndl "sigshiftl" SignedShift True 16384 [] [] generateSigTestBlock hndl "sigshiftl" SignedShift True 16384 [] []
generateSigTestBlock hndl "sigshiftr" SignedShift True 16384 [] [] generateSigTestBlock hndl "sigshiftr" SignedShift True 16384 [] []
generateSigTestBlock hndl "egcd" EGCD True 1024 [(+ 64)] [(+ 64)] generateSigTestBlock hndl "egcd" EGCD True 1024 [(+ 64)] [(+ 64)]
generateSigTestBlock hndl "modinv" ModInv True 9000 [] [] generateSigTestBlock hndl "modinv" ModInv True 2048 [] []
hPutStrLn hndl "}" hPutStrLn hndl "}"
log :: String -> IO () log :: String -> IO ()
@@ -517,13 +517,15 @@ generateAllTheTests =
("v", showX v)] ("v", showX v)]
in assert (v == gcd x y) (res, v, memory2) in assert (v == gcd x y) (res, v, memory2)
let (dbM, genM) = emptyDatabase genL let (dbM, genM) = emptyDatabase genL
generateTests "I" ModInv "modinv" dbM $ \ size memory0 -> generateTests "I" ModInv "modinv" dbM $ \ size memoryIn ->
let (a, memory1) = genSign (generateNum memory0 "a" size) let attempt memory0 =
(b, memory2) = genSign (generateNum memory1 "b" size) let (a, memory1) = generateNum memory0 "a" size
c = recipModInteger a b (b, memory2) = generateNum memory1 "b" size
res = Map.fromList [("a", showX a), ("b", showX b), c = recipModInteger a b
("c", showX c)] res = Map.fromList [("a", showX a), ("b", showX b),
in (res, c, memory2) ("c", showX c)]
in if c == 0 then attempt memory2 else (res, c, memory2)
in attempt memoryIn
data AlgState = AlgState { data AlgState = AlgState {
u :: Integer, u :: Integer,

View File

@@ -18,6 +18,10 @@ macro_rules! signed_impls {
pub fn abs(&self) -> $sname { pub fn abs(&self) -> $sname {
$sname{ negative: false, value: self.value.clone() } $sname{ negative: false, value: self.value.clone() }
} }
pub fn is_negative(&self) -> bool {
self.negative
}
} }
impl From<$sname> for $name { impl From<$sname> for $name {

View File

@@ -1,7 +1,7 @@
signed_impls!(I192, U192); signed_impls!(I192, U192);
conversion_impls!(I192, U192, I256, U256); conversion_impls!(I192, U192, I256, U256);
egcd_impls!(I256, U192, I192); egcd_impls!(I256, U192, I192);
modinv_impls!(I192); modinv_impls!(U192, I256, U256);
add_impls!(I256, I320, U320); add_impls!(I256, I320, U320);
signed_impls!(I256, U256); signed_impls!(I256, U256);
cmp_impls!(I256); cmp_impls!(I256);
@@ -9,7 +9,7 @@ shift_impls!(I256, U256);
subtraction_impls!(I256, I320, U320); subtraction_impls!(I256, I320, U320);
conversion_impls!(I256, U256, I320, U320); conversion_impls!(I256, U256, I320, U320);
egcd_impls!(I320, U256, I256); egcd_impls!(I320, U256, I256);
modinv_impls!(I256); modinv_impls!(U256, I320, U320);
add_impls!(I320, I384, U384); add_impls!(I320, I384, U384);
signed_impls!(I320, U320); signed_impls!(I320, U320);
cmp_impls!(I320); cmp_impls!(I320);
@@ -19,7 +19,7 @@ conversion_impls!(I320, U320, I384, U384);
signed_impls!(I384, U384); signed_impls!(I384, U384);
conversion_impls!(I384, U384, I448, U448); conversion_impls!(I384, U384, I448, U448);
egcd_impls!(I448, U384, I384); egcd_impls!(I448, U384, I384);
modinv_impls!(I384); modinv_impls!(U384, I448, U448);
add_impls!(I448, I512, U512); add_impls!(I448, I512, U512);
signed_impls!(I448, U448); signed_impls!(I448, U448);
cmp_impls!(I448); cmp_impls!(I448);
@@ -29,7 +29,7 @@ conversion_impls!(I448, U448, I512, U512);
signed_impls!(I512, U512); signed_impls!(I512, U512);
conversion_impls!(I512, U512, I576, U576); conversion_impls!(I512, U512, I576, U576);
egcd_impls!(I576, U512, I512); egcd_impls!(I576, U512, I512);
modinv_impls!(I512); modinv_impls!(U512, I576, U576);
add_impls!(I576, I640, U640); add_impls!(I576, I640, U640);
signed_impls!(I576, U576); signed_impls!(I576, U576);
cmp_impls!(I576); cmp_impls!(I576);
@@ -37,7 +37,7 @@ shift_impls!(I576, U576);
subtraction_impls!(I576, I640, U640); subtraction_impls!(I576, I640, U640);
conversion_impls!(I576, U576, I640, U640); conversion_impls!(I576, U576, I640, U640);
egcd_impls!(I640, U576, I576); egcd_impls!(I640, U576, I576);
modinv_impls!(I576); modinv_impls!(U576, I640, U640);
add_impls!(I640, I704, U704); add_impls!(I640, I704, U704);
signed_impls!(I640, U640); signed_impls!(I640, U640);
cmp_impls!(I640); cmp_impls!(I640);
@@ -48,7 +48,7 @@ signed_impls!(I704, U704);
signed_impls!(I1024, U1024); signed_impls!(I1024, U1024);
conversion_impls!(I1024, U1024, I1088, U1088); conversion_impls!(I1024, U1024, I1088, U1088);
egcd_impls!(I1088, U1024, I1024); egcd_impls!(I1088, U1024, I1024);
modinv_impls!(I1024); modinv_impls!(U1024, I1088, U1088);
add_impls!(I1088, I1152, U1152); add_impls!(I1088, I1152, U1152);
signed_impls!(I1088, U1088); signed_impls!(I1088, U1088);
cmp_impls!(I1088); cmp_impls!(I1088);
@@ -59,7 +59,7 @@ signed_impls!(I1152, U1152);
signed_impls!(I2048, U2048); signed_impls!(I2048, U2048);
conversion_impls!(I2048, U2048, I2112, U2112); conversion_impls!(I2048, U2048, I2112, U2112);
egcd_impls!(I2112, U2048, I2048); egcd_impls!(I2112, U2048, I2048);
modinv_impls!(I2048); modinv_impls!(U2048, I2112, U2112);
add_impls!(I2112, I2176, U2176); add_impls!(I2112, I2176, U2176);
signed_impls!(I2112, U2112); signed_impls!(I2112, U2112);
cmp_impls!(I2112); cmp_impls!(I2112);
@@ -70,7 +70,7 @@ signed_impls!(I2176, U2176);
signed_impls!(I3072, U3072); signed_impls!(I3072, U3072);
conversion_impls!(I3072, U3072, I3136, U3136); conversion_impls!(I3072, U3072, I3136, U3136);
egcd_impls!(I3136, U3072, I3072); egcd_impls!(I3136, U3072, I3072);
modinv_impls!(I3072); modinv_impls!(U3072, I3136, U3136);
add_impls!(I3136, I3200, U3200); add_impls!(I3136, I3200, U3200);
signed_impls!(I3136, U3136); signed_impls!(I3136, U3136);
cmp_impls!(I3136); cmp_impls!(I3136);
@@ -81,7 +81,7 @@ signed_impls!(I3200, U3200);
signed_impls!(I4096, U4096); signed_impls!(I4096, U4096);
conversion_impls!(I4096, U4096, I4160, U4160); conversion_impls!(I4096, U4096, I4160, U4160);
egcd_impls!(I4160, U4096, I4096); egcd_impls!(I4160, U4096, I4096);
modinv_impls!(I4096); modinv_impls!(U4096, I4160, U4160);
add_impls!(I4160, I4224, U4224); add_impls!(I4160, I4224, U4224);
signed_impls!(I4160, U4160); signed_impls!(I4160, U4160);
cmp_impls!(I4160); cmp_impls!(I4160);
@@ -92,7 +92,7 @@ signed_impls!(I4224, U4224);
signed_impls!(I7680, U7680); signed_impls!(I7680, U7680);
conversion_impls!(I7680, U7680, I7744, U7744); conversion_impls!(I7680, U7680, I7744, U7744);
egcd_impls!(I7744, U7680, I7680); egcd_impls!(I7744, U7680, I7680);
modinv_impls!(I7680); modinv_impls!(U7680, I7744, U7744);
add_impls!(I7744, I7808, U7808); add_impls!(I7744, I7808, U7808);
signed_impls!(I7744, U7744); signed_impls!(I7744, U7744);
cmp_impls!(I7744); cmp_impls!(I7744);
@@ -103,7 +103,7 @@ signed_impls!(I7808, U7808);
signed_impls!(I8192, U8192); signed_impls!(I8192, U8192);
conversion_impls!(I8192, U8192, I8256, U8256); conversion_impls!(I8192, U8192, I8256, U8256);
egcd_impls!(I8256, U8192, I8192); egcd_impls!(I8256, U8192, I8192);
modinv_impls!(I8192); modinv_impls!(U8192, I8256, U8256);
add_impls!(I8256, I8320, U8320); add_impls!(I8256, I8320, U8320);
signed_impls!(I8256, U8256); signed_impls!(I8256, U8256);
cmp_impls!(I8256); cmp_impls!(I8256);
@@ -114,7 +114,7 @@ signed_impls!(I8320, U8320);
signed_impls!(I15360, U15360); signed_impls!(I15360, U15360);
conversion_impls!(I15360, U15360, I15424, U15424); conversion_impls!(I15360, U15360, I15424, U15424);
egcd_impls!(I15424, U15360, I15360); egcd_impls!(I15424, U15360, I15360);
modinv_impls!(I15360); modinv_impls!(U15360, I15424, U15424);
add_impls!(I15424, I15488, U15488); add_impls!(I15424, I15488, U15488);
signed_impls!(I15424, U15424); signed_impls!(I15424, U15424);
cmp_impls!(I15424); cmp_impls!(I15424);
@@ -305,11 +305,11 @@ mod tests {
generate_modinv_tests!(I512, U512, i512); generate_modinv_tests!(I512, U512, i512);
generate_modinv_tests!(I576, U576, i576); generate_modinv_tests!(I576, U576, i576);
generate_modinv_tests!(I1024, U1024, i1024); generate_modinv_tests!(I1024, U1024, i1024);
generate_modinv_tests!(I2048, U2048, i2048); generate_modinv_tests!(ignore I2048, U2048, i2048);
generate_modinv_tests!(I3072, U3072, i3072); generate_modinv_tests!(ignore I3072, U3072, i3072);
generate_modinv_tests!(I4096, U4096, i4096); generate_modinv_tests!(ignore I4096, U4096, i4096);
generate_modinv_tests!(I7680, U7680, i7680); generate_modinv_tests!(ignore I7680, U7680, i7680);
generate_modinv_tests!(I8192, U8192, i8192); generate_modinv_tests!(ignore I8192, U8192, i8192);
generate_modinv_tests!(ignore I15360, U15360, i15360); generate_modinv_tests!(ignore I15360, U15360, i15360);
} }
} }

View File

@@ -23,5 +23,6 @@ use std::ops::{Sub,SubAssign};
use unsigned::*; use unsigned::*;
pub use self::egcd::EGCD; pub use self::egcd::EGCD;
pub use self::modinv::ModInv;
include!("invoc.rs"); include!("invoc.rs");

View File

@@ -1,14 +1,59 @@
pub trait ModInv: Sized {
fn modinv(&self, phi: &Self) -> Option<Self>;
}
macro_rules! modinv_impls { macro_rules! modinv_impls {
($sname: ident) => { ($name: ident, $sname: ident, $uname: ident) => {
impl ModInv for $name {
fn modinv(&self, phi: &$name) -> Option<$name>
{
let (_, mut b, g) = phi.egcd(&self);
if g != $sname::from(1i64) {
return None;
}
while b.is_negative() {
b += $sname::from($uname::from(phi));
}
Some($name::from($uname::from(b)))
}
}
}; };
} }
#[cfg(test)] #[cfg(test)]
macro_rules! generate_modinv_tests { macro_rules! generate_modinv_tests {
($sname: ident, $tname: ident, $mname: ident) => { ($sname: ident, $tname: ident, $mname: ident) => {
#[test]
fn $mname() {
generate_modinv_tests!(body $sname, $tname, $mname);
}
}; };
(ignore $sname: ident, $tname: ident, $mname: ident) => { (ignore $sname: ident, $tname: ident, $mname: ident) => {
#[test]
#[ignore]
fn $mname() {
generate_modinv_tests!(body $sname, $tname, $mname);
}
}; };
(body $sname: ident, $tname: ident, $mname: ident) => { (body $sname: ident, $tname: ident, $mname: ident) => {
let fname = format!("testdata/modinv/{}.tests", stringify!($sname));
run_test(fname.to_string(), 3, |case| {
let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap();
let (negc, cbytes) = case.get("c").unwrap();
assert!(!nega && !negb && !negc);
let a = $tname::from_bytes(abytes);
let b = $tname::from_bytes(bbytes);
let c = $tname::from_bytes(cbytes);
match a.modinv(&b) {
None => assert!(false),
Some(myc) => assert_eq!(c, myc)
}
});
}; };
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff