End IdomainUnit.
Module Field.
Include IdomainDefs.
Export IdomainDefs.
Include CommonIdomain.
Section FieldDivision.
Variable F : fieldType.
Implicit Type p q r d : {poly F}.

(* Specifications: *)
Lemma divp_eq p q : p = (p %/ q) * q + (p %% q).
Lemma divp_modpP p q d r : p = q * d + r -> size r < size d ->
q = (p %/ d) /\ r = p %% d.
Lemma divpP p q d r : p = q * d + r -> size r < size d ->
q = (p %/ d).
Lemma dvdp_eq q p : (q %| p) = (p == p %/ q * q).
Lemma eqpf_eq p q : reflect (exists2 c, c != 0 & p = c *: q) (p %= q).
Lemma modp_scalel c p q : (c *: p) %% q = c *: (p %% q).
Lemma mulpK p q : q != 0 -> p * q %/ q = p.
Lemma modp_scaler c p d : c != 0 -> p %% (c *: d) = (p %% d).
Lemma divp_scaler c p d : c != 0 -> p %/ (c *: d) = c^-1 *: (p %/ d).
Lemma eqp_modpl d p q : p %= q -> (p %% d) %= (q %% d).
Lemma eqp_divl d p q : p %= q -> (p %/ d) %= (q %/ d).
Lemma eqp_modpr d p q : p %= q -> (d %% p) %= (d %% q).
Lemma eqp_mod p1 p2 q1 q2 : p1 %= p2 -> q1 %= q2 -> p1 %% q1 %= p2 %% q2.
Lemma eqp_divr (d m n : {poly F}) : m %= n -> (d %/ m) %= (d %/ n).
Lemma eqp_div p1 p2 q1 q2 : p1 %= p2 -> q1 %= q2 -> p1 %/ q1 %= p2 %/ q2.
Lemma eqp_gdcor p q r : q %= r -> gdcop p q %= gdcop p r.
Lemma eqp_gdcol p q r : q %= r -> gdcop q p %= gdcop r p.
Lemma eqp_rgdco_gdco q p : rgdcop q p %= gdcop q p.
Lemma modp_opp p q : (- p) %% q = - (p %% q).
Lemma divp_opp p q : (- p) %/ q = - (p %/ q).
Lemma modp_add d p q : (p + q) %% d = p %% d + q %% d.
Lemma modNp p q : (- p) %% q = - (p %% q).
Lemma divp_addl_mul_small d q r :
size r < size d -> (q * d + r) %/ d = q.
Lemma modp_addl_mul_small d q r :
size r < size d -> (q * d + r) %% d = r.
Lemma leq_trunc_divp d m : size (m %/ d * d) <= size m.
Lemma divpK d p : d %| p -> p %/ d * d = p.
Lemma divpKC d p : d %| p -> d * (p %/ d) = p.
Lemma dvdp_eq_mul d p q : d != 0 -> d %| p -> (p == q * d) = (p %/ d == q).
Lemma divp_mulAC d m n : d %| m -> m %/ d * n = m * n %/ d.
Lemma divp_pmul2r d p q : d != 0 -> p != 0 ->  q * d %/ (p * d) = q %/ p.
Lemma divpAC d p q : q %/ d %/ p =  q %/ p %/ d.
Lemma divpE p q : p %/ q = (lead_coef q)^-(rscalp p q) *: (rdivp p q).
Lemma modpE p q : p %% q = (lead_coef q)^-(rscalp p q) *: (rmodp p q).
Lemma scalpE p q : scalp p q = 0%N.
(* Just to have it without importing the weak theory *)
Lemma dvdpE p q : p %| q = rdvdp p q. Proof. exact: Idomain.dvdpE. Qed.
Variant edivp_spec m d : nat * {poly F} * {poly F} -> Type :=
EdivpSpec n q r of
m = q * d + r & (d != 0) ==> (size r < size d) : edivp_spec m d (n, q, r).
Lemma edivpP m d : edivp_spec m d (edivp m d).
Lemma edivp_eq d q r : size r < size d -> edivp (q * d + r) d = (0%N, q, r).
Lemma modp_mul p q m : (p * (q %% m)) %% m = (p * q) %% m.
Lemma dvdpP p q : reflect (exists qq, p = qq * q) (q %| p).
Lemma Bezout_eq1_coprimepP : forall p q,
reflect (exists u, u.1 * p + u.2 * q = 1) (coprimep p q).
Lemma dvdp_gdcor p q : q != 0 -> p %| (gdcop q p) * (q ^+ size p).
Lemma reducible_cubic_root p q :
size p <= 4 -> 1 < size q < size p -> q %| p -> {r | root p r}.
Lemma cubic_irreducible p :
1 < size p <= 4 -> (forall x, ~~ root p x) -> irreducible_poly p.