@@ -1622,20 +1622,17 @@ macro_rules! uint_impl {
16221622 let mut base = self ;
16231623 let mut acc: Self = 1 ;
16241624
1625- while exp > 1 {
1625+ loop {
16261626 if ( exp & 1 ) == 1 {
16271627 acc = try_opt!( acc. checked_mul( base) ) ;
1628+ // since exp!=0, finally the exp must be 1.
1629+ if exp == 1 {
1630+ return Some ( acc) ;
1631+ }
16281632 }
16291633 exp /= 2 ;
16301634 base = try_opt!( base. checked_mul( base) ) ;
16311635 }
1632-
1633- // since exp!=0, finally the exp must be 1.
1634- // Deal with the final bit of the exponent separately, since
1635- // squaring the base afterwards is not necessary and may cause a
1636- // needless overflow.
1637-
1638- acc. checked_mul( base)
16391636 }
16401637
16411638 /// Strict exponentiation. Computes `self.pow(exp)`, panicking if
@@ -1675,18 +1672,17 @@ macro_rules! uint_impl {
16751672 let mut base = self ;
16761673 let mut acc: Self = 1 ;
16771674
1678- while exp > 1 {
1675+ loop {
16791676 if ( exp & 1 ) == 1 {
16801677 acc = acc. strict_mul( base) ;
1678+ // since exp!=0, finally the exp must be 1.
1679+ if exp == 1 {
1680+ return acc;
1681+ }
16811682 }
16821683 exp /= 2 ;
16831684 base = base. strict_mul( base) ;
16841685 }
1685- // since exp!=0, finally the exp must be 1.
1686- // Deal with the final bit of the exponent separately, since
1687- // squaring the base afterwards is not necessary and may cause a
1688- // needless overflow.
1689- acc. strict_mul( base)
16901686 }
16911687
16921688 /// Saturating integer addition. Computes `self + rhs`, saturating at
@@ -2138,26 +2134,44 @@ macro_rules! uint_impl {
21382134 #[ must_use = "this returns the result of the operation, \
21392135 without modifying the original"]
21402136 #[ inline]
2137+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
21412138 pub const fn wrapping_pow( self , mut exp: u32 ) -> Self {
21422139 if exp == 0 {
21432140 return 1 ;
21442141 }
21452142 let mut base = self ;
21462143 let mut acc: Self = 1 ;
21472144
2148- while exp > 1 {
2149- if ( exp & 1 ) == 1 {
2150- acc = acc. wrapping_mul( base) ;
2145+ if intrinsics:: is_val_statically_known( exp) {
2146+ while exp > 1 {
2147+ if ( exp & 1 ) == 1 {
2148+ acc = acc. wrapping_mul( base) ;
2149+ }
2150+ exp /= 2 ;
2151+ base = base. wrapping_mul( base) ;
21512152 }
2152- exp /= 2 ;
2153- base = base. wrapping_mul( base) ;
2154- }
21552153
2156- // since exp!=0, finally the exp must be 1.
2157- // Deal with the final bit of the exponent separately, since
2158- // squaring the base afterwards is not necessary and may cause a
2159- // needless overflow.
2160- acc. wrapping_mul( base)
2154+ // since exp!=0, finally the exp must be 1.
2155+ // Deal with the final bit of the exponent separately, since
2156+ // squaring the base afterwards is not necessary.
2157+ acc. wrapping_mul( base)
2158+ } else {
2159+ // This is faster than the above when the exponent is not known
2160+ // at compile time. We can't use the same code for the constant
2161+ // exponent case because LLVM is currently unable to unroll
2162+ // this loop.
2163+ loop {
2164+ if ( exp & 1 ) == 1 {
2165+ acc = acc. wrapping_mul( base) ;
2166+ // since exp!=0, finally the exp must be 1.
2167+ if exp == 1 {
2168+ return acc;
2169+ }
2170+ }
2171+ exp /= 2 ;
2172+ base = base. wrapping_mul( base) ;
2173+ }
2174+ }
21612175 }
21622176
21632177 /// Calculates `self` + `rhs`.
@@ -2603,9 +2617,14 @@ macro_rules! uint_impl {
26032617 // Scratch space for storing results of overflowing_mul.
26042618 let mut r;
26052619
2606- while exp > 1 {
2620+ loop {
26072621 if ( exp & 1 ) == 1 {
26082622 r = acc. overflowing_mul( base) ;
2623+ // since exp!=0, finally the exp must be 1.
2624+ if exp == 1 {
2625+ r. 1 |= overflown;
2626+ return r;
2627+ }
26092628 acc = r. 0 ;
26102629 overflown |= r. 1 ;
26112630 }
@@ -2614,15 +2633,6 @@ macro_rules! uint_impl {
26142633 base = r. 0 ;
26152634 overflown |= r. 1 ;
26162635 }
2617-
2618- // since exp!=0, finally the exp must be 1.
2619- // Deal with the final bit of the exponent separately, since
2620- // squaring the base afterwards is not necessary and may cause a
2621- // needless overflow.
2622- r = acc. overflowing_mul( base) ;
2623- r. 1 |= overflown;
2624-
2625- r
26262636 }
26272637
26282638 /// Raises self to the power of `exp`, using exponentiation by squaring.
@@ -2640,26 +2650,45 @@ macro_rules! uint_impl {
26402650 without modifying the original"]
26412651 #[ inline]
26422652 #[ rustc_inherit_overflow_checks]
2653+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
26432654 pub const fn pow( self , mut exp: u32 ) -> Self {
26442655 if exp == 0 {
26452656 return 1 ;
26462657 }
26472658 let mut base = self ;
26482659 let mut acc = 1 ;
26492660
2650- while exp > 1 {
2651- if ( exp & 1 ) == 1 {
2652- acc = acc * base;
2661+ if intrinsics:: is_val_statically_known( exp) {
2662+ while exp > 1 {
2663+ if ( exp & 1 ) == 1 {
2664+ acc = acc * base;
2665+ }
2666+ exp /= 2 ;
2667+ base = base * base;
26532668 }
2654- exp /= 2 ;
2655- base = base * base;
2656- }
26572669
2658- // since exp!=0, finally the exp must be 1.
2659- // Deal with the final bit of the exponent separately, since
2660- // squaring the base afterwards is not necessary and may cause a
2661- // needless overflow.
2662- acc * base
2670+ // since exp!=0, finally the exp must be 1.
2671+ // Deal with the final bit of the exponent separately, since
2672+ // squaring the base afterwards is not necessary and may cause a
2673+ // needless overflow.
2674+ acc * base
2675+ } else {
2676+ // This is faster than the above when the exponent is not known
2677+ // at compile time. We can't use the same code for the constant
2678+ // exponent case because LLVM is currently unable to unroll
2679+ // this loop.
2680+ loop {
2681+ if ( exp & 1 ) == 1 {
2682+ acc = acc * base;
2683+ // since exp!=0, finally the exp must be 1.
2684+ if exp == 1 {
2685+ return acc;
2686+ }
2687+ }
2688+ exp /= 2 ;
2689+ base = base * base;
2690+ }
2691+ }
26632692 }
26642693
26652694 /// Returns the square root of the number, rounded down.
0 commit comments