Skip to content

Commit b44090a

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 c2fb0a3 commit b44090a

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

library/core/src/num/int_macros.rs

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

1854+
if intrinsics::is_val_statically_known(exp) {
1855+
while exp > 1 {
1856+
if (exp & 1) == 1 {
1857+
acc = try_opt!(acc.checked_mul(base));
1858+
}
1859+
exp /= 2;
1860+
base = try_opt!(base.checked_mul(base));
1861+
}
1862+
1863+
// since exp!=0, finally the exp must be 1.
1864+
// Deal with the final bit of the exponent separately, since
1865+
// squaring the base afterwards is not necessary and may cause a
1866+
// needless overflow.
1867+
return acc.checked_mul(base);
1868+
}
1869+
18541870
loop {
18551871
if (exp & 1) == 1 {
18561872
acc = try_opt!(acc.checked_mul(base));
@@ -3089,6 +3105,26 @@ macro_rules! int_impl {
30893105
let mut overflow = false;
30903106
let mut tmp_overflow;
30913107

3108+
if intrinsics::is_val_statically_known(exp) {
3109+
while exp > 1 {
3110+
if (exp & 1) == 1 {
3111+
(acc, tmp_overflow) = acc.overflowing_mul(base);
3112+
overflow |= tmp_overflow;
3113+
}
3114+
exp /= 2;
3115+
(base, tmp_overflow) = base.overflowing_mul(base);
3116+
overflow |= tmp_overflow;
3117+
}
3118+
3119+
// since exp!=0, finally the exp must be 1.
3120+
// Deal with the final bit of the exponent separately, since
3121+
// squaring the base afterwards is not necessary and may cause a
3122+
// needless overflow.
3123+
(acc, tmp_overflow) = acc.overflowing_mul(base);
3124+
overflow |= tmp_overflow;
3125+
return (acc, overflow);
3126+
}
3127+
30923128
loop {
30933129
if (exp & 1) == 1 {
30943130
(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
@@ -2373,6 +2373,22 @@ macro_rules! uint_impl {
23732373
let mut base = self;
23742374
let mut acc: Self = 1;
23752375

2376+
if intrinsics::is_val_statically_known(exp) {
2377+
while exp > 1 {
2378+
if (exp & 1) == 1 {
2379+
acc = try_opt!(acc.checked_mul(base));
2380+
}
2381+
exp /= 2;
2382+
base = try_opt!(base.checked_mul(base));
2383+
}
2384+
2385+
// since exp!=0, finally the exp must be 1.
2386+
// Deal with the final bit of the exponent separately, since
2387+
// squaring the base afterwards is not necessary and may cause a
2388+
// needless overflow.
2389+
return acc.checked_mul(base);
2390+
}
2391+
23762392
loop {
23772393
if (exp & 1) == 1 {
23782394
acc = try_opt!(acc.checked_mul(base));
@@ -3558,6 +3574,26 @@ macro_rules! uint_impl {
35583574
let mut overflow = false;
35593575
let mut tmp_overflow;
35603576

3577+
if intrinsics::is_val_statically_known(exp) {
3578+
while exp > 1 {
3579+
if (exp & 1) == 1 {
3580+
(acc, tmp_overflow) = acc.overflowing_mul(base);
3581+
overflow |= tmp_overflow;
3582+
}
3583+
exp /= 2;
3584+
(base, tmp_overflow) = base.overflowing_mul(base);
3585+
overflow |= tmp_overflow;
3586+
}
3587+
3588+
// since exp!=0, finally the exp must be 1.
3589+
// Deal with the final bit of the exponent separately, since
3590+
// squaring the base afterwards is not necessary and may cause a
3591+
// needless overflow.
3592+
(acc, tmp_overflow) = acc.overflowing_mul(base);
3593+
overflow |= tmp_overflow;
3594+
return (acc, overflow);
3595+
}
3596+
35613597
loop {
35623598
if (exp & 1) == 1 {
35633599
(acc, tmp_overflow) = acc.overflowing_mul(base);

0 commit comments

Comments
 (0)