32 lines
763 B
Python
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))
|