Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq {
/// ~~~
fn lcm(&self, other: &Self) -> Self;

/// Lowest Common Multiple (LCM) that returns `None`
/// if the LCM is too big for the type.
///
/// # Examples
///
/// ~~~
/// # use num_integer::Integer;
/// assert_eq!(7.checked_lcm(&3), Some(21));
/// assert_eq!(262144i32.checked_lcm(&262145i32), None);
/// ~~~
fn checked_lcm(&self, other: &Self) -> Option<Self>;

/// Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) together.
///
Expand All @@ -139,6 +151,25 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq {
(self.gcd(other), self.lcm(other))
}

/// Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) together, with the LCM returning `None`
/// if the LCM is too big for the type.
///
/// Potentially more efficient than calling `gcd` and `lcm`
/// individually for identical inputs.
///
/// # Examples
///
/// ~~~
/// # use num_integer::Integer;
/// assert_eq!(10.checked_gcd_lcm(&4), (2, Some(20)));
/// assert_eq!(262144i32.checked_gcd_lcm(&262145i32), (1, None));
/// ~~~
#[inline]
fn checked_gcd_lcm(&self, other: &Self) -> (Self, Option<Self>) {
(self.gcd(other), self.checked_lcm(other))
}

/// Greatest common divisor and Bézout coefficients.
///
/// # Examples
Expand Down Expand Up @@ -425,6 +456,12 @@ pub fn gcd<T: Integer>(x: T, y: T) -> T {
pub fn lcm<T: Integer>(x: T, y: T) -> T {
x.lcm(&y)
}
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`,
/// returning `None` if the LCM is too big for the type.
#[inline(always)]
pub fn checked_lcm<T: Integer>(x: T, y: T) -> Option<T> {
x.checked_lcm(&y)
}

/// Calculates the Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) of the number and `other`.
Expand All @@ -433,6 +470,14 @@ pub fn gcd_lcm<T: Integer>(x: T, y: T) -> (T, T) {
x.gcd_lcm(&y)
}

/// Calculates the Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) of the number and `other`, with the LCM
/// returning `None` if the LCM is too big for the type.
#[inline(always)]
pub fn checked_gcd_lcm<T: Integer>(x: T, y: T) -> (T, Option<T>) {
x.checked_gcd_lcm(&y)
}

macro_rules! impl_integer_for_isize {
($T:ty, $test_mod:ident) => {
impl Integer for $T {
Expand Down Expand Up @@ -550,6 +595,13 @@ macro_rules! impl_integer_for_isize {
self.gcd_lcm(other).1
}

/// Calculates the Lowest Common Multiple (LCM) of the number and
/// `other`, returning `None` if the LCM is too big for the type.
#[inline]
fn checked_lcm(&self, other: &Self) -> Option<Self> {
self.checked_gcd_lcm(other).1
}

/// Calculates the Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) of the number and `other`.
#[inline]
Expand All @@ -563,6 +615,21 @@ macro_rules! impl_integer_for_isize {
(gcd, lcm)
}

/// Calculates the Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) of the number and `other`, with
/// the LCM returning `None` if the LCM is too big for the type.
#[inline]
fn checked_gcd_lcm(&self, other: &Self) -> (Self, Option<Self>) {
if self.is_zero() && other.is_zero() {
return (Self::zero(), Some(Self::zero()));
}
let gcd = self.gcd(other);
match self.checked_mul(*other / gcd) {
Some(prod) => (gcd, Some(prod.abs())),
None => (gcd, None),
}
}

/// Returns `true` if the number is a multiple of `other`.
#[inline]
fn is_multiple_of(&self, other: &Self) -> bool {
Expand Down Expand Up @@ -912,6 +979,13 @@ macro_rules! impl_integer_for_usize {
self.gcd_lcm(other).1
}

/// Calculates the Lowest Common Multiple (LCM) of the number and `other`,
/// returning `None` if the LCM is too big for the type.
#[inline]
fn checked_lcm(&self, other: &Self) -> Option<Self> {
self.checked_gcd_lcm(other).1
}

/// Calculates the Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) of the number and `other`.
#[inline]
Expand All @@ -924,6 +998,21 @@ macro_rules! impl_integer_for_usize {
(gcd, lcm)
}

/// Calculates the Greatest Common Divisor (GCD) and
/// Lowest Common Multiple (LCM) of the number and `other`, with the LCM
/// returning `None` if the LCM is too big for the type.
#[inline]
fn checked_gcd_lcm(&self, other: &Self) -> (Self, Option<Self>) {
if self.is_zero() && other.is_zero() {
return (Self::zero(), Some(Self::zero()));
}
let gcd = self.gcd(other);
match self.checked_mul(*other / gcd) {
Some(prod) => (gcd, Some(prod)),
None => (gcd, None),
}
}

/// Returns `true` if the number is a multiple of `other`.
#[inline]
fn is_multiple_of(&self, other: &Self) -> bool {
Expand Down