@@ -2050,54 +2050,41 @@ macro_rules! uint_impl {
20502050 #[ inline]
20512051 #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
20522052 pub const fn wrapping_pow( self , mut exp: u32 ) -> Self {
2053+ if exp == 0 {
2054+ return 1 ;
2055+ }
20532056 let mut base = self ;
2057+ let mut acc: Self = 1 ;
20542058
20552059 if intrinsics:: is_val_statically_known( exp) {
2056- // Unroll multiplications for small exponent values.
2057- // This gives the optimizer a way to efficiently inline call sites
2058- // for the most common use cases with constant exponents.
2059- // Currently, LLVM is unable to unroll the loop below.
2060- match exp {
2061- 0 => return 1 ,
2062- 1 => return base,
2063- 2 => return base. wrapping_mul( base) ,
2064- 3 => {
2065- let squared = base. wrapping_mul( base) ;
2066- return squared. wrapping_mul( base) ;
2067- }
2068- 4 => {
2069- let squared = base. wrapping_mul( base) ;
2070- return squared. wrapping_mul( squared) ;
2060+ while exp > 1 {
2061+ if ( exp & 1 ) == 1 {
2062+ acc = acc. wrapping_mul( base) ;
20712063 }
2072- 5 => {
2073- let squared = base. wrapping_mul( base) ;
2074- return squared. wrapping_mul( squared) . wrapping_mul( base) ;
2075- }
2076- 6 => {
2077- let cubed = base. wrapping_mul( base) . wrapping_mul( base) ;
2078- return cubed. wrapping_mul( cubed) ;
2079- }
2080- _ => { }
2064+ exp /= 2 ;
2065+ base = base. wrapping_mul( base) ;
20812066 }
2082- } else {
2083- if exp == 0 {
2084- return 1 ;
2085- }
2086- }
2087- debug_assert!( exp != 0 ) ;
20882067
2089- let mut acc: Self = 1 ;
2090-
2091- loop {
2092- if ( exp & 1 ) == 1 {
2093- acc = acc. wrapping_mul( base) ;
2094- // since exp!=0, finally the exp must be 1.
2095- if exp == 1 {
2096- return acc;
2068+ // since exp!=0, finally the exp must be 1.
2069+ // Deal with the final bit of the exponent separately, since
2070+ // squaring the base afterwards is not necessary.
2071+ acc. wrapping_mul( base)
2072+ } else {
2073+ // This is faster than the above when the exponent is not known
2074+ // at compile time. We can't use the same code for the constant
2075+ // exponent case because LLVM is currently unable to unroll
2076+ // this loop.
2077+ loop {
2078+ if ( exp & 1 ) == 1 {
2079+ acc = acc. wrapping_mul( base) ;
2080+ // since exp!=0, finally the exp must be 1.
2081+ if exp == 1 {
2082+ return acc;
2083+ }
20972084 }
2085+ exp /= 2 ;
2086+ base = base. wrapping_mul( base) ;
20982087 }
2099- exp /= 2 ;
2100- base = base. wrapping_mul( base) ;
21012088 }
21022089 }
21032090
@@ -2578,54 +2565,42 @@ macro_rules! uint_impl {
25782565 #[ rustc_inherit_overflow_checks]
25792566 #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
25802567 pub const fn pow( self , mut exp: u32 ) -> Self {
2568+ if exp == 0 {
2569+ return 1 ;
2570+ }
25812571 let mut base = self ;
2572+ let mut acc = 1 ;
25822573
25832574 if intrinsics:: is_val_statically_known( exp) {
2584- // Unroll multiplications for small exponent values.
2585- // This gives the optimizer a way to efficiently inline call sites
2586- // for the most common use cases with constant exponents.
2587- // Currently, LLVM is unable to unroll the loop below.
2588- match exp {
2589- 0 => return 1 ,
2590- 1 => return base,
2591- 2 => return base * base,
2592- 3 => {
2593- let squared = base * base;
2594- return squared * base;
2595- }
2596- 4 => {
2597- let squared = base * base;
2598- return squared * squared;
2575+ while exp > 1 {
2576+ if ( exp & 1 ) == 1 {
2577+ acc = acc * base;
25992578 }
2600- 5 => {
2601- let squared = base * base;
2602- return squared * squared * base;
2603- }
2604- 6 => {
2605- let cubed = base * base * base;
2606- return cubed * cubed;
2607- }
2608- _ => { }
2579+ exp /= 2 ;
2580+ base = base * base;
26092581 }
2610- } else {
2611- if exp == 0 {
2612- return 1 ;
2613- }
2614- }
2615- debug_assert!( exp != 0 ) ;
26162582
2617- let mut acc = 1 ;
2618-
2619- loop {
2620- if ( exp & 1 ) == 1 {
2621- acc = acc * base;
2622- // since exp!=0, finally the exp must be 1.
2623- if exp == 1 {
2624- return acc;
2583+ // since exp!=0, finally the exp must be 1.
2584+ // Deal with the final bit of the exponent separately, since
2585+ // squaring the base afterwards is not necessary and may cause a
2586+ // needless overflow.
2587+ acc * base
2588+ } else {
2589+ // This is faster than the above when the exponent is not known
2590+ // at compile time. We can't use the same code for the constant
2591+ // exponent case because LLVM is currently unable to unroll
2592+ // this loop.
2593+ loop {
2594+ if ( exp & 1 ) == 1 {
2595+ acc = acc * base;
2596+ // since exp!=0, finally the exp must be 1.
2597+ if exp == 1 {
2598+ return acc;
2599+ }
26252600 }
2601+ exp /= 2 ;
2602+ base = base * base;
26262603 }
2627- exp /= 2 ;
2628- base = base * base;
26292604 }
26302605 }
26312606
0 commit comments