Skip to content

Commit b31ff95

Browse files
committed
Add non-panicking variants of pow to all integer types
Currently, calling pow may panic in case of overflow, and the function does not have non-panicking counterparts. Thus, it would be beneficial to add those in.
1 parent 27a046e commit b31ff95

File tree

1 file changed

+308
-0
lines changed

1 file changed

+308
-0
lines changed

src/libcore/num/mod.rs

+308
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,46 @@ $EndFeature, "
634634
}
635635
}
636636

637+
doc_comment! {
638+
concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
639+
overflow occurred.
640+
641+
# Examples
642+
643+
Basic usage:
644+
645+
```
646+
#![feature(no_panic_pow)]
647+
", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));
648+
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);",
649+
$EndFeature, "
650+
```"),
651+
652+
#[unstable(feature = "no_panic_pow", issue = "48320")]
653+
#[inline]
654+
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
655+
let mut base = self;
656+
let mut acc: Self = 1;
657+
658+
while exp > 1 {
659+
if (exp & 1) == 1 {
660+
acc = acc.checked_mul(base)?;
661+
}
662+
exp /= 2;
663+
base = base.checked_mul(base)?;
664+
}
665+
666+
// Deal with the final bit of the exponent separately, since
667+
// squaring the base afterwards is not necessary and may cause a
668+
// needless overflow.
669+
if exp == 1 {
670+
acc = acc.checked_mul(base)?;
671+
}
672+
673+
Some(acc)
674+
}
675+
}
676+
637677
doc_comment! {
638678
concat!("Saturating integer addition. Computes `self + rhs`, saturating at the numeric
639679
bounds instead of overflowing.
@@ -713,6 +753,34 @@ $EndFeature, "
713753
}
714754
}
715755

756+
doc_comment! {
757+
concat!("Saturating integer exponentiation. Computes `self.pow(exp)`,
758+
saturating at the numeric bounds instead of overflowing.
759+
760+
# Examples
761+
762+
Basic usage:
763+
764+
```
765+
#![feature(no_panic_pow)]
766+
", $Feature, "use std::", stringify!($SelfT), ";
767+
768+
assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);
769+
assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);
770+
assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);",
771+
$EndFeature, "
772+
```"),
773+
#[unstable(feature = "no_panic_pow", issue = "48320")]
774+
#[inline]
775+
pub fn saturating_pow(self, exp: u32) -> Self {
776+
match self.checked_pow(exp) {
777+
Some(x) => x,
778+
None if self < 0 && exp % 2 == 1 => Self::min_value(),
779+
None => Self::max_value(),
780+
}
781+
}
782+
}
783+
716784
doc_comment! {
717785
concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the
718786
boundary of the type.
@@ -947,6 +1015,46 @@ $EndFeature, "
9471015
}
9481016
}
9491017

