The primitive PRS algorithm returns the gcd in R[x] full
This proof shows: correctness.
Setting. R is a unique factorization domain with field of fractions K. A polynomial in R[x] is primitive when its coefficients have no common prime factor. We use two forms of Gauss's lemma: (G1) a product of primitive polynomials is primitive; (G2) if p,q∈R[x] are primitive and p=λq with λ∈K∗, then λ is a unit of R. (G2) follows from (G1) by clearing denominators: write λ=a/b with a,b∈R coprime; then bp=aq, the content of the left side is b and of the right side is a, up to units, so a and b are units.
Lemma 1. For f,g∈R[x] not both zero, gcd(f,g)=gcd(contf,contg)⋅gcd(ppf,ppg) up to a unit. Proof. Any common divisor d of f and g splits as cont(d)pp(d). By (G1) the content of f=cont(f)pp(f) factors by contents, so cont(d)∣cont(f) and pp(d)∣pp(f), and the same for g. Conversely the product on the right divides both f and g. □
Lemma 2. Let A,B∈R[x] with B=0 and degA≥degB. Then prem(A,B)=LC(B)e(AmodB) with e=degA−degB+1, where AmodB is the remainder in K[x]. In particular degprem(A,B)<degB, and gcdK[x](A,B)=gcdK[x](B,prem(A,B)). Proof. LC(B)eA=QB+r in R[x] with degr<degB, by the pseudo-division algorithm. Divide by LC(B)e=0: then A=(Q/LC(B)e)B+r/LC(B)e, and by uniqueness of division in K[x], r/LC(B)e=AmodB. A polynomial divides A and B exactly when it divides B and A−qB. □
The algorithm. Lines L1 to L3 handle the cases where f or g is 0: gcd(0,0)=0 and gcd(f,0)=f up to a unit. Otherwise, after line L2, degf≥degg≥0 and g=0. By Lemma 1 it is enough to show that the loop returns gcd(ppf,ppg) (times c), or c when this gcd is 1.
Invariant. At line L5, A and B are primitive, B=0, degA≥degB, and gcdK[x](A,B)=gcdK[x](ppf,ppg) up to a factor in K∗.
It holds at the start. In a pass, let r=prem(A,B). If r=0, then the new pair is (B,pp(r)); pp(r) is primitive, pp(r) is r times an element of K∗, and by Lemma 2 degpp(r)<degB and gcdK[x](B,pp(r))=gcdK[x](B,r)=gcdK[x](A,B). So the invariant holds again.
Termination. degB falls strictly in each pass and is at least 0, so the loop ends after at most degg+1 passes.
Result. There are two ways to leave the loop.
(i) Line L7: r=0. Then B divides A in K[x], so gcdK[x](A,B)=B up to K∗. By the invariant, B=λh with h=gcdR[x](ppf,ppg) and λ∈K∗; here we use that a gcd in R[x] of two primitive polynomials is primitive and is a gcd in K[x] (it divides both in K[x], and every divisor in K[x] becomes, after making it primitive, a divisor in R[x] by (G1)). Both B and h are primitive, so by (G2) λ is a unit of R, and B is the gcd in R[x]. Line L7 returns c⋅B, which is gcd(f,g) by Lemma 1.
(ii) Line L9: degB=0, so B is a nonzero constant, and it is a unit of K. So gcdK[x](ppf,ppg)=1, and the primitive gcd h in R[x] has degree 0; being primitive, it is a unit of R. Line L9 returns c, which is gcd(f,g) by Lemma 1.
Over Z, the content is taken with the sign of the leading coefficient, so every B has a positive leading coefficient, c>0, and the returned gcd is the normalized one. ■