diff options
Diffstat (limited to 'src/Algebra/Ring.v')
-rw-r--r-- | src/Algebra/Ring.v | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/src/Algebra/Ring.v b/src/Algebra/Ring.v new file mode 100644 index 000000000..2d8061ddc --- /dev/null +++ b/src/Algebra/Ring.v @@ -0,0 +1,369 @@ +Require Import Coq.Classes.Morphisms. +Require Import Crypto.Util.Tactics. +Require Import Crypto.Algebra Crypto.Algebra.Group Crypto.Algebra.Monoid. +Require Coq.ZArith.ZArith Coq.PArith.PArith. + +Section Ring. + Context {T eq zero one opp add sub mul} `{@ring T eq zero one opp add sub mul}. + Local Infix "=" := eq : type_scope. Local Notation "a <> b" := (not (a = b)) : type_scope. + Local Notation "0" := zero. Local Notation "1" := one. + Local Infix "+" := add. Local Infix "-" := sub. Local Infix "*" := mul. + + Lemma mul_0_l : forall x, 0 * x = 0. + Proof. + intros. + assert (0*x = 0*x) as Hx by reflexivity. + rewrite <-(right_identity 0), right_distributive in Hx at 1. + assert (0*x + 0*x - 0*x = 0*x - 0*x) as Hxx by (rewrite Hx; reflexivity). + rewrite !ring_sub_definition, <-associative, right_inverse, right_identity in Hxx; exact Hxx. + Qed. + + Lemma mul_0_r : forall x, x * 0 = 0. + Proof. + intros. + assert (x*0 = x*0) as Hx by reflexivity. + rewrite <-(left_identity 0), left_distributive in Hx at 1. + assert (opp (x*0) + (x*0 + x*0) = opp (x*0) + x*0) as Hxx by (rewrite Hx; reflexivity). + rewrite associative, left_inverse, left_identity in Hxx; exact Hxx. + Qed. + + Lemma sub_0_l x : 0 - x = opp x. + Proof. rewrite ring_sub_definition. rewrite left_identity. reflexivity. Qed. + + Lemma mul_opp_r x y : x * opp y = opp (x * y). + Proof. + assert (Ho:x*(opp y) + x*y = 0) + by (rewrite <-left_distributive, left_inverse, mul_0_r; reflexivity). + rewrite <-(left_identity (opp (x*y))), <-Ho; clear Ho. + rewrite <-!associative, right_inverse, right_identity; reflexivity. + Qed. + + Lemma mul_opp_l x y : opp x * y = opp (x * y). + Proof. + assert (Ho:opp x*y + x*y = 0) + by (rewrite <-right_distributive, left_inverse, mul_0_l; reflexivity). + rewrite <-(left_identity (opp (x*y))), <-Ho; clear Ho. + rewrite <-!associative, right_inverse, right_identity; reflexivity. + Qed. + + Definition opp_nonzero_nonzero : forall x, x <> 0 -> opp x <> 0 := Group.inv_nonzero_nonzero. + + Global Instance is_left_distributive_sub : is_left_distributive (eq:=eq)(add:=sub)(mul:=mul). + Proof. + split; intros. rewrite !ring_sub_definition, left_distributive. + eapply Group.cancel_left, mul_opp_r. + Qed. + + Global Instance is_right_distributive_sub : is_right_distributive (eq:=eq)(add:=sub)(mul:=mul). + Proof. + split; intros. rewrite !ring_sub_definition, right_distributive. + eapply Group.cancel_left, mul_opp_l. + Qed. + + Lemma neq_sub_neq_zero x y (Hxy:x<>y) : x-y <> 0. + Proof. + intro Hsub. apply Hxy. rewrite <-(left_identity y), <-Hsub, ring_sub_definition. + rewrite <-associative, left_inverse, right_identity. reflexivity. + Qed. + + Lemma zero_product_iff_zero_factor {Hzpzf:@is_zero_product_zero_factor T eq zero mul} : + forall x y : T, eq (mul x y) zero <-> eq x zero \/ eq y zero. + Proof. + split; eauto using zero_product_zero_factor; []. + intros [Hz|Hz]; rewrite Hz; eauto using mul_0_l, mul_0_r. + Qed. + + Lemma nonzero_product_iff_nonzero_factor {Hzpzf:@is_zero_product_zero_factor T eq zero mul} : + forall x y : T, not (eq (mul x y) zero) <-> (not (eq x zero) /\ not (eq y zero)). + Proof. intros; rewrite zero_product_iff_zero_factor; tauto. Qed. + + Lemma nonzero_hypothesis_to_goal {Hzpzf:@is_zero_product_zero_factor T eq zero mul} : + forall x y : T, (not (eq x zero) -> eq y zero) <-> (eq (mul x y) zero). + Proof. intros; rewrite zero_product_iff_zero_factor; tauto. Qed. + + Global Instance Ncring_Ring_ops : @Ncring.Ring_ops T zero one add mul sub opp eq. + Global Instance Ncring_Ring : @Ncring.Ring T zero one add mul sub opp eq Ncring_Ring_ops. + Proof. + split; exact _ || cbv; intros; eauto using left_identity, right_identity, commutative, associative, right_inverse, left_distributive, right_distributive, ring_sub_definition with core typeclass_instances. + - (* TODO: why does [eauto using @left_identity with typeclass_instances] not work? *) + eapply @left_identity; eauto with typeclass_instances. + - eapply @right_identity; eauto with typeclass_instances. + - eapply associative. + - intros; eapply right_distributive. + - intros; eapply left_distributive. + Qed. +End Ring. + +Section Homomorphism. + Context {R EQ ZERO ONE OPP ADD SUB MUL} `{@ring R EQ ZERO ONE OPP ADD SUB MUL}. + Context {S eq zero one opp add sub mul} `{@ring S eq zero one opp add sub mul}. + Context {phi:R->S}. + Local Infix "=" := eq. Local Infix "=" := eq : type_scope. + + Class is_homomorphism := + { + homomorphism_is_homomorphism : Monoid.is_homomorphism (phi:=phi) (OP:=ADD) (op:=add) (EQ:=EQ) (eq:=eq); + homomorphism_mul : forall x y, phi (MUL x y) = mul (phi x) (phi y); + homomorphism_one : phi ONE = one + }. + Global Existing Instance homomorphism_is_homomorphism. + + Context `{phi_homom:is_homomorphism}. + + Lemma homomorphism_zero : phi ZERO = zero. + Proof. apply Group.homomorphism_id. Qed. + + Lemma homomorphism_add : forall x y, phi (ADD x y) = add (phi x) (phi y). + Proof. apply Monoid.homomorphism. Qed. + + Definition homomorphism_opp : forall x, phi (OPP x) = opp (phi x) := + (Group.homomorphism_inv (INV:=OPP) (inv:=opp)). + + Lemma homomorphism_sub : forall x y, phi (SUB x y) = sub (phi x) (phi y). + Proof. + intros. + rewrite !ring_sub_definition, Monoid.homomorphism, homomorphism_opp. reflexivity. + Qed. +End Homomorphism. + +Ltac push_homomorphism phi := + let H := constr:(_:is_homomorphism(phi:=phi)) in + repeat rewrite + ?(homomorphism_zero( phi_homom:=H)), + ?(homomorphism_one(is_homomorphism:=H)), + ?(homomorphism_add( phi_homom:=H)), + ?(homomorphism_opp( phi_homom:=H)), + ?(homomorphism_sub( phi_homom:=H)), + ?(homomorphism_mul(is_homomorphism:=H)). + +Lemma isomorphism_to_subring_ring + {T EQ ZERO ONE OPP ADD SUB MUL} + {Equivalence_EQ: @Equivalence T EQ} {eq_dec: forall x y, {EQ x y} + {~ EQ x y} } + {Proper_OPP:Proper(EQ==>EQ)OPP} + {Proper_ADD:Proper(EQ==>EQ==>EQ)ADD} + {Proper_SUB:Proper(EQ==>EQ==>EQ)SUB} + {Proper_MUL:Proper(EQ==>EQ==>EQ)MUL} + {R eq zero one opp add sub mul} {ringR:@ring R eq zero one opp add sub mul} + {phi} + {eq_phi_EQ: forall x y, eq (phi x) (phi y) -> EQ x y} + {phi_opp : forall a, eq (phi (OPP a)) (opp (phi a))} + {phi_add : forall a b, eq (phi (ADD a b)) (add (phi a) (phi b))} + {phi_sub : forall a b, eq (phi (SUB a b)) (sub (phi a) (phi b))} + {phi_mul : forall a b, eq (phi (MUL a b)) (mul (phi a) (phi b))} + {phi_zero : eq (phi ZERO) zero} + {phi_one : eq (phi ONE) one} + : @ring T EQ ZERO ONE OPP ADD SUB MUL. +Proof. + repeat split; eauto with core typeclass_instances; intros; + eapply eq_phi_EQ; + repeat rewrite ?phi_opp, ?phi_add, ?phi_sub, ?phi_mul, ?phi_inv, ?phi_zero, ?phi_one; + auto using (associative (op := add)), (commutative (op := add)), (left_identity (op := add)), (right_identity (op := add)), + (associative (op := mul)), (commutative (op := add)), (left_identity (op := mul)), (right_identity (op := mul)), + left_inverse, right_inverse, (left_distributive (add := add)), (right_distributive (add := add)), ring_sub_definition. +Qed. + +Section TacticSupportCommutative. + Context {T eq zero one opp add sub mul} `{@commutative_ring T eq zero one opp add sub mul}. + + Global Instance Cring_Cring_commutative_ring : + @Cring.Cring T zero one add mul sub opp eq Ncring_Ring_ops Ncring_Ring. + Proof. unfold Cring.Cring; intros; cbv. eapply commutative. Qed. + + Lemma ring_theory_for_stdlib_tactic : Ring_theory.ring_theory zero one add mul sub opp eq. + Proof. + constructor; intros. (* TODO(automation): make [auto] do this? *) + - apply left_identity. + - apply commutative. + - apply associative. + - apply left_identity. + - apply commutative. + - apply associative. + - apply right_distributive. + - apply ring_sub_definition. + - apply right_inverse. + Qed. +End TacticSupportCommutative. + +Section Z. + Import ZArith. + Global Instance ring_Z : @ring Z Logic.eq 0%Z 1%Z Z.opp Z.add Z.sub Z.mul. + Proof. repeat split; auto using Z.eq_dec with zarith typeclass_instances. Qed. + + Global Instance commutative_ring_Z : @commutative_ring Z Logic.eq 0%Z 1%Z Z.opp Z.add Z.sub Z.mul. + Proof. eauto using @commutative_ring, @is_commutative, ring_Z with zarith. Qed. + + Global Instance integral_domain_Z : @integral_domain Z Logic.eq 0%Z 1%Z Z.opp Z.add Z.sub Z.mul. + Proof. + split. + { apply commutative_ring_Z. } + { split. intros. eapply Z.eq_mul_0; assumption. } + { split. discriminate. } + Qed. +End Z. + +Section of_Z. + Import ZArith PArith. Local Open Scope Z_scope. + Context {R Req Rzero Rone Ropp Radd Rsub Rmul} + {Rring : @ring R Req Rzero Rone Ropp Radd Rsub Rmul}. + Local Infix "=" := Req. Local Infix "=" := Req : type_scope. + + Fixpoint of_nat (n:nat) : R := + match n with + | O => Rzero + | S n' => Radd (of_nat n') Rone + end. + Definition of_Z (x:Z) : R := + match x with + | Z0 => Rzero + | Zpos p => of_nat (Pos.to_nat p) + | Zneg p => Ropp (of_nat (Pos.to_nat p)) + end. + + Lemma of_Z_0 : of_Z 0 = Rzero. + Proof. reflexivity. Qed. + + Lemma of_nat_add x : + of_nat (Nat.add x 1) = Radd (of_nat x) Rone. + Proof. destruct x; rewrite ?Nat.add_1_r; reflexivity. Qed. + + Lemma of_nat_sub x (H: (0 < x)%nat): + of_nat (Nat.sub x 1) = Rsub (of_nat x) Rone. + Proof. + induction x; [omega|simpl]. + rewrite <-of_nat_add. + rewrite Nat.sub_0_r, Nat.add_1_r. + simpl of_nat. + rewrite ring_sub_definition, <-associative. + rewrite right_inverse, right_identity. + reflexivity. + Qed. + + Lemma of_Z_add_1_r : + forall x, of_Z (Z.add x 1) = Radd (of_Z x) Rone. + Proof. + destruct x; [reflexivity| | ]; simpl of_Z. + { rewrite Pos2Nat.inj_add, of_nat_add. + reflexivity. } + { rewrite Z.pos_sub_spec; break_match; + match goal with + | H : _ |- _ => rewrite Pos.compare_eq_iff in H + | H : _ |- _ => rewrite Pos.compare_lt_iff in H + | H : _ |- _ => rewrite Pos.compare_gt_iff in H; + apply Pos.nlt_1_r in H; tauto + end; + subst; simpl of_Z; simpl of_nat. + { rewrite left_identity, left_inverse; reflexivity. } + { rewrite Pos2Nat.inj_sub by assumption. + rewrite of_nat_sub by apply Pos2Nat.is_pos. + rewrite ring_sub_definition, Group.inv_op, Group.inv_inv. + rewrite commutative; reflexivity. } } + Qed. + + Lemma of_Z_sub_1_r : + forall x, of_Z (Z.sub x 1) = Rsub (of_Z x) Rone. + Proof. + induction x. + { simpl; rewrite ring_sub_definition, !left_identity; + reflexivity. } + { case_eq (1 ?= p)%positive; intros; + match goal with + | H : _ |- _ => rewrite Pos.compare_eq_iff in H + | H : _ |- _ => rewrite Pos.compare_lt_iff in H + | H : _ |- _ => rewrite Pos.compare_gt_iff in H; + apply Pos.nlt_1_r in H; tauto + end. + { subst. simpl; rewrite ring_sub_definition, !left_identity, + right_inverse; reflexivity. } + { rewrite <-Pos2Z.inj_sub by assumption; simpl of_Z. + rewrite Pos2Nat.inj_sub by assumption. + rewrite of_nat_sub by apply Pos2Nat.is_pos. + reflexivity. } } + { simpl. rewrite Pos2Nat.inj_add, of_nat_add. + rewrite ring_sub_definition, Group.inv_op, commutative. + reflexivity. } + Qed. + + Lemma of_Z_opp : forall a, + of_Z (Z.opp a) = Ropp (of_Z a). + Proof. + destruct a; simpl; rewrite ?Group.inv_id, ?Group.inv_inv; + reflexivity. + Qed. + + Lemma of_Z_add : forall a b, + of_Z (Z.add a b) = Radd (of_Z a) (of_Z b). + Proof. + intros. + let x := match goal with |- ?x => x end in + let f := match (eval pattern b in x) with ?f _ => f end in + apply (Z.peano_ind f); intros. + { rewrite !right_identity. reflexivity. } + { replace (a + Z.succ x) with ((a + x) + 1) by ring. + replace (Z.succ x) with (x+1) by ring. + rewrite !of_Z_add_1_r, H. + rewrite associative; reflexivity. } + { replace (a + Z.pred x) with ((a+x)-1) + by (rewrite <-Z.sub_1_r; ring). + replace (Z.pred x) with (x-1) by apply Z.sub_1_r. + rewrite !of_Z_sub_1_r, H. + rewrite !ring_sub_definition. + rewrite associative; reflexivity. } + Qed. + + Lemma of_Z_mul : forall a b, + of_Z (Z.mul a b) = Rmul (of_Z a) (of_Z b). + Proof. + intros. + let x := match goal with |- ?x => x end in + let f := match (eval pattern b in x) with ?f _ => f end in + apply (Z.peano_ind f); intros until 0; try intro IHb. + { rewrite !mul_0_r; reflexivity. } + { rewrite Z.mul_succ_r, <-Z.add_1_r. + rewrite of_Z_add, of_Z_add_1_r. + rewrite IHb. + rewrite left_distributive, right_identity. + reflexivity. } + { rewrite Z.mul_pred_r, <-Z.sub_1_r. + rewrite of_Z_sub_1_r. + rewrite <-Z.add_opp_r. + rewrite of_Z_add, of_Z_opp. + rewrite IHb. + rewrite ring_sub_definition, left_distributive. + rewrite mul_opp_r,right_identity. + reflexivity. } + Qed. + + + Global Instance homomorphism_of_Z : + @is_homomorphism + Z Logic.eq Z.one Z.add Z.mul + R Req Rone Radd Rmul + of_Z. + Proof. + repeat constructor; intros. + { apply of_Z_add. } + { repeat intro; subst; reflexivity. } + { apply of_Z_mul. } + { simpl. rewrite left_identity; reflexivity. } + Qed. +End of_Z. + +Definition char_gt + {R eq zero one opp add} {sub:R->R->R} {mul:R->R->R} + C := + @Algebra.char_gt R eq zero (fun n => (@of_Z R zero one opp add) (BinInt.Z.of_N n)) C. +Existing Class char_gt. + +(*** Tactics for ring equations *) +Require Export Coq.setoid_ring.Ring_tac. +Ltac ring_simplify_subterms := tac_on_subterms ltac:(fun t => ring_simplify t). + +Ltac ring_simplify_subterms_in_all := + reverse_nondep; ring_simplify_subterms; intros. + +Create HintDb ring_simplify discriminated. +Create HintDb ring_simplify_subterms discriminated. +Create HintDb ring_simplify_subterms_in_all discriminated. +Hint Extern 1 => progress ring_simplify : ring_simplify. +Hint Extern 1 => progress ring_simplify_subterms : ring_simplify_subterms. +Hint Extern 1 => progress ring_simplify_subterms_in_all : ring_simplify_subterms_in_all.
\ No newline at end of file |