From c0a4c4889feefebf8458dd48fc03ce327d7df170 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Tue, 18 Dec 2018 11:37:42 -0800 Subject: [PATCH 1/9] Define extended GCD, combined GCD+LCM --- src/lib.rs | 174 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 162 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 39e9de5..8dbd5ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,8 @@ extern crate std; extern crate num_traits as traits; -use core::ops::Add; +use core::mem; +use core::ops::{Add, SubAssign}; use traits::{Num, Signed, Zero}; @@ -95,6 +96,69 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// ~~~ fn lcm(&self, other: &Self) -> Self; + /// Greatest Common Divisor (GCD) and + /// Lowest Common Multiple (LCM) together. + /// + /// Potentially more efficient than calling `gcd` and `lcm` + /// individually for identical inputs. + /// + /// # Examples + /// + /// ~~~ + /// # use num_integer::Integer; + /// assert_eq!(10.gcd_lcm(&4), (2, 20)); + /// assert_eq!(8.gcd_lcm(&9), (1, 72)); + /// ~~~ + #[inline] + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + (self.gcd(other), self.lcm(other)) + } + + /// Greatest common divisor and Bézout coefficients. + /// + /// # Examples + /// + /// ~~~ + /// # extern crate num_traits; + /// # use num_integer::{ExtendedGcd, Integer}; + /// # use num_traits::NumAssign; + /// fn check(a: A, b: A) -> bool { + /// let ExtendedGcd { gcd, coeffs: [x, y], .. } = a.extended_gcd(&b); + /// gcd == x * a + y * b + /// } + /// assert!(check(10isize, 4isize)); + /// assert!(check(8isize, 9isize)); + /// ~~~ + #[inline] + fn extended_gcd(&self, other: &Self) -> ExtendedGcd + where Self: Clone + SubAssign { + let mut s = (Self::zero(), Self::one()); + let mut t = (Self::one(), Self::zero()); + let mut r = (other.clone(), self.clone()); + + while !r.0.is_zero() { + let q = r.1.clone() / r.0.clone(); + let f = |r: &mut (Self, Self)| { + mem::swap(&mut r.0, &mut r.1); + r.0 -= q.clone() * r.1.clone(); + }; + f(&mut r); + f(&mut s); + f(&mut t); + } + + if r.1 >= Self::zero() { ExtendedGcd { gcd: r.1, coeffs: [s.1, t.1], _hidden: () } } + else { ExtendedGcd { gcd: Self::zero() - r.1, + coeffs: [Self::zero() - s.1, Self::zero() - t.1], _hidden: () } } + } + + /// Greatest common divisor, least common multiple, and Bézout coefficients. + #[inline] + fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) + where Self: Clone + SubAssign { + (self.extended_gcd(other), self.lcm(other)) + } + /// Deprecated, use `is_multiple_of` instead. fn divides(&self, other: &Self) -> bool; @@ -173,6 +237,14 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { } } +/// Greatest common divisor and Bézout coefficients +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ExtendedGcd { + pub gcd: A, + pub coeffs: [A; 2], + _hidden: (), +} + /// Simultaneous integer division and modulus #[inline] pub fn div_rem(x: T, y: T) -> (T, T) { @@ -206,6 +278,13 @@ pub fn lcm(x: T, y: T) -> T { x.lcm(&y) } +/// Calculates the Greatest Common Divisor (GCD) and +/// Lowest Common Multiple (LCM) of the number and `other`. +#[inline(always)] +pub fn gcd_lcm(x: T, y: T) -> (T, T) { + x.gcd_lcm(&y) +} + macro_rules! impl_integer_for_isize { ($T:ty, $test_mod:ident) => { impl Integer for $T { @@ -294,16 +373,31 @@ macro_rules! impl_integer_for_isize { m << shift } + #[inline] + fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) { + let egcd = self.extended_gcd(other); + // should not have to recalculate abs + let lcm = if egcd.gcd.is_zero() { Self::zero() } + else { (*self * (*other / egcd.gcd)).abs() }; + (egcd, lcm) + } + /// Calculates the Lowest Common Multiple (LCM) of the number and /// `other`. #[inline] fn lcm(&self, other: &Self) -> Self { - if self.is_zero() && other.is_zero() { - Self::zero() - } else { - // should not have to recalculate abs - (*self * (*other / self.gcd(other))).abs() - } + self.gcd_lcm(other).1 + } + + /// Calculates the Greatest Common Divisor (GCD) and + /// Lowest Common Multiple (LCM) of the number and `other`. + #[inline] + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + if self.is_zero() && other.is_zero() { return (Self::zero(), Self::zero()) } + let gcd = self.gcd(other); + // should not have to recalculate abs + let lcm = (*self * (*other / gcd)).abs(); + (gcd, lcm) } /// Deprecated, use `is_multiple_of` instead. @@ -488,6 +582,38 @@ macro_rules! impl_integer_for_isize { assert_eq!((11 as $T).lcm(&5), 55 as $T); } + #[test] + fn test_gcd_lcm() { + use core::iter::once; + let r = once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)); + for i in r.clone() { + for j in r.clone() { + assert_eq!(i.gcd_lcm(&j), (i.gcd(&j), i.lcm(&j))); + } + } + } + + #[test] + fn test_extended_gcd_lcm() { + use ExtendedGcd; + use traits::NumAssign; + + fn check(a: A, b: A) -> bool { + let ExtendedGcd { gcd, coeffs: [x, y], .. } = a.extended_gcd(&b); + gcd == x * a + y * b + } + + use core::iter::once; + let r = once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)); + for i in r.clone() { + for j in r.clone() { + check(i, j); + let (ExtendedGcd { gcd, .. }, lcm) = i.extended_gcd_lcm(&j); + assert_eq!((gcd, lcm), (i.gcd(&j), i.lcm(&j))); + } + } + } + #[test] fn test_even() { assert_eq!((-4 as $T).is_even(), true); @@ -569,14 +695,29 @@ macro_rules! impl_integer_for_usize { m << shift } + #[inline] + fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) { + let egcd = self.extended_gcd(other); + // should not have to recalculate abs + let lcm = if egcd.gcd.is_zero() { Self::zero() } + else { *self * (*other / egcd.gcd) }; + (egcd, lcm) + } + /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn lcm(&self, other: &Self) -> Self { - if self.is_zero() && other.is_zero() { - Self::zero() - } else { - *self * (*other / self.gcd(other)) - } + self.gcd_lcm(other).1 + } + + /// Calculates the Greatest Common Divisor (GCD) and + /// Lowest Common Multiple (LCM) of the number and `other`. + #[inline] + fn gcd_lcm(&self, other: &Self) -> (Self, Self) { + if self.is_zero() && other.is_zero() { return (Self::zero(), Self::zero()) } + let gcd = self.gcd(other); + let lcm = *self * (*other / gcd); + (gcd, lcm) } /// Deprecated, use `is_multiple_of` instead. @@ -672,6 +813,15 @@ macro_rules! impl_integer_for_usize { assert_eq!((15 as $T).lcm(&17), 255 as $T); } + #[test] + fn test_gcd_lcm() { + for i in (0..).take(256) { + for j in (0..).take(256) { + assert_eq!(i.gcd_lcm(&j), (i.gcd(&j), i.lcm(&j))); + } + } + } + #[test] fn test_is_multiple_of() { assert!((6 as $T).is_multiple_of(&(6 as $T))); From c3bf89af8dc750bf2b3a38a786e6fc801d7a0db0 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Tue, 18 Dec 2018 17:24:32 -0800 Subject: [PATCH 2/9] unbreak on older Rust --- build.rs | 4 ++++ src/lib.rs | 34 +++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/build.rs b/build.rs index fd60866..0a42588 100644 --- a/build.rs +++ b/build.rs @@ -8,6 +8,10 @@ fn main() { } else if env::var_os("CARGO_FEATURE_I128").is_some() { panic!("i128 support was not detected!"); } + + if probe("#[derive(Clone)] struct A; fn main() { let _ = [A; 2].clone(); }") { + println!("cargo:rustc-cfg=array_clone"); + } } /// Test if a code snippet can be compiled diff --git a/src/lib.rs b/src/lib.rs index 8dbd5ce..cc37002 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,15 +119,18 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// # Examples /// /// ~~~ + /// # extern crate num_integer; /// # extern crate num_traits; + /// # fn main() { /// # use num_integer::{ExtendedGcd, Integer}; /// # use num_traits::NumAssign; - /// fn check(a: A, b: A) -> bool { - /// let ExtendedGcd { gcd, coeffs: [x, y], .. } = a.extended_gcd(&b); - /// gcd == x * a + y * b + /// fn check(a: A, b: A) -> bool { + /// let ExtendedGcd { gcd, coeffs, .. } = a.extended_gcd(&b); + /// gcd == coeffs[0] * a + coeffs[1] * b /// } /// assert!(check(10isize, 4isize)); /// assert!(check(8isize, 9isize)); + /// # } /// ~~~ #[inline] fn extended_gcd(&self, other: &Self) -> ExtendedGcd @@ -238,13 +241,20 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { } /// Greatest common divisor and Bézout coefficients -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Copy, PartialEq, Eq)] +#[cfg_attr(array_clone, derive(Clone))] pub struct ExtendedGcd { pub gcd: A, pub coeffs: [A; 2], _hidden: (), } +#[cfg(not(array_clone))] +impl Clone for ExtendedGcd { + #[inline] + fn clone(&self) -> Self { *self } +} + /// Simultaneous integer division and modulus #[inline] pub fn div_rem(x: T, y: T) -> (T, T) { @@ -585,9 +595,8 @@ macro_rules! impl_integer_for_isize { #[test] fn test_gcd_lcm() { use core::iter::once; - let r = once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)); - for i in r.clone() { - for j in r.clone() { + for i in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { + for j in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { assert_eq!(i.gcd_lcm(&j), (i.gcd(&j), i.lcm(&j))); } } @@ -598,15 +607,14 @@ macro_rules! impl_integer_for_isize { use ExtendedGcd; use traits::NumAssign; - fn check(a: A, b: A) -> bool { - let ExtendedGcd { gcd, coeffs: [x, y], .. } = a.extended_gcd(&b); - gcd == x * a + y * b + fn check(a: A, b: A) -> bool { + let ExtendedGcd { gcd, coeffs, .. } = a.extended_gcd(&b); + gcd == coeffs[0] * a + coeffs[1] * b } use core::iter::once; - let r = once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)); - for i in r.clone() { - for j in r.clone() { + for i in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { + for j in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { check(i, j); let (ExtendedGcd { gcd, .. }, lcm) = i.extended_gcd_lcm(&j); assert_eq!((gcd, lcm), (i.gcd(&j), i.lcm(&j))); From d0bd5c39df42e19b2ab1dd5a040b88f3466e8c9b Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Fri, 29 Mar 2019 21:59:33 -0800 Subject: [PATCH 3/9] cargo fmt --- src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cc37002..b20ebc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,7 +134,8 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// ~~~ #[inline] fn extended_gcd(&self, other: &Self) -> ExtendedGcd - where Self: Clone + SubAssign { + where + Self: Clone + SubAssign, { let mut s = (Self::zero(), Self::one()); let mut t = (Self::one(), Self::zero()); let mut r = (other.clone(), self.clone()); @@ -150,15 +151,26 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { f(&mut t); } - if r.1 >= Self::zero() { ExtendedGcd { gcd: r.1, coeffs: [s.1, t.1], _hidden: () } } - else { ExtendedGcd { gcd: Self::zero() - r.1, - coeffs: [Self::zero() - s.1, Self::zero() - t.1], _hidden: () } } + if r.1 >= Self::zero() { + ExtendedGcd { + gcd: r.1, + coeffs: [s.1, t.1], + _hidden: (), + } + } else { + ExtendedGcd { + gcd: Self::zero() - r.1, + coeffs: [Self::zero() - s.1, Self::zero() - t.1], + _hidden: (), + } + } } /// Greatest common divisor, least common multiple, and Bézout coefficients. #[inline] fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) - where Self: Clone + SubAssign { + where + Self: Clone + SubAssign, { (self.extended_gcd(other), self.lcm(other)) } @@ -387,23 +399,26 @@ macro_rules! impl_integer_for_isize { fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) { let egcd = self.extended_gcd(other); // should not have to recalculate abs - let lcm = if egcd.gcd.is_zero() { Self::zero() } - else { (*self * (*other / egcd.gcd)).abs() }; + let lcm = if egcd.gcd.is_zero() { + Self::zero() + } else { + (*self * (*other / egcd.gcd)).abs() + }; (egcd, lcm) } /// Calculates the Lowest Common Multiple (LCM) of the number and /// `other`. #[inline] - fn lcm(&self, other: &Self) -> Self { - self.gcd_lcm(other).1 - } + fn lcm(&self, other: &Self) -> Self { self.gcd_lcm(other).1 } /// Calculates the Greatest Common Divisor (GCD) and /// Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn gcd_lcm(&self, other: &Self) -> (Self, Self) { - if self.is_zero() && other.is_zero() { return (Self::zero(), Self::zero()) } + if self.is_zero() && other.is_zero() { + return (Self::zero(), Self::zero()); + } let gcd = self.gcd(other); // should not have to recalculate abs let lcm = (*self * (*other / gcd)).abs(); @@ -595,8 +610,14 @@ macro_rules! impl_integer_for_isize { #[test] fn test_gcd_lcm() { use core::iter::once; - for i in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { - for j in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { + for i in once(0) + .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) + .chain(once(-128)) + { + for j in once(0) + .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) + .chain(once(-128)) + { assert_eq!(i.gcd_lcm(&j), (i.gcd(&j), i.lcm(&j))); } } @@ -604,8 +625,8 @@ macro_rules! impl_integer_for_isize { #[test] fn test_extended_gcd_lcm() { - use ExtendedGcd; use traits::NumAssign; + use ExtendedGcd; fn check(a: A, b: A) -> bool { let ExtendedGcd { gcd, coeffs, .. } = a.extended_gcd(&b); @@ -613,8 +634,14 @@ macro_rules! impl_integer_for_isize { } use core::iter::once; - for i in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { - for j in once(0).chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))).chain(once(-128)) { + for i in once(0) + .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) + .chain(once(-128)) + { + for j in once(0) + .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) + .chain(once(-128)) + { check(i, j); let (ExtendedGcd { gcd, .. }, lcm) = i.extended_gcd_lcm(&j); assert_eq!((gcd, lcm), (i.gcd(&j), i.lcm(&j))); @@ -707,22 +734,25 @@ macro_rules! impl_integer_for_usize { fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) { let egcd = self.extended_gcd(other); // should not have to recalculate abs - let lcm = if egcd.gcd.is_zero() { Self::zero() } - else { *self * (*other / egcd.gcd) }; + let lcm = if egcd.gcd.is_zero() { + Self::zero() + } else { + *self * (*other / egcd.gcd) + }; (egcd, lcm) } /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] - fn lcm(&self, other: &Self) -> Self { - self.gcd_lcm(other).1 - } + fn lcm(&self, other: &Self) -> Self { self.gcd_lcm(other).1 } /// Calculates the Greatest Common Divisor (GCD) and /// Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn gcd_lcm(&self, other: &Self) -> (Self, Self) { - if self.is_zero() && other.is_zero() { return (Self::zero(), Self::zero()) } + if self.is_zero() && other.is_zero() { + return (Self::zero(), Self::zero()); + } let gcd = self.gcd(other); let lcm = *self * (*other / gcd); (gcd, lcm) From 1c21bc88cf328e415d776c48712aa049523fa16c Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Wed, 10 Apr 2019 06:51:04 -0800 Subject: [PATCH 4/9] scrub `Self: SubAssign` bound on `fn extended_gcd` --- src/lib.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b20ebc2..abd7047 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ extern crate std; extern crate num_traits as traits; use core::mem; -use core::ops::{Add, SubAssign}; +use core::ops::Add; use traits::{Num, Signed, Zero}; @@ -135,20 +135,21 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { #[inline] fn extended_gcd(&self, other: &Self) -> ExtendedGcd where - Self: Clone + SubAssign, { + Self: Clone { let mut s = (Self::zero(), Self::one()); let mut t = (Self::one(), Self::zero()); let mut r = (other.clone(), self.clone()); while !r.0.is_zero() { let q = r.1.clone() / r.0.clone(); - let f = |r: &mut (Self, Self)| { + let f = |mut r: (Self, Self)| { mem::swap(&mut r.0, &mut r.1); - r.0 -= q.clone() * r.1.clone(); + r.0 = r.0.clone() - q.clone() * r.1.clone(); + r }; - f(&mut r); - f(&mut s); - f(&mut t); + r = f(r); + s = f(s); + t = f(t); } if r.1 >= Self::zero() { @@ -170,7 +171,7 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { #[inline] fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) where - Self: Clone + SubAssign, { + Self: Clone + Signed { (self.extended_gcd(other), self.lcm(other)) } From 7c9c42bd4560271fc67cebeee0eaf73ea472f635 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Wed, 10 Apr 2019 06:51:38 -0800 Subject: [PATCH 5/9] separately declare coefficients of `ExtendedGcd` --- build.rs | 4 ---- src/lib.rs | 31 ++++++++++++++++--------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/build.rs b/build.rs index 0a42588..fd60866 100644 --- a/build.rs +++ b/build.rs @@ -8,10 +8,6 @@ fn main() { } else if env::var_os("CARGO_FEATURE_I128").is_some() { panic!("i128 support was not detected!"); } - - if probe("#[derive(Clone)] struct A; fn main() { let _ = [A; 2].clone(); }") { - println!("cargo:rustc-cfg=array_clone"); - } } /// Test if a code snippet can be compiled diff --git a/src/lib.rs b/src/lib.rs index abd7047..542a3b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,8 +125,8 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// # use num_integer::{ExtendedGcd, Integer}; /// # use num_traits::NumAssign; /// fn check(a: A, b: A) -> bool { - /// let ExtendedGcd { gcd, coeffs, .. } = a.extended_gcd(&b); - /// gcd == coeffs[0] * a + coeffs[1] * b + /// let ExtendedGcd { gcd, x, y, .. } = a.extended_gcd(&b); + /// gcd == x * a + y * b /// } /// assert!(check(10isize, 4isize)); /// assert!(check(8isize, 9isize)); @@ -155,13 +155,15 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { if r.1 >= Self::zero() { ExtendedGcd { gcd: r.1, - coeffs: [s.1, t.1], + x: s.1, + y: t.1, _hidden: (), } } else { ExtendedGcd { gcd: Self::zero() - r.1, - coeffs: [Self::zero() - s.1, Self::zero() - t.1], + x: Self::zero() - s.1, + y: Self::zero() - t.1, _hidden: (), } } @@ -254,20 +256,19 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { } /// Greatest common divisor and Bézout coefficients -#[derive(Debug, Copy, PartialEq, Eq)] -#[cfg_attr(array_clone, derive(Clone))] +/// +/// ```no_build +/// let e = isize::extended_gcd(a, b); +/// assert_eq!(e.gcd, e.x*a + e.y*b); +/// ``` +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ExtendedGcd { pub gcd: A, - pub coeffs: [A; 2], + pub x: A, + pub y: A, _hidden: (), } -#[cfg(not(array_clone))] -impl Clone for ExtendedGcd { - #[inline] - fn clone(&self) -> Self { *self } -} - /// Simultaneous integer division and modulus #[inline] pub fn div_rem(x: T, y: T) -> (T, T) { @@ -630,8 +631,8 @@ macro_rules! impl_integer_for_isize { use ExtendedGcd; fn check(a: A, b: A) -> bool { - let ExtendedGcd { gcd, coeffs, .. } = a.extended_gcd(&b); - gcd == coeffs[0] * a + coeffs[1] * b + let ExtendedGcd { gcd, x, y, .. } = a.extended_gcd(&b); + gcd == x * a + y * b } use core::iter::once; From f25cfc21aa6d2c999fcb2f1c248076d9591bc6a2 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Apr 2019 15:35:53 -0700 Subject: [PATCH 6/9] cargo fmt --- src/lib.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 542a3b2..3a70418 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -135,7 +135,8 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { #[inline] fn extended_gcd(&self, other: &Self) -> ExtendedGcd where - Self: Clone { + Self: Clone, + { let mut s = (Self::zero(), Self::one()); let mut t = (Self::one(), Self::zero()); let mut r = (other.clone(), self.clone()); @@ -173,7 +174,8 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { #[inline] fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) where - Self: Clone + Signed { + Self: Clone + Signed, + { (self.extended_gcd(other), self.lcm(other)) } @@ -412,7 +414,9 @@ macro_rules! impl_integer_for_isize { /// Calculates the Lowest Common Multiple (LCM) of the number and /// `other`. #[inline] - fn lcm(&self, other: &Self) -> Self { self.gcd_lcm(other).1 } + fn lcm(&self, other: &Self) -> Self { + self.gcd_lcm(other).1 + } /// Calculates the Greatest Common Divisor (GCD) and /// Lowest Common Multiple (LCM) of the number and `other`. @@ -746,7 +750,9 @@ macro_rules! impl_integer_for_usize { /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] - fn lcm(&self, other: &Self) -> Self { self.gcd_lcm(other).1 } + fn lcm(&self, other: &Self) -> Self { + self.gcd_lcm(other).1 + } /// Calculates the Greatest Common Divisor (GCD) and /// Lowest Common Multiple (LCM) of the number and `other`. From 6d20102f41bb2ef6816b51b9116a8d36416f1db7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Apr 2019 18:36:55 -0700 Subject: [PATCH 7/9] remove an unnecessary clone --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3a70418..a1e9323 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,7 +145,7 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { let q = r.1.clone() / r.0.clone(); let f = |mut r: (Self, Self)| { mem::swap(&mut r.0, &mut r.1); - r.0 = r.0.clone() - q.clone() * r.1.clone(); + r.0 = r.0 - q.clone() * r.1.clone(); r }; r = f(r); From 10fd5e857f983939560772c30f956eae14c6830c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Apr 2019 18:37:32 -0700 Subject: [PATCH 8/9] =?UTF-8?q?assert=20the=20test=20for=20B=C3=A9zout=20c?= =?UTF-8?q?oefficients?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a1e9323..c865738 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -631,12 +631,13 @@ macro_rules! impl_integer_for_isize { #[test] fn test_extended_gcd_lcm() { + use std::fmt::Debug; use traits::NumAssign; use ExtendedGcd; - fn check(a: A, b: A) -> bool { + fn check(a: A, b: A) { let ExtendedGcd { gcd, x, y, .. } = a.extended_gcd(&b); - gcd == x * a + y * b + assert_eq!(gcd, x * a + y * b); } use core::iter::once; From a169ee248d770b65e937c36491d3bb4f2c8b25a4 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Apr 2019 19:48:14 -0700 Subject: [PATCH 9/9] use core::fmt::Debug; --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index c865738..536f2fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -631,7 +631,7 @@ macro_rules! impl_integer_for_isize { #[test] fn test_extended_gcd_lcm() { - use std::fmt::Debug; + use core::fmt::Debug; use traits::NumAssign; use ExtendedGcd;