@@ -1496,18 +1496,17 @@ macro_rules! int_impl {
1496
1496
let mut base = self ;
1497
1497
let mut acc: Self = 1 ;
1498
1498
1499
- while exp > 1 {
1499
+ loop {
1500
1500
if ( exp & 1 ) == 1 {
1501
1501
acc = try_opt!( acc. checked_mul( base) ) ;
1502
+ // since exp!=0, finally the exp must be 1.
1503
+ if exp == 1 {
1504
+ return Some ( acc) ;
1505
+ }
1502
1506
}
1503
1507
exp /= 2 ;
1504
1508
base = try_opt!( base. checked_mul( base) ) ;
1505
1509
}
1506
- // since exp!=0, finally the exp must be 1.
1507
- // Deal with the final bit of the exponent separately, since
1508
- // squaring the base afterwards is not necessary and may cause a
1509
- // needless overflow.
1510
- acc. checked_mul( base)
1511
1510
}
1512
1511
1513
1512
/// Strict exponentiation. Computes `self.pow(exp)`, panicking if
@@ -1547,18 +1546,17 @@ macro_rules! int_impl {
1547
1546
let mut base = self ;
1548
1547
let mut acc: Self = 1 ;
1549
1548
1550
- while exp > 1 {
1549
+ loop {
1551
1550
if ( exp & 1 ) == 1 {
1552
1551
acc = acc. strict_mul( base) ;
1552
+ // since exp!=0, finally the exp must be 1.
1553
+ if exp == 1 {
1554
+ return acc;
1555
+ }
1553
1556
}
1554
1557
exp /= 2 ;
1555
1558
base = base. strict_mul( base) ;
1556
1559
}
1557
- // since exp!=0, finally the exp must be 1.
1558
- // Deal with the final bit of the exponent separately, since
1559
- // squaring the base afterwards is not necessary and may cause a
1560
- // needless overflow.
1561
- acc. strict_mul( base)
1562
1560
}
1563
1561
1564
1562
/// Returns the square root of the number, rounded down.
@@ -2175,26 +2173,44 @@ macro_rules! int_impl {
2175
2173
#[ must_use = "this returns the result of the operation, \
2176
2174
without modifying the original"]
2177
2175
#[ inline]
2176
+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
2178
2177
pub const fn wrapping_pow( self , mut exp: u32 ) -> Self {
2179
2178
if exp == 0 {
2180
2179
return 1 ;
2181
2180
}
2182
2181
let mut base = self ;
2183
2182
let mut acc: Self = 1 ;
2184
2183
2185
- while exp > 1 {
2186
- if ( exp & 1 ) == 1 {
2187
- acc = acc. wrapping_mul( base) ;
2184
+ if intrinsics:: is_val_statically_known( exp) {
2185
+ while exp > 1 {
2186
+ if ( exp & 1 ) == 1 {
2187
+ acc = acc. wrapping_mul( base) ;
2188
+ }
2189
+ exp /= 2 ;
2190
+ base = base. wrapping_mul( base) ;
2188
2191
}
2189
- exp /= 2 ;
2190
- base = base. wrapping_mul( base) ;
2191
- }
2192
2192
2193
- // since exp!=0, finally the exp must be 1.
2194
- // Deal with the final bit of the exponent separately, since
2195
- // squaring the base afterwards is not necessary and may cause a
2196
- // needless overflow.
2197
- acc. wrapping_mul( base)
2193
+ // since exp!=0, finally the exp must be 1.
2194
+ // Deal with the final bit of the exponent separately, since
2195
+ // squaring the base afterwards is not necessary.
2196
+ acc. wrapping_mul( base)
2197
+ } else {
2198
+ // This is faster than the above when the exponent is not known
2199
+ // at compile time. We can't use the same code for the constant
2200
+ // exponent case because LLVM is currently unable to unroll
2201
+ // this loop.
2202
+ loop {
2203
+ if ( exp & 1 ) == 1 {
2204
+ acc = acc. wrapping_mul( base) ;
2205
+ // since exp!=0, finally the exp must be 1.
2206
+ if exp == 1 {
2207
+ return acc;
2208
+ }
2209
+ }
2210
+ exp /= 2 ;
2211
+ base = base. wrapping_mul( base) ;
2212
+ }
2213
+ }
2198
2214
}
2199
2215
2200
2216
/// Calculates `self` + `rhs`.
@@ -2690,9 +2706,14 @@ macro_rules! int_impl {
2690
2706
// Scratch space for storing results of overflowing_mul.
2691
2707
let mut r;
2692
2708
2693
- while exp > 1 {
2709
+ loop {
2694
2710
if ( exp & 1 ) == 1 {
2695
2711
r = acc. overflowing_mul( base) ;
2712
+ // since exp!=0, finally the exp must be 1.
2713
+ if exp == 1 {
2714
+ r. 1 |= overflown;
2715
+ return r;
2716
+ }
2696
2717
acc = r. 0 ;
2697
2718
overflown |= r. 1 ;
2698
2719
}
@@ -2701,14 +2722,6 @@ macro_rules! int_impl {
2701
2722
base = r. 0 ;
2702
2723
overflown |= r. 1 ;
2703
2724
}
2704
-
2705
- // since exp!=0, finally the exp must be 1.
2706
- // Deal with the final bit of the exponent separately, since
2707
- // squaring the base afterwards is not necessary and may cause a
2708
- // needless overflow.
2709
- r = acc. overflowing_mul( base) ;
2710
- r. 1 |= overflown;
2711
- r
2712
2725
}
2713
2726
2714
2727
/// Raises self to the power of `exp`, using exponentiation by squaring.
@@ -2728,26 +2741,45 @@ macro_rules! int_impl {
2728
2741
without modifying the original"]
2729
2742
#[ inline]
2730
2743
#[ rustc_inherit_overflow_checks]
2744
+ #[ rustc_allow_const_fn_unstable( is_val_statically_known) ]
2731
2745
pub const fn pow( self , mut exp: u32 ) -> Self {
2732
2746
if exp == 0 {
2733
2747
return 1 ;
2734
2748
}
2735
2749
let mut base = self ;
2736
2750
let mut acc = 1 ;
2737
2751
2738
- while exp > 1 {
2739
- if ( exp & 1 ) == 1 {
2740
- acc = acc * base;
2752
+ if intrinsics:: is_val_statically_known( exp) {
2753
+ while exp > 1 {
2754
+ if ( exp & 1 ) == 1 {
2755
+ acc = acc * base;
2756
+ }
2757
+ exp /= 2 ;
2758
+ base = base * base;
2741
2759
}
2742
- exp /= 2 ;
2743
- base = base * base;
2744
- }
2745
2760
2746
- // since exp!=0, finally the exp must be 1.
2747
- // Deal with the final bit of the exponent separately, since
2748
- // squaring the base afterwards is not necessary and may cause a
2749
- // needless overflow.
2750
- acc * base
2761
+ // since exp!=0, finally the exp must be 1.
2762
+ // Deal with the final bit of the exponent separately, since
2763
+ // squaring the base afterwards is not necessary and may cause a
2764
+ // needless overflow.
2765
+ acc * base
2766
+ } else {
2767
+ // This is faster than the above when the exponent is not known
2768
+ // at compile time. We can't use the same code for the constant
2769
+ // exponent case because LLVM is currently unable to unroll
2770
+ // this loop.
2771
+ loop {
2772
+ if ( exp & 1 ) == 1 {
2773
+ acc = acc * base;
2774
+ // since exp!=0, finally the exp must be 1.
2775
+ if exp == 1 {
2776
+ return acc;
2777
+ }
2778
+ }
2779
+ exp /= 2 ;
2780
+ base = base * base;
2781
+ }
2782
+ }
2751
2783
}
2752
2784
2753
2785
/// Returns the square root of the number, rounded down.
0 commit comments