From 9a3583f06d7086c8eca70ae5770ecce1a74680be Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 30 Jan 2014 16:35:17 +1100 Subject: [PATCH 1/4] Make next_power_of_two generic for unsigned integers Also rename `next_power_of_two_opt` to `checked_next_power_of_two`. --- src/libarena/lib.rs | 4 +- src/libstd/at_vec.rs | 6 +-- src/libstd/hashmap.rs | 2 +- src/libstd/num/mod.rs | 76 ++++++++++++++++++++++++++- src/libstd/num/uint.rs | 65 ----------------------- src/libstd/str.rs | 4 +- src/libstd/sync/mpmc_bounded_queue.rs | 4 +- src/libstd/vec.rs | 4 +- 8 files changed, 87 insertions(+), 78 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 27dad55c42946..56c1871597401 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -178,7 +178,7 @@ impl Arena { let new_min_chunk_size = num::max(n_bytes, chunk_size); self.chunks.set(@Cons(self.pod_head.clone(), self.chunks.get())); self.pod_head = - chunk(uint::next_power_of_two(new_min_chunk_size + 1u), true); + chunk(num::next_power_of_two(new_min_chunk_size + 1u), true); return self.alloc_pod_inner(n_bytes, align); } @@ -220,7 +220,7 @@ impl Arena { let new_min_chunk_size = num::max(n_bytes, chunk_size); self.chunks.set(@Cons(self.head.clone(), self.chunks.get())); self.head = - chunk(uint::next_power_of_two(new_min_chunk_size + 1u), false); + chunk(num::next_power_of_two(new_min_chunk_size + 1u), false); return self.alloc_nonpod_inner(n_bytes, align); } diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index 18cb470db4da2..55e90248e1c3b 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -177,9 +177,9 @@ pub mod raw { use cast::{transmute, transmute_copy}; use container::Container; use option::None; - use ptr; use mem; - use uint; + use num::next_power_of_two; + use ptr; use unstable::intrinsics::{move_val_init, TyDesc}; use unstable::intrinsics; use unstable::raw::{Box, Vec}; @@ -293,7 +293,7 @@ pub mod raw { */ #[inline] pub unsafe fn reserve_at_least(v: &mut @[T], n: uint) { - reserve(v, uint::next_power_of_two(n)); + reserve(v, next_power_of_two(n)); } } diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 13a03d3252514..31bf4679144bc 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -388,7 +388,7 @@ impl HashMap { pub fn reserve_at_least(&mut self, n: uint) { if n > self.buckets.len() { let buckets = n * 4 / 3 + 1; - self.resize(uint::next_power_of_two(buckets)); + self.resize(num::next_power_of_two(buckets)); } } diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 956c04db09c63..976761b512053 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(n: T) -> T { + let halfbits: T = cast(size_of::() * 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(n: T) -> Option { + let halfbits: T = cast(size_of::() * 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 89914571adaf8..7954cdc92f07e 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::() * 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 { - let halfbits: uint = mem::size_of::() * 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] @@ -165,50 +144,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; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 9cc9799d0c017..cefa39fb3cd24 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -104,7 +104,7 @@ use iter::{Iterator, FromIterator, Extendable, range}; use iter::{Filter, AdditiveIterator, Map}; use iter::{Rev, DoubleEndedIterator, ExactSize}; use libc; -use num::{Saturating}; +use num::{Saturating, checked_next_power_of_two}; use option::{None, Option, Some}; use ptr; use ptr::RawPtr; @@ -2640,7 +2640,7 @@ impl OwnedStr for ~str { #[inline] fn reserve_at_least(&mut self, n: uint) { - self.reserve(uint::next_power_of_two_opt(n).unwrap_or(n)) + self.reserve(checked_next_power_of_two(n).unwrap_or(n)) } #[inline] diff --git a/src/libstd/sync/mpmc_bounded_queue.rs b/src/libstd/sync/mpmc_bounded_queue.rs index bb0e96f96de2b..74f3a6f6918da 100644 --- a/src/libstd/sync/mpmc_bounded_queue.rs +++ b/src/libstd/sync/mpmc_bounded_queue.rs @@ -31,10 +31,10 @@ use clone::Clone; use kinds::Send; +use num::next_power_of_two; use option::{Option, Some, None}; use sync::arc::UnsafeArc; use sync::atomics::{AtomicUint,Relaxed,Release,Acquire}; -use uint; use vec; struct Node { @@ -64,7 +64,7 @@ impl State { 2u } else { // use next power of 2 as capacity - uint::next_power_of_two(capacity) + next_power_of_two(capacity) } } else { capacity diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 467bcf075f60c..11b5790aeb792 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -109,7 +109,7 @@ use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater}; use cmp; use default::Default; use iter::*; -use num::{Integer, CheckedAdd, Saturating}; +use num::{Integer, CheckedAdd, Saturating, checked_next_power_of_two}; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; use ptr; @@ -1486,7 +1486,7 @@ impl OwnedVector for ~[T] { #[inline] fn reserve_at_least(&mut self, n: uint) { - self.reserve(uint::next_power_of_two_opt(n).unwrap_or(n)); + self.reserve(checked_next_power_of_two(n).unwrap_or(n)); } #[inline] From 4109caffc320018d93e9ae7f739d6f25dfe003f1 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 30 Jan 2014 21:18:30 +1100 Subject: [PATCH 2/4] Remove some unused imports --- src/libarena/lib.rs | 1 - src/libstd/hashmap.rs | 1 - src/libstd/str.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 56c1871597401..c4fc281915583 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -35,7 +35,6 @@ use std::num; use std::ptr; use std::mem; use std::rt::global_heap; -use std::uint; use std::unstable::intrinsics::{TyDesc, get_tydesc}; use std::unstable::intrinsics; use std::util; diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 31bf4679144bc..a97feea786d19 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -64,7 +64,6 @@ use num; use option::{None, Option, Some}; use rand::Rng; use rand; -use uint; use util::replace; use vec::{ImmutableVector, MutableVector, OwnedVector, Items, MutItems}; use vec_ng; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index cefa39fb3cd24..cd6edd2a6c258 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -110,7 +110,6 @@ use ptr; use ptr::RawPtr; use to_str::ToStr; use from_str::FromStr; -use uint; use vec; use vec::{OwnedVector, OwnedCloneableVector, ImmutableVector, MutableVector}; use default::Default; From 1388c053a8b59347b607674fb5b83910d309aa9b Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 30 Jan 2014 22:39:58 +1100 Subject: [PATCH 3/4] Remove free-standing div functions in std::uint --- src/libstd/num/uint.rs | 60 ------------------------------------------ 1 file changed, 60 deletions(-) diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 7954cdc92f07e..34611d43677f6 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -25,59 +25,6 @@ use unstable::intrinsics; uint_module!(uint, int, ::int::BITS) -/// -/// Divide two numbers, return the result, rounded up. -/// -/// # Arguments -/// -/// * x - an integer -/// * y - an integer distinct from 0u -/// -/// # Return value -/// -/// The smallest integer `q` such that `x/y <= q`. -/// -pub fn div_ceil(x: uint, y: uint) -> uint { - let div = x / y; - if x % y == 0u { div } - else { div + 1u } -} - -/// -/// Divide two numbers, return the result, rounded to the closest integer. -/// -/// # Arguments -/// -/// * x - an integer -/// * y - an integer distinct from 0u -/// -/// # Return value -/// -/// The integer `q` closest to `x/y`. -/// -pub fn div_round(x: uint, y: uint) -> uint { - let div = x / y; - if x % y * 2u < y { div } - else { div + 1u } -} - -/// -/// Divide two numbers, return the result, rounded down. -/// -/// Note: This is the same function as `div`. -/// -/// # Arguments -/// -/// * x - an integer -/// * y - an integer distinct from 0u -/// -/// # Return value -/// -/// The smallest integer `q` such that `x/y <= q`. This -/// is either `x/y` or `x/y + 1`. -/// -pub fn div_floor(x: uint, y: uint) -> uint { return x / y; } - #[cfg(target_word_size = "32")] impl CheckedAdd for uint { #[inline] @@ -151,10 +98,3 @@ fn test_overflows() { assert!((uint::MIN <= 0u)); assert!((uint::MIN + uint::MAX + 1u == 0u)); } - -#[test] -fn test_div() { - assert!((div_floor(3u, 4u) == 0u)); - assert!((div_ceil(3u, 4u) == 1u)); - assert!((div_round(3u, 4u) == 1u)); -} From 1f15d24243078903410176a0924bd5d09fe1c2b8 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 30 Jan 2014 23:55:34 +1100 Subject: [PATCH 4/4] Move int and uint overflow tests into macros --- src/libstd/num/int.rs | 7 ------- src/libstd/num/int_macros.rs | 7 +++++++ src/libstd/num/uint.rs | 8 -------- src/libstd/num/uint_macros.rs | 7 +++++++ 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 96e182adb82e1..f336afe12f400 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -120,10 +120,3 @@ impl CheckedMul for int { } } } - -#[test] -fn test_overflows() { - assert!((::int::MAX > 0)); - assert!((::int::MIN <= 0)); - assert!((::int::MIN + ::int::MAX + 1 == 0)); -} diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index c0f67912cdec6..c8d5dc1249959 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -445,6 +445,13 @@ mod tests { use num::CheckedDiv; use num::Bitwise; + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert_eq!(MIN + MAX + 1, 0); + } + #[test] fn test_num() { num::test_num(10 as $T, 2 as $T); diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 34611d43677f6..1811ebc7acc04 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -90,11 +90,3 @@ impl CheckedMul for uint { } } } - -#[test] -fn test_overflows() { - use uint; - assert!((uint::MAX > 0u)); - assert!((uint::MIN <= 0u)); - assert!((uint::MIN + uint::MAX + 1u == 0u)); -} diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 224f16cc6639e..eb483843b5dc2 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -317,6 +317,13 @@ mod tests { use num::Bitwise; use u16; + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert_eq!(MIN + MAX + 1, 0); + } + #[test] fn test_num() { num::test_num(10 as $T, 2 as $T);