diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 17cf2a7b261fd..229cd89bea3f0 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1312,6 +1312,34 @@ 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: + /// ``` + /// #![feature(unbounded_shifts)] + #[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_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[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`. /// @@ -1410,6 +1438,40 @@ 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: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(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_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[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`. /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 719a6a55940dc..0d0bbc5256f78 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1501,6 +1501,34 @@ 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: + /// ``` + /// #![feature(unbounded_shifts)] + #[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_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[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`. /// @@ -1599,6 +1627,34 @@ 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: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[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. ///