Fixpoint gcdGI_rec (n : nat) (xx  yy : GI) {struct n} :=
let rr := modGI xx yy in
if rr == 0 then yy else
if n is n1.+1 then gcdGI_rec n1 yy rr else rr.
Definition gcdGI x y :=
let: (x1, y1) := if ('N x < 'N y)%N then (y, x) else (x, y) in
if x1 == 0 then y1 else
gcdGI_rec ('N x1) x1 y1.

(* Specifications: *)
Lemma gcd0GI : left_id 0 gcdGI.
Lemma gcdGI0 : right_id 0 gcdGI.
Lemma gcdGI_recE m n x y : ('N y <= m)%N -> ('N y <= n)%N
-> ('N y < 'N x)%N -> gcdGI_rec m x y = gcdGI_rec n x y.
Lemma gcdGIE x y :
gcdGI x y = if ('N x < 'N y)%N
then gcdGI (y %% x) x else gcdGI (x %% y) y.
Lemma gcd1GIE y :
gcdGI 1 y = if ('N y == 1)%N then y else 1.
Lemma gcd1GI_norm y : 'N(gcdGI 1 y) = 1%N.
Lemma gcdGIxx : idempotent gcdGI.
Lemma dvdGI_gcdlr x y : (gcdGI x y %| x) && (gcdGI x y %| y).
Lemma dvdGI_gcdl x y : gcdGI x y %| x.
Lemma dvdGI_leq x y : y != 0 -> x %| y -> ('N x <= 'N y)%N.
Lemma leq_gcdGIl (x y : GI) : x != 0 -> ('N (gcdGI x y) <= 'N x)%N.
Lemma dvdGI_gcd x y z : x %| gcdGI y z = (x %| y) && (x %| z).
Lemma dvdGI_mul2r (p d x : GI) :  p != 0 ->  (d * p %| x * p) = (d %| x).
Lemma dvdGI_mul2l (p d x : GI) :  p != 0 ->  (p * d %| p * x) = (d %| x).
Definition eqGI x y :=  (dvdGI x y) && (dvdGI y x).
Lemma eqGIxx : reflexive eqGI.
Infix "%=" := eqGI : GI_scope.
Lemma eqGI0 (x : GI) : (x %= 0) = (x == 0).
Lemma eqGI_eq0  x y : x %= y -> (x == 0) = (y == 0).
Lemma eqGI_norm  x y : x %= y -> 'N x = 'N y.
Lemma dvdGI_eq_norm x y : 'N x = 'N y -> x %| y -> x %= y.
Lemma eqGI_nat m n : m%:R %= n%:R -> m = n.
Lemma conjGI_gcd x y : conjGI (gcdGI x y) %= gcdGI (conjGI x) (conjGI y).
Lemma conjGIM_norm x : x * conjGI x = ('N x)%:R.
Lemma eqGIP (x y : GI) :
reflect (exists2 u, normGI u = 1%N & x = u * y)
(x %= y).
Lemma gcdGIC x y : gcdGI x y %= gcdGI y x.
Lemma eqGI_dvdr x y1 y2 : y1 %= y2 -> (x %| y1) = (x %| y2).
Lemma eqGI_dvdl y x1 x2 : x1 %= x2 -> (x1 %| y) = (x2 %| y).
Lemma eqGI_gcdr x y1 y2 : y1 %= y2 -> gcdGI x y1 %= gcdGI x y2.
Lemma eqGI_gcdl y x1 x2 : x1 %= x2 -> gcdGI x1 y %= gcdGI x2 y.
Lemma eqGI_mul2r (r p q : GI) : r != 0 -> (p * r %= q * r) = (p %= q).
Fixpoint egcdGI_rec n (x y : GI) :=
if y == 0 then (1, 0) else
if n is n1.+1 then
let: (u, v) := egcdGI_rec n1 y (modGI x y) in
(v, u - v * (x %/ y)%GI)
else (1, 0).