Section IDomainPseudoDivision.
Variable R : idomainType.
Implicit Type p q r d m n : {poly R}.
Hint Resolve divp0 divp1 mod0p modp0 modp1 : core.
Hint Resolve dvdp0 : core.
Hint Resolve dvdpp : core.
Hint Resolve eqpxx : core.
suff Hmn m n: m %= n -> (m %| p) -> (n %| p).
by move=> ?; apply/idP/idP; apply: Hmn; rewrite // eqp_sym.
by rewrite /eqp; case/andP=> dd' d'd dp; apply: (dvdp_trans d'd).
Qed.
Definition gcdp_rec p q :=
let: (p1, q1) := if size p < size q then (q, p) else (p, q) in
if p1 == 0 then q1 else
let fix loop (n : nat) (pp qq : {poly R}) {struct n} :=
let rr := modp pp qq in
if rr == 0 then qq else
if n is n1.+1 then loop n1 qq rr else rr in
loop (size p1) p1 q1.
Definition gcdp := nosimpl gcdp_rec.
Definition coprimep p q := size (gcdp p q) == 1%N.
(* "gdcop Q P" is the Greatest Divisor of P which is coprime to Q *)
(* if P null, we pose that gdcop returns 1 if Q null, 0 otherwise*)
Fixpoint gdcop_rec q p k :=
if k is m.+1 then
if coprimep p q then p
else gdcop_rec q (divp p (gcdp p q)) m
else (q == 0)%:R.
Definition gdcop q p := gdcop_rec q p (size p).
Variant gdcop_spec q p : {poly R} -> Type :=
GdcopSpec r of (dvdp r p) & ((coprimep r q) || (p == 0))
& (forall d, dvdp d p -> coprimep d q -> dvdp d r)
: gdcop_spec q p r.

Lemma dvdp_gdco p q : (gdcop p q) %| q. Proof. by case: gdcopP. Qed.