15
15
use convert:: TryFrom ;
16
16
use fmt;
17
17
use intrinsics;
18
- use mem:: size_of;
19
18
use str:: FromStr ;
20
19
21
20
/// Provides intentionally-wrapped arithmetic on `T`.
@@ -2176,8 +2175,32 @@ macro_rules! uint_impl {
2176
2175
( self . wrapping_sub( 1 ) ) & self == 0 && !( self == 0 )
2177
2176
}
2178
2177
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
+
2179
2199
/// 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).
2181
2204
///
2182
2205
/// # Examples
2183
2206
///
@@ -2190,9 +2213,7 @@ macro_rules! uint_impl {
2190
2213
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2191
2214
#[ inline]
2192
2215
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
2196
2217
}
2197
2218
2198
2219
/// Returns the smallest power of two greater than or equal to `n`. If
@@ -2210,12 +2231,7 @@ macro_rules! uint_impl {
2210
2231
/// ```
2211
2232
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2212
2233
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 )
2219
2235
}
2220
2236
}
2221
2237
}
0 commit comments