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