@@ -989,7 +989,7 @@ macro_rules! int_impl {
989
989
intrinsics:: saturating_sub( 0 , self )
990
990
}
991
991
992
- /// Panic-free bitwise shift-left; yields `0` where the shift exceeds the bitwidth of the type .
992
+ /// Panic-free bitwise shift-left; saturates to `MIN` or `MAX` instead of wrapping around .
993
993
///
994
994
/// Note that this is *not* the same as a rotate-left; the RHS of a saturating shift-left is restricted to
995
995
/// the range of the type, rather than the bits shifted out of the LHS being returned to the other end.
@@ -1002,19 +1002,34 @@ macro_rules! int_impl {
1002
1002
///
1003
1003
/// ```
1004
1004
/// #![feature(saturating_bit_shifts)]
1005
- #[ doc = concat!( "assert_eq!(0b0000_0001_u8.saturating_shl(u8::BITS - 1), 0b1000_0000_u8);" ) ]
1006
- #[ doc = concat!( "assert_eq!(0b0000_0001_u8.saturating_shl(u8::BITS), 0b0000_0000_u8);" ) ]
1005
+ #[ doc = concat!( "assert_eq!(1_" , stringify!( $SelfT) , ".saturating_shl(" , stringify!( $SelfT) , "::BITS - 2), 1_" , stringify!( $SelfT) , " << " , stringify!( $SelfT) , "::BITS - 2);" ) ]
1006
+ #[ doc = concat!( "assert_eq!(1_" , stringify!( $SelfT) , ".saturating_shl(" , stringify!( $SelfT) , "::BITS - 1), " , stringify!( $SelfT) , "::MAX);" ) ]
1007
+ #[ doc = concat!( "assert_eq!(-1_" , stringify!( $SelfT) , ".saturating_shl(" , stringify!( $SelfT) , "::BITS - 2), -1_" , stringify!( $SelfT) , " << " , stringify!( $SelfT) , "::BITS - 2);" ) ]
1008
+ #[ doc = concat!( "assert_eq!(-1_" , stringify!( $SelfT) , ".saturating_shl(" , stringify!( $SelfT) , "::BITS - 1), " , stringify!( $SelfT) , "::MIN);" ) ]
1009
+ #[ doc = concat!( "assert_eq!(-1_" , stringify!( $SelfT) , ".saturating_shl(" , stringify!( $SelfT) , "::BITS), " , stringify!( $SelfT) , "::MIN);" ) ]
1007
1010
/// ```
1008
1011
#[ unstable( feature = "saturating_bit_shifts" , issue = "103440" ) ]
1009
1012
#[ rustc_const_unstable( feature = "saturating_bit_shifts" , issue = "103440" ) ]
1010
1013
#[ must_use = "this returns the result of the operation, \
1011
1014
without modifying the original"]
1012
1015
#[ inline( always) ]
1013
1016
pub const fn saturating_shl( self , rhs: u32 ) -> Self {
1014
- if rhs >= <$SelfT> :: BITS {
1015
- 0
1017
+ if rhs == 0 {
1018
+ self
1016
1019
} else {
1017
- self << rhs
1020
+ // leading zeros ignoring first bit (which indicates negative values)
1021
+ let leading_zeros = ( self << 1 ) . leading_zeros( ) ;
1022
+ let leading_ones = ( self << 1 ) . leading_ones( ) ;
1023
+
1024
+ // would overflow => MIN / MAX depending on whether the value is negative or not
1025
+ if self >= 0 && leading_zeros < rhs {
1026
+ <$SelfT>:: MAX
1027
+ } else if self < 0 && leading_ones < rhs {
1028
+ <$SelfT>:: MIN
1029
+ } else {
1030
+ // normal shift left
1031
+ self << rhs
1032
+ }
1018
1033
}
1019
1034
}
1020
1035
0 commit comments