The C source code for that function can be found here, in GMPy_MPZ_Function_Divm
. As you can see, it's not really a one-to-one mapping to the underlying C code but, when you strip away all the Python reference counting stuff, it looks pretty basic:
// numz, denz, and modz are copies of the arguments.
// resz, gcdz ar temporaries.
if (mpz_invert(resz, denz, modz)) { // inverse exists?
ok = 1;
} else { // num, den AND mod have a gcd > 1?
mpz_init(gcdz);
mpz_gcd(gcdz, numz, denz);
mpz_gcd(gcdz, gcdz, modz);
mpz_divexact(numz, numz, gcdz);
mpz_divexact(denz, denz, gcdz);
mpz_divexact(modz, modz, gcdz);
mpz_clear(gcdz);
ok = mpz_invert(resz, denz, modz);
}
if (ok) {
mpz_mul(resz, resz, numz);
mpz_mod(resz, resz, modz);
mpz_clear(numz);
mpz_clear(denz);
mpz_clear(modz);
return resz;
} else {
mpz_clear(numz);
mpz_clear(denz);
mpz_clear(modz);
return NULL;
}
Mathematically, it just calculates the expression b-1 * a % m
for divm(a, b, m)
, assuming of course that that expression is valid (eg, b
is non-zero).