@@ -1413,32 +1413,40 @@ macro_rules! int_impl {
14131413 }
14141414 }
14151415
1416- /// Exact shift left. Computes `self << rhs`, returning `None` if any bits disagreeing with
1417- /// the resulting sign bit would be shifted out.
1416+ /// Exact shift left. Computes `self << rhs` as long as it can be reversed losslessly.
1417+ ///
1418+ /// Returns `None` if any bits that would be shifted out differ from the resulting sign bit
1419+ /// or if `rhs` >=
1420+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1421+ /// Otherwise, returns `Some(self << rhs)`.
14181422 ///
14191423 /// # Examples
14201424 ///
14211425 /// ```
14221426 /// #![feature(exact_bitshifts)]
14231427 ///
14241428 #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(4), Some(0x10));" ) ]
1425- #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(129), None);" ) ]
1429+ #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(" , stringify!( $SelfT) , "::BITS - 2), Some(1 << " , stringify!( $SelfT) , "::BITS - 2));" ) ]
1430+ #[ doc = concat!( "assert_eq!(0x1" , stringify!( $SelfT) , ".exact_shl(" , stringify!( $SelfT) , "::BITS - 1), None);" ) ]
1431+ #[ doc = concat!( "assert_eq!((-0x2" , stringify!( $SelfT) , ").exact_shl(" , stringify!( $SelfT) , "::BITS - 2), Some(-0x2 << " , stringify!( $SelfT) , "::BITS - 2));" ) ]
1432+ #[ doc = concat!( "assert_eq!((-0x2" , stringify!( $SelfT) , ").exact_shl(" , stringify!( $SelfT) , "::BITS - 1), None);" ) ]
14261433 /// ```
14271434 #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
14281435 #[ must_use = "this returns the result of the operation, \
14291436 without modifying the original"]
14301437 #[ inline]
1431- pub fn exact_shl( self , rhs: u32 ) -> Option <$SelfT> {
1432- if rhs < self . leading_zeros( ) . max ( self . leading_ones( ) ) {
1438+ pub const fn exact_shl( self , rhs: u32 ) -> Option <$SelfT> {
1439+ if rhs < self . leading_zeros( ) || rhs < self . leading_ones( ) {
14331440 // SAFETY: rhs is checked above
14341441 Some ( unsafe { self . unchecked_shl( rhs) } )
14351442 } else {
14361443 None
14371444 }
14381445 }
14391446
1440- /// Unchecked exact shift left. Computes `self << rhs`, assuming bits disagreeing with the
1441- /// resulting sign bit cannot be shifted out.
1447+ /// Unchecked exact shift left. Computes `self << rhs`, assuming the operation can be
1448+ /// losslessly reversed and `rhs` cannot be larger than
1449+ #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
14421450 ///
14431451 /// # Safety
14441452 ///
@@ -1450,14 +1458,15 @@ macro_rules! int_impl {
14501458 #[ must_use = "this returns the result of the operation, \
14511459 without modifying the original"]
14521460 #[ inline]
1453- pub unsafe fn exact_shl_unchecked ( self , rhs: u32 ) -> $SelfT {
1461+ pub const unsafe fn unchecked_exact_shl ( self , rhs: u32 ) -> $SelfT {
14541462 assert_unsafe_precondition!(
14551463 check_language_ub,
1456- concat!( stringify!( $SelfT) , "::exact_shl_unchecked cannot shift out non-zero bits" ) ,
1464+ concat!( stringify!( $SelfT) , "::unchecked_exact_shl cannot shift out non-zero bits" ) ,
14571465 (
1458- len: u32 = self . leading_zeros( ) . max( self . leading_ones( ) ) ,
1466+ zeros: u32 = self . leading_zeros( ) ,
1467+ ones: u32 = self . leading_ones( ) ,
14591468 rhs: u32 = rhs,
1460- ) => rhs < len ,
1469+ ) => rhs < zeros || rhs < ones ,
14611470 ) ;
14621471
14631472 // SAFETY: this is guaranteed to be safe by the caller
@@ -1585,33 +1594,35 @@ macro_rules! int_impl {
15851594 }
15861595 }
15871596
1588- /// Exact shift right. Computes `self >> rhs`, returning `None` if any non-zero bits would be
1589- /// shifted out or if `rhs` >=
1597+ /// Exact shift right. Computes `self >> rhs` as long as it can be reversed losslessly.
1598+ ///
1599+ /// Returns `None` if any non-zero bits would be shifted out or if `rhs` >=
15901600 #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
1601+ /// Otherwise, returns `Some(self >> rhs)`.
15911602 ///
15921603 /// # Examples
15931604 ///
15941605 /// ```
15951606 /// #![feature(exact_bitshifts)]
15961607 ///
15971608 #[ doc = concat!( "assert_eq!(0x10" , stringify!( $SelfT) , ".exact_shr(4), Some(0x1));" ) ]
1598- #[ doc = concat!( "assert_eq!(0x10" , stringify!( $SelfT) , ".exact_shr(129 ), None);" ) ]
1609+ #[ doc = concat!( "assert_eq!(0x10" , stringify!( $SelfT) , ".exact_shr(5 ), None);" ) ]
15991610 /// ```
16001611 #[ unstable( feature = "exact_bitshifts" , issue = "144336" ) ]
16011612 #[ must_use = "this returns the result of the operation, \
16021613 without modifying the original"]
16031614 #[ inline]
1604- pub fn exact_shr( self , rhs: u32 ) -> Option <$SelfT> {
1605- if rhs <= self . trailing_zeros( ) . max ( < $SelfT>:: BITS - 1 ) {
1615+ pub const fn exact_shr( self , rhs: u32 ) -> Option <$SelfT> {
1616+ if rhs <= self . trailing_zeros( ) && rhs < < $SelfT>:: BITS {
16061617 // SAFETY: rhs is checked above
16071618 Some ( unsafe { self . unchecked_shr( rhs) } )
16081619 } else {
16091620 None
16101621 }
16111622 }
16121623
1613- /// Unchecked exact shift right. Computes `self >> rhs`, assuming non-zero bits cannot be
1614- /// shifted out and `rhs` cannot be larger than
1624+ /// Unchecked exact shift right. Computes `self >> rhs`, assuming the operation can be
1625+ /// losslessly reversed and `rhs` cannot be larger than
16151626 #[ doc = concat!( "`" , stringify!( $SelfT) , "::BITS`." ) ]
16161627 ///
16171628 /// # Safety
@@ -1625,14 +1636,15 @@ macro_rules! int_impl {
16251636 #[ must_use = "this returns the result of the operation, \
16261637 without modifying the original"]
16271638 #[ inline]
1628- pub unsafe fn exact_shr_unchecked ( self , rhs: u32 ) -> $SelfT {
1639+ pub const unsafe fn unchecked_exact_shr ( self , rhs: u32 ) -> $SelfT {
16291640 assert_unsafe_precondition!(
16301641 check_language_ub,
1631- concat!( stringify!( $SelfT) , "::exact_shr_unchecked cannot shift out non-zero bits" ) ,
1642+ concat!( stringify!( $SelfT) , "::unchecked_exact_shr cannot shift out non-zero bits" ) ,
16321643 (
1633- len: u32 = self . trailing_zeros( ) . max( <$SelfT>:: BITS - 1 ) ,
1644+ zeros: u32 = self . trailing_zeros( ) ,
1645+ bits: u32 = <$SelfT>:: BITS ,
16341646 rhs: u32 = rhs,
1635- ) => rhs <= len ,
1647+ ) => rhs <= zeros && rhs < bits ,
16361648 ) ;
16371649
16381650 // SAFETY: this is guaranteed to be safe by the caller
0 commit comments