(** A generalized gcd: it additionnally keeps track of the divisors. *)
Fixpoint Zggcdn (n:nat) : Z -> Z -> (Z*(Z*Z)) := fun a b =>
match n with
| O => (1,(a,b))   (*(Zabs b,(0,Zsgn b))*)
| S n => match a with
| Z0 => (Zabs b,(0,Zsgn b))
| Zpos _ =>
let (q,r) := Zdiv_eucl b a in   (* b = q*a+r *)
let (g,p) := Zggcdn n r a in
let (rr,aa) := p in        (* r = g *rr /\ a = g * aa *)
(g,(aa,q*aa+rr))
| Zneg a =>
let (q,r) := Zdiv_eucl b (Zpos a) in  (* b = q*(-a)+r *)
let (g,p) := Zggcdn n r (Zpos a) in
let (rr,aa) := p in         (* r = g*rr /\ (-a) = g * aa *)
(g,(-aa,q*aa+rr))
end
end.
Definition Zggcd a b : Z * (Z * Z) := Zggcdn (Zgcd_bound a) a b.
(** The first component of [Zggcd] is [Zgcd] *)

(* Specifications: *)
Lemma Zggcdn_gcdn : forall n a b,
fst (Zggcdn n a b) = Zgcdn n a b.
Lemma Zggcd_gcd : forall a b, fst (Zggcd a b) = Zgcd a b.
(** [Zggcd] always returns divisors that are coherent with its first output. *)
Lemma Zggcdn_correct_divisors : forall n a b,
let (g,p) := Zggcdn n a b in
let (aa,bb):=p in
a=g*aa /\ b=g*bb.
Lemma Zggcd_correct_divisors : forall a b,
let (g,p) := Zggcd a b in
let (aa,bb):=p in
a=g*aa /\ b=g*bb.