From 1588c840c06f6a50c4ee98d2cc939c28ad3cd91e Mon Sep 17 00:00:00 2001 From: ltdk Date: Mon, 1 Jul 2024 10:47:22 -0400 Subject: [PATCH] Add rem_floor and rem_ceil --- library/core/src/num/int_macros.rs | 81 +++++++++++++++++++++++++++++ library/core/src/num/uint_macros.rs | 64 +++++++++++++++++++++++ 2 files changed, 145 insertions(+) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 878a911dde50d..e1e42fc2a7b69 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3030,6 +3030,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 @@ -3066,6 +3105,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 d9036abecc592..163b8228f5e51 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2863,6 +2863,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 @@ -2892,6 +2918,44 @@ macro_rules! uint_impl { } } + /// 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`. ///