Implement #88581
This commit is contained in:
parent
76e755cf4a
commit
727a4fc7e3
5 changed files with 346 additions and 0 deletions
|
@ -1746,6 +1746,173 @@ macro_rules! int_impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function will panic if `rhs` is 0 or the division results in overflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
|
||||||
|
/// let b = 3;
|
||||||
|
///
|
||||||
|
/// assert_eq!(a.div_floor(b), 2);
|
||||||
|
/// assert_eq!(a.div_floor(-b), -3);
|
||||||
|
/// assert_eq!((-a).div_floor(b), -3);
|
||||||
|
/// assert_eq!((-a).div_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 div_floor(self, rhs: Self) -> Self {
|
||||||
|
let d = self / rhs;
|
||||||
|
let r = self % rhs;
|
||||||
|
if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
|
||||||
|
d - 1
|
||||||
|
} else {
|
||||||
|
d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function will panic if `rhs` is 0 or the division results in overflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
|
||||||
|
/// let b = 3;
|
||||||
|
///
|
||||||
|
/// assert_eq!(a.div_ceil(b), 3);
|
||||||
|
/// assert_eq!(a.div_ceil(-b), -2);
|
||||||
|
/// assert_eq!((-a).div_ceil(b), -2);
|
||||||
|
/// assert_eq!((-a).div_ceil(-b), 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 div_ceil(self, rhs: Self) -> Self {
|
||||||
|
let d = self / rhs;
|
||||||
|
let r = self % rhs;
|
||||||
|
if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {
|
||||||
|
d + 1
|
||||||
|
} else {
|
||||||
|
d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// multiple of `rhs`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function will panic if `rhs` is 0 or the operation results in overflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
|
||||||
|
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
|
||||||
|
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
|
||||||
|
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
|
||||||
|
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
|
||||||
|
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
|
||||||
|
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(-8), -16);")]
|
||||||
|
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(-8), -24);")]
|
||||||
|
/// ```
|
||||||
|
#[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 next_multiple_of(self, rhs: Self) -> Self {
|
||||||
|
// This would otherwise fail when calculating `r` when self == T::MIN.
|
||||||
|
if rhs == -1 {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = self % rhs;
|
||||||
|
let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
|
||||||
|
r + rhs
|
||||||
|
} else {
|
||||||
|
r
|
||||||
|
};
|
||||||
|
|
||||||
|
if m == 0 {
|
||||||
|
self
|
||||||
|
} else {
|
||||||
|
self + (rhs - m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// multiple of `rhs`. Returns `None` if `rhs` is zero or the operation
|
||||||
|
/// would result in overflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")]
|
||||||
|
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")]
|
||||||
|
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")]
|
||||||
|
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")]
|
||||||
|
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")]
|
||||||
|
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")]
|
||||||
|
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-16));")]
|
||||||
|
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-24));")]
|
||||||
|
#[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")]
|
||||||
|
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")]
|
||||||
|
/// ```
|
||||||
|
#[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 checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
|
||||||
|
// This would otherwise fail when calculating `r` when self == T::MIN.
|
||||||
|
if rhs == -1 {
|
||||||
|
return Some(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = try_opt!(self.checked_rem(rhs));
|
||||||
|
let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
|
||||||
|
try_opt!(r.checked_add(rhs))
|
||||||
|
} else {
|
||||||
|
r
|
||||||
|
};
|
||||||
|
|
||||||
|
if m == 0 {
|
||||||
|
Some(self)
|
||||||
|
} else {
|
||||||
|
self.checked_add(try_opt!(rhs.checked_sub(m)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the logarithm of the number with respect to an arbitrary base.
|
/// Returns the logarithm of the number with respect to an arbitrary base.
|
||||||
///
|
///
|
||||||
/// This method might not be optimized owing to implementation details;
|
/// This method might not be optimized owing to implementation details;
|
||||||
|
|
|
@ -1758,6 +1758,110 @@ macro_rules! uint_impl {
|
||||||
self % rhs
|
self % rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity.
|
||||||
|
///
|
||||||
|
/// This is the same as performing `self / rhs` for all unsigned integers.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function will panic if `rhs` is 0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_floor(4), 1);")]
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "int_roundings", issue = "88581")]
|
||||||
|
#[inline(always)]
|
||||||
|
#[rustc_inherit_overflow_checks]
|
||||||
|
pub const fn div_floor(self, rhs: Self) -> Self {
|
||||||
|
self / rhs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function will panic if `rhs` is 0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")]
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "int_roundings", issue = "88581")]
|
||||||
|
#[inline]
|
||||||
|
#[rustc_inherit_overflow_checks]
|
||||||
|
pub const fn div_ceil(self, rhs: Self) -> Self {
|
||||||
|
let d = self / rhs;
|
||||||
|
let r = self % rhs;
|
||||||
|
if r > 0 && rhs > 0 {
|
||||||
|
d + 1
|
||||||
|
} else {
|
||||||
|
d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the smallest value greater than or equal to `self` that
|
||||||
|
/// is a multiple of `rhs`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function will panic if `rhs` is 0 or the operation results in overflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
|
||||||
|
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
|
||||||
|
/// ```
|
||||||
|
#[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 next_multiple_of(self, rhs: Self) -> Self {
|
||||||
|
match self % rhs {
|
||||||
|
0 => self,
|
||||||
|
r => self + (rhs - r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the smallest value greater than or equal to `self` that
|
||||||
|
/// is a multiple of `rhs`. If `rhs` is negative,
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(int_roundings)]
|
||||||
|
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")]
|
||||||
|
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")]
|
||||||
|
#[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")]
|
||||||
|
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")]
|
||||||
|
/// ```
|
||||||
|
#[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 checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
|
||||||
|
match try_opt!(self.checked_rem(rhs)) {
|
||||||
|
0 => Some(self),
|
||||||
|
r => self.checked_add(try_opt!(rhs.checked_sub(r)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if and only if `self == 2^k` for some `k`.
|
/// Returns `true` if and only if `self == 2^k` for some `k`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#![feature(unsized_tuple_coercion)]
|
#![feature(unsized_tuple_coercion)]
|
||||||
#![feature(const_option)]
|
#![feature(const_option)]
|
||||||
#![feature(integer_atomics)]
|
#![feature(integer_atomics)]
|
||||||
|
#![feature(int_roundings)]
|
||||||
#![feature(slice_group_by)]
|
#![feature(slice_group_by)]
|
||||||
#![feature(trusted_random_access)]
|
#![feature(trusted_random_access)]
|
||||||
#![feature(unsize)]
|
#![feature(unsize)]
|
||||||
|
|
|
@ -289,6 +289,55 @@ macro_rules! int_module {
|
||||||
assert_eq!(r.saturating_pow(3), -8 as $T);
|
assert_eq!(r.saturating_pow(3), -8 as $T);
|
||||||
assert_eq!(r.saturating_pow(0), 1 as $T);
|
assert_eq!(r.saturating_pow(0), 1 as $T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_div_floor() {
|
||||||
|
let a: $T = 8;
|
||||||
|
let b = 3;
|
||||||
|
assert_eq!(a.div_floor(b), 2);
|
||||||
|
assert_eq!(a.div_floor(-b), -3);
|
||||||
|
assert_eq!((-a).div_floor(b), -3);
|
||||||
|
assert_eq!((-a).div_floor(-b), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_div_ceil() {
|
||||||
|
let a: $T = 8;
|
||||||
|
let b = 3;
|
||||||
|
assert_eq!(a.div_ceil(b), 3);
|
||||||
|
assert_eq!(a.div_ceil(-b), -2);
|
||||||
|
assert_eq!((-a).div_ceil(b), -2);
|
||||||
|
assert_eq!((-a).div_ceil(-b), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_next_multiple_of() {
|
||||||
|
assert_eq!((16 as $T).next_multiple_of(8), 16);
|
||||||
|
assert_eq!((23 as $T).next_multiple_of(8), 24);
|
||||||
|
assert_eq!((16 as $T).next_multiple_of(-8), 16);
|
||||||
|
assert_eq!((23 as $T).next_multiple_of(-8), 16);
|
||||||
|
assert_eq!((-16 as $T).next_multiple_of(8), -16);
|
||||||
|
assert_eq!((-23 as $T).next_multiple_of(8), -16);
|
||||||
|
assert_eq!((-16 as $T).next_multiple_of(-8), -16);
|
||||||
|
assert_eq!((-23 as $T).next_multiple_of(-8), -24);
|
||||||
|
assert_eq!(MIN.next_multiple_of(-1), MIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_checked_next_multiple_of() {
|
||||||
|
assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16));
|
||||||
|
assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24));
|
||||||
|
assert_eq!((16 as $T).checked_next_multiple_of(-8), Some(16));
|
||||||
|
assert_eq!((23 as $T).checked_next_multiple_of(-8), Some(16));
|
||||||
|
assert_eq!((-16 as $T).checked_next_multiple_of(8), Some(-16));
|
||||||
|
assert_eq!((-23 as $T).checked_next_multiple_of(8), Some(-16));
|
||||||
|
assert_eq!((-16 as $T).checked_next_multiple_of(-8), Some(-16));
|
||||||
|
assert_eq!((-23 as $T).checked_next_multiple_of(-8), Some(-24));
|
||||||
|
assert_eq!((1 as $T).checked_next_multiple_of(0), None);
|
||||||
|
assert_eq!(MAX.checked_next_multiple_of(2), None);
|
||||||
|
assert_eq!(MIN.checked_next_multiple_of(-3), None);
|
||||||
|
assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,31 @@ macro_rules! uint_module {
|
||||||
assert_eq!(r.overflowing_pow(2), (1 as $T, true));
|
assert_eq!(r.overflowing_pow(2), (1 as $T, true));
|
||||||
assert_eq!(r.saturating_pow(2), MAX);
|
assert_eq!(r.saturating_pow(2), MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_div_floor() {
|
||||||
|
assert_eq!((8 as $T).div_floor(3), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_div_ceil() {
|
||||||
|
assert_eq!((8 as $T).div_ceil(3), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_next_multiple_of() {
|
||||||
|
assert_eq!((16 as $T).next_multiple_of(8), 16);
|
||||||
|
assert_eq!((23 as $T).next_multiple_of(8), 24);
|
||||||
|
assert_eq!(MAX.next_multiple_of(1), MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_checked_next_multiple_of() {
|
||||||
|
assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16));
|
||||||
|
assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24));
|
||||||
|
assert_eq!((1 as $T).checked_next_multiple_of(0), None);
|
||||||
|
assert_eq!(MAX.checked_next_multiple_of(2), None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue