minor optimizations of the modexp builtin
This commit is contained in:
parent
8d04dffe69
commit
ca27234a59
@ -288,9 +288,11 @@ impl Impl for ModexpImpl {
|
|||||||
let exp = read_num(exp_len);
|
let exp = read_num(exp_len);
|
||||||
let modulus = read_num(mod_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 {
|
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) => return BigUint::one(), // n^0 % m
|
||||||
(true, false) => return BigUint::zero(), // 0^n % m, n>0
|
(true, false) => return BigUint::zero(), // 0^n % m, n>0
|
||||||
(false, false) if modulus <= BigUint::one() => return BigUint::zero(), // a^b % 1 = 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;
|
base = base % &modulus;
|
||||||
|
|
||||||
// fast path for base divisible by modulus.
|
// fast path for base divisible by modulus.
|
||||||
if base == BigUint::zero() { return result }
|
if base.is_zero() { return result }
|
||||||
while exp != BigUint::zero() {
|
while !exp.is_zero() {
|
||||||
// exp has to be on the right here to avoid move.
|
if exp.is_odd() {
|
||||||
if BigUint::one() & &exp == BigUint::one() {
|
|
||||||
result = (result * &base) % &modulus;
|
result = (result * &base) % &modulus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user