From 421a7b160bf2b633695e4fae269188ef956c8c13 Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 17 Feb 2023 16:42:37 -0500 Subject: [PATCH] Add rem_floor and rem_ceil --- library/core/src/num/int_macros.rs | 81 +++++++++++++++++++++++++++++ library/core/src/num/uint_macros.rs | 66 ++++++++++++++++++++++- 2 files changed, 146 insertions(+), 1 deletion(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index fd01f1b261012..2bcc248f0f182 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2269,6 +2269,45 @@ macro_rules! int_impl { } } + /// Calculates the remainder of `self / rhs` if the quotient is rounded toward negative infinity. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// On overflow, this function will panic if overflow checks are enabled (default in debug + /// mode) and wrap if overflow checks are disabled (default in release mode). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_roundings)] + #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")] + /// let b = 3; + /// + /// assert_eq!(a.rem_floor(b), 2); + /// assert_eq!(a.rem_floor(-b), -1); + /// assert_eq!((-a).rem_floor(b), 1); + /// assert_eq!((-a).rem_floor(-b), -2); + /// ``` + #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn rem_floor(self, rhs: Self) -> Self { + let r = self % rhs; + if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) { + r + rhs + } else { + r + } + } + /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. /// /// # Panics @@ -2309,6 +2348,48 @@ macro_rules! int_impl { } } + /// Calculates the remainder of `self / rhs` if the quotient is rounded towards positive infinity. + /// + /// This operation is *only* available for signed integers, + /// since the result would be negative if both operands are positive. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// On overflow, this function will panic if overflow checks are enabled (default in debug + /// mode) and wrap if overflow checks are disabled (default in release mode). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(rem_ceil)] + #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")] + /// let b = 3; + /// + /// assert_eq!(a.rem_ceil(b), -1); + /// assert_eq!(a.rem_ceil(-b), 2); + /// assert_eq!((-a).rem_ceil(b), -2); + /// assert_eq!((-a).rem_ceil(-b), 1); + /// ``` + #[unstable(feature = "rem_ceil", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn rem_ceil(self, rhs: Self) -> Self { + let r = self % rhs; + if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) { + r - rhs + } else { + r + } + } + /// If `rhs` is positive, calculates the smallest value greater than or /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative, /// calculates the largest value less than or equal to `self` that is a diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 11a53aaf122ec..7e761c353f545 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2123,6 +2123,32 @@ macro_rules! uint_impl { self / rhs } + /// Calculates the remainder of `self / rhs` if the quotient is rounded toward negative infinity. + /// + /// This is the same as performing `self % rhs` for all unsigned integers. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_roundings)] + #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".rem_floor(4), 3);")] + /// ``` + #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn rem_floor(self, rhs: Self) -> Self { + self % rhs + } + + /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. /// /// # Panics @@ -2150,13 +2176,51 @@ macro_rules! uint_impl { pub const fn div_ceil(self, rhs: Self) -> Self { let d = self / rhs; let r = self % rhs; - if r > 0 && rhs > 0 { + if r != 0 { d + 1 } else { d } } + /// Calculates the remainder of `self / rhs` if the quotient is rounded towards positive infinity. + /// + /// Since this remainder can never be positive, we return the opposite of the actual remainder. + /// If you want the sign to reflect the actual remainder, you need to use the [signed version]. + /// + #[doc = concat!("[signed version]: primitive.", stringify!($SignedT), ".html#method.rem_ceil")] + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// On overflow, this function will panic if overflow checks are enabled (default in debug + /// mode) and wrap if overflow checks are disabled (default in release mode). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(rem_ceil)] + #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unsigned_rem_ceil(4), 1);")] + /// ``` + #[unstable(feature = "rem_ceil", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn unsigned_rem_ceil(self, rhs: Self) -> Self { + let r = self % rhs; + if r != 0 { + rhs - r + } else { + r + } + } + /// Calculates the smallest value greater than or equal to `self` that /// is a multiple of `rhs`. ///