add exact_div functions
This commit is contained in:
parent
4d051fb306
commit
90ebad3f49
2 changed files with 207 additions and 1 deletions
|
|
@ -4,7 +4,7 @@ macro_rules! int_impl {
|
|||
ActualT = $ActualT:ident,
|
||||
UnsignedT = $UnsignedT:ty,
|
||||
|
||||
// There are all for use *only* in doc comments.
|
||||
// These are all for use *only* in doc comments.
|
||||
// As such, they're all passed as literals -- passing them as a string
|
||||
// literal is fine if they need to be multiple code tokens.
|
||||
// In non-comments, use the associated constants rather than these.
|
||||
|
|
@ -1018,6 +1018,110 @@ macro_rules! int_impl {
|
|||
if b { overflow_panic::div() } else { a }
|
||||
}
|
||||
|
||||
/// Checked integer division without remainder. Computes `self / rhs`,
|
||||
/// returning `None` if `rhs == 0`, the division results in overflow,
|
||||
/// or `self % rhs != 0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_exact_div(-1), Some(", stringify!($Max), "));")]
|
||||
#[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_exact_div(2), None);")]
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_exact_div(-1), None);")]
|
||||
#[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_exact_div(0), None);")]
|
||||
/// ```
|
||||
#[unstable(
|
||||
feature = "exact_div",
|
||||
issue = "139911",
|
||||
)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_exact_div(self, rhs: Self) -> Option<Self> {
|
||||
if intrinsics::unlikely(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: division by zero and overflow are checked above
|
||||
unsafe {
|
||||
if intrinsics::unlikely(intrinsics::unchecked_rem(self, rhs) != 0) {
|
||||
None
|
||||
} else {
|
||||
Some(intrinsics::exact_div(self, rhs))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checked integer division without remainder. Computes `self / rhs`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs == 0`, the division results in overflow,
|
||||
/// or `self % rhs != 0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
|
||||
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).exact_div(-1), ", stringify!($Max), ");")]
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
|
||||
/// ```
|
||||
/// ```should_panic
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.exact_div(-1);")]
|
||||
/// ```
|
||||
#[unstable(
|
||||
feature = "exact_div",
|
||||
issue = "139911",
|
||||
)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn exact_div(self, rhs: Self) -> Self {
|
||||
match self.checked_exact_div(rhs) {
|
||||
Some(x) => x,
|
||||
None => panic!("Failed to divide without remainder"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Unchecked integer division without remainder. Computes `self / rhs`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when `rhs == 0`, `self % rhs != 0`, or
|
||||
#[doc = concat!("`self == ", stringify!($SelfT), "::MIN && rhs == -1`,")]
|
||||
/// i.e. when [`checked_exact_div`](Self::checked_exact_div) would return `None`.
|
||||
#[unstable(
|
||||
feature = "exact_div",
|
||||
issue = "139911",
|
||||
)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const unsafe fn unchecked_exact_div(self, rhs: Self) -> Self {
|
||||
assert_unsafe_precondition!(
|
||||
check_language_ub,
|
||||
concat!(stringify!($SelfT), "::unchecked_exact_div cannot overflow, divide by zero, or leave a remainder"),
|
||||
(
|
||||
lhs: $SelfT = self,
|
||||
rhs: $SelfT = rhs,
|
||||
) => rhs > 0 && lhs % rhs == 0 && (lhs != <$SelfT>::MIN || rhs != -1),
|
||||
);
|
||||
// SAFETY: Same precondition
|
||||
unsafe { intrinsics::exact_div(self, rhs) }
|
||||
}
|
||||
|
||||
/// Checked integer remainder. Computes `self % rhs`, returning `None` if
|
||||
/// `rhs == 0` or the division results in overflow.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1110,6 +1110,108 @@ macro_rules! uint_impl {
|
|||
self / rhs
|
||||
}
|
||||
|
||||
/// Checked integer division without remainder. Computes `self / rhs`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs == 0` or `self % rhs != 0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
|
||||
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
|
||||
/// ```
|
||||
#[unstable(
|
||||
feature = "exact_div",
|
||||
issue = "139911",
|
||||
)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_exact_div(self, rhs: Self) -> Option<Self> {
|
||||
if intrinsics::unlikely(rhs == 0) {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: division by zero is checked above
|
||||
unsafe {
|
||||
if intrinsics::unlikely(intrinsics::unchecked_rem(self, rhs) != 0) {
|
||||
None
|
||||
} else {
|
||||
Some(intrinsics::exact_div(self, rhs))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checked integer division without remainder. Computes `self / rhs`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs == 0` or `self % rhs != 0`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
|
||||
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(exact_div)]
|
||||
#[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
|
||||
/// ```
|
||||
#[unstable(
|
||||
feature = "exact_div",
|
||||
issue = "139911",
|
||||
)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn exact_div(self, rhs: Self) -> Self {
|
||||
match self.checked_exact_div(rhs) {
|
||||
Some(x) => x,
|
||||
None => panic!("Failed to divide without remainder"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Unchecked integer division without remainder. Computes `self / rhs`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This results in undefined behavior when `rhs == 0` or `self % rhs != 0`,
|
||||
/// i.e. when [`checked_exact_div`](Self::checked_exact_div) would return `None`.
|
||||
#[unstable(
|
||||
feature = "exact_div",
|
||||
issue = "139911",
|
||||
)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const unsafe fn unchecked_exact_div(self, rhs: Self) -> Self {
|
||||
assert_unsafe_precondition!(
|
||||
check_language_ub,
|
||||
concat!(stringify!($SelfT), "::unchecked_exact_div divide by zero or leave a remainder"),
|
||||
(
|
||||
lhs: $SelfT = self,
|
||||
rhs: $SelfT = rhs,
|
||||
) => rhs > 0 && lhs % rhs == 0,
|
||||
);
|
||||
// SAFETY: Same precondition
|
||||
unsafe { intrinsics::exact_div(self, rhs) }
|
||||
}
|
||||
|
||||
/// Checked integer remainder. Computes `self % rhs`, returning `None`
|
||||
/// if `rhs == 0`.
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue