Add functions to add unsigned and signed integers

This commit is contained in:
Benoît du Garreau 2021-07-29 19:39:56 +02:00
parent ed937594d3
commit fe11483afa
5 changed files with 112 additions and 15 deletions

View file

@ -159,6 +159,7 @@
#![feature(trait_alias)] #![feature(trait_alias)]
#![feature(transparent_unions)] #![feature(transparent_unions)]
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(uint_add_signed)]
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(unsized_fn_params)] #![feature(unsized_fn_params)]
// //

View file

@ -245,7 +245,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000;
#[lang = "u8"] #[lang = "u8"]
impl u8 { impl u8 {
widening_impl! { u8, u16, 8 } 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]", "", "" } "[0x12]", "", "" }
/// Checks if the value is within the ASCII range. /// Checks if the value is within the ASCII range.
@ -779,21 +779,21 @@ impl u8 {
#[lang = "u16"] #[lang = "u16"]
impl u16 { impl u16 {
widening_impl! { u16, u32, 16 } 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]", "", "" } "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
} }
#[lang = "u32"] #[lang = "u32"]
impl u32 { impl u32 {
widening_impl! { u32, u64, 32 } 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]", "", "" } "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
} }
#[lang = "u64"] #[lang = "u64"]
impl u64 { impl u64 {
widening_impl! { u64, u128, 64 } 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", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
@ -802,7 +802,7 @@ impl u64 {
#[lang = "u128"] #[lang = "u128"]
impl u128 { impl u128 {
uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, 16, uint_impl! { u128, u128, i128, 128, 340282366920938463463374607431768211455, 16,
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
"0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
"[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
@ -816,7 +816,7 @@ impl u128 {
#[lang = "usize"] #[lang = "usize"]
impl usize { impl usize {
widening_impl! { usize, u32, 16 } 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]", "[0x34, 0x12]", "[0x12, 0x34]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
} }
@ -824,7 +824,7 @@ impl usize {
#[lang = "usize"] #[lang = "usize"]
impl usize { impl usize {
widening_impl! { usize, u64, 32 } 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]", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
} }
@ -833,7 +833,7 @@ impl usize {
#[lang = "usize"] #[lang = "usize"]
impl usize { impl usize {
widening_impl! { usize, u128, 64 } 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", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",

View file

@ -1,5 +1,5 @@
macro_rules! uint_impl { 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, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
$reversed:expr, $le_bytes:expr, $be_bytes:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr,
$to_xe_bytes_doc:expr, $from_xe_bytes_doc: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) } unsafe { intrinsics::unchecked_add(self, rhs) }
} }
/// Checked addition with a signed integer. Computes `self + rhs`,
/// returning `None` if overflow occurred.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(uint_add_signed)]
#[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(3), None);")]
/// ```
#[unstable(feature = "uint_add_signed", issue = "none")]
#[rustc_const_unstable(feature = "uint_add_signed", issue = "none")]
#[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 /// Checked integer subtraction. Computes `self - rhs`, returning
/// `None` if overflow occurred. /// `None` if overflow occurred.
/// ///
@ -995,6 +1018,32 @@ macro_rules! uint_impl {
intrinsics::saturating_add(self, rhs) 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(uint_add_signed)]
#[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")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn saturating_add_signed(self, rhs: $SignedT) -> Self {
if rhs >= 0 {
self.saturating_add(rhs as Self)
} else {
self.saturating_sub(rhs.unsigned_abs())
}
}
/// Saturating integer subtraction. Computes `self - rhs`, saturating /// Saturating integer subtraction. Computes `self - rhs`, saturating
/// at the numeric bounds instead of overflowing. /// at the numeric bounds instead of overflowing.
/// ///
@ -1111,6 +1160,28 @@ macro_rules! uint_impl {
intrinsics::wrapping_add(self, rhs) 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(uint_add_signed)]
#[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")]
#[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 (modular) subtraction. Computes `self - rhs`,
/// wrapping around at the boundary of the type. /// wrapping around at the boundary of the type.
/// ///
@ -1435,6 +1506,35 @@ macro_rules! uint_impl {
(c, b | d) (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(uint_add_signed)]
#[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")]
#[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) {
if rhs >= 0 {
self.overflowing_add(rhs as Self)
} else {
self.overflowing_sub(rhs.unsigned_abs())
}
}
/// Calculates `self` - `rhs` /// Calculates `self` - `rhs`
/// ///
/// Returns a tuple of the subtraction along with a boolean indicating /// Returns a tuple of the subtraction along with a boolean indicating

View file

@ -292,12 +292,7 @@ where
SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
SeekFrom::Current(n) => (self.pos, n), SeekFrom::Current(n) => (self.pos, n),
}; };
let new_pos = if offset >= 0 { match base_pos.checked_add_signed(offset) {
base_pos.checked_add(offset as u64)
} else {
base_pos.checked_sub((offset.wrapping_neg()) as u64)
};
match new_pos {
Some(n) => { Some(n) => {
self.pos = n; self.pos = n;
Ok(self.pos) Ok(self.pos)

View file

@ -333,6 +333,7 @@
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(try_reserve)] #![feature(try_reserve)]
#![feature(try_reserve_kind)] #![feature(try_reserve_kind)]
#![feature(uint_add_signed)]
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(unwrap_infallible)] #![feature(unwrap_infallible)]
#![feature(vec_into_raw_parts)] #![feature(vec_into_raw_parts)]