Files
troupe-standup/wizard-work/beam/mod_inverse.py
T

32 lines
763 B
Python

"""Modular multiplicative inverse via extended Euclid.
modinv(a, m) returns x in [0, m) with a*x ≡ 1 (mod m), or None when
gcd(a, m) != 1 (no inverse exists). Handles negative a, m>1 only.
"""
def egcd(a, b):
if b == 0:
return (a, 1, 0)
g, x1, y1 = egcd(b, a % b)
return (g, y1, x1 - (a // b) * y1)
def modinv(a, m):
if not isinstance(m, int) or m <= 1:
raise ValueError("modulus must be int > 1")
a = a % m
g, x, _ = egcd(a, m)
if g != 1 and g != -1:
# normalize gcd sign
if g < 0:
g = -g
x = -x
if g != 1:
return None
x %= m
# verify
if (a * x) % m != 1:
return None
return x
if __name__ == "__main__":
print(modinv(3, 11))