diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 17cf2a7b261..0ec178448e4 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -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, v: u32) -> $SelfT{ + if v < Self::BITS{ + // SAFETY: + // v is just checked to be in-range above + unsafe{self.unchecked_shl(v)} + }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 +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, v: u32) -> $SelfT{ + if v < Self::BITS{ + // SAFETY: + // v is just checked to be in-range above + unsafe{self.unchecked_shr(v)} + }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 719a6a55940..5a2f1876ca2 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -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)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shl(self, v: u32) -> $SelfT{ + if v < Self::BITS{ + // SAFETY: + // v is just checked to be in-range above + unsafe{self.unchecked_shl(v)} + }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 +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, v: u32) -> $SelfT{ + if v < Self::BITS{ + // SAFETY: + // v is just checked to be in-range above + unsafe{self.unchecked_shr(v)} + }else{ + 0 + } + } + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if /// overflow occurred. ///