Merge pull request #1608 from ethcore/pow-opt

is_zero() and pow() optimisations for uint
This commit is contained in:
Robert Habermeier 2016-07-13 17:33:11 +02:00 committed by GitHub
commit 0f83ef6a0b

View File

@ -687,24 +687,25 @@ macro_rules! construct_uint {
/// Fast exponentation by squaring /// Fast exponentation by squaring
/// https://en.wikipedia.org/wiki/Exponentiation_by_squaring /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
fn pow(self, expon: Self) -> Self { fn pow(self, expon: Self) -> Self {
if expon == Self::zero() { if expon.is_zero() {
return Self::one() return Self::one()
} }
let is_even = |x : &Self| x.low_u64() & 1 == 0; let is_even = |x : &Self| x.low_u64() & 1 == 0;
let u_one = Self::one(); let u_one = Self::one();
let u_two = Self::from(2);
let mut y = u_one; let mut y = u_one;
let mut n = expon; let mut n = expon;
let mut x = self; let mut x = self;
while n > u_one { while n > u_one {
if is_even(&n) { if is_even(&n) {
x = x * x; x = x * x;
n = n / u_two; n = n >> 1;
} else { } else {
y = x * y; y = x * y;
x = x * x; x = x * x;
n = (n - u_one) / u_two; // to reduce odd number by 1 we should just clear the last bit
n.0[$n_words-1] = n.0[$n_words-1] & ((!0u64)>>1);
n = n >> 1;
} }
} }
x * y x * y
@ -713,13 +714,11 @@ macro_rules! construct_uint {
/// Fast exponentation by squaring /// Fast exponentation by squaring
/// https://en.wikipedia.org/wiki/Exponentiation_by_squaring /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
fn overflowing_pow(self, expon: Self) -> (Self, bool) { fn overflowing_pow(self, expon: Self) -> (Self, bool) {
if expon == Self::zero() { if expon.is_zero() { return (Self::one(), false) }
return (Self::one(), false)
}
let is_even = |x : &Self| x.low_u64() & 1 == 0; let is_even = |x : &Self| x.low_u64() & 1 == 0;
let u_one = Self::one(); let u_one = Self::one();
let u_two = Self::from(2);
let mut y = u_one; let mut y = u_one;
let mut n = expon; let mut n = expon;
let mut x = self; let mut x = self;
@ -728,11 +727,11 @@ macro_rules! construct_uint {
while n > u_one { while n > u_one {
if is_even(&n) { if is_even(&n) {
x = overflowing!(x.overflowing_mul(x), overflow); x = overflowing!(x.overflowing_mul(x), overflow);
n = n / u_two; n = n >> 1;
} else { } else {
y = overflowing!(x.overflowing_mul(y), overflow); y = overflowing!(x.overflowing_mul(y), overflow);
x = overflowing!(x.overflowing_mul(x), overflow); x = overflowing!(x.overflowing_mul(x), overflow);
n = (n - u_one) / u_two; n = (n - u_one) >> 1;
} }
} }
let res = overflowing!(x.overflowing_mul(y), overflow); let res = overflowing!(x.overflowing_mul(y), overflow);
@ -1068,7 +1067,7 @@ macro_rules! construct_uint {
impl fmt::Display for $name { impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if *self == $name::zero() { if self.is_zero() {
return write!(f, "0"); return write!(f, "0");
} }
@ -1076,7 +1075,7 @@ macro_rules! construct_uint {
let mut current = *self; let mut current = *self;
let ten = $name::from(10); let ten = $name::from(10);
while current != $name::zero() { while !current.is_zero() {
s = format!("{}{}", (current % ten).low_u32(), s); s = format!("{}{}", (current % ten).low_u32(), s);
current = current / ten; current = current / ten;
} }