Support modular inverses.
This commit is contained in:
@@ -220,3 +220,16 @@ fn barrett_reduction_test()
|
||||
assert_eq!(&result, r);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modular_inverse_test()
|
||||
{
|
||||
run_test("tests/math/modinv.tests", 3, |scase| {
|
||||
let case = make_unsigned(scase);
|
||||
let a = case.get("x").unwrap();
|
||||
let m = case.get("y").unwrap();
|
||||
let r = case.get("z").unwrap();
|
||||
let result = a.modinv(m);
|
||||
assert_eq!(r, &result);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -130,23 +130,18 @@ impl UCN {
|
||||
}
|
||||
|
||||
pub fn modinv(&self, phi: &UCN) -> UCN {
|
||||
let (_, mut x, _) = self.extended_euclidean(&phi);
|
||||
let int_phi = SCN::from(phi.clone());
|
||||
while x.is_negative() {
|
||||
x = x + &int_phi;
|
||||
}
|
||||
x.into()
|
||||
}
|
||||
let x = SCN::from(self.clone());
|
||||
let y = SCN::from(phi.clone());
|
||||
let (d, a, _b) = x.egcd(y);
|
||||
|
||||
fn extended_euclidean(&self, b: &UCN) -> (SCN, SCN, SCN) {
|
||||
let posinta = SCN::from(self.clone());
|
||||
let posintb = SCN::from(b.clone());
|
||||
let (d, x, y) = posinta.egcd(posintb);
|
||||
|
||||
if d.is_negative() {
|
||||
(d.neg(), x.neg(), y.neg())
|
||||
if d == SCN::from(1 as u8) {
|
||||
if a.is_negative() {
|
||||
(a + SCN::from(phi.clone())).value
|
||||
} else {
|
||||
(d, x, y)
|
||||
a.value
|
||||
}
|
||||
} else {
|
||||
UCN::zero()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1294,5 +1289,9 @@ mod test {
|
||||
let fast = a.fastmodexp(&b, &cu);
|
||||
slow == fast
|
||||
}
|
||||
fn modinv(a: UCN, b: UCN) -> bool {
|
||||
let i = a.modinv(&b);
|
||||
i.is_zero() || ( ((a * i) % b) == UCN::from(1 as u64) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ main =
|
||||
in if m == 0
|
||||
then (Nothing, (), g''')
|
||||
else (Just res, (), g''')
|
||||
_ <- runGenerator g9 "barrett" () $ \ g () ->
|
||||
g10<- runGenerator g9 "barrett" () $ \ g () ->
|
||||
let (m, g') = randomVal (>= 0) g
|
||||
(v, g'') = randomVal (>= 0) g'
|
||||
barrett = barrett_u m
|
||||
@@ -151,7 +151,7 @@ main =
|
||||
in if me /= standard
|
||||
then error "Barrett broken"
|
||||
else (Just res, (), g'')
|
||||
_ <- runGenerator g9 "fastmodexp" () $ \ g () ->
|
||||
g11<- runGenerator g10 "fastmodexp" () $ \ g () ->
|
||||
let (a, g') = randomVal (>= 0) g
|
||||
(b, g'') = randomVal (>= 0) g'
|
||||
(m, g''') = randomVal (>= 0) g'
|
||||
@@ -164,6 +164,10 @@ main =
|
||||
("m", m), ("u", bu barrett),
|
||||
("k", fromIntegral (bk barrett))]
|
||||
in (Just res, (), g''')
|
||||
_ <- runGenerator g11 "modinv" Map.empty $
|
||||
buildBasicLimitingGenerator (>= 0) $ \ a b ->
|
||||
let res == recipModInteger a b
|
||||
if b == 0 then Nothing else Just (recipModInteger a b)
|
||||
return ()
|
||||
|
||||
-- Implement Barrett reduction using incredibly simplistic implementations, to
|
||||
|
||||
15000
tests/math/modinv.tests
Normal file
15000
tests/math/modinv.tests
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user