From 605773edf18e82d46c2b246e9a28698f3f2af482 Mon Sep 17 00:00:00 2001 From: Nym Seddon Date: Tue, 29 Dec 2020 07:20:45 +0000 Subject: [PATCH 1/2] Add invmod API to Integer trait --- src/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 0281954..02d4520 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -208,6 +208,21 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { (self.extended_gcd(other), self.lcm(other)) } + /// Inverse of the number modulo the modulus + #[inline] + fn invmod(&self, modulus: &Self) -> Self + where + Self: Clone, + { + let egcd = self.extended_gcd(modulus); + assert!(egcd.gcd.is_one(), "no inverse, GCD(x, modulus) != 1"); + if egcd.x < Self::zero() { + egcd.x + modulus.clone() + } else { + egcd.x + } + } + /// Deprecated, use `is_multiple_of` instead. fn divides(&self, other: &Self) -> bool; From d702d00144c2ab639b3c477e39b483081f03251a Mon Sep 17 00:00:00 2001 From: Nym Seddon Date: Mon, 18 Jan 2021 19:58:33 +0000 Subject: [PATCH 2/2] fixup! Add invmod API to Integer trait --- src/lib.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 02d4520..5b51db9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -209,17 +209,29 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { } /// Inverse of the number modulo the modulus + /// + /// # Examples + /// + /// ~~~ + /// # extern crate num_integer; + /// # fn main() { + /// # use num_integer::Integer; + /// assert_eq!((10isize).invmod(&11isize).unwrap(), 10isize); + /// assert_eq!((173isize).invmod(&1729isize).unwrap(), 10isize); + /// # } + /// ~~~ #[inline] - fn invmod(&self, modulus: &Self) -> Self + fn invmod(&self, modulus: &Self) -> Option where Self: Clone, { - let egcd = self.extended_gcd(modulus); - assert!(egcd.gcd.is_one(), "no inverse, GCD(x, modulus) != 1"); - if egcd.x < Self::zero() { - egcd.x + modulus.clone() + let ExtendedGcd { gcd, x, .. } = self.extended_gcd(modulus); + if !gcd.is_one() { + None + } else if x < Self::zero() { + Some(x + modulus.clone()) } else { - egcd.x + Some(x) } } @@ -1356,3 +1368,11 @@ fn test_multinomial() { check_multinomial!(u64, &[0], 1); check_multinomial!(u64, &[12345], 1); } + +#[test] +fn test_invmod() { + assert_eq!((10isize).invmod(&11isize).unwrap(), 10isize); + assert_eq!((173isize).invmod(&1729isize).unwrap(), 10isize); + + assert!((10isize).invmod(&12isize).is_none()); +}