From cde58ee7e1caf581a313ada70d322f1d4dc42cf6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 3 Sep 2021 14:50:31 -0700 Subject: [PATCH] Fix prev/next_multiple_of(&MIN, &-1) --- src/lib.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 9d55722..d8ba443 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -563,6 +563,29 @@ macro_rules! impl_integer_for_isize { fn div_rem(&self, other: &Self) -> (Self, Self) { (*self / *other, *self % *other) } + + /// Rounds up to nearest multiple of argument. + #[inline] + fn next_multiple_of(&self, other: &Self) -> Self { + // Avoid the overflow of `MIN % -1` + if *other == -1 { + return *self; + } + + let m = Integer::mod_floor(self, other); + *self + if m == 0 { 0 } else { other - m } + } + + /// Rounds down to nearest multiple of argument. + #[inline] + fn prev_multiple_of(&self, other: &Self) -> Self { + // Avoid the overflow of `MIN % -1` + if *other == -1 { + return *self; + } + + *self - Integer::mod_floor(self, other) + } } #[cfg(test)] @@ -785,6 +808,16 @@ macro_rules! impl_integer_for_isize { assert_eq!((3 as $T).is_odd(), true); assert_eq!((4 as $T).is_odd(), false); } + + #[test] + fn test_multiple_of_one_limits() { + for x in &[<$T>::min_value(), <$T>::max_value()] { + for one in &[1, -1] { + assert_eq!(Integer::next_multiple_of(x, one), *x); + assert_eq!(Integer::prev_multiple_of(x, one), *x); + } + } + } } }; }