@@ -1705,6 +1705,60 @@ macro_rules! uint_impl {
17051705 }
17061706 }
17071707
1708+ /// Exact shift left. Computes `self << rhs`, returning `None` if any non-zero bits would be
1709+ /// shifted out or if `rhs` >=
1710+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1711+ ///
1712+ /// # Examples
1713+ ///
1714+ /// ```
1715+ /// #![feature(exact_bitshifts)]
1716+ ///
1717+ #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(4), Some(0x10));" ) ]
1718+ #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(129), None);" ) ]
1719+ /// ```
1720+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1721+ #[ must_use = "this returns the result of the operation, \
1722+ without modifying the original"]
1723+ #[ inline]
1724+ pub fn exact_shl( self , rhs: u32 ) -> Option <$SelfT> {
1725+ if rhs <= self . leading_zeros( ) . max( <$SelfT>:: BITS - 1 ) {
1726+ // SAFETY: rhs is checked above
1727+ Some ( unsafe { self . unchecked_shl( rhs) } )
1728+ } else {
1729+ None
1730+ }
1731+ }
1732+
1733+ /// Unchecked exact shift left. Computes `self << rhs`, assuming non-zero bits cannot be
1734+ /// shifted out and `rhs` cannot be larger than
1735+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1736+ ///
1737+ /// # Safety
1738+ ///
1739+ /// This results in undefined behavior when `rhs > self.leading_zeros() || rhs >=
1740+ #[ doc = concat!( stringify!( $SelfT) , "::BITS`" ) ]
1741+ /// i.e. when
1742+ #[ doc = concat!( "[`" , stringify!( $SelfT) , "::exact_shl`]" ) ]
1743+ /// would return `None`.
1744+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1745+ #[ must_use = "this returns the result of the operation, \
1746+ without modifying the original"]
1747+ #[ inline]
1748+ pub unsafe fn exact_shl_unchecked( self , rhs: u32 ) -> $SelfT {
1749+ assert_unsafe_precondition!(
1750+ check_language_ub,
1751+ concat!( stringify!( $SelfT) , "::exact_shl_unchecked cannot shift out non-zero bits" ) ,
1752+ (
1753+ len: u32 = self . leading_zeros( ) . max( <$SelfT>:: BITS - 1 ) ,
1754+ rhs: u32 = rhs,
1755+ ) => rhs <= len,
1756+ ) ;
1757+
1758+ // SAFETY: this is guaranteed to be safe by the caller
1759+ unsafe { self . unchecked_shl( rhs) }
1760+ }
1761+
17081762 /// Checked shift right. Computes `self >> rhs`, returning `None`
17091763 /// if `rhs` is larger than or equal to the number of bits in `self`.
17101764 ///
@@ -1821,6 +1875,60 @@ macro_rules! uint_impl {
18211875 }
18221876 }
18231877
1878+ /// Exact shift right. Computes `self >> rhs`, returning `None` if any non-zero bits would be
1879+ /// shifted out or if `rhs` >=
1880+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1881+ ///
1882+ /// # Examples
1883+ ///
1884+ /// ```
1885+ /// #![feature(exact_bitshifts)]
1886+ ///
1887+ #[ doc = concat!( "assert_eq!(0x10" , stringify!( $SelfT) , ".exact_shr(4), Some(0x1));" ) ]
1888+ #[ doc = concat!( "assert_eq!(0x10" , stringify!( $SelfT) , ".exact_shr(129), None);" ) ]
1889+ /// ```
1890+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1891+ #[ must_use = "this returns the result of the operation, \
1892+ without modifying the original"]
1893+ #[ inline]
1894+ pub fn exact_shr( self , rhs: u32 ) -> Option <$SelfT> {
1895+ if rhs <= self . trailing_zeros( ) . max( <$SelfT>:: BITS - 1 ) {
1896+ // SAFETY: rhs is checked above
1897+ Some ( unsafe { self . unchecked_shr( rhs) } )
1898+ } else {
1899+ None
1900+ }
1901+ }
1902+
1903+ /// Unchecked exact shift right. Computes `self >> rhs`, assuming non-zero bits cannot be
1904+ /// shifted out and `rhs` cannot be larger than
1905+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1906+ ///
1907+ /// # Safety
1908+ ///
1909+ /// This results in undefined behavior when `rhs > self.trailing_zeros() || rhs >=
1910+ #[ doc = concat!( stringify!( $SelfT) , "::BITS`" ) ]
1911+ /// i.e. when
1912+ #[ doc = concat!( "[`" , stringify!( $SelfT) , "::exact_shr`]" ) ]
1913+ /// would return `None`.
1914+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1915+ #[ must_use = "this returns the result of the operation, \
1916+ without modifying the original"]
1917+ #[ inline]
1918+ pub unsafe fn exact_shr_unchecked( self , rhs: u32 ) -> $SelfT {
1919+ assert_unsafe_precondition!(
1920+ check_language_ub,
1921+ concat!( stringify!( $SelfT) , "::exact_shr_unchecked cannot shift out non-zero bits" ) ,
1922+ (
1923+ len: u32 = self . trailing_zeros( ) . max( <$SelfT>:: BITS - 1 ) ,
1924+ rhs: u32 = rhs,
1925+ ) => rhs <= len,
1926+ ) ;
1927+
1928+ // SAFETY: this is guaranteed to be safe by the caller
1929+ unsafe { self . unchecked_shr( rhs) }
1930+ }
1931+
18241932 /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
18251933 /// overflow occurred.
18261934 ///
0 commit comments