Skip to content

Commit 9988dcd

Browse files
committed
optimize: pow if exp is statically known
Copy the optimization that unrolls the loop from `pow` to `checked_pow` and `overflowing_pow`.
1 parent fc24178 commit 9988dcd

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

library/core/src/num/int_macros.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,22 @@ macro_rules! int_impl {
17461746
let mut base = self;
17471747
let mut acc: Self = 1;
17481748

1749+
if intrinsics::is_val_statically_known(exp) {
1750+
while exp > 1 {
1751+
if (exp & 1) == 1 {
1752+
acc = try_opt!(acc.checked_mul(base));
1753+
}
1754+
exp /= 2;
1755+
base = try_opt!(base.checked_mul(base));
1756+
}
1757+
1758+
// since exp!=0, finally the exp must be 1.
1759+
// Deal with the final bit of the exponent separately, since
1760+
// squaring the base afterwards is not necessary and may cause a
1761+
// needless overflow.
1762+
return acc.checked_mul(base);
1763+
}
1764+
17491765
loop {
17501766
if (exp & 1) == 1 {
17511767
acc = try_opt!(acc.checked_mul(base));
@@ -2952,6 +2968,26 @@ macro_rules! int_impl {
29522968
let mut overflow = false;
29532969
let mut tmp_overflow;
29542970

2971+
if intrinsics::is_val_statically_known(exp) {
2972+
while exp > 1 {
2973+
if (exp & 1) == 1 {
2974+
(acc, tmp_overflow) = acc.overflowing_mul(base);
2975+
overflow |= tmp_overflow;
2976+
}
2977+
exp /= 2;
2978+
(base, tmp_overflow) = base.overflowing_mul(base);
2979+
overflow |= tmp_overflow;
2980+
}
2981+
2982+
// since exp!=0, finally the exp must be 1.
2983+
// Deal with the final bit of the exponent separately, since
2984+
// squaring the base afterwards is not necessary and may cause a
2985+
// needless overflow.
2986+
(acc, tmp_overflow) = acc.overflowing_mul(base);
2987+
overflow |= tmp_overflow;
2988+
return (acc, overflow);
2989+
}
2990+
29552991
loop {
29562992
if (exp & 1) == 1 {
29572993
(acc, tmp_overflow) = acc.overflowing_mul(base);

library/core/src/num/uint_macros.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,6 +2091,22 @@ macro_rules! uint_impl {
20912091
let mut base = self;
20922092
let mut acc: Self = 1;
20932093

2094+
if intrinsics::is_val_statically_known(exp) {
2095+
while exp > 1 {
2096+
if (exp & 1) == 1 {
2097+
acc = try_opt!(acc.checked_mul(base));
2098+
}
2099+
exp /= 2;
2100+
base = try_opt!(base.checked_mul(base));
2101+
}
2102+
2103+
// since exp!=0, finally the exp must be 1.
2104+
// Deal with the final bit of the exponent separately, since
2105+
// squaring the base afterwards is not necessary and may cause a
2106+
// needless overflow.
2107+
return acc.checked_mul(base);
2108+
}
2109+
20942110
loop {
20952111
if (exp & 1) == 1 {
20962112
acc = try_opt!(acc.checked_mul(base));
@@ -3247,6 +3263,26 @@ macro_rules! uint_impl {
32473263
let mut overflow = false;
32483264
let mut tmp_overflow;
32493265

3266+
if intrinsics::is_val_statically_known(exp) {
3267+
while exp > 1 {
3268+
if (exp & 1) == 1 {
3269+
(acc, tmp_overflow) = acc.overflowing_mul(base);
3270+
overflow |= tmp_overflow;
3271+
}
3272+
exp /= 2;
3273+
(base, tmp_overflow) = base.overflowing_mul(base);
3274+
overflow |= tmp_overflow;
3275+
}
3276+
3277+
// since exp!=0, finally the exp must be 1.
3278+
// Deal with the final bit of the exponent separately, since
3279+
// squaring the base afterwards is not necessary and may cause a
3280+
// needless overflow.
3281+
(acc, tmp_overflow) = acc.overflowing_mul(base);
3282+
overflow |= tmp_overflow;
3283+
return (acc, overflow);
3284+
}
3285+
32503286
loop {
32513287
if (exp & 1) == 1 {
32523288
(acc, tmp_overflow) = acc.overflowing_mul(base);

0 commit comments

Comments
 (0)