Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define ceiled division, rounding to nearest multiple #16

Merged
merged 10 commits into from
Mar 28, 2019
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