Skip to content
105 changes: 105 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,31 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq {
/// ~~~
fn mod_floor(&self, other: &Self) -> Self;

/// Ceiled integer division.
///
/// # Examples
///
/// ~~~
/// # use num_integer::Integer;
/// assert_eq!(( 8).div_ceil( &3), 3);
/// assert_eq!(( 8).div_ceil(&-3), -2);
/// assert_eq!((-8).div_ceil( &3), -2);
/// assert_eq!((-8).div_ceil(&-3), 3);
///
/// assert_eq!(( 1).div_ceil( &2), 1);
/// assert_eq!(( 1).div_ceil(&-2), 0);
/// assert_eq!((-1).div_ceil( &2), 0);
/// assert_eq!((-1).div_ceil(&-2), 1);
/// ~~~
fn div_ceil(&self, other: &Self) -> Self {
let (q, r) = self.div_mod_floor(other);
if r.is_zero() {
q
} else {
q + Self::one()
}
}

/// Greatest Common Divisor (GCD).
///
/// # Examples
Expand Down Expand Up @@ -171,6 +196,66 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq {
fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
(self.div_floor(other), self.mod_floor(other))
}

/// Rounds up to nearest multiple of argument.
///
/// # Notes
///
/// For signed types, `a.next_multiple_of(b) = a.prev_multiple_of(b.neg())`.
///
/// # Examples
///
/// ~~~
/// # use num_integer::Integer;
/// assert_eq!(( 16).next_multiple_of(& 8), 16);
/// assert_eq!(( 23).next_multiple_of(& 8), 24);
/// assert_eq!(( 16).next_multiple_of(&-8), 16);
/// assert_eq!(( 23).next_multiple_of(&-8), 16);
/// assert_eq!((-16).next_multiple_of(& 8), -16);
/// assert_eq!((-23).next_multiple_of(& 8), -16);
/// assert_eq!((-16).next_multiple_of(&-8), -16);
/// assert_eq!((-23).next_multiple_of(&-8), -24);
/// ~~~
#[inline]
fn next_multiple_of(&self, other: &Self) -> Self
where
Self: Clone,
{
let m = self.mod_floor(other);
self.clone()
+ if m.is_zero() {
Self::zero()
} else {
other.clone() - m
}
}

/// Rounds down to nearest multiple of argument.
///
/// # Notes
///
/// For signed types, `a.prev_multiple_of(b) = a.next_multiple_of(b.neg())`.
///
/// # Examples
///
/// ~~~
/// # use num_integer::Integer;
/// assert_eq!(( 16).prev_multiple_of(& 8), 16);
/// assert_eq!(( 23).prev_multiple_of(& 8), 16);
/// assert_eq!(( 16).prev_multiple_of(&-8), 16);
/// assert_eq!(( 23).prev_multiple_of(&-8), 24);
/// assert_eq!((-16).prev_multiple_of(& 8), -16);
/// assert_eq!((-23).prev_multiple_of(& 8), -24);
/// assert_eq!((-16).prev_multiple_of(&-8), -16);
/// assert_eq!((-23).prev_multiple_of(&-8), -16);
/// ~~~
#[inline]
fn prev_multiple_of(&self, other: &Self) -> Self
where
Self: Clone,
{
self.clone() - self.mod_floor(other)
}
}

/// Simultaneous integer division and modulus
Expand All @@ -193,6 +278,11 @@ pub fn mod_floor<T: Integer>(x: T, y: T) -> T {
pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) {
x.div_mod_floor(&y)
}
/// Ceiled integer division
#[inline]
pub fn div_ceil<T: Integer>(x: T, y: T) -> T {
x.div_ceil(&y)
}

/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
/// result is always positive.
Expand Down Expand Up @@ -245,6 +335,16 @@ macro_rules! impl_integer_for_isize {
}
}

#[inline]
fn div_ceil(&self, other: &Self) -> Self {
let (d, r) = self.div_rem(other);
if (r > 0 && *other > 0) || (r < 0 && *other < 0) {
d + 1
} else {
d
}
}

/// Calculates the Greatest Common Divisor (GCD) of the number and
/// `other`. The result is always positive.
#[inline]
Expand Down Expand Up @@ -527,6 +627,11 @@ macro_rules! impl_integer_for_usize {
*self % *other
}

#[inline]
fn div_ceil(&self, other: &Self) -> Self {
*self / *other + (0 != *self % *other) as Self
}

/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
#[inline]
fn gcd(&self, other: &Self) -> Self {
Expand Down