Skip to content

Commit

Permalink
Merge #291
Browse files Browse the repository at this point in the history
291: feat: add an extra method to (Checked)Euclid trait to get both quotien and rem r=cuviper a=tdelabro

closes #290 

Co-authored-by: Timothée Delabrouille <timothee.delabrouille@gmail.com>
Co-authored-by: Josh Stone <cuviper@gmail.com>
  • Loading branch information
3 people committed Oct 25, 2023
2 parents d916787 + 8175e12 commit f832428
Showing 1 changed file with 48 additions and 2 deletions.
50 changes: 48 additions & 2 deletions src/ops/euclid.rs
Expand Up @@ -46,6 +46,27 @@ pub trait Euclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
/// assert_eq!(Euclid::rem_euclid(&-a, &-b), 1);
/// ```
fn rem_euclid(&self, v: &Self) -> Self;

/// Returns both the quotient and remainder from Euclidean division.
///
/// By default, it internally calls both `Euclid::div_euclid` and `Euclid::rem_euclid`,
/// but it can be overridden in order to implement some optimization.
///
/// # Examples
///
/// ```
/// # use num_traits::Euclid;
/// let x = 5u8;
/// let y = 3u8;
///
/// let div = Euclid::div_euclid(&x, &y);
/// let rem = Euclid::rem_euclid(&x, &y);
///
/// assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y));
/// ```
fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
(self.div_euclid(v), self.rem_euclid(v))
}
}

macro_rules! euclid_forward_impl {
Expand Down Expand Up @@ -174,6 +195,26 @@ pub trait CheckedEuclid: Euclid {
/// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
/// division by zero. If any of that happens, `None` is returned.
fn checked_rem_euclid(&self, v: &Self) -> Option<Self>;

/// Returns both the quotient and remainder from checked Euclidean division.
///
/// By default, it internally calls both `CheckedEuclid::checked_div_euclid` and `CheckedEuclid::checked_rem_euclid`,
/// but it can be overridden in order to implement some optimization.
/// # Examples
///
/// ```
/// # use num_traits::CheckedEuclid;
/// let x = 5u8;
/// let y = 3u8;
///
/// let div = CheckedEuclid::checked_div_euclid(&x, &y);
/// let rem = CheckedEuclid::checked_rem_euclid(&x, &y);
///
/// assert_eq!(Some((div.unwrap(), rem.unwrap())), CheckedEuclid::checked_div_rem_euclid(&x, &y));
/// ```
fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> {
Some((self.checked_div_euclid(v)?, self.checked_rem_euclid(v)?))
}
}

macro_rules! checked_euclid_forward_impl {
Expand Down Expand Up @@ -262,8 +303,11 @@ mod tests {
{
let x: $t = 10;
let y: $t = 3;
assert_eq!(Euclid::div_euclid(&x, &y), 3);
assert_eq!(Euclid::rem_euclid(&x, &y), 1);
let div = Euclid::div_euclid(&x, &y);
let rem = Euclid::rem_euclid(&x, &y);
assert_eq!(div, 3);
assert_eq!(rem, 1);
assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y));
}
)+
};
Expand All @@ -284,6 +328,7 @@ mod tests {
assert_eq!(Euclid::div_euclid(&-x, &y), 4);
assert_eq!(Euclid::rem_euclid(&x, &y), 1);
assert_eq!(Euclid::rem_euclid(&-x, &y), 2);
assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y));
let x: $t = $t::min_value() + 1;
let y: $t = -1;
assert_eq!(Euclid::div_euclid(&x, &y), $t::max_value());
Expand Down Expand Up @@ -311,6 +356,7 @@ mod tests {
<= 46.4 * <$t as crate::float::FloatCore>::epsilon());
assert!(Euclid::div_euclid(&-x, &-y) * -y + Euclid::rem_euclid(&-x, &-y) + x
<= 46.4 * <$t as crate::float::FloatCore>::epsilon());
assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y));
}
)+
};
Expand Down

0 comments on commit f832428

Please sign in to comment.