Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
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 Down
190 changes: 190 additions & 0 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
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
16 changes: 8 additions & 8 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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]",
Expand All @@ -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, \
Expand All @@ -816,15 +816,15 @@ 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!() }
}
#[cfg(target_pointer_width = "32")]
#[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!() }
}
Expand All @@ -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]",
Expand Down
Loading