First whack at modular inverses.
This commit is contained in:
@@ -7,3 +7,54 @@ mod unsigned;
|
|||||||
|
|
||||||
pub use self::signed::SCN;
|
pub use self::signed::SCN;
|
||||||
pub use self::unsigned::UCN;
|
pub use self::unsigned::UCN;
|
||||||
|
|
||||||
|
use std::ops::Neg;
|
||||||
|
|
||||||
|
pub fn modinv(e: &UCN, phi: &UCN) -> UCN {
|
||||||
|
let (_, mut x, _) = extended_euclidean(&e, &phi);
|
||||||
|
let int_phi = SCN::from(phi.clone());
|
||||||
|
while x.is_negative() {
|
||||||
|
x = x + &int_phi;
|
||||||
|
}
|
||||||
|
x.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_euclidean(a: &UCN, b: &UCN) -> (SCN, SCN, SCN) {
|
||||||
|
let posinta = SCN::from(a.clone());
|
||||||
|
let posintb = SCN::from(b.clone());
|
||||||
|
let (d, x, y) = egcd(posinta, posintb);
|
||||||
|
|
||||||
|
if d.is_negative() {
|
||||||
|
(d.neg(), x.neg(), y.neg())
|
||||||
|
} else {
|
||||||
|
(d, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn egcd(a: SCN, b: SCN) -> (SCN, SCN, SCN) {
|
||||||
|
let mut s = SCN::zero();
|
||||||
|
let mut old_s = SCN::from(1 as u8);
|
||||||
|
let mut t = SCN::from(1 as u8);
|
||||||
|
let mut old_t = SCN::zero();
|
||||||
|
let mut r = b;
|
||||||
|
let mut old_r = a;
|
||||||
|
|
||||||
|
while !r.is_zero() {
|
||||||
|
let quotient = old_r.clone() / r.clone();
|
||||||
|
|
||||||
|
let prov_r = r.clone();
|
||||||
|
let prov_s = s.clone();
|
||||||
|
let prov_t = t.clone();
|
||||||
|
|
||||||
|
r = old_r - (r * "ient);
|
||||||
|
s = old_s - (s * "ient);
|
||||||
|
t = old_t - (t * "ient);
|
||||||
|
|
||||||
|
old_r = prov_r;
|
||||||
|
old_s = prov_s;
|
||||||
|
old_t = prov_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
(old_r, old_s, old_t)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ impl SCN {
|
|||||||
self.value.is_zero()
|
self.value.is_zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_negative(&self) -> bool {
|
||||||
|
self.negative
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_str(x: &str) -> SCN {
|
pub fn from_str(x: &str) -> SCN {
|
||||||
if x.get(0..1) == Some("-") {
|
if x.get(0..1) == Some("-") {
|
||||||
SCN{ negative: true, value: UCN::from_str(&x[1..]) }
|
SCN{ negative: true, value: UCN::from_str(&x[1..]) }
|
||||||
@@ -59,6 +63,18 @@ define_signed_into!(SCN, i16, u16);
|
|||||||
define_signed_into!(SCN, i32, u32);
|
define_signed_into!(SCN, i32, u32);
|
||||||
define_signed_into!(SCN, i64, u64);
|
define_signed_into!(SCN, i64, u64);
|
||||||
|
|
||||||
|
impl From<UCN> for SCN {
|
||||||
|
fn from(x: UCN) -> SCN {
|
||||||
|
SCN{ negative: false, value: x }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<UCN> for SCN {
|
||||||
|
fn into(self) -> UCN {
|
||||||
|
self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Comparisons
|
// Comparisons
|
||||||
|
|||||||
Reference in New Issue
Block a user