Merge pull request #5860 from paritytech/minor-modexp-optimization

minor optimizations of the modexp builtin
This commit is contained in:
Robert Habermeier 2017-06-18 18:20:59 +02:00 committed by GitHub
commit a99d4c3dd3
1 changed files with 35 additions and 34 deletions

View File

@ -288,9 +288,11 @@ impl Impl for ModexpImpl {
let exp = read_num(exp_len);
let modulus = read_num(mod_len);
// calculate modexp: exponentiation by squaring.
// calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular.
fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint {
match (base == BigUint::zero(), exp == BigUint::zero()) {
use num::Integer;
match (base.is_zero(), exp.is_zero()) {
(_, true) => return BigUint::one(), // n^0 % m
(true, false) => return BigUint::zero(), // 0^n % m, n>0
(false, false) if modulus <= BigUint::one() => return BigUint::zero(), // a^b % 1 = 0.
@ -301,10 +303,9 @@ impl Impl for ModexpImpl {
base = base % &modulus;
// fast path for base divisible by modulus.
if base == BigUint::zero() { return result }
while exp != BigUint::zero() {
// exp has to be on the right here to avoid move.
if BigUint::one() & &exp == BigUint::one() {
if base.is_zero() { return result }
while !exp.is_zero() {
if exp.is_odd() {
result = (result * &base) % &modulus;
}