@@ -1734,6 +1734,60 @@ macro_rules! uint_impl {
17341734 }
17351735 }
17361736
1737+ /// Exact shift left. Computes `self << rhs`, returning `None` if any non-zero bits would be
1738+ /// shifted out or if `rhs` >=
1739+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1740+ ///
1741+ /// # Examples
1742+ ///
1743+ /// ```
1744+ /// #![feature(exact_bitshifts)]
1745+ ///
1746+ #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(4), Some(0x10));" ) ]
1747+ #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(129), None);" ) ]
1748+ /// ```
1749+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1750+ #[ must_use = "this returns the result of the operation, \
1751+ without modifying the original"]
1752+ #[ inline]
1753+ pub fn exact_shl( self , rhs: u32 ) -> Option <$SelfT> {
1754+ if rhs <= self . leading_zeros( ) . max( <$SelfT>:: BITS - 1 ) {
1755+ // SAFETY: rhs is checked above
1756+ Some ( unsafe { self . unchecked_shl( rhs) } )
1757+ } else {
1758+ None
1759+ }
1760+ }
1761+
1762+ /// Unchecked exact shift left. Computes `self << rhs`, assuming non-zero bits cannot be
1763+ /// shifted out and `rhs` cannot be larger than
1764+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1765+ ///
1766+ /// # Safety
1767+ ///
1768+ /// This results in undefined behavior when `rhs > self.leading_zeros() || rhs >=
1769+ #[ doc = concat!( stringify!( $SelfT) , "::BITS`" ) ]
1770+ /// i.e. when
1771+ #[ doc = concat!( "[`" , stringify!( $SelfT) , "::exact_shl`]" ) ]
1772+ /// would return `None`.
1773+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1774+ #[ must_use = "this returns the result of the operation, \
1775+ without modifying the original"]
1776+ #[ inline]
1777+ pub unsafe fn exact_shl_unchecked( self , rhs: u32 ) -> $SelfT {
1778+ assert_unsafe_precondition!(
1779+ check_language_ub,
1780+ concat!( stringify!( $SelfT) , "::exact_shl_unchecked cannot shift out non-zero bits" ) ,
1781+ (
1782+ len: u32 = self . leading_zeros( ) . max( <$SelfT>:: BITS - 1 ) ,
1783+ rhs: u32 = rhs,
1784+ ) => rhs <= len,
1785+ ) ;
1786+
1787+ // SAFETY: this is guaranteed to be safe by the caller
1788+ unsafe { self . unchecked_shl( rhs) }
1789+ }
1790+
17371791 /// Checked shift right. Computes `self >> rhs`, returning `None`
17381792 /// if `rhs` is larger than or equal to the number of bits in `self`.
17391793 ///
@@ -1849,6 +1903,60 @@ macro_rules! uint_impl {
18491903 }
18501904 }
18511905
1906+ /// Exact shift right. Computes `self >> rhs`, returning `None` if any non-zero bits would be
1907+ /// shifted out or if `rhs` >=
1908+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1909+ ///
1910+ /// # Examples
1911+ ///
1912+ /// ```
1913+ /// #![feature(exact_bitshifts)]
1914+ ///
1915+ #[ doc = concat!( "assert_eq!(0x10" , stringify!( $SelfT) , ".exact_shr(4), Some(0x1));" ) ]
1916+ #[ doc = concat!( "assert_eq!(0x10" , stringify!( $SelfT) , ".exact_shr(129), None);" ) ]
1917+ /// ```
1918+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1919+ #[ must_use = "this returns the result of the operation, \
1920+ without modifying the original"]
1921+ #[ inline]
1922+ pub fn exact_shr( self , rhs: u32 ) -> Option <$SelfT> {
1923+ if rhs <= self . trailing_zeros( ) . max( <$SelfT>:: BITS - 1 ) {
1924+ // SAFETY: rhs is checked above
1925+ Some ( unsafe { self . unchecked_shr( rhs) } )
1926+ } else {
1927+ None
1928+ }
1929+ }
1930+
1931+ /// Unchecked exact shift right. Computes `self >> rhs`, assuming non-zero bits cannot be
1932+ /// shifted out and `rhs` cannot be larger than
1933+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1934+ ///
1935+ /// # Safety
1936+ ///
1937+ /// This results in undefined behavior when `rhs > self.trailing_zeros() || rhs >=
1938+ #[ doc = concat!( stringify!( $SelfT) , "::BITS`" ) ]
1939+ /// i.e. when
1940+ #[ doc = concat!( "[`" , stringify!( $SelfT) , "::exact_shr`]" ) ]
1941+ /// would return `None`.
1942+ #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
1943+ #[ must_use = "this returns the result of the operation, \
1944+ without modifying the original"]
1945+ #[ inline]
1946+ pub unsafe fn exact_shr_unchecked( self , rhs: u32 ) -> $SelfT {
1947+ assert_unsafe_precondition!(
1948+ check_language_ub,
1949+ concat!( stringify!( $SelfT) , "::exact_shr_unchecked cannot shift out non-zero bits" ) ,
1950+ (
1951+ len: u32 = self . trailing_zeros( ) . max( <$SelfT>:: BITS - 1 ) ,
1952+ rhs: u32 = rhs,
1953+ ) => rhs <= len,
1954+ ) ;
1955+
1956+ // SAFETY: this is guaranteed to be safe by the caller
1957+ unsafe { self . unchecked_shr( rhs) }
1958+ }
1959+
18521960 /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
18531961 /// overflow occurred.
18541962 ///
0 commit comments