End ZmoduleTheory.
Arguments addrI {V} y [x1 x2].
Arguments addIr {V} x [x1 x2].
Arguments opprK {V}.
Arguments oppr_inj {V} [x1 x2].
Module Ring.
Record mixin_of (R : zmodType) : Type := Mixin {
one : R;
mul : R -> R -> R;
_ : associative mul;
_ : left_id one mul;
_ : right_id one mul;
_ : left_distributive mul +%R;
_ : right_distributive mul +%R;
_ : one != 0
}.
Definition EtaMixin R one mul mulA mul1x mulx1 mul_addl mul_addr nz1 :=
let _ := @Mixin R one mul mulA mul1x mulx1 mul_addl mul_addr nz1 in
@Mixin (Zmodule.Pack (Zmodule.class R)) _ _
mulA mul1x mulx1 mul_addl mul_addr nz1.
Section ClassDef.
Record class_of (R : Type) : Type := Class {
base : Zmodule.class_of R;
mixin : mixin_of (Zmodule.Pack base)
}.
Local Coercion base : class_of >-> Zmodule.class_of.
Structure type := Pack {sort; _ : class_of sort}.
Local Coercion sort : type >-> Sortclass.
Variables (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 : mixin_of (@Zmodule.Pack T b0)) :=
fun bT b & phant_id (Zmodule.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.
End ClassDef.
Module Exports.
Coercion base : class_of >-> Zmodule.class_of.
Coercion mixin : class_of >-> mixin_of.
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.
Notation ringType := type.
Notation RingType T m := (@pack T _ m _ _ id _ id).
Notation RingMixin := Mixin.
Notation "[ 'ringType' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
(at level 0, format "[ 'ringType'  'of'  T  'for'  cT ]") : form_scope.
Notation "[ 'ringType' 'of' T ]" := (@clone T _ _ id)
(at level 0, format "[ 'ringType'  'of'  T ]") : form_scope.
End Exports.
End Ring.
Definition one (R : ringType) : R := Ring.one (Ring.class R).
Definition mul (R : ringType) : R -> R -> R := Ring.mul (Ring.class R).
Definition exp R x n := nosimpl iterop _ n (@mul R) x (one R).
Notation sign R b := (exp (- one R) (nat_of_bool b)) (only parsing).
Definition comm R x y := @mul R x y = mul y x.
Definition lreg R x := injective (@mul R x).
Definition rreg R x := injective ((@mul R)^~ x).
Local Notation "1" := (one _) : ring_scope.
Local Notation "- 1" := (- (1)) : ring_scope.
Local Notation "n %:R" := (1 *+ n) : ring_scope.
Local Notation "*%R" := (@mul _).
Local Notation "x * y" := (mul x y) : ring_scope.
Local Notation "x ^+ n" := (exp x n) : ring_scope.
Local Notation "\prod_ ( i <- r | P ) F" := (\big[*%R/1]_(i <- r | P) F).
Local Notation "\prod_ ( i | P ) F" := (\big[*%R/1]_(i | P) F).
Local Notation "\prod_ ( i 'in' A ) F" := (\big[*%R/1]_(i in A) F).
Local Notation "\prod_ ( m <= i < n ) F" := (\big[*%R/1%R]_(m <= i < n) F%R).
(* The ``field'' characteristic; the definition, and many of the theorems,   *)
(* has to apply to rings as well; indeed, we need the Frobenius automorphism *)
(* results for a non commutative ring in the proof of Gorenstein 2.6.3.      *)
Definition char (R : Ring.type) of phant R : nat_pred :=
[pred p | prime p & p%:R == 0 :> R].
Local Notation "[ 'char' R ]" := (char (Phant R)) : ring_scope.
(* Converse ring tag. *)
Definition converse R : Type := R.
Local Notation "R ^c" := (converse R) (at level 2, format "R ^c") : type_scope.
Section RingTheory.
Variable R : ringType.
Implicit Types x y : R.

(* Specifications: *)
Lemma mulrA : @associative R *%R. Proof. by case R => T [? []]. Qed.
Lemma mul1r : @left_id R R 1 *%R. Proof. by case R => T [? []]. Qed.
Lemma mulr1 : @right_id R R 1 *%R. Proof. by case R => T [? []]. Qed.
Lemma mulrDl : @left_distributive R R *%R +%R.
Lemma mulr0 : @right_zero R R 0 *%R.
Lemma mulrN x y : x * (- y) = - (x * y).
Lemma commrM x y z : comm x y -> comm x z -> comm x (y * z).
Lemma exprMn_comm x y n : comm x y -> (x * y) ^+ n = x ^+ n * y ^+ n.
Lemma commr_sign x n : comm x ((-1) ^+ n).
Lemma exprM x m n : x ^+ (m * n) = x ^+ m ^+ n.
Lemma exprAC x m n : (x ^+ m) ^+ n = (x ^+ n) ^+ m.
Lemma expr_dvd n x i : x ^+ n = 1 -> n %| i -> x ^+ i = 1.
Lemma natrX n k : (n ^ k)%:R = n%:R ^+ k :> R.
Lemma signr_eq0 n : ((-1) ^+ n == 0 :> R) = false.
Lemma exprNn x n : (- x) ^+ n = (-1) ^+ n * x ^+ n :> R.
Lemma lregN x : lreg x -> lreg (- x).
Lemma lreg_sign n : lreg ((-1) ^+ n : R).
Lemma prodrMn n (I : finType) (A : pred I) (F : I -> R) :
\prod_(i in A) (F i *+ n) = \prod_(i in A) F i *+ n ^ #|A|.
Lemma natr_prod I r P (F : I -> nat) :
(\prod_(i <- r | P i) F i)%:R = \prod_(i <- r | P i) (F i)%:R :> R.
Lemma exprBn_comm x y n (cxy : comm x y) :
(x - y) ^+ n =
\sum_(i < n.+1) ((-1) ^+ i * x ^+ (n - i) * y ^+ i) *+ 'C(n, i).
Lemma subrXX_comm x y n (cxy : comm x y) :
x ^+ n - y ^+ n = (x - y) * (\sum_(i < n) x ^+ (n.-1 - i) * y ^+ i).
Lemma exprD1n x n : (x + 1) ^+ n = \sum_(i < n.+1) x ^+ i *+ 'C(n, i).
Lemma subrX1 x n : x ^+ n - 1 = (x - 1) * (\sum_(i < n) x ^+ i).
Lemma sqrrD1 x : (x + 1) ^+ 2 = x ^+ 2 + x *+ 2 + 1.
Lemma sqrrB1 x : (x - 1) ^+ 2 = x ^+ 2 - x *+ 2 + 1.
Lemma charf_eq : [char R] =i (p : nat_pred).
Lemma bin_lt_charf_0 k : 0 < k < p -> 'C(p, k)%:R = 0 :> R.
Lemma Frobenius_autMn x n : (x *+ n)^f = x^f *+ n.
Lemma Frobenius_aut_nat n : (n%:R)^f = n%:R.
Lemma Frobenius_autB_comm x y : comm x y -> (x - y)^f = x^f - y^f.
End FrobeniusAutomorphism.
Lemma exprNn_char x n : [char R].-nat n -> (- x) ^+ n = - (x ^+ n).
Section Char2.