diff options
| author | Brendan Zabarauskas <bjzaba@yahoo.com.au> | 2014-01-30 16:35:17 +1100 |
|---|---|---|
| committer | Brendan Zabarauskas <bjzaba@yahoo.com.au> | 2014-02-01 13:02:53 +1100 |
| commit | 9a3583f06d7086c8eca70ae5770ecce1a74680be (patch) | |
| tree | c1d228c64e7f4d547292b7fb94f5b7a0a8fe4633 /src/libstd/num | |
| parent | 535e806841e1eca7adb9f41796001848f6859637 (diff) | |
| download | rust-9a3583f06d7086c8eca70ae5770ecce1a74680be.tar.gz rust-9a3583f06d7086c8eca70ae5770ecce1a74680be.zip | |
Make next_power_of_two generic for unsigned integers
Also rename `next_power_of_two_opt` to `checked_next_power_of_two`.
Diffstat (limited to 'src/libstd/num')
| -rw-r--r-- | src/libstd/num/mod.rs | 76 | ||||
| -rw-r--r-- | src/libstd/num/uint.rs | 65 |
2 files changed, 75 insertions, 66 deletions
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 956c04db09c..976761b5120 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -440,7 +440,39 @@ pub trait Primitive: Clone /// A collection of traits relevant to primitive signed and unsigned integers pub trait Int: Integer + Primitive - + Bitwise {} + + Bitwise + + CheckedAdd + + CheckedSub + // + CheckedMul // FIXME #8849: currently not impled on 32-bit + + CheckedDiv {} + +/// Returns the smallest power of 2 greater than or equal to `n`. +#[inline] +pub fn next_power_of_two<T: Unsigned + Int>(n: T) -> T { + let halfbits: T = cast(size_of::<T>() * 4).unwrap(); + let mut tmp: T = n - one(); + let mut shift: T = one(); + while shift <= halfbits { + tmp = tmp | (tmp >> shift); + shift = shift << one(); + } + tmp + one() +} + +/// Returns the smallest power of 2 greater than or equal to `n`. If the next +/// power of two is greater than the type's maximum value, `None` is returned, +/// otherwise the power of 2 is wrapped in `Some`. +#[inline] +pub fn checked_next_power_of_two<T: Unsigned + Int>(n: T) -> Option<T> { + let halfbits: T = cast(size_of::<T>() * 4).unwrap(); + let mut tmp: T = n - one(); + let mut shift: T = one(); + while shift <= halfbits { + tmp = tmp | (tmp >> shift); + shift = shift << one(); + } + tmp.checked_add(&one()) +} /// Used for representing the classification of floating point numbers #[deriving(Eq)] @@ -1589,6 +1621,48 @@ mod tests { assert_eq!(third.checked_mul(&4), None); } + macro_rules! test_next_power_of_two( + ($test_name:ident, $T:ident) => ( + fn $test_name() { + #[test]; + assert_eq!(next_power_of_two::<$T>(0), 0); + let mut next_power = 1; + for i in range::<$T>(1, 40) { + assert_eq!(next_power_of_two(i), next_power); + if i == next_power { next_power *= 2 } + } + } + ) + ) + + test_next_power_of_two!(test_next_power_of_two_u8, u8) + test_next_power_of_two!(test_next_power_of_two_u16, u16) + test_next_power_of_two!(test_next_power_of_two_u32, u32) + test_next_power_of_two!(test_next_power_of_two_u64, u64) + test_next_power_of_two!(test_next_power_of_two_uint, uint) + + macro_rules! test_checked_next_power_of_two( + ($test_name:ident, $T:ident) => ( + fn $test_name() { + #[test]; + assert_eq!(checked_next_power_of_two::<$T>(0), None); + let mut next_power = 1; + for i in range::<$T>(1, 40) { + assert_eq!(checked_next_power_of_two(i), Some(next_power)); + if i == next_power { next_power *= 2 } + } + assert!(checked_next_power_of_two::<$T>($T::MAX / 2).is_some()); + assert_eq!(checked_next_power_of_two::<$T>($T::MAX - 1), None); + assert_eq!(checked_next_power_of_two::<$T>($T::MAX), None); + } + ) + ) + + test_checked_next_power_of_two!(test_checked_next_power_of_two_u8, u8) + test_checked_next_power_of_two!(test_checked_next_power_of_two_u16, u16) + test_checked_next_power_of_two!(test_checked_next_power_of_two_u32, u32) + test_checked_next_power_of_two!(test_checked_next_power_of_two_u64, u64) + test_checked_next_power_of_two!(test_checked_next_power_of_two_uint, uint) #[deriving(Eq)] struct Value { x: int } diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 89914571ada..7954cdc92f0 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -15,7 +15,6 @@ use prelude::*; use default::Default; -use mem; use num::{Bitwise, Bounded}; use num::{CheckedAdd, CheckedSub, CheckedMul}; use num::{CheckedDiv, Zero, One, strconv}; @@ -79,26 +78,6 @@ pub fn div_round(x: uint, y: uint) -> uint { /// pub fn div_floor(x: uint, y: uint) -> uint { return x / y; } -/// Returns the smallest power of 2 greater than or equal to `n` -#[inline] -pub fn next_power_of_two(n: uint) -> uint { - let halfbits: uint = mem::size_of::<uint>() * 4u; - let mut tmp: uint = n - 1u; - let mut shift: uint = 1u; - while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; } - tmp + 1u -} - -/// Returns the smallest power of 2 greater than or equal to `n` -#[inline] -pub fn next_power_of_two_opt(n: uint) -> Option<uint> { - let halfbits: uint = mem::size_of::<uint>() * 4u; - let mut tmp: uint = n - 1u; - let mut shift: uint = 1u; - while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; } - tmp.checked_add(&1) -} - #[cfg(target_word_size = "32")] impl CheckedAdd for uint { #[inline] @@ -166,50 +145,6 @@ impl CheckedMul for uint { } #[test] -fn test_next_power_of_two() { - assert!((next_power_of_two(0u) == 0u)); - assert!((next_power_of_two(1u) == 1u)); - assert!((next_power_of_two(2u) == 2u)); - assert!((next_power_of_two(3u) == 4u)); - assert!((next_power_of_two(4u) == 4u)); - assert!((next_power_of_two(5u) == 8u)); - assert!((next_power_of_two(6u) == 8u)); - assert!((next_power_of_two(7u) == 8u)); - assert!((next_power_of_two(8u) == 8u)); - assert!((next_power_of_two(9u) == 16u)); - assert!((next_power_of_two(10u) == 16u)); - assert!((next_power_of_two(11u) == 16u)); - assert!((next_power_of_two(12u) == 16u)); - assert!((next_power_of_two(13u) == 16u)); - assert!((next_power_of_two(14u) == 16u)); - assert!((next_power_of_two(15u) == 16u)); - assert!((next_power_of_two(16u) == 16u)); - assert!((next_power_of_two(17u) == 32u)); - assert!((next_power_of_two(18u) == 32u)); - assert!((next_power_of_two(19u) == 32u)); - assert!((next_power_of_two(20u) == 32u)); - assert!((next_power_of_two(21u) == 32u)); - assert!((next_power_of_two(22u) == 32u)); - assert!((next_power_of_two(23u) == 32u)); - assert!((next_power_of_two(24u) == 32u)); - assert!((next_power_of_two(25u) == 32u)); - assert!((next_power_of_two(26u) == 32u)); - assert!((next_power_of_two(27u) == 32u)); - assert!((next_power_of_two(28u) == 32u)); - assert!((next_power_of_two(29u) == 32u)); - assert!((next_power_of_two(30u) == 32u)); - assert!((next_power_of_two(31u) == 32u)); - assert!((next_power_of_two(32u) == 32u)); - assert!((next_power_of_two(33u) == 64u)); - assert!((next_power_of_two(34u) == 64u)); - assert!((next_power_of_two(35u) == 64u)); - assert!((next_power_of_two(36u) == 64u)); - assert!((next_power_of_two(37u) == 64u)); - assert!((next_power_of_two(38u) == 64u)); - assert!((next_power_of_two(39u) == 64u)); -} - -#[test] fn test_overflows() { use uint; assert!((uint::MAX > 0u)); |
