1515use convert:: TryFrom ;
1616use fmt;
1717use intrinsics;
18- use mem:: size_of;
1918use str:: FromStr ;
2019
2120/// Provides intentionally-wrapped arithmetic on `T`.
@@ -2176,8 +2175,32 @@ macro_rules! uint_impl {
21762175 ( self . wrapping_sub( 1 ) ) & self == 0 && !( self == 0 )
21772176 }
21782177
2178+ // Returns one less than next power of two.
2179+ // (For 8u8 next power of two is 8u8 and for 6u8 it is 8u8)
2180+ //
2181+ // 8u8.one_less_than_next_power_of_two() == 7
2182+ // 6u8.one_less_than_next_power_of_two() == 7
2183+ //
2184+ // This method cannot overflow, as in the `next_power_of_two`
2185+ // overflow cases it instead ends up returning the maximum value
2186+ // of the type, and can return 0 for 0.
2187+ fn one_less_than_next_power_of_two( self ) -> Self {
2188+ if self <= 1 { return 0 ; }
2189+
2190+ // Because `p > 0`, it cannot consist entirely of leading zeros.
2191+ // That means the shift is always in-bounds, and some processors
2192+ // (such as intel pre-haswell) have more efficient ctlz
2193+ // intrinsics when the argument is non-zero.
2194+ let p = self - 1 ;
2195+ let z = p. leading_zeros( ) ;
2196+ <$SelfT>:: max_value( ) >> z
2197+ }
2198+
21792199 /// Returns the smallest power of two greater than or equal to `self`.
2180- /// Unspecified behavior on overflow.
2200+ ///
2201+ /// When return value overflows (i.e. `self > (1 << (N-1))` for type
2202+ /// `uN`), it panics in debug mode and return value is wrapped to 0 in
2203+ /// release mode (the only situation in which method can return 0).
21812204 ///
21822205 /// # Examples
21832206 ///
@@ -2190,9 +2213,7 @@ macro_rules! uint_impl {
21902213 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
21912214 #[ inline]
21922215 pub fn next_power_of_two( self ) -> Self {
2193- let bits = size_of:: <Self >( ) * 8 ;
2194- let one: Self = 1 ;
2195- one << ( ( bits - self . wrapping_sub( one) . leading_zeros( ) as usize ) % bits)
2216+ self . one_less_than_next_power_of_two( ) + 1
21962217 }
21972218
21982219 /// Returns the smallest power of two greater than or equal to `n`. If
@@ -2210,12 +2231,7 @@ macro_rules! uint_impl {
22102231 /// ```
22112232 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
22122233 pub fn checked_next_power_of_two( self ) -> Option <Self > {
2213- let npot = self . next_power_of_two( ) ;
2214- if npot >= self {
2215- Some ( npot)
2216- } else {
2217- None
2218- }
2234+ self . one_less_than_next_power_of_two( ) . checked_add( 1 )
22192235 }
22202236 }
22212237}
0 commit comments