Talk:Extended Euclidean algorithm

message: hello. Don't you think it is confusing to have this gcd/hcf thing all along the text?
I believe that if this hcf thing is really important at all, this alternative name should stick to that phrase in the first sentence.
If someone here really belives that HCF is the best name to call the gcd, then perhaps we can change the whole text to hcf, and keep gcd only in the first sentence.  It's extremelly awkward to me, but it's better than having the operation called by two names all the time, don't you think?...
Every mathematical text have this problem with what nomenclature to adopt. This is to be defined on a prologue, and the rest of the text should use a unique notation and nomenclature. Bringing the problem to the body of the text is extremmlly confuse.
: agree 100% ... should stick to gcd after introduction Dmharvey  Talk 9 July 2005 14:02 (UTC)
Also for the pseudocode below, it would be nice to mention that "<>" means not equals to. Does any programming language use that syntax. Is it a standard syntax used in psuedocode?
:Several languages use it, mostly notably BASIC. It should use ≠ in the article, however. Deco 01:45, 14 December 2005 (UTC)
thread_title:  gcd/hcf 

message: Notice that the first method in article is iterative rather than recusive in nature: it employs the quotient in the same order they appear/ the algorithm proceed forward. Compare this with the second method described, which is really a recursion and notice how they use the quotient in the reverse order they appear/ it work backward. Thus it is reasonable that the pseudocode is so long and seemingly complicated in the first method: it uses recursion rather than iteration. I suggest the code and the function call can be rewritten in an iterative fashion. Thanks. --Lemontea 14:47, 26 January 2006 (UTC)
thread_title:  The two methods 

message: I've refactored quite some sections of this article, here are something I would like to see get handled:
# Cleanup the informal description part I've written. Proofread it, check its tone, etc.
# Help format the table and layout of this article in general.(e.g. the last table in the iterative method section could do some highlighting, just as the last table do)
# Gives commments on the style of the informal formulation section: is it suitable to intermix the example with the theory(that is, explain the theory, then demostrate it in action, then some theory again, and so on), or is it good to completely separate them? Partly because of the messy nature of this algorithm, and partly because of easy understanding and readibility(could have drowned off if it were pure theory), I've chosen the first one.
# Does The formal description part need a description of finding out x and y: just like those written out by bulleted list(see other algorithm page for examples), or does the pseudocode suffice?
That's all I can think up with now. Thanks.
--Lemontea 15:15, 17 February 2006 (UTC)
thread_title:  Leftover 

message: I removed a link to an .exe file (presumably a Windows executable, compiled from one of the source code examples). Since there are other, safer, demonstrations, I think it's worth it to minimise the risk of Wikipedia being used to spread malicious software.
In case someone strongly disagrees, I left the original link commented out in the references section.
Robert 21:35, 11 May 2006 (UTC)
thread_title:  Link to .exe file 

message: There is a representation of the EEA step -- that x_{i+1}=x_{i-1}-q_i x_i; y_{i+1}=y_{i-1}-q_i y_i thing -- as a matrix multiplication. Mine source is Gregory & Krishnamurthy, "Methods and Applications of Error-Free Computation", Springer, 1984. The respresentation itself is
:\begin{bmatrix}x_{i+1} & y_{i+1}\end{bmatrix}=\begin{bmatrix}1 &-q_i\end{bmatrix}\begin{bmatrix}x_{i-1} & y_{i-1}\\x_{i} & y_{i}\end{bmatrix}
and is IMHO rather understandable and brings some more insight as the notation used in this article. --88.68.34.243 12:44, 9 June 2006 (UTC)
thread_title:  Matrix form 

message: I have cleaned up the iterative method section and used equations to express what was previously written only as text.  I hope this new version is much clearer. Cintrom (talk) 18:42, 21 January 2008 (UTC)
thread_title:  Iterative method 

message: "In this case, the remainder in the last but one line (which is 1) indicates that the gcd is 1; that is, 120 and 23 are coprime (also called relatively prime)." As a reader, I'm completely unable to parse what the heck "in the last but one line (which is 1)" is supposed to mean. What is a in-the-last-but-one-line?  —Preceding unsigned comment added by 146.113.43.88 (talk) 20:43, 7 February 2008 (UTC)
replies: text: There are five lines. The last line is the fifth line. The last-but-one line is the fourth line. This might be clearer with hyphens. Algebraist 13:01, 8 March 2008 (UTC)
thread_title:  Unclear wording 

message: I'd suggest the recursive version should return the gcd.  Then the proof of correctness doesn't have to link off to another article.  The code to return the triple becomes something like:
 euc' a 0 = (1, 0, a)
 euc' a b = (k,j-k*(div a b), g)
   where (j, k, g) = euc' b (mod a b)
