(** We implement the extended version of Euclid's algorithm, i.e. the one computing Bezout's coefficients as it computes the [gcd]. We follow the algorithm given in Knuth's "Art of Computer Programming", vol 2, page 325. *)
Section extended_euclid_algorithm.
Variables a b : Z.
Local Lemma extgcd_rec_helper r1 r2 q :
Z.gcd r1 r2 = Z.gcd a b -> Z.gcd (r2 - q * r1) r1 = Z.gcd a b.
Let f := S(S(Z.to_nat(Z.log2_up(Z.log2_up(Z.abs(a*b)))))). (* log2(fuel) *)
Local Definition extgcd_rec : forall r1 u1 v1 r2 u2 v2,
(True -> 0 <= r1 /\ 0 <= r2 /\ r1 = u1 * a + v1 * b /\ r2 = u2 * a + v2 * b /\
Z.gcd r1 r2 = Z.gcd a b)
-> { '(u, v, d) | True -> u * a + v * b = d /\ d = Z.gcd a b}.
(** * Bezout's coefficients *)
Inductive Bezout (a b d:Z) : Prop :=
Bezout_intro : forall u v:Z, u * a + v * b = d -> Bezout a b d.
(** Existence of Bezout's coefficients for the [gcd] of [a] and [b] *)

(* Specifications: *)
Lemma Zis_gcd_bezout : forall a b d:Z, Zis_gcd a b d -> Bezout a b d.
(** gcd of [ca] and [cb] is [c gcd(a,b)]. *)
Lemma Zis_gcd_mult :
forall a b c d:Z, Zis_gcd a b d -> Zis_gcd (c * a) (c * b) (c * d).