End MultiQuant.
End EvalTerm.
Prenex Implicits dnf_rterm.
Module IntegralDomain.
Definition axiom (R : ringType) :=
forall x y : R, x * y = 0 -> (x == 0) || (y == 0).
Section ClassDef.
Record class_of (R : Type) : Type :=
Class {base : ComUnitRing.class_of R; mixin : axiom (Ring.Pack base)}.
Local Coercion base : class_of >-> ComUnitRing.class_of.
Structure type := Pack {sort; _ : class_of sort}.
Local Coercion sort : type >-> Sortclass.
Variable (T : Type) (cT : type).
Definition class := let: Pack _ c as cT' := cT return class_of cT' in c.
Definition clone c of phant_id class c := @Pack T c.
Let xT := let: Pack T _ := cT in T.
Notation xclass := (class : class_of xT).
Definition pack b0 (m0 : axiom (@Ring.Pack T b0)) :=
fun bT b & phant_id (ComUnitRing.class bT) b =>
fun    m & phant_id m0 m => Pack (@Class T b m).
Definition eqType := @Equality.Pack cT xclass.
Definition choiceType := @Choice.Pack cT xclass.
Definition zmodType := @Zmodule.Pack cT xclass.
Definition ringType := @Ring.Pack cT xclass.
Definition comRingType := @ComRing.Pack cT xclass.
Definition unitRingType := @UnitRing.Pack cT xclass.
Definition comUnitRingType := @ComUnitRing.Pack cT xclass.
End ClassDef.
Module Exports.
Coercion base : class_of >-> ComUnitRing.class_of.
Arguments mixin [R] c [x y].
Coercion mixin : class_of >-> axiom.
Coercion sort : type >-> Sortclass.
Bind Scope ring_scope with sort.
Coercion eqType : type >-> Equality.type.
Canonical eqType.
Coercion choiceType : type >-> Choice.type.
Canonical choiceType.
Coercion zmodType : type >-> Zmodule.type.
Canonical zmodType.
Coercion ringType : type >-> Ring.type.
Canonical ringType.
Coercion comRingType : type >-> ComRing.type.
Canonical comRingType.
Coercion unitRingType : type >-> UnitRing.type.
Canonical unitRingType.
Coercion comUnitRingType : type >-> ComUnitRing.type.
Canonical comUnitRingType.
Notation idomainType := type.
Notation IdomainType T m := (@pack T _ m _ _ id _ id).
Notation "[ 'idomainType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
(at level 0, format "[ 'idomainType'  'of'  T  'for'  cT ]") : form_scope.
Notation "[ 'idomainType' 'of' T ]" := (@clone T _ _ id)
(at level 0, format "[ 'idomainType'  'of'  T ]") : form_scope.
End Exports.
End IntegralDomain.
Section IntegralDomainTheory.
Variable R : idomainType.
Implicit Types x y : R.

(* Specifications: *)
Lemma mulf_eq0 x y : (x * y == 0) = (x == 0) || (y == 0).
Lemma prodf_eq0 (I : finType) (P : pred I) (F : I -> R) :
reflect (exists2 i, P i & (F i == 0)) (\prod_(i | P i) F i == 0).
Lemma prodf_seq_eq0 I r (P : pred I) (F : I -> R) :
(\prod_(i <- r | P i) F i == 0) = has (fun i => P i && (F i == 0)) r.
Lemma prodf_seq_neq0 I r (P : pred I) (F : I -> R) :
(\prod_(i <- r | P i) F i != 0) = all (fun i => P i ==> (F i != 0)) r.
Lemma expf_eq0 x n : (x ^+ n == 0) = (n > 0) && (x == 0).
Lemma sqrf_eq0 x : (x ^+ 2 == 0) = (x == 0). Proof. exact: expf_eq0. Qed.
Lemma expf_neq0 x m : x != 0 -> x ^+ m != 0.
Lemma natf0_char n : n > 0 -> n%:R == 0 :> R -> exists p, p \in [char R].
Lemma charf'_nat n : [char R]^'.-nat n = (n%:R != 0 :> R).
Lemma charf0P : [char R] =i pred0 <-> (forall n, (n%:R == 0 :> R) = (n == 0)%N).
Lemma eqf_sqr x y : (x ^+ 2 == y ^+ 2) = (x == y) || (x == - y).
Lemma mulIf x : x != 0 -> injective ( *%R^~ x).
Section Mixins.