arithmetic: fix PerThing pow (#9030)

* arithmetic: add failing test for pow

* arithmetic: fix PerThing::pow

* Revert back to previous optimisations

Co-authored-by: Gav Wood <gavin@parity.io>
This commit is contained in:
André Silva
2021-06-06 09:07:29 +01:00
committed by GitHub
parent c44b552d8f
commit f0c5699bc6
@@ -639,20 +639,20 @@ macro_rules! implement_per_thing {
impl Pow<usize> for $name { impl Pow<usize> for $name {
type Output = Self; type Output = Self;
fn pow(self, exp: usize) -> Self::Output { fn pow(mut self, exp: usize) -> Self::Output {
if exp == 0 || self.is_one() { if exp == 0 || self.is_one() {
return Self::one() return Self::one()
} }
let mut result = self; let mut result = self;
let mut exp = exp - 1; let mut exp = exp - 1;
while exp > 0 && !result.is_zero() { while exp > 0 && !result.is_zero() {
if exp % 2 == 0 { if exp % 2 != 0 {
result = result.square();
exp /= 2;
} else {
result = result * self; result = result * self;
exp -= 1; exp -= 1;
} }
self = self.square();
exp /= 2;
} }
result result
} }
@@ -1107,11 +1107,13 @@ macro_rules! implement_per_thing {
$name::from_parts($max / 2).square(), $name::from_parts($max / 2).square(),
); );
// x^3 // x^2 .. x^16
assert_eq!( for n in 1..=16 {
$name::from_parts($max / 2).saturating_pow(3), assert_eq!(
$name::from_parts($max / 8), $name::from_parts($max / 2).saturating_pow(n),
); $name::from_parts(($max as u128 / 2u128.pow(n as u32)) as $type),
);
}
// 0^n == 0 // 0^n == 0
assert_eq!( assert_eq!(