We could (but probably shouldn't) include a pretty print:
 euc a b  = (show n) ++ "*" ++ (show a) ++ " + " ++ (show m) ++ "*" ++ (show b) ++ " = " ++ (show g)
   where (n,m,g) = euc' a b
jbolden1517Talk 17:29, 11 December 2008 (UTC)
thread_title:  recursive version with gcd 

message: My revert of User:Luckyblue1's deletion of the C implementation was itself reverted by Special:Contributions/130.86.206.33.  All of the edits were without explanation, and so I was perhaps rather quick to assume vandalism, but then I didn't give an explanation myself either so maybe the latter one assumed I was the vandal here. I am just an occasional editor myself, so to avoid an edit war I am hereby asking here: Should the C implementation stay or not? --Ørjan (talk) 00:53, 21 November 2009 (UTC)
thread_title:  Revert of C implementation deletion? 

message: "Suppose d_i = d_{i-2} - k_{i-1} \cdot d_{i-1}. Then it must be that  "
Hey! Where did k come from? it's not in the table!
"To find the third row of the table in the example, just notice that 120 divided by 23 goes 5 times plus a remainder. This gives us k, the multiplying factor for this row."
So .. which is k? The dividend, or the remainder? Both are 5.  — Preceding unsigned comment added by Paul Murray (talk • contribs) 01:07, 27 January 2011 (UTC)
replies: text: The sentence quoted is another way of saying "Let k_{i-1} = \frac{d_{i-2}-d_i}{d_{i-1}}"; but that may still be a bit obscure.  The point is that you divide d_{i-2} by d_{i-1}, call the integer quotient k_{i-1}, and call the remainder d_i. —Tamfang (talk) 04:08, 27 January 2011 (UTC)
thread_title:  Horribly unclear 

message: The so-called "Proof of correctness" is woefully lacking.  It makes claims like, "we know that..." without first establishing or in any way justifying the conclusion.  It then proceeds with steps which do not appear to follow from that bit which, "we know."  This cannot be called a proof at all, and I suggest it be removed until something vaguely proof-like can be substituted.  --Prestidigitator (talk) 06:48, 6 March 2011 (UTC)
replies: text: I've redone the proof as a proper inductive argument, in the mean time proving termination, cleaning up the algorithm itself so that it avoids dividing a by b twice in (almost) every call, and proving ax + by is nonnegative. Hope this helps. Marc van Leeuwen (talk) 11:38, 6 March 2011 (UTC)
replies: text: Definitely a lot more satisfying and correct from my vantage point Marc.  Well done, and thank you!  --Prestidigitator (talk) 18:03, 6 March 2011 (UTC)
thread_title:  Insufficient Proof 

message: The "external link" "How to use the algorithm by hand" is broken. I don't recall what to do in that case, if s/o knows, please do it. — MFH:Talk 20:08, 7 August 2011 (UTC)
replies: text: It should be deleted. -- X7q (talk) 20:23, 7 August 2011 (UTC)
thread_title:  broken link 

message: This case should be formulated a little bit more careful. For example
if I take the equation:
   1*x + 1*y + 2*z = 1
Then a triple obtained with the algorithm in the article would be
   (1,0,0)
i.e.
   -1 + 1*1 + 1*0 + 2*0 = 0
But I cannot take the triple and generalize it to:
    (1+2*u, 0+2*v, 0-2*u-2*v)
The above would say x is odd and y is even. But there are of
course also solutions where x is even and y is odd. 
So the generalization has to already happen during the calculation
of the triples somehow. So that for example also the following 
triple can be found:
   (0,1,0)
Jan Burse (talk) 19:36, 1 July 2012 (UTC)
thread_title:  Many Variables Case Probably Missleading 

message: The article introduces lengthy confusing explanations that make difficult to the reader to find where the algorithm is described. In particular, it seems that the editors of this article did ignore that an algorithm is like a theorem, it has to be stated separately from its explanation and its proof. The consequence, is that, although I have taught many times this algorithm, I am unable to decide, without a careful reading, if the algorithm(s) which is (are) described is(are) the one that is known under this name. What may understand a non-expert of the subject? I have rewritten the lead. I plan to rewrite the remainder of the article, but, because of the amount of needed work, I am not sure that this will be done soon. D.Lazard (talk) 16:42, 2 November 2013 (UTC)
replies: text: I have began to rewrite the article, and put in "todo" list above the list of edits yet needed. D.Lazard (talk) 23:37, 3 November 2013 (UTC)
thread_title:  The article deserves to be completely rewritten 

message: The recursive algorithm that is presented is not a tail recursion. It follows that, if implemented, it needs an auxiliary memory (in the execution stack) which is not constant and is proportional to the number of recursive calls. It follows that the implementation of this code is not recommended, and as such is not notable. Even if notable, presenting it here would give it a undue weight. There is a tail recursive version of the algorithm, which involve a function with 6
parameters. Its construction from the iterative version of the algorithm is a standard programming exercise, which does not provides any encyclopedic insight to the subject of the article. I'll thus remove the present recursive version and not replacing it by the tail recursive version. However, if someone judges that the tail recursive version is really needed, I'll not oppose to its insertion. D.Lazard (talk) 15:23, 4 November 2013 (UTC)
thread_title:  Recursive method 

message: q_i is not defined at all. Jackzhp (talk) 08:42, 20 April 2016 (UTC)
replies: text: r_{i-1}=q_i*r_i+r_{i+1} given r_{i-1}>r_i, That's to say r_{i+1}=r_{i-1}%r_i and q_i=r_{i-1} / r_i integer division, no decimals. Jackzhp (talk) 08:46, 20 April 2016 (UTC)
thread_title: the definition of <math>q_i</math>

message: I ran into a very clever modular inverse that used an extended form of the binary GCD algorithm. I'm surprised it's not referenced here -- seems like a useful thing to include, especially next time someone wants to take a stab at improving the article. - Taral (talk) 21:04, 11 October 2020 (UTC)
replies: text: Please, provide a reference. Without it, we cannot decide whether it is reliable and notable enough for being included in WP, and, if it is, to decide whether it must be included (here or in Modular inverse). In any case, this article lacks a section "Generalization". In fact, the method used to pass from the Euclidean algorithm to the extended algorithm can be applied to many gcd algorithms, even to algorithms that use fast multiplication. This must appear in the article. D.Lazard (talk) 21:23, 11 October 2020 (UTC)
thread_title:  Binary GCD 

message: I thought I'd post my python code [based on pseudo-code] here just in case anyone runs into similar points of confusion.
    def extended_euclidean_algorithm(a: int, b: int) -> tuple[tuple[int, int], int]:
        """For two ints, (a,b), solves: `a * x + b * y = gcd(a,b)`"""
        (old_r, r) = (a, b)
        (old_x, x) = (1, 0) # We will back out y at the end.
        
        while r != 0:
            quotient = old_r // r # "div" is just integer division!
            
            (old_r, r) = (r, old_r - quotient * r)
            (old_x, x) = (x, old_x - quotient * x)
        
        # Assign the OLD values: when r==0 we've gone too far.
        # If output the most recent `x`, then we'd get a * x + b * y == 0
        # See esp. the example table. 
        x = old_x
        gcd = old_r
        
        # If "gcd < 0" then we know that's not true: If "gcd" is a
        # common divisor, then so is -gcd>0.
        # Relevant for negative numbers.
        # This step is identical to multiplying both sides of the
        # equation by -1.
        if gcd < 0:
            gcd *= -1
            x *= -1
        
        # Fill in y (coeff on b) now that we know other values.
        if b != 0:
            y = (gcd - x * a) // b
        else:
            y = 0
        
        return (x, y), gcd Wobblesome (talk) 18:35, 7 September 2022 (UTC)
thread_title:  Python code 

message: Not too long ago I updated the pseudocode for calculating the `inverse(a,n)` (https://en.wikipedia.org/w/index.php?diff=1154654926&oldid=1150662331&title=Extended_Euclidean_algorithm). As far as I can tell, it doesn't work for negative values of `a` and (if I remember correctly) it won't return the smallest possible number unless a final `mod n` operation is performed before returning the value.
I'm not an expert in the field, although I did have some conviction over the edits given that's how I implemented the `inverse()` function (in Rust), with successful results. Given the edit was reverted, I would like to ask User:D.Lazard if you've had a chance to implement either versions of the pseudocode (my edit or the reverted version)? If you could provide some step by step examples of how the current version would work with negative numbers, for example, or if you have an implementation in any programming language I'd like to take a look.
This is my working Rust implementation
    pub fn mod_mult_inv(a: &BigInt, n: &BigInt) -> Option<BigInt> {
        if n < &BigInt::from(0) {
            panic!("Expected `modulus` to be positive.");
        }
    
        // Ensure `a` is positive. The remaining code expects a positive `a` value.
        let a: BigInt = if a > &BigInt::from(0) {
            a.clone()
        } else {
            // If `a` is negative, find a positive congruent using Euclidean
            // division. Using `a` or any of its congruents will result in the same
            // value being returned from this function.
            //
            // Couldn't find a Euclidean division function, so using `mod_floor`
            // which produces the same results for a positive modulus, as is the
            // case here. See https://en.wikipedia.org/wiki/Modulo
            a.mod_floor(n)
        };
    
        let mut t = BigInt::from(0);
        let mut r = n.clone();
        let mut new_t = BigInt::from(1);
        let mut new_r = a.clone();
    
        while new_r != BigInt::from(0) {
            let quotient = &r / &new_r;
    
            (t, new_t) = (new_t.clone(), &t - "ient * &new_t);
            (r, new_r) = (new_r.clone(), &r - "ient * &new_r)
        }
    
        if r > BigInt::from(1) {
            None
        } else {
            Some(t.mod_floor(&n))
        }
    }
``` Aryzing (talk) 11:18, 6 October 2023 (UTC)
thread_title:  Isn't the `inverse(a,n)` pseudocode wrong?