The extended Euclidian algorithm
The extended Euclidian algorithm is based on the Euclidian algorithm, which finds the greatest common divisor of two numbers . The extended Euclidian algorithm also does some bookkeeping, which allows it to express the greatest common divisor as a linear combination of and . For example, if we run the Euclidian algorithm for , we find that . Now, running the Euclidian algorithm tells us that and additionally tells us that .
Theory
If we suppose that the Euclidian algorithm is used to find the greatest common divisor of where , we can formulate the algorithm as a recurrent relation
which is then applied until , in which case is the greatest common divisor of and .
The extended Euclidian algorithm now keeps numbers such that
Obviously, we have and . Using that , we see that
To find and , use that . Using and we see that
factoring out and , we see that
so we see that
Implementation
Normally I try to give an implementation that works in C-style languages. However, the C-style languages are rather primitive in the sense that they provide no uniform and comfortable way to use tuples, so I will use Python for now.
Like in the implementation for Euclids algorithm, we have a wrapper that ensures that the first argument is always the biggest. The wrapper returns a triple (gcd, p, q), such that gcd is the greatest common divisor, and we have .
def gcd_extended(a, b):
if a < b:
(gcd, p, q) = gcd_extended_helper(b, 1, 0, a, 0, 1)
return (gcd, q, p)
else: return gcd_extended_helper(a, 1, 0, b, 0, 1)
Like for Euclids algorithm, we can use a recursive implementation
def gcd_extended_helper(a, p, q, b, r, s):
if b == 0: return (a, p, q)
k = a // b;
return gcd_extended_helper(b, r, s, a - k * b, p - k * r, q - k * s)
or an iterative one
def gcd_extended_helper(a, p, q, b, r, s):
while b != 0:
(a, p, q, b, r, s) = (b, r, s, a - k * b, p - k * r, q - k * s)
return (a, p, q)
Applications
When modular arithmetic modulo some number , we may want to find a multiplicative inverse of the element . That is, we want to find such that
Now, such an element only exists if , which is why it is often convenient to take prime (we can take any ). Now, note that if , then we have . So is the element we’re looking for.
Now we can define a function that computes the multiplicative inverse modulo as follows:
def inverse_modulo(a, n):
(gcd, p, q) = gcd_extended(a, n)
return p