Skip to content

Commit

Permalink
Add methods to add/sub uX to/from iX
Browse files Browse the repository at this point in the history
  • Loading branch information
a1phyr committed Oct 1, 2021
1 parent b5dd522 commit 9faf621
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 14 deletions.
2 changes: 1 addition & 1 deletion library/core/src/lib.rs
Expand Up @@ -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)]
Expand All @@ -159,7 +160,6 @@
#![feature(trait_alias)]
#![feature(transparent_unions)]
#![feature(try_blocks)]
#![feature(uint_add_signed)]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
//
Expand Down
190 changes: 190 additions & 0 deletions library/core/src/num/int_macros.rs
Expand Up @@ -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.
///
Expand Down Expand Up @@ -479,6 +501,28 @@ macro_rules! int_impl {
unsafe { intrinsics::unchecked_sub(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_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.
///
Expand Down Expand Up @@ -822,6 +866,31 @@ 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
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.
///
Expand All @@ -843,6 +912,31 @@ macro_rules! int_impl {
intrinsics::saturating_sub(self, rhs)
}

/// Saturating substraction 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
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.
///
Expand Down Expand Up @@ -998,6 +1092,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.
///
Expand All @@ -1018,6 +1133,27 @@ macro_rules! int_impl {
intrinsics::wrapping_sub(self, rhs)
}

/// Wrapping (modular) substraction 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.
///
Expand Down Expand Up @@ -1368,6 +1504,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
Expand Down Expand Up @@ -1419,6 +1582,33 @@ macro_rules! int_impl {
(sum as $SelfT, borrow)
}

/// Calculates `self` - `rhs` with an unsigned `rhs`
///
/// Returns a tuple of the substraction 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
Expand Down
24 changes: 12 additions & 12 deletions library/core/src/num/uint_macros.rs
Expand Up @@ -450,13 +450,13 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(uint_add_signed)]
/// # #![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 = "uint_add_signed", issue = "none")]
#[rustc_const_unstable(feature = "uint_add_signed", issue = "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]
Expand Down Expand Up @@ -1026,13 +1026,13 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(uint_add_signed)]
/// # #![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 = "uint_add_signed", issue = "none")]
#[rustc_const_unstable(feature = "uint_add_signed", issue = "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]
Expand Down Expand Up @@ -1168,13 +1168,13 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(uint_add_signed)]
/// # #![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 = "uint_add_signed", issue = "none")]
#[rustc_const_unstable(feature = "uint_add_signed", issue = "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]
Expand Down Expand Up @@ -1517,13 +1517,13 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(uint_add_signed)]
/// # #![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 = "uint_add_signed", issue = "none")]
#[rustc_const_unstable(feature = "uint_add_signed", issue = "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]
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/lib.rs
Expand Up @@ -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)]
Expand Down Expand Up @@ -333,7 +334,6 @@
#![feature(try_blocks)]
#![feature(try_reserve)]
#![feature(try_reserve_kind)]
#![feature(uint_add_signed)]
#![feature(unboxed_closures)]
#![feature(unwrap_infallible)]
#![feature(vec_into_raw_parts)]
Expand Down

0 comments on commit 9faf621

Please sign in to comment.