Skip to content

Commit f832428

Browse files
bors[bot]tdelabrocuviper
authored
Merge #291
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>
2 parents d916787 + 8175e12 commit f832428

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

src/ops/euclid.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,27 @@ pub trait Euclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
4646
/// assert_eq!(Euclid::rem_euclid(&-a, &-b), 1);
4747
/// ```
4848
fn rem_euclid(&self, v: &Self) -> Self;
49+
50+
/// Returns both the quotient and remainder from Euclidean division.
51+
///
52+
/// By default, it internally calls both `Euclid::div_euclid` and `Euclid::rem_euclid`,
53+
/// but it can be overridden in order to implement some optimization.
54+
///
55+
/// # Examples
56+
///
57+
/// ```
58+
/// # use num_traits::Euclid;
59+
/// let x = 5u8;
60+
/// let y = 3u8;
61+
///
62+
/// let div = Euclid::div_euclid(&x, &y);
63+
/// let rem = Euclid::rem_euclid(&x, &y);
64+
///
65+
/// assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y));
66+
/// ```
67+
fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
68+
(self.div_euclid(v), self.rem_euclid(v))
69+
}
4970
}
5071

5172
macro_rules! euclid_forward_impl {
@@ -174,6 +195,26 @@ pub trait CheckedEuclid: Euclid {
174195
/// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
175196
/// division by zero. If any of that happens, `None` is returned.
176197
fn checked_rem_euclid(&self, v: &Self) -> Option<Self>;
198+
199+
/// Returns both the quotient and remainder from checked Euclidean division.
200+
///
201+
/// By default, it internally calls both `CheckedEuclid::checked_div_euclid` and `CheckedEuclid::checked_rem_euclid`,
202+
/// but it can be overridden in order to implement some optimization.
203+
/// # Examples
204+
///
205+
/// ```
206+
/// # use num_traits::CheckedEuclid;
207+
/// let x = 5u8;
208+
/// let y = 3u8;
209+
///
210+
/// let div = CheckedEuclid::checked_div_euclid(&x, &y);
211+
/// let rem = CheckedEuclid::checked_rem_euclid(&x, &y);
212+
///
213+
/// assert_eq!(Some((div.unwrap(), rem.unwrap())), CheckedEuclid::checked_div_rem_euclid(&x, &y));
214+
/// ```
215+
fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> {
216+
Some((self.checked_div_euclid(v)?, self.checked_rem_euclid(v)?))
217+
}
177218
}
178219

179220
macro_rules! checked_euclid_forward_impl {
@@ -262,8 +303,11 @@ mod tests {
262303
{
263304
let x: $t = 10;
264305
let y: $t = 3;
265-
assert_eq!(Euclid::div_euclid(&x, &y), 3);
266-
assert_eq!(Euclid::rem_euclid(&x, &y), 1);
306+
let div = Euclid::div_euclid(&x, &y);
307+
let rem = Euclid::rem_euclid(&x, &y);
308+
assert_eq!(div, 3);
309+
assert_eq!(rem, 1);
310+
assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y));
267311
}
268312
)+
269313
};
@@ -284,6 +328,7 @@ mod tests {
284328
assert_eq!(Euclid::div_euclid(&-x, &y), 4);
285329
assert_eq!(Euclid::rem_euclid(&x, &y), 1);
286330
assert_eq!(Euclid::rem_euclid(&-x, &y), 2);
331+
assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y));
287332
let x: $t = $t::min_value() + 1;
288333
let y: $t = -1;
289334
assert_eq!(Euclid::div_euclid(&x, &y), $t::max_value());
@@ -311,6 +356,7 @@ mod tests {
311356
<= 46.4 * <$t as crate::float::FloatCore>::epsilon());
312357
assert!(Euclid::div_euclid(&-x, &-y) * -y + Euclid::rem_euclid(&-x, &-y) + x
313358
<= 46.4 * <$t as crate::float::FloatCore>::epsilon());
359+
assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y));
314360
}
315361
)+
316362
};

0 commit comments

Comments
 (0)