diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f4a1afd436adb..c576465c622fe 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1103,6 +1103,9 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } let mut base = self; let mut acc: Self = 1; @@ -1113,15 +1116,11 @@ $EndFeature, " exp /= 2; base = try_opt!(base.checked_mul(base)); } - + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - - Some(acc) + Some(try_opt!(acc.checked_mul(base))) } } @@ -1631,6 +1630,9 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc: Self = 1; @@ -1642,14 +1644,11 @@ $EndFeature, " base = base.wrapping_mul(base); } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc.wrapping_mul(base); - } - - acc + acc.wrapping_mul(base) } } @@ -1999,6 +1998,9 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0 { + return (1,false); + } let mut base = self; let mut acc: Self = 1; let mut overflown = false; @@ -2017,16 +2019,13 @@ $EndFeature, " overflown |= r.1; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - - (acc, overflown) + r = acc.overflowing_mul(base); + r.1 |= overflown; + r } } @@ -2050,6 +2049,9 @@ $EndFeature, " #[inline] #[rustc_inherit_overflow_checks] pub const fn pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc = 1; @@ -2061,14 +2063,11 @@ $EndFeature, " base = base * base; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc * base; - } - - acc + acc * base } } @@ -3306,6 +3305,9 @@ assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " without modifying the original"] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } let mut base = self; let mut acc: Self = 1; @@ -3317,14 +3319,12 @@ assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " base = try_opt!(base.checked_mul(base)); } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - Some(acc) + Some(try_opt!(acc.checked_mul(base))) } } @@ -3715,6 +3715,9 @@ assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc: Self = 1; @@ -3726,14 +3729,11 @@ assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " base = base.wrapping_mul(base); } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc.wrapping_mul(base); - } - - acc + acc.wrapping_mul(base) } } @@ -4040,6 +4040,9 @@ assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " without modifying the original"] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0{ + return (1,false); + } let mut base = self; let mut acc: Self = 1; let mut overflown = false; @@ -4058,16 +4061,14 @@ assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " overflown |= r.1; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } + r = acc.overflowing_mul(base); + r.1 |= overflown; - (acc, overflown) + r } } @@ -4088,6 +4089,9 @@ Basic usage: #[inline] #[rustc_inherit_overflow_checks] pub const fn pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc = 1; @@ -4099,14 +4103,11 @@ Basic usage: base = base * base; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc * base; - } - - acc + acc * base } } diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 8396a0dd62db9..58a585669122c 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -255,12 +255,43 @@ macro_rules! int_module { #[test] fn test_pow() { let mut r = 2 as $T; - assert_eq!(r.pow(2), 4 as $T); assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + //test for negative exponent. r = -2 as $T; assert_eq!(r.pow(2), 4 as $T); assert_eq!(r.pow(3), -8 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(3), -8 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(3), Some(-8 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(3), (-8 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(3), -8 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); } } }; diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs index 8f1ca8e6fac2c..b84a8a7d9f88b 100644 --- a/src/libcore/tests/num/uint_macros.rs +++ b/src/libcore/tests/num/uint_macros.rs @@ -184,6 +184,31 @@ macro_rules! uint_module { assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); } + + #[test] + fn test_pow() { + let mut r = 2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + } } }; }