Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add implementations for unbounded_shl/unbounded_shr #129377

Merged
merged 8 commits into from
Aug 26, 2024
60 changes: 60 additions & 0 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,33 @@ macro_rules! int_impl {
}
}

/// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`
///
/// If `rhs` is larger or equal to the number of bits in `self`,
/// the entire value is shifted out, and `0` is returned.
///
/// # Examples
///
/// Basic usage:
/// ```
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")]
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")]
/// ```
#[unstable(feature = "unbounded_shifts", issue = "129375")]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{
if rhs < Self::BITS {
// SAFETY:
// rhs is just checked to be in-range above
unsafe { self.unchecked_shl(rhs) }
} else {
0
}
}

/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
/// larger than or equal to the number of bits in `self`.
///
Expand Down Expand Up @@ -1410,6 +1437,39 @@ macro_rules! int_impl {
}
}

/// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`
///
/// If `rhs` is larger or equal to the number of bits in `self`,
/// the entire value is shifted out, which yields `0` for a positive number,
/// and `-1` for a negative number.
///
/// # Examples
///
/// Basic usage:
/// ```
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shl(4), 0x1);")]
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.unbounded_shr(129), -1);")]
/// ```
#[unstable(feature = "unbounded_shifts", issue = "129375")]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{
if rhs < Self::BITS {
// SAFETY:
// rhs is just checked to be in-range above
unsafe { self.unchecked_shr(rhs) }
} else {
// A shift by `Self::BITS-1` suffices for signed integers, because the sign bit is copied for each of the shifted bits.

// SAFETY:
// `Self::BITS-1` is guaranteed to be less than `Self::BITS`
unsafe { self.unchecked_shr(Self::BITS - 1) }
}
}

/// Checked absolute value. Computes `self.abs()`, returning `None` if
/// `self == MIN`.
///
Expand Down
54 changes: 54 additions & 0 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,33 @@ macro_rules! uint_impl {
}
}

/// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`
///
/// If `rhs` is larger or equal to the number of bits in `self`,
/// the entire value is shifted out, and `0` is returned.
///
/// # Examples
///
/// Basic usage:
/// ```
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")]
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")]
/// ```
#[unstable(feature = "unbounded_shifts", issue = "129375")]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
chorman0773 marked this conversation as resolved.
Show resolved Hide resolved
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{
if rhs < Self::BITS {
// SAFETY:
// rhs is just checked to be in-range above
unsafe { self.unchecked_shl(rhs) }
} else {
0
}
}

/// Checked shift right. Computes `self >> rhs`, returning `None`
/// if `rhs` is larger than or equal to the number of bits in `self`.
///
Expand Down Expand Up @@ -1599,6 +1626,33 @@ macro_rules! uint_impl {
}
}

/// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`
///
/// If `rhs` is larger or equal to the number of bits in `self`,
/// the entire value is shifted out, and `0` is returned.
///
/// # Examples
///
/// Basic usage:
/// ```
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x10);")]
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")]
/// ```
#[unstable(feature = "unbounded_shifts", issue = "129375")]
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{
if rhs < Self::BITS {
// SAFETY:
// rhs is just checked to be in-range above
unsafe { self.unchecked_shr(rhs) }
} else {
0
}
}

/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
/// overflow occurred.
///
Expand Down
Loading