1018+
doc_comment! {
1019+
concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`,
1020+
wrapping around at the boundary of the type.
1021+
1022+
# Examples
1023+
1024+
Basic usage:
1025+
1026+
```
1027+
#![feature(no_panic_pow)]
1028+
", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81);
1029+
assert_eq!(3i8.wrapping_pow(5), -13);
1030+
assert_eq!(3i8.wrapping_pow(6), -39);",
1031+
$EndFeature, "
1032+
```"),
1033+
#[unstable(feature = "no_panic_pow", issue = "48320")]
1034+
#[inline]
1035+
pub fn wrapping_pow(self, mut exp: u32) -> Self {
1036+
let mut base = self;
1037+
let mut acc: Self = 1;
1038+
1039+
while exp > 1 {
1040+
if (exp & 1) == 1 {
1041+
acc = acc.wrapping_mul(base);
1042+
}
1043+
exp /= 2;
1044+
base = base.wrapping_mul(base);
1045+
}
1046+
1047+
// Deal with the final bit of the exponent separately, since
1048+
// squaring the base afterwards is not necessary and may cause a
1049+
// needless overflow.
1050+
if exp == 1 {
1051+
acc = acc.wrapping_mul(base);
1052+
}
1053+
1054+
acc
1055+
}
1056+
}
1057+
9501058
doc_comment! {
9511059
concat!("Calculates `self` + `rhs`
9521060
@@ -1202,6 +1310,56 @@ $EndFeature, "
12021310
doc_comment! {
12031311
concat!("Raises self to the power of `exp`, using exponentiation by squaring.
12041312
1313+
Returns a tuple of the exponentiation along with a bool indicating
1314+
whether an overflow happened.
1315+
1316+
# Examples
1317+
1318+
Basic usage:
1319+
1320+
```
1321+
#![feature(no_panic_pow)]
1322+
", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false));
1323+
assert_eq!(3i8.overflowing_pow(5), (-13, true));",
1324+
$EndFeature, "
1325+
```"),
1326+
#[unstable(feature = "no_panic_pow", issue = "48320")]
1327+
#[inline]
1328+
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
1329+
let mut base = self;
1330+
let mut acc: Self = 1;
1331+
let mut overflown = false;
1332+
// Scratch space for storing results of overflowing_mul.
1333+
let mut r;
1334+
1335+
while exp > 1 {
1336+
if (exp & 1) == 1 {
1337+
r = acc.overflowing_mul(base);
1338+
acc = r.0;
1339+
overflown |= r.1;
1340+
}
1341+
exp /= 2;
1342+
r = base.overflowing_mul(base);
1343+
base = r.0;
1344+
overflown |= r.1;
1345+
}
1346+
1347+
// Deal with the final bit of the exponent separately, since
1348+
// squaring the base afterwards is not necessary and may cause a
1349+
// needless overflow.
1350+
if exp == 1 {
1351+
r = acc.overflowing_mul(base);
1352+
acc = r.0;
1353+
overflown |= r.1;
1354+
}
1355+
1356+
(acc, overflown)
1357+
}
1358+
}
1359+
1360+
doc_comment! {
1361+
concat!("Raises self to the power of `exp`, using exponentiation by squaring.
1362+
12051363
# Examples
12061364
12071365
Basic usage:
@@ -1887,6 +2045,44 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature,
18872045
}
18882046
}
18892047

2048+
doc_comment! {
2049+
concat!("Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
2050+
overflow occurred.
2051+
2052+
# Examples
2053+
2054+
Basic usage:
2055+
2056+
```
2057+
#![feature(no_panic_pow)]
2058+
", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));
2059+
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
2060+
```"),
2061+
#[unstable(feature = "no_panic_pow", issue = "48320")]
2062+
#[inline]
2063+
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
2064+
let mut base = self;
2065+
let mut acc: Self = 1;
2066+
2067+
while exp > 1 {
2068+
if (exp & 1) == 1 {
2069+
acc = acc.checked_mul(base)?;
2070+
}
2071+
exp /= 2;
2072+
base = base.checked_mul(base)?;
2073+
}
2074+
2075+
// Deal with the final bit of the exponent separately, since
2076+
// squaring the base afterwards is not necessary and may cause a
2077+
// needless overflow.
2078+
if exp == 1 {
2079+
acc = acc.checked_mul(base)?;
2080+
}
2081+
2082+
Some(acc)
2083+
}
2084+
}
2085+
18902086
doc_comment! {
18912087
concat!("Saturating integer addition. Computes `self + rhs`, saturating at
18922088
the numeric bounds instead of overflowing.
@@ -1953,6 +2149,32 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se
19532149
}
19542150
}
19552151

2152+
doc_comment! {
2153+
concat!("Saturating integer exponentiation. Computes `self.pow(exp)`,
2154+
saturating at the numeric bounds instead of overflowing.
2155+
2156+
# Examples
2157+
2158+
Basic usage:
2159+
2160+
```
2161+
#![feature(no_panic_pow)]
2162+
", $Feature, "use std::", stringify!($SelfT), ";
2163+
2164+
assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);
2165+
assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);",
2166+
$EndFeature, "
2167+
```"),
2168+
#[unstable(feature = "no_panic_pow", issue = "48320")]
2169+
#[inline]
2170+
pub fn saturating_pow(self, exp: u32) -> Self {
2171+
match self.checked_pow(exp) {
2172+
Some(x) => x,
2173+
None => Self::max_value(),
2174+
}
2175+
}
2176+
}
2177+
19562178
doc_comment! {
19572179
concat!("Wrapping (modular) addition. Computes `self + rhs`,
19582180
wrapping around at the boundary of the type.
@@ -2147,6 +2369,44 @@ assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, "
21472369
}
21482370
}
21492371

2372+
doc_comment! {
2373+
concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`,
2374+
wrapping around at the boundary of the type.
2375+
2376+
# Examples
2377+
2378+
Basic usage:
2379+
2380+
```
2381+
#![feature(no_panic_pow)]
2382+
", $Feature, "assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243);
2383+
assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
2384+
```"),
2385+
#[unstable(feature = "no_panic_pow", issue = "48320")]
2386+
#[inline]
2387+
pub fn wrapping_pow(self, mut exp: u32) -> Self {
2388+
let mut base = self;
2389+
let mut acc: Self = 1;
2390+
2391+
while exp > 1 {
2392+
if (exp & 1) == 1 {
2393+
acc = acc.wrapping_mul(base);
2394+
}
2395+
exp /= 2;
2396+
base = base.wrapping_mul(base);
2397+
}
2398+
2399+
// Deal with the final bit of the exponent separately, since
2400+
// squaring the base afterwards is not necessary and may cause a
2401+
// needless overflow.
2402+
if exp == 1 {
2403+
acc = acc.wrapping_mul(base);
2404+
}
2405+
2406+
acc
2407+
}
2408+
}
2409+
21502410
doc_comment! {
21512411
concat!("Calculates `self` + `rhs`
21522412
@@ -2353,7 +2613,55 @@ assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $E
23532613
pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
23542614
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
23552615
}
2616+
}
23562617

2618+
doc_comment! {
2619+
concat!("Raises self to the power of `exp`, using exponentiation by squaring.
2620+
2621+
Returns a tuple of the exponentiation along with a bool indicating
2622+
whether an overflow happened.
2623+
2624+
# Examples
2625+
2626+
Basic usage:
2627+
2628+
```
2629+
#![feature(no_panic_pow)]
2630+
", $Feature, "assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false));
2631+
assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
2632+
```"),
2633+
#[unstable(feature = "no_panic_pow", issue = "48320")]
2634+
#[inline]
2635+
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
2636+
let mut base = self;
2637+
let mut acc: Self = 1;
2638+
let mut overflown = false;
2639+
// Scratch space for storing results of overflowing_mul.
2640+
let mut r;
2641+
2642+
while exp > 1 {
2643+
if (exp & 1) == 1 {
2644+
r = acc.overflowing_mul(base);
2645+
acc = r.0;
2646+
overflown |= r.1;
2647+
}
2648+
exp /= 2;
2649+
r = base.overflowing_mul(base);
2650+
base = r.0;
2651+
overflown |= r.1;
2652+
}
2653+
2654+
// Deal with the final bit of the exponent separately, since
2655+
// squaring the base afterwards is not necessary and may cause a
2656+
// needless overflow.
2657+
if exp == 1 {
2658+
r = acc.overflowing_mul(base);
2659+
acc = r.0;
2660+
overflown |= r.1;
2661+
}
2662+
2663+
(acc, overflown)
2664+
}
23572665
}
23582666

23592667
doc_comment! {

0 commit comments

Comments
 (0)