Modular inverse computation.
This commit is contained in:
20
generate.hs
20
generate.hs
@@ -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,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
6006
testdata/modinv/I1024.tests
vendored
6006
testdata/modinv/I1024.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I15360.tests
vendored
6006
testdata/modinv/I15360.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I192.tests
vendored
6006
testdata/modinv/I192.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I2048.tests
vendored
6006
testdata/modinv/I2048.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I256.tests
vendored
6006
testdata/modinv/I256.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I3072.tests
vendored
6006
testdata/modinv/I3072.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I384.tests
vendored
6006
testdata/modinv/I384.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I4096.tests
vendored
6006
testdata/modinv/I4096.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I512.tests
vendored
6006
testdata/modinv/I512.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I576.tests
vendored
6006
testdata/modinv/I576.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I7680.tests
vendored
6006
testdata/modinv/I7680.tests
vendored
File diff suppressed because it is too large
Load Diff
6006
testdata/modinv/I8192.tests
vendored
6006
testdata/modinv/I8192.tests
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user