Rollup merge of #87601 - a1phyr:feature_uint_add_signed, r=kennytm
Add functions to add unsigned and signed integers This PR adds methods to unsigned integers to add signed integers with good overflow semantics under `#![feature(mixed_integer_ops)]`. The added API is: ```rust // `uX` is `u8`, `u16`, `u32`, `u64`,`u128`, `usize` impl uX { pub const fn checked_add_signed(self, iX) -> Option<Self>; pub const fn overflowing_add_signed(self, iX) -> (Self, bool); pub const fn saturating_add_signed(self, iX) -> Self; pub const fn wrapping_add_signed(self, iX) -> Self; } impl iX { pub const fn checked_add_unsigned(self, uX) -> Option<Self>; pub const fn overflowing_add_unsigned(self, uX) -> (Self, bool); pub const fn saturating_add_unsigned(self, uX) -> Self; pub const fn wrapping_add_unsigned(self, uX) -> Self; pub const fn checked_sub_unsigned(self, uX) -> Option<Self>; pub const fn overflowing_sub_unsigned(self, uX) -> (Self, bool); pub const fn saturating_sub_unsigned(self, uX) -> Self; pub const fn wrapping_sub_unsigned(self, uX) -> Self; } ``` Maybe it would be interesting to also have `add_signed` that panics in debug and wraps in release ?
This commit is contained in:
commit
3209582a87
6 changed files with 304 additions and 15 deletions
|
@ -142,6 +142,7 @@
|
|||
#![feature(link_llvm_intrinsics)]
|
||||
#![feature(llvm_asm)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(mixed_integer_ops)]
|
||||
#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
|
|
|
@ -433,6 +433,28 @@ macro_rules! int_impl {
|
|||
unsafe { intrinsics::unchecked_add(self, rhs) }
|
||||
}
|
||||
|
||||
/// Checked addition with an unsigned integer. Computes `self + rhs`,
|
||||
/// returning `None` if overflow occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_add_unsigned(rhs);
|
||||
if unlikely!(b) {None} else {Some(a)}
|
||||
}
|
||||
|
||||
/// Checked integer subtraction. Computes `self - rhs`, returning `None` if
|
||||
/// overflow occurred.
|
||||
///
|
||||
|
@ -479,6 +501,28 @@ macro_rules! int_impl {
|
|||
unsafe { intrinsics::unchecked_sub(self, rhs) }
|
||||
}
|
||||
|
||||
/// Checked subtraction with an unsigned integer. Computes `self - rhs`,
|
||||
/// returning `None` if overflow occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_sub_unsigned(rhs);
|
||||
if unlikely!(b) {None} else {Some(a)}
|
||||
}
|
||||
|
||||
/// Checked integer multiplication. Computes `self * rhs`, returning `None` if
|
||||
/// overflow occurred.
|
||||
///
|
||||
|
@ -826,6 +870,32 @@ macro_rules! int_impl {
|
|||
intrinsics::saturating_add(self, rhs)
|
||||
}
|
||||
|
||||
/// Saturating addition with an unsigned integer. Computes `self + rhs`,
|
||||
/// saturating at the numeric bounds instead of overflowing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")]
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn saturating_add_unsigned(self, rhs: $UnsignedT) -> Self {
|
||||
// Overflow can only happen at the upper bound
|
||||
// We cannot use `unwrap_or` here because it is not `const`
|
||||
match self.checked_add_unsigned(rhs) {
|
||||
Some(x) => x,
|
||||
None => Self::MAX,
|
||||
}
|
||||
}
|
||||
|
||||
/// Saturating integer subtraction. Computes `self - rhs`, saturating at the
|
||||
/// numeric bounds instead of overflowing.
|
||||
///
|
||||
|
@ -847,6 +917,32 @@ macro_rules! int_impl {
|
|||
intrinsics::saturating_sub(self, rhs)
|
||||
}
|
||||
|
||||
/// Saturating subtraction with an unsigned integer. Computes `self - rhs`,
|
||||
/// saturating at the numeric bounds instead of overflowing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")]
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn saturating_sub_unsigned(self, rhs: $UnsignedT) -> Self {
|
||||
// Overflow can only happen at the lower bound
|
||||
// We cannot use `unwrap_or` here because it is not `const`
|
||||
match self.checked_sub_unsigned(rhs) {
|
||||
Some(x) => x,
|
||||
None => Self::MIN,
|
||||
}
|
||||
}
|
||||
|
||||
/// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN`
|
||||
/// instead of overflowing.
|
||||
///
|
||||
|
@ -1002,6 +1098,27 @@ macro_rules! int_impl {
|
|||
intrinsics::wrapping_add(self, rhs)
|
||||
}
|
||||
|
||||
/// Wrapping (modular) addition with an unsigned integer. Computes
|
||||
/// `self + rhs`, wrapping around at the boundary of the type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")]
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn wrapping_add_unsigned(self, rhs: $UnsignedT) -> Self {
|
||||
self.wrapping_add(rhs as Self)
|
||||
}
|
||||
|
||||
/// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the
|
||||
/// boundary of the type.
|
||||
///
|
||||
|
@ -1022,6 +1139,27 @@ macro_rules! int_impl {
|
|||
intrinsics::wrapping_sub(self, rhs)
|
||||
}
|
||||
|
||||
/// Wrapping (modular) subtraction with an unsigned integer. Computes
|
||||
/// `self - rhs`, wrapping around at the boundary of the type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")]
|
||||
#[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn wrapping_sub_unsigned(self, rhs: $UnsignedT) -> Self {
|
||||
self.wrapping_sub(rhs as Self)
|
||||
}
|
||||
|
||||
/// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
|
||||
/// the boundary of the type.
|
||||
///
|
||||
|
@ -1372,6 +1510,33 @@ macro_rules! int_impl {
|
|||
(sum as $SelfT, carry)
|
||||
}
|
||||
|
||||
/// Calculates `self` + `rhs` with an unsigned `rhs`
|
||||
///
|
||||
/// Returns a tuple of the addition along with a boolean indicating
|
||||
/// whether an arithmetic overflow would occur. If an overflow would
|
||||
/// have occurred then the wrapped value is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_add_unsigned(self, rhs: $UnsignedT) -> (Self, bool) {
|
||||
let rhs = rhs as Self;
|
||||
let (res, overflowed) = self.overflowing_add(rhs);
|
||||
(res, overflowed ^ (rhs < 0))
|
||||
}
|
||||
|
||||
/// Calculates `self` - `rhs`
|
||||
///
|
||||
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow
|
||||
|
@ -1423,6 +1588,33 @@ macro_rules! int_impl {
|
|||
(sum as $SelfT, borrow)
|
||||
}
|
||||
|
||||
/// Calculates `self` - `rhs` with an unsigned `rhs`
|
||||
///
|
||||
/// Returns a tuple of the subtraction along with a boolean indicating
|
||||
/// whether an arithmetic overflow would occur. If an overflow would
|
||||
/// have occurred then the wrapped value is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_sub_unsigned(self, rhs: $UnsignedT) -> (Self, bool) {
|
||||
let rhs = rhs as Self;
|
||||
let (res, overflowed) = self.overflowing_sub(rhs);
|
||||
(res, overflowed ^ (rhs < 0))
|
||||
}
|
||||
|
||||
/// Calculates the multiplication of `self` and `rhs`.
|
||||
///
|
||||
/// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow
|
||||
|
|
|
@ -245,7 +245,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000;
|
|||
#[lang = "u8"]
|
||||
impl u8 {
|
||||
widening_impl! { u8, u16, 8 }
|
||||
uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
|
||||
uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
|
||||
"[0x12]", "", "" }
|
||||
|
||||
/// Checks if the value is within the ASCII range.
|
||||
|
@ -779,21 +779,21 @@ impl u8 {
|
|||
#[lang = "u16"]
|
||||
impl u16 {
|
||||
widening_impl! { u16, u32, 16 }
|
||||
uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||
uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "u32"]
|
||||
impl u32 {
|
||||
widening_impl! { u32, u64, 32 }
|
||||
uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
||||
uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
||||
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "u64"]
|
||||
impl u64 {
|
||||
widening_impl! { u64, u128, 64 }
|
||||
uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
||||
uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
||||
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
||||
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
|
||||
|
@ -802,7 +802,7 @@ impl u64 {
|
|||
|
||||
#[lang = "u128"]
|
||||
impl u128 {
|
||||
uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, 16,
|
||||
uint_impl! { u128, u128, i128, 128, 340282366920938463463374607431768211455, 16,
|
||||
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
|
||||
"0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
|
||||
"[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
|
||||
|
@ -816,7 +816,7 @@ impl u128 {
|
|||
#[lang = "usize"]
|
||||
impl usize {
|
||||
widening_impl! { usize, u32, 16 }
|
||||
uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||
uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||
"[0x34, 0x12]", "[0x12, 0x34]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
|
@ -824,7 +824,7 @@ impl usize {
|
|||
#[lang = "usize"]
|
||||
impl usize {
|
||||
widening_impl! { usize, u64, 32 }
|
||||
uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
||||
uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
||||
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
|
@ -833,7 +833,7 @@ impl usize {
|
|||
#[lang = "usize"]
|
||||
impl usize {
|
||||
widening_impl! { usize, u128, 64 }
|
||||
uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
||||
uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
||||
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
||||
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
macro_rules! uint_impl {
|
||||
($SelfT:ty, $ActualT:ident, $BITS:expr, $MaxV:expr,
|
||||
($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr,
|
||||
$rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
|
||||
$reversed:expr, $le_bytes:expr, $be_bytes:expr,
|
||||
$to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
|
||||
|
@ -442,6 +442,29 @@ macro_rules! uint_impl {
|
|||
unsafe { intrinsics::unchecked_add(self, rhs) }
|
||||
}
|
||||
|
||||
/// Checked addition with a signed integer. Computes `self + rhs`,
|
||||
/// returning `None` if overflow occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_add_signed(self, rhs: $SignedT) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_add_signed(rhs);
|
||||
if unlikely!(b) {None} else {Some(a)}
|
||||
}
|
||||
|
||||
/// Checked integer subtraction. Computes `self - rhs`, returning
|
||||
/// `None` if overflow occurred.
|
||||
///
|
||||
|
@ -995,6 +1018,35 @@ macro_rules! uint_impl {
|
|||
intrinsics::saturating_add(self, rhs)
|
||||
}
|
||||
|
||||
/// Saturating addition with a signed integer. Computes `self + rhs`,
|
||||
/// saturating at the numeric bounds instead of overflowing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn saturating_add_signed(self, rhs: $SignedT) -> Self {
|
||||
let (res, overflow) = self.overflowing_add(rhs as Self);
|
||||
if overflow == (rhs < 0) {
|
||||
res
|
||||
} else if overflow {
|
||||
Self::MAX
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Saturating integer subtraction. Computes `self - rhs`, saturating
|
||||
/// at the numeric bounds instead of overflowing.
|
||||
///
|
||||
|
@ -1111,6 +1163,28 @@ macro_rules! uint_impl {
|
|||
intrinsics::wrapping_add(self, rhs)
|
||||
}
|
||||
|
||||
/// Wrapping (modular) addition with a signed integer. Computes
|
||||
/// `self + rhs`, wrapping around at the boundary of the type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_add_signed(self, rhs: $SignedT) -> Self {
|
||||
self.wrapping_add(rhs as Self)
|
||||
}
|
||||
|
||||
/// Wrapping (modular) subtraction. Computes `self - rhs`,
|
||||
/// wrapping around at the boundary of the type.
|
||||
///
|
||||
|
@ -1435,6 +1509,32 @@ macro_rules! uint_impl {
|
|||
(c, b | d)
|
||||
}
|
||||
|
||||
/// Calculates `self` + `rhs` with a signed `rhs`
|
||||
///
|
||||
/// Returns a tuple of the addition along with a boolean indicating
|
||||
/// whether an arithmetic overflow would occur. If an overflow would
|
||||
/// have occurred then the wrapped value is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(mixed_integer_ops)]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")]
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")]
|
||||
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")]
|
||||
/// ```
|
||||
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_add_signed(self, rhs: $SignedT) -> (Self, bool) {
|
||||
let (res, overflowed) = self.overflowing_add(rhs as Self);
|
||||
(res, overflowed ^ (rhs < 0))
|
||||
}
|
||||
|
||||
/// Calculates `self` - `rhs`
|
||||
///
|
||||
/// Returns a tuple of the subtraction along with a boolean indicating
|
||||
|
|
|
@ -292,12 +292,7 @@ where
|
|||
SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
|
||||
SeekFrom::Current(n) => (self.pos, n),
|
||||
};
|
||||
let new_pos = if offset >= 0 {
|
||||
base_pos.checked_add(offset as u64)
|
||||
} else {
|
||||
base_pos.checked_sub((offset.wrapping_neg()) as u64)
|
||||
};
|
||||
match new_pos {
|
||||
match base_pos.checked_add_signed(offset) {
|
||||
Some(n) => {
|
||||
self.pos = n;
|
||||
Ok(self.pos)
|
||||
|
|
|
@ -297,6 +297,7 @@
|
|||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_uninit_array)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(mixed_integer_ops)]
|
||||
#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
|
||||
#![feature(needs_panic_runtime)]
|
||||
#![feature(negative_impls)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue