]> git.lizzy.rs Git - rust.git/commitdiff
Simplify helper functions
authorIrfan Hudda <irfanhudda@gmail.com>
Wed, 31 May 2017 16:55:15 +0000 (22:25 +0530)
committerIrfan Hudda <irfanhudda@gmail.com>
Wed, 31 May 2017 16:55:15 +0000 (22:25 +0530)
Based on @scottmcm 's suggestion

src/libcore/num/mod.rs
src/libstd/num.rs

index 8fd21d77dc3167db62c23c7c6ee3aa7a6c2fb4da..e5a8cfdd9a1d5539bf184bb5ea622ed9082ef57e 100644 (file)
@@ -15,7 +15,6 @@
 use convert::TryFrom;
 use fmt;
 use intrinsics;
-use mem::size_of;
 use str::FromStr;
 
 /// Provides intentionally-wrapped arithmetic on `T`.
@@ -2327,26 +2326,25 @@ pub fn is_power_of_two(self) -> bool {
             (self.wrapping_sub(1)) & self == 0 && !(self == 0)
         }
 
-        // Returns one less than next greater power of two.
-        // (For 8u8 next greater power of two is 16u8 and for 6u8 it is 8u8)
-        //
-        // 8u8.round_up_to_one_less_than_a_power_of_two() == 15
-        // 6u8.round_up_to_one_less_than_a_power_of_two() == 7
-        fn round_up_to_one_less_than_a_power_of_two(self) -> Self {
-            let bits = size_of::<Self>() as u32 * 8;
-            let z = self.leading_zeros();
-            (if z == bits { 0 as Self } else { !0 }).wrapping_shr(z)
-        }
-
         // Returns one less than next power of two.
         // (For 8u8 next power of two is 8u8 and for 6u8 it is 8u8)
         //
         // 8u8.one_less_than_next_power_of_two() == 7
         // 6u8.one_less_than_next_power_of_two() == 7
+        //
+        // This method cannot overflow, as in the `next_power_of_two`
+        // overflow cases it instead ends up returning the maximum value
+        // of the type, and can return 0 for 0.
         fn one_less_than_next_power_of_two(self) -> Self {
-            self.wrapping_sub(1)
-                .round_up_to_one_less_than_a_power_of_two()
-                .wrapping_add(if self == 0 { 1 } else { 0 })
+            if self <= 1 { return 0; }
+
+            // Because `p > 0`, it cannot consist entirely of leading zeros.
+            // That means the shift is always in-bounds, and some processors
+            // (such as intel pre-haswell) have more efficient ctlz
+            // intrinsics when the argument is non-zero.
+            let p = self - 1;
+            let z = p.leading_zeros();
+            <$SelfT>::max_value() >> z
         }
 
         /// Returns the smallest power of two greater than or equal to `self`.
index 5f83d077a13682897b570234ca23ae77b10520c1..894a6e6796ca645cc0a47db2061699e51c8ef962 100644 (file)
@@ -176,7 +176,10 @@ macro_rules! test_checked_next_power_of_two {
             fn $test_name() {
                 #![test]
                 assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
-                assert!(($T::MAX / 2).checked_next_power_of_two().is_some());
+                let smax = $T::MAX >> 1;
+                assert_eq!(smax.checked_next_power_of_two(), Some(smax+1));
+                assert_eq!((smax + 1).checked_next_power_of_two(), Some(smax + 1));
+                assert_eq!((smax + 2).checked_next_power_of_two(), None);
                 assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None);
                 assert_eq!($T::MAX.checked_next_power_of_two(), None);
                 let mut next_power = 1;