@@ -1622,20 +1622,17 @@ macro_rules! uint_impl {
1622
1622
let mut base = self ;
1623
1623
let mut acc: Self = 1 ;
1624
1624
1625
- while exp > 1 {
1625
+ loop {
1626
1626
if ( exp & 1 ) == 1 {
1627
1627
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
+ }
1628
1632
}
1629
1633
exp /= 2 ;
1630
1634
base = try_opt!( base. checked_mul( base) ) ;
1631
1635
}
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)
1639
1636
}
1640
1637
1641
1638
/// Strict exponentiation. Computes `self.pow(exp)`, panicking if
@@ -1675,18 +1672,17 @@ macro_rules! uint_impl {
1675
1672
let mut base = self ;
1676
1673
let mut acc: Self = 1 ;
1677
1674
1678
- while exp > 1 {
1675
+ loop {
1679
1676
if ( exp & 1 ) == 1 {
1680
1677
acc = acc. strict_mul( base) ;
1678
+ // since exp!=0, finally the exp must be 1.
1679
+ if exp == 1 {
1680
+ return acc;
1681
+ }
1681
1682
}
1682
1683
exp /= 2 ;
1683
1684
base = base. strict_mul( base) ;
1684
1685
}
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)
1690
1686
}
1691
1687
1692
1688
/// Saturating integer addition. Computes `self + rhs`, saturating at
@@ -2138,26 +2134,44 @@ macro_rules! uint_impl {
2138
2134
#[ must_use = "this returns the result of the operation, \
2139
2135
without modifying the original"]
2140
2136
#[ inline]
2137
+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
2141
2138
pub const fn wrapping_pow( self , mut exp: u32 ) -> Self {
2142
2139
if exp == 0 {
2143
2140
return 1 ;
2144
2141
}
2145
2142
let mut base = self ;
2146
2143
let mut acc: Self = 1 ;
2147
2144
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) ;
2151
2152
}
2152
- exp /= 2 ;
2153
- base = base. wrapping_mul( base) ;
2154
- }
2155
2153
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
+ }
2161
2175
}
2162
2176
2163
2177
/// Calculates `self` + `rhs`.
@@ -2603,9 +2617,14 @@ macro_rules! uint_impl {
2603
2617
// Scratch space for storing results of overflowing_mul.
2604
2618
let mut r;
2605
2619
2606
- while exp > 1 {
2620
+ loop {
2607
2621
if ( exp & 1 ) == 1 {
2608
2622
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
+ }
2609
2628
acc = r. 0 ;
2610
2629
overflown |= r. 1 ;
2611
2630
}
@@ -2614,15 +2633,6 @@ macro_rules! uint_impl {
2614
2633
base = r. 0 ;
2615
2634
overflown |= r. 1 ;
2616
2635
}
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
2626
2636
}
2627
2637
2628
2638
/// Raises self to the power of `exp`, using exponentiation by squaring.
@@ -2640,26 +2650,45 @@ macro_rules! uint_impl {
2640
2650
without modifying the original"]
2641
2651
#[ inline]
2642
2652
#[ rustc_inherit_overflow_checks]
2653
+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
2643
2654
pub const fn pow( self , mut exp: u32 ) -> Self {
2644
2655
if exp == 0 {
2645
2656
return 1 ;
2646
2657
}
2647
2658
let mut base = self ;
2648
2659
let mut acc = 1 ;
2649
2660
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;
2653
2668
}
2654
- exp /= 2 ;
2655
- base = base * base;
2656
- }
2657
2669
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
+ }
2663
2692
}
2664
2693
2665
2694
/// Returns the square root of the number, rounded down.
0 commit comments