Skip to content

Commit 82357c1

Browse files
committed
refactor: Deduplicate pow implementations
`wrapping_pow`, `strict_pow` and `checked_pow` can all be implemented in terms of `overflowing_pow`.
1 parent d397302 commit 82357c1

File tree

2 files changed

+17
-75
lines changed

2 files changed

+17
-75
lines changed

library/core/src/num/overflow_panic.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ pub(super) const fn rem() -> ! {
3232
panic!("attempt to calculate the remainder with overflow")
3333
}
3434

35+
#[cold]
36+
#[track_caller]
37+
pub(super) const fn pow() -> ! {
38+
panic!("attempt to calculate the power with overflow")
39+
}
40+
3541
#[cold]
3642
#[track_caller]
3743
pub(super) const fn neg() -> ! {

library/core/src/num/uint_macros.rs

Lines changed: 11 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,24 +2071,9 @@ macro_rules! uint_impl {
20712071
#[must_use = "this returns the result of the operation, \
20722072
without modifying the original"]
20732073
#[inline]
2074-
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
2075-
if exp == 0 {
2076-
return Some(1);
2077-
}
2078-
let mut base = self;
2079-
let mut acc: Self = 1;
2080-
2081-
loop {
2082-
if (exp & 1) == 1 {
2083-
acc = try_opt!(acc.checked_mul(base));
2084-
// since exp!=0, finally the exp must be 1.
2085-
if exp == 1 {
2086-
return Some(acc);
2087-
}
2088-
}
2089-
exp /= 2;
2090-
base = try_opt!(base.checked_mul(base));
2091-
}
2074+
pub const fn checked_pow(self, exp: u32) -> Option<Self> {
2075+
let (a, b) = self.overflowing_pow(exp);
2076+
if b { None } else { Some(a) }
20922077
}
20932078

20942079
/// Strict exponentiation. Computes `self.pow(exp)`, panicking if
@@ -2117,24 +2102,9 @@ macro_rules! uint_impl {
21172102
without modifying the original"]
21182103
#[inline]
21192104
#[track_caller]
2120-
pub const fn strict_pow(self, mut exp: u32) -> Self {
2121-
if exp == 0 {
2122-
return 1;
2123-
}
2124-
let mut base = self;
2125-
let mut acc: Self = 1;
2126-
2127-
loop {
2128-
if (exp & 1) == 1 {
2129-
acc = acc.strict_mul(base);
2130-
// since exp!=0, finally the exp must be 1.
2131-
if exp == 1 {
2132-
return acc;
2133-
}
2134-
}
2135-
exp /= 2;
2136-
base = base.strict_mul(base);
2137-
}
2105+
pub const fn strict_pow(self, exp: u32) -> Self {
2106+
let (a, b) = self.overflowing_pow(exp);
2107+
if b { overflow_panic::pow() } else { a }
21382108
}
21392109

21402110
/// Saturating integer addition. Computes `self + rhs`, saturating at
@@ -2593,43 +2563,9 @@ macro_rules! uint_impl {
25932563
#[must_use = "this returns the result of the operation, \
25942564
without modifying the original"]
25952565
#[inline]
2596-
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
2597-
if exp == 0 {
2598-
return 1;
2599-
}
2600-
let mut base = self;
2601-
let mut acc: Self = 1;
2602-
2603-
if intrinsics::is_val_statically_known(exp) {
2604-
while exp > 1 {
2605-
if (exp & 1) == 1 {
2606-
acc = acc.wrapping_mul(base);
2607-
}
2608-
exp /= 2;
2609-
base = base.wrapping_mul(base);
2610-
}
2611-
2612-
// since exp!=0, finally the exp must be 1.
2613-
// Deal with the final bit of the exponent separately, since
2614-
// squaring the base afterwards is not necessary.
2615-
acc.wrapping_mul(base)
2616-
} else {
2617-
// This is faster than the above when the exponent is not known
2618-
// at compile time. We can't use the same code for the constant
2619-
// exponent case because LLVM is currently unable to unroll
2620-
// this loop.
2621-
loop {
2622-
if (exp & 1) == 1 {
2623-
acc = acc.wrapping_mul(base);
2624-
// since exp!=0, finally the exp must be 1.
2625-
if exp == 1 {
2626-
return acc;
2627-
}
2628-
}
2629-
exp /= 2;
2630-
base = base.wrapping_mul(base);
2631-
}
2632-
}
2566+
pub const fn wrapping_pow(self, exp: u32) -> Self {
2567+
let (a, _) = self.overflowing_pow(exp);
2568+
a
26332569
}
26342570

26352571
/// Calculates `self` + `rhs`.
@@ -3269,8 +3205,8 @@ macro_rules! uint_impl {
32693205
without modifying the original"]
32703206
#[inline]
32713207
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
3272-
if exp == 0{
3273-
return (1,false);
3208+
if exp == 0 {
3209+
return (1, false);
32743210
}
32753211
let mut base = self;
32763212
let mut acc: Self = 1;

0 commit comments

Comments
 (0)