summary refs log tree commit diff
path: root/src/libcore/num
diff options
context:
space:
mode:
authorAaron Liblong <liblonga@physics.utoronto.ca>2014-12-08 01:03:35 -0500
committerAaron Liblong <liblonga@physics.utoronto.ca>2014-12-19 18:21:24 -0500
commitf6328b60da4c506f0f15dc0194f9b9a89aa61a79 (patch)
treefa079f83c6ba1a4d2651230958c078e7c6ef1a27 /src/libcore/num
parent99d6956c3bdb290b9fd539c5dc15a2b502da5e7a (diff)
downloadrust-f6328b60da4c506f0f15dc0194f9b9a89aa61a79.tar.gz
rust-f6328b60da4c506f0f15dc0194f9b9a89aa61a79.zip
Reform power_of_two methods for perf increase & semantic change to consider 0 not a power of 2.
Vec panics when attempting to reserve capacity > int::MAX (uint::MAX / 2).
Diffstat (limited to 'src/libcore/num')
-rw-r--r--src/libcore/num/mod.rs27
1 files changed, 11 insertions, 16 deletions
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index fcb2ca93054..39d8ac279a0 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -673,35 +673,30 @@ signed_int_impl! { int }
 #[unstable = "recently settled as part of numerics reform"]
 pub trait UnsignedInt: Int {
     /// Returns `true` iff `self == 2^k` for some `k`.
+    #[inline]
     fn is_power_of_two(self) -> bool {
-        (self - Int::one()) & self == Int::zero()
+        (self - Int::one()) & self == Int::zero() && !(self == Int::zero())
     }
 
     /// Returns the smallest power of two greater than or equal to `self`.
+    /// Unspecified behavior on overflow.
     #[inline]
     fn next_power_of_two(self) -> Self {
-        let halfbits = size_of::<Self>() * 4;
-        let mut tmp = self - Int::one();
-        let mut shift = 1u;
-        while shift <= halfbits {
-            tmp = tmp | (tmp >> shift);
-            shift = shift << 1u;
-        }
-        tmp + Int::one()
+        let bits = size_of::<Self>() * 8;
+        let one: Self = Int::one();
+        one << ((bits - (self - one).leading_zeros()) % bits)
     }
 
     /// Returns the smallest power of two 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 two is wrapped in `Some`.
     fn checked_next_power_of_two(self) -> Option<Self> {
-        let halfbits = size_of::<Self>() * 4;
-        let mut tmp = self - Int::one();
-        let mut shift = 1u;
-        while shift <= halfbits {
-            tmp = tmp | (tmp >> shift);
-            shift = shift << 1u;
+        let npot = self.next_power_of_two();
+        if npot >= self {
+            Some(npot)
+        } else {
+            None
         }
-        tmp.checked_add(Int::one())
     }
 }