I wrote the following modulo exponentiation. But I am not sure if I will loose precision when converting from MPZ type to long.
def mypowmod(base, power, modulus):
base = gmpy.mpz(base)
power = gmpy.mpz(power)
modulus = gmpy.mpz(modulus)
result = pow(base, power, modulus)
return long(result)
Disclaimer: I am the maintainer of gmpy
and gmpy2
.
The Python long type is arbitrary precision. Conversion to/from long
and mpz
are always exact.
Since long
is arbitrary precision, the built-in pow() function will calculate the correct result without requiring the use of gmpy
or gmpy2
. However, using the mpz
type will be much faster. A quick test shows that it is faster even for number of only 10 digits.
$ python -m timeit -s "import gmpy;a=10;b=gmpy.mpz('1'*a);p=gmpy.mpz('2'*a)-7;m=gmpy.mpz('3'*a)+11" "pow(b,p,m)"
1000000 loops, best of 3: 1.41 usec per loop
$ python -m timeit -s "a=10;b=long('1'*a);p=long('2'*a)-7;m=long('3'*a)+11" "pow(b,p,m)"
100000 loops, best of 3: 8.89 usec per loop
gmpy
does not have a powmod() function. That function was introduced in gmpy2
. gmpy2.powmod
will automatically convert the arguments to mpz
and return an mpz
result. Your function could be written as:
def mypowmod(base, power, modulus):
return long(gmpy2.powmod(base, power modulus)
Even including the conversion between long
and mpz
, it is still much faster than using the built-in long
type.
python -m timeit -s "import gmpy2;a=10;b=long('1'*a);p=long('2'*a)-7;m=long('3'*a)+11" "long(gmpy2.powmod(b,p,m))"
1000000 loops, best of 3: 1.72 usec per loop