Let bezout_rec p q : 0 < p < q
-> { a : nat
& { b : nat
& { g : nat
& { l : nat
& { u : nat
& { v : nat
| a*p+b*q = g + l
/\ is_gcd p q g
/\ is_lcm p q l
/\ p = u*g
/\ q = v*g
/\ a <= v
/\ b <= u } } } } } }.
Hint Resolve is_gcd_sym is_lcm_sym.
Definition bezout_generalized p q : { a : nat
& { b : nat
& { g : nat
& { l : nat
| a*p+b*q = g + l
/\ is_gcd p q g
/\ is_lcm p q l } } } }.
End bezout_generalized.
Section gcd_lcm.
Let gcd_full p q : sig (is_gcd p q).
Definition gcd p q := proj1_sig (gcd_full p q).
Fact gcd_spec p q : is_gcd p q (gcd p q).
Definition lcm p q := proj1_sig (lcm_full p q).
Fact lcm_spec p q : is_lcm p q (lcm p q).
Definition div q p := projT1 (div_full q p).
Definition rem q p := proj1_sig (projT2 (div_full q p)).
Fact div_rem_spec1 q p : q = div q p * p + rem q p.
Fact div_rem_uniq p n1 r1 n2 r2 :
p <> 0 -> n1*p + r1 = n2*p + r2 -> r1 < p -> r2 < p -> n1 = n2 /\ r1 = r2.
Fact div_prop q p n r : q = n*p+r -> r < p -> div q p = n.
Fact rem_prop q p n r : q = n*p+r -> r < p -> rem q p = r.
Fact rem_idem q p : q < p -> rem q p = q.
Fact rem_erase q n p r : q = n*p+r -> rem q p = rem r p.
Fact divides_div q p : divides p q -> q = div q p * p.
Fact divides_rem_eq q p : divides p q <-> rem q p = 0.
Fact rem_of_0 p : rem 0 p = 0.
Hint Resolve divides_0_inv.
Fact divides_dec q p : { k | q = k*p } + { ~ divides p q }.
End division.
Section rem.
Variable (p : nat) (Hp : p <> 0).
Fact rem_plus_rem a b : rem (a+rem b p) p = rem (a+b) p.
Fact rem_mult_rem a b : rem (a*rem b p) p = rem (a*b) p.
Fact rem_diag : rem p p = 0.
Fact rem_scal k a : rem (k*a) p = rem (k*rem a p) p.
Fact rem_plus_div a b : divides p b -> rem a p = rem (a+b) p.
Fact div_eq_0 n : n < p -> div n p = 0.
End rem.
Fact div_by_p_lt p n : 2 <= p -> n <> 0 -> div n p < n.
Section rem_2.
Fact rem_2_is_0_or_1 x : rem x 2 = 0 \/ rem x 2 = 1.
Fact rem_2_fix_0 : rem 0 2 = 0.
Fact rem_2_lt n : rem n 2 < 2.
Fact euclid_2 n : exists q, n = 2*q \/ n = 1+2*q.
End rem_2.
Local Hint Resolve divides_mult divides_mult_r divides_refl.

Theorem CRT u v a b : u <> 0 -> v <> 0 -> is_gcd u v 1 -> exists w, rem w u = rem a u /\ rem w v = rem b v /\ 2 < w.