Auto merge of #162 - est31:add_checked_pow, r=cuviper
Add checked_pow function Implements a `checked_pow` function which does the same as `pow`, just with overflow checks. And, similar to #152 and #153, the function uses references instead of cloning. Adds a little macro to spare code repetition. Its scoped to the function so nothing gets polluted.
This commit is contained in:
commit
d1adf45389
42
src/lib.rs
42
src/lib.rs
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -164,6 +164,46 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raises a value to the power of exp, returning `None` if an overflow occured.
|
||||||
|
///
|
||||||
|
/// Otherwise same as the `pow` function.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use num;
|
||||||
|
///
|
||||||
|
/// assert_eq!(num::checked_pow(2i8, 4), Some(16));
|
||||||
|
/// assert_eq!(num::checked_pow(7i8, 8), None);
|
||||||
|
/// assert_eq!(num::checked_pow(7u32, 8), Some(5_764_801));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
|
||||||
|
if exp == 0 { return Some(T::one()) }
|
||||||
|
|
||||||
|
macro_rules! optry {
|
||||||
|
( $ expr : expr ) => {
|
||||||
|
if let Some(val) = $expr { val } else { return None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while exp & 1 == 0 {
|
||||||
|
base = optry!(base.checked_mul(&base));
|
||||||
|
exp >>= 1;
|
||||||
|
}
|
||||||
|
if exp == 1 { return Some(base) }
|
||||||
|
|
||||||
|
let mut acc = base.clone();
|
||||||
|
while exp > 1 {
|
||||||
|
exp >>= 1;
|
||||||
|
base = optry!(base.checked_mul(&base));
|
||||||
|
if exp & 1 == 1 {
|
||||||
|
acc = optry!(acc.checked_mul(&base));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(acc)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn hash<T: hash::Hash>(x: &T) -> u64 {
|
fn hash<T: hash::Hash>(x: &T) -> u64 {
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
|
|
Loading…
Reference in New Issue