(* $Id: CRings.v,v 1.101 2000/11/10 11:27:30 freek Exp $ *)

Require Export CSums.
Require Export Even.
Require Export Div2.

Transparent sym_eq.
Transparent f_equal.

(* Begin_SpecReals *)

(* Constructive RINGS *)

(* Tex_Prose
\section{Rings}
We actually define commutative rings with 1.
*)

(* Tex_Prose
\subsection{Definition of the notion of Ring}
*)
(* Begin_Tex_Verb *)
Definition distributive :=
  [S:CSetoid; mult,plus:(CSetoid_bin_op S)]
  (x,y,z:S) (mult x (plus y z)) [=] (plus (mult x y) (mult x z)).
(* End_Tex_Verb *)
Syntactic Definition Distributive := (distributive ?).

(* Begin_Tex_Verb *)
Record is_CRing [G : CGroup; one : G; mult : (CSetoid_bin_op G)] : Prop :=
  { ax_mult_assoc : (Associative mult);
    ax_mult_mon : (is_CMonoid (Build_CSemi_grp G one mult ax_mult_assoc));
    ax_dist : (Distributive mult (csg_op G));
    ax_non_triv : (one [#] Zero)
  }.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Record CRing : Type :=
  { cr_crr   :> CGroup;
    cr_one   :  cr_crr;
    cr_mult  :  (CSetoid_bin_op cr_crr);
    cr_proof :  (is_CRing cr_crr cr_one cr_mult)
  }.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Definition cr_plus  :=  csg_op.
Definition cr_inv   :=  cg_inv.
Definition cr_minus :=  cg_minus.
(* End_Tex_Verb *)

Syntactic Definition Cr_mult := (cr_mult ?).

(* Tex_Prose
\begin{notation}
The term \verb!cr_one! with its first argument left implicit is denoted by
\verb!One!.
\end{notation}
*)
Syntactic Definition One    := (cr_one ?).
Syntax constr level 1:
  cr_one_constant [<<(cr_one $e0)>>] -> ["One"].

(* End_SpecReals *)



(* Begin_SpecReals *)

(* Tex_Prose
\begin{notation}
The multiplication \verb!cr_mult x y! is denoted by \verb!x [*] y!.
\end{notation}

\begin{nameconvention}
In the {\em names} of lemmas, we will denote \verb!One! with \verb!one!,
and \verb![*]! with \verb!mult!.
\end{nameconvention}
*)
Infix 6 "[*]" Cr_mult.
Syntax constr level 6:
  cr_mult_infix [<<(csbf_fun $_ $_ $_ (cr_mult $_) $e1 $e2)>>] ->
    [[<hov 1> $e1:E [0 1] "[*]" $e2:L]].

Section CRing_axioms.
(* Tex_Prose
\subsection{Ring axioms}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Variable R : CRing.

(* Begin_Tex_Verb *)
Lemma CRing_is_CRing : (is_CRing R One Cr_mult).
(* End_Tex_Verb *)
Elim R; Intros.
Exact cr_proof0.
Qed.

(* Begin_Tex_Verb *)
Lemma mult_assoc : (Associative (cr_mult R)).
(* End_Tex_Verb *)
Elim CRing_is_CRing; Intros.
Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma mult_mon : (is_CMonoid (Build_CSemi_grp R One Cr_mult mult_assoc)).
(* End_Tex_Verb *)
Elim (cr_proof R).
Intros.
Apply is_CMonoid_proof_irr with ax_mult_assoc0.
Assumption.
Qed.

(* End_SpecReals *)

(* Begin_Tex_Verb *)
Lemma dist : (Distributive Cr_mult (cr_plus R)).
(* End_Tex_Verb *)
Elim (cr_proof R).
Intros.
Exact ax_dist0.
Qed.

(* Begin_Tex_Verb *)
Lemma ring_non_triv : (One::R [#] Zero).
(* End_Tex_Verb *)
Elim (cr_proof R).
Intros.
Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma mult_wd : (x1,x2,y1,y2:R)(x1[=]x2)-> (y1[=]y2)-> (x1[*]y1) [=] (x2[*]y2).
(* End_Tex_Verb *)
Intros.
Apply bin_op_wd_unfolded; Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma mult_wd_lft : (x1,x2,y:R)(x1[=]x2)-> (x1[*]y) [=] (x2[*]y).
(* End_Tex_Verb *)
Intros.
Apply mult_wd.
Assumption.
Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma mult_wd_rht : (x,y1,y2:R)(y1[=]y2)-> (x[*]y1) [=] (x[*]y2).
(* End_Tex_Verb *)
Intros.
Apply mult_wd.
Algebra.
Assumption.
Qed.

(* Begin_SpecReals *)

End CRing_axioms.

Section Ring_constructions.
(* Tex_Prose
\subsection{Ring constructions}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Variable R : CRing.

(* Tex_Prose
The multiplicative monoid of a ring is defined as follows.
*)
(* Begin_Tex_Verb *)
Definition Build_multCMonoid : CMonoid := (Build_CMonoid ? (mult_mon R)).
(* End_Tex_Verb *)

(* Tex_Prose
The csetoid of non-zeros of a ring is defined as follows.
*)
(* Begin_Tex_Verb *)
Definition NonZeros : CSetoid := (Build_SubCSetoid R NonZeroP).
Definition nzinj : NonZeros -> R := (scs_elem R NonZeroP).
(* End_Tex_Verb *)

(* End_SpecReals *)

(* Begin_Tex_Verb *)
Definition nzpro : (x:R)(x [#] Zero)->NonZeros :=
                             (Build_subcsetoid_crr R NonZeroP).
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma inj_pro: (x:R; nz:(x[#]Zero)) (nzinj (nzpro x nz)) [=] x.
(* End_Tex_Verb *)
Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma pro_inj: (x:NonZeros) (nzpro (nzinj x) (scs_prf ?? x)) [=] x.
(* End_Tex_Verb *)
Destruct x. Simpl. Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma nonz_eq:(x,y:NonZeros)(((nzinj x)[=](nzinj y))-> (x[=]y)).
(* End_Tex_Verb *)
Destruct x.
Destruct y.
Unfold nzinj.
Intros.
Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma nzinj_strong_ext : (x,y:NonZeros)((nzinj x) [#] (nzinj y)) -> (x[#]y).
(* End_Tex_Verb *)
Intros x y.
Unfold 1 cs_ap.
Unfold NonZeros.
Simpl.
Unfold subcsetoid_ap.
Unfold restrict_relation.
Elim x.
Intro. Intro.
Elim y.
Intro. Intro.
Simpl.
Intro.
Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma nzinj_wd : (x,y:NonZeros)(x[=]y) -> (nzinj x) [=] (nzinj y).
(* End_Tex_Verb *)
Intros x y.
Unfold 1 cs_eq.
Unfold NonZeros.
Simpl.
Unfold subcsetoid_eq.
Unfold restrict_relation.
Elim x.
Intro. Intro.
Elim y.
Intro. Intro.
Simpl.
Intro.
Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma nzpro_strong_ext : (x,y:R)(Hx:x[#]Zero)(Hy:y[#]Zero)
                         (((nzpro x Hx) [#] (nzpro y Hy)) -> (x[#]y)).
(* End_Tex_Verb *)
Simpl.
Intros.
Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma nzpro_wd : (x,y:R)(Hx:x[#]Zero)(Hy:y[#]Zero) (x [=] y) ->
                  (nzpro x Hx) [=] (nzpro y Hy).
(* End_Tex_Verb *)
Intros.
Simpl.
Assumption.
Qed.

(* Begin_SpecReals *)

End Ring_constructions.

(* End_SpecReals *)

Hints Resolve inj_pro pro_inj : algebra.

(* Begin_SpecReals *)

Syntactic Definition NZinj := (nzinj ?).

(* End_SpecReals *)

(* Tex_Prose
\begin{numnotation}\label{notation:nzpro}
We will write \verb!nzpro ? x p! as \verb!x [//] p!.
\end{numnotation}
*)
Syntactic Definition NZpro := (nzpro ??).
Syntactic Definition NZpro1 := (nzpro ?).
Infix 5 "[//]" NZpro1.
Syntax constr level 5:
  nzpro_infix [<<(nzpro $_ $e1 $e2)>>] ->
    [[<hov 1> $e1:E [0 1] "[//]" $e2:L]].


Section Ring_unfolded.
(* Tex_Prose
\subsection{Ring unfolded}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Variable R : CRing.
Local mmR := (Build_multCMonoid R).

(* Begin_Tex_Verb *)
Lemma mult_assoc_unfolded : (x,y,z:R)
                            (x [*] (y [*] z)) [=] ((x [*] y) [*] z).
(* End_Tex_Verb *)
Exact (mult_assoc R).
Qed.

(* Begin_Tex_Verb *)
Lemma mult_commutes: (x,y:R) (x[*]y) [=] (y[*]x).
(* End_Tex_Verb *)
Proof (cm_commutes mmR).
Hints Resolve mult_commutes : algebra.

(* Begin_Tex_Verb *)
Lemma mult_one: (x:R)(x [*] One) [=] x.
(* End_Tex_Verb *)
Proof (cm_rht_unit mmR).

(* Begin_Tex_Verb *)
Lemma one_mult: (x:R)(One [*] x) [=] x.
(* End_Tex_Verb *)
Proof (cm_lft_unit mmR).

(* Begin_Tex_Verb *)
Lemma ring_dist_unfolded:
  (x,y,z:R) x [*] (y [+] z) [=] (x [*] y) [+] (x [*] z).
(* End_Tex_Verb *)
Proof (dist R).
Hints Resolve ring_dist_unfolded : algebra.

(* Begin_Tex_Verb *)
Lemma ring_distl_unfolded:
  (x,y,z:R) (y [+] z) [*] x [=] (y [*] x) [+] (z [*] x).
(* End_Tex_Verb *)
Intros.
Step x [*] (y [+] z).
Step (x [*] y) [+] (x [*] z).
Step (y [*] x) [+] (x [*] z).
Step_final (y [*] x) [+] (z [*] x).
Qed.

End Ring_unfolded.
Hints Resolve mult_assoc_unfolded : algebra.
Hints Resolve ring_non_triv mult_one one_mult mult_commutes : algebra.
Hints Resolve ring_dist_unfolded ring_distl_unfolded : algebra.


Section Ring_basics.
(* Tex_Prose
\subsection{Ring basics}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Variable R : CRing.

(* Begin_Tex_Verb *)
Lemma one_ap_zero : (One::R [#] Zero).
(* End_Tex_Verb *)
Proof (ring_non_triv R).

(* Tex_Prose
NonZeroP is well-defined and strongly-extensional, but we don't use this.
*)
Remark NonZeroP_well_def: (pred_well_def R NonZeroP).
Red. Unfold NonZeroP. Intros. Apply (ap_well_def_lft ???? H H0).
Qed.

Remark NonZeroP_strong_ext: (pred_strong_ext R NonZeroP).
Red. Unfold nonZeroP.
Intros. Case (ap_strong_ext R ? y ? y H).
Intros yapy. Elim (ap_irreflexive R ? yapy).
Intro h. Case h. Auto.
Intro. Constructor 1. Apply (ap_symmetric R). Assumption.
Qed.

Reset NonZeroP_well_def.


(* Begin_Tex_Verb *)
Definition is_zero_rht [S:CSetoid; op:(CSetoid_bin_op S); zero:S]: Prop :=
    (x:S)((op x zero) [=] zero).
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Definition is_zero_lft [S:CSetoid; op:(CSetoid_bin_op S); zero:S]: Prop :=
    (x:S)((op zero x) [=] zero).
(* End_Tex_Verb *)
Syntactic Definition Is_zero_rht := (is_zero_rht ?).
Syntactic Definition Is_zero_lft := (is_zero_lft ?).

(* Begin_Tex_Verb *)
Lemma cring_mult_zero: (x:R) (x [*] Zero) [=] Zero.
(* End_Tex_Verb *)
Intros.
Apply cg_cancel_lft with (x [*] Zero).
Stepr x[*]Zero.
Step_final x[*](Zero[+]Zero).
Qed.
Hints Resolve cring_mult_zero : algebra.

(* Begin_Tex_Verb *)
Lemma cring_mult_zero_op: (x:R) Zero[*]x [=] Zero.
(* End_Tex_Verb *)
Intros. Step_final x[*]Zero.
Qed.
Hints Resolve cring_mult_zero_op : algebra.

(* Begin_Tex_Verb *)
Lemma cring_minus_mult_lft: (x,y:R) x [*] ([--]y) [=] [--](x [*] y).
(* End_Tex_Verb *)
Intros.
Apply cg_inv_unique.
Step x[*](y[+]([--]y)).
Step_final x[*]Zero.
Qed.
Hints Resolve cring_minus_mult_lft : algebra.

(* Begin_Tex_Verb *)
Lemma cring_minus_mult_rht: (x,y:R) ([--]x) [*] y [=] [--](x [*] y).
(* End_Tex_Verb *)
Intros.
Step y[*]([--]x).
Step_final [--](y[*]x).
Qed.
Hints Resolve cring_minus_mult_rht : algebra.

(* Begin_Tex_Verb *)
Lemma cring_mult_ap_zero: (x,y:R)((x [*] y) [#] Zero) -> (x [#] Zero).
(* End_Tex_Verb *)
Intros.
Elim (bin_op_strext ? Cr_mult x Zero y y).
Auto.
Intro contra; Elim (ap_irreflexive ?? contra).
Step_ap_rht (Zero::R).
Qed.

(* Begin_Tex_Verb *)
Lemma cring_mult_ap_zero_op: (x,y:R)((x [*] y) [#] Zero) -> (y [#] Zero).
(* End_Tex_Verb *)
Intros.
Apply cring_mult_ap_zero with x.
Step_ap_lft x[*]y.
Qed.

(* Begin_Tex_Verb *)
Lemma inv_mult_invol: (x,y:R)([--]x[*][--]y [=] x[*]y).
(* End_Tex_Verb *)
Intros.
Step [--](x[*][--]y).
Step_final [--][--](x[*]y).
Qed.

(* Begin_Tex_Verb *)
Lemma ring_dist_minus :
  (x,y,z:R) x [*] (y [-] z) [=] (x [*] y) [-] (x [*] z).
(* End_Tex_Verb *)
Intros.
Unfold cg_minus.
Step_lft x[*]y [+] x[*][--]z.
Algebra.
Qed.

Hints Resolve ring_dist_minus : algebra.

(* Begin_Tex_Verb *)
Lemma ring_distl_minus:
  (x,y,z:R) (y [-] z) [*] x [=] (y [*] x) [-] (z [*] x).
(* End_Tex_Verb *)
Intros.
Unfold cg_minus.
Step_lft y[*]x [+] [--]z[*]x.
Algebra.
Qed.

Hints Resolve ring_distl_minus : algebra.

End Ring_basics.
Hints Resolve cring_mult_zero cring_mult_zero_op : algebra.
Hints Resolve inv_mult_invol : algebra.
Hints Resolve cring_minus_mult_lft cring_minus_mult_rht : algebra.
Hints Resolve ring_dist_minus : algebra.
Hints Resolve ring_distl_minus : algebra.


(* Begin_SpecReals *)

(* Tex_Prose
\subsection{Ring Auxiliary}
Some auxiliary functions and operations over a ring;
especially geared towards CReals.
*)

Section exponentiation.
(* Tex_Prose
\subsubsection{Exponentiation}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Variable R: CRing.

(* End_SpecReals *)

(* Begin_Tex_Verb *)
Fixpoint nexp [x:R;m:nat]: R :=
  Cases m of O => One | (S n) => ((nexp x n) [*] x)
  end.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma nexp_well_def: (n:nat)(Fun_well_def [x:R](nexp x n)).
(* End_Tex_Verb *)
Induction n; Unfold fun_well_def; Intros; Simpl.
Algebra.
Apply (csbf_wd ??? (cr_mult R)). Apply H; Assumption. Assumption.
Qed.

(* Begin_Tex_Verb *)
Lemma nexp_strong_ext: (n:nat)(Fun_strong_ext [x:R](nexp x n)).
(* End_Tex_Verb *)
Unfold fun_strong_ext; Induction n; Simpl; Intros.
Elim (ap_irreflexive ?? H).
Elim (bin_op_strext ? (cr_mult R) ???? H0); Intros.
  Apply H; Assumption.
  Assumption.
Qed.

(* Begin_Tex_Verb *)
Definition nexp_op :=
  [n:nat](Build_CSetoid_un_op R [x:R](nexp x n)
    (nexp_well_def n) (nexp_strong_ext n)).
(* End_Tex_Verb *)

(* Begin_SpecReals *)

End exponentiation.

(* End_SpecReals *)

(* Tex_Prose
\begin{notation}
\verb!a [^] b! stands for \verb!nexp_op ? a b!.
\end{notation}
*)
Syntactic Definition Nexp := (nexp_op ?).
Grammar command command2 :=
  Nexp_nifix [ command2($c2) "[^]" command1($c1) ] ->
    [<<((Nexp $c1) $c2)>>].
Syntax constr level 2:
  nexp_op_nifix [<<(csf_fun $_ $_ (nexp_op $_ $e1) $e2)>>] ->
    [[<hov 1> $e2:E [0 1] "[^]" $e1:L]].


(* Begin_SpecReals *)

Section nat_injection.
(* Tex_Prose
\subsubsection{The injection of natural numbers into a ring}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Variable R: CRing.

(* Tex_Prose
The injection of Coq natural numbers into a ring is called \verb!nring!.
*)
(* Begin_Tex_Verb *)
Fixpoint nring [m:nat]: R :=
  Cases m of O => Zero | (S n) => ((nring n) [+] One)
  end.
(* End_Tex_Verb *)

(* End_SpecReals *)

(* Begin_Tex_Verb *)
Lemma nring_comm_plus:
  (n,m:nat)(nring (plus n m)) [=] ((nring n) [+] (nring m)).
(* End_Tex_Verb *)
Induction n; Simpl; Intros.
Algebra.
Stepr (nring n0)[+](One[+](nring m)).
Stepr (nring n0)[+]((nring m)[+]One).
Stepr ((nring n0)[+](nring m))[+]One.
Apply (bin_op_wd ? (csg_op R));[Apply (H m)|Apply eq_reflexive_unfolded].
Qed.

(* Begin_Tex_Verb *)
Lemma nring_comm_mult :
  (n,m:nat)(nring (mult n m)) [=] ((nring n) [*] (nring m)).
(* End_Tex_Verb *)
Induction n; Simpl; Intros.
Algebra.
Step (nring m)[+](nring (mult n0 m)). Apply (nring_comm_plus m (mult n0 m)).
Stepr ((nring n0)[*](nring m)) [+] (One[*](nring m)).
Stepr ((nring n0)[*](nring m)) [+] (nring m).
Stepr (nring m) [+] ((nring n0)[*](nring m)).
Apply (bin_op_wd ? (csg_op R));[Algebra|Apply (H m)].
Qed.

(* Begin_SpecReals *)

End nat_injection.

(* End_SpecReals *)

Hints Resolve nring_comm_plus nring_comm_mult : algebra.

(* Tex_Prose
\begin{notation}
\verb!Two! denotes \verb!Nring (S (S O))!,
\verb!Three! denotes \verb!Nring (S (S (S O)))! and
\verb!Four! denotes \verb!Nring (S (S (S (S O))))!.
\end{notation}
*)
(* Begin_SpecReals *)

Syntactic Definition Nring := (nring ?).

(* End_SpecReals *)

Syntactic Definition Two    := (Nring (S (S O))).
Syntax constr level 1:
  cr_two_constant [<<(nring $_ (S (S O)))>>] -> ["Two"].


Syntactic Definition Three    := (Nring (S (S (S O)))).
Syntax constr level 1:
  cr_three_constant [<<(nring $_ (S (S (S O))))>>] -> ["Three"].

Syntactic Definition Four    := (Nring (S (S (S (S O))))).
Syntax constr level 1:
  cr_four_constant [<<(nring $_ (S (S (S (S O)))))>>] -> ["Four"].

(* Begin_Tex_Verb *)
Lemma one_plus_one : (R:CRing)((One::R) [+] One) [=] Two.
(* End_Tex_Verb *)
Intro.
Simpl.
Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma x_plus_x : (R:CRing)(x:R)(x[+]x) [=] Two[*]x.
(* End_Tex_Verb *)
Intros.
Step (One[*]x)[+](One[*]x).
Step (One[+]One)[*]x.
Apply mult_wd_lft.
Apply one_plus_one.
Qed.

Hints Resolve x_plus_x : algebra.



Section int_injection.

(* Tex_Prose
\subsubsection{The injection of integers into a ring}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)

Variable R: CRing.

(* Tex_Prose
The injection of Coq integers into a ring is called \verb!zring!.
*)
(* Begin_Tex_Verb *)
Definition zring [k:Z] : R := (caseZ_diff k [m,n:nat](Nring m) [-] (Nring n)).
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma zring_zero : (zring `0`) [=] Zero.
(* End_Tex_Verb *)
Simpl.
Algebra.
Qed.
Hints Resolve zring_zero : algebra.

(* Begin_Tex_Verb *)
Lemma zring_diff : (m,n:nat)(zring `m-n`) [=] (Nring m) [-] (Nring n).
(* End_Tex_Verb *)
Unfold zring.
Intros.
(* Rewrite with [=] *)
Apply proper_caseZ_diff_CS with f:=[m0,n0:nat](nring R m0)[-](nring R n0).
Intros.
Apply cg_cancel_lft with (Nring n0)::R.
Unfold cg_minus.
Step_lft (nring R n0)[+]([--](nring R n0)[+](nring R m0)).
Step_lft ((nring R n0)[+][--](nring R n0))[+](nring R m0).
Step_lft Zero[+](nring R m0).
Step_lft (nring R m0).
Apply cg_cancel_rht with (Nring q)::R.
Step_rht (nring R n0)[+](((nring R p)[+][--](nring R q))[+](nring R q)).
Step_rht (nring R n0)[+]((nring R p)[+]([--](nring R q)[+](nring R q))).
Step_rht (nring R n0)[+]((nring R p)[+](Zero)).
Step_rht (nring R n0)[+](nring R p).
Step_rht (nring R (plus n0 p)).
Step_lft (nring R (plus m0 q)).
Rewrite H.
Algebra.
Qed.

Hints Resolve zring_diff.

(* Begin_Tex_Verb *)
Lemma zring_plus_nat : (n:nat)(zring `n`) [=] (Nring n).
(* End_Tex_Verb *)
Intros.
Replace `n`::Z with `n-O`.
Step_lft (nring R n) [-] (nring R O).
Simpl.
Algebra.
Simpl.
Omega.
Qed.

Hints Resolve zring_plus_nat : algebra.

(* Begin_Tex_Verb *)
Lemma zring_min_nat : (n:nat)(zring `-n`) [=] [--](Nring n).
(* End_Tex_Verb *)
Intros.
Replace `-n` with `O-n`.
Step_lft (nring R O) [-] (nring R n).
Simpl.
Algebra.
Simpl.
Omega.
Qed.

Hints Resolve zring_min_nat : algebra.

(* Begin_Tex_Verb *)
Lemma zring_plus : (i,j:Z)(zring `i+j`) [=] (zring i)[+](zring j).
(* End_Tex_Verb *)
Intros.
Pattern i.
Apply diff_Z_ind.
Intros.
Pattern j.
Apply diff_Z_ind.
Intros.
Hints Resolve zring_diff : algebra.
Replace `(m-n)+(m0-n0)` with `(plus m m0)-(plus n n0)`.
(* Rewrite using [=] would be great. *)
Step_lft (Nring (plus m m0)) [-] (Nring (plus n n0)) ::R.
Step_lft ((Nring m) [+] (Nring m0)) [-] ((Nring n) [+] (Nring n0)) :: R.
Step_rht ((Nring m) [-] (Nring n)) [+] ((Nring m0) [-] (Nring n0)) :: R.
Unfold cg_minus.
Step_lft (Nring m) [+] ((Nring m0) [+][--] ((Nring n) [+] (Nring n0))) :: R.
Step_rht (Nring m) [+] ([--](Nring n) [+] ((Nring m0) [+][--] (Nring n0))) ::R.
Apply bin_op_wd_unfolded.
Algebra.
Step_lft (Nring m0) [+]([--] (Nring n) [+][--] (Nring n0)) :: R.
Step_lft ((Nring m0) [+] [--] (Nring n)) [+][--] (Nring n0) :: R.
Step_rht ([--](Nring n) [+] (Nring m0)) [+] [--](Nring n0) ::R.
Apply bin_op_wd_unfolded.
Algebra.
Algebra.
Repeat Rewrite inj_plus.
Omega.
Qed.

Hints Resolve zring_plus : algebra.

(* Begin_Tex_Verb *)
Lemma zring_min : (i:Z)(zring `-i`) [=] [--](zring i).
(* End_Tex_Verb *)
Intro.
Pattern i.
Apply diff_Z_ind.
Intros.
Replace `-(m-n)` with `n-m`.
Step_lft (nring R n) [-] (nring R m).
Step_rht [--]((nring R m) [-] (nring R n)).
Unfold cg_minus.
Step_rht [--](nring R m)[+][--][--](nring R n).
Step_rht [--](nring R m)[+](nring R n).
Algebra.
Omega.
Qed.

Hints Resolve zring_min : algebra.

(* Begin_Tex_Verb *)
Lemma zring_minus : (i,j:Z)(zring `i-j`) [=] (zring i)[-](zring j).
(* End_Tex_Verb *)
Intros.
Unfold cg_minus.
Replace `i-j` with `i+(-j)`.
Step_lft (zring `i`) [+] (zring `-j`).
Algebra.
Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma zring_mult : (i,j:Z)(zring `i*j`) [=] (zring i)[*](zring j).
(* End_Tex_Verb *)
Intros.
Pattern i.
Apply diff_Z_ind.
Intros.
Pattern j.
Apply diff_Z_ind.
Intros.
Step_rht ((nring R m) [-] (Nring n))[*]((Nring m0) [-] (Nring n0)).
Replace `(m-n)*(m0-n0)` with
        `(plus (mult m m0) (mult n n0)) - (plus (mult n m0) (mult m n0))`.
2: Repeat Rewrite inj_plus.
2: Repeat Rewrite inj_mult.
2: Repeat Rewrite Zmult_minus_distr.
2: Repeat Rewrite Zmult_minus_distr_r.
2: Omega.
Step_lft (nring R (plus (mult m m0) (mult n n0))) [-]
         (nring R (plus (mult n m0) (mult m n0))).
Step_lft ((nring R (mult m m0)) [+] (nring R (mult n n0))) [-]
         ((nring R (mult n m0)) [+] (nring R (mult m n0))).
Step_lft ((nring R m) [*] (nring R m0) [+] (nring R n) [*] (nring R n0)) [-]
         ((nring R n) [*] (nring R m0) [+] (nring R m) [*] (nring R n0)).
Step_rht (nring R m) [*] ((nring R m0)[-](nring R n0)) [-]
         (nring R n) [*] ((nring R m0)[-](nring R n0)).
Step_rht ((nring R m) [*] (nring R m0) [-] (nring R m) [*] (nring R n0)) [-]
         ((nring R n) [*] (nring R m0) [-] (nring R n) [*] (nring R n0)).
Unfold cg_minus.
Step_rht (nring R m)[*](nring R m0)[+](([--]((nring R m)[*](nring R n0)))
            [+][--]((nring R n)[*](nring R m0)
                      [+][--]((nring R n)[*](nring R n0)))).
Step_lft
 (nring R m)[*](nring R m0)[+](((nring R n)[*](nring R n0))
     [+][--]((nring R n)[*](nring R m0)[+](nring R m)[*](nring R n0))).
Apply bin_op_wd_unfolded.
Algebra.
Step_lft
 ((nring R n)[*](nring R n0))
   [+]([--]((nring R n)[*](nring R m0))[+]([--]((nring R m)[*](nring R n0)))).
Step_rht ([--]((nring R m)[*](nring R n0)))
            [+]([--]((nring R n)[*](nring R m0))
                      [+][--][--]((nring R n)[*](nring R n0))).
Step_rht ([--]((nring R m)[*](nring R n0)))
            [+]([--]((nring R n)[*](nring R m0))
                      [+]((nring R n)[*](nring R n0))).
Step_rht ([--]((nring R m)[*](nring R n0)))
            [+](   ((nring R n)[*](nring R n0))
                [+]  [--]((nring R n)[*](nring R m0))   ).
Step_rht ([--]((nring R m)[*](nring R n0)))
            [+]   ((nring R n)[*](nring R n0))
                [+]  [--]((nring R n)[*](nring R m0))   .
Step_rht  ((nring R n)[*](nring R n0))
            [+]   ([--]((nring R m)[*](nring R n0)))
                [+]  [--]((nring R n)[*](nring R m0))   .
Step_rht  ((nring R n)[*](nring R n0))
            [+] (  ([--]((nring R m)[*](nring R n0)))
                [+]  [--]((nring R n)[*](nring R m0))   ).
Apply bin_op_wd_unfolded.
Algebra.
Algebra.
Qed.

Hints Resolve zring_mult : algebra.

(* Begin_Tex_Verb *)
Lemma zring_one : (zring `1`) [=] One.
(* End_Tex_Verb *)
Simpl.
Step_lft One[-]Zero::R.
Algebra.
Qed.

Hints Resolve zring_one : algebra.

(* Begin_Tex_Verb *)
Lemma zring_inv : (x:R)((zring `-1`)[*]x [=] [--]x).
(* End_Tex_Verb *)
Intro.
Simpl.
Step_lft [--](Zero[+]One)[*]x.
Step ([--]One)[*]x.
Step [--](One[*]x).
Algebra.
Qed.

End int_injection.

Syntactic Definition Zring := (zring ?).

Hints Resolve zring_zero zring_diff zring_plus_nat zring_min_nat
              zring_plus zring_min zring_minus zring_mult
              zring_one zring_inv : algebra.


Section Ring_sums.

(* Tex_Prose
\subsection{Ring sums}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Variable R : CRing.

(* Tex_Prose
\subsubsection{Infinite Ring sums}
*)
Section infinite_ring_sums.

(* Begin_Tex_Verb *)
Fixpoint Sum_upto [r:nat->R; n:nat] : R :=
  Cases n of O     => Zero
	   | (S x) => (r x) [+] (Sum_upto r x)
  end.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma sum_upto_O : (r:nat->R)(Sum_upto r O) [=] Zero.
(* End_Tex_Verb *)
Intro.
Simpl.
Apply (eq_reflexive R).
Qed.

(* Begin_Tex_Verb *)
Definition Sum_from_upto [r:nat->R; p,n:nat] : R :=
  (Sum_upto r n) [-] (Sum_upto r p).
(* End_Tex_Verb *)

(* Tex_Prose
Here's an alternative def of \verb!Sum_from_upto!, with lemma that
it's equivalent to the original.
*)
(* Begin_Tex_Verb *)
Definition seq_from [r:nat->R; p:nat] : nat->R := [i:nat](r (plus p i)).
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Definition Sum_from_upto_alt [r:nat->R; p,n:nat] : R :=
  (Sum_upto (seq_from r p) (minus n p)).
(* End_Tex_Verb *)

(*
(* Begin_Tex_Verb *)
Ax_iom sum_from_upto_eq:
  (r:nat->R)(n,p:nat)(le p n) ->
    (Sum_from_upto_alt r p n) [=] (Sum_from_upto r p n).
(* End_Tex_Verb *)
*)

End infinite_ring_sums.

Section ring_sums_over_lists.
(* Tex_Prose
\subsection{Ring Sums over Lists}
*)

(* Begin_Tex_Verb *)
Fixpoint RList_Mem [l:(list R); n:nat] : R :=
  Cases l n of nil _       => Zero
             | (cons a _) O => a
             | (cons _ k) (S y) => (RList_Mem k y)
  end.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Fixpoint List_Sum_upto [l:(list R); n:nat] : R :=
  Cases n of O     => Zero
	   | (S x) => (RList_Mem l x) [+] (List_Sum_upto l x)
  end.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma list_sum_upto_O : (l:(list R))(List_Sum_upto l O) [=] Zero.
(* End_Tex_Verb *)
Simpl.
Intro _.
Apply (eq_reflexive R).
Qed.

(* Begin_Tex_Verb *)
Definition List_Sum_from_upto [l:(list R); p,n:nat] : R :=
   (List_Sum_upto l n) [-] (List_Sum_upto l p).
(* End_Tex_Verb *)

(* Tex_Prose
Here's an alternative def of \verb!List_Sum_from_upto!, with lemma
 that it's equivalent to the original.
*)
(* Begin_Tex_Verb *)
Fixpoint List_End [l:(list R); p:nat] : (list R) :=
   Cases p of O     => l
            | (S x) => (List_End (tail l) x)
   end.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Definition List_Sum_from_upto_alt [l:(list R); p,n:nat] : R :=
   (List_Sum_upto (List_End l p) (minus n p)).
(* End_Tex_Verb *)

(*
(* Begin_Tex_Verb *)
Ax_iom list_sum_from_upto_eq :
  (l:(list R))(n,p:nat)(le p n) ->
      (List_Sum_from_upto_alt l p n) [=] (List_Sum_from_upto l p n).
(* End_Tex_Verb *)
*)

End ring_sums_over_lists.
End Ring_sums.

(* Tex_Prose
\subsection{Distribution properties}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Section Dist_properties.
Variable R : CRing.

(* Begin_Tex_Verb *)
Lemma dist_1b : (x,y,z:R)((x[+]y)[*]z [=] x[*]z[+]y[*]z).
(* End_Tex_Verb *)
Intros.
Step z[*](x[+]y).
Step_final z[*]x[+]z[*]y.
Qed.
Hints Resolve dist_1b : algebra.

(* Begin_Tex_Verb *)
Lemma dist_2a : (x,y,z:R)(z[*](x[-]y) [=] z[*]x[-]z[*]y).
(* End_Tex_Verb *)
Intros.
Step z[*](x[+][--]y).
Step z[*]x[+]z[*][--]y.
Step_final z[*]x[+][--](z[*]y).
Qed.
Hints Resolve dist_2a : algebra.

(* Begin_Tex_Verb *)
Lemma dist_2b : (x,y,z:R)((x[-]y)[*]z [=] x[*]z[-]y[*]z).
(* End_Tex_Verb *)
Intros.
Step z[*](x[-]y).
Step_final z[*]x[-]z[*]y.
Qed.
Hints Resolve dist_2b : algebra.

(* Begin_Tex_Verb *)
Lemma mult_distr_sum0_lft : (f:nat->R)(x:R)(a:nat)
                            (Sum0 a [i:nat](x [*] (f i))) [=]
                            (x [*] (Sum0 a f)).
(* End_Tex_Verb *)
Intros.
Elim a.
Simpl.
Algebra.
Intros.
Simpl.
Step_lft x[*](sum0 (R) n f) [+] x[*](f n).
Algebra.
Qed.
Hints Resolve mult_distr_sum0_lft.

(* Begin_Tex_Verb *)
Lemma mult_distr_sum_lft : (f:nat->R)(x:R)(a,b:nat)
                           (Sum a b [i:nat](x [*] (f i))) [=]
                           (x [*] (Sum a b f)).
(* End_Tex_Verb *)
Intros.
Unfold sum.
Unfold sum1.
Step_lft  x[*](sum0 (R) (S b) f) [-] x[*] (sum0 (R) a f).
Algebra.
Qed.
Hints Resolve mult_distr_sum_lft : algebra.

(* Begin_Tex_Verb *)
Lemma mult_distr_sum_rht : (f:nat->R)(x:R)(a,b:nat)
                           (Sum a b [i:nat]((f i) [*] x)) [=]
                           ((Sum a b f) [*] x).
(* End_Tex_Verb *)
Intros.
Step_lft (sum (R) a b [i:nat]x[*](f i)).
Step_rht x[*] (sum (R) a b f).
Algebra.
Qed.

End Dist_properties.

Hints Resolve dist_1b dist_2a dist_2b mult_distr_sum_lft mult_distr_sum_rht
              : algebra.


(* Tex_Prose
\subsection{Properties of exponenation over N}
\begin{convention}
Let \verb!R! be a ring.
\end{convention}
*)
Section NExp_properties.
Variable R : CRing.

(* Begin_Tex_Verb *)
Lemma nexp_wd :(x,y:R)(n:nat)(x[=]y)->(x[^]n [=] y[^]n).
(* End_Tex_Verb *)
Intros.
Apply un_op_wd_unfolded; Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma nexp_Sn : (x:R)(n:nat)(x[*]x[^]n [=] x[^](S n)).
(* End_Tex_Verb *)
Intros.
Step_final x[^]n[*]x.
Qed.
Hints Resolve nexp_Sn : algebra.

(* Begin_Tex_Verb *)
Lemma nexp_plus : (x:R)(m,n:nat)(x[^]m[*]x[^]n [=] x[^](plus m n)).
(* End_Tex_Verb *)
Intros.
Elim m.

Step One[*]x[^]n.
Step x[^]n.
Replace (plus O n) with n; Auto with arith; Algebra.

Intros.
Step (x[^]n0[*]x)[*]x[^]n.
Step (x[*]x[^]n0)[*]x[^]n.
Step x[*](x[^]n0[*]x[^]n).
Step x[*]x[^](plus n0 n).
Step x[^](S (plus n0 n)).
Replace (S (plus n0 n)) with (plus (S n0) n); Auto with arith; Algebra.

Qed.
Hints Resolve nexp_plus : algebra.

(* Begin_Tex_Verb *)
Lemma one_nexp : (n:nat)((One::R)[^]n [=] One).
(* End_Tex_Verb *)
Intros.
Elim n.
Algebra.

Intros.
Step (One::R)[*]One[^]n0.
Step_final (One::R)[*]One.

Qed.
Hints Resolve one_nexp : algebra.

(* Begin_Tex_Verb *)
Lemma mult_nexp : (x,y:R)(n:nat)((x[*]y)[^]n [=] x[^]n[*]y[^]n).
(* End_Tex_Verb *)
Intros.
Elim n.

Step One::R.
Step_final (One::R)[*]One.

Intros.
Step (x[*]y)[*](x[*]y)[^]n0.
Step (x[*]y)[*](x[^]n0[*]y[^]n0).
Step x[*](y[*](x[^]n0[*]y[^]n0)).
Step x[*]((y[*]x[^]n0)[*]y[^]n0).
Step x[*]((x[^]n0[*]y)[*]y[^]n0).
Step x[*](x[^]n0[*](y[*]y[^]n0)).
Step_final (x[*]x[^]n0)[*](y[*]y[^]n0).

Qed.
Hints Resolve mult_nexp : algebra.

(* Begin_Tex_Verb *)
Lemma nexp_mult : (x:R)(m,n:nat)((x[^]m)[^]n [=] x[^](mult m n)).
(* End_Tex_Verb *)
Intros.
Elim m.

Step (One::R)[^]n.
Step One::R.
Replace (mult O n) with O; Auto with arith; Algebra.

Intros.
Step (x[*]x[^]n0)[^]n.
Step x[^]n[*](x[^]n0)[^]n.
Step x[^]n[*]x[^](mult n0 n).
Step x[^](plus n (mult n0 n)).
Replace (plus n (mult n0 n)) with (mult (S n0) n); Auto with arith; Algebra.

Qed.
Hints Resolve nexp_mult : algebra.

(* Begin_Tex_Verb *)
Lemma zero_nexp : (x:R)(n:nat)(lt O n)->((Zero::R)[^]n [=] Zero).
(* End_Tex_Verb *)
Intro. Intro.
Elim n.
Intros. Absurd (lt O O); Auto with arith.
Intros. Step_final Zero::R[*]Zero[^]n0.
Qed.
Hints Resolve zero_nexp : algebra.

(* Begin_Tex_Verb *)
Lemma min_nexp_even : (x:R)(n:nat)(even n)->(([--]x)[^]n [=] x[^]n).
(* End_Tex_Verb *)
Intros.
Elim (even_2n n); Try Assumption.
Intro n0. Intro.
Rewrite y. Unfold double.
Step [--]x[^]n0[*][--]x[^]n0.
Step ([--]x[*][--]x)[^]n0.
Step (x[*]x)[^]n0.
Step_final x[^]n0[*]x[^]n0.
Qed.
Hints Resolve min_nexp_even : algebra.

(* Begin_Tex_Verb *)
Lemma min_nexp_two : (x:R)(([--]x)[^](2) [=] x[^](2)).
(* End_Tex_Verb *)
Intros.
Apply min_nexp_even.
Auto with arith.
Qed.
Hints Resolve min_nexp_two : algebra.

(* Begin_Tex_Verb *)
Lemma min_nexp_odd : (x:R)(n:nat)(odd n)->(([--]x)[^]n [=] [--](x[^]n)).
(* End_Tex_Verb *)
Intros.
Elim H.
Intros.
Step [--]x[*][--]x[^]n0.
Step [--]x[*]x[^]n0.
Step_final [--](x[*]x[^]n0).
Qed.
Hints Resolve min_nexp_odd : algebra.

(* Begin_Tex_Verb *)
Lemma nexp_one : (x:R)(x[^](1) [=] x).
(* End_Tex_Verb *)
Intros.
Step_final One[*]x.
Qed.
Hints Resolve nexp_one : algebra.

(* Begin_Tex_Verb *)
Lemma nexp_two : (x:R)(x[^](2) [=] x[*]x).
(* End_Tex_Verb *)
Intros.
Replace (2) with (plus (1) (1)).
Step_final x[^](1)[*]x[^](1).
Auto with arith.
Qed.
Hints Resolve nexp_two : algebra.

(* Begin_Tex_Verb *)
Lemma nexp_funny : (x,y:R)((x[+]y)[*](x[-]y) [=] x[^](2)[-]y[^](2)).
(* End_Tex_Verb *)
Intros.
Step x[*](x[-]y)[+]y[*](x[-]y).
Step (x[*]x[-]x[*]y)[+](y[*]x[-]y[*]y).
Step (x[*]x[+][--](x[*]y))[+](y[*]x[+][--](y[*]y)).
Step ((x[*]x[+][--](x[*]y))[+]y[*]x)[+][--](y[*]y).
Step (x[*]x[+]([--](x[*]y)[+]y[*]x))[+][--](y[*]y).
Step (x[*]x[+]([--](x[*]y)[+]x[*]y))[+][--](y[*]y).
Step (x[*]x[+]Zero)[+][--](y[*]y).
Step x[*]x[+][--](y[*]y).
Step_final x[*]x[-]y[*]y.
Qed.
Hints Resolve nexp_funny : algebra.

(* Begin_Tex_Verb *)
Lemma nexp_funny' : (x,y:R)((x[-]y)[*](x[+]y) [=] x[^](2)[-]y[^](2)).
(* End_Tex_Verb *)
Intros.
Step_final (x[+]y)[*](x[-]y).
Qed.
Hints Resolve nexp_funny' : algebra.

End NExp_properties.
Hints Resolve nexp_Sn nexp_plus one_nexp mult_nexp nexp_mult zero_nexp
  min_nexp_even min_nexp_two min_nexp_odd nexp_one nexp_two nexp_funny
  nexp_funny' one_nexp : algebra.


