Skip to content

Commit 18fadb6

Browse files
committed
Simplify helper functions
Based on @scottmcm 's suggestion
1 parent 93219a2 commit 18fadb6

File tree

2 files changed

+17
-16
lines changed

2 files changed

+17
-16
lines changed

src/libcore/num/mod.rs

+13-15
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use convert::TryFrom;
1616
use fmt;
1717
use intrinsics;
18-
use mem::size_of;
1918
use str::FromStr;
2019

2120
/// Provides intentionally-wrapped arithmetic on `T`.
@@ -2327,26 +2326,25 @@ macro_rules! uint_impl {
23272326
(self.wrapping_sub(1)) & self == 0 && !(self == 0)
23282327
}
23292328

2330-
// Returns one less than next greater power of two.
2331-
// (For 8u8 next greater power of two is 16u8 and for 6u8 it is 8u8)
2332-
//
2333-
// 8u8.round_up_to_one_less_than_a_power_of_two() == 15
2334-
// 6u8.round_up_to_one_less_than_a_power_of_two() == 7
2335-
fn round_up_to_one_less_than_a_power_of_two(self) -> Self {
2336-
let bits = size_of::<Self>() as u32 * 8;
2337-
let z = self.leading_zeros();
2338-
(if z == bits { 0 as Self } else { !0 }).wrapping_shr(z)
2339-
}
2340-
23412329
// Returns one less than next power of two.
23422330
// (For 8u8 next power of two is 8u8 and for 6u8 it is 8u8)
23432331
//
23442332
// 8u8.one_less_than_next_power_of_two() == 7
23452333
// 6u8.one_less_than_next_power_of_two() == 7
2334+
//
2335+
// This method cannot overflow, as in the `next_power_of_two`
2336+
// overflow cases it instead ends up returning the maximum value
2337+
// of the type, and can return 0 for 0.
23462338
fn one_less_than_next_power_of_two(self) -> Self {
2347-
self.wrapping_sub(1)
2348-
.round_up_to_one_less_than_a_power_of_two()
2349-
.wrapping_add(if self == 0 { 1 } else { 0 })
2339+
if self <= 1 { return 0; }
2340+
2341+
// Because `p > 0`, it cannot consist entirely of leading zeros.
2342+
// That means the shift is always in-bounds, and some processors
2343+
// (such as intel pre-haswell) have more efficient ctlz
2344+
// intrinsics when the argument is non-zero.
2345+
let p = self - 1;
2346+
let z = p.leading_zeros();
2347+
<$SelfT>::max_value() >> z
23502348
}
23512349

23522350
/// Returns the smallest power of two greater than or equal to `self`.

src/libstd/num.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@ mod tests {
176176
fn $test_name() {
177177
#![test]
178178
assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
179-
assert!(($T::MAX / 2).checked_next_power_of_two().is_some());
179+
let smax = $T::MAX >> 1;
180+
assert_eq!(smax.checked_next_power_of_two(), Some(smax+1));
181+
assert_eq!((smax + 1).checked_next_power_of_two(), Some(smax + 1));
182+
assert_eq!((smax + 2).checked_next_power_of_two(), None);
180183
assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None);
181184
assert_eq!($T::MAX.checked_next_power_of_two(), None);
182185
let mut next_power = 1;

0 commit comments

Comments
 (0)