I'm trying to find a way to implement EEA using uint64_t
in C, on a system that will not support 128-bit integers. The problem is that it seems like there is always a case where some variable or another will overflow, generating incorrect results.
I know it can be done in /signed/ machine words, and there are plenty of answers on here and elsewhere that give pseudocode for this. Can it be done with unsigned and no overflow? Or do you need to have a larger integer size available?
The coefficients in the Euclidian algorithm alternate in sign (after the initial zeros vanish), so we can compute them using magnitudes only and reconstructing the sign at the end from the iteration parity.
The extended Euclidian algorithm finds the multiplicative inverses a and b of positive relatively prime integers u and v with respect to each other. That is, we find a and b such that a•u is congruent to 1 modulo v and b•v is congruent to 1 modulo u. We start with two equations:
Then the algorithm is:
This implements the Euclidean algorithm on the left side of the equation, so we know it terminates in 1 for relatively prime u and v. Then the last equation has the form:
In this, it is clear a is a multiplicative inverse of u modulo v and b is a multiplicative inverse of b modulo u.
Observe that in the third equation, the coefficient of u will be 1−0•q. Thus, it will be positive. And the coefficient of v will be 0−1•q. Thus, it will be negative. In the fourth equation, the coefficient of u will be positive. From that point on, we are always subtracting a negative number from a positive number or a positive number from a negative number, and thus we alternate signs.
In the nth equation, the coefficient of u is non-negative if n is odd and non-positive if n is even, and vice-versa for the coefficient of v.
Therefore, we can implement this with unsigned arithmetic by keeping only the magnitudes of the coefficients:
Example for 13 and 10:
At this point, whatever variable we are using to hold the coefficient of u (13) contains 3, but we know it is negative because we are in an even iteration (the fourth). So an inverse of u is −3. If desired, we can add u (calculated as u minus the stored magnitude) to get a positive result.
I have proven these calculations never exceed v for the coefficient of u or u for the coefficient of v but do not have access to that proof. (It is embedded in source code for a previous employer.)