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

@@ -1,14 +1,59 @@
pub trait ModInv: Sized {
fn modinv(&self, phi: &Self) -> Option<Self>;
}
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)]
macro_rules! generate_modinv_tests {
($sname: ident, $tname: ident, $mname: ident) => {
#[test]
fn $mname() {
generate_modinv_tests!(body $sname, $tname, $mname);
}
};
(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) => {
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)
}
});
};
}