From 162a1cd8a2dff5e74b8696448fad06dbee20f7e3 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Fri, 15 Jan 2016 11:57:51 +0100 Subject: [PATCH] Power for uint --- src/uint.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/uint.rs b/src/uint.rs index 038c85458..f644cdb25 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -183,6 +183,64 @@ macro_rules! construct_uint { } impl $name { + + pub fn pow(self, expon: $name) -> $name { + if expon == $name::zero() { + return $name::one() + } + let is_even = |x : &$name| x.low_u64() & 1 == 0; + + let u_one = $name::one(); + let u_two = $name::from(2); + let mut y = u_one; + let mut n = expon; + let mut x = self; + while n > u_one { + if is_even(&n) { + x = x * x; + n = n / u_two; + } else { + y = x * y; + x = x * x; + n = (n - u_one) / u_two; + } + } + x * y + } + + pub fn overflowing_pow(self, expon: $name) -> ($name, bool) { + if expon == $name::zero() { + return ($name::one(), false) + } + let is_even = |x : &$name| x.low_u64() & 1 == 0; + + let u_one = $name::one(); + let u_two = $name::from(2); + let mut y = u_one; + let mut n = expon; + let mut x = self; + let mut overflow = false; + + while n > u_one { + if is_even(&n) { + let (c, mul_overflow) = x.overflowing_mul(x); + x = c; + overflow |= mul_overflow; + n = n / u_two; + } else { + let (new_y, y_overflow) = x.overflowing_mul(y); + let (new_x, x_overflow) = x.overflowing_mul(x); + x = new_x; + y = new_y; + overflow |= y_overflow | x_overflow; + + n = (n - u_one) / u_two; + } + } + let (res, mul_overflow) = x.overflowing_mul(y); + (res, mul_overflow | overflow) + } + /// Multiplication by u32 fn mul_u32(self, other: u32) -> $name { let $name(ref arr) = self; @@ -894,6 +952,33 @@ mod tests { assert_eq!(U256::from(1000u64).mul_u32(50), U256::from(50000u64)); } + #[test] + fn uint256_pow () { + assert_eq!(U256::from(10).pow(U256::from(0)), U256::from(1)); + assert_eq!(U256::from(10).pow(U256::from(1)), U256::from(10)); + assert_eq!(U256::from(10).pow(U256::from(2)), U256::from(100)); + assert_eq!(U256::from(10).pow(U256::from(3)), U256::from(1000)); + assert_eq!(U256::from(10).pow(U256::from(20)), U256::exp10(20)); + } + + #[test] + #[should_panic] + fn uint256_pow_overflow () { + U256::from(2).pow(U256::from(0x001)); + } + + #[test] + fn uint256_overflowing_pow () { + assert_eq!( + U256::from(2).overflowing_pow(U256::from(0xfe)), + (U256::zero(), false) + ); + assert_eq!( + U256::from(2).overflowing_pow(U256::from(0x001)), + (U256::zero(), true) + ); + } + #[test] pub fn uint256_mul1() { assert_eq!(U256::from(1u64) * U256::from(10u64), U256::from(10u64));