From 208a0f7bfa5249f9795e6e225f309cbe715c0fad Mon Sep 17 00:00:00 2001 From: Samuel Mimram Date: Tue, 21 Nov 2006 21:38:49 +0000 Subject: Imported Upstream version 8.1~gamma --- theories/ZArith/BinInt.v | 977 ++++++++++++++++++------------------ theories/ZArith/Int.v | 673 ++++++++++++------------- theories/ZArith/Wf_Z.v | 355 ++++++------- theories/ZArith/ZArith.v | 4 +- theories/ZArith/ZArith_dec.v | 326 ++++++------ theories/ZArith/Zabs.v | 114 ++--- theories/ZArith/Zbinary.v | 676 ++++++++++++------------- theories/ZArith/Zbool.v | 125 ++--- theories/ZArith/Zcompare.v | 713 ++++++++++++++------------- theories/ZArith/Zcomplements.v | 258 +++++----- theories/ZArith/Zdiv.v | 476 +++++++++--------- theories/ZArith/Zeven.v | 212 ++++---- theories/ZArith/Zhints.v | 347 +++++++++---- theories/ZArith/Zlogarithm.v | 434 ++++++++-------- theories/ZArith/Zmax.v | 62 +-- theories/ZArith/Zmin.v | 80 +-- theories/ZArith/Zminmax.v | 50 +- theories/ZArith/Zmisc.v | 88 ++-- theories/ZArith/Znat.v | 126 ++--- theories/ZArith/Znumtheory.v | 1066 ++++++++++++++++++++-------------------- theories/ZArith/Zorder.v | 862 ++++++++++++++++---------------- theories/ZArith/Zpower.v | 671 ++++++++++++------------- theories/ZArith/Zsqrt.v | 185 +++---- theories/ZArith/Zwf.v | 92 ++-- theories/ZArith/auxiliary.v | 118 ++--- 25 files changed, 4609 insertions(+), 4481 deletions(-) (limited to 'theories/ZArith') diff --git a/theories/ZArith/BinInt.v b/theories/ZArith/BinInt.v index fda521de..71e48360 100644 --- a/theories/ZArith/BinInt.v +++ b/theories/ZArith/BinInt.v @@ -6,10 +6,10 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: BinInt.v 8883 2006-05-31 21:56:37Z letouzey $ i*) +(*i $Id: BinInt.v 9245 2006-10-17 12:53:34Z notin $ i*) (***********************************************************) -(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) +(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) (***********************************************************) Require Export BinPos. @@ -19,190 +19,190 @@ Require Import Plus. Require Import Mult. Unset Boxed Definitions. -(**********************************************************************) -(** Binary integer numbers *) + +(*****************************) +(** * Binary integer numbers *) Inductive Z : Set := | Z0 : Z | Zpos : positive -> Z | Zneg : positive -> Z. -(** Declare Scope Z_scope with Key Z *) -Delimit Scope Z_scope with Z. (** Automatically open scope positive_scope for the constructors of Z *) +Delimit Scope Z_scope with Z. Bind Scope Z_scope with Z. Arguments Scope Zpos [positive_scope]. Arguments Scope Zneg [positive_scope]. -(** Subtraction of positive into Z *) +(** ** Subtraction of positive into Z *) Definition Zdouble_plus_one (x:Z) := match x with - | Z0 => Zpos 1 - | Zpos p => Zpos (xI p) - | Zneg p => Zneg (Pdouble_minus_one p) + | Z0 => Zpos 1 + | Zpos p => Zpos (xI p) + | Zneg p => Zneg (Pdouble_minus_one p) end. Definition Zdouble_minus_one (x:Z) := match x with - | Z0 => Zneg 1 - | Zneg p => Zneg (xI p) - | Zpos p => Zpos (Pdouble_minus_one p) + | Z0 => Zneg 1 + | Zneg p => Zneg (xI p) + | Zpos p => Zpos (Pdouble_minus_one p) end. Definition Zdouble (x:Z) := match x with - | Z0 => Z0 - | Zpos p => Zpos (xO p) - | Zneg p => Zneg (xO p) + | Z0 => Z0 + | Zpos p => Zpos (xO p) + | Zneg p => Zneg (xO p) end. Fixpoint ZPminus (x y:positive) {struct y} : Z := match x, y with - | xI x', xI y' => Zdouble (ZPminus x' y') - | xI x', xO y' => Zdouble_plus_one (ZPminus x' y') - | xI x', xH => Zpos (xO x') - | xO x', xI y' => Zdouble_minus_one (ZPminus x' y') - | xO x', xO y' => Zdouble (ZPminus x' y') - | xO x', xH => Zpos (Pdouble_minus_one x') - | xH, xI y' => Zneg (xO y') - | xH, xO y' => Zneg (Pdouble_minus_one y') - | xH, xH => Z0 + | xI x', xI y' => Zdouble (ZPminus x' y') + | xI x', xO y' => Zdouble_plus_one (ZPminus x' y') + | xI x', xH => Zpos (xO x') + | xO x', xI y' => Zdouble_minus_one (ZPminus x' y') + | xO x', xO y' => Zdouble (ZPminus x' y') + | xO x', xH => Zpos (Pdouble_minus_one x') + | xH, xI y' => Zneg (xO y') + | xH, xO y' => Zneg (Pdouble_minus_one y') + | xH, xH => Z0 end. -(** Addition on integers *) +(** ** Addition on integers *) Definition Zplus (x y:Z) := match x, y with - | Z0, y => y - | x, Z0 => x - | Zpos x', Zpos y' => Zpos (x' + y') - | Zpos x', Zneg y' => + | Z0, y => y + | x, Z0 => x + | Zpos x', Zpos y' => Zpos (x' + y') + | Zpos x', Zneg y' => match (x' ?= y')%positive Eq with - | Eq => Z0 - | Lt => Zneg (y' - x') - | Gt => Zpos (x' - y') + | Eq => Z0 + | Lt => Zneg (y' - x') + | Gt => Zpos (x' - y') end - | Zneg x', Zpos y' => + | Zneg x', Zpos y' => match (x' ?= y')%positive Eq with - | Eq => Z0 - | Lt => Zpos (y' - x') - | Gt => Zneg (x' - y') + | Eq => Z0 + | Lt => Zpos (y' - x') + | Gt => Zneg (x' - y') end - | Zneg x', Zneg y' => Zneg (x' + y') + | Zneg x', Zneg y' => Zneg (x' + y') end. Infix "+" := Zplus : Z_scope. -(** Opposite *) +(** ** Opposite *) Definition Zopp (x:Z) := match x with - | Z0 => Z0 - | Zpos x => Zneg x - | Zneg x => Zpos x + | Z0 => Z0 + | Zpos x => Zneg x + | Zneg x => Zpos x end. Notation "- x" := (Zopp x) : Z_scope. -(** Successor on integers *) +(** ** Successor on integers *) Definition Zsucc (x:Z) := (x + Zpos 1)%Z. -(** Predecessor on integers *) +(** ** Predecessor on integers *) Definition Zpred (x:Z) := (x + Zneg 1)%Z. -(** Subtraction on integers *) +(** ** Subtraction on integers *) Definition Zminus (m n:Z) := (m + - n)%Z. Infix "-" := Zminus : Z_scope. -(** Multiplication on integers *) +(** ** Multiplication on integers *) Definition Zmult (x y:Z) := match x, y with - | Z0, _ => Z0 - | _, Z0 => Z0 - | Zpos x', Zpos y' => Zpos (x' * y') - | Zpos x', Zneg y' => Zneg (x' * y') - | Zneg x', Zpos y' => Zneg (x' * y') - | Zneg x', Zneg y' => Zpos (x' * y') + | Z0, _ => Z0 + | _, Z0 => Z0 + | Zpos x', Zpos y' => Zpos (x' * y') + | Zpos x', Zneg y' => Zneg (x' * y') + | Zneg x', Zpos y' => Zneg (x' * y') + | Zneg x', Zneg y' => Zpos (x' * y') end. Infix "*" := Zmult : Z_scope. -(** Comparison of integers *) +(** ** Comparison of integers *) Definition Zcompare (x y:Z) := match x, y with - | Z0, Z0 => Eq - | Z0, Zpos y' => Lt - | Z0, Zneg y' => Gt - | Zpos x', Z0 => Gt - | Zpos x', Zpos y' => (x' ?= y')%positive Eq - | Zpos x', Zneg y' => Gt - | Zneg x', Z0 => Lt - | Zneg x', Zpos y' => Lt - | Zneg x', Zneg y' => CompOpp ((x' ?= y')%positive Eq) + | Z0, Z0 => Eq + | Z0, Zpos y' => Lt + | Z0, Zneg y' => Gt + | Zpos x', Z0 => Gt + | Zpos x', Zpos y' => (x' ?= y')%positive Eq + | Zpos x', Zneg y' => Gt + | Zneg x', Z0 => Lt + | Zneg x', Zpos y' => Lt + | Zneg x', Zneg y' => CompOpp ((x' ?= y')%positive Eq) end. Infix "?=" := Zcompare (at level 70, no associativity) : Z_scope. Ltac elim_compare com1 com2 := case (Dcompare (com1 ?= com2)%Z); - [ idtac | let x := fresh "H" in - (intro x; case x; clear x) ]. + [ idtac | let x := fresh "H" in + (intro x; case x; clear x) ]. -(** Sign function *) +(** ** Sign function *) Definition Zsgn (z:Z) : Z := match z with - | Z0 => Z0 - | Zpos p => Zpos 1 - | Zneg p => Zneg 1 + | Z0 => Z0 + | Zpos p => Zpos 1 + | Zneg p => Zneg 1 end. -(** Direct, easier to handle variants of successor and addition *) +(** ** Direct, easier to handle variants of successor and addition *) Definition Zsucc' (x:Z) := match x with - | Z0 => Zpos 1 - | Zpos x' => Zpos (Psucc x') - | Zneg x' => ZPminus 1 x' + | Z0 => Zpos 1 + | Zpos x' => Zpos (Psucc x') + | Zneg x' => ZPminus 1 x' end. Definition Zpred' (x:Z) := match x with - | Z0 => Zneg 1 - | Zpos x' => ZPminus x' 1 - | Zneg x' => Zneg (Psucc x') + | Z0 => Zneg 1 + | Zpos x' => ZPminus x' 1 + | Zneg x' => Zneg (Psucc x') end. Definition Zplus' (x y:Z) := match x, y with - | Z0, y => y - | x, Z0 => x - | Zpos x', Zpos y' => Zpos (x' + y') - | Zpos x', Zneg y' => ZPminus x' y' - | Zneg x', Zpos y' => ZPminus y' x' - | Zneg x', Zneg y' => Zneg (x' + y') + | Z0, y => y + | x, Z0 => x + | Zpos x', Zpos y' => Zpos (x' + y') + | Zpos x', Zneg y' => ZPminus x' y' + | Zneg x', Zpos y' => ZPminus y' x' + | Zneg x', Zneg y' => Zneg (x' + y') end. Open Local Scope Z_scope. (**********************************************************************) -(** Inductive specification of Z *) +(** ** Inductive specification of Z *) Theorem Zind : - forall P:Z -> Prop, - P Z0 -> - (forall x:Z, P x -> P (Zsucc' x)) -> - (forall x:Z, P x -> P (Zpred' x)) -> forall n:Z, P n. + forall P:Z -> Prop, + P Z0 -> + (forall x:Z, P x -> P (Zsucc' x)) -> + (forall x:Z, P x -> P (Zpred' x)) -> forall n:Z, P n. Proof. -intros P H0 Hs Hp z; destruct z. + intros P H0 Hs Hp z; destruct z. assumption. apply Pind with (P := fun p => P (Zpos p)). change (P (Zsucc' Z0)) in |- *; apply Hs; apply H0. @@ -213,52 +213,56 @@ intros P H0 Hs Hp z; destruct z. Qed. (**********************************************************************) -(** Properties of opposite on binary integer numbers *) +(** * Misc properties about binary integer operations *) + + +(**********************************************************************) +(** ** Properties of opposite on binary integer numbers *) Theorem Zopp_neg : forall p:positive, - Zneg p = Zpos p. Proof. -reflexivity. + reflexivity. Qed. (** [opp] is involutive *) Theorem Zopp_involutive : forall n:Z, - - n = n. Proof. -intro x; destruct x; reflexivity. + intro x; destruct x; reflexivity. Qed. (** Injectivity of the opposite *) Theorem Zopp_inj : forall n m:Z, - n = - m -> n = m. Proof. -intros x y; case x; case y; simpl in |- *; intros; - [ trivial - | discriminate H - | discriminate H - | discriminate H - | simplify_eq H; intro E; rewrite E; trivial - | discriminate H - | discriminate H - | discriminate H - | simplify_eq H; intro E; rewrite E; trivial ]. + intros x y; case x; case y; simpl in |- *; intros; + [ trivial + | discriminate H + | discriminate H + | discriminate H + | simplify_eq H; intro E; rewrite E; trivial + | discriminate H + | discriminate H + | discriminate H + | simplify_eq H; intro E; rewrite E; trivial ]. Qed. -(**********************************************************************) -(* Properties of the direct definition of successor and predecessor *) +(*************************************************************************) +(** ** Properties of the direct definition of successor and predecessor *) Lemma Zpred'_succ' : forall n:Z, Zpred' (Zsucc' n) = n. Proof. -intro x; destruct x; simpl in |- *. - reflexivity. -destruct p; simpl in |- *; try rewrite Pdouble_minus_one_o_succ_eq_xI; - reflexivity. -destruct p; simpl in |- *; try rewrite Psucc_o_double_minus_one_eq_xO; - reflexivity. + intro x; destruct x; simpl in |- *. + reflexivity. + destruct p; simpl in |- *; try rewrite Pdouble_minus_one_o_succ_eq_xI; + reflexivity. + destruct p; simpl in |- *; try rewrite Psucc_o_double_minus_one_eq_xO; + reflexivity. Qed. Lemma Zsucc'_discr : forall n:Z, n <> Zsucc' n. Proof. -intro x; destruct x; simpl in |- *. + intro x; destruct x; simpl in |- *. discriminate. injection; apply Psucc_discr. destruct p; simpl in |- *. @@ -268,512 +272,517 @@ intro x; destruct x; simpl in |- *. Qed. (**********************************************************************) -(** Other properties of binary integer numbers *) +(** ** Other properties of binary integer numbers *) Lemma ZL0 : 2%nat = (1 + 1)%nat. Proof. -reflexivity. + reflexivity. Qed. (**********************************************************************) -(** Properties of the addition on integers *) +(** * Properties of the addition on integers *) -(** zero is left neutral for addition *) +(** ** zero is left neutral for addition *) Theorem Zplus_0_l : forall n:Z, Z0 + n = n. Proof. -intro x; destruct x; reflexivity. + intro x; destruct x; reflexivity. Qed. -(** zero is right neutral for addition *) +(** *** zero is right neutral for addition *) Theorem Zplus_0_r : forall n:Z, n + Z0 = n. Proof. -intro x; destruct x; reflexivity. + intro x; destruct x; reflexivity. Qed. -(** addition is commutative *) +(** ** addition is commutative *) Theorem Zplus_comm : forall n m:Z, n + m = m + n. Proof. -intro x; induction x as [| p| p]; intro y; destruct y as [| q| q]; - simpl in |- *; try reflexivity. + intro x; induction x as [| p| p]; intro y; destruct y as [| q| q]; + simpl in |- *; try reflexivity. rewrite Pplus_comm; reflexivity. rewrite ZC4; destruct ((q ?= p)%positive Eq); reflexivity. rewrite ZC4; destruct ((q ?= p)%positive Eq); reflexivity. rewrite Pplus_comm; reflexivity. Qed. -(** opposite distributes over addition *) +(** ** opposite distributes over addition *) Theorem Zopp_plus_distr : forall n m:Z, - (n + m) = - n + - m. Proof. -intro x; destruct x as [| p| p]; intro y; destruct y as [| q| q]; - simpl in |- *; reflexivity || destruct ((p ?= q)%positive Eq); - reflexivity. + intro x; destruct x as [| p| p]; intro y; destruct y as [| q| q]; + simpl in |- *; reflexivity || destruct ((p ?= q)%positive Eq); + reflexivity. Qed. -(** opposite is inverse for addition *) +(** ** opposite is inverse for addition *) Theorem Zplus_opp_r : forall n:Z, n + - n = Z0. Proof. -intro x; destruct x as [| p| p]; simpl in |- *; - [ reflexivity - | rewrite (Pcompare_refl p); reflexivity - | rewrite (Pcompare_refl p); reflexivity ]. + intro x; destruct x as [| p| p]; simpl in |- *; + [ reflexivity + | rewrite (Pcompare_refl p); reflexivity + | rewrite (Pcompare_refl p); reflexivity ]. Qed. Theorem Zplus_opp_l : forall n:Z, - n + n = Z0. Proof. -intro; rewrite Zplus_comm; apply Zplus_opp_r. + intro; rewrite Zplus_comm; apply Zplus_opp_r. Qed. Hint Local Resolve Zplus_0_l Zplus_0_r. -(** addition is associative *) +(** ** addition is associative *) Lemma weak_assoc : - forall (p q:positive) (n:Z), Zpos p + (Zpos q + n) = Zpos p + Zpos q + n. -Proof. -intros x y z'; case z'; - [ auto with arith - | intros z; simpl in |- *; rewrite Pplus_assoc; auto with arith - | intros z; simpl in |- *; ElimPcompare y z; intros E0; rewrite E0; - ElimPcompare (x + y)%positive z; intros E1; rewrite E1; - [ absurd ((x + y ?= z)%positive Eq = Eq); - [ (* Case 1 *) - rewrite nat_of_P_gt_Gt_compare_complement_morphism; - [ discriminate - | rewrite nat_of_P_plus_morphism; rewrite (Pcompare_Eq_eq y z E0); - elim (ZL4 x); intros k E2; rewrite E2; - simpl in |- *; unfold gt, lt in |- *; - apply le_n_S; apply le_plus_r ] - | assumption ] - | absurd ((x + y ?= z)%positive Eq = Lt); - [ (* Case 2 *) - rewrite nat_of_P_gt_Gt_compare_complement_morphism; - [ discriminate - | rewrite nat_of_P_plus_morphism; rewrite (Pcompare_Eq_eq y z E0); - elim (ZL4 x); intros k E2; rewrite E2; - simpl in |- *; unfold gt, lt in |- *; - apply le_n_S; apply le_plus_r ] - | assumption ] - | rewrite (Pcompare_Eq_eq y z E0); - (* Case 3 *) - elim (Pminus_mask_Gt (x + z) z); - [ intros t H; elim H; intros H1 H2; elim H2; intros H3 H4; - unfold Pminus in |- *; rewrite H1; cut (x = t); - [ intros E; rewrite E; auto with arith - | apply Pplus_reg_r with (r := z); rewrite <- H3; - rewrite Pplus_comm; trivial with arith ] - | pattern z at 1 in |- *; rewrite <- (Pcompare_Eq_eq y z E0); - assumption ] - | elim (Pminus_mask_Gt z y); - [ (* Case 4 *) - intros k H; elim H; intros H1 H2; elim H2; intros H3 H4; - unfold Pminus at 1 in |- *; rewrite H1; cut (x = k); - [ intros E; rewrite E; rewrite (Pcompare_refl k); - trivial with arith - | apply Pplus_reg_r with (r := y); rewrite (Pplus_comm k y); - rewrite H3; apply Pcompare_Eq_eq; assumption ] - | apply ZC2; assumption ] - | elim (Pminus_mask_Gt z y); - [ (* Case 5 *) - intros k H; elim H; intros H1 H2; elim H2; intros H3 H4; - unfold Pminus at 1 3 5 in |- *; rewrite H1; - cut ((x ?= k)%positive Eq = Lt); - [ intros E2; rewrite E2; elim (Pminus_mask_Gt k x); - [ intros i H5; elim H5; intros H6 H7; elim H7; intros H8 H9; - elim (Pminus_mask_Gt z (x + y)); - [ intros j H10; elim H10; intros H11 H12; elim H12; - intros H13 H14; unfold Pminus in |- *; - rewrite H6; rewrite H11; cut (i = j); - [ intros E; rewrite E; auto with arith - | apply (Pplus_reg_l (x + y)); rewrite H13; - rewrite (Pplus_comm x y); rewrite <- Pplus_assoc; - rewrite H8; assumption ] - | apply ZC2; assumption ] - | apply ZC2; assumption ] - | apply nat_of_P_lt_Lt_compare_complement_morphism; - apply plus_lt_reg_l with (p := nat_of_P y); - do 2 rewrite <- nat_of_P_plus_morphism; - apply nat_of_P_lt_Lt_compare_morphism; - rewrite H3; rewrite Pplus_comm; assumption ] - | apply ZC2; assumption ] - | elim (Pminus_mask_Gt z y); - [ (* Case 6 *) - intros k H; elim H; intros H1 H2; elim H2; intros H3 H4; - elim (Pminus_mask_Gt (x + y) z); - [ intros i H5; elim H5; intros H6 H7; elim H7; intros H8 H9; - unfold Pminus in |- *; rewrite H1; rewrite H6; - cut ((x ?= k)%positive Eq = Gt); - [ intros H10; elim (Pminus_mask_Gt x k H10); intros j H11; - elim H11; intros H12 H13; elim H13; - intros H14 H15; rewrite H10; rewrite H12; - cut (i = j); - [ intros H16; rewrite H16; auto with arith - | apply (Pplus_reg_l (z + k)); rewrite <- (Pplus_assoc z k j); - rewrite H14; rewrite (Pplus_comm z k); - rewrite <- Pplus_assoc; rewrite H8; - rewrite (Pplus_comm x y); rewrite Pplus_assoc; - rewrite (Pplus_comm k y); rewrite H3; - trivial with arith ] - | apply nat_of_P_gt_Gt_compare_complement_morphism; - unfold lt, gt in |- *; - apply plus_lt_reg_l with (p := nat_of_P y); - do 2 rewrite <- nat_of_P_plus_morphism; - apply nat_of_P_lt_Lt_compare_morphism; - rewrite H3; rewrite Pplus_comm; apply ZC1; - assumption ] - | assumption ] - | apply ZC2; assumption ] - | absurd ((x + y ?= z)%positive Eq = Eq); - [ (* Case 7 *) - rewrite nat_of_P_gt_Gt_compare_complement_morphism; - [ discriminate - | rewrite nat_of_P_plus_morphism; unfold gt in |- *; - apply lt_le_trans with (m := nat_of_P y); - [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption - | apply le_plus_r ] ] - | assumption ] - | absurd ((x + y ?= z)%positive Eq = Lt); - [ (* Case 8 *) - rewrite nat_of_P_gt_Gt_compare_complement_morphism; - [ discriminate - | unfold gt in |- *; apply lt_le_trans with (m := nat_of_P y); - [ exact (nat_of_P_gt_Gt_compare_morphism y z E0) - | rewrite nat_of_P_plus_morphism; apply le_plus_r ] ] - | assumption ] - | elim Pminus_mask_Gt with (1 := E0); intros k H1; - (* Case 9 *) - elim Pminus_mask_Gt with (1 := E1); intros i H2; - elim H1; intros H3 H4; elim H4; intros H5 H6; - elim H2; intros H7 H8; elim H8; intros H9 H10; - unfold Pminus in |- *; rewrite H3; rewrite H7; - cut ((x + k)%positive = i); - [ intros E; rewrite E; auto with arith - | apply (Pplus_reg_l z); rewrite (Pplus_comm x k); rewrite Pplus_assoc; - rewrite H5; rewrite H9; rewrite Pplus_comm; - trivial with arith ] ] ]. + forall (p q:positive) (n:Z), Zpos p + (Zpos q + n) = Zpos p + Zpos q + n. +Proof. + intros x y z'; case z'; + [ auto with arith + | intros z; simpl in |- *; rewrite Pplus_assoc; auto with arith + | intros z; simpl in |- *; ElimPcompare y z; intros E0; rewrite E0; + ElimPcompare (x + y)%positive z; intros E1; rewrite E1; + [ absurd ((x + y ?= z)%positive Eq = Eq); + [ (* Case 1 *) + rewrite nat_of_P_gt_Gt_compare_complement_morphism; + [ discriminate + | rewrite nat_of_P_plus_morphism; rewrite (Pcompare_Eq_eq y z E0); + elim (ZL4 x); intros k E2; rewrite E2; + simpl in |- *; unfold gt, lt in |- *; + apply le_n_S; apply le_plus_r ] + | assumption ] + | absurd ((x + y ?= z)%positive Eq = Lt); + [ (* Case 2 *) + rewrite nat_of_P_gt_Gt_compare_complement_morphism; + [ discriminate + | rewrite nat_of_P_plus_morphism; rewrite (Pcompare_Eq_eq y z E0); + elim (ZL4 x); intros k E2; rewrite E2; + simpl in |- *; unfold gt, lt in |- *; + apply le_n_S; apply le_plus_r ] + | assumption ] + | rewrite (Pcompare_Eq_eq y z E0); + (* Case 3 *) + elim (Pminus_mask_Gt (x + z) z); + [ intros t H; elim H; intros H1 H2; elim H2; intros H3 H4; + unfold Pminus in |- *; rewrite H1; cut (x = t); + [ intros E; rewrite E; auto with arith + | apply Pplus_reg_r with (r := z); rewrite <- H3; + rewrite Pplus_comm; trivial with arith ] + | pattern z at 1 in |- *; rewrite <- (Pcompare_Eq_eq y z E0); + assumption ] + | elim (Pminus_mask_Gt z y); + [ (* Case 4 *) + intros k H; elim H; intros H1 H2; elim H2; intros H3 H4; + unfold Pminus at 1 in |- *; rewrite H1; cut (x = k); + [ intros E; rewrite E; rewrite (Pcompare_refl k); + trivial with arith + | apply Pplus_reg_r with (r := y); rewrite (Pplus_comm k y); + rewrite H3; apply Pcompare_Eq_eq; assumption ] + | apply ZC2; assumption ] + | elim (Pminus_mask_Gt z y); + [ (* Case 5 *) + intros k H; elim H; intros H1 H2; elim H2; intros H3 H4; + unfold Pminus at 1 3 5 in |- *; rewrite H1; + cut ((x ?= k)%positive Eq = Lt); + [ intros E2; rewrite E2; elim (Pminus_mask_Gt k x); + [ intros i H5; elim H5; intros H6 H7; elim H7; intros H8 H9; + elim (Pminus_mask_Gt z (x + y)); + [ intros j H10; elim H10; intros H11 H12; elim H12; + intros H13 H14; unfold Pminus in |- *; + rewrite H6; rewrite H11; cut (i = j); + [ intros E; rewrite E; auto with arith + | apply (Pplus_reg_l (x + y)); rewrite H13; + rewrite (Pplus_comm x y); rewrite <- Pplus_assoc; + rewrite H8; assumption ] + | apply ZC2; assumption ] + | apply ZC2; assumption ] + | apply nat_of_P_lt_Lt_compare_complement_morphism; + apply plus_lt_reg_l with (p := nat_of_P y); + do 2 rewrite <- nat_of_P_plus_morphism; + apply nat_of_P_lt_Lt_compare_morphism; + rewrite H3; rewrite Pplus_comm; assumption ] + | apply ZC2; assumption ] + | elim (Pminus_mask_Gt z y); + [ (* Case 6 *) + intros k H; elim H; intros H1 H2; elim H2; intros H3 H4; + elim (Pminus_mask_Gt (x + y) z); + [ intros i H5; elim H5; intros H6 H7; elim H7; intros H8 H9; + unfold Pminus in |- *; rewrite H1; rewrite H6; + cut ((x ?= k)%positive Eq = Gt); + [ intros H10; elim (Pminus_mask_Gt x k H10); intros j H11; + elim H11; intros H12 H13; elim H13; + intros H14 H15; rewrite H10; rewrite H12; + cut (i = j); + [ intros H16; rewrite H16; auto with arith + | apply (Pplus_reg_l (z + k)); rewrite <- (Pplus_assoc z k j); + rewrite H14; rewrite (Pplus_comm z k); + rewrite <- Pplus_assoc; rewrite H8; + rewrite (Pplus_comm x y); rewrite Pplus_assoc; + rewrite (Pplus_comm k y); rewrite H3; + trivial with arith ] + | apply nat_of_P_gt_Gt_compare_complement_morphism; + unfold lt, gt in |- *; + apply plus_lt_reg_l with (p := nat_of_P y); + do 2 rewrite <- nat_of_P_plus_morphism; + apply nat_of_P_lt_Lt_compare_morphism; + rewrite H3; rewrite Pplus_comm; apply ZC1; + assumption ] + | assumption ] + | apply ZC2; assumption ] + | absurd ((x + y ?= z)%positive Eq = Eq); + [ (* Case 7 *) + rewrite nat_of_P_gt_Gt_compare_complement_morphism; + [ discriminate + | rewrite nat_of_P_plus_morphism; unfold gt in |- *; + apply lt_le_trans with (m := nat_of_P y); + [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption + | apply le_plus_r ] ] + | assumption ] + | absurd ((x + y ?= z)%positive Eq = Lt); + [ (* Case 8 *) + rewrite nat_of_P_gt_Gt_compare_complement_morphism; + [ discriminate + | unfold gt in |- *; apply lt_le_trans with (m := nat_of_P y); + [ exact (nat_of_P_gt_Gt_compare_morphism y z E0) + | rewrite nat_of_P_plus_morphism; apply le_plus_r ] ] + | assumption ] + | elim Pminus_mask_Gt with (1 := E0); intros k H1; + (* Case 9 *) + elim Pminus_mask_Gt with (1 := E1); intros i H2; + elim H1; intros H3 H4; elim H4; intros H5 H6; + elim H2; intros H7 H8; elim H8; intros H9 H10; + unfold Pminus in |- *; rewrite H3; rewrite H7; + cut ((x + k)%positive = i); + [ intros E; rewrite E; auto with arith + | apply (Pplus_reg_l z); rewrite (Pplus_comm x k); rewrite Pplus_assoc; + rewrite H5; rewrite H9; rewrite Pplus_comm; + trivial with arith ] ] ]. Qed. Hint Local Resolve weak_assoc. Theorem Zplus_assoc : forall n m p:Z, n + (m + p) = n + m + p. Proof. -intros x y z; case x; case y; case z; auto with arith; intros; - [ rewrite (Zplus_comm (Zneg p0)); rewrite weak_assoc; - rewrite (Zplus_comm (Zpos p1 + Zneg p0)); rewrite weak_assoc; - rewrite (Zplus_comm (Zpos p1)); trivial with arith - | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; - rewrite Zplus_comm; rewrite <- weak_assoc; - rewrite (Zplus_comm (- Zpos p1)); - rewrite (Zplus_comm (Zpos p0 + - Zpos p1)); rewrite (weak_assoc p); - rewrite weak_assoc; rewrite (Zplus_comm (Zpos p0)); - trivial with arith - | rewrite Zplus_comm; rewrite (Zplus_comm (Zpos p0) (Zpos p)); - rewrite <- weak_assoc; rewrite Zplus_comm; rewrite (Zplus_comm (Zpos p0)); - trivial with arith - | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; - rewrite (Zplus_comm (- Zpos p0)); rewrite weak_assoc; - rewrite (Zplus_comm (Zpos p1 + - Zpos p0)); rewrite weak_assoc; - rewrite (Zplus_comm (Zpos p)); trivial with arith - | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; - apply weak_assoc - | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; - apply weak_assoc ]. + intros x y z; case x; case y; case z; auto with arith; intros; + [ rewrite (Zplus_comm (Zneg p0)); rewrite weak_assoc; + rewrite (Zplus_comm (Zpos p1 + Zneg p0)); rewrite weak_assoc; + rewrite (Zplus_comm (Zpos p1)); trivial with arith + | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; + rewrite Zplus_comm; rewrite <- weak_assoc; + rewrite (Zplus_comm (- Zpos p1)); + rewrite (Zplus_comm (Zpos p0 + - Zpos p1)); rewrite (weak_assoc p); + rewrite weak_assoc; rewrite (Zplus_comm (Zpos p0)); + trivial with arith + | rewrite Zplus_comm; rewrite (Zplus_comm (Zpos p0) (Zpos p)); + rewrite <- weak_assoc; rewrite Zplus_comm; rewrite (Zplus_comm (Zpos p0)); + trivial with arith + | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; + rewrite (Zplus_comm (- Zpos p0)); rewrite weak_assoc; + rewrite (Zplus_comm (Zpos p1 + - Zpos p0)); rewrite weak_assoc; + rewrite (Zplus_comm (Zpos p)); trivial with arith + | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; + apply weak_assoc + | apply Zopp_inj; do 4 rewrite Zopp_plus_distr; do 2 rewrite Zopp_neg; + apply weak_assoc ]. Qed. Lemma Zplus_assoc_reverse : forall n m p:Z, n + m + p = n + (m + p). Proof. -intros; symmetry in |- *; apply Zplus_assoc. + intros; symmetry in |- *; apply Zplus_assoc. Qed. -(** Associativity mixed with commutativity *) +(** ** Associativity mixed with commutativity *) Theorem Zplus_permute : forall n m p:Z, n + (m + p) = m + (n + p). Proof. -intros n m p; rewrite Zplus_comm; rewrite <- Zplus_assoc; - rewrite (Zplus_comm p n); trivial with arith. + intros n m p; rewrite Zplus_comm; rewrite <- Zplus_assoc; + rewrite (Zplus_comm p n); trivial with arith. Qed. -(** addition simplifies *) +(** ** addition simplifies *) Theorem Zplus_reg_l : forall n m p:Z, n + m = n + p -> m = p. -intros n m p H; cut (- n + (n + m) = - n + (n + p)); - [ do 2 rewrite Zplus_assoc; rewrite (Zplus_comm (- n) n); - rewrite Zplus_opp_r; simpl in |- *; trivial with arith - | rewrite H; trivial with arith ]. + intros n m p H; cut (- n + (n + m) = - n + (n + p)); + [ do 2 rewrite Zplus_assoc; rewrite (Zplus_comm (- n) n); + rewrite Zplus_opp_r; simpl in |- *; trivial with arith + | rewrite H; trivial with arith ]. Qed. -(** addition and successor permutes *) +(** ** addition and successor permutes *) Lemma Zplus_succ_l : forall n m:Z, Zsucc n + m = Zsucc (n + m). Proof. -intros x y; unfold Zsucc in |- *; rewrite (Zplus_comm (x + y)); - rewrite Zplus_assoc; rewrite (Zplus_comm (Zpos 1)); - trivial with arith. + intros x y; unfold Zsucc in |- *; rewrite (Zplus_comm (x + y)); + rewrite Zplus_assoc; rewrite (Zplus_comm (Zpos 1)); + trivial with arith. Qed. Lemma Zplus_succ_r : forall n m:Z, Zsucc (n + m) = n + Zsucc m. Proof. -intros n m; unfold Zsucc in |- *; rewrite Zplus_assoc; trivial with arith. + intros n m; unfold Zsucc in |- *; rewrite Zplus_assoc; trivial with arith. Qed. Lemma Zplus_succ_comm : forall n m:Z, Zsucc n + m = n + Zsucc m. Proof. -unfold Zsucc in |- *; intros n m; rewrite <- Zplus_assoc; - rewrite (Zplus_comm (Zpos 1)); trivial with arith. + unfold Zsucc in |- *; intros n m; rewrite <- Zplus_assoc; + rewrite (Zplus_comm (Zpos 1)); trivial with arith. Qed. -(** Misc properties, usually redundant or non natural *) +(** ** Misc properties, usually redundant or non natural *) Lemma Zplus_0_r_reverse : forall n:Z, n = n + Z0. Proof. -symmetry in |- *; apply Zplus_0_r. + symmetry in |- *; apply Zplus_0_r. Qed. Lemma Zplus_0_simpl_l : forall n m:Z, n + Z0 = m -> n = m. Proof. -intros n m; rewrite Zplus_0_r; intro; assumption. + intros n m; rewrite Zplus_0_r; intro; assumption. Qed. Lemma Zplus_0_simpl_l_reverse : forall n m:Z, n = m + Z0 -> n = m. Proof. -intros n m; rewrite Zplus_0_r; intro; assumption. + intros n m; rewrite Zplus_0_r; intro; assumption. Qed. Lemma Zplus_eq_compat : forall n m p q:Z, n = m -> p = q -> n + p = m + q. Proof. -intros; rewrite H; rewrite H0; reflexivity. + intros; rewrite H; rewrite H0; reflexivity. Qed. Lemma Zplus_opp_expand : forall n m p:Z, n + - m = n + - p + (p + - m). Proof. -intros x y z. -rewrite <- (Zplus_assoc x). -rewrite (Zplus_assoc (- z)). -rewrite Zplus_opp_l. -reflexivity. + intros x y z. + rewrite <- (Zplus_assoc x). + rewrite (Zplus_assoc (- z)). + rewrite Zplus_opp_l. + reflexivity. Qed. -(**********************************************************************) -(** Properties of successor and predecessor on binary integer numbers *) +(************************************************************************) +(** * Properties of successor and predecessor on binary integer numbers *) Theorem Zsucc_discr : forall n:Z, n <> Zsucc n. Proof. -intros n; cut (Z0 <> Zpos 1); - [ unfold not in |- *; intros H1 H2; apply H1; apply (Zplus_reg_l n); - rewrite Zplus_0_r; exact H2 - | discriminate ]. + intros n; cut (Z0 <> Zpos 1); + [ unfold not in |- *; intros H1 H2; apply H1; apply (Zplus_reg_l n); + rewrite Zplus_0_r; exact H2 + | discriminate ]. Qed. Theorem Zpos_succ_morphism : - forall p:positive, Zpos (Psucc p) = Zsucc (Zpos p). + forall p:positive, Zpos (Psucc p) = Zsucc (Zpos p). Proof. -intro; rewrite Pplus_one_succ_r; unfold Zsucc in |- *; simpl in |- *; - trivial with arith. + intro; rewrite Pplus_one_succ_r; unfold Zsucc in |- *; simpl in |- *; + trivial with arith. Qed. (** successor and predecessor are inverse functions *) Theorem Zsucc_pred : forall n:Z, n = Zsucc (Zpred n). Proof. -intros n; unfold Zsucc, Zpred in |- *; rewrite <- Zplus_assoc; simpl in |- *; - rewrite Zplus_0_r; trivial with arith. + intros n; unfold Zsucc, Zpred in |- *; rewrite <- Zplus_assoc; simpl in |- *; + rewrite Zplus_0_r; trivial with arith. Qed. Hint Immediate Zsucc_pred: zarith. Theorem Zpred_succ : forall n:Z, n = Zpred (Zsucc n). Proof. -intros m; unfold Zpred, Zsucc in |- *; rewrite <- Zplus_assoc; simpl in |- *; - rewrite Zplus_comm; auto with arith. + intros m; unfold Zpred, Zsucc in |- *; rewrite <- Zplus_assoc; simpl in |- *; + rewrite Zplus_comm; auto with arith. Qed. Theorem Zsucc_inj : forall n m:Z, Zsucc n = Zsucc m -> n = m. Proof. -intros n m H. -change (Zneg 1 + Zpos 1 + n = Zneg 1 + Zpos 1 + m) in |- *; - do 2 rewrite <- Zplus_assoc; do 2 rewrite (Zplus_comm (Zpos 1)); - unfold Zsucc in H; rewrite H; trivial with arith. + intros n m H. + change (Zneg 1 + Zpos 1 + n = Zneg 1 + Zpos 1 + m) in |- *; + do 2 rewrite <- Zplus_assoc; do 2 rewrite (Zplus_comm (Zpos 1)); + unfold Zsucc in H; rewrite H; trivial with arith. Qed. (** Misc properties, usually redundant or non natural *) Lemma Zsucc_eq_compat : forall n m:Z, n = m -> Zsucc n = Zsucc m. Proof. -intros n m H; rewrite H; reflexivity. + intros n m H; rewrite H; reflexivity. Qed. Lemma Zsucc_inj_contrapositive : forall n m:Z, n <> m -> Zsucc n <> Zsucc m. Proof. -unfold not in |- *; intros n m H1 H2; apply H1; apply Zsucc_inj; assumption. + unfold not in |- *; intros n m H1 H2; apply H1; apply Zsucc_inj; assumption. Qed. (**********************************************************************) -(** Properties of subtraction on binary integer numbers *) +(** * Properties of subtraction on binary integer numbers *) + +(** ** [minus] and [Z0] *) Lemma Zminus_0_r : forall n:Z, n - Z0 = n. Proof. -intro; unfold Zminus in |- *; simpl in |- *; rewrite Zplus_0_r; - trivial with arith. + intro; unfold Zminus in |- *; simpl in |- *; rewrite Zplus_0_r; + trivial with arith. Qed. Lemma Zminus_0_l_reverse : forall n:Z, n = n - Z0. Proof. -intro; symmetry in |- *; apply Zminus_0_r. + intro; symmetry in |- *; apply Zminus_0_r. Qed. Lemma Zminus_diag : forall n:Z, n - n = Z0. Proof. -intro; unfold Zminus in |- *; rewrite Zplus_opp_r; trivial with arith. + intro; unfold Zminus in |- *; rewrite Zplus_opp_r; trivial with arith. Qed. Lemma Zminus_diag_reverse : forall n:Z, Z0 = n - n. Proof. -intro; symmetry in |- *; apply Zminus_diag. + intro; symmetry in |- *; apply Zminus_diag. Qed. + +(** ** Relating [minus] with [plus] and [Zsucc] *) + Lemma Zplus_minus_eq : forall n m p:Z, n = m + p -> p = n - m. Proof. -intros n m p H; unfold Zminus in |- *; apply (Zplus_reg_l m); - rewrite (Zplus_comm m (n + - m)); rewrite <- Zplus_assoc; - rewrite Zplus_opp_l; rewrite Zplus_0_r; rewrite H; - trivial with arith. + intros n m p H; unfold Zminus in |- *; apply (Zplus_reg_l m); + rewrite (Zplus_comm m (n + - m)); rewrite <- Zplus_assoc; + rewrite Zplus_opp_l; rewrite Zplus_0_r; rewrite H; + trivial with arith. Qed. Lemma Zminus_plus : forall n m:Z, n + m - n = m. Proof. -intros n m; unfold Zminus in |- *; rewrite (Zplus_comm n m); - rewrite <- Zplus_assoc; rewrite Zplus_opp_r; apply Zplus_0_r. + intros n m; unfold Zminus in |- *; rewrite (Zplus_comm n m); + rewrite <- Zplus_assoc; rewrite Zplus_opp_r; apply Zplus_0_r. Qed. Lemma Zplus_minus : forall n m:Z, n + (m - n) = m. Proof. -unfold Zminus in |- *; intros n m; rewrite Zplus_permute; rewrite Zplus_opp_r; - apply Zplus_0_r. + unfold Zminus in |- *; intros n m; rewrite Zplus_permute; rewrite Zplus_opp_r; + apply Zplus_0_r. Qed. Lemma Zminus_succ_l : forall n m:Z, Zsucc (n - m) = Zsucc n - m. Proof. -intros n m; unfold Zminus, Zsucc in |- *; rewrite (Zplus_comm n (- m)); - rewrite <- Zplus_assoc; apply Zplus_comm. + intros n m; unfold Zminus, Zsucc in |- *; rewrite (Zplus_comm n (- m)); + rewrite <- Zplus_assoc; apply Zplus_comm. Qed. Lemma Zminus_plus_simpl_l : forall n m p:Z, p + n - (p + m) = n - m. Proof. -intros n m p; unfold Zminus in |- *; rewrite Zopp_plus_distr; - rewrite Zplus_assoc; rewrite (Zplus_comm p); rewrite <- (Zplus_assoc n p); - rewrite Zplus_opp_r; rewrite Zplus_0_r; trivial with arith. + intros n m p; unfold Zminus in |- *; rewrite Zopp_plus_distr; + rewrite Zplus_assoc; rewrite (Zplus_comm p); rewrite <- (Zplus_assoc n p); + rewrite Zplus_opp_r; rewrite Zplus_0_r; trivial with arith. Qed. Lemma Zminus_plus_simpl_l_reverse : forall n m p:Z, n - m = p + n - (p + m). Proof. -intros; symmetry in |- *; apply Zminus_plus_simpl_l. + intros; symmetry in |- *; apply Zminus_plus_simpl_l. Qed. Lemma Zminus_plus_simpl_r : forall n m p:Z, n + p - (m + p) = n - m. -intros x y n. -unfold Zminus in |- *. -rewrite Zopp_plus_distr. -rewrite (Zplus_comm (- y) (- n)). -rewrite Zplus_assoc. -rewrite <- (Zplus_assoc x n (- n)). -rewrite (Zplus_opp_r n). -rewrite <- Zplus_0_r_reverse. -reflexivity. +Proof. + intros x y n. + unfold Zminus in |- *. + rewrite Zopp_plus_distr. + rewrite (Zplus_comm (- y) (- n)). + rewrite Zplus_assoc. + rewrite <- (Zplus_assoc x n (- n)). + rewrite (Zplus_opp_r n). + rewrite <- Zplus_0_r_reverse. + reflexivity. Qed. -(** Misc redundant properties *) - +(** ** Misc redundant properties *) Lemma Zeq_minus : forall n m:Z, n = m -> n - m = Z0. Proof. -intros x y H; rewrite H; symmetry in |- *; apply Zminus_diag_reverse. + intros x y H; rewrite H; symmetry in |- *; apply Zminus_diag_reverse. Qed. Lemma Zminus_eq : forall n m:Z, n - m = Z0 -> n = m. Proof. -intros x y H; rewrite <- (Zplus_minus y x); rewrite H; apply Zplus_0_r. + intros x y H; rewrite <- (Zplus_minus y x); rewrite H; apply Zplus_0_r. Qed. (**********************************************************************) -(** Properties of multiplication on binary integer numbers *) +(** * Properties of multiplication on binary integer numbers *) Theorem Zpos_mult_morphism : - forall p q:positive, Zpos (p*q) = Zpos p * Zpos q. + forall p q:positive, Zpos (p*q) = Zpos p * Zpos q. Proof. -auto. + auto. Qed. -(** One is neutral for multiplication *) +(** ** One is neutral for multiplication *) Theorem Zmult_1_l : forall n:Z, Zpos 1 * n = n. Proof. -intro x; destruct x; reflexivity. + intro x; destruct x; reflexivity. Qed. Theorem Zmult_1_r : forall n:Z, n * Zpos 1 = n. Proof. -intro x; destruct x; simpl in |- *; try rewrite Pmult_1_r; reflexivity. + intro x; destruct x; simpl in |- *; try rewrite Pmult_1_r; reflexivity. Qed. -(** Zero property of multiplication *) +(** ** Zero property of multiplication *) Theorem Zmult_0_l : forall n:Z, Z0 * n = Z0. Proof. -intro x; destruct x; reflexivity. + intro x; destruct x; reflexivity. Qed. Theorem Zmult_0_r : forall n:Z, n * Z0 = Z0. Proof. -intro x; destruct x; reflexivity. + intro x; destruct x; reflexivity. Qed. Hint Local Resolve Zmult_0_l Zmult_0_r. Lemma Zmult_0_r_reverse : forall n:Z, Z0 = n * Z0. Proof. -intro x; destruct x; reflexivity. + intro x; destruct x; reflexivity. Qed. -(** Commutativity of multiplication *) +(** ** Commutativity of multiplication *) Theorem Zmult_comm : forall n m:Z, n * m = m * n. Proof. -intros x y; destruct x as [| p| p]; destruct y as [| q| q]; simpl in |- *; - try rewrite (Pmult_comm p q); reflexivity. + intros x y; destruct x as [| p| p]; destruct y as [| q| q]; simpl in |- *; + try rewrite (Pmult_comm p q); reflexivity. Qed. -(** Associativity of multiplication *) +(** ** Associativity of multiplication *) Theorem Zmult_assoc : forall n m p:Z, n * (m * p) = n * m * p. Proof. -intros x y z; destruct x; destruct y; destruct z; simpl in |- *; - try rewrite Pmult_assoc; reflexivity. + intros x y z; destruct x; destruct y; destruct z; simpl in |- *; + try rewrite Pmult_assoc; reflexivity. Qed. Lemma Zmult_assoc_reverse : forall n m p:Z, n * m * p = n * (m * p). Proof. -intros n m p; rewrite Zmult_assoc; trivial with arith. + intros n m p; rewrite Zmult_assoc; trivial with arith. Qed. -(** Associativity mixed with commutativity *) +(** ** Associativity mixed with commutativity *) Theorem Zmult_permute : forall n m p:Z, n * (m * p) = m * (n * p). Proof. -intros x y z; rewrite (Zmult_assoc y x z); rewrite (Zmult_comm y x). -apply Zmult_assoc. + intros x y z; rewrite (Zmult_assoc y x z); rewrite (Zmult_comm y x). + apply Zmult_assoc. Qed. -(** Z is integral *) +(** ** Z is integral *) Theorem Zmult_integral_l : forall n m:Z, n <> Z0 -> m * n = Z0 -> m = Z0. Proof. -intros x y; destruct x as [| p| p]. + intros x y; destruct x as [| p| p]. intro H; absurd (Z0 = Z0); trivial. intros _ H; destruct y as [| q| q]; reflexivity || discriminate. intros _ H; destruct y as [| q| q]; reflexivity || discriminate. @@ -782,214 +791,220 @@ Qed. Theorem Zmult_integral : forall n m:Z, n * m = Z0 -> n = Z0 \/ m = Z0. Proof. -intros x y; destruct x; destruct y; auto; simpl in |- *; intro H; - discriminate H. + intros x y; destruct x; destruct y; auto; simpl in |- *; intro H; + discriminate H. Qed. Lemma Zmult_1_inversion_l : - forall n m:Z, n * m = Zpos 1 -> n = Zpos 1 \/ n = Zneg 1. + forall n m:Z, n * m = Zpos 1 -> n = Zpos 1 \/ n = Zneg 1. Proof. -intros x y; destruct x as [| p| p]; intro; [ discriminate | left | right ]; - (destruct y as [| q| q]; try discriminate; simpl in H; injection H; clear H; - intro H; rewrite Pmult_1_inversion_l with (1 := H); - reflexivity). + intros x y; destruct x as [| p| p]; intro; [ discriminate | left | right ]; + (destruct y as [| q| q]; try discriminate; simpl in H; injection H; clear H; + intro H; rewrite Pmult_1_inversion_l with (1 := H); + reflexivity). Qed. -(** Multiplication and Opposite *) +(** ** Multiplication and Opposite *) Theorem Zopp_mult_distr_l : forall n m:Z, - (n * m) = - n * m. Proof. -intros x y; destruct x; destruct y; reflexivity. + intros x y; destruct x; destruct y; reflexivity. Qed. Theorem Zopp_mult_distr_r : forall n m:Z, - (n * m) = n * - m. -intros x y; rewrite (Zmult_comm x y); rewrite Zopp_mult_distr_l; - apply Zmult_comm. +Proof. + intros x y; rewrite (Zmult_comm x y); rewrite Zopp_mult_distr_l; + apply Zmult_comm. Qed. Lemma Zopp_mult_distr_l_reverse : forall n m:Z, - n * m = - (n * m). Proof. -intros x y; symmetry in |- *; apply Zopp_mult_distr_l. + intros x y; symmetry in |- *; apply Zopp_mult_distr_l. Qed. Theorem Zmult_opp_comm : forall n m:Z, - n * m = n * - m. -intros x y; rewrite Zopp_mult_distr_l_reverse; rewrite Zopp_mult_distr_r; - trivial with arith. +Proof. + intros x y; rewrite Zopp_mult_distr_l_reverse; rewrite Zopp_mult_distr_r; + trivial with arith. Qed. Theorem Zmult_opp_opp : forall n m:Z, - n * - m = n * m. Proof. -intros x y; destruct x; destruct y; reflexivity. + intros x y; destruct x; destruct y; reflexivity. Qed. Theorem Zopp_eq_mult_neg_1 : forall n:Z, - n = n * Zneg 1. -intro x; induction x; intros; rewrite Zmult_comm; auto with arith. +Proof. + intro x; induction x; intros; rewrite Zmult_comm; auto with arith. Qed. -(** Distributivity of multiplication over addition *) +(** ** Distributivity of multiplication over addition *) Lemma weak_Zmult_plus_distr_r : - forall (p:positive) (n m:Z), Zpos p * (n + m) = Zpos p * n + Zpos p * m. -Proof. -intros x y' z'; case y'; case z'; auto with arith; intros y z; - (simpl in |- *; rewrite Pmult_plus_distr_l; trivial with arith) || - (simpl in |- *; ElimPcompare z y; intros E0; rewrite E0; - [ rewrite (Pcompare_Eq_eq z y E0); rewrite (Pcompare_refl (x * y)); - trivial with arith - | cut ((x * z ?= x * y)%positive Eq = Lt); - [ intros E; rewrite E; rewrite Pmult_minus_distr_l; - [ trivial with arith | apply ZC2; assumption ] - | apply nat_of_P_lt_Lt_compare_complement_morphism; - do 2 rewrite nat_of_P_mult_morphism; elim (ZL4 x); - intros h H1; rewrite H1; apply mult_S_lt_compat_l; - exact (nat_of_P_lt_Lt_compare_morphism z y E0) ] - | cut ((x * z ?= x * y)%positive Eq = Gt); - [ intros E; rewrite E; rewrite Pmult_minus_distr_l; auto with arith - | apply nat_of_P_gt_Gt_compare_complement_morphism; unfold gt in |- *; - do 2 rewrite nat_of_P_mult_morphism; elim (ZL4 x); - intros h H1; rewrite H1; apply mult_S_lt_compat_l; - exact (nat_of_P_gt_Gt_compare_morphism z y E0) ] ]). + forall (p:positive) (n m:Z), Zpos p * (n + m) = Zpos p * n + Zpos p * m. +Proof. + intros x y' z'; case y'; case z'; auto with arith; intros y z; + (simpl in |- *; rewrite Pmult_plus_distr_l; trivial with arith) || + (simpl in |- *; ElimPcompare z y; intros E0; rewrite E0; + [ rewrite (Pcompare_Eq_eq z y E0); rewrite (Pcompare_refl (x * y)); + trivial with arith + | cut ((x * z ?= x * y)%positive Eq = Lt); + [ intros E; rewrite E; rewrite Pmult_minus_distr_l; + [ trivial with arith | apply ZC2; assumption ] + | apply nat_of_P_lt_Lt_compare_complement_morphism; + do 2 rewrite nat_of_P_mult_morphism; elim (ZL4 x); + intros h H1; rewrite H1; apply mult_S_lt_compat_l; + exact (nat_of_P_lt_Lt_compare_morphism z y E0) ] + | cut ((x * z ?= x * y)%positive Eq = Gt); + [ intros E; rewrite E; rewrite Pmult_minus_distr_l; auto with arith + | apply nat_of_P_gt_Gt_compare_complement_morphism; unfold gt in |- *; + do 2 rewrite nat_of_P_mult_morphism; elim (ZL4 x); + intros h H1; rewrite H1; apply mult_S_lt_compat_l; + exact (nat_of_P_gt_Gt_compare_morphism z y E0) ] ]). Qed. Theorem Zmult_plus_distr_r : forall n m p:Z, n * (m + p) = n * m + n * p. Proof. -intros x y z; case x; - [ auto with arith - | intros x'; apply weak_Zmult_plus_distr_r - | intros p; apply Zopp_inj; rewrite Zopp_plus_distr; - do 3 rewrite <- Zopp_mult_distr_l_reverse; rewrite Zopp_neg; - apply weak_Zmult_plus_distr_r ]. + intros x y z; case x; + [ auto with arith + | intros x'; apply weak_Zmult_plus_distr_r + | intros p; apply Zopp_inj; rewrite Zopp_plus_distr; + do 3 rewrite <- Zopp_mult_distr_l_reverse; rewrite Zopp_neg; + apply weak_Zmult_plus_distr_r ]. Qed. Theorem Zmult_plus_distr_l : forall n m p:Z, (n + m) * p = n * p + m * p. Proof. -intros n m p; rewrite Zmult_comm; rewrite Zmult_plus_distr_r; - do 2 rewrite (Zmult_comm p); trivial with arith. + intros n m p; rewrite Zmult_comm; rewrite Zmult_plus_distr_r; + do 2 rewrite (Zmult_comm p); trivial with arith. Qed. -(** Distributivity of multiplication over subtraction *) +(** ** Distributivity of multiplication over subtraction *) Lemma Zmult_minus_distr_r : forall n m p:Z, (n - m) * p = n * p - m * p. Proof. -intros x y z; unfold Zminus in |- *. -rewrite <- Zopp_mult_distr_l_reverse. -apply Zmult_plus_distr_l. + intros x y z; unfold Zminus in |- *. + rewrite <- Zopp_mult_distr_l_reverse. + apply Zmult_plus_distr_l. Qed. Lemma Zmult_minus_distr_l : forall n m p:Z, p * (n - m) = p * n - p * m. Proof. -intros x y z; rewrite (Zmult_comm z (x - y)). -rewrite (Zmult_comm z x). -rewrite (Zmult_comm z y). -apply Zmult_minus_distr_r. + intros x y z; rewrite (Zmult_comm z (x - y)). + rewrite (Zmult_comm z x). + rewrite (Zmult_comm z y). + apply Zmult_minus_distr_r. Qed. -(** Simplification of multiplication for non-zero integers *) +(** ** Simplification of multiplication for non-zero integers *) Lemma Zmult_reg_l : forall n m p:Z, p <> Z0 -> p * n = p * m -> n = m. Proof. -intros x y z H H0. -generalize (Zeq_minus _ _ H0). -intro. -apply Zminus_eq. -rewrite <- Zmult_minus_distr_l in H1. -clear H0; destruct (Zmult_integral _ _ H1). -contradiction. -trivial. + intros x y z H H0. + generalize (Zeq_minus _ _ H0). + intro. + apply Zminus_eq. + rewrite <- Zmult_minus_distr_l in H1. + clear H0; destruct (Zmult_integral _ _ H1). + contradiction. + trivial. Qed. Lemma Zmult_reg_r : forall n m p:Z, p <> Z0 -> n * p = m * p -> n = m. Proof. -intros x y z Hz. -rewrite (Zmult_comm x z). -rewrite (Zmult_comm y z). -intro; apply Zmult_reg_l with z; assumption. + intros x y z Hz. + rewrite (Zmult_comm x z). + rewrite (Zmult_comm y z). + intro; apply Zmult_reg_l with z; assumption. Qed. -(** Addition and multiplication by 2 *) +(** ** Addition and multiplication by 2 *) Lemma Zplus_diag_eq_mult_2 : forall n:Z, n + n = n * Zpos 2. Proof. -intros x; pattern x at 1 2 in |- *; rewrite <- (Zmult_1_r x); - rewrite <- Zmult_plus_distr_r; reflexivity. + intros x; pattern x at 1 2 in |- *; rewrite <- (Zmult_1_r x); + rewrite <- Zmult_plus_distr_r; reflexivity. Qed. -(** Multiplication and successor *) +(** ** Multiplication and successor *) Lemma Zmult_succ_r : forall n m:Z, n * Zsucc m = n * m + n. Proof. -intros n m; unfold Zsucc in |- *; rewrite Zmult_plus_distr_r; - rewrite (Zmult_comm n (Zpos 1)); rewrite Zmult_1_l; - trivial with arith. + intros n m; unfold Zsucc in |- *; rewrite Zmult_plus_distr_r; + rewrite (Zmult_comm n (Zpos 1)); rewrite Zmult_1_l; + trivial with arith. Qed. Lemma Zmult_succ_r_reverse : forall n m:Z, n * m + n = n * Zsucc m. Proof. -intros; symmetry in |- *; apply Zmult_succ_r. + intros; symmetry in |- *; apply Zmult_succ_r. Qed. Lemma Zmult_succ_l : forall n m:Z, Zsucc n * m = n * m + m. Proof. -intros n m; unfold Zsucc in |- *; rewrite Zmult_plus_distr_l; - rewrite Zmult_1_l; trivial with arith. + intros n m; unfold Zsucc in |- *; rewrite Zmult_plus_distr_l; + rewrite Zmult_1_l; trivial with arith. Qed. Lemma Zmult_succ_l_reverse : forall n m:Z, n * m + m = Zsucc n * m. Proof. -intros; symmetry in |- *; apply Zmult_succ_l. + intros; symmetry in |- *; apply Zmult_succ_l. Qed. -(** Misc redundant properties *) +(** ** Misc redundant properties *) Lemma Z_eq_mult : forall n m:Z, m = Z0 -> m * n = Z0. -intros x y H; rewrite H; auto with arith. +Proof. + intros x y H; rewrite H; auto with arith. Qed. + + (**********************************************************************) -(** Relating binary positive numbers and binary integers *) +(** * Relating binary positive numbers and binary integers *) Lemma Zpos_xI : forall p:positive, Zpos (xI p) = Zpos 2 * Zpos p + Zpos 1. Proof. -intro; apply refl_equal. + intro; apply refl_equal. Qed. Lemma Zpos_xO : forall p:positive, Zpos (xO p) = Zpos 2 * Zpos p. Proof. -intro; apply refl_equal. + intro; apply refl_equal. Qed. Lemma Zneg_xI : forall p:positive, Zneg (xI p) = Zpos 2 * Zneg p - Zpos 1. Proof. -intro; apply refl_equal. + intro; apply refl_equal. Qed. Lemma Zneg_xO : forall p:positive, Zneg (xO p) = Zpos 2 * Zneg p. Proof. -reflexivity. + reflexivity. Qed. Lemma Zpos_plus_distr : forall p q:positive, Zpos (p + q) = Zpos p + Zpos q. Proof. -intros p p'; destruct p; - [ destruct p' as [p0| p0| ] - | destruct p' as [p0| p0| ] - | destruct p' as [p| p| ] ]; reflexivity. + intros p p'; destruct p; + [ destruct p' as [p0| p0| ] + | destruct p' as [p0| p0| ] + | destruct p' as [p| p| ] ]; reflexivity. Qed. Lemma Zneg_plus_distr : forall p q:positive, Zneg (p + q) = Zneg p + Zneg q. Proof. -intros p p'; destruct p; - [ destruct p' as [p0| p0| ] - | destruct p' as [p0| p0| ] - | destruct p' as [p| p| ] ]; reflexivity. + intros p p'; destruct p; + [ destruct p' as [p0| p0| ] + | destruct p' as [p0| p0| ] + | destruct p' as [p| p| ] ]; reflexivity. Qed. (**********************************************************************) -(** Order relations *) +(** * Order relations *) Definition Zlt (x y:Z) := (x ?= y) = Lt. Definition Zgt (x y:Z) := (x ?= y) = Gt. @@ -1008,41 +1023,41 @@ Notation "x < y < z" := (x < y /\ y < z) : Z_scope. Notation "x < y <= z" := (x < y /\ y <= z) : Z_scope. (**********************************************************************) -(** Absolute value on integers *) +(** * Absolute value on integers *) Definition Zabs_nat (x:Z) : nat := match x with - | Z0 => 0%nat - | Zpos p => nat_of_P p - | Zneg p => nat_of_P p + | Z0 => 0%nat + | Zpos p => nat_of_P p + | Zneg p => nat_of_P p end. Definition Zabs (z:Z) : Z := match z with - | Z0 => Z0 - | Zpos p => Zpos p - | Zneg p => Zpos p + | Z0 => Z0 + | Zpos p => Zpos p + | Zneg p => Zpos p end. (**********************************************************************) -(** From [nat] to [Z] *) +(** * From [nat] to [Z] *) Definition Z_of_nat (x:nat) := match x with - | O => Z0 - | S y => Zpos (P_of_succ_nat y) + | O => Z0 + | S y => Zpos (P_of_succ_nat y) end. Require Import BinNat. Definition Zabs_N (z:Z) := match z with - | Z0 => 0%N - | Zpos p => Npos p - | Zneg p => Npos p + | Z0 => 0%N + | Zpos p => Npos p + | Zneg p => Npos p end. Definition Z_of_N (x:N) := match x with - | N0 => Z0 - | Npos p => Zpos p + | N0 => Z0 + | Npos p => Zpos p end. diff --git a/theories/ZArith/Int.v b/theories/ZArith/Int.v index cb51b9d2..3cee9190 100644 --- a/theories/ZArith/Int.v +++ b/theories/ZArith/Int.v @@ -7,120 +7,126 @@ (***********************************************************************) (* Finite sets library. - * Authors: Pierre Letouzey and Jean-Christophe Filliâtre - * Institution: LRI, CNRS UMR 8623 - Université Paris Sud + * Authors: Pierre Letouzey and Jean-Christophe Filliâtre + * Institution: LRI, CNRS UMR 8623 - Université Paris Sud * 91405 Orsay, France *) -(* $Id: Int.v 8933 2006-06-09 14:08:38Z herbelin $ *) +(* $Id: Int.v 9319 2006-10-30 12:41:21Z barras $ *) -(** * An axiomatization of integers. *) +(** An axiomatization of integers. *) (** We define a signature for an integer datatype based on [Z]. - The goal is to allow a switch after extraction to ocaml's - [big_int] or even [int] when finiteness isn't a problem - (typically : when mesuring the height of an AVL tree). + The goal is to allow a switch after extraction to ocaml's + [big_int] or even [int] when finiteness isn't a problem + (typically : when mesuring the height of an AVL tree). *) Require Import ZArith. Require Import ROmega. Delimit Scope Int_scope with I. + +(** * a specification of integers *) + Module Type Int. - Open Scope Int_scope. - - Parameter int : Set. - - Parameter i2z : int -> Z. - Arguments Scope i2z [ Int_scope ]. - - Parameter _0 : int. - Parameter _1 : int. - Parameter _2 : int. - Parameter _3 : int. - Parameter plus : int -> int -> int. - Parameter opp : int -> int. - Parameter minus : int -> int -> int. - Parameter mult : int -> int -> int. - Parameter max : int -> int -> int. - - Notation "0" := _0 : Int_scope. - Notation "1" := _1 : Int_scope. - Notation "2" := _2 : Int_scope. - Notation "3" := _3 : Int_scope. - Infix "+" := plus : Int_scope. - Infix "-" := minus : Int_scope. - Infix "*" := mult : Int_scope. - Notation "- x" := (opp x) : Int_scope. - -(** For logical relations, we can rely on their counterparts in Z, - since they don't appear after extraction. Moreover, using tactics - like omega is easier this way. *) - - Notation "x == y" := (i2z x = i2z y) - (at level 70, y at next level, no associativity) : Int_scope. - Notation "x <= y" := (Zle (i2z x) (i2z y)): Int_scope. - Notation "x < y" := (Zlt (i2z x) (i2z y)) : Int_scope. - Notation "x >= y" := (Zge (i2z x) (i2z y)) : Int_scope. - Notation "x > y" := (Zgt (i2z x) (i2z y)): Int_scope. - Notation "x <= y <= z" := (x <= y /\ y <= z) : Int_scope. - Notation "x <= y < z" := (x <= y /\ y < z) : Int_scope. - Notation "x < y < z" := (x < y /\ y < z) : Int_scope. - Notation "x < y <= z" := (x < y /\ y <= z) : Int_scope. - - (** Some decidability fonctions (informative). *) - - Axiom gt_le_dec : forall x y: int, {x > y} + {x <= y}. - Axiom ge_lt_dec : forall x y : int, {x >= y} + {x < y}. - Axiom eq_dec : forall x y : int, { x == y } + {~ x==y }. - - (** Specifications *) - - (** First, we ask [i2z] to be injective. Said otherwise, our ad-hoc equality - [==] and the generic [=] are in fact equivalent. We define [==] - nonetheless since the translation to [Z] for using automatic tactic is easier. *) - - Axiom i2z_eq : forall n p : int, n == p -> n = p. - - (** Then, we express the specifications of the above parameters using their - Z counterparts. *) - - Open Scope Z_scope. - Axiom i2z_0 : i2z _0 = 0. - Axiom i2z_1 : i2z _1 = 1. - Axiom i2z_2 : i2z _2 = 2. - Axiom i2z_3 : i2z _3 = 3. - Axiom i2z_plus : forall n p, i2z (n + p) = i2z n + i2z p. - Axiom i2z_opp : forall n, i2z (-n) = -i2z n. - Axiom i2z_minus : forall n p, i2z (n - p) = i2z n - i2z p. - Axiom i2z_mult : forall n p, i2z (n * p) = i2z n * i2z p. - Axiom i2z_max : forall n p, i2z (max n p) = Zmax (i2z n) (i2z p). + Open Scope Int_scope. + + Parameter int : Set. + + Parameter i2z : int -> Z. + Arguments Scope i2z [ Int_scope ]. + + Parameter _0 : int. + Parameter _1 : int. + Parameter _2 : int. + Parameter _3 : int. + Parameter plus : int -> int -> int. + Parameter opp : int -> int. + Parameter minus : int -> int -> int. + Parameter mult : int -> int -> int. + Parameter max : int -> int -> int. + + Notation "0" := _0 : Int_scope. + Notation "1" := _1 : Int_scope. + Notation "2" := _2 : Int_scope. + Notation "3" := _3 : Int_scope. + Infix "+" := plus : Int_scope. + Infix "-" := minus : Int_scope. + Infix "*" := mult : Int_scope. + Notation "- x" := (opp x) : Int_scope. + + (** For logical relations, we can rely on their counterparts in Z, + since they don't appear after extraction. Moreover, using tactics + like omega is easier this way. *) + + Notation "x == y" := (i2z x = i2z y) + (at level 70, y at next level, no associativity) : Int_scope. + Notation "x <= y" := (Zle (i2z x) (i2z y)): Int_scope. + Notation "x < y" := (Zlt (i2z x) (i2z y)) : Int_scope. + Notation "x >= y" := (Zge (i2z x) (i2z y)) : Int_scope. + Notation "x > y" := (Zgt (i2z x) (i2z y)): Int_scope. + Notation "x <= y <= z" := (x <= y /\ y <= z) : Int_scope. + Notation "x <= y < z" := (x <= y /\ y < z) : Int_scope. + Notation "x < y < z" := (x < y /\ y < z) : Int_scope. + Notation "x < y <= z" := (x < y /\ y <= z) : Int_scope. + + (** Some decidability fonctions (informative). *) + + Axiom gt_le_dec : forall x y: int, {x > y} + {x <= y}. + Axiom ge_lt_dec : forall x y : int, {x >= y} + {x < y}. + Axiom eq_dec : forall x y : int, { x == y } + {~ x==y }. + + (** Specifications *) + + (** First, we ask [i2z] to be injective. Said otherwise, our ad-hoc equality + [==] and the generic [=] are in fact equivalent. We define [==] + nonetheless since the translation to [Z] for using automatic tactic is easier. *) + + Axiom i2z_eq : forall n p : int, n == p -> n = p. + + (** Then, we express the specifications of the above parameters using their + Z counterparts. *) + + Open Scope Z_scope. + Axiom i2z_0 : i2z _0 = 0. + Axiom i2z_1 : i2z _1 = 1. + Axiom i2z_2 : i2z _2 = 2. + Axiom i2z_3 : i2z _3 = 3. + Axiom i2z_plus : forall n p, i2z (n + p) = i2z n + i2z p. + Axiom i2z_opp : forall n, i2z (-n) = -i2z n. + Axiom i2z_minus : forall n p, i2z (n - p) = i2z n - i2z p. + Axiom i2z_mult : forall n p, i2z (n * p) = i2z n * i2z p. + Axiom i2z_max : forall n p, i2z (max n p) = Zmax (i2z n) (i2z p). End Int. -Module MoreInt (I:Int). - Import I. - Open Scope Int_scope. +(** * Facts and tactics using [Int] *) + +Module MoreInt (I:Int). + Import I. + + Open Scope Int_scope. - (** A magic (but costly) tactic that goes from [int] back to the [Z] - friendly world ... *) + (** A magic (but costly) tactic that goes from [int] back to the [Z] + friendly world ... *) - Hint Rewrite -> - i2z_0 i2z_1 i2z_2 i2z_3 i2z_plus i2z_opp i2z_minus i2z_mult i2z_max : i2z. + Hint Rewrite -> + i2z_0 i2z_1 i2z_2 i2z_3 i2z_plus i2z_opp i2z_minus i2z_mult i2z_max : i2z. - Ltac i2z := match goal with - | H : (eq (A:=int) ?a ?b) |- _ => - generalize (f_equal i2z H); - try autorewrite with i2z; clear H; intro H; i2z - | |- (eq (A:=int) ?a ?b) => apply (i2z_eq a b); try autorewrite with i2z; i2z - | H : _ |- _ => progress autorewrite with i2z in H; i2z - | _ => try autorewrite with i2z - end. + Ltac i2z := match goal with + | H : (eq (A:=int) ?a ?b) |- _ => + generalize (f_equal i2z H); + try autorewrite with i2z; clear H; intro H; i2z + | |- (eq (A:=int) ?a ?b) => apply (i2z_eq a b); try autorewrite with i2z; i2z + | H : _ |- _ => progress autorewrite with i2z in H; i2z + | _ => try autorewrite with i2z + end. - (** A reflexive version of the [i2z] tactic *) + (** A reflexive version of the [i2z] tactic *) - (** this [i2z_refl] is actually weaker than [i2z]. For instance, if a + (** this [i2z_refl] is actually weaker than [i2z]. For instance, if a [i2z] is buried deep inside a subterm, [i2z_refl] may miss it. See also the limitation about [Set] or [Type] part below. Anyhow, [i2z_refl] is enough for applying [romega]. *) @@ -150,228 +156,228 @@ Module MoreInt (I:Int). end. Inductive ExprI : Set := - | EI0 : ExprI - | EI1 : ExprI - | EI2 : ExprI - | EI3 : ExprI - | EIplus : ExprI -> ExprI -> ExprI - | EIopp : ExprI -> ExprI - | EIminus : ExprI -> ExprI -> ExprI - | EImult : ExprI -> ExprI -> ExprI - | EImax : ExprI -> ExprI -> ExprI - | EIraw : int -> ExprI. + | EI0 : ExprI + | EI1 : ExprI + | EI2 : ExprI + | EI3 : ExprI + | EIplus : ExprI -> ExprI -> ExprI + | EIopp : ExprI -> ExprI + | EIminus : ExprI -> ExprI -> ExprI + | EImult : ExprI -> ExprI -> ExprI + | EImax : ExprI -> ExprI -> ExprI + | EIraw : int -> ExprI. Inductive ExprZ : Set := - | EZplus : ExprZ -> ExprZ -> ExprZ - | EZopp : ExprZ -> ExprZ - | EZminus : ExprZ -> ExprZ -> ExprZ - | EZmult : ExprZ -> ExprZ -> ExprZ - | EZmax : ExprZ -> ExprZ -> ExprZ - | EZofI : ExprI -> ExprZ - | EZraw : Z -> ExprZ. + | EZplus : ExprZ -> ExprZ -> ExprZ + | EZopp : ExprZ -> ExprZ + | EZminus : ExprZ -> ExprZ -> ExprZ + | EZmult : ExprZ -> ExprZ -> ExprZ + | EZmax : ExprZ -> ExprZ -> ExprZ + | EZofI : ExprI -> ExprZ + | EZraw : Z -> ExprZ. Inductive ExprP : Type := - | EPeq : ExprZ -> ExprZ -> ExprP - | EPlt : ExprZ -> ExprZ -> ExprP - | EPle : ExprZ -> ExprZ -> ExprP - | EPgt : ExprZ -> ExprZ -> ExprP - | EPge : ExprZ -> ExprZ -> ExprP - | EPimpl : ExprP -> ExprP -> ExprP - | EPequiv : ExprP -> ExprP -> ExprP - | EPand : ExprP -> ExprP -> ExprP - | EPor : ExprP -> ExprP -> ExprP - | EPneg : ExprP -> ExprP - | EPraw : Prop -> ExprP. - - (** [int] to [ExprI] *) - - Ltac i2ei trm := - match constr:trm with - | 0 => constr:EI0 - | 1 => constr:EI1 - | 2 => constr:EI2 - | 3 => constr:EI3 - | ?x + ?y => let ex := i2ei x with ey := i2ei y in constr:(EIplus ex ey) - | ?x - ?y => let ex := i2ei x with ey := i2ei y in constr:(EIminus ex ey) - | ?x * ?y => let ex := i2ei x with ey := i2ei y in constr:(EImult ex ey) - | max ?x ?y => let ex := i2ei x with ey := i2ei y in constr:(EImax ex ey) - | - ?x => let ex := i2ei x in constr:(EIopp ex) - | ?x => constr:(EIraw x) - end - - (** [Z] to [ExprZ] *) - - with z2ez trm := - match constr:trm with - | (?x+?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EZplus ex ey) - | (?x-?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EZminus ex ey) - | (?x*?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EZmult ex ey) - | (Zmax ?x ?y) => let ex := z2ez x with ey := z2ez y in constr:(EZmax ex ey) - | (-?x)%Z => let ex := z2ez x in constr:(EZopp ex) - | i2z ?x => let ex := i2ei x in constr:(EZofI ex) - | ?x => constr:(EZraw x) - end. + | EPeq : ExprZ -> ExprZ -> ExprP + | EPlt : ExprZ -> ExprZ -> ExprP + | EPle : ExprZ -> ExprZ -> ExprP + | EPgt : ExprZ -> ExprZ -> ExprP + | EPge : ExprZ -> ExprZ -> ExprP + | EPimpl : ExprP -> ExprP -> ExprP + | EPequiv : ExprP -> ExprP -> ExprP + | EPand : ExprP -> ExprP -> ExprP + | EPor : ExprP -> ExprP -> ExprP + | EPneg : ExprP -> ExprP + | EPraw : Prop -> ExprP. + + (** [int] to [ExprI] *) + + Ltac i2ei trm := + match constr:trm with + | 0 => constr:EI0 + | 1 => constr:EI1 + | 2 => constr:EI2 + | 3 => constr:EI3 + | ?x + ?y => let ex := i2ei x with ey := i2ei y in constr:(EIplus ex ey) + | ?x - ?y => let ex := i2ei x with ey := i2ei y in constr:(EIminus ex ey) + | ?x * ?y => let ex := i2ei x with ey := i2ei y in constr:(EImult ex ey) + | max ?x ?y => let ex := i2ei x with ey := i2ei y in constr:(EImax ex ey) + | - ?x => let ex := i2ei x in constr:(EIopp ex) + | ?x => constr:(EIraw x) + end + + (** [Z] to [ExprZ] *) + + with z2ez trm := + match constr:trm with + | (?x+?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EZplus ex ey) + | (?x-?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EZminus ex ey) + | (?x*?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EZmult ex ey) + | (Zmax ?x ?y) => let ex := z2ez x with ey := z2ez y in constr:(EZmax ex ey) + | (-?x)%Z => let ex := z2ez x in constr:(EZopp ex) + | i2z ?x => let ex := i2ei x in constr:(EZofI ex) + | ?x => constr:(EZraw x) + end. - (** [Prop] to [ExprP] *) - - Ltac p2ep trm := - match constr:trm with - | (?x <-> ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPequiv ex ey) - | (?x -> ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPimpl ex ey) - | (?x /\ ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPand ex ey) - | (?x \/ ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPor ex ey) - | (~ ?x) => let ex := p2ep x in constr:(EPneg ex) - | (eq (A:=Z) ?x ?y) => let ex := z2ez x with ey := z2ez y in constr:(EPeq ex ey) - | (?x let ex := z2ez x with ey := z2ez y in constr:(EPlt ex ey) - | (?x<=?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EPle ex ey) - | (?x>?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EPgt ex ey) - | (?x>=?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EPge ex ey) - | ?x => constr:(EPraw x) - end. - - (** [ExprI] to [int] *) - - Fixpoint ei2i (e:ExprI) : int := - match e with - | EI0 => 0 - | EI1 => 1 - | EI2 => 2 - | EI3 => 3 - | EIplus e1 e2 => (ei2i e1)+(ei2i e2) - | EIminus e1 e2 => (ei2i e1)-(ei2i e2) - | EImult e1 e2 => (ei2i e1)*(ei2i e2) - | EImax e1 e2 => max (ei2i e1) (ei2i e2) - | EIopp e => -(ei2i e) - | EIraw i => i - end. - - (** [ExprZ] to [Z] *) - - Fixpoint ez2z (e:ExprZ) : Z := - match e with - | EZplus e1 e2 => ((ez2z e1)+(ez2z e2))%Z - | EZminus e1 e2 => ((ez2z e1)-(ez2z e2))%Z - | EZmult e1 e2 => ((ez2z e1)*(ez2z e2))%Z - | EZmax e1 e2 => Zmax (ez2z e1) (ez2z e2) - | EZopp e => (-(ez2z e))%Z - | EZofI e => i2z (ei2i e) - | EZraw z => z - end. - - (** [ExprP] to [Prop] *) - - Fixpoint ep2p (e:ExprP) : Prop := - match e with - | EPeq e1 e2 => (ez2z e1) = (ez2z e2) - | EPlt e1 e2 => ((ez2z e1)<(ez2z e2))%Z - | EPle e1 e2 => ((ez2z e1)<=(ez2z e2))%Z - | EPgt e1 e2 => ((ez2z e1)>(ez2z e2))%Z - | EPge e1 e2 => ((ez2z e1)>=(ez2z e2))%Z - | EPimpl e1 e2 => (ep2p e1) -> (ep2p e2) - | EPequiv e1 e2 => (ep2p e1) <-> (ep2p e2) - | EPand e1 e2 => (ep2p e1) /\ (ep2p e2) - | EPor e1 e2 => (ep2p e1) \/ (ep2p e2) - | EPneg e => ~ (ep2p e) - | EPraw p => p - end. - - (** [ExprI] (supposed under a [i2z]) to a simplified [ExprZ] *) + (** [Prop] to [ExprP] *) + + Ltac p2ep trm := + match constr:trm with + | (?x <-> ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPequiv ex ey) + | (?x -> ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPimpl ex ey) + | (?x /\ ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPand ex ey) + | (?x \/ ?y) => let ex := p2ep x with ey := p2ep y in constr:(EPor ex ey) + | (~ ?x) => let ex := p2ep x in constr:(EPneg ex) + | (eq (A:=Z) ?x ?y) => let ex := z2ez x with ey := z2ez y in constr:(EPeq ex ey) + | (?x let ex := z2ez x with ey := z2ez y in constr:(EPlt ex ey) + | (?x<=?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EPle ex ey) + | (?x>?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EPgt ex ey) + | (?x>=?y)%Z => let ex := z2ez x with ey := z2ez y in constr:(EPge ex ey) + | ?x => constr:(EPraw x) + end. + + (** [ExprI] to [int] *) + + Fixpoint ei2i (e:ExprI) : int := + match e with + | EI0 => 0 + | EI1 => 1 + | EI2 => 2 + | EI3 => 3 + | EIplus e1 e2 => (ei2i e1)+(ei2i e2) + | EIminus e1 e2 => (ei2i e1)-(ei2i e2) + | EImult e1 e2 => (ei2i e1)*(ei2i e2) + | EImax e1 e2 => max (ei2i e1) (ei2i e2) + | EIopp e => -(ei2i e) + | EIraw i => i + end. + + (** [ExprZ] to [Z] *) + + Fixpoint ez2z (e:ExprZ) : Z := + match e with + | EZplus e1 e2 => ((ez2z e1)+(ez2z e2))%Z + | EZminus e1 e2 => ((ez2z e1)-(ez2z e2))%Z + | EZmult e1 e2 => ((ez2z e1)*(ez2z e2))%Z + | EZmax e1 e2 => Zmax (ez2z e1) (ez2z e2) + | EZopp e => (-(ez2z e))%Z + | EZofI e => i2z (ei2i e) + | EZraw z => z + end. + + (** [ExprP] to [Prop] *) + + Fixpoint ep2p (e:ExprP) : Prop := + match e with + | EPeq e1 e2 => (ez2z e1) = (ez2z e2) + | EPlt e1 e2 => ((ez2z e1)<(ez2z e2))%Z + | EPle e1 e2 => ((ez2z e1)<=(ez2z e2))%Z + | EPgt e1 e2 => ((ez2z e1)>(ez2z e2))%Z + | EPge e1 e2 => ((ez2z e1)>=(ez2z e2))%Z + | EPimpl e1 e2 => (ep2p e1) -> (ep2p e2) + | EPequiv e1 e2 => (ep2p e1) <-> (ep2p e2) + | EPand e1 e2 => (ep2p e1) /\ (ep2p e2) + | EPor e1 e2 => (ep2p e1) \/ (ep2p e2) + | EPneg e => ~ (ep2p e) + | EPraw p => p + end. + + (** [ExprI] (supposed under a [i2z]) to a simplified [ExprZ] *) - Fixpoint norm_ei (e:ExprI) : ExprZ := - match e with - | EI0 => EZraw (0%Z) - | EI1 => EZraw (1%Z) - | EI2 => EZraw (2%Z) - | EI3 => EZraw (3%Z) - | EIplus e1 e2 => EZplus (norm_ei e1) (norm_ei e2) - | EIminus e1 e2 => EZminus (norm_ei e1) (norm_ei e2) - | EImult e1 e2 => EZmult (norm_ei e1) (norm_ei e2) - | EImax e1 e2 => EZmax (norm_ei e1) (norm_ei e2) - | EIopp e => EZopp (norm_ei e) - | EIraw i => EZofI (EIraw i) - end. - - (** [ExprZ] to a simplified [ExprZ] *) - - Fixpoint norm_ez (e:ExprZ) : ExprZ := - match e with - | EZplus e1 e2 => EZplus (norm_ez e1) (norm_ez e2) - | EZminus e1 e2 => EZminus (norm_ez e1) (norm_ez e2) - | EZmult e1 e2 => EZmult (norm_ez e1) (norm_ez e2) - | EZmax e1 e2 => EZmax (norm_ez e1) (norm_ez e2) - | EZopp e => EZopp (norm_ez e) - | EZofI e => norm_ei e - | EZraw z => EZraw z - end. - - (** [ExprP] to a simplified [ExprP] *) - - Fixpoint norm_ep (e:ExprP) : ExprP := - match e with - | EPeq e1 e2 => EPeq (norm_ez e1) (norm_ez e2) - | EPlt e1 e2 => EPlt (norm_ez e1) (norm_ez e2) - | EPle e1 e2 => EPle (norm_ez e1) (norm_ez e2) - | EPgt e1 e2 => EPgt (norm_ez e1) (norm_ez e2) - | EPge e1 e2 => EPge (norm_ez e1) (norm_ez e2) - | EPimpl e1 e2 => EPimpl (norm_ep e1) (norm_ep e2) - | EPequiv e1 e2 => EPequiv (norm_ep e1) (norm_ep e2) - | EPand e1 e2 => EPand (norm_ep e1) (norm_ep e2) - | EPor e1 e2 => EPor (norm_ep e1) (norm_ep e2) - | EPneg e => EPneg (norm_ep e) - | EPraw p => EPraw p - end. - - Lemma norm_ei_correct : forall e:ExprI, ez2z (norm_ei e) = i2z (ei2i e). - Proof. - induction e; simpl; intros; i2z; auto; try congruence. - Qed. - - Lemma norm_ez_correct : forall e:ExprZ, ez2z (norm_ez e) = ez2z e. - Proof. - induction e; simpl; intros; i2z; auto; try congruence; apply norm_ei_correct. - Qed. - - Lemma norm_ep_correct : - forall e:ExprP, ep2p (norm_ep e) <-> ep2p e. - Proof. - induction e; simpl; repeat (rewrite norm_ez_correct); intuition. - Qed. - - Lemma norm_ep_correct2 : - forall e:ExprP, ep2p (norm_ep e) -> ep2p e. - Proof. - intros; destruct (norm_ep_correct e); auto. - Qed. - - Ltac i2z_refl := - i2z_gen; - match goal with |- ?t => - let e := p2ep t - in - (change (ep2p e); - apply norm_ep_correct2; - simpl) - end. + Fixpoint norm_ei (e:ExprI) : ExprZ := + match e with + | EI0 => EZraw (0%Z) + | EI1 => EZraw (1%Z) + | EI2 => EZraw (2%Z) + | EI3 => EZraw (3%Z) + | EIplus e1 e2 => EZplus (norm_ei e1) (norm_ei e2) + | EIminus e1 e2 => EZminus (norm_ei e1) (norm_ei e2) + | EImult e1 e2 => EZmult (norm_ei e1) (norm_ei e2) + | EImax e1 e2 => EZmax (norm_ei e1) (norm_ei e2) + | EIopp e => EZopp (norm_ei e) + | EIraw i => EZofI (EIraw i) + end. + + (** [ExprZ] to a simplified [ExprZ] *) + + Fixpoint norm_ez (e:ExprZ) : ExprZ := + match e with + | EZplus e1 e2 => EZplus (norm_ez e1) (norm_ez e2) + | EZminus e1 e2 => EZminus (norm_ez e1) (norm_ez e2) + | EZmult e1 e2 => EZmult (norm_ez e1) (norm_ez e2) + | EZmax e1 e2 => EZmax (norm_ez e1) (norm_ez e2) + | EZopp e => EZopp (norm_ez e) + | EZofI e => norm_ei e + | EZraw z => EZraw z + end. + + (** [ExprP] to a simplified [ExprP] *) + + Fixpoint norm_ep (e:ExprP) : ExprP := + match e with + | EPeq e1 e2 => EPeq (norm_ez e1) (norm_ez e2) + | EPlt e1 e2 => EPlt (norm_ez e1) (norm_ez e2) + | EPle e1 e2 => EPle (norm_ez e1) (norm_ez e2) + | EPgt e1 e2 => EPgt (norm_ez e1) (norm_ez e2) + | EPge e1 e2 => EPge (norm_ez e1) (norm_ez e2) + | EPimpl e1 e2 => EPimpl (norm_ep e1) (norm_ep e2) + | EPequiv e1 e2 => EPequiv (norm_ep e1) (norm_ep e2) + | EPand e1 e2 => EPand (norm_ep e1) (norm_ep e2) + | EPor e1 e2 => EPor (norm_ep e1) (norm_ep e2) + | EPneg e => EPneg (norm_ep e) + | EPraw p => EPraw p + end. + + Lemma norm_ei_correct : forall e:ExprI, ez2z (norm_ei e) = i2z (ei2i e). + Proof. + induction e; simpl; intros; i2z; auto; try congruence. + Qed. + + Lemma norm_ez_correct : forall e:ExprZ, ez2z (norm_ez e) = ez2z e. + Proof. + induction e; simpl; intros; i2z; auto; try congruence; apply norm_ei_correct. + Qed. + + Lemma norm_ep_correct : + forall e:ExprP, ep2p (norm_ep e) <-> ep2p e. + Proof. + induction e; simpl; repeat (rewrite norm_ez_correct); intuition. + Qed. + + Lemma norm_ep_correct2 : + forall e:ExprP, ep2p (norm_ep e) -> ep2p e. + Proof. + intros; destruct (norm_ep_correct e); auto. + Qed. + + Ltac i2z_refl := + i2z_gen; + match goal with |- ?t => + let e := p2ep t + in + (change (ep2p e); + apply norm_ep_correct2; + simpl) + end. - Ltac iauto := i2z_refl; auto. - Ltac iomega := i2z_refl; intros; romega. + Ltac iauto := i2z_refl; auto. + Ltac iomega := i2z_refl; intros; romega. - Open Scope Z_scope. + Open Scope Z_scope. - Lemma max_spec : forall (x y:Z), - x >= y /\ Zmax x y = x \/ - x < y /\ Zmax x y = y. - Proof. - intros; unfold Zmax, Zlt, Zge. - destruct (Zcompare x y); [ left | right | left ]; split; auto; discriminate. - Qed. + Lemma max_spec : forall (x y:Z), + x >= y /\ Zmax x y = x \/ + x < y /\ Zmax x y = y. + Proof. + intros; unfold Zmax, Zlt, Zge. + destruct (Zcompare x y); [ left | right | left ]; split; auto; discriminate. + Qed. - Ltac omega_max_genspec x y := + Ltac omega_max_genspec x y := generalize (max_spec x y); - let z := fresh "z" in let Hz := fresh "Hz" in - (set (z:=Zmax x y); clearbody z). + (let z := fresh "z" in let Hz := fresh "Hz" in + set (z:=Zmax x y); clearbody z). - Ltac omega_max_loop := + Ltac omega_max_loop := match goal with (* hack: we don't want [i2z (height ...)] to be reduced by romega later... *) | |- context [ i2z (?f ?x) ] => @@ -380,42 +386,45 @@ Module MoreInt (I:Int). | _ => intros end. - Ltac omega_max := i2z_refl; omega_max_loop; try romega. + Ltac omega_max := i2z_refl; omega_max_loop; try romega. + + Ltac false_omega := i2z_refl; intros; romega. + Ltac false_omega_max := elimtype False; omega_max. - Ltac false_omega := i2z_refl; intros; romega. - Ltac false_omega_max := elimtype False; omega_max. - - Open Scope Int_scope. + Open Scope Int_scope. End MoreInt. + +(** * An implementation of [Int] *) + (** It's always nice to know that our [Int] interface is realizable :-) *) Module Z_as_Int <: Int. - Open Scope Z_scope. - Definition int := Z. - Definition _0 := 0. - Definition _1 := 1. - Definition _2 := 2. - Definition _3 := 3. - Definition plus := Zplus. - Definition opp := Zopp. - Definition minus := Zminus. - Definition mult := Zmult. - Definition max := Zmax. - Definition gt_le_dec := Z_gt_le_dec. - Definition ge_lt_dec := Z_ge_lt_dec. - Definition eq_dec := Z_eq_dec. - Definition i2z : int -> Z := fun n => n. - Lemma i2z_eq : forall n p, i2z n=i2z p -> n = p. Proof. auto. Qed. - Lemma i2z_0 : i2z _0 = 0. Proof. auto. Qed. - Lemma i2z_1 : i2z _1 = 1. Proof. auto. Qed. - Lemma i2z_2 : i2z _2 = 2. Proof. auto. Qed. - Lemma i2z_3 : i2z _3 = 3. Proof. auto. Qed. - Lemma i2z_plus : forall n p, i2z (n + p) = i2z n + i2z p. Proof. auto. Qed. - Lemma i2z_opp : forall n, i2z (- n) = - i2z n. Proof. auto. Qed. - Lemma i2z_minus : forall n p, i2z (n - p) = i2z n - i2z p. Proof. auto. Qed. - Lemma i2z_mult : forall n p, i2z (n * p) = i2z n * i2z p. Proof. auto. Qed. - Lemma i2z_max : forall n p, i2z (max n p) = Zmax (i2z n) (i2z p). Proof. auto. Qed. + Open Scope Z_scope. + Definition int := Z. + Definition _0 := 0. + Definition _1 := 1. + Definition _2 := 2. + Definition _3 := 3. + Definition plus := Zplus. + Definition opp := Zopp. + Definition minus := Zminus. + Definition mult := Zmult. + Definition max := Zmax. + Definition gt_le_dec := Z_gt_le_dec. + Definition ge_lt_dec := Z_ge_lt_dec. + Definition eq_dec := Z_eq_dec. + Definition i2z : int -> Z := fun n => n. + Lemma i2z_eq : forall n p, i2z n=i2z p -> n = p. Proof. auto. Qed. + Lemma i2z_0 : i2z _0 = 0. Proof. auto. Qed. + Lemma i2z_1 : i2z _1 = 1. Proof. auto. Qed. + Lemma i2z_2 : i2z _2 = 2. Proof. auto. Qed. + Lemma i2z_3 : i2z _3 = 3. Proof. auto. Qed. + Lemma i2z_plus : forall n p, i2z (n + p) = i2z n + i2z p. Proof. auto. Qed. + Lemma i2z_opp : forall n, i2z (- n) = - i2z n. Proof. auto. Qed. + Lemma i2z_minus : forall n p, i2z (n - p) = i2z n - i2z p. Proof. auto. Qed. + Lemma i2z_mult : forall n p, i2z (n * p) = i2z n * i2z p. Proof. auto. Qed. + Lemma i2z_max : forall n p, i2z (max n p) = Zmax (i2z n) (i2z p). Proof. auto. Qed. End Z_as_Int. diff --git a/theories/ZArith/Wf_Z.v b/theories/ZArith/Wf_Z.v index af1fdd0b..1d7948a5 100644 --- a/theories/ZArith/Wf_Z.v +++ b/theories/ZArith/Wf_Z.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Wf_Z.v 6984 2005-05-02 10:50:15Z herbelin $ i*) +(*i $Id: Wf_Z.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import BinInt. Require Import Zcompare. @@ -35,222 +35,229 @@ Open Local Scope Z_scope. Then the diagram will be closed and the theorem proved. *) Lemma Z_of_nat_complete : - forall x:Z, 0 <= x -> exists n : nat, x = Z_of_nat n. -intro x; destruct x; intros; - [ exists 0%nat; auto with arith - | specialize (ZL4 p); intros Hp; elim Hp; intros; exists (S x); intros; - simpl in |- *; specialize (nat_of_P_o_P_of_succ_nat_eq_succ x); - intro Hx0; rewrite <- H0 in Hx0; apply f_equal with (f := Zpos); - apply nat_of_P_inj; auto with arith - | absurd (0 <= Zneg p); - [ unfold Zle in |- *; simpl in |- *; do 2 unfold not in |- *; - auto with arith - | assumption ] ]. + forall x:Z, 0 <= x -> exists n : nat, x = Z_of_nat n. +Proof. + intro x; destruct x; intros; + [ exists 0%nat; auto with arith + | specialize (ZL4 p); intros Hp; elim Hp; intros; exists (S x); intros; + simpl in |- *; specialize (nat_of_P_o_P_of_succ_nat_eq_succ x); + intro Hx0; rewrite <- H0 in Hx0; apply f_equal with (f := Zpos); + apply nat_of_P_inj; auto with arith + | absurd (0 <= Zneg p); + [ unfold Zle in |- *; simpl in |- *; do 2 unfold not in |- *; + auto with arith + | assumption ] ]. Qed. Lemma ZL4_inf : forall y:positive, {h : nat | nat_of_P y = S h}. -intro y; induction y as [p H| p H1| ]; - [ elim H; intros x H1; exists (S x + S x)%nat; unfold nat_of_P in |- *; - simpl in |- *; rewrite ZL0; rewrite Pmult_nat_r_plus_morphism; - unfold nat_of_P in H1; rewrite H1; auto with arith - | elim H1; intros x H2; exists (x + S x)%nat; unfold nat_of_P in |- *; - simpl in |- *; rewrite ZL0; rewrite Pmult_nat_r_plus_morphism; - unfold nat_of_P in H2; rewrite H2; auto with arith - | exists 0%nat; auto with arith ]. +Proof. + intro y; induction y as [p H| p H1| ]; + [ elim H; intros x H1; exists (S x + S x)%nat; unfold nat_of_P in |- *; + simpl in |- *; rewrite ZL0; rewrite Pmult_nat_r_plus_morphism; + unfold nat_of_P in H1; rewrite H1; auto with arith + | elim H1; intros x H2; exists (x + S x)%nat; unfold nat_of_P in |- *; + simpl in |- *; rewrite ZL0; rewrite Pmult_nat_r_plus_morphism; + unfold nat_of_P in H2; rewrite H2; auto with arith + | exists 0%nat; auto with arith ]. Qed. Lemma Z_of_nat_complete_inf : forall x:Z, 0 <= x -> {n : nat | x = Z_of_nat n}. -intro x; destruct x; intros; - [ exists 0%nat; auto with arith - | specialize (ZL4_inf p); intros Hp; elim Hp; intros x0 H0; exists (S x0); - intros; simpl in |- *; specialize (nat_of_P_o_P_of_succ_nat_eq_succ x0); - intro Hx0; rewrite <- H0 in Hx0; apply f_equal with (f := Zpos); - apply nat_of_P_inj; auto with arith - | absurd (0 <= Zneg p); - [ unfold Zle in |- *; simpl in |- *; do 2 unfold not in |- *; - auto with arith - | assumption ] ]. +Proof. + intro x; destruct x; intros; + [ exists 0%nat; auto with arith + | specialize (ZL4_inf p); intros Hp; elim Hp; intros x0 H0; exists (S x0); + intros; simpl in |- *; specialize (nat_of_P_o_P_of_succ_nat_eq_succ x0); + intro Hx0; rewrite <- H0 in Hx0; apply f_equal with (f := Zpos); + apply nat_of_P_inj; auto with arith + | absurd (0 <= Zneg p); + [ unfold Zle in |- *; simpl in |- *; do 2 unfold not in |- *; + auto with arith + | assumption ] ]. Qed. Lemma Z_of_nat_prop : - forall P:Z -> Prop, - (forall n:nat, P (Z_of_nat n)) -> forall x:Z, 0 <= x -> P x. -intros P H x H0. -specialize (Z_of_nat_complete x H0). -intros Hn; elim Hn; intros. -rewrite H1; apply H. + forall P:Z -> Prop, + (forall n:nat, P (Z_of_nat n)) -> forall x:Z, 0 <= x -> P x. +Proof. + intros P H x H0. + specialize (Z_of_nat_complete x H0). + intros Hn; elim Hn; intros. + rewrite H1; apply H. Qed. Lemma Z_of_nat_set : forall P:Z -> Set, (forall n:nat, P (Z_of_nat n)) -> forall x:Z, 0 <= x -> P x. -intros P H x H0. -specialize (Z_of_nat_complete_inf x H0). -intros Hn; elim Hn; intros. -rewrite p; apply H. +Proof. + intros P H x H0. + specialize (Z_of_nat_complete_inf x H0). + intros Hn; elim Hn; intros. + rewrite p; apply H. Qed. Lemma natlike_ind : forall P:Z -> Prop, P 0 -> (forall x:Z, 0 <= x -> P x -> P (Zsucc x)) -> forall x:Z, 0 <= x -> P x. -intros P H H0 x H1; apply Z_of_nat_prop; - [ simple induction n; - [ simpl in |- *; assumption - | intros; rewrite (inj_S n0); exact (H0 (Z_of_nat n0) (Zle_0_nat n0) H2) ] - | assumption ]. +Proof. + intros P H H0 x H1; apply Z_of_nat_prop; + [ simple induction n; + [ simpl in |- *; assumption + | intros; rewrite (inj_S n0); exact (H0 (Z_of_nat n0) (Zle_0_nat n0) H2) ] + | assumption ]. Qed. Lemma natlike_rec : forall P:Z -> Set, P 0 -> (forall x:Z, 0 <= x -> P x -> P (Zsucc x)) -> forall x:Z, 0 <= x -> P x. -intros P H H0 x H1; apply Z_of_nat_set; - [ simple induction n; - [ simpl in |- *; assumption - | intros; rewrite (inj_S n0); exact (H0 (Z_of_nat n0) (Zle_0_nat n0) H2) ] - | assumption ]. +Proof. + intros P H H0 x H1; apply Z_of_nat_set; + [ simple induction n; + [ simpl in |- *; assumption + | intros; rewrite (inj_S n0); exact (H0 (Z_of_nat n0) (Zle_0_nat n0) H2) ] + | assumption ]. Qed. Section Efficient_Rec. -(** [natlike_rec2] is the same as [natlike_rec], but with a different proof, designed - to give a better extracted term. *) + (** [natlike_rec2] is the same as [natlike_rec], but with a different proof, designed + to give a better extracted term. *) -Let R (a b:Z) := 0 <= a /\ a < b. + Let R (a b:Z) := 0 <= a /\ a < b. + + Let R_wf : well_founded R. + Proof. + set + (f := + fun z => + match z with + | Zpos p => nat_of_P p + | Z0 => 0%nat + | Zneg _ => 0%nat + end) in *. + apply well_founded_lt_compat with f. + unfold R, f in |- *; clear f R. + intros x y; case x; intros; elim H; clear H. + case y; intros; apply lt_O_nat_of_P || inversion H0. + case y; intros; apply nat_of_P_lt_Lt_compare_morphism || inversion H0; auto. + intros; elim H; auto. + Qed. -Let R_wf : well_founded R. -Proof. -set - (f := - fun z => - match z with - | Zpos p => nat_of_P p - | Z0 => 0%nat - | Zneg _ => 0%nat - end) in *. -apply well_founded_lt_compat with f. -unfold R, f in |- *; clear f R. -intros x y; case x; intros; elim H; clear H. -case y; intros; apply lt_O_nat_of_P || inversion H0. -case y; intros; apply nat_of_P_lt_Lt_compare_morphism || inversion H0; auto. -intros; elim H; auto. -Qed. + Lemma natlike_rec2 : + forall P:Z -> Type, + P 0 -> + (forall z:Z, 0 <= z -> P z -> P (Zsucc z)) -> forall z:Z, 0 <= z -> P z. + Proof. + intros P Ho Hrec z; pattern z in |- *; + apply (well_founded_induction_type R_wf). + intro x; case x. + trivial. + intros. + assert (0 <= Zpred (Zpos p)). + apply Zorder.Zlt_0_le_0_pred; unfold Zlt in |- *; simpl in |- *; trivial. + rewrite Zsucc_pred. + apply Hrec. + auto. + apply X; auto; unfold R in |- *; intuition; apply Zlt_pred. + intros; elim H; simpl in |- *; trivial. + Qed. -Lemma natlike_rec2 : - forall P:Z -> Type, - P 0 -> - (forall z:Z, 0 <= z -> P z -> P (Zsucc z)) -> forall z:Z, 0 <= z -> P z. -Proof. -intros P Ho Hrec z; pattern z in |- *; - apply (well_founded_induction_type R_wf). -intro x; case x. -trivial. -intros. -assert (0 <= Zpred (Zpos p)). -apply Zorder.Zlt_0_le_0_pred; unfold Zlt in |- *; simpl in |- *; trivial. -rewrite Zsucc_pred. -apply Hrec. -auto. -apply X; auto; unfold R in |- *; intuition; apply Zlt_pred. -intros; elim H; simpl in |- *; trivial. -Qed. + (** A variant of the previous using [Zpred] instead of [Zs]. *) -(** A variant of the previous using [Zpred] instead of [Zs]. *) + Lemma natlike_rec3 : + forall P:Z -> Type, + P 0 -> + (forall z:Z, 0 < z -> P (Zpred z) -> P z) -> forall z:Z, 0 <= z -> P z. + Proof. + intros P Ho Hrec z; pattern z in |- *; + apply (well_founded_induction_type R_wf). + intro x; case x. + trivial. + intros; apply Hrec. + unfold Zlt in |- *; trivial. + assert (0 <= Zpred (Zpos p)). + apply Zorder.Zlt_0_le_0_pred; unfold Zlt in |- *; simpl in |- *; trivial. + apply X; auto; unfold R in |- *; intuition; apply Zlt_pred. + intros; elim H; simpl in |- *; trivial. + Qed. -Lemma natlike_rec3 : - forall P:Z -> Type, - P 0 -> - (forall z:Z, 0 < z -> P (Zpred z) -> P z) -> forall z:Z, 0 <= z -> P z. -Proof. -intros P Ho Hrec z; pattern z in |- *; - apply (well_founded_induction_type R_wf). -intro x; case x. -trivial. -intros; apply Hrec. -unfold Zlt in |- *; trivial. -assert (0 <= Zpred (Zpos p)). -apply Zorder.Zlt_0_le_0_pred; unfold Zlt in |- *; simpl in |- *; trivial. -apply X; auto; unfold R in |- *; intuition; apply Zlt_pred. -intros; elim H; simpl in |- *; trivial. -Qed. + (** A more general induction principle on non-negative numbers using [Zlt]. *) -(** A more general induction principle on non-negative numbers using [Zlt]. *) + Lemma Zlt_0_rec : + forall P:Z -> Type, + (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> 0 <= x -> P x) -> + forall x:Z, 0 <= x -> P x. + Proof. + intros P Hrec z; pattern z in |- *; apply (well_founded_induction_type R_wf). + intro x; case x; intros. + apply Hrec; intros. + assert (H2 : 0 < 0). + apply Zle_lt_trans with y; intuition. + inversion H2. + assumption. + firstorder. + unfold Zle, Zcompare in H; elim H; auto. + Defined. -Lemma Zlt_0_rec : - forall P:Z -> Type, - (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> 0 <= x -> P x) -> - forall x:Z, 0 <= x -> P x. -Proof. -intros P Hrec z; pattern z in |- *; apply (well_founded_induction_type R_wf). -intro x; case x; intros. -apply Hrec; intros. -assert (H2 : 0 < 0). - apply Zle_lt_trans with y; intuition. -inversion H2. -assumption. -firstorder. -unfold Zle, Zcompare in H; elim H; auto. -Defined. + Lemma Zlt_0_ind : + forall P:Z -> Prop, + (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> 0 <= x -> P x) -> + forall x:Z, 0 <= x -> P x. + Proof. + exact Zlt_0_rec. + Qed. -Lemma Zlt_0_ind : - forall P:Z -> Prop, - (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> 0 <= x -> P x) -> - forall x:Z, 0 <= x -> P x. -Proof. -exact Zlt_0_rec. -Qed. + (** Obsolete version of [Zlt] induction principle on non-negative numbers *) -(** Obsolete version of [Zlt] induction principle on non-negative numbers *) + Lemma Z_lt_rec : + forall P:Z -> Type, + (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> P x) -> + forall x:Z, 0 <= x -> P x. + Proof. + intros P Hrec; apply Zlt_0_rec; auto. + Qed. -Lemma Z_lt_rec : - forall P:Z -> Type, - (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> P x) -> - forall x:Z, 0 <= x -> P x. -Proof. -intros P Hrec; apply Zlt_0_rec; auto. -Qed. + Lemma Z_lt_induction : + forall P:Z -> Prop, + (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> P x) -> + forall x:Z, 0 <= x -> P x. + Proof. + exact Z_lt_rec. + Qed. -Lemma Z_lt_induction : - forall P:Z -> Prop, - (forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> P x) -> - forall x:Z, 0 <= x -> P x. -Proof. -exact Z_lt_rec. -Qed. + (** An even more general induction principle using [Zlt]. *) -(** An even more general induction principle using [Zlt]. *) + Lemma Zlt_lower_bound_rec : + forall P:Z -> Type, forall z:Z, + (forall x:Z, (forall y:Z, z <= y < x -> P y) -> z <= x -> P x) -> + forall x:Z, z <= x -> P x. + Proof. + intros P z Hrec x. + assert (Hexpand : forall x, x = x - z + z). + intro; unfold Zminus; rewrite <- Zplus_assoc; rewrite Zplus_opp_l; + rewrite Zplus_0_r; trivial. + intro Hz. + rewrite (Hexpand x); pattern (x - z) in |- *; apply Zlt_0_rec. + 2: apply Zplus_le_reg_r with z; rewrite <- Hexpand; assumption. + intros x0 Hlt_x0 H. + apply Hrec. + 2: change z with (0+z); apply Zplus_le_compat_r; assumption. + intro y; rewrite (Hexpand y); intros. + destruct H0. + apply Hlt_x0. + split. + apply Zplus_le_reg_r with z; assumption. + apply Zplus_lt_reg_r with z; assumption. + Qed. -Lemma Zlt_lower_bound_rec : - forall P:Z -> Type, forall z:Z, - (forall x:Z, (forall y:Z, z <= y < x -> P y) -> z <= x -> P x) -> - forall x:Z, z <= x -> P x. -Proof. -intros P z Hrec x. -assert (Hexpand : forall x, x = x - z + z). - intro; unfold Zminus; rewrite <- Zplus_assoc; rewrite Zplus_opp_l; - rewrite Zplus_0_r; trivial. -intro Hz. -rewrite (Hexpand x); pattern (x - z) in |- *; apply Zlt_0_rec. -2: apply Zplus_le_reg_r with z; rewrite <- Hexpand; assumption. -intros x0 Hlt_x0 H. -apply Hrec. - 2: change z with (0+z); apply Zplus_le_compat_r; assumption. - intro y; rewrite (Hexpand y); intros. -destruct H0. -apply Hlt_x0. -split. - apply Zplus_le_reg_r with z; assumption. - apply Zplus_lt_reg_r with z; assumption. -Qed. - -Lemma Zlt_lower_bound_ind : - forall P:Z -> Prop, forall z:Z, - (forall x:Z, (forall y:Z, z <= y < x -> P y) -> z <= x -> P x) -> - forall x:Z, z <= x -> P x. -Proof. -exact Zlt_lower_bound_rec. -Qed. + Lemma Zlt_lower_bound_ind : + forall P:Z -> Prop, forall z:Z, + (forall x:Z, (forall y:Z, z <= y < x -> P y) -> z <= x -> P x) -> + forall x:Z, z <= x -> P x. + Proof. + exact Zlt_lower_bound_rec. + Qed. End Efficient_Rec. diff --git a/theories/ZArith/ZArith.v b/theories/ZArith/ZArith.v index 45749fa3..66e0bda8 100644 --- a/theories/ZArith/ZArith.v +++ b/theories/ZArith/ZArith.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ZArith.v 6013 2004-08-03 17:56:19Z herbelin $ i*) +(*i $Id: ZArith.v 9210 2006-10-05 10:12:15Z barras $ i*) (** Library for manipulating integers based on binary encoding *) @@ -19,3 +19,5 @@ Require Export Zsqrt. Require Export Zpower. Require Export Zdiv. Require Export Zlogarithm. + +Export ZArithRing. diff --git a/theories/ZArith/ZArith_dec.v b/theories/ZArith/ZArith_dec.v index 40c5860c..84249955 100644 --- a/theories/ZArith/ZArith_dec.v +++ b/theories/ZArith/ZArith_dec.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ZArith_dec.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: ZArith_dec.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import Sumbool. @@ -17,210 +17,210 @@ Open Local Scope Z_scope. Lemma Dcompare_inf : forall r:comparison, {r = Eq} + {r = Lt} + {r = Gt}. Proof. -simple induction r; auto with arith. + simple induction r; auto with arith. Defined. Lemma Zcompare_rec : - forall (P:Set) (n m:Z), - ((n ?= m) = Eq -> P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P. + forall (P:Set) (n m:Z), + ((n ?= m) = Eq -> P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P. Proof. -intros P x y H1 H2 H3. -elim (Dcompare_inf (x ?= y)). -intro H. elim H; auto with arith. auto with arith. + intros P x y H1 H2 H3. + elim (Dcompare_inf (x ?= y)). + intro H. elim H; auto with arith. auto with arith. Defined. Section decidability. -Variables x y : Z. - -(** Decidability of equality on binary integers *) - -Definition Z_eq_dec : {x = y} + {x <> y}. -Proof. -apply Zcompare_rec with (n := x) (m := y). -intro. left. elim (Zcompare_Eq_iff_eq x y); auto with arith. -intro H3. right. elim (Zcompare_Eq_iff_eq x y). intros H1 H2. unfold not in |- *. intro H4. - rewrite (H2 H4) in H3. discriminate H3. -intro H3. right. elim (Zcompare_Eq_iff_eq x y). intros H1 H2. unfold not in |- *. intro H4. - rewrite (H2 H4) in H3. discriminate H3. -Defined. - -(** Decidability of order on binary integers *) - -Definition Z_lt_dec : {x < y} + {~ x < y}. -Proof. -unfold Zlt in |- *. -apply Zcompare_rec with (n := x) (m := y); intro H. -right. rewrite H. discriminate. -left; assumption. -right. rewrite H. discriminate. -Defined. - -Definition Z_le_dec : {x <= y} + {~ x <= y}. -Proof. -unfold Zle in |- *. -apply Zcompare_rec with (n := x) (m := y); intro H. -left. rewrite H. discriminate. -left. rewrite H. discriminate. -right. tauto. -Defined. - -Definition Z_gt_dec : {x > y} + {~ x > y}. -Proof. -unfold Zgt in |- *. -apply Zcompare_rec with (n := x) (m := y); intro H. -right. rewrite H. discriminate. -right. rewrite H. discriminate. -left; assumption. -Defined. - -Definition Z_ge_dec : {x >= y} + {~ x >= y}. -Proof. -unfold Zge in |- *. -apply Zcompare_rec with (n := x) (m := y); intro H. -left. rewrite H. discriminate. -right. tauto. -left. rewrite H. discriminate. -Defined. - -Definition Z_lt_ge_dec : {x < y} + {x >= y}. -Proof. -exact Z_lt_dec. -Defined. - -Lemma Z_lt_le_dec : {x < y} + {y <= x}. -Proof. -intros. -elim Z_lt_ge_dec. -intros; left; assumption. -intros; right; apply Zge_le; assumption. -Qed. - -Definition Z_le_gt_dec : {x <= y} + {x > y}. -Proof. -elim Z_le_dec; auto with arith. -intro. right. apply Znot_le_gt; auto with arith. -Defined. - -Definition Z_gt_le_dec : {x > y} + {x <= y}. -Proof. -exact Z_gt_dec. -Defined. - -Definition Z_ge_lt_dec : {x >= y} + {x < y}. -Proof. -elim Z_ge_dec; auto with arith. -intro. right. apply Znot_ge_lt; auto with arith. -Defined. - -Definition Z_le_lt_eq_dec : x <= y -> {x < y} + {x = y}. -Proof. -intro H. -apply Zcompare_rec with (n := x) (m := y). -intro. right. elim (Zcompare_Eq_iff_eq x y); auto with arith. -intro. left. elim (Zcompare_Eq_iff_eq x y); auto with arith. -intro H1. absurd (x > y); auto with arith. -Defined. + Variables x y : Z. + + (** * Decidability of equality on binary integers *) + + Definition Z_eq_dec : {x = y} + {x <> y}. + Proof. + apply Zcompare_rec with (n := x) (m := y). + intro. left. elim (Zcompare_Eq_iff_eq x y); auto with arith. + intro H3. right. elim (Zcompare_Eq_iff_eq x y). intros H1 H2. unfold not in |- *. intro H4. + rewrite (H2 H4) in H3. discriminate H3. + intro H3. right. elim (Zcompare_Eq_iff_eq x y). intros H1 H2. unfold not in |- *. intro H4. + rewrite (H2 H4) in H3. discriminate H3. + Defined. + + (** * Decidability of order on binary integers *) + + Definition Z_lt_dec : {x < y} + {~ x < y}. + Proof. + unfold Zlt in |- *. + apply Zcompare_rec with (n := x) (m := y); intro H. + right. rewrite H. discriminate. + left; assumption. + right. rewrite H. discriminate. + Defined. + + Definition Z_le_dec : {x <= y} + {~ x <= y}. + Proof. + unfold Zle in |- *. + apply Zcompare_rec with (n := x) (m := y); intro H. + left. rewrite H. discriminate. + left. rewrite H. discriminate. + right. tauto. + Defined. + + Definition Z_gt_dec : {x > y} + {~ x > y}. + Proof. + unfold Zgt in |- *. + apply Zcompare_rec with (n := x) (m := y); intro H. + right. rewrite H. discriminate. + right. rewrite H. discriminate. + left; assumption. + Defined. + + Definition Z_ge_dec : {x >= y} + {~ x >= y}. + Proof. + unfold Zge in |- *. + apply Zcompare_rec with (n := x) (m := y); intro H. + left. rewrite H. discriminate. + right. tauto. + left. rewrite H. discriminate. + Defined. + + Definition Z_lt_ge_dec : {x < y} + {x >= y}. + Proof. + exact Z_lt_dec. + Defined. + + Lemma Z_lt_le_dec : {x < y} + {y <= x}. + Proof. + intros. + elim Z_lt_ge_dec. + intros; left; assumption. + intros; right; apply Zge_le; assumption. + Qed. + + Definition Z_le_gt_dec : {x <= y} + {x > y}. + Proof. + elim Z_le_dec; auto with arith. + intro. right. apply Znot_le_gt; auto with arith. + Defined. + + Definition Z_gt_le_dec : {x > y} + {x <= y}. + Proof. + exact Z_gt_dec. + Defined. + + Definition Z_ge_lt_dec : {x >= y} + {x < y}. + Proof. + elim Z_ge_dec; auto with arith. + intro. right. apply Znot_ge_lt; auto with arith. + Defined. + + Definition Z_le_lt_eq_dec : x <= y -> {x < y} + {x = y}. + Proof. + intro H. + apply Zcompare_rec with (n := x) (m := y). + intro. right. elim (Zcompare_Eq_iff_eq x y); auto with arith. + intro. left. elim (Zcompare_Eq_iff_eq x y); auto with arith. + intro H1. absurd (x > y); auto with arith. + Defined. End decidability. -(** Cotransitivity of order on binary integers *) +(** * Cotransitivity of order on binary integers *) Lemma Zlt_cotrans : forall n m:Z, n < m -> forall p:Z, {n < p} + {p < m}. Proof. - intros x y H z. - case (Z_lt_ge_dec x z). - intro. - left. - assumption. - intro. - right. - apply Zle_lt_trans with (m := x). - apply Zge_le. - assumption. - assumption. + intros x y H z. + case (Z_lt_ge_dec x z). + intro. + left. + assumption. + intro. + right. + apply Zle_lt_trans with (m := x). + apply Zge_le. + assumption. + assumption. Defined. Lemma Zlt_cotrans_pos : forall n m:Z, 0 < n + m -> {0 < n} + {0 < m}. Proof. - intros x y H. - case (Zlt_cotrans 0 (x + y) H x). - intro. - left. - assumption. - intro. - right. - apply Zplus_lt_reg_l with (p := x). - rewrite Zplus_0_r. - assumption. + intros x y H. + case (Zlt_cotrans 0 (x + y) H x). + intro. + left. + assumption. + intro. + right. + apply Zplus_lt_reg_l with (p := x). + rewrite Zplus_0_r. + assumption. Defined. Lemma Zlt_cotrans_neg : forall n m:Z, n + m < 0 -> {n < 0} + {m < 0}. Proof. - intros x y H; case (Zlt_cotrans (x + y) 0 H x); intro Hxy; - [ right; apply Zplus_lt_reg_l with (p := x); rewrite Zplus_0_r | left ]; - assumption. + intros x y H; case (Zlt_cotrans (x + y) 0 H x); intro Hxy; + [ right; apply Zplus_lt_reg_l with (p := x); rewrite Zplus_0_r | left ]; + assumption. Defined. Lemma not_Zeq_inf : forall n m:Z, n <> m -> {n < m} + {m < n}. Proof. - intros x y H. - case Z_lt_ge_dec with x y. - intro. - left. - assumption. - intro H0. - generalize (Zge_le _ _ H0). - intro. - case (Z_le_lt_eq_dec _ _ H1). - intro. - right. - assumption. - intro. - apply False_rec. - apply H. - symmetry in |- *. - assumption. + intros x y H. + case Z_lt_ge_dec with x y. + intro. + left. + assumption. + intro H0. + generalize (Zge_le _ _ H0). + intro. + case (Z_le_lt_eq_dec _ _ H1). + intro. + right. + assumption. + intro. + apply False_rec. + apply H. + symmetry in |- *. + assumption. Defined. Lemma Z_dec : forall n m:Z, {n < m} + {n > m} + {n = m}. Proof. - intros x y. - case (Z_lt_ge_dec x y). - intro H. - left. - left. - assumption. - intro H. - generalize (Zge_le _ _ H). - intro H0. - case (Z_le_lt_eq_dec y x H0). - intro H1. - left. - right. - apply Zlt_gt. - assumption. - intro. - right. - symmetry in |- *. - assumption. + intros x y. + case (Z_lt_ge_dec x y). + intro H. + left. + left. + assumption. + intro H. + generalize (Zge_le _ _ H). + intro H0. + case (Z_le_lt_eq_dec y x H0). + intro H1. + left. + right. + apply Zlt_gt. + assumption. + intro. + right. + symmetry in |- *. + assumption. Defined. Lemma Z_dec' : forall n m:Z, {n < m} + {m < n} + {n = m}. Proof. - intros x y. - case (Z_eq_dec x y); intro H; - [ right; assumption | left; apply (not_Zeq_inf _ _ H) ]. + intros x y. + case (Z_eq_dec x y); intro H; + [ right; assumption | left; apply (not_Zeq_inf _ _ H) ]. Defined. Definition Z_zerop : forall x:Z, {x = 0} + {x <> 0}. Proof. -exact (fun x:Z => Z_eq_dec x 0). + exact (fun x:Z => Z_eq_dec x 0). Defined. Definition Z_notzerop (x:Z) := sumbool_not _ _ (Z_zerop x). -Definition Z_noteq_dec (x y:Z) := sumbool_not _ _ (Z_eq_dec x y). \ No newline at end of file +Definition Z_noteq_dec (x y:Z) := sumbool_not _ _ (Z_eq_dec x y). diff --git a/theories/ZArith/Zabs.v b/theories/ZArith/Zabs.v index fed6ad76..ed641358 100644 --- a/theories/ZArith/Zabs.v +++ b/theories/ZArith/Zabs.v @@ -5,11 +5,11 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zabs.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Zabs.v 9302 2006-10-27 21:21:17Z barras $ i*) (** Binary Integers (Pierre Crégut (CNET, Lannion, France) *) -Require Import Arith. +Require Import Arith_base. Require Import BinPos. Require Import BinInt. Require Import Zorder. @@ -18,111 +18,113 @@ Require Import ZArith_dec. Open Local Scope Z_scope. (**********************************************************************) -(** Properties of absolute value *) +(** * Properties of absolute value *) Lemma Zabs_eq : forall n:Z, 0 <= n -> Zabs n = n. -intro x; destruct x; auto with arith. -compute in |- *; intros; absurd (Gt = Gt); trivial with arith. +Proof. + intro x; destruct x; auto with arith. + compute in |- *; intros; absurd (Gt = Gt); trivial with arith. Qed. Lemma Zabs_non_eq : forall n:Z, n <= 0 -> Zabs n = - n. Proof. -intro x; destruct x; auto with arith. -compute in |- *; intros; absurd (Gt = Gt); trivial with arith. + intro x; destruct x; auto with arith. + compute in |- *; intros; absurd (Gt = Gt); trivial with arith. Qed. Theorem Zabs_Zopp : forall n:Z, Zabs (- n) = Zabs n. Proof. -intros z; case z; simpl in |- *; auto. + intros z; case z; simpl in |- *; auto. Qed. -(** Proving a property of the absolute value by cases *) +(** * Proving a property of the absolute value by cases *) Lemma Zabs_ind : - forall (P:Z -> Prop) (n:Z), - (n >= 0 -> P n) -> (n <= 0 -> P (- n)) -> P (Zabs n). + forall (P:Z -> Prop) (n:Z), + (n >= 0 -> P n) -> (n <= 0 -> P (- n)) -> P (Zabs n). Proof. -intros P x H H0; elim (Z_lt_ge_dec x 0); intro. -assert (x <= 0). apply Zlt_le_weak; assumption. -rewrite Zabs_non_eq. apply H0. assumption. assumption. -rewrite Zabs_eq. apply H; assumption. apply Zge_le. assumption. + intros P x H H0; elim (Z_lt_ge_dec x 0); intro. + assert (x <= 0). apply Zlt_le_weak; assumption. + rewrite Zabs_non_eq. apply H0. assumption. assumption. + rewrite Zabs_eq. apply H; assumption. apply Zge_le. assumption. Qed. Theorem Zabs_intro : forall P (n:Z), P (- n) -> P n -> P (Zabs n). -intros P z; case z; simpl in |- *; auto. +Proof. + intros P z; case z; simpl in |- *; auto. Qed. Definition Zabs_dec : forall x:Z, {x = Zabs x} + {x = - Zabs x}. Proof. -intro x; destruct x; auto with arith. + intro x; destruct x; auto with arith. Defined. Lemma Zabs_pos : forall n:Z, 0 <= Zabs n. -intro x; destruct x; auto with arith; compute in |- *; intros H; inversion H. + intro x; destruct x; auto with arith; compute in |- *; intros H; inversion H. Qed. Theorem Zabs_eq_case : forall n m:Z, Zabs n = Zabs m -> n = m \/ n = - m. Proof. -intros z1 z2; case z1; case z2; simpl in |- *; auto; - try (intros; discriminate); intros p1 p2 H1; injection H1; - (intros H2; rewrite H2); auto. + intros z1 z2; case z1; case z2; simpl in |- *; auto; + try (intros; discriminate); intros p1 p2 H1; injection H1; + (intros H2; rewrite H2); auto. Qed. -(** Triangular inequality *) +(** * Triangular inequality *) Hint Local Resolve Zle_neg_pos: zarith. Theorem Zabs_triangle : forall n m:Z, Zabs (n + m) <= Zabs n + Zabs m. Proof. -intros z1 z2; case z1; case z2; try (simpl in |- *; auto with zarith; fail). -intros p1 p2; - apply Zabs_intro with (P := fun x => x <= Zabs (Zpos p2) + Zabs (Zneg p1)); - try rewrite Zopp_plus_distr; auto with zarith. -apply Zplus_le_compat; simpl in |- *; auto with zarith. -apply Zplus_le_compat; simpl in |- *; auto with zarith. -intros p1 p2; - apply Zabs_intro with (P := fun x => x <= Zabs (Zpos p2) + Zabs (Zneg p1)); - try rewrite Zopp_plus_distr; auto with zarith. -apply Zplus_le_compat; simpl in |- *; auto with zarith. -apply Zplus_le_compat; simpl in |- *; auto with zarith. + intros z1 z2; case z1; case z2; try (simpl in |- *; auto with zarith; fail). + intros p1 p2; + apply Zabs_intro with (P := fun x => x <= Zabs (Zpos p2) + Zabs (Zneg p1)); + try rewrite Zopp_plus_distr; auto with zarith. + apply Zplus_le_compat; simpl in |- *; auto with zarith. + apply Zplus_le_compat; simpl in |- *; auto with zarith. + intros p1 p2; + apply Zabs_intro with (P := fun x => x <= Zabs (Zpos p2) + Zabs (Zneg p1)); + try rewrite Zopp_plus_distr; auto with zarith. + apply Zplus_le_compat; simpl in |- *; auto with zarith. + apply Zplus_le_compat; simpl in |- *; auto with zarith. Qed. -(** Absolute value and multiplication *) +(** * Absolute value and multiplication *) Lemma Zsgn_Zabs : forall n:Z, n * Zsgn n = Zabs n. Proof. -intro x; destruct x; rewrite Zmult_comm; auto with arith. + intro x; destruct x; rewrite Zmult_comm; auto with arith. Qed. Lemma Zabs_Zsgn : forall n:Z, Zabs n * Zsgn n = n. Proof. -intro x; destruct x; rewrite Zmult_comm; auto with arith. + intro x; destruct x; rewrite Zmult_comm; auto with arith. Qed. Theorem Zabs_Zmult : forall n m:Z, Zabs (n * m) = Zabs n * Zabs m. Proof. -intros z1 z2; case z1; case z2; simpl in |- *; auto. + intros z1 z2; case z1; case z2; simpl in |- *; auto. Qed. -(** absolute value in nat is compatible with order *) +(** * Absolute value in nat is compatible with order *) Lemma Zabs_nat_lt : - forall n m:Z, 0 <= n /\ n < m -> (Zabs_nat n < Zabs_nat m)%nat. + forall n m:Z, 0 <= n /\ n < m -> (Zabs_nat n < Zabs_nat m)%nat. Proof. -intros x y. case x; simpl in |- *. case y; simpl in |- *. - -intro. absurd (0 < 0). compute in |- *. intro H0. discriminate H0. intuition. -intros. elim (ZL4 p). intros. rewrite H0. auto with arith. -intros. elim (ZL4 p). intros. rewrite H0. auto with arith. - -case y; simpl in |- *. -intros. absurd (Zpos p < 0). compute in |- *. intro H0. discriminate H0. intuition. -intros. change (nat_of_P p > nat_of_P p0)%nat in |- *. -apply nat_of_P_gt_Gt_compare_morphism. -elim H; auto with arith. intro. exact (ZC2 p0 p). - -intros. absurd (Zpos p0 < Zneg p). -compute in |- *. intro H0. discriminate H0. intuition. - -intros. absurd (0 <= Zneg p). compute in |- *. auto with arith. intuition. -Qed. \ No newline at end of file + intros x y. case x; simpl in |- *. case y; simpl in |- *. + + intro. absurd (0 < 0). compute in |- *. intro H0. discriminate H0. intuition. + intros. elim (ZL4 p). intros. rewrite H0. auto with arith. + intros. elim (ZL4 p). intros. rewrite H0. auto with arith. + + case y; simpl in |- *. + intros. absurd (Zpos p < 0). compute in |- *. intro H0. discriminate H0. intuition. + intros. change (nat_of_P p > nat_of_P p0)%nat in |- *. + apply nat_of_P_gt_Gt_compare_morphism. + elim H; auto with arith. intro. exact (ZC2 p0 p). + + intros. absurd (Zpos p0 < Zneg p). + compute in |- *. intro H0. discriminate H0. intuition. + + intros. absurd (0 <= Zneg p). compute in |- *. auto with arith. intuition. +Qed. diff --git a/theories/ZArith/Zbinary.v b/theories/ZArith/Zbinary.v index 353f0d5d..08f08e12 100644 --- a/theories/ZArith/Zbinary.v +++ b/theories/ZArith/Zbinary.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zbinary.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Zbinary.v 9245 2006-10-17 12:53:34Z notin $ i*) (** Bit vectors interpreted as integers. Contribution by Jean Duprat (ENS Lyon). *) @@ -16,11 +16,10 @@ Require Import ZArith. Require Export Zpower. Require Import Omega. -(* -L'évaluation des vecteurs de booléens se font à la fois en binaire et -en complément à deux. Le nombre appartient à Z. -On utilise donc Omega pour faire les calculs dans Z. -De plus, on utilise les fonctions 2^n où n est un naturel, ici la longueur. +(** L'évaluation des vecteurs de booléens se font à la fois en binaire et + en complément à  deux. Le nombre appartient à  Z. + On utilise donc Omega pour faire les calculs dans Z. + De plus, on utilise les fonctions 2^n où n est un naturel, ici la longueur. two_power_nat = [n:nat](POS (shift_nat n xH)) : nat->Z two_power_nat_S @@ -32,395 +31,322 @@ De plus, on utilise les fonctions 2^n où n est un naturel, ici la longueur. Section VALUE_OF_BOOLEAN_VECTORS. -(* -Les calculs sont effectués dans la convention positive usuelle. -Les valeurs correspondent soit à l'écriture binaire (nat), -soit au complément à deux (int). -On effectue le calcul suivant le schéma de Horner. -Le complément à deux n'a de sens que sur les vecteurs de taille -supérieure ou égale à un, le bit de signe étant évalué négativement. +(** Les calculs sont effectués dans la convention positive usuelle. + Les valeurs correspondent soit à  l'écriture binaire (nat), + soit au complément à  deux (int). + On effectue le calcul suivant le schéma de Horner. + Le complément à  deux n'a de sens que sur les vecteurs de taille + supérieure ou égale à  un, le bit de signe étant évalué négativement. *) -Definition bit_value (b:bool) : Z := - match b with - | true => 1%Z - | false => 0%Z - end. - -Lemma binary_value : forall n:nat, Bvector n -> Z. -Proof. - simple induction n; intros. - exact 0%Z. - - inversion H0. - exact (bit_value a + 2 * H H2)%Z. -Defined. - -Lemma two_compl_value : forall n:nat, Bvector (S n) -> Z. -Proof. - simple induction n; intros. - inversion H. - exact (- bit_value a)%Z. - - inversion H0. - exact (bit_value a + 2 * H H2)%Z. -Defined. - -(* -Coq < Eval Compute in (binary_value (3) (Bcons true (2) (Bcons false (1) (Bcons true (0) Bnil)))). - = `5` - : Z -*) - -(* -Coq < Eval Compute in (two_compl_value (3) (Bcons true (3) (Bcons false (2) (Bcons true (1) (Bcons true (0) Bnil))))). - = `-3` - : Z -*) + Definition bit_value (b:bool) : Z := + match b with + | true => 1%Z + | false => 0%Z + end. + + Lemma binary_value : forall n:nat, Bvector n -> Z. + Proof. + simple induction n; intros. + exact 0%Z. + + inversion H0. + exact (bit_value a + 2 * H H2)%Z. + Defined. + + Lemma two_compl_value : forall n:nat, Bvector (S n) -> Z. + Proof. + simple induction n; intros. + inversion H. + exact (- bit_value a)%Z. + + inversion H0. + exact (bit_value a + 2 * H H2)%Z. + Defined. End VALUE_OF_BOOLEAN_VECTORS. Section ENCODING_VALUE. -(* -On calcule la valeur binaire selon un schema de Horner. -Le calcul s'arrete à la longueur du vecteur sans vérification. -On definit une fonction Zmod2 calquee sur Zdiv2 mais donnant le quotient -de la division z=2q+r avec 0<=r<=1. -La valeur en complément à deux est calculée selon un schema de Horner -avec Zmod2, le paramètre est la taille moins un. -*) - -Definition Zmod2 (z:Z) := - match z with - | Z0 => 0%Z - | Zpos p => match p with - | xI q => Zpos q - | xO q => Zpos q - | xH => 0%Z - end - | Zneg p => - match p with - | xI q => (Zneg q - 1)%Z - | xO q => Zneg q - | xH => (-1)%Z - end - end. - - -Lemma Zmod2_twice : - forall z:Z, z = (2 * Zmod2 z + bit_value (Zeven.Zodd_bool z))%Z. -Proof. - destruct z; simpl in |- *. - trivial. - - destruct p; simpl in |- *; trivial. - - destruct p; simpl in |- *. - destruct p as [p| p| ]; simpl in |- *. - rewrite <- (Pdouble_minus_one_o_succ_eq_xI p); trivial. - - trivial. - - trivial. - - trivial. - - trivial. -Qed. - -Lemma Z_to_binary : forall n:nat, Z -> Bvector n. -Proof. - simple induction n; intros. - exact Bnil. - - exact (Bcons (Zeven.Zodd_bool H0) n0 (H (Zeven.Zdiv2 H0))). -Defined. - -(* -Eval Compute in (Z_to_binary (5) `5`). - = (Vcons bool true (4) - (Vcons bool false (3) - (Vcons bool true (2) - (Vcons bool false (1) (Vcons bool false (0) (Vnil bool)))))) - : (Bvector (5)) +(** On calcule la valeur binaire selon un schema de Horner. + Le calcul s'arrete à  la longueur du vecteur sans vérification. + On definit une fonction Zmod2 calquee sur Zdiv2 mais donnant le quotient + de la division z=2q+r avec 0<=r<=1. + La valeur en complément à  deux est calculée selon un schema de Horner + avec Zmod2, le paramètre est la taille moins un. *) -Lemma Z_to_two_compl : forall n:nat, Z -> Bvector (S n). -Proof. - simple induction n; intros. - exact (Bcons (Zeven.Zodd_bool H) 0 Bnil). - - exact (Bcons (Zeven.Zodd_bool H0) (S n0) (H (Zmod2 H0))). -Defined. - -(* -Eval Compute in (Z_to_two_compl (3) `0`). - = (Vcons bool false (3) - (Vcons bool false (2) - (Vcons bool false (1) (Vcons bool false (0) (Vnil bool))))) - : (vector bool (4)) - -Eval Compute in (Z_to_two_compl (3) `5`). - = (Vcons bool true (3) - (Vcons bool false (2) - (Vcons bool true (1) (Vcons bool false (0) (Vnil bool))))) - : (vector bool (4)) - -Eval Compute in (Z_to_two_compl (3) `-5`). - = (Vcons bool true (3) - (Vcons bool true (2) - (Vcons bool false (1) (Vcons bool true (0) (Vnil bool))))) - : (vector bool (4)) -*) + Definition Zmod2 (z:Z) := + match z with + | Z0 => 0%Z + | Zpos p => match p with + | xI q => Zpos q + | xO q => Zpos q + | xH => 0%Z + end + | Zneg p => + match p with + | xI q => (Zneg q - 1)%Z + | xO q => Zneg q + | xH => (-1)%Z + end + end. + + + Lemma Zmod2_twice : + forall z:Z, z = (2 * Zmod2 z + bit_value (Zeven.Zodd_bool z))%Z. + Proof. + destruct z; simpl in |- *. + trivial. + + destruct p; simpl in |- *; trivial. + + destruct p; simpl in |- *. + destruct p as [p| p| ]; simpl in |- *. + rewrite <- (Pdouble_minus_one_o_succ_eq_xI p); trivial. + + trivial. + + trivial. + + trivial. + + trivial. + Qed. + + Lemma Z_to_binary : forall n:nat, Z -> Bvector n. + Proof. + simple induction n; intros. + exact Bnil. + + exact (Bcons (Zeven.Zodd_bool H0) n0 (H (Zeven.Zdiv2 H0))). + Defined. + + Lemma Z_to_two_compl : forall n:nat, Z -> Bvector (S n). + Proof. + simple induction n; intros. + exact (Bcons (Zeven.Zodd_bool H) 0 Bnil). + + exact (Bcons (Zeven.Zodd_bool H0) (S n0) (H (Zmod2 H0))). + Defined. End ENCODING_VALUE. Section Z_BRIC_A_BRAC. -(* -Bibliotheque de lemmes utiles dans la section suivante. -Utilise largement ZArith. -Meriterait d'etre reecrite. -*) - -Lemma binary_value_Sn : - forall (n:nat) (b:bool) (bv:Bvector n), - binary_value (S n) (Vcons bool b n bv) = - (bit_value b + 2 * binary_value n bv)%Z. -Proof. - intros; auto. -Qed. - -Lemma Z_to_binary_Sn : - forall (n:nat) (b:bool) (z:Z), - (z >= 0)%Z -> - Z_to_binary (S n) (bit_value b + 2 * z) = Bcons b n (Z_to_binary n z). -Proof. - destruct b; destruct z; simpl in |- *; auto. - intro H; elim H; trivial. -Qed. - -Lemma binary_value_pos : - forall (n:nat) (bv:Bvector n), (binary_value n bv >= 0)%Z. -Proof. - induction bv as [| a n v IHbv]; simpl in |- *. - omega. - - destruct a; destruct (binary_value n v); simpl in |- *; auto. - auto with zarith. -Qed. - - -Lemma two_compl_value_Sn : - forall (n:nat) (bv:Bvector (S n)) (b:bool), - two_compl_value (S n) (Bcons b (S n) bv) = - (bit_value b + 2 * two_compl_value n bv)%Z. -Proof. - intros; auto. -Qed. - -Lemma Z_to_two_compl_Sn : - forall (n:nat) (b:bool) (z:Z), - Z_to_two_compl (S n) (bit_value b + 2 * z) = - Bcons b (S n) (Z_to_two_compl n z). -Proof. - destruct b; destruct z as [| p| p]; auto. - destruct p as [p| p| ]; auto. - destruct p as [p| p| ]; simpl in |- *; auto. - intros; rewrite (Psucc_o_double_minus_one_eq_xO p); trivial. -Qed. - -Lemma Z_to_binary_Sn_z : - forall (n:nat) (z:Z), - Z_to_binary (S n) z = - Bcons (Zeven.Zodd_bool z) n (Z_to_binary n (Zeven.Zdiv2 z)). -Proof. - intros; auto. -Qed. - -Lemma Z_div2_value : - forall z:Z, - (z >= 0)%Z -> (bit_value (Zeven.Zodd_bool z) + 2 * Zeven.Zdiv2 z)%Z = z. -Proof. - destruct z as [| p| p]; auto. - destruct p; auto. - intro H; elim H; trivial. -Qed. - -Lemma Pdiv2 : forall z:Z, (z >= 0)%Z -> (Zeven.Zdiv2 z >= 0)%Z. -Proof. - destruct z as [| p| p]. - auto. - - destruct p; auto. - simpl in |- *; intros; omega. - - intro H; elim H; trivial. - -Qed. - -Lemma Zdiv2_two_power_nat : - forall (z:Z) (n:nat), - (z >= 0)%Z -> - (z < two_power_nat (S n))%Z -> (Zeven.Zdiv2 z < two_power_nat n)%Z. -Proof. - intros. - cut (2 * Zeven.Zdiv2 z < 2 * two_power_nat n)%Z; intros. - omega. - - rewrite <- two_power_nat_S. - destruct (Zeven.Zeven_odd_dec z); intros. - rewrite <- Zeven.Zeven_div2; auto. - - generalize (Zeven.Zodd_div2 z H z0); omega. -Qed. - -(* - -Lemma Z_minus_one_or_zero : (z:Z) - `z >= -1` -> - `z < 1` -> - {`z=-1`} + {`z=0`}. -Proof. - NewDestruct z; Auto. - NewDestruct p; Auto. - Tauto. - - Tauto. - - Intros. - Right; Omega. - - NewDestruct p. - Tauto. - - Tauto. - - Intros; Left; Omega. -Save. -*) - -Lemma Z_to_two_compl_Sn_z : - forall (n:nat) (z:Z), - Z_to_two_compl (S n) z = - Bcons (Zeven.Zodd_bool z) (S n) (Z_to_two_compl n (Zmod2 z)). -Proof. - intros; auto. -Qed. - -Lemma Zeven_bit_value : - forall z:Z, Zeven.Zeven z -> bit_value (Zeven.Zodd_bool z) = 0%Z. -Proof. - destruct z; unfold bit_value in |- *; auto. - destruct p; tauto || (intro H; elim H). - destruct p; tauto || (intro H; elim H). -Qed. - -Lemma Zodd_bit_value : - forall z:Z, Zeven.Zodd z -> bit_value (Zeven.Zodd_bool z) = 1%Z. -Proof. - destruct z; unfold bit_value in |- *; auto. - intros; elim H. - destruct p; tauto || (intros; elim H). - destruct p; tauto || (intros; elim H). -Qed. - -Lemma Zge_minus_two_power_nat_S : - forall (n:nat) (z:Z), - (z >= - two_power_nat (S n))%Z -> (Zmod2 z >= - two_power_nat n)%Z. -Proof. - intros n z; rewrite (two_power_nat_S n). - generalize (Zmod2_twice z). - destruct (Zeven.Zeven_odd_dec z) as [H| H]. - rewrite (Zeven_bit_value z H); intros; omega. - - rewrite (Zodd_bit_value z H); intros; omega. -Qed. - -Lemma Zlt_two_power_nat_S : - forall (n:nat) (z:Z), - (z < two_power_nat (S n))%Z -> (Zmod2 z < two_power_nat n)%Z. -Proof. - intros n z; rewrite (two_power_nat_S n). - generalize (Zmod2_twice z). - destruct (Zeven.Zeven_odd_dec z) as [H| H]. - rewrite (Zeven_bit_value z H); intros; omega. - - rewrite (Zodd_bit_value z H); intros; omega. -Qed. + (** Bibliotheque de lemmes utiles dans la section suivante. + Utilise largement ZArith. + Mériterait d'être récrite. + *) + + Lemma binary_value_Sn : + forall (n:nat) (b:bool) (bv:Bvector n), + binary_value (S n) (Vcons bool b n bv) = + (bit_value b + 2 * binary_value n bv)%Z. + Proof. + intros; auto. + Qed. + + Lemma Z_to_binary_Sn : + forall (n:nat) (b:bool) (z:Z), + (z >= 0)%Z -> + Z_to_binary (S n) (bit_value b + 2 * z) = Bcons b n (Z_to_binary n z). + Proof. + destruct b; destruct z; simpl in |- *; auto. + intro H; elim H; trivial. + Qed. + + Lemma binary_value_pos : + forall (n:nat) (bv:Bvector n), (binary_value n bv >= 0)%Z. + Proof. + induction bv as [| a n v IHbv]; simpl in |- *. + omega. + + destruct a; destruct (binary_value n v); simpl in |- *; auto. + auto with zarith. + Qed. + + Lemma two_compl_value_Sn : + forall (n:nat) (bv:Bvector (S n)) (b:bool), + two_compl_value (S n) (Bcons b (S n) bv) = + (bit_value b + 2 * two_compl_value n bv)%Z. + Proof. + intros; auto. + Qed. + + Lemma Z_to_two_compl_Sn : + forall (n:nat) (b:bool) (z:Z), + Z_to_two_compl (S n) (bit_value b + 2 * z) = + Bcons b (S n) (Z_to_two_compl n z). + Proof. + destruct b; destruct z as [| p| p]; auto. + destruct p as [p| p| ]; auto. + destruct p as [p| p| ]; simpl in |- *; auto. + intros; rewrite (Psucc_o_double_minus_one_eq_xO p); trivial. + Qed. + + Lemma Z_to_binary_Sn_z : + forall (n:nat) (z:Z), + Z_to_binary (S n) z = + Bcons (Zeven.Zodd_bool z) n (Z_to_binary n (Zeven.Zdiv2 z)). + Proof. + intros; auto. + Qed. + + Lemma Z_div2_value : + forall z:Z, + (z >= 0)%Z -> (bit_value (Zeven.Zodd_bool z) + 2 * Zeven.Zdiv2 z)%Z = z. + Proof. + destruct z as [| p| p]; auto. + destruct p; auto. + intro H; elim H; trivial. + Qed. + + Lemma Pdiv2 : forall z:Z, (z >= 0)%Z -> (Zeven.Zdiv2 z >= 0)%Z. + Proof. + destruct z as [| p| p]. + auto. + + destruct p; auto. + simpl in |- *; intros; omega. + + intro H; elim H; trivial. + Qed. + + Lemma Zdiv2_two_power_nat : + forall (z:Z) (n:nat), + (z >= 0)%Z -> + (z < two_power_nat (S n))%Z -> (Zeven.Zdiv2 z < two_power_nat n)%Z. + Proof. + intros. + cut (2 * Zeven.Zdiv2 z < 2 * two_power_nat n)%Z; intros. + omega. + + rewrite <- two_power_nat_S. + destruct (Zeven.Zeven_odd_dec z); intros. + rewrite <- Zeven.Zeven_div2; auto. + + generalize (Zeven.Zodd_div2 z H z0); omega. + Qed. + + Lemma Z_to_two_compl_Sn_z : + forall (n:nat) (z:Z), + Z_to_two_compl (S n) z = + Bcons (Zeven.Zodd_bool z) (S n) (Z_to_two_compl n (Zmod2 z)). + Proof. + intros; auto. + Qed. + + Lemma Zeven_bit_value : + forall z:Z, Zeven.Zeven z -> bit_value (Zeven.Zodd_bool z) = 0%Z. + Proof. + destruct z; unfold bit_value in |- *; auto. + destruct p; tauto || (intro H; elim H). + destruct p; tauto || (intro H; elim H). + Qed. + + Lemma Zodd_bit_value : + forall z:Z, Zeven.Zodd z -> bit_value (Zeven.Zodd_bool z) = 1%Z. + Proof. + destruct z; unfold bit_value in |- *; auto. + intros; elim H. + destruct p; tauto || (intros; elim H). + destruct p; tauto || (intros; elim H). + Qed. + + Lemma Zge_minus_two_power_nat_S : + forall (n:nat) (z:Z), + (z >= - two_power_nat (S n))%Z -> (Zmod2 z >= - two_power_nat n)%Z. + Proof. + intros n z; rewrite (two_power_nat_S n). + generalize (Zmod2_twice z). + destruct (Zeven.Zeven_odd_dec z) as [H| H]. + rewrite (Zeven_bit_value z H); intros; omega. + + rewrite (Zodd_bit_value z H); intros; omega. + Qed. + + Lemma Zlt_two_power_nat_S : + forall (n:nat) (z:Z), + (z < two_power_nat (S n))%Z -> (Zmod2 z < two_power_nat n)%Z. + Proof. + intros n z; rewrite (two_power_nat_S n). + generalize (Zmod2_twice z). + destruct (Zeven.Zeven_odd_dec z) as [H| H]. + rewrite (Zeven_bit_value z H); intros; omega. + + rewrite (Zodd_bit_value z H); intros; omega. + Qed. End Z_BRIC_A_BRAC. Section COHERENT_VALUE. -(* -On vérifie que dans l'intervalle de définition les fonctions sont -réciproques l'une de l'autre. -Elles utilisent les lemmes du bric-a-brac. +(** On vérifie que dans l'intervalle de définition les fonctions sont + réciproques l'une de l'autre. Elles utilisent les lemmes du bric-a-brac. *) -Lemma binary_to_Z_to_binary : - forall (n:nat) (bv:Bvector n), Z_to_binary n (binary_value n bv) = bv. -Proof. - induction bv as [| a n bv IHbv]. - auto. - - rewrite binary_value_Sn. - rewrite Z_to_binary_Sn. - rewrite IHbv; trivial. - - apply binary_value_pos. -Qed. - -Lemma two_compl_to_Z_to_two_compl : - forall (n:nat) (bv:Bvector n) (b:bool), - Z_to_two_compl n (two_compl_value n (Bcons b n bv)) = Bcons b n bv. -Proof. - induction bv as [| a n bv IHbv]; intro b. - destruct b; auto. - - rewrite two_compl_value_Sn. - rewrite Z_to_two_compl_Sn. - rewrite IHbv; trivial. -Qed. - -Lemma Z_to_binary_to_Z : - forall (n:nat) (z:Z), - (z >= 0)%Z -> - (z < two_power_nat n)%Z -> binary_value n (Z_to_binary n z) = z. -Proof. - induction n as [| n IHn]. - unfold two_power_nat, shift_nat in |- *; simpl in |- *; intros; omega. - - intros; rewrite Z_to_binary_Sn_z. - rewrite binary_value_Sn. - rewrite IHn. - apply Z_div2_value; auto. - - apply Pdiv2; trivial. - - apply Zdiv2_two_power_nat; trivial. -Qed. - -Lemma Z_to_two_compl_to_Z : - forall (n:nat) (z:Z), - (z >= - two_power_nat n)%Z -> - (z < two_power_nat n)%Z -> two_compl_value n (Z_to_two_compl n z) = z. -Proof. - induction n as [| n IHn]. - unfold two_power_nat, shift_nat in |- *; simpl in |- *; intros. - assert (z = (-1)%Z \/ z = 0%Z). omega. -intuition; subst z; trivial. - - intros; rewrite Z_to_two_compl_Sn_z. - rewrite two_compl_value_Sn. - rewrite IHn. - generalize (Zmod2_twice z); omega. - - apply Zge_minus_two_power_nat_S; auto. - - apply Zlt_two_power_nat_S; auto. -Qed. + Lemma binary_to_Z_to_binary : + forall (n:nat) (bv:Bvector n), Z_to_binary n (binary_value n bv) = bv. + Proof. + induction bv as [| a n bv IHbv]. + auto. + + rewrite binary_value_Sn. + rewrite Z_to_binary_Sn. + rewrite IHbv; trivial. + + apply binary_value_pos. + Qed. + + Lemma two_compl_to_Z_to_two_compl : + forall (n:nat) (bv:Bvector n) (b:bool), + Z_to_two_compl n (two_compl_value n (Bcons b n bv)) = Bcons b n bv. + Proof. + induction bv as [| a n bv IHbv]; intro b. + destruct b; auto. + + rewrite two_compl_value_Sn. + rewrite Z_to_two_compl_Sn. + rewrite IHbv; trivial. + Qed. + + Lemma Z_to_binary_to_Z : + forall (n:nat) (z:Z), + (z >= 0)%Z -> + (z < two_power_nat n)%Z -> binary_value n (Z_to_binary n z) = z. + Proof. + induction n as [| n IHn]. + unfold two_power_nat, shift_nat in |- *; simpl in |- *; intros; omega. + + intros; rewrite Z_to_binary_Sn_z. + rewrite binary_value_Sn. + rewrite IHn. + apply Z_div2_value; auto. + + apply Pdiv2; trivial. + + apply Zdiv2_two_power_nat; trivial. + Qed. + + Lemma Z_to_two_compl_to_Z : + forall (n:nat) (z:Z), + (z >= - two_power_nat n)%Z -> + (z < two_power_nat n)%Z -> two_compl_value n (Z_to_two_compl n z) = z. + Proof. + induction n as [| n IHn]. + unfold two_power_nat, shift_nat in |- *; simpl in |- *; intros. + assert (z = (-1)%Z \/ z = 0%Z). omega. + intuition; subst z; trivial. + + intros; rewrite Z_to_two_compl_Sn_z. + rewrite two_compl_value_Sn. + rewrite IHn. + generalize (Zmod2_twice z); omega. + + apply Zge_minus_two_power_nat_S; auto. + + apply Zlt_two_power_nat_S; auto. + Qed. End COHERENT_VALUE. diff --git a/theories/ZArith/Zbool.v b/theories/ZArith/Zbool.v index a195b951..7da91c44 100644 --- a/theories/ZArith/Zbool.v +++ b/theories/ZArith/Zbool.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zbool.v 6295 2004-11-12 16:40:39Z gregoire $ *) +(* $Id: Zbool.v 9245 2006-10-17 12:53:34Z notin $ *) Require Import BinInt. Require Import Zeven. @@ -17,6 +17,8 @@ Require Import Sumbool. Unset Boxed Definitions. + +(** * Boolean operations from decidabilty of order *) (** The decidability of equality and order relations over type [Z] give some boolean functions with the adequate specification. *) @@ -32,65 +34,70 @@ Definition Z_noteq_bool (x y:Z) := bool_of_sumbool (Z_noteq_dec x y). Definition Zeven_odd_bool (x:Z) := bool_of_sumbool (Zeven_odd_dec x). (**********************************************************************) -(** Boolean comparisons of binary integers *) +(** * Boolean comparisons of binary integers *) Definition Zle_bool (x y:Z) := match (x ?= y)%Z with - | Gt => false - | _ => true + | Gt => false + | _ => true end. + Definition Zge_bool (x y:Z) := match (x ?= y)%Z with - | Lt => false - | _ => true + | Lt => false + | _ => true end. + Definition Zlt_bool (x y:Z) := match (x ?= y)%Z with - | Lt => true - | _ => false + | Lt => true + | _ => false end. + Definition Zgt_bool (x y:Z) := match (x ?= y)%Z with - | Gt => true - | _ => false + | Gt => true + | _ => false end. + Definition Zeq_bool (x y:Z) := match (x ?= y)%Z with - | Eq => true - | _ => false + | Eq => true + | _ => false end. + Definition Zneq_bool (x y:Z) := match (x ?= y)%Z with - | Eq => false - | _ => true + | Eq => false + | _ => true end. Lemma Zle_cases : - forall n m:Z, if Zle_bool n m then (n <= m)%Z else (n > m)%Z. + forall n m:Z, if Zle_bool n m then (n <= m)%Z else (n > m)%Z. Proof. -intros x y; unfold Zle_bool, Zle, Zgt in |- *. -case (x ?= y)%Z; auto; discriminate. + intros x y; unfold Zle_bool, Zle, Zgt in |- *. + case (x ?= y)%Z; auto; discriminate. Qed. Lemma Zlt_cases : - forall n m:Z, if Zlt_bool n m then (n < m)%Z else (n >= m)%Z. + forall n m:Z, if Zlt_bool n m then (n < m)%Z else (n >= m)%Z. Proof. -intros x y; unfold Zlt_bool, Zlt, Zge in |- *. -case (x ?= y)%Z; auto; discriminate. + intros x y; unfold Zlt_bool, Zlt, Zge in |- *. + case (x ?= y)%Z; auto; discriminate. Qed. Lemma Zge_cases : - forall n m:Z, if Zge_bool n m then (n >= m)%Z else (n < m)%Z. + forall n m:Z, if Zge_bool n m then (n >= m)%Z else (n < m)%Z. Proof. -intros x y; unfold Zge_bool, Zge, Zlt in |- *. -case (x ?= y)%Z; auto; discriminate. + intros x y; unfold Zge_bool, Zge, Zlt in |- *. + case (x ?= y)%Z; auto; discriminate. Qed. Lemma Zgt_cases : - forall n m:Z, if Zgt_bool n m then (n > m)%Z else (n <= m)%Z. + forall n m:Z, if Zgt_bool n m then (n > m)%Z else (n <= m)%Z. Proof. -intros x y; unfold Zgt_bool, Zgt, Zle in |- *. -case (x ?= y)%Z; auto; discriminate. + intros x y; unfold Zgt_bool, Zgt, Zle in |- *. + case (x ?= y)%Z; auto; discriminate. Qed. (** Lemmas on [Zle_bool] used in contrib/graphs *) @@ -112,15 +119,15 @@ Proof. Qed. Lemma Zle_bool_antisym : - forall n m:Z, Zle_bool n m = true -> Zle_bool m n = true -> n = m. + forall n m:Z, Zle_bool n m = true -> Zle_bool m n = true -> n = m. Proof. intros. apply Zle_antisym. apply Zle_bool_imp_le. assumption. apply Zle_bool_imp_le. assumption. Qed. Lemma Zle_bool_trans : - forall n m p:Z, - Zle_bool n m = true -> Zle_bool m p = true -> Zle_bool n p = true. + forall n m p:Z, + Zle_bool n m = true -> Zle_bool m p = true -> Zle_bool n p = true. Proof. intros x y z; intros. apply Zle_imp_le_bool. apply Zle_trans with (m := y). apply Zle_bool_imp_le. assumption. apply Zle_bool_imp_le. assumption. @@ -137,9 +144,9 @@ Proof. Defined. Lemma Zle_bool_plus_mono : - forall n m p q:Z, - Zle_bool n m = true -> - Zle_bool p q = true -> Zle_bool (n + p) (m + q) = true. + forall n m p q:Z, + Zle_bool n m = true -> + Zle_bool p q = true -> Zle_bool (n + p) (m + q) = true. Proof. intros. apply Zle_imp_le_bool. apply Zplus_le_compat. apply Zle_bool_imp_le. assumption. apply Zle_bool_imp_le. assumption. @@ -159,30 +166,30 @@ Proof. Qed. - Lemma Zle_is_le_bool : forall n m:Z, (n <= m)%Z <-> Zle_bool n m = true. - Proof. - intros. split. intro. apply Zle_imp_le_bool. assumption. - intro. apply Zle_bool_imp_le. assumption. - Qed. - - Lemma Zge_is_le_bool : forall n m:Z, (n >= m)%Z <-> Zle_bool m n = true. - Proof. - intros. split. intro. apply Zle_imp_le_bool. apply Zge_le. assumption. - intro. apply Zle_ge. apply Zle_bool_imp_le. assumption. - Qed. - - Lemma Zlt_is_le_bool : - forall n m:Z, (n < m)%Z <-> Zle_bool n (m - 1) = true. - Proof. - intros x y. split. intro. apply Zle_imp_le_bool. apply Zlt_succ_le. rewrite (Zsucc_pred y) in H. - assumption. - intro. rewrite (Zsucc_pred y). apply Zle_lt_succ. apply Zle_bool_imp_le. assumption. - Qed. - - Lemma Zgt_is_le_bool : - forall n m:Z, (n > m)%Z <-> Zle_bool m (n - 1) = true. - Proof. - intros x y. apply iff_trans with (y < x)%Z. split. exact (Zgt_lt x y). - exact (Zlt_gt y x). - exact (Zlt_is_le_bool y x). - Qed. +Lemma Zle_is_le_bool : forall n m:Z, (n <= m)%Z <-> Zle_bool n m = true. +Proof. + intros. split. intro. apply Zle_imp_le_bool. assumption. + intro. apply Zle_bool_imp_le. assumption. +Qed. + +Lemma Zge_is_le_bool : forall n m:Z, (n >= m)%Z <-> Zle_bool m n = true. +Proof. + intros. split. intro. apply Zle_imp_le_bool. apply Zge_le. assumption. + intro. apply Zle_ge. apply Zle_bool_imp_le. assumption. +Qed. + +Lemma Zlt_is_le_bool : + forall n m:Z, (n < m)%Z <-> Zle_bool n (m - 1) = true. +Proof. + intros x y. split. intro. apply Zle_imp_le_bool. apply Zlt_succ_le. rewrite (Zsucc_pred y) in H. + assumption. + intro. rewrite (Zsucc_pred y). apply Zle_lt_succ. apply Zle_bool_imp_le. assumption. +Qed. + +Lemma Zgt_is_le_bool : + forall n m:Z, (n > m)%Z <-> Zle_bool m (n - 1) = true. +Proof. + intros x y. apply iff_trans with (y < x)%Z. split. exact (Zgt_lt x y). + exact (Zlt_gt y x). + exact (Zlt_is_le_bool y x). +Qed. diff --git a/theories/ZArith/Zcompare.v b/theories/ZArith/Zcompare.v index 4003c338..6c5b07d2 100644 --- a/theories/ZArith/Zcompare.v +++ b/theories/ZArith/Zcompare.v @@ -8,6 +8,10 @@ (*i $$ i*) +(**********************************************************************) +(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) +(**********************************************************************) + Require Export BinPos. Require Export BinInt. Require Import Lt. @@ -17,485 +21,480 @@ Require Import Mult. Open Local Scope Z_scope. -(**********************************************************************) -(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) -(**********************************************************************) - -(**********************************************************************) -(** Comparison on integers *) +(***************************) +(** * Comparison on integers *) Lemma Zcompare_refl : forall n:Z, (n ?= n) = Eq. Proof. -intro x; destruct x as [| p| p]; simpl in |- *; - [ reflexivity | apply Pcompare_refl | rewrite Pcompare_refl; reflexivity ]. + intro x; destruct x as [| p| p]; simpl in |- *; + [ reflexivity | apply Pcompare_refl | rewrite Pcompare_refl; reflexivity ]. Qed. Lemma Zcompare_Eq_eq : forall n m:Z, (n ?= m) = Eq -> n = m. Proof. -intros x y; destruct x as [| x'| x']; destruct y as [| y'| y']; simpl in |- *; - intro H; reflexivity || (try discriminate H); - [ rewrite (Pcompare_Eq_eq x' y' H); reflexivity - | rewrite (Pcompare_Eq_eq x' y'); - [ reflexivity - | destruct ((x' ?= y')%positive Eq); reflexivity || discriminate ] ]. + intros x y; destruct x as [| x'| x']; destruct y as [| y'| y']; simpl in |- *; + intro H; reflexivity || (try discriminate H); + [ rewrite (Pcompare_Eq_eq x' y' H); reflexivity + | rewrite (Pcompare_Eq_eq x' y'); + [ reflexivity + | destruct ((x' ?= y')%positive Eq); reflexivity || discriminate ] ]. Qed. Lemma Zcompare_Eq_iff_eq : forall n m:Z, (n ?= m) = Eq <-> n = m. Proof. -intros x y; split; intro E; - [ apply Zcompare_Eq_eq; assumption | rewrite E; apply Zcompare_refl ]. + intros x y; split; intro E; + [ apply Zcompare_Eq_eq; assumption | rewrite E; apply Zcompare_refl ]. Qed. Lemma Zcompare_antisym : forall n m:Z, CompOpp (n ?= m) = (m ?= n). Proof. -intros x y; destruct x; destruct y; simpl in |- *; - reflexivity || discriminate H || rewrite Pcompare_antisym; - reflexivity. + intros x y; destruct x; destruct y; simpl in |- *; + reflexivity || discriminate H || rewrite Pcompare_antisym; + reflexivity. Qed. Lemma Zcompare_Gt_Lt_antisym : forall n m:Z, (n ?= m) = Gt <-> (m ?= n) = Lt. Proof. -intros x y; split; intro H; - [ change Lt with (CompOpp Gt) in |- *; rewrite <- Zcompare_antisym; - rewrite H; reflexivity - | change Gt with (CompOpp Lt) in |- *; rewrite <- Zcompare_antisym; - rewrite H; reflexivity ]. + intros x y; split; intro H; + [ change Lt with (CompOpp Gt) in |- *; rewrite <- Zcompare_antisym; + rewrite H; reflexivity + | change Gt with (CompOpp Lt) in |- *; rewrite <- Zcompare_antisym; + rewrite H; reflexivity ]. Qed. -(** Transitivity of comparison *) +(** * Transitivity of comparison *) Lemma Zcompare_Gt_trans : - forall n m p:Z, (n ?= m) = Gt -> (m ?= p) = Gt -> (n ?= p) = Gt. + forall n m p:Z, (n ?= m) = Gt -> (m ?= p) = Gt -> (n ?= p) = Gt. Proof. -intros x y z; case x; case y; case z; simpl in |- *; - try (intros; discriminate H || discriminate H0); auto with arith; - [ intros p q r H H0; apply nat_of_P_gt_Gt_compare_complement_morphism; - unfold gt in |- *; apply lt_trans with (m := nat_of_P q); - apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; - assumption - | intros p q r; do 3 rewrite <- ZC4; intros H H0; - apply nat_of_P_gt_Gt_compare_complement_morphism; - unfold gt in |- *; apply lt_trans with (m := nat_of_P q); - apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; - assumption ]. + intros x y z; case x; case y; case z; simpl in |- *; + try (intros; discriminate H || discriminate H0); auto with arith; + [ intros p q r H H0; apply nat_of_P_gt_Gt_compare_complement_morphism; + unfold gt in |- *; apply lt_trans with (m := nat_of_P q); + apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; + assumption + | intros p q r; do 3 rewrite <- ZC4; intros H H0; + apply nat_of_P_gt_Gt_compare_complement_morphism; + unfold gt in |- *; apply lt_trans with (m := nat_of_P q); + apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; + assumption ]. Qed. -(** Comparison and opposite *) +(** * Comparison and opposite *) Lemma Zcompare_opp : forall n m:Z, (n ?= m) = (- m ?= - n). Proof. -intros x y; case x; case y; simpl in |- *; auto with arith; intros; - rewrite <- ZC4; trivial with arith. + intros x y; case x; case y; simpl in |- *; auto with arith; intros; + rewrite <- ZC4; trivial with arith. Qed. Hint Local Resolve Pcompare_refl. -(** Comparison first-order specification *) +(** * Comparison first-order specification *) Lemma Zcompare_Gt_spec : - forall n m:Z, (n ?= m) = Gt -> exists h : positive, n + - m = Zpos h. + forall n m:Z, (n ?= m) = Gt -> exists h : positive, n + - m = Zpos h. Proof. -intros x y; case x; case y; - [ simpl in |- *; intros H; discriminate H - | simpl in |- *; intros p H; discriminate H - | intros p H; exists p; simpl in |- *; auto with arith - | intros p H; exists p; simpl in |- *; auto with arith - | intros q p H; exists (p - q)%positive; unfold Zplus, Zopp in |- *; - unfold Zcompare in H; rewrite H; trivial with arith - | intros q p H; exists (p + q)%positive; simpl in |- *; trivial with arith - | simpl in |- *; intros p H; discriminate H - | simpl in |- *; intros q p H; discriminate H - | unfold Zcompare in |- *; intros q p; rewrite <- ZC4; intros H; - exists (q - p)%positive; simpl in |- *; rewrite (ZC1 q p H); - trivial with arith ]. + intros x y; case x; case y; + [ simpl in |- *; intros H; discriminate H + | simpl in |- *; intros p H; discriminate H + | intros p H; exists p; simpl in |- *; auto with arith + | intros p H; exists p; simpl in |- *; auto with arith + | intros q p H; exists (p - q)%positive; unfold Zplus, Zopp in |- *; + unfold Zcompare in H; rewrite H; trivial with arith + | intros q p H; exists (p + q)%positive; simpl in |- *; trivial with arith + | simpl in |- *; intros p H; discriminate H + | simpl in |- *; intros q p H; discriminate H + | unfold Zcompare in |- *; intros q p; rewrite <- ZC4; intros H; + exists (q - p)%positive; simpl in |- *; rewrite (ZC1 q p H); + trivial with arith ]. Qed. -(** Comparison and addition *) +(** * Comparison and addition *) Lemma weaken_Zcompare_Zplus_compatible : - (forall (n m:Z) (p:positive), (Zpos p + n ?= Zpos p + m) = (n ?= m)) -> - forall n m p:Z, (p + n ?= p + m) = (n ?= m). + (forall (n m:Z) (p:positive), (Zpos p + n ?= Zpos p + m) = (n ?= m)) -> + forall n m p:Z, (p + n ?= p + m) = (n ?= m). Proof. -intros H x y z; destruct z; - [ reflexivity - | apply H - | rewrite (Zcompare_opp x y); rewrite Zcompare_opp; - do 2 rewrite Zopp_plus_distr; rewrite Zopp_neg; - apply H ]. + intros H x y z; destruct z; + [ reflexivity + | apply H + | rewrite (Zcompare_opp x y); rewrite Zcompare_opp; + do 2 rewrite Zopp_plus_distr; rewrite Zopp_neg; + apply H ]. Qed. Hint Local Resolve ZC4. Lemma weak_Zcompare_Zplus_compatible : - forall (n m:Z) (p:positive), (Zpos p + n ?= Zpos p + m) = (n ?= m). + forall (n m:Z) (p:positive), (Zpos p + n ?= Zpos p + m) = (n ?= m). Proof. -intros x y z; case x; case y; simpl in |- *; auto with arith; - [ intros p; apply nat_of_P_lt_Lt_compare_complement_morphism; apply ZL17 - | intros p; ElimPcompare z p; intros E; rewrite E; auto with arith; - apply nat_of_P_gt_Gt_compare_complement_morphism; - rewrite nat_of_P_minus_morphism; - [ unfold gt in |- *; apply ZL16 | assumption ] - | intros p; ElimPcompare z p; intros E; auto with arith; - apply nat_of_P_gt_Gt_compare_complement_morphism; - unfold gt in |- *; apply ZL17 - | intros p q; ElimPcompare q p; intros E; rewrite E; - [ rewrite (Pcompare_Eq_eq q p E); apply Pcompare_refl - | apply nat_of_P_lt_Lt_compare_complement_morphism; - do 2 rewrite nat_of_P_plus_morphism; apply plus_lt_compat_l; - apply nat_of_P_lt_Lt_compare_morphism with (1 := E) - | apply nat_of_P_gt_Gt_compare_complement_morphism; unfold gt in |- *; - do 2 rewrite nat_of_P_plus_morphism; apply plus_lt_compat_l; - exact (nat_of_P_gt_Gt_compare_morphism q p E) ] - | intros p q; ElimPcompare z p; intros E; rewrite E; auto with arith; - apply nat_of_P_gt_Gt_compare_complement_morphism; - rewrite nat_of_P_minus_morphism; - [ unfold gt in |- *; apply lt_trans with (m := nat_of_P z); - [ apply ZL16 | apply ZL17 ] - | assumption ] - | intros p; ElimPcompare z p; intros E; rewrite E; auto with arith; - simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism; - rewrite nat_of_P_minus_morphism; [ apply ZL16 | assumption ] - | intros p q; ElimPcompare z q; intros E; rewrite E; auto with arith; - simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism; - rewrite nat_of_P_minus_morphism; - [ apply lt_trans with (m := nat_of_P z); [ apply ZL16 | apply ZL17 ] - | assumption ] - | intros p q; ElimPcompare z q; intros E0; rewrite E0; ElimPcompare z p; - intros E1; rewrite E1; ElimPcompare q p; intros E2; - rewrite E2; auto with arith; - [ absurd ((q ?= p)%positive Eq = Lt); - [ rewrite <- (Pcompare_Eq_eq z q E0); - rewrite <- (Pcompare_Eq_eq z p E1); rewrite (Pcompare_refl z); - discriminate - | assumption ] - | absurd ((q ?= p)%positive Eq = Gt); - [ rewrite <- (Pcompare_Eq_eq z q E0); - rewrite <- (Pcompare_Eq_eq z p E1); rewrite (Pcompare_refl z); - discriminate - | assumption ] - | absurd ((z ?= p)%positive Eq = Lt); - [ rewrite (Pcompare_Eq_eq z q E0); rewrite <- (Pcompare_Eq_eq q p E2); - rewrite (Pcompare_refl q); discriminate - | assumption ] - | absurd ((z ?= p)%positive Eq = Lt); - [ rewrite (Pcompare_Eq_eq z q E0); rewrite E2; discriminate - | assumption ] - | absurd ((z ?= p)%positive Eq = Gt); - [ rewrite (Pcompare_Eq_eq z q E0); rewrite <- (Pcompare_Eq_eq q p E2); - rewrite (Pcompare_refl q); discriminate - | assumption ] - | absurd ((z ?= p)%positive Eq = Gt); - [ rewrite (Pcompare_Eq_eq z q E0); rewrite E2; discriminate - | assumption ] - | absurd ((z ?= q)%positive Eq = Lt); - [ rewrite (Pcompare_Eq_eq z p E1); rewrite (Pcompare_Eq_eq q p E2); - rewrite (Pcompare_refl p); discriminate - | assumption ] - | absurd ((p ?= q)%positive Eq = Gt); - [ rewrite <- (Pcompare_Eq_eq z p E1); rewrite E0; discriminate - | apply ZC2; assumption ] - | simpl in |- *; rewrite (Pcompare_Eq_eq q p E2); - rewrite (Pcompare_refl (p - z)); auto with arith - | simpl in |- *; rewrite <- ZC4; - apply nat_of_P_gt_Gt_compare_complement_morphism; - rewrite nat_of_P_minus_morphism; - [ rewrite nat_of_P_minus_morphism; - [ unfold gt in |- *; apply plus_lt_reg_l with (p := nat_of_P z); - rewrite le_plus_minus_r; - [ rewrite le_plus_minus_r; - [ apply nat_of_P_lt_Lt_compare_morphism; assumption - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - assumption ] - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - assumption ] - | apply ZC2; assumption ] - | apply ZC2; assumption ] - | simpl in |- *; rewrite <- ZC4; - apply nat_of_P_lt_Lt_compare_complement_morphism; - rewrite nat_of_P_minus_morphism; - [ rewrite nat_of_P_minus_morphism; - [ apply plus_lt_reg_l with (p := nat_of_P z); - rewrite le_plus_minus_r; - [ rewrite le_plus_minus_r; - [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; - assumption - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - assumption ] - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - assumption ] - | apply ZC2; assumption ] - | apply ZC2; assumption ] - | absurd ((z ?= q)%positive Eq = Lt); - [ rewrite (Pcompare_Eq_eq q p E2); rewrite E1; discriminate - | assumption ] - | absurd ((q ?= p)%positive Eq = Lt); - [ cut ((q ?= p)%positive Eq = Gt); - [ intros E; rewrite E; discriminate - | apply nat_of_P_gt_Gt_compare_complement_morphism; - unfold gt in |- *; apply lt_trans with (m := nat_of_P z); - [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption - | apply nat_of_P_lt_Lt_compare_morphism; assumption ] ] - | assumption ] - | absurd ((z ?= q)%positive Eq = Gt); - [ rewrite (Pcompare_Eq_eq z p E1); rewrite (Pcompare_Eq_eq q p E2); - rewrite (Pcompare_refl p); discriminate - | assumption ] - | absurd ((z ?= q)%positive Eq = Gt); - [ rewrite (Pcompare_Eq_eq z p E1); rewrite ZC1; - [ discriminate | assumption ] - | assumption ] - | absurd ((z ?= q)%positive Eq = Gt); - [ rewrite (Pcompare_Eq_eq q p E2); rewrite E1; discriminate - | assumption ] - | absurd ((q ?= p)%positive Eq = Gt); - [ rewrite ZC1; - [ discriminate - | apply nat_of_P_gt_Gt_compare_complement_morphism; - unfold gt in |- *; apply lt_trans with (m := nat_of_P z); - [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption - | apply nat_of_P_lt_Lt_compare_morphism; assumption ] ] - | assumption ] - | simpl in |- *; rewrite (Pcompare_Eq_eq q p E2); apply Pcompare_refl - | simpl in |- *; apply nat_of_P_gt_Gt_compare_complement_morphism; - unfold gt in |- *; rewrite nat_of_P_minus_morphism; - [ rewrite nat_of_P_minus_morphism; - [ apply plus_lt_reg_l with (p := nat_of_P p); - rewrite le_plus_minus_r; - [ rewrite plus_comm; apply plus_lt_reg_l with (p := nat_of_P q); - rewrite plus_assoc; rewrite le_plus_minus_r; - [ rewrite (plus_comm (nat_of_P q)); apply plus_lt_compat_l; - apply nat_of_P_lt_Lt_compare_morphism; - assumption - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - apply ZC1; assumption ] - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - apply ZC1; assumption ] - | assumption ] - | assumption ] - | simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism; - rewrite nat_of_P_minus_morphism; - [ rewrite nat_of_P_minus_morphism; - [ apply plus_lt_reg_l with (p := nat_of_P q); - rewrite le_plus_minus_r; - [ rewrite plus_comm; apply plus_lt_reg_l with (p := nat_of_P p); - rewrite plus_assoc; rewrite le_plus_minus_r; - [ rewrite (plus_comm (nat_of_P p)); apply plus_lt_compat_l; - apply nat_of_P_lt_Lt_compare_morphism; - apply ZC1; assumption - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - apply ZC1; assumption ] - | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; - apply ZC1; assumption ] - | assumption ] - | assumption ] ] ]. + intros x y z; case x; case y; simpl in |- *; auto with arith; + [ intros p; apply nat_of_P_lt_Lt_compare_complement_morphism; apply ZL17 + | intros p; ElimPcompare z p; intros E; rewrite E; auto with arith; + apply nat_of_P_gt_Gt_compare_complement_morphism; + rewrite nat_of_P_minus_morphism; + [ unfold gt in |- *; apply ZL16 | assumption ] + | intros p; ElimPcompare z p; intros E; auto with arith; + apply nat_of_P_gt_Gt_compare_complement_morphism; + unfold gt in |- *; apply ZL17 + | intros p q; ElimPcompare q p; intros E; rewrite E; + [ rewrite (Pcompare_Eq_eq q p E); apply Pcompare_refl + | apply nat_of_P_lt_Lt_compare_complement_morphism; + do 2 rewrite nat_of_P_plus_morphism; apply plus_lt_compat_l; + apply nat_of_P_lt_Lt_compare_morphism with (1 := E) + | apply nat_of_P_gt_Gt_compare_complement_morphism; unfold gt in |- *; + do 2 rewrite nat_of_P_plus_morphism; apply plus_lt_compat_l; + exact (nat_of_P_gt_Gt_compare_morphism q p E) ] + | intros p q; ElimPcompare z p; intros E; rewrite E; auto with arith; + apply nat_of_P_gt_Gt_compare_complement_morphism; + rewrite nat_of_P_minus_morphism; + [ unfold gt in |- *; apply lt_trans with (m := nat_of_P z); + [ apply ZL16 | apply ZL17 ] + | assumption ] + | intros p; ElimPcompare z p; intros E; rewrite E; auto with arith; + simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism; + rewrite nat_of_P_minus_morphism; [ apply ZL16 | assumption ] + | intros p q; ElimPcompare z q; intros E; rewrite E; auto with arith; + simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism; + rewrite nat_of_P_minus_morphism; + [ apply lt_trans with (m := nat_of_P z); [ apply ZL16 | apply ZL17 ] + | assumption ] + | intros p q; ElimPcompare z q; intros E0; rewrite E0; ElimPcompare z p; + intros E1; rewrite E1; ElimPcompare q p; intros E2; + rewrite E2; auto with arith; + [ absurd ((q ?= p)%positive Eq = Lt); + [ rewrite <- (Pcompare_Eq_eq z q E0); + rewrite <- (Pcompare_Eq_eq z p E1); rewrite (Pcompare_refl z); + discriminate + | assumption ] + | absurd ((q ?= p)%positive Eq = Gt); + [ rewrite <- (Pcompare_Eq_eq z q E0); + rewrite <- (Pcompare_Eq_eq z p E1); rewrite (Pcompare_refl z); + discriminate + | assumption ] + | absurd ((z ?= p)%positive Eq = Lt); + [ rewrite (Pcompare_Eq_eq z q E0); rewrite <- (Pcompare_Eq_eq q p E2); + rewrite (Pcompare_refl q); discriminate + | assumption ] + | absurd ((z ?= p)%positive Eq = Lt); + [ rewrite (Pcompare_Eq_eq z q E0); rewrite E2; discriminate + | assumption ] + | absurd ((z ?= p)%positive Eq = Gt); + [ rewrite (Pcompare_Eq_eq z q E0); rewrite <- (Pcompare_Eq_eq q p E2); + rewrite (Pcompare_refl q); discriminate + | assumption ] + | absurd ((z ?= p)%positive Eq = Gt); + [ rewrite (Pcompare_Eq_eq z q E0); rewrite E2; discriminate + | assumption ] + | absurd ((z ?= q)%positive Eq = Lt); + [ rewrite (Pcompare_Eq_eq z p E1); rewrite (Pcompare_Eq_eq q p E2); + rewrite (Pcompare_refl p); discriminate + | assumption ] + | absurd ((p ?= q)%positive Eq = Gt); + [ rewrite <- (Pcompare_Eq_eq z p E1); rewrite E0; discriminate + | apply ZC2; assumption ] + | simpl in |- *; rewrite (Pcompare_Eq_eq q p E2); + rewrite (Pcompare_refl (p - z)); auto with arith + | simpl in |- *; rewrite <- ZC4; + apply nat_of_P_gt_Gt_compare_complement_morphism; + rewrite nat_of_P_minus_morphism; + [ rewrite nat_of_P_minus_morphism; + [ unfold gt in |- *; apply plus_lt_reg_l with (p := nat_of_P z); + rewrite le_plus_minus_r; + [ rewrite le_plus_minus_r; + [ apply nat_of_P_lt_Lt_compare_morphism; assumption + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + assumption ] + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + assumption ] + | apply ZC2; assumption ] + | apply ZC2; assumption ] + | simpl in |- *; rewrite <- ZC4; + apply nat_of_P_lt_Lt_compare_complement_morphism; + rewrite nat_of_P_minus_morphism; + [ rewrite nat_of_P_minus_morphism; + [ apply plus_lt_reg_l with (p := nat_of_P z); + rewrite le_plus_minus_r; + [ rewrite le_plus_minus_r; + [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; + assumption + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + assumption ] + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + assumption ] + | apply ZC2; assumption ] + | apply ZC2; assumption ] + | absurd ((z ?= q)%positive Eq = Lt); + [ rewrite (Pcompare_Eq_eq q p E2); rewrite E1; discriminate + | assumption ] + | absurd ((q ?= p)%positive Eq = Lt); + [ cut ((q ?= p)%positive Eq = Gt); + [ intros E; rewrite E; discriminate + | apply nat_of_P_gt_Gt_compare_complement_morphism; + unfold gt in |- *; apply lt_trans with (m := nat_of_P z); + [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption + | apply nat_of_P_lt_Lt_compare_morphism; assumption ] ] + | assumption ] + | absurd ((z ?= q)%positive Eq = Gt); + [ rewrite (Pcompare_Eq_eq z p E1); rewrite (Pcompare_Eq_eq q p E2); + rewrite (Pcompare_refl p); discriminate + | assumption ] + | absurd ((z ?= q)%positive Eq = Gt); + [ rewrite (Pcompare_Eq_eq z p E1); rewrite ZC1; + [ discriminate | assumption ] + | assumption ] + | absurd ((z ?= q)%positive Eq = Gt); + [ rewrite (Pcompare_Eq_eq q p E2); rewrite E1; discriminate + | assumption ] + | absurd ((q ?= p)%positive Eq = Gt); + [ rewrite ZC1; + [ discriminate + | apply nat_of_P_gt_Gt_compare_complement_morphism; + unfold gt in |- *; apply lt_trans with (m := nat_of_P z); + [ apply nat_of_P_lt_Lt_compare_morphism; apply ZC1; assumption + | apply nat_of_P_lt_Lt_compare_morphism; assumption ] ] + | assumption ] + | simpl in |- *; rewrite (Pcompare_Eq_eq q p E2); apply Pcompare_refl + | simpl in |- *; apply nat_of_P_gt_Gt_compare_complement_morphism; + unfold gt in |- *; rewrite nat_of_P_minus_morphism; + [ rewrite nat_of_P_minus_morphism; + [ apply plus_lt_reg_l with (p := nat_of_P p); + rewrite le_plus_minus_r; + [ rewrite plus_comm; apply plus_lt_reg_l with (p := nat_of_P q); + rewrite plus_assoc; rewrite le_plus_minus_r; + [ rewrite (plus_comm (nat_of_P q)); apply plus_lt_compat_l; + apply nat_of_P_lt_Lt_compare_morphism; + assumption + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + apply ZC1; assumption ] + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + apply ZC1; assumption ] + | assumption ] + | assumption ] + | simpl in |- *; apply nat_of_P_lt_Lt_compare_complement_morphism; + rewrite nat_of_P_minus_morphism; + [ rewrite nat_of_P_minus_morphism; + [ apply plus_lt_reg_l with (p := nat_of_P q); + rewrite le_plus_minus_r; + [ rewrite plus_comm; apply plus_lt_reg_l with (p := nat_of_P p); + rewrite plus_assoc; rewrite le_plus_minus_r; + [ rewrite (plus_comm (nat_of_P p)); apply plus_lt_compat_l; + apply nat_of_P_lt_Lt_compare_morphism; + apply ZC1; assumption + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + apply ZC1; assumption ] + | apply lt_le_weak; apply nat_of_P_lt_Lt_compare_morphism; + apply ZC1; assumption ] + | assumption ] + | assumption ] ] ]. Qed. Lemma Zcompare_plus_compat : forall n m p:Z, (p + n ?= p + m) = (n ?= m). Proof. -exact (weaken_Zcompare_Zplus_compatible weak_Zcompare_Zplus_compatible). + exact (weaken_Zcompare_Zplus_compatible weak_Zcompare_Zplus_compatible). Qed. Lemma Zplus_compare_compat : - forall (r:comparison) (n m p q:Z), - (n ?= m) = r -> (p ?= q) = r -> (n + p ?= m + q) = r. + forall (r:comparison) (n m p q:Z), + (n ?= m) = r -> (p ?= q) = r -> (n + p ?= m + q) = r. Proof. -intros r x y z t; case r; - [ intros H1 H2; elim (Zcompare_Eq_iff_eq x y); elim (Zcompare_Eq_iff_eq z t); - intros H3 H4 H5 H6; rewrite H3; - [ rewrite H5; - [ elim (Zcompare_Eq_iff_eq (y + t) (y + t)); auto with arith - | auto with arith ] - | auto with arith ] - | intros H1 H2; elim (Zcompare_Gt_Lt_antisym (y + t) (x + z)); intros H3 H4; - apply H3; apply Zcompare_Gt_trans with (m := y + z); - [ rewrite Zcompare_plus_compat; elim (Zcompare_Gt_Lt_antisym t z); - auto with arith - | do 2 rewrite <- (Zplus_comm z); rewrite Zcompare_plus_compat; - elim (Zcompare_Gt_Lt_antisym y x); auto with arith ] - | intros H1 H2; apply Zcompare_Gt_trans with (m := x + t); - [ rewrite Zcompare_plus_compat; assumption - | do 2 rewrite <- (Zplus_comm t); rewrite Zcompare_plus_compat; - assumption ] ]. + intros r x y z t; case r; + [ intros H1 H2; elim (Zcompare_Eq_iff_eq x y); elim (Zcompare_Eq_iff_eq z t); + intros H3 H4 H5 H6; rewrite H3; + [ rewrite H5; + [ elim (Zcompare_Eq_iff_eq (y + t) (y + t)); auto with arith + | auto with arith ] + | auto with arith ] + | intros H1 H2; elim (Zcompare_Gt_Lt_antisym (y + t) (x + z)); intros H3 H4; + apply H3; apply Zcompare_Gt_trans with (m := y + z); + [ rewrite Zcompare_plus_compat; elim (Zcompare_Gt_Lt_antisym t z); + auto with arith + | do 2 rewrite <- (Zplus_comm z); rewrite Zcompare_plus_compat; + elim (Zcompare_Gt_Lt_antisym y x); auto with arith ] + | intros H1 H2; apply Zcompare_Gt_trans with (m := x + t); + [ rewrite Zcompare_plus_compat; assumption + | do 2 rewrite <- (Zplus_comm t); rewrite Zcompare_plus_compat; + assumption ] ]. Qed. Lemma Zcompare_succ_Gt : forall n:Z, (Zsucc n ?= n) = Gt. Proof. -intro x; unfold Zsucc in |- *; pattern x at 2 in |- *; - rewrite <- (Zplus_0_r x); rewrite Zcompare_plus_compat; - reflexivity. + intro x; unfold Zsucc in |- *; pattern x at 2 in |- *; + rewrite <- (Zplus_0_r x); rewrite Zcompare_plus_compat; + reflexivity. Qed. Lemma Zcompare_Gt_not_Lt : forall n m:Z, (n ?= m) = Gt <-> (n ?= m + 1) <> Lt. Proof. -intros x y; split; - [ intro H; elim_compare x (y + 1); - [ intro H1; rewrite H1; discriminate - | intros H1; elim Zcompare_Gt_spec with (1 := H); intros h H2; - absurd ((nat_of_P h > 0)%nat /\ (nat_of_P h < 1)%nat); - [ unfold not in |- *; intros H3; elim H3; intros H4 H5; - absurd (nat_of_P h > 0)%nat; - [ unfold gt in |- *; apply le_not_lt; apply le_S_n; exact H5 - | assumption ] - | split; - [ elim (ZL4 h); intros i H3; rewrite H3; apply gt_Sn_O - | change (nat_of_P h < nat_of_P 1)%nat in |- *; - apply nat_of_P_lt_Lt_compare_morphism; - change ((Zpos h ?= 1) = Lt) in |- *; rewrite <- H2; - rewrite <- (fun m n:Z => Zcompare_plus_compat m n y); - rewrite (Zplus_comm x); rewrite Zplus_assoc; - rewrite Zplus_opp_r; simpl in |- *; exact H1 ] ] - | intros H1; rewrite H1; discriminate ] - | intros H; elim_compare x (y + 1); - [ intros H1; elim (Zcompare_Eq_iff_eq x (y + 1)); intros H2 H3; - rewrite (H2 H1); exact (Zcompare_succ_Gt y) - | intros H1; absurd ((x ?= y + 1) = Lt); assumption - | intros H1; apply Zcompare_Gt_trans with (m := Zsucc y); - [ exact H1 | exact (Zcompare_succ_Gt y) ] ] ]. + intros x y; split; + [ intro H; elim_compare x (y + 1); + [ intro H1; rewrite H1; discriminate + | intros H1; elim Zcompare_Gt_spec with (1 := H); intros h H2; + absurd ((nat_of_P h > 0)%nat /\ (nat_of_P h < 1)%nat); + [ unfold not in |- *; intros H3; elim H3; intros H4 H5; + absurd (nat_of_P h > 0)%nat; + [ unfold gt in |- *; apply le_not_lt; apply le_S_n; exact H5 + | assumption ] + | split; + [ elim (ZL4 h); intros i H3; rewrite H3; apply gt_Sn_O + | change (nat_of_P h < nat_of_P 1)%nat in |- *; + apply nat_of_P_lt_Lt_compare_morphism; + change ((Zpos h ?= 1) = Lt) in |- *; rewrite <- H2; + rewrite <- (fun m n:Z => Zcompare_plus_compat m n y); + rewrite (Zplus_comm x); rewrite Zplus_assoc; + rewrite Zplus_opp_r; simpl in |- *; exact H1 ] ] + | intros H1; rewrite H1; discriminate ] + | intros H; elim_compare x (y + 1); + [ intros H1; elim (Zcompare_Eq_iff_eq x (y + 1)); intros H2 H3; + rewrite (H2 H1); exact (Zcompare_succ_Gt y) + | intros H1; absurd ((x ?= y + 1) = Lt); assumption + | intros H1; apply Zcompare_Gt_trans with (m := Zsucc y); + [ exact H1 | exact (Zcompare_succ_Gt y) ] ] ]. Qed. -(** Successor and comparison *) +(** * Successor and comparison *) Lemma Zcompare_succ_compat : forall n m:Z, (Zsucc n ?= Zsucc m) = (n ?= m). Proof. -intros n m; unfold Zsucc in |- *; do 2 rewrite (fun t:Z => Zplus_comm t 1); - rewrite Zcompare_plus_compat; auto with arith. + intros n m; unfold Zsucc in |- *; do 2 rewrite (fun t:Z => Zplus_comm t 1); + rewrite Zcompare_plus_compat; auto with arith. Qed. -(** Multiplication and comparison *) +(** * Multiplication and comparison *) Lemma Zcompare_mult_compat : - forall (p:positive) (n m:Z), (Zpos p * n ?= Zpos p * m) = (n ?= m). + forall (p:positive) (n m:Z), (Zpos p * n ?= Zpos p * m) = (n ?= m). Proof. -intros x; induction x as [p H| p H| ]; - [ intros y z; cut (Zpos (xI p) = Zpos p + Zpos p + 1); - [ intros E; rewrite E; do 4 rewrite Zmult_plus_distr_l; - do 2 rewrite Zmult_1_l; apply Zplus_compare_compat; - [ apply Zplus_compare_compat; apply H | trivial with arith ] - | simpl in |- *; rewrite (Pplus_diag p); trivial with arith ] - | intros y z; cut (Zpos (xO p) = Zpos p + Zpos p); - [ intros E; rewrite E; do 2 rewrite Zmult_plus_distr_l; - apply Zplus_compare_compat; apply H - | simpl in |- *; rewrite (Pplus_diag p); trivial with arith ] - | intros y z; do 2 rewrite Zmult_1_l; trivial with arith ]. + intros x; induction x as [p H| p H| ]; + [ intros y z; cut (Zpos (xI p) = Zpos p + Zpos p + 1); + [ intros E; rewrite E; do 4 rewrite Zmult_plus_distr_l; + do 2 rewrite Zmult_1_l; apply Zplus_compare_compat; + [ apply Zplus_compare_compat; apply H | trivial with arith ] + | simpl in |- *; rewrite (Pplus_diag p); trivial with arith ] + | intros y z; cut (Zpos (xO p) = Zpos p + Zpos p); + [ intros E; rewrite E; do 2 rewrite Zmult_plus_distr_l; + apply Zplus_compare_compat; apply H + | simpl in |- *; rewrite (Pplus_diag p); trivial with arith ] + | intros y z; do 2 rewrite Zmult_1_l; trivial with arith ]. Qed. -(** Reverting [x ?= y] to trichotomy *) +(** * Reverting [x ?= y] to trichotomy *) Lemma rename : - forall (A:Type) (P:A -> Prop) (x:A), (forall y:A, x = y -> P y) -> P x. + forall (A:Type) (P:A -> Prop) (x:A), (forall y:A, x = y -> P y) -> P x. Proof. -auto with arith. + auto with arith. Qed. Lemma Zcompare_elim : - forall (c1 c2 c3:Prop) (n m:Z), - (n = m -> c1) -> - (n < m -> c2) -> - (n > m -> c3) -> match n ?= m with - | Eq => c1 - | Lt => c2 - | Gt => c3 - end. + forall (c1 c2 c3:Prop) (n m:Z), + (n = m -> c1) -> + (n < m -> c2) -> + (n > m -> c3) -> match n ?= m with + | Eq => c1 + | Lt => c2 + | Gt => c3 + end. Proof. -intros c1 c2 c3 x y; intros. -apply rename with (x := x ?= y); intro r; elim r; - [ intro; apply H; apply (Zcompare_Eq_eq x y); assumption - | unfold Zlt in H0; assumption - | unfold Zgt in H1; assumption ]. + intros c1 c2 c3 x y; intros. + apply rename with (x := x ?= y); intro r; elim r; + [ intro; apply H; apply (Zcompare_Eq_eq x y); assumption + | unfold Zlt in H0; assumption + | unfold Zgt in H1; assumption ]. Qed. Lemma Zcompare_eq_case : - forall (c1 c2 c3:Prop) (n m:Z), - c1 -> n = m -> match n ?= m with - | Eq => c1 - | Lt => c2 - | Gt => c3 - end. + forall (c1 c2 c3:Prop) (n m:Z), + c1 -> n = m -> match n ?= m with + | Eq => c1 + | Lt => c2 + | Gt => c3 + end. Proof. -intros c1 c2 c3 x y; intros. -rewrite H0; rewrite Zcompare_refl. -assumption. + intros c1 c2 c3 x y; intros. + rewrite H0; rewrite Zcompare_refl. + assumption. Qed. -(** Decompose an egality between two [?=] relations into 3 implications *) +(** * Decompose an egality between two [?=] relations into 3 implications *) Lemma Zcompare_egal_dec : - forall n m p q:Z, - (n < m -> p < q) -> - ((n ?= m) = Eq -> (p ?= q) = Eq) -> - (n > m -> p > q) -> (n ?= m) = (p ?= q). + forall n m p q:Z, + (n < m -> p < q) -> + ((n ?= m) = Eq -> (p ?= q) = Eq) -> + (n > m -> p > q) -> (n ?= m) = (p ?= q). Proof. -intros x1 y1 x2 y2. -unfold Zgt in |- *; unfold Zlt in |- *; case (x1 ?= y1); case (x2 ?= y2); - auto with arith; symmetry in |- *; auto with arith. + intros x1 y1 x2 y2. + unfold Zgt in |- *; unfold Zlt in |- *; case (x1 ?= y1); case (x2 ?= y2); + auto with arith; symmetry in |- *; auto with arith. Qed. -(** Relating [x ?= y] to [Zle], [Zlt], [Zge] or [Zgt] *) +(** * Relating [x ?= y] to [Zle], [Zlt], [Zge] or [Zgt] *) Lemma Zle_compare : - forall n m:Z, - n <= m -> match n ?= m with - | Eq => True - | Lt => True - | Gt => False - end. + forall n m:Z, + n <= m -> match n ?= m with + | Eq => True + | Lt => True + | Gt => False + end. Proof. -intros x y; unfold Zle in |- *; elim (x ?= y); auto with arith. + intros x y; unfold Zle in |- *; elim (x ?= y); auto with arith. Qed. Lemma Zlt_compare : - forall n m:Z, + forall n m:Z, n < m -> match n ?= m with - | Eq => False - | Lt => True - | Gt => False + | Eq => False + | Lt => True + | Gt => False end. Proof. -intros x y; unfold Zlt in |- *; elim (x ?= y); intros; - discriminate || trivial with arith. + intros x y; unfold Zlt in |- *; elim (x ?= y); intros; + discriminate || trivial with arith. Qed. Lemma Zge_compare : - forall n m:Z, - n >= m -> match n ?= m with - | Eq => True - | Lt => False - | Gt => True - end. + forall n m:Z, + n >= m -> match n ?= m with + | Eq => True + | Lt => False + | Gt => True + end. Proof. -intros x y; unfold Zge in |- *; elim (x ?= y); auto with arith. + intros x y; unfold Zge in |- *; elim (x ?= y); auto with arith. Qed. Lemma Zgt_compare : - forall n m:Z, - n > m -> match n ?= m with - | Eq => False - | Lt => False - | Gt => True - end. + forall n m:Z, + n > m -> match n ?= m with + | Eq => False + | Lt => False + | Gt => True + end. Proof. -intros x y; unfold Zgt in |- *; elim (x ?= y); intros; - discriminate || trivial with arith. + intros x y; unfold Zgt in |- *; elim (x ?= y); intros; + discriminate || trivial with arith. Qed. -(**********************************************************************) -(* Other properties *) - +(*********************) +(** * Other properties *) Lemma Zmult_compare_compat_l : - forall n m p:Z, p > 0 -> (n ?= m) = (p * n ?= p * m). + forall n m p:Z, p > 0 -> (n ?= m) = (p * n ?= p * m). Proof. -intros x y z H; destruct z. + intros x y z H; destruct z. discriminate H. rewrite Zcompare_mult_compat; reflexivity. discriminate H. Qed. Lemma Zmult_compare_compat_r : - forall n m p:Z, p > 0 -> (n ?= m) = (n * p ?= m * p). + forall n m p:Z, p > 0 -> (n ?= m) = (n * p ?= m * p). Proof. -intros x y z H; rewrite (Zmult_comm x z); rewrite (Zmult_comm y z); - apply Zmult_compare_compat_l; assumption. + intros x y z H; rewrite (Zmult_comm x z); rewrite (Zmult_comm y z); + apply Zmult_compare_compat_l; assumption. Qed. diff --git a/theories/ZArith/Zcomplements.v b/theories/ZArith/Zcomplements.v index 817fbc1b..78c8a976 100644 --- a/theories/ZArith/Zcomplements.v +++ b/theories/ZArith/Zcomplements.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zcomplements.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Zcomplements.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import ZArithRing. Require Import ZArith_base. @@ -19,27 +19,27 @@ Open Local Scope Z_scope. (** About parity *) Lemma two_or_two_plus_one : - forall n:Z, {y : Z | n = 2 * y} + {y : Z | n = 2 * y + 1}. + forall n:Z, {y : Z | n = 2 * y} + {y : Z | n = 2 * y + 1}. Proof. -intro x; destruct x. -left; split with 0; reflexivity. - -destruct p. -right; split with (Zpos p); reflexivity. - -left; split with (Zpos p); reflexivity. - -right; split with 0; reflexivity. - -destruct p. -right; split with (Zneg (1 + p)). -rewrite BinInt.Zneg_xI. -rewrite BinInt.Zneg_plus_distr. -omega. - -left; split with (Zneg p); reflexivity. - -right; split with (-1); reflexivity. + intro x; destruct x. + left; split with 0; reflexivity. + + destruct p. + right; split with (Zpos p); reflexivity. + + left; split with (Zpos p); reflexivity. + + right; split with 0; reflexivity. + + destruct p. + right; split with (Zneg (1 + p)). + rewrite BinInt.Zneg_xI. + rewrite BinInt.Zneg_plus_distr. + omega. + + left; split with (Zneg p); reflexivity. + + right; split with (-1); reflexivity. Qed. (**********************************************************************) @@ -50,109 +50,109 @@ Qed. Fixpoint floor_pos (a:positive) : positive := match a with - | xH => 1%positive - | xO a' => xO (floor_pos a') - | xI b' => xO (floor_pos b') + | xH => 1%positive + | xO a' => xO (floor_pos a') + | xI b' => xO (floor_pos b') end. Definition floor (a:positive) := Zpos (floor_pos a). Lemma floor_gt0 : forall p:positive, floor p > 0. Proof. -intro. -compute in |- *. -trivial. + intro. + compute in |- *. + trivial. Qed. Lemma floor_ok : forall p:positive, floor p <= Zpos p < 2 * floor p. Proof. -unfold floor in |- *. -intro a; induction a as [p| p| ]. - -simpl in |- *. -repeat rewrite BinInt.Zpos_xI. -rewrite (BinInt.Zpos_xO (xO (floor_pos p))). -rewrite (BinInt.Zpos_xO (floor_pos p)). -omega. - -simpl in |- *. -repeat rewrite BinInt.Zpos_xI. -rewrite (BinInt.Zpos_xO (xO (floor_pos p))). -rewrite (BinInt.Zpos_xO (floor_pos p)). -rewrite (BinInt.Zpos_xO p). -omega. - -simpl in |- *; omega. + unfold floor in |- *. + intro a; induction a as [p| p| ]. + + simpl in |- *. + repeat rewrite BinInt.Zpos_xI. + rewrite (BinInt.Zpos_xO (xO (floor_pos p))). + rewrite (BinInt.Zpos_xO (floor_pos p)). + omega. + + simpl in |- *. + repeat rewrite BinInt.Zpos_xI. + rewrite (BinInt.Zpos_xO (xO (floor_pos p))). + rewrite (BinInt.Zpos_xO (floor_pos p)). + rewrite (BinInt.Zpos_xO p). + omega. + + simpl in |- *; omega. Qed. (**********************************************************************) (** Two more induction principles over [Z]. *) Theorem Z_lt_abs_rec : - forall P:Z -> Set, - (forall n:Z, (forall m:Z, Zabs m < Zabs n -> P m) -> P n) -> - forall n:Z, P n. + forall P:Z -> Set, + (forall n:Z, (forall m:Z, Zabs m < Zabs n -> P m) -> P n) -> + forall n:Z, P n. Proof. -intros P HP p. -set (Q := fun z => 0 <= z -> P z * P (- z)) in *. -cut (Q (Zabs p)); [ intros | apply (Z_lt_rec Q); auto with zarith ]. -elim (Zabs_dec p); intro eq; rewrite eq; elim H; auto with zarith. -unfold Q in |- *; clear Q; intros. -apply pair; apply HP. -rewrite Zabs_eq; auto; intros. -elim (H (Zabs m)); intros; auto with zarith. -elim (Zabs_dec m); intro eq; rewrite eq; trivial. -rewrite Zabs_non_eq; auto with zarith. -rewrite Zopp_involutive; intros. -elim (H (Zabs m)); intros; auto with zarith. -elim (Zabs_dec m); intro eq; rewrite eq; trivial. + intros P HP p. + set (Q := fun z => 0 <= z -> P z * P (- z)) in *. + cut (Q (Zabs p)); [ intros | apply (Z_lt_rec Q); auto with zarith ]. + elim (Zabs_dec p); intro eq; rewrite eq; elim H; auto with zarith. + unfold Q in |- *; clear Q; intros. + apply pair; apply HP. + rewrite Zabs_eq; auto; intros. + elim (H (Zabs m)); intros; auto with zarith. + elim (Zabs_dec m); intro eq; rewrite eq; trivial. + rewrite Zabs_non_eq; auto with zarith. + rewrite Zopp_involutive; intros. + elim (H (Zabs m)); intros; auto with zarith. + elim (Zabs_dec m); intro eq; rewrite eq; trivial. Qed. Theorem Z_lt_abs_induction : - forall P:Z -> Prop, - (forall n:Z, (forall m:Z, Zabs m < Zabs n -> P m) -> P n) -> - forall n:Z, P n. + forall P:Z -> Prop, + (forall n:Z, (forall m:Z, Zabs m < Zabs n -> P m) -> P n) -> + forall n:Z, P n. Proof. -intros P HP p. -set (Q := fun z => 0 <= z -> P z /\ P (- z)) in *. -cut (Q (Zabs p)); [ intros | apply (Z_lt_induction Q); auto with zarith ]. -elim (Zabs_dec p); intro eq; rewrite eq; elim H; auto with zarith. -unfold Q in |- *; clear Q; intros. -split; apply HP. -rewrite Zabs_eq; auto; intros. -elim (H (Zabs m)); intros; auto with zarith. -elim (Zabs_dec m); intro eq; rewrite eq; trivial. -rewrite Zabs_non_eq; auto with zarith. -rewrite Zopp_involutive; intros. -elim (H (Zabs m)); intros; auto with zarith. -elim (Zabs_dec m); intro eq; rewrite eq; trivial. + intros P HP p. + set (Q := fun z => 0 <= z -> P z /\ P (- z)) in *. + cut (Q (Zabs p)); [ intros | apply (Z_lt_induction Q); auto with zarith ]. + elim (Zabs_dec p); intro eq; rewrite eq; elim H; auto with zarith. + unfold Q in |- *; clear Q; intros. + split; apply HP. + rewrite Zabs_eq; auto; intros. + elim (H (Zabs m)); intros; auto with zarith. + elim (Zabs_dec m); intro eq; rewrite eq; trivial. + rewrite Zabs_non_eq; auto with zarith. + rewrite Zopp_involutive; intros. + elim (H (Zabs m)); intros; auto with zarith. + elim (Zabs_dec m); intro eq; rewrite eq; trivial. Qed. (** To do case analysis over the sign of [z] *) Lemma Zcase_sign : - forall (n:Z) (P:Prop), (n = 0 -> P) -> (n > 0 -> P) -> (n < 0 -> P) -> P. + forall (n:Z) (P:Prop), (n = 0 -> P) -> (n > 0 -> P) -> (n < 0 -> P) -> P. Proof. -intros x P Hzero Hpos Hneg. -induction x as [| p| p]. -apply Hzero; trivial. -apply Hpos; apply Zorder.Zgt_pos_0. -apply Hneg; apply Zorder.Zlt_neg_0. + intros x P Hzero Hpos Hneg. + induction x as [| p| p]. + apply Hzero; trivial. + apply Hpos; apply Zorder.Zgt_pos_0. + apply Hneg; apply Zorder.Zlt_neg_0. Qed. Lemma sqr_pos : forall n:Z, n * n >= 0. Proof. -intro x. -apply (Zcase_sign x (x * x >= 0)). -intros H; rewrite H; omega. -intros H; replace 0 with (0 * 0). -apply Zmult_ge_compat; omega. -omega. -intros H; replace 0 with (0 * 0). -replace (x * x) with (- x * - x). -apply Zmult_ge_compat; omega. -ring. -omega. + intro x. + apply (Zcase_sign x (x * x >= 0)). + intros H; rewrite H; omega. + intros H; replace 0 with (0 * 0). + apply Zmult_ge_compat; omega. + omega. + intros H; replace 0 with (0 * 0). + replace (x * x) with (- x * - x). + apply Zmult_ge_compat; omega. + ring. + omega. Qed. (**********************************************************************) @@ -162,8 +162,8 @@ Require Import List. Fixpoint Zlength_aux (acc:Z) (A:Set) (l:list A) {struct l} : Z := match l with - | nil => acc - | _ :: l => Zlength_aux (Zsucc acc) A l + | nil => acc + | _ :: l => Zlength_aux (Zsucc acc) A l end. Definition Zlength := Zlength_aux 0. @@ -171,42 +171,42 @@ Implicit Arguments Zlength [A]. Section Zlength_properties. -Variable A : Set. - -Implicit Type l : list A. - -Lemma Zlength_correct : forall l, Zlength l = Z_of_nat (length l). -Proof. -assert (forall l (acc:Z), Zlength_aux acc A l = acc + Z_of_nat (length l)). -simple induction l. -simpl in |- *; auto with zarith. -intros; simpl (length (a :: l0)) in |- *; rewrite Znat.inj_S. -simpl in |- *; rewrite H; auto with zarith. -unfold Zlength in |- *; intros; rewrite H; auto. -Qed. - -Lemma Zlength_nil : Zlength (A:=A) nil = 0. -Proof. -auto. -Qed. - -Lemma Zlength_cons : forall (x:A) l, Zlength (x :: l) = Zsucc (Zlength l). -Proof. -intros; do 2 rewrite Zlength_correct. -simpl (length (x :: l)) in |- *; rewrite Znat.inj_S; auto. -Qed. - -Lemma Zlength_nil_inv : forall l, Zlength l = 0 -> l = nil. -Proof. -intro l; rewrite Zlength_correct. -case l; auto. -intros x l'; simpl (length (x :: l')) in |- *. -rewrite Znat.inj_S. -intros; elimtype False; generalize (Zle_0_nat (length l')); omega. -Qed. + Variable A : Set. + + Implicit Type l : list A. + + Lemma Zlength_correct : forall l, Zlength l = Z_of_nat (length l). + Proof. + assert (forall l (acc:Z), Zlength_aux acc A l = acc + Z_of_nat (length l)). + simple induction l. + simpl in |- *; auto with zarith. + intros; simpl (length (a :: l0)) in |- *; rewrite Znat.inj_S. + simpl in |- *; rewrite H; auto with zarith. + unfold Zlength in |- *; intros; rewrite H; auto. + Qed. + + Lemma Zlength_nil : Zlength (A:=A) nil = 0. + Proof. + auto. + Qed. + + Lemma Zlength_cons : forall (x:A) l, Zlength (x :: l) = Zsucc (Zlength l). + Proof. + intros; do 2 rewrite Zlength_correct. + simpl (length (x :: l)) in |- *; rewrite Znat.inj_S; auto. + Qed. + + Lemma Zlength_nil_inv : forall l, Zlength l = 0 -> l = nil. + Proof. + intro l; rewrite Zlength_correct. + case l; auto. + intros x l'; simpl (length (x :: l')) in |- *. + rewrite Znat.inj_S. + intros; elimtype False; generalize (Zle_0_nat (length l')); omega. + Qed. End Zlength_properties. Implicit Arguments Zlength_correct [A]. Implicit Arguments Zlength_cons [A]. -Implicit Arguments Zlength_nil_inv [A]. \ No newline at end of file +Implicit Arguments Zlength_nil_inv [A]. diff --git a/theories/ZArith/Zdiv.v b/theories/ZArith/Zdiv.v index e391d087..31f68207 100644 --- a/theories/ZArith/Zdiv.v +++ b/theories/ZArith/Zdiv.v @@ -6,17 +6,14 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zdiv.v 6295 2004-11-12 16:40:39Z gregoire $ i*) +(*i $Id: Zdiv.v 9245 2006-10-17 12:53:34Z notin $ i*) (* Contribution by Claude Marché and Xavier Urbain *) -(** - -Euclidean Division - -Defines first of function that allows Coq to normalize. -Then only after proves the main required property. +(** Euclidean Division + Defines first of function that allows Coq to normalize. + Then only after proves the main required property. *) Require Export ZArith_base. @@ -26,40 +23,37 @@ Require Import ZArithRing. Require Import Zcomplements. Open Local Scope Z_scope. -(** +(** * Definitions of Euclidian operations *) - Euclidean division of a positive by a integer - (that is supposed to be positive). +(** Euclidean division of a positive by a integer + (that is supposed to be positive). - total function than returns an arbitrary value when - divisor is not positive + Total function than returns an arbitrary value when + divisor is not positive *) Unboxed Fixpoint Zdiv_eucl_POS (a:positive) (b:Z) {struct a} : - Z * Z := + Z * Z := match a with - | xH => if Zge_bool b 2 then (0, 1) else (1, 0) - | xO a' => + | xH => if Zge_bool b 2 then (0, 1) else (1, 0) + | xO a' => let (q, r) := Zdiv_eucl_POS a' b in - let r' := 2 * r in - if Zgt_bool b r' then (2 * q, r') else (2 * q + 1, r' - b) - | xI a' => + let r' := 2 * r in + if Zgt_bool b r' then (2 * q, r') else (2 * q + 1, r' - b) + | xI a' => let (q, r) := Zdiv_eucl_POS a' b in - let r' := 2 * r + 1 in - if Zgt_bool b r' then (2 * q, r') else (2 * q + 1, r' - b) + let r' := 2 * r + 1 in + if Zgt_bool b r' then (2 * q, r') else (2 * q + 1, r' - b) end. -(** - - Euclidean division of integers. +(** Euclidean division of integers. - Total function than returns (0,0) when dividing by 0. - + Total function than returns (0,0) when dividing by 0. *) -(* +(** The pseudo-code is: @@ -82,22 +76,22 @@ Unboxed Fixpoint Zdiv_eucl_POS (a:positive) (b:Z) {struct a} : Definition Zdiv_eucl (a b:Z) : Z * Z := match a, b with - | Z0, _ => (0, 0) - | _, Z0 => (0, 0) - | Zpos a', Zpos _ => Zdiv_eucl_POS a' b - | Zneg a', Zpos _ => + | Z0, _ => (0, 0) + | _, Z0 => (0, 0) + | Zpos a', Zpos _ => Zdiv_eucl_POS a' b + | Zneg a', Zpos _ => let (q, r) := Zdiv_eucl_POS a' b in - match r with - | Z0 => (- q, 0) - | _ => (- (q + 1), b - r) - end - | Zneg a', Zneg b' => let (q, r) := Zdiv_eucl_POS a' (Zpos b') in (q, - r) - | Zpos a', Zneg b' => + match r with + | Z0 => (- q, 0) + | _ => (- (q + 1), b - r) + end + | Zneg a', Zneg b' => let (q, r) := Zdiv_eucl_POS a' (Zpos b') in (q, - r) + | Zpos a', Zneg b' => let (q, r) := Zdiv_eucl_POS a' (Zpos b') in - match r with - | Z0 => (- q, 0) - | _ => (- (q + 1), b + r) - end + match r with + | Z0 => (- q, 0) + | _ => (- (q + 1), b + r) + end end. @@ -107,6 +101,11 @@ Definition Zdiv (a b:Z) : Z := let (q, _) := Zdiv_eucl a b in q. Definition Zmod (a b:Z) : Z := let (_, r) := Zdiv_eucl a b in r. +(** Syntax *) + +Infix "/" := Zdiv : Z_scope. +Infix "mod" := Zmod (at level 40, no associativity) : Z_scope. + (* Tests: Eval Compute in `(Zdiv_eucl 7 3)`. @@ -120,19 +119,15 @@ Eval Compute in `(Zdiv_eucl (-7) (-3))`. *) -(** - - Main division theorem. - - First a lemma for positive +(** * Main division theorem *) -*) +(** First a lemma for positive *) Lemma Z_div_mod_POS : - forall b:Z, - b > 0 -> - forall a:positive, - let (q, r) := Zdiv_eucl_POS a b in Zpos a = b * q + r /\ 0 <= r < b. + forall b:Z, + b > 0 -> + forall a:positive, + let (q, r) := Zdiv_eucl_POS a b in Zpos a = b * q + r /\ 0 <= r < b. Proof. simple induction a; unfold Zdiv_eucl_POS in |- *; fold Zdiv_eucl_POS in |- *. @@ -148,276 +143,269 @@ case (Zgt_bool b (2 * r)); rewrite BinInt.Zpos_xO; (split; [ ring | omega ]). generalize (Zge_cases b 2). -case (Zge_bool b 2); (intros; split; [ ring | omega ]). +case (Zge_bool b 2); (intros; split; [ try ring | omega ]). omega. Qed. Theorem Z_div_mod : - forall a b:Z, - b > 0 -> let (q, r) := Zdiv_eucl a b in a = b * q + r /\ 0 <= r < b. + forall a b:Z, + b > 0 -> let (q, r) := Zdiv_eucl a b in a = b * q + r /\ 0 <= r < b. Proof. -intros a b; case a; case b; try (simpl in |- *; intros; omega). -unfold Zdiv_eucl in |- *; intros; apply Z_div_mod_POS; trivial. - -intros; discriminate. - -intros. -generalize (Z_div_mod_POS (Zpos p) H p0). -unfold Zdiv_eucl in |- *. -case (Zdiv_eucl_POS p0 (Zpos p)). -intros z z0. -case z0. - -intros [H1 H2]. -split; trivial. -replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. - -intros p1 [H1 H2]. -split; trivial. -replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. -generalize (Zorder.Zgt_pos_0 p1); omega. - -intros p1 [H1 H2]. -split; trivial. -replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. -generalize (Zorder.Zlt_neg_0 p1); omega. - -intros; discriminate. + intros a b; case a; case b; try (simpl in |- *; intros; omega). + unfold Zdiv_eucl in |- *; intros; apply Z_div_mod_POS; trivial. + + intros; discriminate. + + intros. + generalize (Z_div_mod_POS (Zpos p) H p0). + unfold Zdiv_eucl in |- *. + case (Zdiv_eucl_POS p0 (Zpos p)). + intros z z0. + case z0. + + intros [H1 H2]. + split; trivial. + replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. + + intros p1 [H1 H2]. + split; trivial. + replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. + generalize (Zorder.Zgt_pos_0 p1); omega. + + intros p1 [H1 H2]. + split; trivial. + replace (Zneg p0) with (- Zpos p0); [ rewrite H1; ring | trivial ]. + generalize (Zorder.Zlt_neg_0 p1); omega. + + intros; discriminate. Qed. (** Existence theorems *) Theorem Zdiv_eucl_exist : - forall b:Z, - b > 0 -> - forall a:Z, {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < b}. + forall b:Z, + b > 0 -> + forall a:Z, {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < b}. Proof. -intros b Hb a. -exists (Zdiv_eucl a b). -exact (Z_div_mod a b Hb). + intros b Hb a. + exists (Zdiv_eucl a b). + exact (Z_div_mod a b Hb). Qed. Implicit Arguments Zdiv_eucl_exist. Theorem Zdiv_eucl_extended : - forall b:Z, - b <> 0 -> - forall a:Z, - {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Zabs b}. + forall b:Z, + b <> 0 -> + forall a:Z, + {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Zabs b}. Proof. -intros b Hb a. -elim (Z_le_gt_dec 0 b); intro Hb'. -cut (b > 0); [ intro Hb'' | omega ]. -rewrite Zabs_eq; [ apply Zdiv_eucl_exist; assumption | assumption ]. -cut (- b > 0); [ intro Hb'' | omega ]. -elim (Zdiv_eucl_exist Hb'' a); intros qr. -elim qr; intros q r Hqr. -exists (- q, r). -elim Hqr; intros. -split. -rewrite <- Zmult_opp_comm; assumption. -rewrite Zabs_non_eq; [ assumption | omega ]. + intros b Hb a. + elim (Z_le_gt_dec 0 b); intro Hb'. + cut (b > 0); [ intro Hb'' | omega ]. + rewrite Zabs_eq; [ apply Zdiv_eucl_exist; assumption | assumption ]. + cut (- b > 0); [ intro Hb'' | omega ]. + elim (Zdiv_eucl_exist Hb'' a); intros qr. + elim qr; intros q r Hqr. + exists (- q, r). + elim Hqr; intros. + split. + rewrite <- Zmult_opp_comm; assumption. + rewrite Zabs_non_eq; [ assumption | omega ]. Qed. Implicit Arguments Zdiv_eucl_extended. -(** Auxiliary lemmas about [Zdiv] and [Zmod] *) +(** * Auxiliary lemmas about [Zdiv] and [Zmod] *) Lemma Z_div_mod_eq : forall a b:Z, b > 0 -> a = b * Zdiv a b + Zmod a b. Proof. -unfold Zdiv, Zmod in |- *. -intros a b Hb. -generalize (Z_div_mod a b Hb). -case Zdiv_eucl; tauto. + unfold Zdiv, Zmod in |- *. + intros a b Hb. + generalize (Z_div_mod a b Hb). + case Zdiv_eucl; tauto. Qed. Lemma Z_mod_lt : forall a b:Z, b > 0 -> 0 <= Zmod a b < b. Proof. -unfold Zmod in |- *. -intros a b Hb. -generalize (Z_div_mod a b Hb). -case (Zdiv_eucl a b); tauto. + unfold Zmod in |- *. + intros a b Hb. + generalize (Z_div_mod a b Hb). + case (Zdiv_eucl a b); tauto. Qed. Lemma Z_div_POS_ge0 : - forall (b:Z) (a:positive), let (q, _) := Zdiv_eucl_POS a b in q >= 0. + forall (b:Z) (a:positive), let (q, _) := Zdiv_eucl_POS a b in q >= 0. Proof. -simple induction a; unfold Zdiv_eucl_POS in |- *; fold Zdiv_eucl_POS in |- *. -intro p; case (Zdiv_eucl_POS p b). -intros; case (Zgt_bool b (2 * z0 + 1)); intros; omega. -intro p; case (Zdiv_eucl_POS p b). -intros; case (Zgt_bool b (2 * z0)); intros; omega. -case (Zge_bool b 2); simpl in |- *; omega. + simple induction a; unfold Zdiv_eucl_POS in |- *; fold Zdiv_eucl_POS in |- *. + intro p; case (Zdiv_eucl_POS p b). + intros; case (Zgt_bool b (2 * z0 + 1)); intros; omega. + intro p; case (Zdiv_eucl_POS p b). + intros; case (Zgt_bool b (2 * z0)); intros; omega. + case (Zge_bool b 2); simpl in |- *; omega. Qed. Lemma Z_div_ge0 : forall a b:Z, b > 0 -> a >= 0 -> Zdiv a b >= 0. Proof. -intros a b Hb; unfold Zdiv, Zdiv_eucl in |- *; case a; simpl in |- *; intros. -case b; simpl in |- *; trivial. -generalize Hb; case b; try trivial. -auto with zarith. -intros p0 Hp0; generalize (Z_div_POS_ge0 (Zpos p0) p). -case (Zdiv_eucl_POS p (Zpos p0)); simpl in |- *; tauto. -intros; discriminate. -elim H; trivial. + intros a b Hb; unfold Zdiv, Zdiv_eucl in |- *; case a; simpl in |- *; intros. + case b; simpl in |- *; trivial. + generalize Hb; case b; try trivial. + auto with zarith. + intros p0 Hp0; generalize (Z_div_POS_ge0 (Zpos p0) p). + case (Zdiv_eucl_POS p (Zpos p0)); simpl in |- *; tauto. + intros; discriminate. + elim H; trivial. Qed. Lemma Z_div_lt : forall a b:Z, b >= 2 -> a > 0 -> Zdiv a b < a. Proof. -intros. cut (b > 0); [ intro Hb | omega ]. -generalize (Z_div_mod a b Hb). -cut (a >= 0); [ intro Ha | omega ]. -generalize (Z_div_ge0 a b Hb Ha). -unfold Zdiv in |- *; case (Zdiv_eucl a b); intros q r H1 [H2 H3]. -cut (a >= 2 * q -> q < a); [ intro h; apply h; clear h | intros; omega ]. -apply Zge_trans with (b * q). -omega. -auto with zarith. + intros. cut (b > 0); [ intro Hb | omega ]. + generalize (Z_div_mod a b Hb). + cut (a >= 0); [ intro Ha | omega ]. + generalize (Z_div_ge0 a b Hb Ha). + unfold Zdiv in |- *; case (Zdiv_eucl a b); intros q r H1 [H2 H3]. + cut (a >= 2 * q -> q < a); [ intro h; apply h; clear h | intros; omega ]. + apply Zge_trans with (b * q). + omega. + auto with zarith. Qed. -(** Syntax *) - - - -Infix "/" := Zdiv : Z_scope. -Infix "mod" := Zmod (at level 40, no associativity) : Z_scope. - -(** Other lemmas (now using the syntax for [Zdiv] and [Zmod]). *) +(** * Other lemmas (now using the syntax for [Zdiv] and [Zmod]). *) Lemma Z_div_ge : forall a b c:Z, c > 0 -> a >= b -> a / c >= b / c. Proof. -intros a b c cPos aGeb. -generalize (Z_div_mod_eq a c cPos). -generalize (Z_mod_lt a c cPos). -generalize (Z_div_mod_eq b c cPos). -generalize (Z_mod_lt b c cPos). -intros. -elim (Z_ge_lt_dec (a / c) (b / c)); trivial. -intro. -absurd (b - a >= 1). -omega. -rewrite H0. -rewrite H2. -assert - (c * (b / c) + b mod c - (c * (a / c) + a mod c) = - c * (b / c - a / c) + b mod c - a mod c). -ring. -rewrite H3. -assert (c * (b / c - a / c) >= c * 1). -apply Zmult_ge_compat_l. -omega. -omega. -assert (c * 1 = c). -ring. -omega. + intros a b c cPos aGeb. + generalize (Z_div_mod_eq a c cPos). + generalize (Z_mod_lt a c cPos). + generalize (Z_div_mod_eq b c cPos). + generalize (Z_mod_lt b c cPos). + intros. + elim (Z_ge_lt_dec (a / c) (b / c)); trivial. + intro. + absurd (b - a >= 1). + omega. + rewrite H0. + rewrite H2. + assert + (c * (b / c) + b mod c - (c * (a / c) + a mod c) = + c * (b / c - a / c) + b mod c - a mod c). + ring. + rewrite H3. + assert (c * (b / c - a / c) >= c * 1). + apply Zmult_ge_compat_l. + omega. + omega. + assert (c * 1 = c). + ring. + omega. Qed. Lemma Z_mod_plus : forall a b c:Z, c > 0 -> (a + b * c) mod c = a mod c. Proof. -intros a b c cPos. -generalize (Z_div_mod_eq a c cPos). -generalize (Z_mod_lt a c cPos). -generalize (Z_div_mod_eq (a + b * c) c cPos). -generalize (Z_mod_lt (a + b * c) c cPos). -intros. - -assert ((a + b * c) mod c - a mod c = c * (b + a / c - (a + b * c) / c)). -replace ((a + b * c) mod c) with (a + b * c - c * ((a + b * c) / c)). -replace (a mod c) with (a - c * (a / c)). -ring. -omega. -omega. -set (q := b + a / c - (a + b * c) / c) in *. -apply (Zcase_sign q); intros. -assert (c * q = 0). -rewrite H4; ring. -rewrite H5 in H3. -omega. - -assert (c * q >= c). -pattern c at 2 in |- *; replace c with (c * 1). -apply Zmult_ge_compat_l; omega. -ring. -omega. - -assert (c * q <= - c). -replace (- c) with (c * -1). -apply Zmult_le_compat_l; omega. -ring. -omega. + intros a b c cPos. + generalize (Z_div_mod_eq a c cPos). + generalize (Z_mod_lt a c cPos). + generalize (Z_div_mod_eq (a + b * c) c cPos). + generalize (Z_mod_lt (a + b * c) c cPos). + intros. + + assert ((a + b * c) mod c - a mod c = c * (b + a / c - (a + b * c) / c)). + replace ((a + b * c) mod c) with (a + b * c - c * ((a + b * c) / c)). + replace (a mod c) with (a - c * (a / c)). + ring. + omega. + omega. + set (q := b + a / c - (a + b * c) / c) in *. + apply (Zcase_sign q); intros. + assert (c * q = 0). + rewrite H4; ring. + rewrite H5 in H3. + omega. + + assert (c * q >= c). + pattern c at 2 in |- *; replace c with (c * 1). + apply Zmult_ge_compat_l; omega. + ring. + omega. + + assert (c * q <= - c). + replace (- c) with (c * -1). + apply Zmult_le_compat_l; omega. + ring. + omega. Qed. Lemma Z_div_plus : forall a b c:Z, c > 0 -> (a + b * c) / c = a / c + b. Proof. -intros a b c cPos. -generalize (Z_div_mod_eq a c cPos). -generalize (Z_mod_lt a c cPos). -generalize (Z_div_mod_eq (a + b * c) c cPos). -generalize (Z_mod_lt (a + b * c) c cPos). -intros. -apply Zmult_reg_l with c. omega. -replace (c * ((a + b * c) / c)) with (a + b * c - (a + b * c) mod c). -rewrite (Z_mod_plus a b c cPos). -pattern a at 1 in |- *; rewrite H2. -ring. -pattern (a + b * c) at 1 in |- *; rewrite H0. -ring. + intros a b c cPos. + generalize (Z_div_mod_eq a c cPos). + generalize (Z_mod_lt a c cPos). + generalize (Z_div_mod_eq (a + b * c) c cPos). + generalize (Z_mod_lt (a + b * c) c cPos). + intros. + apply Zmult_reg_l with c. omega. + replace (c * ((a + b * c) / c)) with (a + b * c - (a + b * c) mod c). + rewrite (Z_mod_plus a b c cPos). + pattern a at 1 in |- *; rewrite H2. + ring. + pattern (a + b * c) at 1 in |- *; rewrite H0. + ring. Qed. Lemma Z_div_mult : forall a b:Z, b > 0 -> a * b / b = a. -intros; replace (a * b) with (0 + a * b); auto. -rewrite Z_div_plus; auto. + intros; replace (a * b) with (0 + a * b); auto. + rewrite Z_div_plus; auto. Qed. Lemma Z_mult_div_ge : forall a b:Z, b > 0 -> b * (a / b) <= a. Proof. -intros a b bPos. -generalize (Z_div_mod_eq a _ bPos); intros. -generalize (Z_mod_lt a _ bPos); intros. -pattern a at 2 in |- *; rewrite H. -omega. + intros a b bPos. + generalize (Z_div_mod_eq a _ bPos); intros. + generalize (Z_mod_lt a _ bPos); intros. + pattern a at 2 in |- *; rewrite H. + omega. Qed. Lemma Z_mod_same : forall a:Z, a > 0 -> a mod a = 0. Proof. -intros a aPos. -generalize (Z_mod_plus 0 1 a aPos). -replace (0 + 1 * a) with a. -intros. -rewrite H. -compute in |- *. -trivial. -ring. + intros a aPos. + generalize (Z_mod_plus 0 1 a aPos). + replace (0 + 1 * a) with a. + intros. + rewrite H. + compute in |- *. + trivial. + ring. Qed. Lemma Z_div_same : forall a:Z, a > 0 -> a / a = 1. Proof. -intros a aPos. -generalize (Z_div_plus 0 1 a aPos). -replace (0 + 1 * a) with a. -intros. -rewrite H. -compute in |- *. -trivial. -ring. + intros a aPos. + generalize (Z_div_plus 0 1 a aPos). + replace (0 + 1 * a) with a. + intros. + rewrite H. + compute in |- *. + trivial. + ring. Qed. Lemma Z_div_exact_1 : forall a b:Z, b > 0 -> a = b * (a / b) -> a mod b = 0. -intros a b Hb; generalize (Z_div_mod a b Hb); unfold Zmod, Zdiv in |- *. -case (Zdiv_eucl a b); intros q r; omega. + intros a b Hb; generalize (Z_div_mod a b Hb); unfold Zmod, Zdiv in |- *. + case (Zdiv_eucl a b); intros q r; omega. Qed. Lemma Z_div_exact_2 : forall a b:Z, b > 0 -> a mod b = 0 -> a = b * (a / b). -intros a b Hb; generalize (Z_div_mod a b Hb); unfold Zmod, Zdiv in |- *. -case (Zdiv_eucl a b); intros q r; omega. + intros a b Hb; generalize (Z_div_mod a b Hb); unfold Zmod, Zdiv in |- *. + case (Zdiv_eucl a b); intros q r; omega. Qed. Lemma Z_mod_zero_opp : forall a b:Z, b > 0 -> a mod b = 0 -> - a mod b = 0. -intros a b Hb. -intros. -rewrite Z_div_exact_2 with a b; auto. -replace (- (b * (a / b))) with (0 + - (a / b) * b). -rewrite Z_mod_plus; auto. -ring. + intros a b Hb. + intros. + rewrite Z_div_exact_2 with a b; auto. + replace (- (b * (a / b))) with (0 + - (a / b) * b). + rewrite Z_mod_plus; auto. + ring. Qed. diff --git a/theories/ZArith/Zeven.v b/theories/ZArith/Zeven.v index 72d2d828..6fab4461 100644 --- a/theories/ZArith/Zeven.v +++ b/theories/ZArith/Zeven.v @@ -6,199 +6,203 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zeven.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Zeven.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import BinInt. -(**********************************************************************) +(*******************************************************************) (** About parity: even and odd predicates on Z, division by 2 on Z *) -(**********************************************************************) -(** [Zeven], [Zodd], [Zdiv2] and their related properties *) +(***************************************************) +(** * [Zeven], [Zodd] and their related properties *) Definition Zeven (z:Z) := match z with - | Z0 => True - | Zpos (xO _) => True - | Zneg (xO _) => True - | _ => False + | Z0 => True + | Zpos (xO _) => True + | Zneg (xO _) => True + | _ => False end. Definition Zodd (z:Z) := match z with - | Zpos xH => True - | Zneg xH => True - | Zpos (xI _) => True - | Zneg (xI _) => True - | _ => False + | Zpos xH => True + | Zneg xH => True + | Zpos (xI _) => True + | Zneg (xI _) => True + | _ => False end. Definition Zeven_bool (z:Z) := match z with - | Z0 => true - | Zpos (xO _) => true - | Zneg (xO _) => true - | _ => false + | Z0 => true + | Zpos (xO _) => true + | Zneg (xO _) => true + | _ => false end. Definition Zodd_bool (z:Z) := match z with - | Z0 => false - | Zpos (xO _) => false - | Zneg (xO _) => false - | _ => true + | Z0 => false + | Zpos (xO _) => false + | Zneg (xO _) => false + | _ => true end. Definition Zeven_odd_dec : forall z:Z, {Zeven z} + {Zodd z}. Proof. intro z. case z; [ left; compute in |- *; trivial - | intro p; case p; intros; - (right; compute in |- *; exact I) || (left; compute in |- *; exact I) - | intro p; case p; intros; - (right; compute in |- *; exact I) || (left; compute in |- *; exact I) ]. + | intro p; case p; intros; + (right; compute in |- *; exact I) || (left; compute in |- *; exact I) + | intro p; case p; intros; + (right; compute in |- *; exact I) || (left; compute in |- *; exact I) ]. Defined. Definition Zeven_dec : forall z:Z, {Zeven z} + {~ Zeven z}. Proof. intro z. case z; [ left; compute in |- *; trivial - | intro p; case p; intros; - (left; compute in |- *; exact I) || (right; compute in |- *; trivial) - | intro p; case p; intros; - (left; compute in |- *; exact I) || (right; compute in |- *; trivial) ]. + | intro p; case p; intros; + (left; compute in |- *; exact I) || (right; compute in |- *; trivial) + | intro p; case p; intros; + (left; compute in |- *; exact I) || (right; compute in |- *; trivial) ]. Defined. Definition Zodd_dec : forall z:Z, {Zodd z} + {~ Zodd z}. Proof. intro z. case z; [ right; compute in |- *; trivial - | intro p; case p; intros; - (left; compute in |- *; exact I) || (right; compute in |- *; trivial) - | intro p; case p; intros; - (left; compute in |- *; exact I) || (right; compute in |- *; trivial) ]. + | intro p; case p; intros; + (left; compute in |- *; exact I) || (right; compute in |- *; trivial) + | intro p; case p; intros; + (left; compute in |- *; exact I) || (right; compute in |- *; trivial) ]. Defined. Lemma Zeven_not_Zodd : forall n:Z, Zeven n -> ~ Zodd n. Proof. intro z; destruct z; [ idtac | destruct p | destruct p ]; compute in |- *; - trivial. + trivial. Qed. Lemma Zodd_not_Zeven : forall n:Z, Zodd n -> ~ Zeven n. Proof. intro z; destruct z; [ idtac | destruct p | destruct p ]; compute in |- *; - trivial. + trivial. Qed. Lemma Zeven_Sn : forall n:Z, Zodd n -> Zeven (Zsucc n). Proof. - intro z; destruct z; unfold Zsucc in |- *; - [ idtac | destruct p | destruct p ]; simpl in |- *; - trivial. - unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. + intro z; destruct z; unfold Zsucc in |- *; + [ idtac | destruct p | destruct p ]; simpl in |- *; + trivial. + unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. Qed. Lemma Zodd_Sn : forall n:Z, Zeven n -> Zodd (Zsucc n). Proof. - intro z; destruct z; unfold Zsucc in |- *; - [ idtac | destruct p | destruct p ]; simpl in |- *; - trivial. - unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. + intro z; destruct z; unfold Zsucc in |- *; + [ idtac | destruct p | destruct p ]; simpl in |- *; + trivial. + unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. Qed. Lemma Zeven_pred : forall n:Z, Zodd n -> Zeven (Zpred n). Proof. - intro z; destruct z; unfold Zpred in |- *; - [ idtac | destruct p | destruct p ]; simpl in |- *; - trivial. - unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. + intro z; destruct z; unfold Zpred in |- *; + [ idtac | destruct p | destruct p ]; simpl in |- *; + trivial. + unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. Qed. Lemma Zodd_pred : forall n:Z, Zeven n -> Zodd (Zpred n). Proof. - intro z; destruct z; unfold Zpred in |- *; - [ idtac | destruct p | destruct p ]; simpl in |- *; - trivial. - unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. + intro z; destruct z; unfold Zpred in |- *; + [ idtac | destruct p | destruct p ]; simpl in |- *; + trivial. + unfold Pdouble_minus_one in |- *; case p; simpl in |- *; auto. Qed. Hint Unfold Zeven Zodd: zarith. -(**********************************************************************) + +(******************************************************************) +(** * Definition of [Zdiv2] and properties wrt [Zeven] and [Zodd] *) + (** [Zdiv2] is defined on all [Z], but notice that for odd negative - integers it is not the euclidean quotient: in that case we have [n = - 2*(n/2)-1] *) + integers it is not the euclidean quotient: in that case we have + [n = 2*(n/2)-1] *) Definition Zdiv2 (z:Z) := match z with - | Z0 => 0%Z - | Zpos xH => 0%Z - | Zpos p => Zpos (Pdiv2 p) - | Zneg xH => 0%Z - | Zneg p => Zneg (Pdiv2 p) + | Z0 => 0%Z + | Zpos xH => 0%Z + | Zpos p => Zpos (Pdiv2 p) + | Zneg xH => 0%Z + | Zneg p => Zneg (Pdiv2 p) end. Lemma Zeven_div2 : forall n:Z, Zeven n -> n = (2 * Zdiv2 n)%Z. Proof. -intro x; destruct x. -auto with arith. -destruct p; auto with arith. -intros. absurd (Zeven (Zpos (xI p))); red in |- *; auto with arith. -intros. absurd (Zeven 1); red in |- *; auto with arith. -destruct p; auto with arith. -intros. absurd (Zeven (Zneg (xI p))); red in |- *; auto with arith. -intros. absurd (Zeven (-1)); red in |- *; auto with arith. + intro x; destruct x. + auto with arith. + destruct p; auto with arith. + intros. absurd (Zeven (Zpos (xI p))); red in |- *; auto with arith. + intros. absurd (Zeven 1); red in |- *; auto with arith. + destruct p; auto with arith. + intros. absurd (Zeven (Zneg (xI p))); red in |- *; auto with arith. + intros. absurd (Zeven (-1)); red in |- *; auto with arith. Qed. Lemma Zodd_div2 : forall n:Z, (n >= 0)%Z -> Zodd n -> n = (2 * Zdiv2 n + 1)%Z. Proof. -intro x; destruct x. -intros. absurd (Zodd 0); red in |- *; auto with arith. -destruct p; auto with arith. -intros. absurd (Zodd (Zpos (xO p))); red in |- *; auto with arith. -intros. absurd (Zneg p >= 0)%Z; red in |- *; auto with arith. + intro x; destruct x. + intros. absurd (Zodd 0); red in |- *; auto with arith. + destruct p; auto with arith. + intros. absurd (Zodd (Zpos (xO p))); red in |- *; auto with arith. + intros. absurd (Zneg p >= 0)%Z; red in |- *; auto with arith. Qed. Lemma Zodd_div2_neg : - forall n:Z, (n <= 0)%Z -> Zodd n -> n = (2 * Zdiv2 n - 1)%Z. + forall n:Z, (n <= 0)%Z -> Zodd n -> n = (2 * Zdiv2 n - 1)%Z. Proof. -intro x; destruct x. -intros. absurd (Zodd 0); red in |- *; auto with arith. -intros. absurd (Zneg p >= 0)%Z; red in |- *; auto with arith. -destruct p; auto with arith. -intros. absurd (Zodd (Zneg (xO p))); red in |- *; auto with arith. + intro x; destruct x. + intros. absurd (Zodd 0); red in |- *; auto with arith. + intros. absurd (Zneg p >= 0)%Z; red in |- *; auto with arith. + destruct p; auto with arith. + intros. absurd (Zodd (Zneg (xO p))); red in |- *; auto with arith. Qed. Lemma Z_modulo_2 : - forall n:Z, {y : Z | n = (2 * y)%Z} + {y : Z | n = (2 * y + 1)%Z}. + forall n:Z, {y : Z | n = (2 * y)%Z} + {y : Z | n = (2 * y + 1)%Z}. Proof. -intros x. -elim (Zeven_odd_dec x); intro. -left. split with (Zdiv2 x). exact (Zeven_div2 x a). -right. generalize b; clear b; case x. -intro b; inversion b. -intro p; split with (Zdiv2 (Zpos p)). apply (Zodd_div2 (Zpos p)); trivial. -unfold Zge, Zcompare in |- *; simpl in |- *; discriminate. -intro p; split with (Zdiv2 (Zpred (Zneg p))). -pattern (Zneg p) at 1 in |- *; rewrite (Zsucc_pred (Zneg p)). -pattern (Zpred (Zneg p)) at 1 in |- *; rewrite (Zeven_div2 (Zpred (Zneg p))). -reflexivity. -apply Zeven_pred; assumption. + intros x. + elim (Zeven_odd_dec x); intro. + left. split with (Zdiv2 x). exact (Zeven_div2 x a). + right. generalize b; clear b; case x. + intro b; inversion b. + intro p; split with (Zdiv2 (Zpos p)). apply (Zodd_div2 (Zpos p)); trivial. + unfold Zge, Zcompare in |- *; simpl in |- *; discriminate. + intro p; split with (Zdiv2 (Zpred (Zneg p))). + pattern (Zneg p) at 1 in |- *; rewrite (Zsucc_pred (Zneg p)). + pattern (Zpred (Zneg p)) at 1 in |- *; rewrite (Zeven_div2 (Zpred (Zneg p))). + reflexivity. + apply Zeven_pred; assumption. Qed. Lemma Zsplit2 : - forall n:Z, - {p : Z * Z | - let (x1, x2) := p in n = (x1 + x2)%Z /\ (x1 = x2 \/ x2 = (x1 + 1)%Z)}. + forall n:Z, + {p : Z * Z | + let (x1, x2) := p in n = (x1 + x2)%Z /\ (x1 = x2 \/ x2 = (x1 + 1)%Z)}. Proof. -intros x. -elim (Z_modulo_2 x); intros [y Hy]; rewrite Zmult_comm in Hy; - rewrite <- Zplus_diag_eq_mult_2 in Hy. -exists (y, y); split. -assumption. -left; reflexivity. -exists (y, (y + 1)%Z); split. -rewrite Zplus_assoc; assumption. -right; reflexivity. -Qed. \ No newline at end of file + intros x. + elim (Z_modulo_2 x); intros [y Hy]; rewrite Zmult_comm in Hy; + rewrite <- Zplus_diag_eq_mult_2 in Hy. + exists (y, y); split. + assumption. + left; reflexivity. + exists (y, (y + 1)%Z); split. + rewrite Zplus_assoc; assumption. + right; reflexivity. +Qed. + diff --git a/theories/ZArith/Zhints.v b/theories/ZArith/Zhints.v index d0a2d2a0..b8f8ba30 100644 --- a/theories/ZArith/Zhints.v +++ b/theories/ZArith/Zhints.v @@ -6,26 +6,24 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zhints.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Zhints.v 9245 2006-10-17 12:53:34Z notin $ i*) (** This file centralizes the lemmas about [Z], classifying them according to the way they can be used in automatic search *) -(*i*) +(** Lemmas which clearly leads to simplification during proof search are *) +(** declared as Hints. A definite status (Hint or not) for the other lemmas *) +(** remains to be given *) -(* Lemmas which clearly leads to simplification during proof search are *) -(* declared as Hints. A definite status (Hint or not) for the other lemmas *) -(* remains to be given *) +(** Structure of the file *) +(** - simplification lemmas (only those are declared as Hints) *) +(** - reversible lemmas relating operators *) +(** - useful Bottom-up lemmas *) +(** - irreversible lemmas with meta-variables *) +(** - unclear or too specific lemmas *) +(** - lemmas to be used as rewrite rules *) -(* Structure of the file *) -(* - simplification lemmas (only those are declared as Hints) *) -(* - reversible lemmas relating operators *) -(* - useful Bottom-up lemmas *) -(* - irreversible lemmas with meta-variables *) -(* - unclear or too specific lemmas *) -(* - lemmas to be used as rewrite rules *) - -(* Lemmas involving positive and compare are not taken into account *) +(** Lemmas involving positive and compare are not taken into account *) Require Import BinInt. Require Import Zorder. @@ -37,32 +35,33 @@ Require Import auxiliary. Require Import Zmisc. Require Import Wf_Z. -(**********************************************************************) -(* Simplification lemmas *) -(* No subgoal or smaller subgoals *) +(************************************************************************) +(** * Simplification lemmas *) + +(** No subgoal or smaller subgoals *) Hint Resolve - (* A) Reversible simplification lemmas (no loss of information) *) - (* Should clearly declared as hints *) + (** ** Reversible simplification lemmas (no loss of information) *) + (** Should clearly be declared as hints *) - (* Lemmas ending by eq *) + (** Lemmas ending by eq *) Zsucc_eq_compat (* :(n,m:Z)`n = m`->`(Zs n) = (Zs m)` *) - (* Lemmas ending by Zgt *) + (** Lemmas ending by Zgt *) Zsucc_gt_compat (* :(n,m:Z)`m > n`->`(Zs m) > (Zs n)` *) Zgt_succ (* :(n:Z)`(Zs n) > n` *) Zorder.Zgt_pos_0 (* :(p:positive)`(POS p) > 0` *) Zplus_gt_compat_l (* :(n,m,p:Z)`n > m`->`p+n > p+m` *) Zplus_gt_compat_r (* :(n,m,p:Z)`n > m`->`n+p > m+p` *) - (* Lemmas ending by Zlt *) + (** Lemmas ending by Zlt *) Zlt_succ (* :(n:Z)`n < (Zs n)` *) Zsucc_lt_compat (* :(n,m:Z)`n < m`->`(Zs n) < (Zs m)` *) Zlt_pred (* :(n:Z)`(Zpred n) < n` *) Zplus_lt_compat_l (* :(n,m,p:Z)`n < m`->`p+n < p+m` *) Zplus_lt_compat_r (* :(n,m,p:Z)`n < m`->`n+p < m+p` *) - (* Lemmas ending by Zle *) + (** Lemmas ending by Zle *) Zle_0_nat (* :(n:nat)`0 <= (inject_nat n)` *) Zorder.Zle_0_pos (* :(p:positive)`0 <= (POS p)` *) Zle_refl (* :(n:Z)`n <= n` *) @@ -75,24 +74,24 @@ Hint Resolve Zplus_le_compat_r (* :(a,b,c:Z)`a <= b`->`a+c <= b+c` *) Zabs_pos (* :(x:Z)`0 <= |x|` *) - (* B) Irreversible simplification lemmas : Probably to be declared as *) - (* hints, when no other simplification is possible *) + (** ** Irreversible simplification lemmas *) + (** Probably to be declared as hints, when no other simplification is possible *) - (* Lemmas ending by eq *) + (** Lemmas ending by eq *) BinInt.Z_eq_mult (* :(x,y:Z)`y = 0`->`y*x = 0` *) Zplus_eq_compat (* :(n,m,p,q:Z)`n = m`->`p = q`->`n+p = m+q` *) - (* Lemmas ending by Zge *) + (** Lemmas ending by Zge *) Zorder.Zmult_ge_compat_r (* :(a,b,c:Z)`a >= b`->`c >= 0`->`a*c >= b*c` *) Zorder.Zmult_ge_compat_l (* :(a,b,c:Z)`a >= b`->`c >= 0`->`c*a >= c*b` *) Zorder.Zmult_ge_compat (* : (a,b,c,d:Z)`a >= c`->`b >= d`->`c >= 0`->`d >= 0`->`a*b >= c*d` *) - (* Lemmas ending by Zlt *) + (** Lemmas ending by Zlt *) Zorder.Zmult_gt_0_compat (* :(a,b:Z)`a > 0`->`b > 0`->`a*b > 0` *) Zlt_lt_succ (* :(n,m:Z)`n < m`->`n < (Zs m)` *) - (* Lemmas ending by Zle *) + (** Lemmas ending by Zle *) Zorder.Zmult_le_0_compat (* :(x,y:Z)`0 <= x`->`0 <= y`->`0 <= x*y` *) Zorder.Zmult_le_compat_r (* :(a,b,c:Z)`a <= b`->`0 <= c`->`a*c <= b*c` *) Zorder.Zmult_le_compat_l (* :(a,b,c:Z)`a <= b`->`0 <= c`->`c*a <= c*b` *) @@ -103,68 +102,118 @@ Hint Resolve : zarith. (**********************************************************************) -(* Reversible lemmas relating operators *) -(* Probably to be declared as hints but need to define precedences *) +(** * Reversible lemmas relating operators *) +(** Probably to be declared as hints but need to define precedences *) -(* A) Conversion between comparisons/predicates and arithmetic operators +(** ** Conversion between comparisons/predicates and arithmetic operators *) -(* Lemmas ending by eq *) +(** Lemmas ending by eq *) +(** +<< Zegal_left: (x,y:Z)`x = y`->`x+(-y) = 0` Zabs_eq: (x:Z)`0 <= x`->`|x| = x` Zeven_div2: (x:Z)(Zeven x)->`x = 2*(Zdiv2 x)` Zodd_div2: (x:Z)`x >= 0`->(Zodd x)->`x = 2*(Zdiv2 x)+1` +>> +*) -(* Lemmas ending by Zgt *) +(** Lemmas ending by Zgt *) +(** +<< Zgt_left_rev: (x,y:Z)`x+(-y) > 0`->`x > y` Zgt_left_gt: (x,y:Z)`x > y`->`x+(-y) > 0` +>> +*) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< Zlt_left_rev: (x,y:Z)`0 < y+(-x)`->`x < y` Zlt_left_lt: (x,y:Z)`x < y`->`0 < y+(-x)` Zlt_O_minus_lt: (n,m:Z)`0 < n-m`->`m < n` +>> +*) -(* Lemmas ending by Zle *) +(** Lemmas ending by Zle *) +(** +<< Zle_left: (x,y:Z)`x <= y`->`0 <= y+(-x)` Zle_left_rev: (x,y:Z)`0 <= y+(-x)`->`x <= y` Zlt_left: (x,y:Z)`x < y`->`0 <= y+(-1)+(-x)` Zge_left: (x,y:Z)`x >= y`->`0 <= x+(-y)` Zgt_left: (x,y:Z)`x > y`->`0 <= x+(-1)+(-y)` +>> +*) -(* B) Conversion between nat comparisons and Z comparisons *) +(** ** Conversion between nat comparisons and Z comparisons *) -(* Lemmas ending by eq *) +(** Lemmas ending by eq *) +(** +<< inj_eq: (x,y:nat)x=y->`(inject_nat x) = (inject_nat y)` +>> +*) -(* Lemmas ending by Zge *) +(** Lemmas ending by Zge *) +(** +<< inj_ge: (x,y:nat)(ge x y)->`(inject_nat x) >= (inject_nat y)` +>> +*) -(* Lemmas ending by Zgt *) +(** Lemmas ending by Zgt *) +(** +<< inj_gt: (x,y:nat)(gt x y)->`(inject_nat x) > (inject_nat y)` +>> +*) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< inj_lt: (x,y:nat)(lt x y)->`(inject_nat x) < (inject_nat y)` +>> +*) -(* Lemmas ending by Zle *) +(** Lemmas ending by Zle *) +(** +<< inj_le: (x,y:nat)(le x y)->`(inject_nat x) <= (inject_nat y)` +>> +*) -(* C) Conversion between comparisons *) +(** ** Conversion between comparisons *) -(* Lemmas ending by Zge *) +(** Lemmas ending by Zge *) +(** +<< not_Zlt: (x,y:Z)~`x < y`->`x >= y` Zle_ge: (m,n:Z)`m <= n`->`n >= m` +>> +*) -(* Lemmas ending by Zgt *) +(** Lemmas ending by Zgt *) +(** +<< Zle_gt_S: (n,p:Z)`n <= p`->`(Zs p) > n` not_Zle: (x,y:Z)~`x <= y`->`x > y` Zlt_gt: (m,n:Z)`m < n`->`n > m` Zle_S_gt: (n,m:Z)`(Zs n) <= m`->`m > n` +>> +*) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< not_Zge: (x,y:Z)~`x >= y`->`x < y` Zgt_lt: (m,n:Z)`m > n`->`n < m` Zle_lt_n_Sm: (n,m:Z)`n <= m`->`n < (Zs m)` +>> +*) -(* Lemmas ending by Zle *) +(** Lemmas ending by Zle *) +(** +<< Zlt_ZERO_pred_le_ZERO: (x:Z)`0 < x`->`0 <= (Zpred x)` not_Zgt: (x,y:Z)~`x > y`->`x <= y` Zgt_le_S: (n,p:Z)`p > n`->`(Zs n) <= p` @@ -174,138 +223,226 @@ Zlt_le_S: (n,p:Z)`n < p`->`(Zs n) <= p` Zlt_n_Sm_le: (n,m:Z)`n < (Zs m)`->`n <= m` Zlt_le_weak: (n,m:Z)`n < m`->`n <= m` Zle_refl: (n,m:Z)`n = m`->`n <= m` +>> +*) -(* D) Irreversible simplification involving several comparaisons, *) -(* useful with clear precedences *) +(** ** Irreversible simplification involving several comparaisons *) +(** useful with clear precedences *) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< Zlt_le_reg :(a,b,c,d:Z)`a < b`->`c <= d`->`a+c < b+d` Zle_lt_reg : (a,b,c,d:Z)`a <= b`->`c < d`->`a+c < b+d` +>> +*) -(* D) What is decreasing here ? *) +(** ** What is decreasing here ? *) -(* Lemmas ending by eq *) +(** Lemmas ending by eq *) +(** +<< Zplus_minus: (n,m,p:Z)`n = m+p`->`p = n-m` +>> +*) -(* Lemmas ending by Zgt *) +(** Lemmas ending by Zgt *) +(** +<< Zgt_pred: (n,p:Z)`p > (Zs n)`->`(Zpred p) > n` +>> +*) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< Zlt_pred: (n,p:Z)`(Zs n) < p`->`n < (Zpred p)` - +>> *) (**********************************************************************) -(* Useful Bottom-up lemmas *) +(** * Useful Bottom-up lemmas *) -(* A) Bottom-up simplification: should be used +(** ** Bottom-up simplification: should be used *) -(* Lemmas ending by eq *) +(** Lemmas ending by eq *) +(** +<< Zeq_add_S: (n,m:Z)`(Zs n) = (Zs m)`->`n = m` Zsimpl_plus_l: (n,m,p:Z)`n+m = n+p`->`m = p` Zplus_unit_left: (n,m:Z)`n+0 = m`->`n = m` Zplus_unit_right: (n,m:Z)`n = m+0`->`n = m` +>> +*) -(* Lemmas ending by Zgt *) +(** Lemmas ending by Zgt *) +(** +<< Zsimpl_gt_plus_l: (n,m,p:Z)`p+n > p+m`->`n > m` Zsimpl_gt_plus_r: (n,m,p:Z)`n+p > m+p`->`n > m` -Zgt_S_n: (n,p:Z)`(Zs p) > (Zs n)`->`p > n` +Zgt_S_n: (n,p:Z)`(Zs p) > (Zs n)`->`p > n` +>> +*) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< Zsimpl_lt_plus_l: (n,m,p:Z)`p+n < p+m`->`n < m` Zsimpl_lt_plus_r: (n,m,p:Z)`n+p < m+p`->`n < m` -Zlt_S_n: (n,m:Z)`(Zs n) < (Zs m)`->`n < m` +Zlt_S_n: (n,m:Z)`(Zs n) < (Zs m)`->`n < m` +>> +*) -(* Lemmas ending by Zle *) -Zsimpl_le_plus_l: (p,n,m:Z)`p+n <= p+m`->`n <= m` +(** Lemmas ending by Zle *) +(** << Zsimpl_le_plus_l: (p,n,m:Z)`p+n <= p+m`->`n <= m` Zsimpl_le_plus_r: (p,n,m:Z)`n+p <= m+p`->`n <= m` -Zle_S_n: (n,m:Z)`(Zs m) <= (Zs n)`->`m <= n` +Zle_S_n: (n,m:Z)`(Zs m) <= (Zs n)`->`m <= n` >> *) -(* B) Bottom-up irreversible (syntactic) simplification *) +(** ** Bottom-up irreversible (syntactic) simplification *) -(* Lemmas ending by Zle *) +(** Lemmas ending by Zle *) +(** +<< Zle_trans_S: (n,m:Z)`(Zs n) <= m`->`n <= m` +>> +*) -(* C) Other unclearly simplifying lemmas *) +(** ** Other unclearly simplifying lemmas *) -(* Lemmas ending by Zeq *) -Zmult_eq: (x,y:Z)`x <> 0`->`y*x = 0`->`y = 0` +(** Lemmas ending by Zeq *) +(** +<< +Zmult_eq: (x,y:Z)`x <> 0`->`y*x = 0`->`y = 0` +>> +*) (* Lemmas ending by Zgt *) +(** +<< Zmult_gt: (x,y:Z)`x > 0`->`x*y > 0`->`y > 0` +>> +*) (* Lemmas ending by Zlt *) +(** +<< pZmult_lt: (x,y:Z)`x > 0`->`0 < y*x`->`0 < y` +>> +*) (* Lemmas ending by Zle *) +(** +<< Zmult_le: (x,y:Z)`x > 0`->`0 <= y*x`->`0 <= y` OMEGA1: (x,y:Z)`x = y`->`0 <= x`->`0 <= y` +>> *) + (**********************************************************************) -(* Irreversible lemmas with meta-variables *) -(* To be used by EAuto +(** * Irreversible lemmas with meta-variables *) +(** To be used by EAuto *) -Hints Immediate -(* Lemmas ending by eq *) +(* Hints Immediate *) +(** Lemmas ending by eq *) +(** +<< Zle_antisym: (n,m:Z)`n <= m`->`m <= n`->`n = m` +>> +*) -(* Lemmas ending by Zge *) +(** Lemmas ending by Zge *) +(** +<< Zge_trans: (n,m,p:Z)`n >= m`->`m >= p`->`n >= p` +>> +*) -(* Lemmas ending by Zgt *) +(** Lemmas ending by Zgt *) +(** +<< Zgt_trans: (n,m,p:Z)`n > m`->`m > p`->`n > p` Zgt_trans_S: (n,m,p:Z)`(Zs n) > m`->`m > p`->`n > p` Zle_gt_trans: (n,m,p:Z)`m <= n`->`m > p`->`n > p` Zgt_le_trans: (n,m,p:Z)`n > m`->`p <= m`->`n > p` +>> +*) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< Zlt_trans: (n,m,p:Z)`n < m`->`m < p`->`n < p` Zlt_le_trans: (n,m,p:Z)`n < m`->`m <= p`->`n < p` Zle_lt_trans: (n,m,p:Z)`n <= m`->`m < p`->`n < p` +>> +*) -(* Lemmas ending by Zle *) +(** Lemmas ending by Zle *) +(** +<< Zle_trans: (n,m,p:Z)`n <= m`->`m <= p`->`n <= p` +>> *) + (**********************************************************************) -(* Unclear or too specific lemmas *) -(* Not to be used ?? *) +(** * Unclear or too specific lemmas *) +(** Not to be used ? *) -(* A) Irreversible and too specific (not enough regular) +(** ** Irreversible and too specific (not enough regular) *) -(* Lemmas ending by Zle *) +(** Lemmas ending by Zle *) +(** +<< Zle_mult: (x,y:Z)`x > 0`->`0 <= y`->`0 <= y*x` Zle_mult_approx: (x,y,z:Z)`x > 0`->`z > 0`->`0 <= y`->`0 <= y*x+z` OMEGA6: (x,y,z:Z)`0 <= x`->`y = 0`->`0 <= x+y*z` OMEGA7: (x,y,z,t:Z)`z > 0`->`t > 0`->`0 <= x`->`0 <= y`->`0 <= x*z+y*t` +>> +*) +(** ** Expansion and too specific ? *) -(* B) Expansion and too specific ? *) - -(* Lemmas ending by Zge *) +(** Lemmas ending by Zge *) +(** +<< Zge_mult_simpl: (a,b,c:Z)`c > 0`->`a*c >= b*c`->`a >= b` +>> +*) -(* Lemmas ending by Zgt *) +(** Lemmas ending by Zgt *) +(** +<< Zgt_mult_simpl: (a,b,c:Z)`c > 0`->`a*c > b*c`->`a > b` Zgt_square_simpl: (x,y:Z)`x >= 0`->`y >= 0`->`x*x > y*y`->`x > y` +>> +*) -(* Lemmas ending by Zle *) +(** Lemmas ending by Zle *) +(** +<< Zle_mult_simpl: (a,b,c:Z)`c > 0`->`a*c <= b*c`->`a <= b` Zmult_le_approx: (x,y,z:Z)`x > 0`->`x > z`->`0 <= y*x+z`->`0 <= y` +>> +*) -(* C) Reversible but too specific ? *) +(** ** Reversible but too specific ? *) -(* Lemmas ending by Zlt *) +(** Lemmas ending by Zlt *) +(** +<< Zlt_minus: (n,m:Z)`0 < m`->`n-m < n` +>> *) (**********************************************************************) -(* Lemmas to be used as rewrite rules *) -(* but can also be used as hints +(** * Lemmas to be used as rewrite rules *) +(** but can also be used as hints *) -(* Left-to-right simplification lemmas (a symbol disappears) *) +(** Left-to-right simplification lemmas (a symbol disappears) *) +(** +<< Zcompare_n_S: (n,m:Z)(Zcompare (Zs n) (Zs m))=(Zcompare n m) Zmin_n_n: (n:Z)`(Zmin n n) = n` Zmult_1_n: (n:Z)`1*n = n` @@ -322,9 +459,13 @@ Zmult_one: (x:Z)`1*x = x` Zero_mult_left: (x:Z)`0*x = 0` Zero_mult_right: (x:Z)`x*0 = 0` Zmult_Zopp_Zopp: (x,y:Z)`(-x)*(-y) = x*y` +>> +*) -(* Right-to-left simplification lemmas (a symbol disappears) *) +(** Right-to-left simplification lemmas (a symbol disappears) *) +(** +<< Zpred_Sn: (m:Z)`m = (Zpred (Zs m))` Zs_pred: (n:Z)`n = (Zs (Zpred n))` Zplus_n_O: (n:Z)`n = n+0` @@ -333,9 +474,13 @@ Zminus_n_O: (n:Z)`n = n-0` Zminus_n_n: (n:Z)`0 = n-n` Zred_factor6: (x:Z)`x = x+0` Zred_factor0: (x:Z)`x = x*1` +>> +*) -(* Unclear orientation (no symbol disappears) *) +(** Unclear orientation (no symbol disappears) *) +(** +<< Zplus_n_Sm: (n,m:Z)`(Zs (n+m)) = n+(Zs m)` Zmult_n_Sm: (n,m:Z)`n*m+n = n*(Zs m)` Zmin_SS: (n,m:Z)`(Zs (Zmin n m)) = (Zmin (Zs n) (Zs m))` @@ -370,17 +515,25 @@ Zred_factor3: (x,y:Z)`x*y+x = x*(1+y)` Zred_factor4: (x,y,z:Z)`x*y+x*z = x*(y+z)` Zminus_Zplus_compatible: (x,y,n:Z)`x+n-(y+n) = x-y` Zmin_plus: (x,y,n:Z)`(Zmin (x+n) (y+n)) = (Zmin x y)+n` +>> +*) -(* nat <-> Z *) +(** nat <-> Z *) +(** +<< inj_S: (y:nat)`(inject_nat (S y)) = (Zs (inject_nat y))` inj_plus: (x,y:nat)`(inject_nat (plus x y)) = (inject_nat x)+(inject_nat y)` inj_mult: (x,y:nat)`(inject_nat (mult x y)) = (inject_nat x)*(inject_nat y)` inj_minus1: (x,y:nat)(le y x)->`(inject_nat (minus x y)) = (inject_nat x)-(inject_nat y)` inj_minus2: (x,y:nat)(gt y x)->`(inject_nat (minus x y)) = 0` +>> +*) -(* Too specific ? *) +(** Too specific ? *) +(** +<< Zred_factor5: (x,y:Z)`x*0+y = y` +>> *) -(*i*) \ No newline at end of file diff --git a/theories/ZArith/Zlogarithm.v b/theories/ZArith/Zlogarithm.v index 653ee951..d8f4f236 100644 --- a/theories/ZArith/Zlogarithm.v +++ b/theories/ZArith/Zlogarithm.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zlogarithm.v 6295 2004-11-12 16:40:39Z gregoire $ i*) +(*i $Id: Zlogarithm.v 9245 2006-10-17 12:53:34Z notin $ i*) (**********************************************************************) (** The integer logarithms with base 2. @@ -27,235 +27,221 @@ Require Import Zpower. Open Local Scope Z_scope. Section Log_pos. (* Log of positive integers *) - -(** First we build [log_inf] and [log_sup] *) - -Fixpoint log_inf (p:positive) : Z := - match p with - | xH => 0 (* 1 *) - | xO q => Zsucc (log_inf q) (* 2n *) - | xI q => Zsucc (log_inf q) (* 2n+1 *) - end. - -Fixpoint log_sup (p:positive) : Z := - match p with - | xH => 0 (* 1 *) - | xO n => Zsucc (log_sup n) (* 2n *) - | xI n => Zsucc (Zsucc (log_inf n)) (* 2n+1 *) - end. - -Hint Unfold log_inf log_sup. - -(** Then we give the specifications of [log_inf] and [log_sup] + + (** First we build [log_inf] and [log_sup] *) + + Fixpoint log_inf (p:positive) : Z := + match p with + | xH => 0 (* 1 *) + | xO q => Zsucc (log_inf q) (* 2n *) + | xI q => Zsucc (log_inf q) (* 2n+1 *) + end. + + Fixpoint log_sup (p:positive) : Z := + match p with + | xH => 0 (* 1 *) + | xO n => Zsucc (log_sup n) (* 2n *) + | xI n => Zsucc (Zsucc (log_inf n)) (* 2n+1 *) + end. + + Hint Unfold log_inf log_sup. + + (** Then we give the specifications of [log_inf] and [log_sup] and prove their validity *) - -(*i Hints Resolve ZERO_le_S : zarith. i*) -Hint Resolve Zle_trans: zarith. - -Theorem log_inf_correct : - forall x:positive, - 0 <= log_inf x /\ two_p (log_inf x) <= Zpos x < two_p (Zsucc (log_inf x)). -simple induction x; intros; simpl in |- *; - [ elim H; intros Hp HR; clear H; split; - [ auto with zarith - | conditional apply Zle_le_succ; trivial rewrite - two_p_S with (x := Zsucc (log_inf p)); - conditional trivial rewrite two_p_S; - conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xI p); - omega ] - | elim H; intros Hp HR; clear H; split; - [ auto with zarith - | conditional apply Zle_le_succ; trivial rewrite - two_p_S with (x := Zsucc (log_inf p)); - conditional trivial rewrite two_p_S; - conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xO p); - omega ] - | unfold two_power_pos in |- *; unfold shift_pos in |- *; simpl in |- *; - omega ]. -Qed. - -Definition log_inf_correct1 (p:positive) := proj1 (log_inf_correct p). -Definition log_inf_correct2 (p:positive) := proj2 (log_inf_correct p). - -Opaque log_inf_correct1 log_inf_correct2. - -Hint Resolve log_inf_correct1 log_inf_correct2: zarith. - -Lemma log_sup_correct1 : forall p:positive, 0 <= log_sup p. -simple induction p; intros; simpl in |- *; auto with zarith. -Qed. - -(** For every [p], either [p] is a power of two and [(log_inf p)=(log_sup p)] - either [(log_sup p)=(log_inf p)+1] *) - -Theorem log_sup_log_inf : - forall p:positive, - IF Zpos p = two_p (log_inf p) then Zpos p = two_p (log_sup p) - else log_sup p = Zsucc (log_inf p). - -simple induction p; intros; - [ elim H; right; simpl in |- *; - rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite BinInt.Zpos_xI; unfold Zsucc in |- *; omega - | elim H; clear H; intro Hif; - [ left; simpl in |- *; - rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite (two_p_S (log_sup p0) (log_sup_correct1 p0)); - rewrite <- (proj1 Hif); rewrite <- (proj2 Hif); - auto - | right; simpl in |- *; - rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite BinInt.Zpos_xO; unfold Zsucc in |- *; - omega ] - | left; auto ]. -Qed. - -Theorem log_sup_correct2 : - forall x:positive, two_p (Zpred (log_sup x)) < Zpos x <= two_p (log_sup x). - -intro. -elim (log_sup_log_inf x). -(* x is a power of two and [log_sup = log_inf] *) -intros [E1 E2]; rewrite E2. -split; [ apply two_p_pred; apply log_sup_correct1 | apply Zle_refl ]. -intros [E1 E2]; rewrite E2. -rewrite <- (Zpred_succ (log_inf x)). -generalize (log_inf_correct2 x); omega. -Qed. - -Lemma log_inf_le_log_sup : forall p:positive, log_inf p <= log_sup p. -simple induction p; simpl in |- *; intros; omega. -Qed. - -Lemma log_sup_le_Slog_inf : forall p:positive, log_sup p <= Zsucc (log_inf p). -simple induction p; simpl in |- *; intros; omega. -Qed. - -(** Now it's possible to specify and build the [Log] rounded to the nearest *) - -Fixpoint log_near (x:positive) : Z := - match x with - | xH => 0 - | xO xH => 1 - | xI xH => 2 - | xO y => Zsucc (log_near y) - | xI y => Zsucc (log_near y) - end. - -Theorem log_near_correct1 : forall p:positive, 0 <= log_near p. -simple induction p; simpl in |- *; intros; - [ elim p0; auto with zarith - | elim p0; auto with zarith - | trivial with zarith ]. -intros; apply Zle_le_succ. -generalize H0; elim p1; intros; simpl in |- *; - [ assumption | assumption | apply Zorder.Zle_0_pos ]. -intros; apply Zle_le_succ. -generalize H0; elim p1; intros; simpl in |- *; - [ assumption | assumption | apply Zorder.Zle_0_pos ]. -Qed. - -Theorem log_near_correct2 : - forall p:positive, log_near p = log_inf p \/ log_near p = log_sup p. -simple induction p. -intros p0 [Einf| Esup]. -simpl in |- *. rewrite Einf. -case p0; [ left | left | right ]; reflexivity. -simpl in |- *; rewrite Esup. -elim (log_sup_log_inf p0). -generalize (log_inf_le_log_sup p0). -generalize (log_sup_le_Slog_inf p0). -case p0; auto with zarith. -intros; omega. -case p0; intros; auto with zarith. -intros p0 [Einf| Esup]. -simpl in |- *. -repeat rewrite Einf. -case p0; intros; auto with zarith. -simpl in |- *. -repeat rewrite Esup. -case p0; intros; auto with zarith. -auto. -Qed. - -(*i****************** -Theorem log_near_correct: (p:positive) - `| (two_p (log_near p)) - (POS p) | <= (POS p)-(two_p (log_inf p))` - /\`| (two_p (log_near p)) - (POS p) | <= (two_p (log_sup p))-(POS p)`. -Intro. -Induction p. -Intros p0 [(Einf1,Einf2)|(Esup1,Esup2)]. -Unfold log_near log_inf log_sup. Fold log_near log_inf log_sup. -Rewrite Einf1. -Repeat Rewrite two_p_S. -Case p0; [Left | Left | Right]. - -Split. -Simpl. -Rewrite E1; Case p0; Try Reflexivity. -Compute. -Unfold log_near; Fold log_near. -Unfold log_inf; Fold log_inf. -Repeat Rewrite E1. -Split. -**********************************i*) + + Hint Resolve Zle_trans: zarith. + + Theorem log_inf_correct : + forall x:positive, + 0 <= log_inf x /\ two_p (log_inf x) <= Zpos x < two_p (Zsucc (log_inf x)). + simple induction x; intros; simpl in |- *; + [ elim H; intros Hp HR; clear H; split; + [ auto with zarith + | conditional apply Zle_le_succ; trivial rewrite + two_p_S with (x := Zsucc (log_inf p)); + conditional trivial rewrite two_p_S; + conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xI p); + omega ] + | elim H; intros Hp HR; clear H; split; + [ auto with zarith + | conditional apply Zle_le_succ; trivial rewrite + two_p_S with (x := Zsucc (log_inf p)); + conditional trivial rewrite two_p_S; + conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xO p); + omega ] + | unfold two_power_pos in |- *; unfold shift_pos in |- *; simpl in |- *; + omega ]. + Qed. + + Definition log_inf_correct1 (p:positive) := proj1 (log_inf_correct p). + Definition log_inf_correct2 (p:positive) := proj2 (log_inf_correct p). + + Opaque log_inf_correct1 log_inf_correct2. + + Hint Resolve log_inf_correct1 log_inf_correct2: zarith. + + Lemma log_sup_correct1 : forall p:positive, 0 <= log_sup p. + Proof. + simple induction p; intros; simpl in |- *; auto with zarith. + Qed. + + (** For every [p], either [p] is a power of two and [(log_inf p)=(log_sup p)] + either [(log_sup p)=(log_inf p)+1] *) + + Theorem log_sup_log_inf : + forall p:positive, + IF Zpos p = two_p (log_inf p) then Zpos p = two_p (log_sup p) + else log_sup p = Zsucc (log_inf p). + Proof. + simple induction p; intros; + [ elim H; right; simpl in |- *; + rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); + rewrite BinInt.Zpos_xI; unfold Zsucc in |- *; omega + | elim H; clear H; intro Hif; + [ left; simpl in |- *; + rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); + rewrite (two_p_S (log_sup p0) (log_sup_correct1 p0)); + rewrite <- (proj1 Hif); rewrite <- (proj2 Hif); + auto + | right; simpl in |- *; + rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); + rewrite BinInt.Zpos_xO; unfold Zsucc in |- *; + omega ] + | left; auto ]. + Qed. + + Theorem log_sup_correct2 : + forall x:positive, two_p (Zpred (log_sup x)) < Zpos x <= two_p (log_sup x). + Proof. + intro. + elim (log_sup_log_inf x). + (* x is a power of two and [log_sup = log_inf] *) + intros [E1 E2]; rewrite E2. + split; [ apply two_p_pred; apply log_sup_correct1 | apply Zle_refl ]. + intros [E1 E2]; rewrite E2. + rewrite <- (Zpred_succ (log_inf x)). + generalize (log_inf_correct2 x); omega. + Qed. + + Lemma log_inf_le_log_sup : forall p:positive, log_inf p <= log_sup p. + Proof. + simple induction p; simpl in |- *; intros; omega. + Qed. + + Lemma log_sup_le_Slog_inf : forall p:positive, log_sup p <= Zsucc (log_inf p). + Proof. + simple induction p; simpl in |- *; intros; omega. + Qed. + + (** Now it's possible to specify and build the [Log] rounded to the nearest *) + + Fixpoint log_near (x:positive) : Z := + match x with + | xH => 0 + | xO xH => 1 + | xI xH => 2 + | xO y => Zsucc (log_near y) + | xI y => Zsucc (log_near y) + end. + + Theorem log_near_correct1 : forall p:positive, 0 <= log_near p. + Proof. + simple induction p; simpl in |- *; intros; + [ elim p0; auto with zarith + | elim p0; auto with zarith + | trivial with zarith ]. + intros; apply Zle_le_succ. + generalize H0; elim p1; intros; simpl in |- *; + [ assumption | assumption | apply Zorder.Zle_0_pos ]. + intros; apply Zle_le_succ. + generalize H0; elim p1; intros; simpl in |- *; + [ assumption | assumption | apply Zorder.Zle_0_pos ]. + Qed. + + Theorem log_near_correct2 : + forall p:positive, log_near p = log_inf p \/ log_near p = log_sup p. + Proof. + simple induction p. + intros p0 [Einf| Esup]. + simpl in |- *. rewrite Einf. + case p0; [ left | left | right ]; reflexivity. + simpl in |- *; rewrite Esup. + elim (log_sup_log_inf p0). + generalize (log_inf_le_log_sup p0). + generalize (log_sup_le_Slog_inf p0). + case p0; auto with zarith. + intros; omega. + case p0; intros; auto with zarith. + intros p0 [Einf| Esup]. + simpl in |- *. + repeat rewrite Einf. + case p0; intros; auto with zarith. + simpl in |- *. + repeat rewrite Esup. + case p0; intros; auto with zarith. + auto. + Qed. End Log_pos. Section divers. -(** Number of significative digits. *) - -Definition N_digits (x:Z) := - match x with - | Zpos p => log_inf p - | Zneg p => log_inf p - | Z0 => 0 - end. - -Lemma ZERO_le_N_digits : forall x:Z, 0 <= N_digits x. -simple induction x; simpl in |- *; - [ apply Zle_refl | exact log_inf_correct1 | exact log_inf_correct1 ]. -Qed. - -Lemma log_inf_shift_nat : forall n:nat, log_inf (shift_nat n 1) = Z_of_nat n. -simple induction n; intros; - [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. -Qed. - -Lemma log_sup_shift_nat : forall n:nat, log_sup (shift_nat n 1) = Z_of_nat n. -simple induction n; intros; - [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. -Qed. - -(** [Is_power p] means that p is a power of two *) -Fixpoint Is_power (p:positive) : Prop := - match p with - | xH => True - | xO q => Is_power q - | xI q => False - end. - -Lemma Is_power_correct : - forall p:positive, Is_power p <-> (exists y : nat, p = shift_nat y 1). - -split; - [ elim p; - [ simpl in |- *; tauto - | simpl in |- *; intros; generalize (H H0); intro H1; elim H1; - intros y0 Hy0; exists (S y0); rewrite Hy0; reflexivity - | intro; exists 0%nat; reflexivity ] - | intros; elim H; intros; rewrite H0; elim x; intros; simpl in |- *; trivial ]. -Qed. - -Lemma Is_power_or : forall p:positive, Is_power p \/ ~ Is_power p. -simple induction p; - [ intros; right; simpl in |- *; tauto - | intros; elim H; - [ intros; left; simpl in |- *; exact H0 - | intros; right; simpl in |- *; exact H0 ] - | left; simpl in |- *; trivial ]. -Qed. + (** Number of significative digits. *) + + Definition N_digits (x:Z) := + match x with + | Zpos p => log_inf p + | Zneg p => log_inf p + | Z0 => 0 + end. + + Lemma ZERO_le_N_digits : forall x:Z, 0 <= N_digits x. + Proof. + simple induction x; simpl in |- *; + [ apply Zle_refl | exact log_inf_correct1 | exact log_inf_correct1 ]. + Qed. + + Lemma log_inf_shift_nat : forall n:nat, log_inf (shift_nat n 1) = Z_of_nat n. + Proof. + simple induction n; intros; + [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. + Qed. + + Lemma log_sup_shift_nat : forall n:nat, log_sup (shift_nat n 1) = Z_of_nat n. + Proof. + simple induction n; intros; + [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. + Qed. + + (** [Is_power p] means that p is a power of two *) + Fixpoint Is_power (p:positive) : Prop := + match p with + | xH => True + | xO q => Is_power q + | xI q => False + end. + + Lemma Is_power_correct : + forall p:positive, Is_power p <-> (exists y : nat, p = shift_nat y 1). + Proof. + split; + [ elim p; + [ simpl in |- *; tauto + | simpl in |- *; intros; generalize (H H0); intro H1; elim H1; + intros y0 Hy0; exists (S y0); rewrite Hy0; reflexivity + | intro; exists 0%nat; reflexivity ] + | intros; elim H; intros; rewrite H0; elim x; intros; simpl in |- *; trivial ]. + Qed. + + Lemma Is_power_or : forall p:positive, Is_power p \/ ~ Is_power p. + Proof. + simple induction p; + [ intros; right; simpl in |- *; tauto + | intros; elim H; + [ intros; left; simpl in |- *; exact H0 + | intros; right; simpl in |- *; exact H0 ] + | left; simpl in |- *; trivial ]. + Qed. End divers. diff --git a/theories/ZArith/Zmax.v b/theories/ZArith/Zmax.v index ae3bbf41..8af9b891 100644 --- a/theories/ZArith/Zmax.v +++ b/theories/ZArith/Zmax.v @@ -5,104 +5,104 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmax.v 8032 2006-02-12 21:20:48Z herbelin $ i*) +(*i $Id: Zmax.v 9302 2006-10-27 21:21:17Z barras $ i*) -Require Import Arith. +Require Import Arith_base. Require Import BinInt. Require Import Zcompare. Require Import Zorder. Open Local Scope Z_scope. -(**********************************************************************) -(** *** Maximum of two binary integer numbers *) +(******************************************) +(** Maximum of two binary integer numbers *) Definition Zmax m n := - match m ?= n with + match m ?= n with | Eq | Gt => m | Lt => n - end. + end. -(** Characterization of maximum on binary integer numbers *) +(** * Characterization of maximum on binary integer numbers *) Lemma Zmax_case : forall (n m:Z) (P:Z -> Type), P n -> P m -> P (Zmax n m). Proof. -intros n m P H1 H2; unfold Zmax in |- *; case (n ?= m); auto with arith. + intros n m P H1 H2; unfold Zmax in |- *; case (n ?= m); auto with arith. Qed. Lemma Zmax_case_strong : forall (n m:Z) (P:Z -> Type), (m<=n -> P n) -> (n<=m -> P m) -> P (Zmax n m). Proof. -intros n m P H1 H2; unfold Zmax, Zle, Zge in *. -rewrite <- (Zcompare_antisym n m) in H1. -destruct (n ?= m); (apply H1|| apply H2); discriminate. + intros n m P H1 H2; unfold Zmax, Zle, Zge in *. + rewrite <- (Zcompare_antisym n m) in H1. + destruct (n ?= m); (apply H1|| apply H2); discriminate. Qed. -(** Least upper bound properties of max *) +(** * Least upper bound properties of max *) Lemma Zle_max_l : forall n m:Z, n <= Zmax n m. Proof. -intros; apply Zmax_case_strong; auto with zarith. + intros; apply Zmax_case_strong; auto with zarith. Qed. Notation Zmax1 := Zle_max_l (only parsing). Lemma Zle_max_r : forall n m:Z, m <= Zmax n m. Proof. -intros; apply Zmax_case_strong; auto with zarith. + intros; apply Zmax_case_strong; auto with zarith. Qed. Notation Zmax2 := Zle_max_r (only parsing). Lemma Zmax_lub : forall n m p:Z, n <= p -> m <= p -> Zmax n m <= p. Proof. -intros; apply Zmax_case; assumption. + intros; apply Zmax_case; assumption. Qed. -(** Semi-lattice properties of max *) +(** * Semi-lattice properties of max *) Lemma Zmax_idempotent : forall n:Z, Zmax n n = n. Proof. -intros; apply Zmax_case; auto. + intros; apply Zmax_case; auto. Qed. Lemma Zmax_comm : forall n m:Z, Zmax n m = Zmax m n. Proof. -intros; do 2 apply Zmax_case_strong; intros; - apply Zle_antisym; auto with zarith. + intros; do 2 apply Zmax_case_strong; intros; + apply Zle_antisym; auto with zarith. Qed. Lemma Zmax_assoc : forall n m p:Z, Zmax n (Zmax m p) = Zmax (Zmax n m) p. Proof. -intros n m p; repeat apply Zmax_case_strong; intros; - reflexivity || (try apply Zle_antisym); eauto with zarith. + intros n m p; repeat apply Zmax_case_strong; intros; + reflexivity || (try apply Zle_antisym); eauto with zarith. Qed. -(** Additional properties of max *) +(** * Additional properties of max *) Lemma Zmax_irreducible_inf : forall n m:Z, Zmax n m = n \/ Zmax n m = m. Proof. -intros; apply Zmax_case; auto. + intros; apply Zmax_case; auto. Qed. Lemma Zmax_le_prime_inf : forall n m p:Z, p <= Zmax n m -> p <= n \/ p <= m. Proof. -intros n m p; apply Zmax_case; auto. + intros n m p; apply Zmax_case; auto. Qed. -(** Operations preserving max *) +(** * Operations preserving max *) Lemma Zsucc_max_distr : forall n m:Z, Zsucc (Zmax n m) = Zmax (Zsucc n) (Zsucc m). Proof. -intros n m; unfold Zmax in |- *; rewrite (Zcompare_succ_compat n m); - elim_compare n m; intros E; rewrite E; auto with arith. + intros n m; unfold Zmax in |- *; rewrite (Zcompare_succ_compat n m); + elim_compare n m; intros E; rewrite E; auto with arith. Qed. Lemma Zplus_max_distr_r : forall n m p:Z, Zmax (n + p) (m + p) = Zmax n m + p. Proof. -intros x y n; unfold Zmax in |- *. -rewrite (Zplus_comm x n); rewrite (Zplus_comm y n); - rewrite (Zcompare_plus_compat x y n). -case (x ?= y); apply Zplus_comm. + intros x y n; unfold Zmax in |- *. + rewrite (Zplus_comm x n); rewrite (Zplus_comm y n); + rewrite (Zcompare_plus_compat x y n). + case (x ?= y); apply Zplus_comm. Qed. diff --git a/theories/ZArith/Zmin.v b/theories/ZArith/Zmin.v index d79ebe98..37d78a74 100644 --- a/theories/ZArith/Zmin.v +++ b/theories/ZArith/Zmin.v @@ -5,126 +5,126 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmin.v 8032 2006-02-12 21:20:48Z herbelin $ i*) +(*i $Id: Zmin.v 9302 2006-10-27 21:21:17Z barras $ i*) (** Initial version from Pierre Crégut (CNET, Lannion, France), 1996. Further extensions by the Coq development team, with suggestions from Russell O'Connor (Radbout U., Nijmegen, The Netherlands). *) -Require Import Arith. +Require Import Arith_base. Require Import BinInt. Require Import Zcompare. Require Import Zorder. Open Local Scope Z_scope. -(**********************************************************************) -(** *** Minimum on binary integer numbers *) +(**************************************) +(** Minimum on binary integer numbers *) Unboxed Definition Zmin (n m:Z) := match n ?= m with - | Eq | Lt => n - | Gt => m + | Eq | Lt => n + | Gt => m end. -(** Characterization of the minimum on binary integer numbers *) +(** * Characterization of the minimum on binary integer numbers *) Lemma Zmin_case_strong : forall (n m:Z) (P:Z -> Type), (n<=m -> P n) -> (m<=n -> P m) -> P (Zmin n m). Proof. -intros n m P H1 H2; unfold Zmin, Zle, Zge in *. -rewrite <- (Zcompare_antisym n m) in H2. -destruct (n ?= m); (apply H1|| apply H2); discriminate. + intros n m P H1 H2; unfold Zmin, Zle, Zge in *. + rewrite <- (Zcompare_antisym n m) in H2. + destruct (n ?= m); (apply H1|| apply H2); discriminate. Qed. Lemma Zmin_case : forall (n m:Z) (P:Z -> Type), P n -> P m -> P (Zmin n m). Proof. -intros n m P H1 H2; unfold Zmin in |- *; case (n ?= m); auto with arith. + intros n m P H1 H2; unfold Zmin in |- *; case (n ?= m); auto with arith. Qed. -(** Greatest lower bound properties of min *) +(** * Greatest lower bound properties of min *) Lemma Zle_min_l : forall n m:Z, Zmin n m <= n. Proof. -intros n m; unfold Zmin in |- *; elim_compare n m; intros E; rewrite E; - [ apply Zle_refl - | apply Zle_refl - | apply Zlt_le_weak; apply Zgt_lt; exact E ]. + intros n m; unfold Zmin in |- *; elim_compare n m; intros E; rewrite E; + [ apply Zle_refl + | apply Zle_refl + | apply Zlt_le_weak; apply Zgt_lt; exact E ]. Qed. Lemma Zle_min_r : forall n m:Z, Zmin n m <= m. Proof. -intros n m; unfold Zmin in |- *; elim_compare n m; intros E; rewrite E; - [ unfold Zle in |- *; rewrite E; discriminate - | unfold Zle in |- *; rewrite E; discriminate - | apply Zle_refl ]. + intros n m; unfold Zmin in |- *; elim_compare n m; intros E; rewrite E; + [ unfold Zle in |- *; rewrite E; discriminate + | unfold Zle in |- *; rewrite E; discriminate + | apply Zle_refl ]. Qed. Lemma Zmin_glb : forall n m p:Z, p <= n -> p <= m -> p <= Zmin n m. Proof. -intros; apply Zmin_case; assumption. + intros; apply Zmin_case; assumption. Qed. -(** Semi-lattice properties of min *) +(** * Semi-lattice properties of min *) Lemma Zmin_idempotent : forall n:Z, Zmin n n = n. Proof. -unfold Zmin in |- *; intros; elim (n ?= n); auto. + unfold Zmin in |- *; intros; elim (n ?= n); auto. Qed. Notation Zmin_n_n := Zmin_idempotent (only parsing). Lemma Zmin_comm : forall n m:Z, Zmin n m = Zmin m n. Proof. -intros n m; unfold Zmin. -rewrite <- (Zcompare_antisym n m). -assert (H:=Zcompare_Eq_eq n m). -destruct (n ?= m); simpl; auto. + intros n m; unfold Zmin. + rewrite <- (Zcompare_antisym n m). + assert (H:=Zcompare_Eq_eq n m). + destruct (n ?= m); simpl; auto. Qed. Lemma Zmin_assoc : forall n m p:Z, Zmin n (Zmin m p) = Zmin (Zmin n m) p. Proof. -intros n m p; repeat apply Zmin_case_strong; intros; - reflexivity || (try apply Zle_antisym); eauto with zarith. + intros n m p; repeat apply Zmin_case_strong; intros; + reflexivity || (try apply Zle_antisym); eauto with zarith. Qed. -(** Additional properties of min *) +(** * Additional properties of min *) Lemma Zmin_irreducible_inf : forall n m:Z, {Zmin n m = n} + {Zmin n m = m}. Proof. -unfold Zmin in |- *; intros; elim (n ?= m); auto. + unfold Zmin in |- *; intros; elim (n ?= m); auto. Qed. Lemma Zmin_irreducible : forall n m:Z, Zmin n m = n \/ Zmin n m = m. Proof. -intros n m; destruct (Zmin_irreducible_inf n m); [left|right]; trivial. + intros n m; destruct (Zmin_irreducible_inf n m); [left|right]; trivial. Qed. Notation Zmin_or := Zmin_irreducible (only parsing). Lemma Zmin_le_prime_inf : forall n m p:Z, Zmin n m <= p -> {n <= p} + {m <= p}. Proof. -intros n m p; apply Zmin_case; auto. + intros n m p; apply Zmin_case; auto. Qed. -(** Operations preserving min *) +(** * Operations preserving min *) Lemma Zsucc_min_distr : forall n m:Z, Zsucc (Zmin n m) = Zmin (Zsucc n) (Zsucc m). Proof. -intros n m; unfold Zmin in |- *; rewrite (Zcompare_succ_compat n m); - elim_compare n m; intros E; rewrite E; auto with arith. + intros n m; unfold Zmin in |- *; rewrite (Zcompare_succ_compat n m); + elim_compare n m; intros E; rewrite E; auto with arith. Qed. Notation Zmin_SS := Zsucc_min_distr (only parsing). Lemma Zplus_min_distr_r : forall n m p:Z, Zmin (n + p) (m + p) = Zmin n m + p. Proof. -intros x y n; unfold Zmin in |- *. -rewrite (Zplus_comm x n); rewrite (Zplus_comm y n); - rewrite (Zcompare_plus_compat x y n). -case (x ?= y); apply Zplus_comm. + intros x y n; unfold Zmin in |- *. + rewrite (Zplus_comm x n); rewrite (Zplus_comm y n); + rewrite (Zcompare_plus_compat x y n). + case (x ?= y); apply Zplus_comm. Qed. Notation Zmin_plus := Zplus_min_distr_r (only parsing). diff --git a/theories/ZArith/Zminmax.v b/theories/ZArith/Zminmax.v index ebe9318e..95668cf8 100644 --- a/theories/ZArith/Zminmax.v +++ b/theories/ZArith/Zminmax.v @@ -5,27 +5,27 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zminmax.v 8034 2006-02-12 22:08:04Z herbelin $ i*) +(*i $Id: Zminmax.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import Zmin Zmax. Require Import BinInt Zorder. Open Local Scope Z_scope. -(** *** Lattice properties of min and max on Z *) +(** Lattice properties of min and max on Z *) (** Absorption *) Lemma Zmin_max_absorption_r_r : forall n m, Zmax n (Zmin n m) = n. Proof. -intros; apply Zmin_case_strong; intro; apply Zmax_case_strong; intro; - reflexivity || apply Zle_antisym; trivial. + intros; apply Zmin_case_strong; intro; apply Zmax_case_strong; intro; + reflexivity || apply Zle_antisym; trivial. Qed. Lemma Zmax_min_absorption_r_r : forall n m, Zmin n (Zmax n m) = n. Proof. -intros; apply Zmax_case_strong; intro; apply Zmin_case_strong; intro; - reflexivity || apply Zle_antisym; trivial. + intros; apply Zmax_case_strong; intro; apply Zmin_case_strong; intro; + reflexivity || apply Zle_antisym; trivial. Qed. (** Distributivity *) @@ -33,19 +33,19 @@ Qed. Lemma Zmax_min_distr_r : forall n m p, Zmax n (Zmin m p) = Zmin (Zmax n m) (Zmax n p). Proof. -intros. -repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; - reflexivity || - apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). + intros. + repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; + reflexivity || + apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). Qed. Lemma Zmin_max_distr_r : forall n m p, Zmin n (Zmax m p) = Zmax (Zmin n m) (Zmin n p). Proof. -intros. -repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; - reflexivity || - apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). + intros. + repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; + reflexivity || + apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). Qed. (** Modularity *) @@ -53,30 +53,24 @@ Qed. Lemma Zmax_min_modular_r : forall n m p, Zmax n (Zmin m (Zmax n p)) = Zmin (Zmax n m) (Zmax n p). Proof. -intros; repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; - reflexivity || - apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). + intros; repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; + reflexivity || + apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). Qed. Lemma Zmin_max_modular_r : forall n m p, Zmin n (Zmax m (Zmin n p)) = Zmax (Zmin n m) (Zmin n p). Proof. -intros; repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; - reflexivity || - apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). + intros; repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; + reflexivity || + apply Zle_antisym; (assumption || eapply Zle_trans; eassumption). Qed. (** Disassociativity *) Lemma max_min_disassoc : forall n m p, Zmin n (Zmax m p) <= Zmax (Zmin n m) p. Proof. -intros; repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; - apply Zle_refl || (assumption || eapply Zle_trans; eassumption). + intros; repeat apply Zmax_case_strong; repeat apply Zmin_case_strong; intros; + apply Zle_refl || (assumption || eapply Zle_trans; eassumption). Qed. - - - - - - diff --git a/theories/ZArith/Zmisc.v b/theories/ZArith/Zmisc.v index 8246e324..d01cada6 100644 --- a/theories/ZArith/Zmisc.v +++ b/theories/ZArith/Zmisc.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmisc.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Zmisc.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import BinInt. Require Import Zcompare. @@ -20,78 +20,78 @@ Open Local Scope Z_scope. (** [n]th iteration of the function [f] *) Fixpoint iter_nat (n:nat) (A:Set) (f:A -> A) (x:A) {struct n} : A := match n with - | O => x - | S n' => f (iter_nat n' A f x) + | O => x + | S n' => f (iter_nat n' A f x) end. Fixpoint iter_pos (n:positive) (A:Set) (f:A -> A) (x:A) {struct n} : A := match n with - | xH => f x - | xO n' => iter_pos n' A f (iter_pos n' A f x) - | xI n' => f (iter_pos n' A f (iter_pos n' A f x)) + | xH => f x + | xO n' => iter_pos n' A f (iter_pos n' A f x) + | xI n' => f (iter_pos n' A f (iter_pos n' A f x)) end. Definition iter (n:Z) (A:Set) (f:A -> A) (x:A) := match n with - | Z0 => x - | Zpos p => iter_pos p A f x - | Zneg p => x + | Z0 => x + | Zpos p => iter_pos p A f x + | Zneg p => x end. Theorem iter_nat_plus : - forall (n m:nat) (A:Set) (f:A -> A) (x:A), - iter_nat (n + m) A f x = iter_nat n A f (iter_nat m A f x). + forall (n m:nat) (A:Set) (f:A -> A) (x:A), + iter_nat (n + m) A f x = iter_nat n A f (iter_nat m A f x). Proof. -simple induction n; - [ simpl in |- *; auto with arith - | intros; simpl in |- *; apply f_equal with (f := f); apply H ]. + simple induction n; + [ simpl in |- *; auto with arith + | intros; simpl in |- *; apply f_equal with (f := f); apply H ]. Qed. Theorem iter_nat_of_P : - forall (p:positive) (A:Set) (f:A -> A) (x:A), - iter_pos p A f x = iter_nat (nat_of_P p) A f x. + forall (p:positive) (A:Set) (f:A -> A) (x:A), + iter_pos p A f x = iter_nat (nat_of_P p) A f x. Proof. -intro n; induction n as [p H| p H| ]; - [ intros; simpl in |- *; rewrite (H A f x); - rewrite (H A f (iter_nat (nat_of_P p) A f x)); - rewrite (ZL6 p); symmetry in |- *; apply f_equal with (f := f); - apply iter_nat_plus - | intros; unfold nat_of_P in |- *; simpl in |- *; rewrite (H A f x); - rewrite (H A f (iter_nat (nat_of_P p) A f x)); - rewrite (ZL6 p); symmetry in |- *; apply iter_nat_plus - | simpl in |- *; auto with arith ]. + intro n; induction n as [p H| p H| ]; + [ intros; simpl in |- *; rewrite (H A f x); + rewrite (H A f (iter_nat (nat_of_P p) A f x)); + rewrite (ZL6 p); symmetry in |- *; apply f_equal with (f := f); + apply iter_nat_plus + | intros; unfold nat_of_P in |- *; simpl in |- *; rewrite (H A f x); + rewrite (H A f (iter_nat (nat_of_P p) A f x)); + rewrite (ZL6 p); symmetry in |- *; apply iter_nat_plus + | simpl in |- *; auto with arith ]. Qed. Theorem iter_pos_plus : - forall (p q:positive) (A:Set) (f:A -> A) (x:A), - iter_pos (p + q) A f x = iter_pos p A f (iter_pos q A f x). + forall (p q:positive) (A:Set) (f:A -> A) (x:A), + iter_pos (p + q) A f x = iter_pos p A f (iter_pos q A f x). Proof. -intros n m; intros. -rewrite (iter_nat_of_P m A f x). -rewrite (iter_nat_of_P n A f (iter_nat (nat_of_P m) A f x)). -rewrite (iter_nat_of_P (n + m) A f x). -rewrite (nat_of_P_plus_morphism n m). -apply iter_nat_plus. + intros n m; intros. + rewrite (iter_nat_of_P m A f x). + rewrite (iter_nat_of_P n A f (iter_nat (nat_of_P m) A f x)). + rewrite (iter_nat_of_P (n + m) A f x). + rewrite (nat_of_P_plus_morphism n m). + apply iter_nat_plus. Qed. (** Preservation of invariants : if [f : A->A] preserves the invariant [Inv], then the iterates of [f] also preserve it. *) Theorem iter_nat_invariant : - forall (n:nat) (A:Set) (f:A -> A) (Inv:A -> Prop), - (forall x:A, Inv x -> Inv (f x)) -> - forall x:A, Inv x -> Inv (iter_nat n A f x). + forall (n:nat) (A:Set) (f:A -> A) (Inv:A -> Prop), + (forall x:A, Inv x -> Inv (f x)) -> + forall x:A, Inv x -> Inv (iter_nat n A f x). Proof. -simple induction n; intros; - [ trivial with arith - | simpl in |- *; apply H0 with (x := iter_nat n0 A f x); apply H; - trivial with arith ]. + simple induction n; intros; + [ trivial with arith + | simpl in |- *; apply H0 with (x := iter_nat n0 A f x); apply H; + trivial with arith ]. Qed. Theorem iter_pos_invariant : - forall (p:positive) (A:Set) (f:A -> A) (Inv:A -> Prop), - (forall x:A, Inv x -> Inv (f x)) -> - forall x:A, Inv x -> Inv (iter_pos p A f x). + forall (p:positive) (A:Set) (f:A -> A) (Inv:A -> Prop), + (forall x:A, Inv x -> Inv (f x)) -> + forall x:A, Inv x -> Inv (iter_pos p A f x). Proof. -intros; rewrite iter_nat_of_P; apply iter_nat_invariant; trivial with arith. + intros; rewrite iter_nat_of_P; apply iter_nat_invariant; trivial with arith. Qed. diff --git a/theories/ZArith/Znat.v b/theories/ZArith/Znat.v index 3e27878c..f0a3d47b 100644 --- a/theories/ZArith/Znat.v +++ b/theories/ZArith/Znat.v @@ -6,11 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Znat.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Znat.v 9302 2006-10-27 21:21:17Z barras $ i*) (** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) -Require Export Arith. +Require Export Arith_base. Require Import BinPos. Require Import BinInt. Require Import Zcompare. @@ -23,116 +23,116 @@ Open Local Scope Z_scope. Definition neq (x y:nat) := x <> y. -(**********************************************************************) +(************************************************) (** Properties of the injection from nat into Z *) Theorem inj_S : forall n:nat, Z_of_nat (S n) = Zsucc (Z_of_nat n). Proof. -intro y; induction y as [| n H]; - [ unfold Zsucc in |- *; simpl in |- *; trivial with arith - | change (Zpos (Psucc (P_of_succ_nat n)) = Zsucc (Z_of_nat (S n))) in |- *; - rewrite Zpos_succ_morphism; trivial with arith ]. + intro y; induction y as [| n H]; + [ unfold Zsucc in |- *; simpl in |- *; trivial with arith + | change (Zpos (Psucc (P_of_succ_nat n)) = Zsucc (Z_of_nat (S n))) in |- *; + rewrite Zpos_succ_morphism; trivial with arith ]. Qed. Theorem inj_plus : forall n m:nat, Z_of_nat (n + m) = Z_of_nat n + Z_of_nat m. Proof. -intro x; induction x as [| n H]; intro y; destruct y as [| m]; - [ simpl in |- *; trivial with arith - | simpl in |- *; trivial with arith - | simpl in |- *; rewrite <- plus_n_O; trivial with arith - | change (Z_of_nat (S (n + S m)) = Z_of_nat (S n) + Z_of_nat (S m)) in |- *; - rewrite inj_S; rewrite H; do 2 rewrite inj_S; rewrite Zplus_succ_l; - trivial with arith ]. + intro x; induction x as [| n H]; intro y; destruct y as [| m]; + [ simpl in |- *; trivial with arith + | simpl in |- *; trivial with arith + | simpl in |- *; rewrite <- plus_n_O; trivial with arith + | change (Z_of_nat (S (n + S m)) = Z_of_nat (S n) + Z_of_nat (S m)) in |- *; + rewrite inj_S; rewrite H; do 2 rewrite inj_S; rewrite Zplus_succ_l; + trivial with arith ]. Qed. - + Theorem inj_mult : forall n m:nat, Z_of_nat (n * m) = Z_of_nat n * Z_of_nat m. Proof. -intro x; induction x as [| n H]; - [ simpl in |- *; trivial with arith - | intro y; rewrite inj_S; rewrite <- Zmult_succ_l_reverse; rewrite <- H; - rewrite <- inj_plus; simpl in |- *; rewrite plus_comm; - trivial with arith ]. + intro x; induction x as [| n H]; + [ simpl in |- *; trivial with arith + | intro y; rewrite inj_S; rewrite <- Zmult_succ_l_reverse; rewrite <- H; + rewrite <- inj_plus; simpl in |- *; rewrite plus_comm; + trivial with arith ]. Qed. Theorem inj_neq : forall n m:nat, neq n m -> Zne (Z_of_nat n) (Z_of_nat m). Proof. -unfold neq, Zne, not in |- *; intros x y H1 H2; apply H1; generalize H2; - case x; case y; intros; - [ auto with arith - | discriminate H0 - | discriminate H0 - | simpl in H0; injection H0; - do 2 rewrite <- nat_of_P_o_P_of_succ_nat_eq_succ; - intros E; rewrite E; auto with arith ]. + unfold neq, Zne, not in |- *; intros x y H1 H2; apply H1; generalize H2; + case x; case y; intros; + [ auto with arith + | discriminate H0 + | discriminate H0 + | simpl in H0; injection H0; + do 2 rewrite <- nat_of_P_o_P_of_succ_nat_eq_succ; + intros E; rewrite E; auto with arith ]. Qed. Theorem inj_le : forall n m:nat, (n <= m)%nat -> Z_of_nat n <= Z_of_nat m. Proof. -intros x y; intros H; elim H; - [ unfold Zle in |- *; elim (Zcompare_Eq_iff_eq (Z_of_nat x) (Z_of_nat x)); - intros H1 H2; rewrite H2; [ discriminate | trivial with arith ] - | intros m H1 H2; apply Zle_trans with (Z_of_nat m); - [ assumption | rewrite inj_S; apply Zle_succ ] ]. + intros x y; intros H; elim H; + [ unfold Zle in |- *; elim (Zcompare_Eq_iff_eq (Z_of_nat x) (Z_of_nat x)); + intros H1 H2; rewrite H2; [ discriminate | trivial with arith ] + | intros m H1 H2; apply Zle_trans with (Z_of_nat m); + [ assumption | rewrite inj_S; apply Zle_succ ] ]. Qed. Theorem inj_lt : forall n m:nat, (n < m)%nat -> Z_of_nat n < Z_of_nat m. Proof. -intros x y H; apply Zgt_lt; apply Zlt_succ_gt; rewrite <- inj_S; apply inj_le; - exact H. + intros x y H; apply Zgt_lt; apply Zlt_succ_gt; rewrite <- inj_S; apply inj_le; + exact H. Qed. Theorem inj_gt : forall n m:nat, (n > m)%nat -> Z_of_nat n > Z_of_nat m. Proof. -intros x y H; apply Zlt_gt; apply inj_lt; exact H. + intros x y H; apply Zlt_gt; apply inj_lt; exact H. Qed. Theorem inj_ge : forall n m:nat, (n >= m)%nat -> Z_of_nat n >= Z_of_nat m. Proof. -intros x y H; apply Zle_ge; apply inj_le; apply H. + intros x y H; apply Zle_ge; apply inj_le; apply H. Qed. Theorem inj_eq : forall n m:nat, n = m -> Z_of_nat n = Z_of_nat m. Proof. -intros x y H; rewrite H; trivial with arith. + intros x y H; rewrite H; trivial with arith. Qed. Theorem intro_Z : - forall n:nat, exists y : Z, Z_of_nat n = y /\ 0 <= y * 1 + 0. + forall n:nat, exists y : Z, Z_of_nat n = y /\ 0 <= y * 1 + 0. Proof. -intros x; exists (Z_of_nat x); split; - [ trivial with arith - | rewrite Zmult_comm; rewrite Zmult_1_l; rewrite Zplus_0_r; - unfold Zle in |- *; elim x; intros; simpl in |- *; - discriminate ]. + intros x; exists (Z_of_nat x); split; + [ trivial with arith + | rewrite Zmult_comm; rewrite Zmult_1_l; rewrite Zplus_0_r; + unfold Zle in |- *; elim x; intros; simpl in |- *; + discriminate ]. Qed. Theorem inj_minus1 : - forall n m:nat, (m <= n)%nat -> Z_of_nat (n - m) = Z_of_nat n - Z_of_nat m. + forall n m:nat, (m <= n)%nat -> Z_of_nat (n - m) = Z_of_nat n - Z_of_nat m. Proof. -intros x y H; apply (Zplus_reg_l (Z_of_nat y)); unfold Zminus in |- *; - rewrite Zplus_permute; rewrite Zplus_opp_r; rewrite <- inj_plus; - rewrite <- (le_plus_minus y x H); rewrite Zplus_0_r; - trivial with arith. + intros x y H; apply (Zplus_reg_l (Z_of_nat y)); unfold Zminus in |- *; + rewrite Zplus_permute; rewrite Zplus_opp_r; rewrite <- inj_plus; + rewrite <- (le_plus_minus y x H); rewrite Zplus_0_r; + trivial with arith. Qed. Theorem inj_minus2 : forall n m:nat, (m > n)%nat -> Z_of_nat (n - m) = 0. Proof. -intros x y H; rewrite not_le_minus_0; - [ trivial with arith | apply gt_not_le; assumption ]. + intros x y H; rewrite not_le_minus_0; + [ trivial with arith | apply gt_not_le; assumption ]. Qed. Theorem Zpos_eq_Z_of_nat_o_nat_of_P : - forall p:positive, Zpos p = Z_of_nat (nat_of_P p). + forall p:positive, Zpos p = Z_of_nat (nat_of_P p). Proof. -intros x; elim x; simpl in |- *; auto. -intros p H; rewrite ZL6. -apply f_equal with (f := Zpos). -apply nat_of_P_inj. -rewrite nat_of_P_o_P_of_succ_nat_eq_succ; unfold nat_of_P in |- *; - simpl in |- *. -rewrite ZL6; auto. -intros p H; unfold nat_of_P in |- *; simpl in |- *. -rewrite ZL6; simpl in |- *. -rewrite inj_plus; repeat rewrite <- H. -rewrite Zpos_xO; simpl in |- *; rewrite Pplus_diag; reflexivity. + intros x; elim x; simpl in |- *; auto. + intros p H; rewrite ZL6. + apply f_equal with (f := Zpos). + apply nat_of_P_inj. + rewrite nat_of_P_o_P_of_succ_nat_eq_succ; unfold nat_of_P in |- *; + simpl in |- *. + rewrite ZL6; auto. + intros p H; unfold nat_of_P in |- *; simpl in |- *. + rewrite ZL6; simpl in |- *. + rewrite inj_plus; repeat rewrite <- H. + rewrite Zpos_xO; simpl in |- *; rewrite Pplus_diag; reflexivity. Qed. diff --git a/theories/ZArith/Znumtheory.v b/theories/ZArith/Znumtheory.v index e722b679..d89ec052 100644 --- a/theories/ZArith/Znumtheory.v +++ b/theories/ZArith/Znumtheory.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Znumtheory.v 8990 2006-06-26 13:57:44Z notin $ i*) +(*i $Id: Znumtheory.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import ZArith_base. Require Import ZArithRing. @@ -38,91 +38,91 @@ Notation "( a | b )" := (Zdivide a b) (at level 0) : Z_scope. Lemma Zdivide_refl : forall a:Z, (a | a). Proof. -intros; apply Zdivide_intro with 1; ring. + intros; apply Zdivide_intro with 1; ring. Qed. Lemma Zone_divide : forall a:Z, (1 | a). Proof. -intros; apply Zdivide_intro with a; ring. + intros; apply Zdivide_intro with a; ring. Qed. Lemma Zdivide_0 : forall a:Z, (a | 0). Proof. -intros; apply Zdivide_intro with 0; ring. + intros; apply Zdivide_intro with 0; ring. Qed. Hint Resolve Zdivide_refl Zone_divide Zdivide_0: zarith. Lemma Zmult_divide_compat_l : forall a b c:Z, (a | b) -> (c * a | c * b). Proof. -simple induction 1; intros; apply Zdivide_intro with q. -rewrite H0; ring. + simple induction 1; intros; apply Zdivide_intro with q. + rewrite H0; ring. Qed. Lemma Zmult_divide_compat_r : forall a b c:Z, (a | b) -> (a * c | b * c). Proof. -intros a b c; rewrite (Zmult_comm a c); rewrite (Zmult_comm b c). -apply Zmult_divide_compat_l; trivial. + intros a b c; rewrite (Zmult_comm a c); rewrite (Zmult_comm b c). + apply Zmult_divide_compat_l; trivial. Qed. Hint Resolve Zmult_divide_compat_l Zmult_divide_compat_r: zarith. Lemma Zdivide_plus_r : forall a b c:Z, (a | b) -> (a | c) -> (a | b + c). Proof. -simple induction 1; intros q Hq; simple induction 1; intros q' Hq'. -apply Zdivide_intro with (q + q'). -rewrite Hq; rewrite Hq'; ring. + simple induction 1; intros q Hq; simple induction 1; intros q' Hq'. + apply Zdivide_intro with (q + q'). + rewrite Hq; rewrite Hq'; ring. Qed. Lemma Zdivide_opp_r : forall a b:Z, (a | b) -> (a | - b). Proof. -simple induction 1; intros; apply Zdivide_intro with (- q). -rewrite H0; ring. + simple induction 1; intros; apply Zdivide_intro with (- q). + rewrite H0; ring. Qed. Lemma Zdivide_opp_r_rev : forall a b:Z, (a | - b) -> (a | b). Proof. -intros; replace b with (- - b). apply Zdivide_opp_r; trivial. ring. + intros; replace b with (- - b). apply Zdivide_opp_r; trivial. ring. Qed. Lemma Zdivide_opp_l : forall a b:Z, (a | b) -> (- a | b). Proof. -simple induction 1; intros; apply Zdivide_intro with (- q). -rewrite H0; ring. + simple induction 1; intros; apply Zdivide_intro with (- q). + rewrite H0; ring. Qed. Lemma Zdivide_opp_l_rev : forall a b:Z, (- a | b) -> (a | b). Proof. -intros; replace a with (- - a). apply Zdivide_opp_l; trivial. ring. + intros; replace a with (- - a). apply Zdivide_opp_l; trivial. ring. Qed. Lemma Zdivide_minus_l : forall a b c:Z, (a | b) -> (a | c) -> (a | b - c). Proof. -simple induction 1; intros q Hq; simple induction 1; intros q' Hq'. -apply Zdivide_intro with (q - q'). -rewrite Hq; rewrite Hq'; ring. + simple induction 1; intros q Hq; simple induction 1; intros q' Hq'. + apply Zdivide_intro with (q - q'). + rewrite Hq; rewrite Hq'; ring. Qed. Lemma Zdivide_mult_l : forall a b c:Z, (a | b) -> (a | b * c). Proof. -simple induction 1; intros q Hq; apply Zdivide_intro with (q * c). -rewrite Hq; ring. + simple induction 1; intros q Hq; apply Zdivide_intro with (q * c). + rewrite Hq; ring. Qed. Lemma Zdivide_mult_r : forall a b c:Z, (a | c) -> (a | b * c). Proof. -simple induction 1; intros q Hq; apply Zdivide_intro with (q * b). -rewrite Hq; ring. + simple induction 1; intros q Hq; apply Zdivide_intro with (q * b). + rewrite Hq; ring. Qed. Lemma Zdivide_factor_r : forall a b:Z, (a | a * b). Proof. -intros; apply Zdivide_intro with b; ring. + intros; apply Zdivide_intro with b; ring. Qed. Lemma Zdivide_factor_l : forall a b:Z, (a | b * a). Proof. -intros; apply Zdivide_intro with b; ring. + intros; apply Zdivide_intro with b; ring. Qed. Hint Resolve Zdivide_plus_r Zdivide_opp_r Zdivide_opp_r_rev Zdivide_opp_l @@ -133,7 +133,7 @@ Hint Resolve Zdivide_plus_r Zdivide_opp_r Zdivide_opp_r_rev Zdivide_opp_l Lemma Zmult_one : forall x y:Z, x >= 0 -> x * y = 1 -> x = 1. Proof. -intros x y H H0; destruct (Zmult_1_inversion_l _ _ H0) as [Hpos| Hneg]. + intros x y H H0; destruct (Zmult_1_inversion_l _ _ H0) as [Hpos| Hneg]. assumption. rewrite Hneg in H; simpl in H. contradiction (Zle_not_lt 0 (-1)). @@ -145,11 +145,11 @@ Qed. Lemma Zdivide_1 : forall x:Z, (x | 1) -> x = 1 \/ x = -1. Proof. -simple induction 1; intros. -elim (Z_lt_ge_dec 0 x); [ left | right ]. -apply Zmult_one with q; auto with zarith; rewrite H0; ring. -assert (- x = 1); auto with zarith. -apply Zmult_one with (- q); auto with zarith; rewrite H0; ring. + simple induction 1; intros. + elim (Z_lt_ge_dec 0 x); [ left | right ]. + apply Zmult_one with q; auto with zarith; rewrite H0; ring. + assert (- x = 1); auto with zarith. + apply Zmult_one with (- q); auto with zarith; rewrite H0; ring. Qed. (** If [a] divides [b] and [b] divides [a] then [a] is [b] or [-b]. *) @@ -164,7 +164,7 @@ left; rewrite H0; rewrite e; ring. assert (Hqq0 : q0 * q = 1). apply Zmult_reg_l with a. assumption. -ring. +ring_simplify. pattern a at 2 in |- *; rewrite H2; ring. assert (q | 1). rewrite <- Hqq0; auto with zarith. @@ -177,21 +177,21 @@ Qed. Lemma Zdivide_bounds : forall a b:Z, (a | b) -> b <> 0 -> Zabs a <= Zabs b. Proof. -simple induction 1; intros. -assert (Zabs b = Zabs q * Zabs a). - subst; apply Zabs_Zmult. -rewrite H2. -assert (H3 := Zabs_pos q). -assert (H4 := Zabs_pos a). -assert (Zabs q * Zabs a >= 1 * Zabs a); auto with zarith. -apply Zmult_ge_compat; auto with zarith. -elim (Z_lt_ge_dec (Zabs q) 1); [ intros | auto with zarith ]. -assert (Zabs q = 0). - omega. -assert (q = 0). - rewrite <- (Zabs_Zsgn q). -rewrite H5; auto with zarith. -subst q; omega. + simple induction 1; intros. + assert (Zabs b = Zabs q * Zabs a). + subst; apply Zabs_Zmult. + rewrite H2. + assert (H3 := Zabs_pos q). + assert (H4 := Zabs_pos a). + assert (Zabs q * Zabs a >= 1 * Zabs a); auto with zarith. + apply Zmult_ge_compat; auto with zarith. + elim (Z_lt_ge_dec (Zabs q) 1); [ intros | auto with zarith ]. + assert (Zabs q = 0). + omega. + assert (q = 0). + rewrite <- (Zabs_Zsgn q). + rewrite H5; auto with zarith. + subst q; omega. Qed. (** * Greatest common divisor (gcd). *) @@ -201,48 +201,48 @@ Qed. (We show later that the [gcd] is actually unique if we discard its sign.) *) Inductive Zis_gcd (a b d:Z) : Prop := - Zis_gcd_intro : - (d | a) -> - (d | b) -> (forall x:Z, (x | a) -> (x | b) -> (x | d)) -> Zis_gcd a b d. + Zis_gcd_intro : + (d | a) -> + (d | b) -> (forall x:Z, (x | a) -> (x | b) -> (x | d)) -> Zis_gcd a b d. (** Trivial properties of [gcd] *) Lemma Zis_gcd_sym : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a d. Proof. -simple induction 1; constructor; intuition. + simple induction 1; constructor; intuition. Qed. Lemma Zis_gcd_0 : forall a:Z, Zis_gcd a 0 a. Proof. -constructor; auto with zarith. + constructor; auto with zarith. Qed. Lemma Zis_gcd_1 : forall a, Zis_gcd a 1 1. Proof. -constructor; auto with zarith. + constructor; auto with zarith. Qed. Lemma Zis_gcd_refl : forall a, Zis_gcd a a a. Proof. -constructor; auto with zarith. + constructor; auto with zarith. Qed. Lemma Zis_gcd_minus : forall a b d:Z, Zis_gcd a (- b) d -> Zis_gcd b a d. Proof. -simple induction 1; constructor; intuition. + simple induction 1; constructor; intuition. Qed. Lemma Zis_gcd_opp : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a (- d). Proof. -simple induction 1; constructor; intuition. + simple induction 1; constructor; intuition. Qed. Lemma Zis_gcd_0_abs : forall a:Z, Zis_gcd 0 a (Zabs a). Proof. -intros a. -apply Zabs_ind. -intros; apply Zis_gcd_sym; apply Zis_gcd_0; auto. -intros; apply Zis_gcd_opp; apply Zis_gcd_0; auto. + intros a. + apply Zabs_ind. + intros; apply Zis_gcd_sym; apply Zis_gcd_0; auto. + intros; apply Zis_gcd_opp; apply Zis_gcd_0; auto. Qed. Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. @@ -253,18 +253,18 @@ Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. the following property. *) Lemma Zis_gcd_for_euclid : - forall a b d q:Z, Zis_gcd b (a - q * b) d -> Zis_gcd a b d. + forall a b d q:Z, Zis_gcd b (a - q * b) d -> Zis_gcd a b d. Proof. -simple induction 1; constructor; intuition. -replace a with (a - q * b + q * b). auto with zarith. ring. + simple induction 1; constructor; intuition. + replace a with (a - q * b + q * b). auto with zarith. ring. Qed. Lemma Zis_gcd_for_euclid2 : - forall b d q r:Z, Zis_gcd r b d -> Zis_gcd b (b * q + r) d. + forall b d q r:Z, Zis_gcd r b d -> Zis_gcd b (b * q + r) d. Proof. -simple induction 1; constructor; intuition. -apply H2; auto. -replace r with (b * q + r - b * q). auto with zarith. ring. + simple induction 1; constructor; intuition. + apply H2; auto. + replace r with (b * q + r - b * q). auto with zarith. ring. Qed. (** We implement the extended version of Euclid's algorithm, @@ -274,117 +274,117 @@ Qed. Section extended_euclid_algorithm. -Variables a b : Z. + Variables a b : Z. -(** The specification of Euclid's algorithm is the existence of - [u], [v] and [d] such that [ua+vb=d] and [(gcd a b d)]. *) + (** The specification of Euclid's algorithm is the existence of + [u], [v] and [d] such that [ua+vb=d] and [(gcd a b d)]. *) -Inductive Euclid : Set := + Inductive Euclid : Set := Euclid_intro : - forall u v d:Z, u * a + v * b = d -> Zis_gcd a b d -> Euclid. - -(** The recursive part of Euclid's algorithm uses well-founded - recursion of non-negative integers. It maintains 6 integers - [u1,u2,u3,v1,v2,v3] such that the following invariant holds: - [u1*a+u2*b=u3] and [v1*a+v2*b=v3] and [gcd(u2,v3)=gcd(a,b)]. - *) - -Lemma euclid_rec : - forall v3:Z, - 0 <= v3 -> - forall u1 u2 u3 v1 v2:Z, - u1 * a + u2 * b = u3 -> - v1 * a + v2 * b = v3 -> - (forall d:Z, Zis_gcd u3 v3 d -> Zis_gcd a b d) -> Euclid. -Proof. -intros v3 Hv3; generalize Hv3; pattern v3 in |- *. -apply Zlt_0_rec. -clear v3 Hv3; intros. -elim (Z_zerop x); intro. -apply Euclid_intro with (u := u1) (v := u2) (d := u3). -assumption. -apply H3. -rewrite a0; auto with zarith. -set (q := u3 / x) in *. -assert (Hq : 0 <= u3 - q * x < x). -replace (u3 - q * x) with (u3 mod x). -apply Z_mod_lt; omega. -assert (xpos : x > 0). omega. -generalize (Z_div_mod_eq u3 x xpos). -unfold q in |- *. -intro eq; pattern u3 at 2 in |- *; rewrite eq; ring. -apply (H (u3 - q * x) Hq (proj1 Hq) v1 v2 x (u1 - q * v1) (u2 - q * v2)). -tauto. -replace ((u1 - q * v1) * a + (u2 - q * v2) * b) with - (u1 * a + u2 * b - q * (v1 * a + v2 * b)). -rewrite H1; rewrite H2; trivial. -ring. -intros; apply H3. -apply Zis_gcd_for_euclid with q; assumption. -assumption. -Qed. - -(** We get Euclid's algorithm by applying [euclid_rec] on - [1,0,a,0,1,b] when [b>=0] and [1,0,a,0,-1,-b] when [b<0]. *) - -Lemma euclid : Euclid. -Proof. -case (Z_le_gt_dec 0 b); intro. -intros; - apply euclid_rec with - (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := 1) (v3 := b); - auto with zarith; ring. -intros; - apply euclid_rec with - (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := -1) (v3 := - b); - auto with zarith; try ring. -Qed. + forall u v d:Z, u * a + v * b = d -> Zis_gcd a b d -> Euclid. + + (** The recursive part of Euclid's algorithm uses well-founded + recursion of non-negative integers. It maintains 6 integers + [u1,u2,u3,v1,v2,v3] such that the following invariant holds: + [u1*a+u2*b=u3] and [v1*a+v2*b=v3] and [gcd(u2,v3)=gcd(a,b)]. + *) + + Lemma euclid_rec : + forall v3:Z, + 0 <= v3 -> + forall u1 u2 u3 v1 v2:Z, + u1 * a + u2 * b = u3 -> + v1 * a + v2 * b = v3 -> + (forall d:Z, Zis_gcd u3 v3 d -> Zis_gcd a b d) -> Euclid. + Proof. + intros v3 Hv3; generalize Hv3; pattern v3 in |- *. + apply Zlt_0_rec. + clear v3 Hv3; intros. + elim (Z_zerop x); intro. + apply Euclid_intro with (u := u1) (v := u2) (d := u3). + assumption. + apply H3. + rewrite a0; auto with zarith. + set (q := u3 / x) in *. + assert (Hq : 0 <= u3 - q * x < x). + replace (u3 - q * x) with (u3 mod x). + apply Z_mod_lt; omega. + assert (xpos : x > 0). omega. + generalize (Z_div_mod_eq u3 x xpos). + unfold q in |- *. + intro eq; pattern u3 at 2 in |- *; rewrite eq; ring. + apply (H (u3 - q * x) Hq (proj1 Hq) v1 v2 x (u1 - q * v1) (u2 - q * v2)). + tauto. + replace ((u1 - q * v1) * a + (u2 - q * v2) * b) with + (u1 * a + u2 * b - q * (v1 * a + v2 * b)). + rewrite H1; rewrite H2; trivial. + ring. + intros; apply H3. + apply Zis_gcd_for_euclid with q; assumption. + assumption. + Qed. + + (** We get Euclid's algorithm by applying [euclid_rec] on + [1,0,a,0,1,b] when [b>=0] and [1,0,a,0,-1,-b] when [b<0]. *) + + Lemma euclid : Euclid. + Proof. + case (Z_le_gt_dec 0 b); intro. + intros; + apply euclid_rec with + (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := 1) (v3 := b); + auto with zarith; ring. + intros; + apply euclid_rec with + (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := -1) (v3 := - b); + auto with zarith; try ring. + Qed. End extended_euclid_algorithm. Theorem Zis_gcd_uniqueness_apart_sign : - forall a b d d':Z, Zis_gcd a b d -> Zis_gcd a b d' -> d = d' \/ d = - d'. + forall a b d d':Z, Zis_gcd a b d -> Zis_gcd a b d' -> d = d' \/ d = - d'. Proof. -simple induction 1. -intros H1 H2 H3; simple induction 1; intros. -generalize (H3 d' H4 H5); intro Hd'd. -generalize (H6 d H1 H2); intro Hdd'. -exact (Zdivide_antisym d d' Hdd' Hd'd). + simple induction 1. + intros H1 H2 H3; simple induction 1; intros. + generalize (H3 d' H4 H5); intro Hd'd. + generalize (H6 d H1 H2); intro Hdd'. + exact (Zdivide_antisym d d' Hdd' Hd'd). Qed. (** * Bezout's coefficients *) Inductive Bezout (a b d:Z) : Prop := - Bezout_intro : forall u v:Z, u * a + v * b = d -> Bezout a b d. + Bezout_intro : forall u v:Z, u * a + v * b = d -> Bezout a b d. (** Existence of Bezout's coefficients for the [gcd] of [a] and [b] *) Lemma Zis_gcd_bezout : forall a b d:Z, Zis_gcd a b d -> Bezout a b d. Proof. -intros a b d Hgcd. -elim (euclid a b); intros u v d0 e g. -generalize (Zis_gcd_uniqueness_apart_sign a b d d0 Hgcd g). -intro H; elim H; clear H; intros. -apply Bezout_intro with u v. -rewrite H; assumption. -apply Bezout_intro with (- u) (- v). -rewrite H; rewrite <- e; ring. + intros a b d Hgcd. + elim (euclid a b); intros u v d0 e g. + generalize (Zis_gcd_uniqueness_apart_sign a b d d0 Hgcd g). + intro H; elim H; clear H; intros. + apply Bezout_intro with u v. + rewrite H; assumption. + apply Bezout_intro with (- u) (- v). + rewrite H; rewrite <- e; ring. Qed. (** gcd of [ca] and [cb] is [c gcd(a,b)]. *) Lemma Zis_gcd_mult : - forall a b c d:Z, Zis_gcd a b d -> Zis_gcd (c * a) (c * b) (c * d). -Proof. -intros a b c d; simple induction 1; constructor; intuition. -elim (Zis_gcd_bezout a b d H); intros. -elim H3; intros. -elim H4; intros. -apply Zdivide_intro with (u * q + v * q0). -rewrite <- H5. -replace (c * (u * a + v * b)) with (u * (c * a) + v * (c * b)). -rewrite H6; rewrite H7; ring. -ring. + forall a b c d:Z, Zis_gcd a b d -> Zis_gcd (c * a) (c * b) (c * d). +Proof. + intros a b c d; simple induction 1; constructor; intuition. + elim (Zis_gcd_bezout a b d H); intros. + elim H3; intros. + elim H4; intros. + apply Zdivide_intro with (u * q + v * q0). + rewrite <- H5. + replace (c * (u * a + v * b)) with (u * (c * a) + v * (c * b)). + rewrite H6; rewrite H7; ring. + ring. Qed. @@ -397,13 +397,13 @@ Definition rel_prime (a b:Z) : Prop := Zis_gcd a b 1. Lemma rel_prime_bezout : forall a b:Z, rel_prime a b -> Bezout a b 1. Proof. -intros a b; exact (Zis_gcd_bezout a b 1). + intros a b; exact (Zis_gcd_bezout a b 1). Qed. Lemma bezout_rel_prime : forall a b:Z, Bezout a b 1 -> rel_prime a b. Proof. -simple induction 1; constructor; auto with zarith. -intros. rewrite <- H0; auto with zarith. + simple induction 1; constructor; auto with zarith. + intros. rewrite <- H0; auto with zarith. Qed. (** Gauss's theorem: if [a] divides [bc] and if [a] and [b] are @@ -411,134 +411,134 @@ Qed. Theorem Gauss : forall a b c:Z, (a | b * c) -> rel_prime a b -> (a | c). Proof. -intros. elim (rel_prime_bezout a b H0); intros. -replace c with (c * 1); [ idtac | ring ]. -rewrite <- H1. -replace (c * (u * a + v * b)) with (c * u * a + v * (b * c)); - [ eauto with zarith | ring ]. + intros. elim (rel_prime_bezout a b H0); intros. + replace c with (c * 1); [ idtac | ring ]. + rewrite <- H1. + replace (c * (u * a + v * b)) with (c * u * a + v * (b * c)); + [ eauto with zarith | ring ]. Qed. (** If [a] is relatively prime to [b] and [c], then it is to [bc] *) Lemma rel_prime_mult : - forall a b c:Z, rel_prime a b -> rel_prime a c -> rel_prime a (b * c). + forall a b c:Z, rel_prime a b -> rel_prime a c -> rel_prime a (b * c). Proof. -intros a b c Hb Hc. -elim (rel_prime_bezout a b Hb); intros. -elim (rel_prime_bezout a c Hc); intros. -apply bezout_rel_prime. -apply Bezout_intro with - (u := u * u0 * a + v0 * c * u + u0 * v * b) (v := v * v0). -rewrite <- H. -replace (u * a + v * b) with ((u * a + v * b) * 1); [ idtac | ring ]. -rewrite <- H0. -ring. + intros a b c Hb Hc. + elim (rel_prime_bezout a b Hb); intros. + elim (rel_prime_bezout a c Hc); intros. + apply bezout_rel_prime. + apply Bezout_intro with + (u := u * u0 * a + v0 * c * u + u0 * v * b) (v := v * v0). + rewrite <- H. + replace (u * a + v * b) with ((u * a + v * b) * 1); [ idtac | ring ]. + rewrite <- H0. + ring. Qed. Lemma rel_prime_cross_prod : - forall a b c d:Z, - rel_prime a b -> - rel_prime c d -> b > 0 -> d > 0 -> a * d = b * c -> a = c /\ b = d. -Proof. -intros a b c d; intros. -elim (Zdivide_antisym b d). -split; auto with zarith. -rewrite H4 in H3. -rewrite Zmult_comm in H3. -apply Zmult_reg_l with d; auto with zarith. -intros; omega. -apply Gauss with a. -rewrite H3. -auto with zarith. -red in |- *; auto with zarith. -apply Gauss with c. -rewrite Zmult_comm. -rewrite <- H3. -auto with zarith. -red in |- *; auto with zarith. + forall a b c d:Z, + rel_prime a b -> + rel_prime c d -> b > 0 -> d > 0 -> a * d = b * c -> a = c /\ b = d. +Proof. + intros a b c d; intros. + elim (Zdivide_antisym b d). + split; auto with zarith. + rewrite H4 in H3. + rewrite Zmult_comm in H3. + apply Zmult_reg_l with d; auto with zarith. + intros; omega. + apply Gauss with a. + rewrite H3. + auto with zarith. + red in |- *; auto with zarith. + apply Gauss with c. + rewrite Zmult_comm. + rewrite <- H3. + auto with zarith. + red in |- *; auto with zarith. Qed. (** After factorization by a gcd, the original numbers are relatively prime. *) Lemma Zis_gcd_rel_prime : - forall a b g:Z, - b > 0 -> g >= 0 -> Zis_gcd a b g -> rel_prime (a / g) (b / g). -intros a b g; intros. -assert (g <> 0). - intro. - elim H1; intros. - elim H4; intros. - rewrite H2 in H6; subst b; omega. -unfold rel_prime in |- *. -destruct H1. -destruct H1 as (a',H1). -destruct H3 as (b',H3). -replace (a/g) with a'; - [|rewrite H1; rewrite Z_div_mult; auto with zarith]. -replace (b/g) with b'; - [|rewrite H3; rewrite Z_div_mult; auto with zarith]. -constructor. -exists a'; auto with zarith. -exists b'; auto with zarith. -intros x (xa,H5) (xb,H6). -destruct (H4 (x*g)). -exists xa; rewrite Zmult_assoc; rewrite <- H5; auto. -exists xb; rewrite Zmult_assoc; rewrite <- H6; auto. -replace g with (1*g) in H7; auto with zarith. -do 2 rewrite Zmult_assoc in H7. -generalize (Zmult_reg_r _ _ _ H2 H7); clear H7; intros. -rewrite Zmult_1_r in H7. -exists q; auto with zarith. + forall a b g:Z, + b > 0 -> g >= 0 -> Zis_gcd a b g -> rel_prime (a / g) (b / g). + intros a b g; intros. + assert (g <> 0). + intro. + elim H1; intros. + elim H4; intros. + rewrite H2 in H6; subst b; omega. + unfold rel_prime in |- *. + destruct H1. + destruct H1 as (a',H1). + destruct H3 as (b',H3). + replace (a/g) with a'; + [|rewrite H1; rewrite Z_div_mult; auto with zarith]. + replace (b/g) with b'; + [|rewrite H3; rewrite Z_div_mult; auto with zarith]. + constructor. + exists a'; auto with zarith. + exists b'; auto with zarith. + intros x (xa,H5) (xb,H6). + destruct (H4 (x*g)). + exists xa; rewrite Zmult_assoc; rewrite <- H5; auto. + exists xb; rewrite Zmult_assoc; rewrite <- H6; auto. + replace g with (1*g) in H7; auto with zarith. + do 2 rewrite Zmult_assoc in H7. + generalize (Zmult_reg_r _ _ _ H2 H7); clear H7; intros. + rewrite Zmult_1_r in H7. + exists q; auto with zarith. Qed. (** * Primality *) Inductive prime (p:Z) : Prop := - prime_intro : - 1 < p -> (forall n:Z, 1 <= n < p -> rel_prime n p) -> prime p. + prime_intro : + 1 < p -> (forall n:Z, 1 <= n < p -> rel_prime n p) -> prime p. (** The sole divisors of a prime number [p] are [-1], [1], [p] and [-p]. *) Lemma prime_divisors : - forall p:Z, - prime p -> forall a:Z, (a | p) -> a = -1 \/ a = 1 \/ a = p \/ a = - p. -Proof. -simple induction 1; intros. -assert - (a = - p \/ - p < a < -1 \/ a = -1 \/ a = 0 \/ a = 1 \/ 1 < a < p \/ a = p). -assert (Zabs a <= Zabs p). apply Zdivide_bounds; [ assumption | omega ]. -generalize H3. -pattern (Zabs a) in |- *; apply Zabs_ind; pattern (Zabs p) in |- *; - apply Zabs_ind; intros; omega. -intuition idtac. -(* -p < a < -1 *) -absurd (rel_prime (- a) p); intuition. -inversion H3. -assert (- a | - a); auto with zarith. -assert (- a | p); auto with zarith. -generalize (H8 (- a) H9 H10); intuition idtac. -generalize (Zdivide_1 (- a) H11); intuition. -(* a = 0 *) -inversion H2. subst a; omega. -(* 1 < a < p *) -absurd (rel_prime a p); intuition. -inversion H3. -assert (a | a); auto with zarith. -assert (a | p); auto with zarith. -generalize (H8 a H9 H10); intuition idtac. -generalize (Zdivide_1 a H11); intuition. + forall p:Z, + prime p -> forall a:Z, (a | p) -> a = -1 \/ a = 1 \/ a = p \/ a = - p. +Proof. + simple induction 1; intros. + assert + (a = - p \/ - p < a < -1 \/ a = -1 \/ a = 0 \/ a = 1 \/ 1 < a < p \/ a = p). + assert (Zabs a <= Zabs p). apply Zdivide_bounds; [ assumption | omega ]. + generalize H3. + pattern (Zabs a) in |- *; apply Zabs_ind; pattern (Zabs p) in |- *; + apply Zabs_ind; intros; omega. + intuition idtac. + (* -p < a < -1 *) + absurd (rel_prime (- a) p); intuition. + inversion H3. + assert (- a | - a); auto with zarith. + assert (- a | p); auto with zarith. + generalize (H8 (- a) H9 H10); intuition idtac. + generalize (Zdivide_1 (- a) H11); intuition. + (* a = 0 *) + inversion H2. subst a; omega. + (* 1 < a < p *) + absurd (rel_prime a p); intuition. + inversion H3. + assert (a | a); auto with zarith. + assert (a | p); auto with zarith. + generalize (H8 a H9 H10); intuition idtac. + generalize (Zdivide_1 a H11); intuition. Qed. (** A prime number is relatively prime with any number it does not divide *) Lemma prime_rel_prime : - forall p:Z, prime p -> forall a:Z, ~ (p | a) -> rel_prime p a. + forall p:Z, prime p -> forall a:Z, ~ (p | a) -> rel_prime p a. Proof. -simple induction 1; intros. -constructor; intuition. -elim (prime_divisors p H x H3); intuition; subst; auto with zarith. -absurd (p | a); auto with zarith. -absurd (p | a); intuition. + simple induction 1; intros. + constructor; intuition. + elim (prime_divisors p H x H3); intuition; subst; auto with zarith. + absurd (p | a); auto with zarith. + absurd (p | a); intuition. Qed. Hint Resolve prime_rel_prime: zarith. @@ -546,46 +546,48 @@ Hint Resolve prime_rel_prime: zarith. (** [Zdivide] can be expressed using [Zmod]. *) Lemma Zmod_divide : forall a b:Z, b > 0 -> a mod b = 0 -> (b | a). -intros a b H H0. -apply Zdivide_intro with (a / b). -pattern a at 1 in |- *; rewrite (Z_div_mod_eq a b H). -rewrite H0; ring. +Proof. + intros a b H H0. + apply Zdivide_intro with (a / b). + pattern a at 1 in |- *; rewrite (Z_div_mod_eq a b H). + rewrite H0; ring. Qed. Lemma Zdivide_mod : forall a b:Z, b > 0 -> (b | a) -> a mod b = 0. -intros a b; simple destruct 2; intros; subst. -change (q * b) with (0 + q * b) in |- *. -rewrite Z_mod_plus; auto. +Proof. + intros a b; simple destruct 2; intros; subst. + change (q * b) with (0 + q * b) in |- *. + rewrite Z_mod_plus; auto. Qed. (** [Zdivide] is hence decidable *) Lemma Zdivide_dec : forall a b:Z, {(a | b)} + {~ (a | b)}. Proof. -intros a b; elim (Ztrichotomy_inf a 0). -(* a<0 *) -intros H; elim H; intros. -case (Z_eq_dec (b mod - a) 0). -left; apply Zdivide_opp_l_rev; apply Zmod_divide; auto with zarith. -intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. -(* a=0 *) -case (Z_eq_dec b 0); intro. -left; subst; auto with zarith. -right; subst; intro H0; inversion H0; omega. -(* a>0 *) -intro H; case (Z_eq_dec (b mod a) 0). -left; apply Zmod_divide; auto with zarith. -intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. + intros a b; elim (Ztrichotomy_inf a 0). + (* a<0 *) + intros H; elim H; intros. + case (Z_eq_dec (b mod - a) 0). + left; apply Zdivide_opp_l_rev; apply Zmod_divide; auto with zarith. + intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. + (* a=0 *) + case (Z_eq_dec b 0); intro. + left; subst; auto with zarith. + right; subst; intro H0; inversion H0; omega. + (* a>0 *) + intro H; case (Z_eq_dec (b mod a) 0). + left; apply Zmod_divide; auto with zarith. + intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith. Qed. (** If a prime [p] divides [ab] then it divides either [a] or [b] *) Lemma prime_mult : - forall p:Z, prime p -> forall a b:Z, (p | a * b) -> (p | a) \/ (p | b). + forall p:Z, prime p -> forall a b:Z, (p | a * b) -> (p | a) \/ (p | b). Proof. -intro p; simple induction 1; intros. -case (Zdivide_dec p a); intuition. -right; apply Gauss with a; auto with zarith. + intro p; simple induction 1; intros. + case (Zdivide_dec p a); intuition. + right; apply Gauss with a; auto with zarith. Qed. @@ -606,53 +608,53 @@ Qed. Open Scope positive_scope. Fixpoint Pgcdn (n: nat) (a b : positive) { struct n } : positive := - match n with - | O => 1 - | S n => - match a,b with - | xH, _ => 1 - | _, xH => 1 - | xO a, xO b => xO (Pgcdn n a b) - | a, xO b => Pgcdn n a b - | xO a, b => Pgcdn n a b - | xI a', xI b' => match Pcompare a' b' Eq with - | Eq => a - | Lt => Pgcdn n (b'-a') a - | Gt => Pgcdn n (a'-b') b - end - end + match n with + | O => 1 + | S n => + match a,b with + | xH, _ => 1 + | _, xH => 1 + | xO a, xO b => xO (Pgcdn n a b) + | a, xO b => Pgcdn n a b + | xO a, b => Pgcdn n a b + | xI a', xI b' => match Pcompare a' b' Eq with + | Eq => a + | Lt => Pgcdn n (b'-a') a + | Gt => Pgcdn n (a'-b') b + end + end end. Fixpoint Pggcdn (n: nat) (a b : positive) { struct n } : (positive*(positive*positive)) := - match n with - | O => (1,(a,b)) - | S n => - match a,b with - | xH, b => (1,(1,b)) - | a, xH => (1,(a,1)) - | xO a, xO b => - let (g,p) := Pggcdn n a b in - (xO g,p) - | a, xO b => - let (g,p) := Pggcdn n a b in - let (aa,bb) := p in - (g,(aa, xO bb)) - | xO a, b => - let (g,p) := Pggcdn n a b in - let (aa,bb) := p in - (g,(xO aa, bb)) - | xI a', xI b' => match Pcompare a' b' Eq with - | Eq => (a,(1,1)) - | Lt => - let (g,p) := Pggcdn n (b'-a') a in - let (ba,aa) := p in - (g,(aa, aa + xO ba)) - | Gt => - let (g,p) := Pggcdn n (a'-b') b in - let (ab,bb) := p in - (g,(bb+xO ab, bb)) - end - end + match n with + | O => (1,(a,b)) + | S n => + match a,b with + | xH, b => (1,(1,b)) + | a, xH => (1,(a,1)) + | xO a, xO b => + let (g,p) := Pggcdn n a b in + (xO g,p) + | a, xO b => + let (g,p) := Pggcdn n a b in + let (aa,bb) := p in + (g,(aa, xO bb)) + | xO a, b => + let (g,p) := Pggcdn n a b in + let (aa,bb) := p in + (g,(xO aa, bb)) + | xI a', xI b' => match Pcompare a' b' Eq with + | Eq => (a,(1,1)) + | Lt => + let (g,p) := Pggcdn n (b'-a') a in + let (ba,aa) := p in + (g,(aa, aa + xO ba)) + | Gt => + let (g,p) := Pggcdn n (a'-b') b in + let (ab,bb) := p in + (g,(bb+xO ab, bb)) + end + end end. Definition Pgcd (a b: positive) := Pgcdn (Psize a + Psize b)%nat a b. @@ -661,269 +663,269 @@ Definition Pggcd (a b: positive) := Pggcdn (Psize a + Psize b)%nat a b. Open Scope Z_scope. Definition Zgcd (a b : Z) : Z := match a,b with - | Z0, _ => Zabs b - | _, Z0 => Zabs a - | Zpos a, Zpos b => Zpos (Pgcd a b) - | Zpos a, Zneg b => Zpos (Pgcd a b) - | Zneg a, Zpos b => Zpos (Pgcd a b) - | Zneg a, Zneg b => Zpos (Pgcd a b) -end. + | Z0, _ => Zabs b + | _, Z0 => Zabs a + | Zpos a, Zpos b => Zpos (Pgcd a b) + | Zpos a, Zneg b => Zpos (Pgcd a b) + | Zneg a, Zpos b => Zpos (Pgcd a b) + | Zneg a, Zneg b => Zpos (Pgcd a b) + end. Definition Zggcd (a b : Z) : Z*(Z*Z) := match a,b with - | Z0, _ => (Zabs b,(0, Zsgn b)) - | _, Z0 => (Zabs a,(Zsgn a, 0)) - | Zpos a, Zpos b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zpos aa, Zpos bb)) - | Zpos a, Zneg b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zpos aa, Zneg bb)) - | Zneg a, Zpos b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zneg aa, Zpos bb)) - | Zneg a, Zneg b => - let (g,p) := Pggcd a b in - let (aa,bb) := p in - (Zpos g, (Zneg aa, Zneg bb)) -end. + | Z0, _ => (Zabs b,(0, Zsgn b)) + | _, Z0 => (Zabs a,(Zsgn a, 0)) + | Zpos a, Zpos b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zpos aa, Zpos bb)) + | Zpos a, Zneg b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zpos aa, Zneg bb)) + | Zneg a, Zpos b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zneg aa, Zpos bb)) + | Zneg a, Zneg b => + let (g,p) := Pggcd a b in + let (aa,bb) := p in + (Zpos g, (Zneg aa, Zneg bb)) + end. Lemma Zgcd_is_pos : forall a b, 0 <= Zgcd a b. Proof. -unfold Zgcd; destruct a; destruct b; auto with zarith. + unfold Zgcd; destruct a; destruct b; auto with zarith. Qed. Lemma Psize_monotone : forall p q, Pcompare p q Eq = Lt -> (Psize p <= Psize q)%nat. Proof. -induction p; destruct q; simpl; auto with arith; intros; try discriminate. -intros; generalize (Pcompare_Gt_Lt _ _ H); auto with arith. -intros; destruct (Pcompare_Lt_Lt _ _ H); auto with arith; subst; auto. + induction p; destruct q; simpl; auto with arith; intros; try discriminate. + intros; generalize (Pcompare_Gt_Lt _ _ H); auto with arith. + intros; destruct (Pcompare_Lt_Lt _ _ H); auto with arith; subst; auto. Qed. Lemma Pminus_Zminus : forall a b, Pcompare a b Eq = Lt -> - Zpos (b-a) = Zpos b - Zpos a. + Zpos (b-a) = Zpos b - Zpos a. Proof. -intros. -repeat rewrite Zpos_eq_Z_of_nat_o_nat_of_P. -rewrite nat_of_P_minus_morphism. -apply inj_minus1. -apply lt_le_weak. -apply nat_of_P_lt_Lt_compare_morphism; auto. -rewrite ZC4; rewrite H; auto. + intros. + repeat rewrite Zpos_eq_Z_of_nat_o_nat_of_P. + rewrite nat_of_P_minus_morphism. + apply inj_minus1. + apply lt_le_weak. + apply nat_of_P_lt_Lt_compare_morphism; auto. + rewrite ZC4; rewrite H; auto. Qed. Lemma Zis_gcd_even_odd : forall a b g, Zis_gcd (Zpos a) (Zpos (xI b)) g -> - Zis_gcd (Zpos (xO a)) (Zpos (xI b)) g. -Proof. -intros. -destruct H. -constructor; auto. -destruct H as (e,H2); exists (2*e); auto with zarith. -rewrite Zpos_xO; rewrite H2; ring. -intros. -apply H1; auto. -rewrite Zpos_xO in H2. -rewrite Zpos_xI in H3. -apply Gauss with 2; auto. -apply bezout_rel_prime. -destruct H3 as (bb, H3). -apply Bezout_intro with bb (-Zpos b). -omega. + Zis_gcd (Zpos (xO a)) (Zpos (xI b)) g. +Proof. + intros. + destruct H. + constructor; auto. + destruct H as (e,H2); exists (2*e); auto with zarith. + rewrite Zpos_xO; rewrite H2; ring. + intros. + apply H1; auto. + rewrite Zpos_xO in H2. + rewrite Zpos_xI in H3. + apply Gauss with 2; auto. + apply bezout_rel_prime. + destruct H3 as (bb, H3). + apply Bezout_intro with bb (-Zpos b). + omega. Qed. Lemma Pgcdn_correct : forall n a b, (Psize a + Psize b<=n)%nat -> - Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcdn n a b)). -Proof. -intro n; pattern n; apply lt_wf_ind; clear n; intros. -destruct n. -simpl. -destruct a; simpl in *; try inversion H0. -destruct a. -destruct b; simpl. -case_eq (Pcompare a b Eq); intros. -(* a = xI, b = xI, compare = Eq *) -rewrite (Pcompare_Eq_eq _ _ H1); apply Zis_gcd_refl. -(* a = xI, b = xI, compare = Lt *) -apply Zis_gcd_sym. -apply Zis_gcd_for_euclid with 1. -apply Zis_gcd_sym. -replace (Zpos (xI b) - 1 * Zpos (xI a)) with (Zpos(xO (b - a))). -apply Zis_gcd_even_odd. -apply H; auto. -simpl in *. -assert (Psize (b-a) <= Psize b)%nat. - apply Psize_monotone. - change (Zpos (b-a) < Zpos b). - rewrite (Pminus_Zminus _ _ H1). - assert (0 < Zpos a) by (compute; auto). - omega. -omega. -rewrite Zpos_xO; do 2 rewrite Zpos_xI. -rewrite Pminus_Zminus; auto. -omega. -(* a = xI, b = xI, compare = Gt *) -apply Zis_gcd_for_euclid with 1. -replace (Zpos (xI a) - 1 * Zpos (xI b)) with (Zpos(xO (a - b))). -apply Zis_gcd_sym. -apply Zis_gcd_even_odd. -apply H; auto. -simpl in *. -assert (Psize (a-b) <= Psize a)%nat. - apply Psize_monotone. - change (Zpos (a-b) < Zpos a). - rewrite (Pminus_Zminus b a). - assert (0 < Zpos b) by (compute; auto). - omega. - rewrite ZC4; rewrite H1; auto. -omega. -rewrite Zpos_xO; do 2 rewrite Zpos_xI. -rewrite Pminus_Zminus; auto. -omega. -rewrite ZC4; rewrite H1; auto. -(* a = xI, b = xO *) -apply Zis_gcd_sym. -apply Zis_gcd_even_odd. -apply Zis_gcd_sym. -apply H; auto. -simpl in *; omega. -(* a = xI, b = xH *) -apply Zis_gcd_1. -destruct b; simpl. -(* a = xO, b = xI *) -apply Zis_gcd_even_odd. -apply H; auto. -simpl in *; omega. -(* a = xO, b = xO *) -rewrite (Zpos_xO a); rewrite (Zpos_xO b); rewrite (Zpos_xO (Pgcdn n a b)). -apply Zis_gcd_mult. -apply H; auto. -simpl in *; omega. -(* a = xO, b = xH *) -apply Zis_gcd_1. -(* a = xH *) -simpl; apply Zis_gcd_sym; apply Zis_gcd_1. + Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcdn n a b)). +Proof. + intro n; pattern n; apply lt_wf_ind; clear n; intros. + destruct n. + simpl. + destruct a; simpl in *; try inversion H0. + destruct a. + destruct b; simpl. + case_eq (Pcompare a b Eq); intros. + (* a = xI, b = xI, compare = Eq *) + rewrite (Pcompare_Eq_eq _ _ H1); apply Zis_gcd_refl. + (* a = xI, b = xI, compare = Lt *) + apply Zis_gcd_sym. + apply Zis_gcd_for_euclid with 1. + apply Zis_gcd_sym. + replace (Zpos (xI b) - 1 * Zpos (xI a)) with (Zpos(xO (b - a))). + apply Zis_gcd_even_odd. + apply H; auto. + simpl in *. + assert (Psize (b-a) <= Psize b)%nat. + apply Psize_monotone. + change (Zpos (b-a) < Zpos b). + rewrite (Pminus_Zminus _ _ H1). + assert (0 < Zpos a) by (compute; auto). + omega. + omega. + rewrite Zpos_xO; do 2 rewrite Zpos_xI. + rewrite Pminus_Zminus; auto. + omega. + (* a = xI, b = xI, compare = Gt *) + apply Zis_gcd_for_euclid with 1. + replace (Zpos (xI a) - 1 * Zpos (xI b)) with (Zpos(xO (a - b))). + apply Zis_gcd_sym. + apply Zis_gcd_even_odd. + apply H; auto. + simpl in *. + assert (Psize (a-b) <= Psize a)%nat. + apply Psize_monotone. + change (Zpos (a-b) < Zpos a). + rewrite (Pminus_Zminus b a). + assert (0 < Zpos b) by (compute; auto). + omega. + rewrite ZC4; rewrite H1; auto. + omega. + rewrite Zpos_xO; do 2 rewrite Zpos_xI. + rewrite Pminus_Zminus; auto. + omega. + rewrite ZC4; rewrite H1; auto. + (* a = xI, b = xO *) + apply Zis_gcd_sym. + apply Zis_gcd_even_odd. + apply Zis_gcd_sym. + apply H; auto. + simpl in *; omega. + (* a = xI, b = xH *) + apply Zis_gcd_1. + destruct b; simpl. + (* a = xO, b = xI *) + apply Zis_gcd_even_odd. + apply H; auto. + simpl in *; omega. + (* a = xO, b = xO *) + rewrite (Zpos_xO a); rewrite (Zpos_xO b); rewrite (Zpos_xO (Pgcdn n a b)). + apply Zis_gcd_mult. + apply H; auto. + simpl in *; omega. + (* a = xO, b = xH *) + apply Zis_gcd_1. + (* a = xH *) + simpl; apply Zis_gcd_sym; apply Zis_gcd_1. Qed. Lemma Pgcd_correct : forall a b, Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcd a b)). Proof. -unfold Pgcd; intros. -apply Pgcdn_correct; auto. + unfold Pgcd; intros. + apply Pgcdn_correct; auto. Qed. Lemma Zgcd_is_gcd : forall a b, Zis_gcd a b (Zgcd a b). Proof. -destruct a. -intros. -simpl. -apply Zis_gcd_0_abs. -destruct b; simpl. -apply Zis_gcd_0. -apply Pgcd_correct. -apply Zis_gcd_sym. -apply Zis_gcd_minus; simpl. -apply Pgcd_correct. -destruct b; simpl. -apply Zis_gcd_minus; simpl. -apply Zis_gcd_sym. -apply Zis_gcd_0. -apply Zis_gcd_minus; simpl. -apply Zis_gcd_sym. -apply Pgcd_correct. -apply Zis_gcd_sym. -apply Zis_gcd_minus; simpl. -apply Zis_gcd_minus; simpl. -apply Zis_gcd_sym. -apply Pgcd_correct. + destruct a. + intros. + simpl. + apply Zis_gcd_0_abs. + destruct b; simpl. + apply Zis_gcd_0. + apply Pgcd_correct. + apply Zis_gcd_sym. + apply Zis_gcd_minus; simpl. + apply Pgcd_correct. + destruct b; simpl. + apply Zis_gcd_minus; simpl. + apply Zis_gcd_sym. + apply Zis_gcd_0. + apply Zis_gcd_minus; simpl. + apply Zis_gcd_sym. + apply Pgcd_correct. + apply Zis_gcd_sym. + apply Zis_gcd_minus; simpl. + apply Zis_gcd_minus; simpl. + apply Zis_gcd_sym. + apply Pgcd_correct. Qed. Lemma Pggcdn_gcdn : forall n a b, - fst (Pggcdn n a b) = Pgcdn n a b. + fst (Pggcdn n a b) = Pgcdn n a b. Proof. -induction n. -simpl; auto. -destruct a; destruct b; simpl; auto. -destruct (Pcompare a b Eq); simpl; auto. -rewrite <- IHn; destruct (Pggcdn n (b-a) (xI a)) as (g,(aa,bb)); simpl; auto. -rewrite <- IHn; destruct (Pggcdn n (a-b) (xI b)) as (g,(aa,bb)); simpl; auto. -rewrite <- IHn; destruct (Pggcdn n (xI a) b) as (g,(aa,bb)); simpl; auto. -rewrite <- IHn; destruct (Pggcdn n a (xI b)) as (g,(aa,bb)); simpl; auto. -rewrite <- IHn; destruct (Pggcdn n a b) as (g,(aa,bb)); simpl; auto. + induction n. + simpl; auto. + destruct a; destruct b; simpl; auto. + destruct (Pcompare a b Eq); simpl; auto. + rewrite <- IHn; destruct (Pggcdn n (b-a) (xI a)) as (g,(aa,bb)); simpl; auto. + rewrite <- IHn; destruct (Pggcdn n (a-b) (xI b)) as (g,(aa,bb)); simpl; auto. + rewrite <- IHn; destruct (Pggcdn n (xI a) b) as (g,(aa,bb)); simpl; auto. + rewrite <- IHn; destruct (Pggcdn n a (xI b)) as (g,(aa,bb)); simpl; auto. + rewrite <- IHn; destruct (Pggcdn n a b) as (g,(aa,bb)); simpl; auto. Qed. Lemma Pggcd_gcd : forall a b, fst (Pggcd a b) = Pgcd a b. Proof. -intros; exact (Pggcdn_gcdn (Psize a+Psize b)%nat a b). + intros; exact (Pggcdn_gcdn (Psize a+Psize b)%nat a b). Qed. Lemma Zggcd_gcd : forall a b, fst (Zggcd a b) = Zgcd a b. Proof. -destruct a; destruct b; simpl; auto; rewrite <- Pggcd_gcd; -destruct (Pggcd p p0) as (g,(aa,bb)); simpl; auto. + destruct a; destruct b; simpl; auto; rewrite <- Pggcd_gcd; + destruct (Pggcd p p0) as (g,(aa,bb)); simpl; auto. Qed. Open Scope positive_scope. Lemma Pggcdn_correct_divisors : forall n a b, let (g,p) := Pggcdn n a b in - let (aa,bb):=p in - (a=g*aa) /\ (b=g*bb). -Proof. -induction n. -simpl; auto. -destruct a; destruct b; simpl; auto. -case_eq (Pcompare a b Eq); intros. -(* Eq *) -rewrite Pmult_comm; simpl; auto. -rewrite (Pcompare_Eq_eq _ _ H); auto. -(* Lt *) -generalize (IHn (b-a) (xI a)); destruct (Pggcdn n (b-a) (xI a)) as (g,(ba,aa)); simpl. -intros (H0,H1); split; auto. -rewrite Pmult_plus_distr_l. -rewrite Pmult_xO_permute_r. -rewrite <- H1; rewrite <- H0. -simpl; f_equal; symmetry. -apply Pplus_minus; auto. -rewrite ZC4; rewrite H; auto. -(* Gt *) -generalize (IHn (a-b) (xI b)); destruct (Pggcdn n (a-b) (xI b)) as (g,(ab,bb)); simpl. -intros (H0,H1); split; auto. -rewrite Pmult_plus_distr_l. -rewrite Pmult_xO_permute_r. -rewrite <- H1; rewrite <- H0. -simpl; f_equal; symmetry. -apply Pplus_minus; auto. -(* Then... *) -generalize (IHn (xI a) b); destruct (Pggcdn n (xI a) b) as (g,(ab,bb)); simpl. -intros (H0,H1); split; auto. -rewrite Pmult_xO_permute_r; rewrite H1; auto. -generalize (IHn a (xI b)); destruct (Pggcdn n a (xI b)) as (g,(ab,bb)); simpl. -intros (H0,H1); split; auto. -rewrite Pmult_xO_permute_r; rewrite H0; auto. -generalize (IHn a b); destruct (Pggcdn n a b) as (g,(ab,bb)); simpl. -intros (H0,H1); split; subst; auto. + let (aa,bb):=p in + (a=g*aa) /\ (b=g*bb). +Proof. + induction n. + simpl; auto. + destruct a; destruct b; simpl; auto. + case_eq (Pcompare a b Eq); intros. + (* Eq *) + rewrite Pmult_comm; simpl; auto. + rewrite (Pcompare_Eq_eq _ _ H); auto. + (* Lt *) + generalize (IHn (b-a) (xI a)); destruct (Pggcdn n (b-a) (xI a)) as (g,(ba,aa)); simpl. + intros (H0,H1); split; auto. + rewrite Pmult_plus_distr_l. + rewrite Pmult_xO_permute_r. + rewrite <- H1; rewrite <- H0. + simpl; f_equal; symmetry. + apply Pplus_minus; auto. + rewrite ZC4; rewrite H; auto. + (* Gt *) + generalize (IHn (a-b) (xI b)); destruct (Pggcdn n (a-b) (xI b)) as (g,(ab,bb)); simpl. + intros (H0,H1); split; auto. + rewrite Pmult_plus_distr_l. + rewrite Pmult_xO_permute_r. + rewrite <- H1; rewrite <- H0. + simpl; f_equal; symmetry. + apply Pplus_minus; auto. + (* Then... *) + generalize (IHn (xI a) b); destruct (Pggcdn n (xI a) b) as (g,(ab,bb)); simpl. + intros (H0,H1); split; auto. + rewrite Pmult_xO_permute_r; rewrite H1; auto. + generalize (IHn a (xI b)); destruct (Pggcdn n a (xI b)) as (g,(ab,bb)); simpl. + intros (H0,H1); split; auto. + rewrite Pmult_xO_permute_r; rewrite H0; auto. + generalize (IHn a b); destruct (Pggcdn n a b) as (g,(ab,bb)); simpl. + intros (H0,H1); split; subst; auto. Qed. Lemma Pggcd_correct_divisors : forall a b, let (g,p) := Pggcd a b in - let (aa,bb):=p in - (a=g*aa) /\ (b=g*bb). + let (aa,bb):=p in + (a=g*aa) /\ (b=g*bb). Proof. -intros a b; exact (Pggcdn_correct_divisors (Psize a + Psize b)%nat a b). + intros a b; exact (Pggcdn_correct_divisors (Psize a + Psize b)%nat a b). Qed. Open Scope Z_scope. Lemma Zggcd_correct_divisors : forall a b, let (g,p) := Zggcd a b in - let (aa,bb):=p in - (a=g*aa) /\ (b=g*bb). + let (aa,bb):=p in + (a=g*aa) /\ (b=g*bb). Proof. -destruct a; destruct b; simpl; auto; try solve [rewrite Pmult_comm; simpl; auto]; -generalize (Pggcd_correct_divisors p p0); destruct (Pggcd p p0) as (g,(aa,bb)); -destruct 1; subst; auto. + destruct a; destruct b; simpl; auto; try solve [rewrite Pmult_comm; simpl; auto]; + generalize (Pggcd_correct_divisors p p0); destruct (Pggcd p p0) as (g,(aa,bb)); + destruct 1; subst; auto. Qed. Theorem Zgcd_spec : forall x y : Z, {z : Z | Zis_gcd x y z /\ 0 <= z}. diff --git a/theories/ZArith/Zorder.v b/theories/ZArith/Zorder.v index b81cc580..47490be6 100644 --- a/theories/ZArith/Zorder.v +++ b/theories/ZArith/Zorder.v @@ -5,13 +5,13 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zorder.v 6983 2005-05-02 10:47:51Z herbelin $ i*) +(*i $Id: Zorder.v 9302 2006-10-27 21:21:17Z barras $ i*) (** Binary Integers (Pierre Crégut (CNET, Lannion, France) *) Require Import BinPos. Require Import BinInt. -Require Import Arith. +Require Import Arith_base. Require Import Decidable. Require Import Zcompare. @@ -19,178 +19,180 @@ Open Local Scope Z_scope. Implicit Types x y z : Z. -(**********************************************************************) +(*********************************************************) (** Properties of the order relations on binary integers *) -(** Trichotomy *) +(** * Trichotomy *) Theorem Ztrichotomy_inf : forall n m:Z, {n < m} + {n = m} + {n > m}. Proof. -unfold Zgt, Zlt in |- *; intros m n; assert (H := refl_equal (m ?= n)). + unfold Zgt, Zlt in |- *; intros m n; assert (H := refl_equal (m ?= n)). set (x := m ?= n) in H at 2 |- *. destruct x; - [ left; right; rewrite Zcompare_Eq_eq with (1 := H) | left; left | right ]; - reflexivity. + [ left; right; rewrite Zcompare_Eq_eq with (1 := H) | left; left | right ]; + reflexivity. Qed. Theorem Ztrichotomy : forall n m:Z, n < m \/ n = m \/ n > m. Proof. intros m n; destruct (Ztrichotomy_inf m n) as [[Hlt| Heq]| Hgt]; - [ left | right; left | right; right ]; assumption. + [ left | right; left | right; right ]; assumption. Qed. (**********************************************************************) -(** Decidability of equality and order on Z *) +(** * Decidability of equality and order on Z *) Theorem dec_eq : forall n m:Z, decidable (n = m). Proof. -intros x y; unfold decidable in |- *; elim (Zcompare_Eq_iff_eq x y); - intros H1 H2; elim (Dcompare (x ?= y)); - [ tauto - | intros H3; right; unfold not in |- *; intros H4; elim H3; rewrite (H2 H4); - intros H5; discriminate H5 ]. + intros x y; unfold decidable in |- *; elim (Zcompare_Eq_iff_eq x y); + intros H1 H2; elim (Dcompare (x ?= y)); + [ tauto + | intros H3; right; unfold not in |- *; intros H4; elim H3; rewrite (H2 H4); + intros H5; discriminate H5 ]. Qed. Theorem dec_Zne : forall n m:Z, decidable (Zne n m). Proof. -intros x y; unfold decidable, Zne in |- *; elim (Zcompare_Eq_iff_eq x y). -intros H1 H2; elim (Dcompare (x ?= y)); - [ right; rewrite H1; auto - | left; unfold not in |- *; intro; absurd ((x ?= y) = Eq); - [ elim H; intros HR; rewrite HR; discriminate | auto ] ]. + intros x y; unfold decidable, Zne in |- *; elim (Zcompare_Eq_iff_eq x y). + intros H1 H2; elim (Dcompare (x ?= y)); + [ right; rewrite H1; auto + | left; unfold not in |- *; intro; absurd ((x ?= y) = Eq); + [ elim H; intros HR; rewrite HR; discriminate | auto ] ]. Qed. Theorem dec_Zle : forall n m:Z, decidable (n <= m). Proof. -intros x y; unfold decidable, Zle in |- *; elim (x ?= y); - [ left; discriminate - | left; discriminate - | right; unfold not in |- *; intros H; apply H; trivial with arith ]. + intros x y; unfold decidable, Zle in |- *; elim (x ?= y); + [ left; discriminate + | left; discriminate + | right; unfold not in |- *; intros H; apply H; trivial with arith ]. Qed. Theorem dec_Zgt : forall n m:Z, decidable (n > m). Proof. -intros x y; unfold decidable, Zgt in |- *; elim (x ?= y); - [ right; discriminate | right; discriminate | auto with arith ]. + intros x y; unfold decidable, Zgt in |- *; elim (x ?= y); + [ right; discriminate | right; discriminate | auto with arith ]. Qed. Theorem dec_Zge : forall n m:Z, decidable (n >= m). Proof. -intros x y; unfold decidable, Zge in |- *; elim (x ?= y); - [ left; discriminate - | right; unfold not in |- *; intros H; apply H; trivial with arith - | left; discriminate ]. + intros x y; unfold decidable, Zge in |- *; elim (x ?= y); + [ left; discriminate + | right; unfold not in |- *; intros H; apply H; trivial with arith + | left; discriminate ]. Qed. Theorem dec_Zlt : forall n m:Z, decidable (n < m). Proof. -intros x y; unfold decidable, Zlt in |- *; elim (x ?= y); - [ right; discriminate | auto with arith | right; discriminate ]. + intros x y; unfold decidable, Zlt in |- *; elim (x ?= y); + [ right; discriminate | auto with arith | right; discriminate ]. Qed. Theorem not_Zeq : forall n m:Z, n <> m -> n < m \/ m < n. Proof. -intros x y; elim (Dcompare (x ?= y)); - [ intros H1 H2; absurd (x = y); - [ assumption | elim (Zcompare_Eq_iff_eq x y); auto with arith ] - | unfold Zlt in |- *; intros H; elim H; intros H1; - [ auto with arith - | right; elim (Zcompare_Gt_Lt_antisym x y); auto with arith ] ]. + intros x y; elim (Dcompare (x ?= y)); + [ intros H1 H2; absurd (x = y); + [ assumption | elim (Zcompare_Eq_iff_eq x y); auto with arith ] + | unfold Zlt in |- *; intros H; elim H; intros H1; + [ auto with arith + | right; elim (Zcompare_Gt_Lt_antisym x y); auto with arith ] ]. Qed. -(** Relating strict and large orders *) +(** * Relating strict and large orders *) Lemma Zgt_lt : forall n m:Z, n > m -> m < n. Proof. -unfold Zgt, Zlt in |- *; intros m n H; elim (Zcompare_Gt_Lt_antisym m n); - auto with arith. + unfold Zgt, Zlt in |- *; intros m n H; elim (Zcompare_Gt_Lt_antisym m n); + auto with arith. Qed. Lemma Zlt_gt : forall n m:Z, n < m -> m > n. Proof. -unfold Zgt, Zlt in |- *; intros m n H; elim (Zcompare_Gt_Lt_antisym n m); - auto with arith. + unfold Zgt, Zlt in |- *; intros m n H; elim (Zcompare_Gt_Lt_antisym n m); + auto with arith. Qed. Lemma Zge_le : forall n m:Z, n >= m -> m <= n. Proof. -intros m n; change (~ m < n -> ~ n > m) in |- *; unfold not in |- *; - intros H1 H2; apply H1; apply Zgt_lt; assumption. + intros m n; change (~ m < n -> ~ n > m) in |- *; unfold not in |- *; + intros H1 H2; apply H1; apply Zgt_lt; assumption. Qed. Lemma Zle_ge : forall n m:Z, n <= m -> m >= n. Proof. -intros m n; change (~ m > n -> ~ n < m) in |- *; unfold not in |- *; - intros H1 H2; apply H1; apply Zlt_gt; assumption. + intros m n; change (~ m > n -> ~ n < m) in |- *; unfold not in |- *; + intros H1 H2; apply H1; apply Zlt_gt; assumption. Qed. Lemma Zle_not_gt : forall n m:Z, n <= m -> ~ n > m. Proof. -trivial. + trivial. Qed. Lemma Zgt_not_le : forall n m:Z, n > m -> ~ n <= m. Proof. -intros n m H1 H2; apply H2; assumption. + intros n m H1 H2; apply H2; assumption. Qed. Lemma Zle_not_lt : forall n m:Z, n <= m -> ~ m < n. Proof. -intros n m H1 H2. -assert (H3 := Zlt_gt _ _ H2). -apply Zle_not_gt with n m; assumption. + intros n m H1 H2. + assert (H3 := Zlt_gt _ _ H2). + apply Zle_not_gt with n m; assumption. Qed. Lemma Zlt_not_le : forall n m:Z, n < m -> ~ m <= n. Proof. -intros n m H1 H2. -apply Zle_not_lt with m n; assumption. + intros n m H1 H2. + apply Zle_not_lt with m n; assumption. Qed. Lemma Znot_ge_lt : forall n m:Z, ~ n >= m -> n < m. Proof. -unfold Zge, Zlt in |- *; intros x y H; apply dec_not_not; - [ exact (dec_Zlt x y) | assumption ]. + unfold Zge, Zlt in |- *; intros x y H; apply dec_not_not; + [ exact (dec_Zlt x y) | assumption ]. Qed. - + Lemma Znot_lt_ge : forall n m:Z, ~ n < m -> n >= m. Proof. -unfold Zlt, Zge in |- *; auto with arith. + unfold Zlt, Zge in |- *; auto with arith. Qed. Lemma Znot_gt_le : forall n m:Z, ~ n > m -> n <= m. Proof. -trivial. + trivial. Qed. Lemma Znot_le_gt : forall n m:Z, ~ n <= m -> n > m. Proof. -unfold Zle, Zgt in |- *; intros x y H; apply dec_not_not; - [ exact (dec_Zgt x y) | assumption ]. + unfold Zle, Zgt in |- *; intros x y H; apply dec_not_not; + [ exact (dec_Zgt x y) | assumption ]. Qed. Lemma Zge_iff_le : forall n m:Z, n >= m <-> m <= n. Proof. - intros x y; intros. split. intro. apply Zge_le. assumption. - intro. apply Zle_ge. assumption. + intros x y; intros. split. intro. apply Zge_le. assumption. + intro. apply Zle_ge. assumption. Qed. Lemma Zgt_iff_lt : forall n m:Z, n > m <-> m < n. Proof. - intros x y. split. intro. apply Zgt_lt. assumption. - intro. apply Zlt_gt. assumption. + intros x y. split. intro. apply Zgt_lt. assumption. + intro. apply Zlt_gt. assumption. Qed. +(** * Equivalence and order properties *) + (** Reflexivity *) Lemma Zle_refl : forall n:Z, n <= n. Proof. -intros n; unfold Zle in |- *; rewrite (Zcompare_refl n); discriminate. + intros n; unfold Zle in |- *; rewrite (Zcompare_refl n); discriminate. Qed. Lemma Zeq_le : forall n m:Z, n = m -> n <= m. Proof. -intros; rewrite H; apply Zle_refl. + intros; rewrite H; apply Zle_refl. Qed. Hint Resolve Zle_refl: zarith. @@ -199,7 +201,7 @@ Hint Resolve Zle_refl: zarith. Lemma Zle_antisym : forall n m:Z, n <= m -> m <= n -> n = m. Proof. -intros n m H1 H2; destruct (Ztrichotomy n m) as [Hlt| [Heq| Hgt]]. + intros n m H1 H2; destruct (Ztrichotomy n m) as [Hlt| [Heq| Hgt]]. absurd (m > n); [ apply Zle_not_gt | apply Zlt_gt ]; assumption. assumption. absurd (n > m); [ apply Zle_not_gt | idtac ]; assumption. @@ -209,138 +211,143 @@ Qed. Lemma Zgt_asym : forall n m:Z, n > m -> ~ m > n. Proof. -unfold Zgt in |- *; intros n m H; elim (Zcompare_Gt_Lt_antisym n m); - intros H1 H2; rewrite H1; [ discriminate | assumption ]. + unfold Zgt in |- *; intros n m H; elim (Zcompare_Gt_Lt_antisym n m); + intros H1 H2; rewrite H1; [ discriminate | assumption ]. Qed. Lemma Zlt_asym : forall n m:Z, n < m -> ~ m < n. Proof. -intros n m H H1; assert (H2 : m > n). apply Zlt_gt; assumption. -assert (H3 : n > m). apply Zlt_gt; assumption. -apply Zgt_asym with m n; assumption. + intros n m H H1; assert (H2 : m > n). apply Zlt_gt; assumption. + assert (H3 : n > m). apply Zlt_gt; assumption. + apply Zgt_asym with m n; assumption. Qed. (** Irreflexivity *) Lemma Zgt_irrefl : forall n:Z, ~ n > n. Proof. -intros n H; apply (Zgt_asym n n H H). + intros n H; apply (Zgt_asym n n H H). Qed. Lemma Zlt_irrefl : forall n:Z, ~ n < n. Proof. -intros n H; apply (Zlt_asym n n H H). + intros n H; apply (Zlt_asym n n H H). Qed. Lemma Zlt_not_eq : forall n m:Z, n < m -> n <> m. Proof. -unfold not in |- *; intros x y H H0. -rewrite H0 in H. -apply (Zlt_irrefl _ H). + unfold not in |- *; intros x y H H0. + rewrite H0 in H. + apply (Zlt_irrefl _ H). Qed. (** Large = strict or equal *) Lemma Zlt_le_weak : forall n m:Z, n < m -> n <= m. Proof. -intros n m Hlt; apply Znot_gt_le; apply Zgt_asym; apply Zlt_gt; assumption. + intros n m Hlt; apply Znot_gt_le; apply Zgt_asym; apply Zlt_gt; assumption. Qed. Lemma Zle_lt_or_eq : forall n m:Z, n <= m -> n < m \/ n = m. Proof. -intros n m H; destruct (Ztrichotomy n m) as [Hlt| [Heq| Hgt]]; - [ left; assumption - | right; assumption - | absurd (n > m); [ apply Zle_not_gt | idtac ]; assumption ]. + intros n m H; destruct (Ztrichotomy n m) as [Hlt| [Heq| Hgt]]; + [ left; assumption + | right; assumption + | absurd (n > m); [ apply Zle_not_gt | idtac ]; assumption ]. Qed. (** Dichotomy *) Lemma Zle_or_lt : forall n m:Z, n <= m \/ m < n. Proof. -intros n m; destruct (Ztrichotomy n m) as [Hlt| [Heq| Hgt]]; - [ left; apply Znot_gt_le; intro Hgt; assert (Hgt' := Zlt_gt _ _ Hlt); - apply Zgt_asym with m n; assumption - | left; rewrite Heq; apply Zle_refl - | right; apply Zgt_lt; assumption ]. + intros n m; destruct (Ztrichotomy n m) as [Hlt| [Heq| Hgt]]; + [ left; apply Znot_gt_le; intro Hgt; assert (Hgt' := Zlt_gt _ _ Hlt); + apply Zgt_asym with m n; assumption + | left; rewrite Heq; apply Zle_refl + | right; apply Zgt_lt; assumption ]. Qed. (** Transitivity of strict orders *) Lemma Zgt_trans : forall n m p:Z, n > m -> m > p -> n > p. Proof. -exact Zcompare_Gt_trans. + exact Zcompare_Gt_trans. Qed. Lemma Zlt_trans : forall n m p:Z, n < m -> m < p -> n < p. Proof. -intros n m p H1 H2; apply Zgt_lt; apply Zgt_trans with (m := m); apply Zlt_gt; - assumption. + intros n m p H1 H2; apply Zgt_lt; apply Zgt_trans with (m := m); apply Zlt_gt; + assumption. Qed. (** Mixed transitivity *) Lemma Zle_gt_trans : forall n m p:Z, m <= n -> m > p -> n > p. Proof. -intros n m p H1 H2; destruct (Zle_lt_or_eq m n H1) as [Hlt| Heq]; - [ apply Zgt_trans with m; [ apply Zlt_gt; assumption | assumption ] - | rewrite <- Heq; assumption ]. + intros n m p H1 H2; destruct (Zle_lt_or_eq m n H1) as [Hlt| Heq]; + [ apply Zgt_trans with m; [ apply Zlt_gt; assumption | assumption ] + | rewrite <- Heq; assumption ]. Qed. Lemma Zgt_le_trans : forall n m p:Z, n > m -> p <= m -> n > p. Proof. -intros n m p H1 H2; destruct (Zle_lt_or_eq p m H2) as [Hlt| Heq]; - [ apply Zgt_trans with m; [ assumption | apply Zlt_gt; assumption ] - | rewrite Heq; assumption ]. + intros n m p H1 H2; destruct (Zle_lt_or_eq p m H2) as [Hlt| Heq]; + [ apply Zgt_trans with m; [ assumption | apply Zlt_gt; assumption ] + | rewrite Heq; assumption ]. Qed. Lemma Zlt_le_trans : forall n m p:Z, n < m -> m <= p -> n < p. -intros n m p H1 H2; apply Zgt_lt; apply Zle_gt_trans with (m := m); - [ assumption | apply Zlt_gt; assumption ]. + intros n m p H1 H2; apply Zgt_lt; apply Zle_gt_trans with (m := m); + [ assumption | apply Zlt_gt; assumption ]. Qed. Lemma Zle_lt_trans : forall n m p:Z, n <= m -> m < p -> n < p. Proof. -intros n m p H1 H2; apply Zgt_lt; apply Zgt_le_trans with (m := m); - [ apply Zlt_gt; assumption | assumption ]. + intros n m p H1 H2; apply Zgt_lt; apply Zgt_le_trans with (m := m); + [ apply Zlt_gt; assumption | assumption ]. Qed. (** Transitivity of large orders *) Lemma Zle_trans : forall n m p:Z, n <= m -> m <= p -> n <= p. Proof. -intros n m p H1 H2; apply Znot_gt_le. -intro Hgt; apply Zle_not_gt with n m. assumption. -exact (Zgt_le_trans n p m Hgt H2). + intros n m p H1 H2; apply Znot_gt_le. + intro Hgt; apply Zle_not_gt with n m. assumption. + exact (Zgt_le_trans n p m Hgt H2). Qed. Lemma Zge_trans : forall n m p:Z, n >= m -> m >= p -> n >= p. Proof. -intros n m p H1 H2. -apply Zle_ge. -apply Zle_trans with m; apply Zge_le; trivial. + intros n m p H1 H2. + apply Zle_ge. + apply Zle_trans with m; apply Zge_le; trivial. Qed. Hint Resolve Zle_trans: zarith. + +(** * Compatibility of order and operations on Z *) + +(** ** Successor *) + (** Compatibility of successor wrt to order *) Lemma Zsucc_le_compat : forall n m:Z, m <= n -> Zsucc m <= Zsucc n. Proof. -unfold Zle, not in |- *; intros m n H1 H2; apply H1; - rewrite <- (Zcompare_plus_compat n m 1); do 2 rewrite (Zplus_comm 1); - exact H2. + unfold Zle, not in |- *; intros m n H1 H2; apply H1; + rewrite <- (Zcompare_plus_compat n m 1); do 2 rewrite (Zplus_comm 1); + exact H2. Qed. Lemma Zsucc_gt_compat : forall n m:Z, m > n -> Zsucc m > Zsucc n. Proof. -unfold Zgt in |- *; intros n m H; rewrite Zcompare_succ_compat; - auto with arith. + unfold Zgt in |- *; intros n m H; rewrite Zcompare_succ_compat; + auto with arith. Qed. Lemma Zsucc_lt_compat : forall n m:Z, n < m -> Zsucc n < Zsucc m. Proof. -intros n m H; apply Zgt_lt; apply Zsucc_gt_compat; apply Zlt_gt; assumption. + intros n m H; apply Zgt_lt; apply Zsucc_gt_compat; apply Zlt_gt; assumption. Qed. Hint Resolve Zsucc_le_compat: zarith. @@ -349,231 +356,119 @@ Hint Resolve Zsucc_le_compat: zarith. Lemma Zsucc_gt_reg : forall n m:Z, Zsucc m > Zsucc n -> m > n. Proof. -unfold Zsucc, Zgt in |- *; intros n p; - do 2 rewrite (fun m:Z => Zplus_comm m 1); - rewrite (Zcompare_plus_compat p n 1); trivial with arith. + unfold Zsucc, Zgt in |- *; intros n p; + do 2 rewrite (fun m:Z => Zplus_comm m 1); + rewrite (Zcompare_plus_compat p n 1); trivial with arith. Qed. Lemma Zsucc_le_reg : forall n m:Z, Zsucc m <= Zsucc n -> m <= n. Proof. -unfold Zle, not in |- *; intros m n H1 H2; apply H1; unfold Zsucc in |- *; - do 2 rewrite <- (Zplus_comm 1); rewrite (Zcompare_plus_compat n m 1); - assumption. + unfold Zle, not in |- *; intros m n H1 H2; apply H1; unfold Zsucc in |- *; + do 2 rewrite <- (Zplus_comm 1); rewrite (Zcompare_plus_compat n m 1); + assumption. Qed. Lemma Zsucc_lt_reg : forall n m:Z, Zsucc n < Zsucc m -> n < m. Proof. -intros n m H; apply Zgt_lt; apply Zsucc_gt_reg; apply Zlt_gt; assumption. -Qed. - -(** Compatibility of addition wrt to order *) - -Lemma Zplus_gt_compat_l : forall n m p:Z, n > m -> p + n > p + m. -Proof. -unfold Zgt in |- *; intros n m p H; rewrite (Zcompare_plus_compat n m p); - assumption. -Qed. - -Lemma Zplus_gt_compat_r : forall n m p:Z, n > m -> n + p > m + p. -Proof. -intros n m p H; rewrite (Zplus_comm n p); rewrite (Zplus_comm m p); - apply Zplus_gt_compat_l; trivial. -Qed. - -Lemma Zplus_le_compat_l : forall n m p:Z, n <= m -> p + n <= p + m. -Proof. -intros n m p; unfold Zle, not in |- *; intros H1 H2; apply H1; - rewrite <- (Zcompare_plus_compat n m p); assumption. -Qed. - -Lemma Zplus_le_compat_r : forall n m p:Z, n <= m -> n + p <= m + p. -Proof. -intros a b c; do 2 rewrite (fun n:Z => Zplus_comm n c); - exact (Zplus_le_compat_l a b c). -Qed. - -Lemma Zplus_lt_compat_l : forall n m p:Z, n < m -> p + n < p + m. -Proof. -unfold Zlt in |- *; intros n m p; rewrite Zcompare_plus_compat; - trivial with arith. -Qed. - -Lemma Zplus_lt_compat_r : forall n m p:Z, n < m -> n + p < m + p. -Proof. -intros n m p H; rewrite (Zplus_comm n p); rewrite (Zplus_comm m p); - apply Zplus_lt_compat_l; trivial. -Qed. - -Lemma Zplus_lt_le_compat : forall n m p q:Z, n < m -> p <= q -> n + p < m + q. -Proof. -intros a b c d H0 H1. -apply Zlt_le_trans with (b + c). -apply Zplus_lt_compat_r; trivial. -apply Zplus_le_compat_l; trivial. -Qed. - -Lemma Zplus_le_lt_compat : forall n m p q:Z, n <= m -> p < q -> n + p < m + q. -Proof. -intros a b c d H0 H1. -apply Zle_lt_trans with (b + c). -apply Zplus_le_compat_r; trivial. -apply Zplus_lt_compat_l; trivial. -Qed. - -Lemma Zplus_le_compat : forall n m p q:Z, n <= m -> p <= q -> n + p <= m + q. -Proof. -intros n m p q; intros H1 H2; apply Zle_trans with (m := n + q); - [ apply Zplus_le_compat_l; assumption - | apply Zplus_le_compat_r; assumption ]. + intros n m H; apply Zgt_lt; apply Zsucc_gt_reg; apply Zlt_gt; assumption. Qed. - -Lemma Zplus_lt_compat : forall n m p q:Z, n < m -> p < q -> n + p < m + q. -intros; apply Zplus_le_lt_compat. apply Zlt_le_weak; assumption. assumption. -Qed. - - -(** Compatibility of addition wrt to being positive *) - -Lemma Zplus_le_0_compat : forall n m:Z, 0 <= n -> 0 <= m -> 0 <= n + m. -Proof. -intros x y H1 H2; rewrite <- (Zplus_0_l 0); apply Zplus_le_compat; assumption. -Qed. - -(** Simplification of addition wrt to order *) - -Lemma Zplus_gt_reg_l : forall n m p:Z, p + n > p + m -> n > m. -Proof. -unfold Zgt in |- *; intros n m p H; rewrite <- (Zcompare_plus_compat n m p); - assumption. -Qed. - -Lemma Zplus_gt_reg_r : forall n m p:Z, n + p > m + p -> n > m. -Proof. -intros n m p H; apply Zplus_gt_reg_l with p. -rewrite (Zplus_comm p n); rewrite (Zplus_comm p m); trivial. -Qed. - -Lemma Zplus_le_reg_l : forall n m p:Z, p + n <= p + m -> n <= m. -Proof. -intros n m p; unfold Zle, not in |- *; intros H1 H2; apply H1; - rewrite (Zcompare_plus_compat n m p); assumption. -Qed. - -Lemma Zplus_le_reg_r : forall n m p:Z, n + p <= m + p -> n <= m. -Proof. -intros n m p H; apply Zplus_le_reg_l with p. -rewrite (Zplus_comm p n); rewrite (Zplus_comm p m); trivial. -Qed. - -Lemma Zplus_lt_reg_l : forall n m p:Z, p + n < p + m -> n < m. -Proof. -unfold Zlt in |- *; intros n m p; rewrite Zcompare_plus_compat; - trivial with arith. -Qed. - -Lemma Zplus_lt_reg_r : forall n m p:Z, n + p < m + p -> n < m. -Proof. -intros n m p H; apply Zplus_lt_reg_l with p. -rewrite (Zplus_comm p n); rewrite (Zplus_comm p m); trivial. -Qed. - (** Special base instances of order *) Lemma Zgt_succ : forall n:Z, Zsucc n > n. Proof. -exact Zcompare_succ_Gt. + exact Zcompare_succ_Gt. Qed. Lemma Znot_le_succ : forall n:Z, ~ Zsucc n <= n. Proof. -intros n; apply Zgt_not_le; apply Zgt_succ. + intros n; apply Zgt_not_le; apply Zgt_succ. Qed. Lemma Zlt_succ : forall n:Z, n < Zsucc n. Proof. -intro n; apply Zgt_lt; apply Zgt_succ. + intro n; apply Zgt_lt; apply Zgt_succ. Qed. Lemma Zlt_pred : forall n:Z, Zpred n < n. Proof. -intros n; apply Zsucc_lt_reg; rewrite <- Zsucc_pred; apply Zlt_succ. + intros n; apply Zsucc_lt_reg; rewrite <- Zsucc_pred; apply Zlt_succ. Qed. (** Relating strict and large order using successor or predecessor *) Lemma Zgt_le_succ : forall n m:Z, m > n -> Zsucc n <= m. Proof. -unfold Zgt, Zle in |- *; intros n p H; elim (Zcompare_Gt_not_Lt p n); - intros H1 H2; unfold not in |- *; intros H3; unfold not in H1; - apply H1; - [ assumption - | elim (Zcompare_Gt_Lt_antisym (n + 1) p); intros H4 H5; apply H4; exact H3 ]. + unfold Zgt, Zle in |- *; intros n p H; elim (Zcompare_Gt_not_Lt p n); + intros H1 H2; unfold not in |- *; intros H3; unfold not in H1; + apply H1; + [ assumption + | elim (Zcompare_Gt_Lt_antisym (n + 1) p); intros H4 H5; apply H4; exact H3 ]. Qed. Lemma Zlt_gt_succ : forall n m:Z, n <= m -> Zsucc m > n. Proof. -intros n p H; apply Zgt_le_trans with p. + intros n p H; apply Zgt_le_trans with p. apply Zgt_succ. assumption. Qed. Lemma Zle_lt_succ : forall n m:Z, n <= m -> n < Zsucc m. Proof. -intros n m H; apply Zgt_lt; apply Zlt_gt_succ; assumption. + intros n m H; apply Zgt_lt; apply Zlt_gt_succ; assumption. Qed. Lemma Zlt_le_succ : forall n m:Z, n < m -> Zsucc n <= m. Proof. -intros n p H; apply Zgt_le_succ; apply Zlt_gt; assumption. + intros n p H; apply Zgt_le_succ; apply Zlt_gt; assumption. Qed. Lemma Zgt_succ_le : forall n m:Z, Zsucc m > n -> n <= m. Proof. -intros n p H; apply Zsucc_le_reg; apply Zgt_le_succ; assumption. + intros n p H; apply Zsucc_le_reg; apply Zgt_le_succ; assumption. Qed. Lemma Zlt_succ_le : forall n m:Z, n < Zsucc m -> n <= m. Proof. -intros n m H; apply Zgt_succ_le; apply Zlt_gt; assumption. + intros n m H; apply Zgt_succ_le; apply Zlt_gt; assumption. Qed. Lemma Zlt_succ_gt : forall n m:Z, Zsucc n <= m -> m > n. Proof. -intros n m H; apply Zle_gt_trans with (m := Zsucc n); - [ assumption | apply Zgt_succ ]. + intros n m H; apply Zle_gt_trans with (m := Zsucc n); + [ assumption | apply Zgt_succ ]. Qed. (** Weakening order *) Lemma Zle_succ : forall n:Z, n <= Zsucc n. Proof. -intros n; apply Zgt_succ_le; apply Zgt_trans with (m := Zsucc n); - apply Zgt_succ. + intros n; apply Zgt_succ_le; apply Zgt_trans with (m := Zsucc n); + apply Zgt_succ. Qed. Hint Resolve Zle_succ: zarith. Lemma Zle_pred : forall n:Z, Zpred n <= n. Proof. -intros n; pattern n at 2 in |- *; rewrite Zsucc_pred; apply Zle_succ. + intros n; pattern n at 2 in |- *; rewrite Zsucc_pred; apply Zle_succ. Qed. Lemma Zlt_lt_succ : forall n m:Z, n < m -> n < Zsucc m. -intros n m H; apply Zgt_lt; apply Zgt_trans with (m := m); - [ apply Zgt_succ | apply Zlt_gt; assumption ]. + intros n m H; apply Zgt_lt; apply Zgt_trans with (m := m); + [ apply Zgt_succ | apply Zlt_gt; assumption ]. Qed. Lemma Zle_le_succ : forall n m:Z, n <= m -> n <= Zsucc m. Proof. -intros x y H. -apply Zle_trans with y; trivial with zarith. + intros x y H. + apply Zle_trans with y; trivial with zarith. Qed. Lemma Zle_succ_le : forall n m:Z, Zsucc n <= m -> n <= m. Proof. -intros n m H; apply Zle_trans with (m := Zsucc n); - [ apply Zle_succ | assumption ]. + intros n m H; apply Zle_trans with (m := Zsucc n); + [ apply Zle_succ | assumption ]. Qed. Hint Resolve Zle_le_succ: zarith. @@ -582,31 +477,32 @@ Hint Resolve Zle_le_succ: zarith. Lemma Zgt_succ_pred : forall n m:Z, m > Zsucc n -> Zpred m > n. Proof. -unfold Zgt, Zsucc, Zpred in |- *; intros n p H; - rewrite <- (fun x y => Zcompare_plus_compat x y 1); - rewrite (Zplus_comm p); rewrite Zplus_assoc; - rewrite (fun x => Zplus_comm x n); simpl in |- *; - assumption. + unfold Zgt, Zsucc, Zpred in |- *; intros n p H; + rewrite <- (fun x y => Zcompare_plus_compat x y 1); + rewrite (Zplus_comm p); rewrite Zplus_assoc; + rewrite (fun x => Zplus_comm x n); simpl in |- *; + assumption. Qed. Lemma Zlt_succ_pred : forall n m:Z, Zsucc n < m -> n < Zpred m. Proof. -intros n p H; apply Zsucc_lt_reg; rewrite <- Zsucc_pred; assumption. + intros n p H; apply Zsucc_lt_reg; rewrite <- Zsucc_pred; assumption. Qed. (** Relating strict order and large order on positive *) Lemma Zlt_0_le_0_pred : forall n:Z, 0 < n -> 0 <= Zpred n. -intros x H. -rewrite (Zsucc_pred x) in H. -apply Zgt_succ_le. -apply Zlt_gt. -assumption. +Proof. + intros x H. + rewrite (Zsucc_pred x) in H. + apply Zgt_succ_le. + apply Zlt_gt. + assumption. Qed. - Lemma Zgt_0_le_0_pred : forall n:Z, n > 0 -> 0 <= Zpred n. -intros; apply Zlt_0_le_0_pred; apply Zgt_lt. assumption. +Proof. + intros; apply Zlt_0_le_0_pred; apply Zgt_lt. assumption. Qed. @@ -614,35 +510,39 @@ Qed. Lemma Zlt_0_1 : 0 < 1. Proof. -change (0 < Zsucc 0) in |- *. apply Zlt_succ. + change (0 < Zsucc 0) in |- *. apply Zlt_succ. Qed. Lemma Zle_0_1 : 0 <= 1. Proof. -change (0 <= Zsucc 0) in |- *. apply Zle_succ. + change (0 <= Zsucc 0) in |- *. apply Zle_succ. Qed. Lemma Zle_neg_pos : forall p q:positive, Zneg p <= Zpos q. Proof. -intros p; red in |- *; simpl in |- *; red in |- *; intros H; discriminate. + intros p; red in |- *; simpl in |- *; red in |- *; intros H; discriminate. Qed. Lemma Zgt_pos_0 : forall p:positive, Zpos p > 0. -unfold Zgt in |- *; trivial. +Proof. + unfold Zgt in |- *; trivial. Qed. - (* weaker but useful (in [Zpower] for instance) *) +(* weaker but useful (in [Zpower] for instance) *) Lemma Zle_0_pos : forall p:positive, 0 <= Zpos p. -intro; unfold Zle in |- *; discriminate. +Proof. + intro; unfold Zle in |- *; discriminate. Qed. Lemma Zlt_neg_0 : forall p:positive, Zneg p < 0. -unfold Zlt in |- *; trivial. +Proof. + unfold Zlt in |- *; trivial. Qed. Lemma Zle_0_nat : forall n:nat, 0 <= Z_of_nat n. -simple induction n; simpl in |- *; intros; - [ apply Zle_refl | unfold Zle in |- *; simpl in |- *; discriminate ]. +Proof. + simple induction n; simpl in |- *; intros; + [ apply Zle_refl | unfold Zle in |- *; simpl in |- *; discriminate ]. Qed. Hint Immediate Zeq_le: zarith. @@ -651,178 +551,294 @@ Hint Immediate Zeq_le: zarith. Lemma Zge_trans_succ : forall n m p:Z, Zsucc n > m -> m > p -> n > p. Proof. -intros n m p H1 H2; apply Zle_gt_trans with (m := m); - [ apply Zgt_succ_le; assumption | assumption ]. + intros n m p H1 H2; apply Zle_gt_trans with (m := m); + [ apply Zgt_succ_le; assumption | assumption ]. Qed. (** Derived lemma *) Lemma Zgt_succ_gt_or_eq : forall n m:Z, Zsucc n > m -> n > m \/ m = n. Proof. -intros n m H. -assert (Hle : m <= n). + intros n m H. + assert (Hle : m <= n). apply Zgt_succ_le; assumption. -destruct (Zle_lt_or_eq _ _ Hle) as [Hlt| Heq]. + destruct (Zle_lt_or_eq _ _ Hle) as [Hlt| Heq]. left; apply Zlt_gt; assumption. right; assumption. Qed. -(** Compatibility of multiplication by a positive wrt to order *) +(** ** Addition *) +(** Compatibility of addition wrt to order *) + +Lemma Zplus_gt_compat_l : forall n m p:Z, n > m -> p + n > p + m. +Proof. + unfold Zgt in |- *; intros n m p H; rewrite (Zcompare_plus_compat n m p); + assumption. +Qed. + +Lemma Zplus_gt_compat_r : forall n m p:Z, n > m -> n + p > m + p. +Proof. + intros n m p H; rewrite (Zplus_comm n p); rewrite (Zplus_comm m p); + apply Zplus_gt_compat_l; trivial. +Qed. + +Lemma Zplus_le_compat_l : forall n m p:Z, n <= m -> p + n <= p + m. +Proof. + intros n m p; unfold Zle, not in |- *; intros H1 H2; apply H1; + rewrite <- (Zcompare_plus_compat n m p); assumption. +Qed. + +Lemma Zplus_le_compat_r : forall n m p:Z, n <= m -> n + p <= m + p. +Proof. + intros a b c; do 2 rewrite (fun n:Z => Zplus_comm n c); + exact (Zplus_le_compat_l a b c). +Qed. + +Lemma Zplus_lt_compat_l : forall n m p:Z, n < m -> p + n < p + m. +Proof. + unfold Zlt in |- *; intros n m p; rewrite Zcompare_plus_compat; + trivial with arith. +Qed. +Lemma Zplus_lt_compat_r : forall n m p:Z, n < m -> n + p < m + p. +Proof. + intros n m p H; rewrite (Zplus_comm n p); rewrite (Zplus_comm m p); + apply Zplus_lt_compat_l; trivial. +Qed. + +Lemma Zplus_lt_le_compat : forall n m p q:Z, n < m -> p <= q -> n + p < m + q. +Proof. + intros a b c d H0 H1. + apply Zlt_le_trans with (b + c). + apply Zplus_lt_compat_r; trivial. + apply Zplus_le_compat_l; trivial. +Qed. + +Lemma Zplus_le_lt_compat : forall n m p q:Z, n <= m -> p < q -> n + p < m + q. +Proof. + intros a b c d H0 H1. + apply Zle_lt_trans with (b + c). + apply Zplus_le_compat_r; trivial. + apply Zplus_lt_compat_l; trivial. +Qed. + +Lemma Zplus_le_compat : forall n m p q:Z, n <= m -> p <= q -> n + p <= m + q. +Proof. + intros n m p q; intros H1 H2; apply Zle_trans with (m := n + q); + [ apply Zplus_le_compat_l; assumption + | apply Zplus_le_compat_r; assumption ]. +Qed. + + +Lemma Zplus_lt_compat : forall n m p q:Z, n < m -> p < q -> n + p < m + q. + intros; apply Zplus_le_lt_compat. apply Zlt_le_weak; assumption. assumption. +Qed. + + +(** Compatibility of addition wrt to being positive *) + +Lemma Zplus_le_0_compat : forall n m:Z, 0 <= n -> 0 <= m -> 0 <= n + m. +Proof. + intros x y H1 H2; rewrite <- (Zplus_0_l 0); apply Zplus_le_compat; assumption. +Qed. + +(** Simplification of addition wrt to order *) + +Lemma Zplus_gt_reg_l : forall n m p:Z, p + n > p + m -> n > m. +Proof. + unfold Zgt in |- *; intros n m p H; rewrite <- (Zcompare_plus_compat n m p); + assumption. +Qed. + +Lemma Zplus_gt_reg_r : forall n m p:Z, n + p > m + p -> n > m. +Proof. + intros n m p H; apply Zplus_gt_reg_l with p. + rewrite (Zplus_comm p n); rewrite (Zplus_comm p m); trivial. +Qed. + +Lemma Zplus_le_reg_l : forall n m p:Z, p + n <= p + m -> n <= m. +Proof. + intros n m p; unfold Zle, not in |- *; intros H1 H2; apply H1; + rewrite (Zcompare_plus_compat n m p); assumption. +Qed. + +Lemma Zplus_le_reg_r : forall n m p:Z, n + p <= m + p -> n <= m. +Proof. + intros n m p H; apply Zplus_le_reg_l with p. + rewrite (Zplus_comm p n); rewrite (Zplus_comm p m); trivial. +Qed. + +Lemma Zplus_lt_reg_l : forall n m p:Z, p + n < p + m -> n < m. +Proof. + unfold Zlt in |- *; intros n m p; rewrite Zcompare_plus_compat; + trivial with arith. +Qed. + +Lemma Zplus_lt_reg_r : forall n m p:Z, n + p < m + p -> n < m. +Proof. + intros n m p H; apply Zplus_lt_reg_l with p. + rewrite (Zplus_comm p n); rewrite (Zplus_comm p m); trivial. +Qed. + +(** ** Multiplication *) +(** Compatibility of multiplication by a positive wrt to order *) Lemma Zmult_le_compat_r : forall n m p:Z, n <= m -> 0 <= p -> n * p <= m * p. Proof. -intros a b c H H0; destruct c. + intros a b c H H0; destruct c. do 2 rewrite Zmult_0_r; assumption. rewrite (Zmult_comm a); rewrite (Zmult_comm b). - unfold Zle in |- *; rewrite Zcompare_mult_compat; assumption. + unfold Zle in |- *; rewrite Zcompare_mult_compat; assumption. unfold Zle in H0; contradiction H0; reflexivity. Qed. Lemma Zmult_le_compat_l : forall n m p:Z, n <= m -> 0 <= p -> p * n <= p * m. Proof. -intros a b c H1 H2; rewrite (Zmult_comm c a); rewrite (Zmult_comm c b). -apply Zmult_le_compat_r; trivial. + intros a b c H1 H2; rewrite (Zmult_comm c a); rewrite (Zmult_comm c b). + apply Zmult_le_compat_r; trivial. Qed. Lemma Zmult_lt_compat_r : forall n m p:Z, 0 < p -> n < m -> n * p < m * p. Proof. -intros x y z H H0; destruct z. + intros x y z H H0; destruct z. contradiction (Zlt_irrefl 0). rewrite (Zmult_comm x); rewrite (Zmult_comm y). - unfold Zlt in |- *; rewrite Zcompare_mult_compat; assumption. + unfold Zlt in |- *; rewrite Zcompare_mult_compat; assumption. discriminate H. Qed. Lemma Zmult_gt_compat_r : forall n m p:Z, p > 0 -> n > m -> n * p > m * p. Proof. -intros x y z; intros; apply Zlt_gt; apply Zmult_lt_compat_r; apply Zgt_lt; - assumption. + intros x y z; intros; apply Zlt_gt; apply Zmult_lt_compat_r; apply Zgt_lt; + assumption. Qed. Lemma Zmult_gt_0_lt_compat_r : - forall n m p:Z, p > 0 -> n < m -> n * p < m * p. + forall n m p:Z, p > 0 -> n < m -> n * p < m * p. Proof. -intros x y z; intros; apply Zmult_lt_compat_r; - [ apply Zgt_lt; assumption | assumption ]. + intros x y z; intros; apply Zmult_lt_compat_r; + [ apply Zgt_lt; assumption | assumption ]. Qed. Lemma Zmult_gt_0_le_compat_r : - forall n m p:Z, p > 0 -> n <= m -> n * p <= m * p. + forall n m p:Z, p > 0 -> n <= m -> n * p <= m * p. Proof. -intros x y z Hz Hxy. -elim (Zle_lt_or_eq x y Hxy). -intros; apply Zlt_le_weak. -apply Zmult_gt_0_lt_compat_r; trivial. -intros; apply Zeq_le. -rewrite H; trivial. + intros x y z Hz Hxy. + elim (Zle_lt_or_eq x y Hxy). + intros; apply Zlt_le_weak. + apply Zmult_gt_0_lt_compat_r; trivial. + intros; apply Zeq_le. + rewrite H; trivial. Qed. Lemma Zmult_lt_0_le_compat_r : - forall n m p:Z, 0 < p -> n <= m -> n * p <= m * p. + forall n m p:Z, 0 < p -> n <= m -> n * p <= m * p. Proof. -intros x y z; intros; apply Zmult_gt_0_le_compat_r; try apply Zlt_gt; - assumption. + intros x y z; intros; apply Zmult_gt_0_le_compat_r; try apply Zlt_gt; + assumption. Qed. Lemma Zmult_gt_0_lt_compat_l : - forall n m p:Z, p > 0 -> n < m -> p * n < p * m. + forall n m p:Z, p > 0 -> n < m -> p * n < p * m. Proof. -intros x y z; intros. -rewrite (Zmult_comm z x); rewrite (Zmult_comm z y); - apply Zmult_gt_0_lt_compat_r; assumption. + intros x y z; intros. + rewrite (Zmult_comm z x); rewrite (Zmult_comm z y); + apply Zmult_gt_0_lt_compat_r; assumption. Qed. Lemma Zmult_lt_compat_l : forall n m p:Z, 0 < p -> n < m -> p * n < p * m. Proof. -intros x y z; intros. -rewrite (Zmult_comm z x); rewrite (Zmult_comm z y); - apply Zmult_gt_0_lt_compat_r; try apply Zlt_gt; assumption. + intros x y z; intros. + rewrite (Zmult_comm z x); rewrite (Zmult_comm z y); + apply Zmult_gt_0_lt_compat_r; try apply Zlt_gt; assumption. Qed. Lemma Zmult_gt_compat_l : forall n m p:Z, p > 0 -> n > m -> p * n > p * m. Proof. -intros x y z; intros; rewrite (Zmult_comm z x); rewrite (Zmult_comm z y); - apply Zmult_gt_compat_r; assumption. + intros x y z; intros; rewrite (Zmult_comm z x); rewrite (Zmult_comm z y); + apply Zmult_gt_compat_r; assumption. Qed. Lemma Zmult_ge_compat_r : forall n m p:Z, n >= m -> p >= 0 -> n * p >= m * p. Proof. -intros a b c H1 H2; apply Zle_ge. -apply Zmult_le_compat_r; apply Zge_le; trivial. + intros a b c H1 H2; apply Zle_ge. + apply Zmult_le_compat_r; apply Zge_le; trivial. Qed. Lemma Zmult_ge_compat_l : forall n m p:Z, n >= m -> p >= 0 -> p * n >= p * m. Proof. -intros a b c H1 H2; apply Zle_ge. -apply Zmult_le_compat_l; apply Zge_le; trivial. + intros a b c H1 H2; apply Zle_ge. + apply Zmult_le_compat_l; apply Zge_le; trivial. Qed. Lemma Zmult_ge_compat : - forall n m p q:Z, n >= p -> m >= q -> p >= 0 -> q >= 0 -> n * m >= p * q. + forall n m p q:Z, n >= p -> m >= q -> p >= 0 -> q >= 0 -> n * m >= p * q. Proof. -intros a b c d H0 H1 H2 H3. -apply Zge_trans with (a * d). -apply Zmult_ge_compat_l; trivial. -apply Zge_trans with c; trivial. -apply Zmult_ge_compat_r; trivial. + intros a b c d H0 H1 H2 H3. + apply Zge_trans with (a * d). + apply Zmult_ge_compat_l; trivial. + apply Zge_trans with c; trivial. + apply Zmult_ge_compat_r; trivial. Qed. Lemma Zmult_le_compat : - forall n m p q:Z, n <= p -> m <= q -> 0 <= n -> 0 <= m -> n * m <= p * q. + forall n m p q:Z, n <= p -> m <= q -> 0 <= n -> 0 <= m -> n * m <= p * q. Proof. -intros a b c d H0 H1 H2 H3. -apply Zle_trans with (c * b). -apply Zmult_le_compat_r; assumption. -apply Zmult_le_compat_l. -assumption. -apply Zle_trans with a; assumption. + intros a b c d H0 H1 H2 H3. + apply Zle_trans with (c * b). + apply Zmult_le_compat_r; assumption. + apply Zmult_le_compat_l. + assumption. + apply Zle_trans with a; assumption. Qed. (** Simplification of multiplication by a positive wrt to being positive *) Lemma Zmult_gt_0_lt_reg_r : forall n m p:Z, p > 0 -> n * p < m * p -> n < m. Proof. -intros x y z; intros; destruct z. + intros x y z; intros; destruct z. contradiction (Zgt_irrefl 0). rewrite (Zmult_comm x) in H0; rewrite (Zmult_comm y) in H0. - unfold Zlt in H0; rewrite Zcompare_mult_compat in H0; assumption. + unfold Zlt in H0; rewrite Zcompare_mult_compat in H0; assumption. discriminate H. Qed. Lemma Zmult_lt_reg_r : forall n m p:Z, 0 < p -> n * p < m * p -> n < m. Proof. -intros a b c H0 H1. -apply Zmult_gt_0_lt_reg_r with c; try apply Zlt_gt; assumption. + intros a b c H0 H1. + apply Zmult_gt_0_lt_reg_r with c; try apply Zlt_gt; assumption. Qed. Lemma Zmult_le_reg_r : forall n m p:Z, p > 0 -> n * p <= m * p -> n <= m. Proof. -intros x y z Hz Hxy. -elim (Zle_lt_or_eq (x * z) (y * z) Hxy). -intros; apply Zlt_le_weak. -apply Zmult_gt_0_lt_reg_r with z; trivial. -intros; apply Zeq_le. -apply Zmult_reg_r with z. + intros x y z Hz Hxy. + elim (Zle_lt_or_eq (x * z) (y * z) Hxy). + intros; apply Zlt_le_weak. + apply Zmult_gt_0_lt_reg_r with z; trivial. + intros; apply Zeq_le. + apply Zmult_reg_r with z. intro. rewrite H0 in Hz. contradiction (Zgt_irrefl 0). -assumption. + assumption. Qed. Lemma Zmult_lt_0_le_reg_r : forall n m p:Z, 0 < p -> n * p <= m * p -> n <= m. -intros x y z; intros; apply Zmult_le_reg_r with z. -try apply Zlt_gt; assumption. -assumption. +Proof. + intros x y z; intros; apply Zmult_le_reg_r with z. + try apply Zlt_gt; assumption. + assumption. Qed. Lemma Zmult_ge_reg_r : forall n m p:Z, p > 0 -> n * p >= m * p -> n >= m. -intros a b c H1 H2; apply Zle_ge; apply Zmult_le_reg_r with c; trivial. -apply Zge_le; trivial. +Proof. + intros a b c H1 H2; apply Zle_ge; apply Zmult_le_reg_r with c; trivial. + apply Zge_le; trivial. Qed. Lemma Zmult_gt_reg_r : forall n m p:Z, p > 0 -> n * p > m * p -> n > m. -intros a b c H1 H2; apply Zlt_gt; apply Zmult_gt_0_lt_reg_r with c; trivial. -apply Zgt_lt; trivial. +Proof. + intros a b c H1 H2; apply Zlt_gt; apply Zmult_gt_0_lt_reg_r with c; trivial. + apply Zgt_lt; trivial. Qed. @@ -830,154 +846,156 @@ Qed. Lemma Zmult_le_0_compat : forall n m:Z, 0 <= n -> 0 <= m -> 0 <= n * m. Proof. -intros x y; case x. -intros; rewrite Zmult_0_l; trivial. -intros p H1; unfold Zle in |- *. + intros x y; case x. + intros; rewrite Zmult_0_l; trivial. + intros p H1; unfold Zle in |- *. pattern 0 at 2 in |- *; rewrite <- (Zmult_0_r (Zpos p)). rewrite Zcompare_mult_compat; trivial. -intros p H1 H2; absurd (0 > Zneg p); trivial. -unfold Zgt in |- *; simpl in |- *; auto with zarith. + intros p H1 H2; absurd (0 > Zneg p); trivial. + unfold Zgt in |- *; simpl in |- *; auto with zarith. Qed. Lemma Zmult_gt_0_compat : forall n m:Z, n > 0 -> m > 0 -> n * m > 0. Proof. -intros x y; case x. -intros H; discriminate H. -intros p H1; unfold Zgt in |- *; pattern 0 at 2 in |- *; - rewrite <- (Zmult_0_r (Zpos p)). + intros x y; case x. + intros H; discriminate H. + intros p H1; unfold Zgt in |- *; pattern 0 at 2 in |- *; + rewrite <- (Zmult_0_r (Zpos p)). rewrite Zcompare_mult_compat; trivial. -intros p H; discriminate H. + intros p H; discriminate H. Qed. Lemma Zmult_lt_0_compat : forall n m:Z, 0 < n -> 0 < m -> 0 < n * m. -intros a b apos bpos. -apply Zgt_lt. -apply Zmult_gt_0_compat; try apply Zlt_gt; assumption. +Proof. + intros a b apos bpos. + apply Zgt_lt. + apply Zmult_gt_0_compat; try apply Zlt_gt; assumption. Qed. -(* For compatibility *) +(** For compatibility *) Notation Zmult_lt_O_compat := Zmult_lt_0_compat (only parsing). Lemma Zmult_gt_0_le_0_compat : forall n m:Z, n > 0 -> 0 <= m -> 0 <= m * n. Proof. -intros x y H1 H2; apply Zmult_le_0_compat; trivial. -apply Zlt_le_weak; apply Zgt_lt; trivial. + intros x y H1 H2; apply Zmult_le_0_compat; trivial. + apply Zlt_le_weak; apply Zgt_lt; trivial. Qed. (** Simplification of multiplication by a positive wrt to being positive *) Lemma Zmult_le_0_reg_r : forall n m:Z, n > 0 -> 0 <= m * n -> 0 <= m. Proof. -intros x y; case x; - [ simpl in |- *; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H - | intros p H1; unfold Zle in |- *; rewrite Zmult_comm; - pattern 0 at 1 in |- *; rewrite <- (Zmult_0_r (Zpos p)); - rewrite Zcompare_mult_compat; auto with arith - | intros p; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H ]. + intros x y; case x; + [ simpl in |- *; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H + | intros p H1; unfold Zle in |- *; rewrite Zmult_comm; + pattern 0 at 1 in |- *; rewrite <- (Zmult_0_r (Zpos p)); + rewrite Zcompare_mult_compat; auto with arith + | intros p; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H ]. Qed. Lemma Zmult_gt_0_lt_0_reg_r : forall n m:Z, n > 0 -> 0 < m * n -> 0 < m. Proof. -intros x y; case x; - [ simpl in |- *; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H - | intros p H1; unfold Zlt in |- *; rewrite Zmult_comm; - pattern 0 at 1 in |- *; rewrite <- (Zmult_0_r (Zpos p)); - rewrite Zcompare_mult_compat; auto with arith - | intros p; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H ]. + intros x y; case x; + [ simpl in |- *; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H + | intros p H1; unfold Zlt in |- *; rewrite Zmult_comm; + pattern 0 at 1 in |- *; rewrite <- (Zmult_0_r (Zpos p)); + rewrite Zcompare_mult_compat; auto with arith + | intros p; unfold Zgt in |- *; simpl in |- *; intros H; discriminate H ]. Qed. Lemma Zmult_lt_0_reg_r : forall n m:Z, 0 < n -> 0 < m * n -> 0 < m. Proof. -intros x y; intros; eapply Zmult_gt_0_lt_0_reg_r with x; try apply Zlt_gt; - assumption. + intros x y; intros; eapply Zmult_gt_0_lt_0_reg_r with x; try apply Zlt_gt; + assumption. Qed. Lemma Zmult_gt_0_reg_l : forall n m:Z, n > 0 -> n * m > 0 -> m > 0. Proof. -intros x y; case x. - intros H; discriminate H. - intros p H1; unfold Zgt in |- *. - pattern 0 at 1 in |- *; rewrite <- (Zmult_0_r (Zpos p)). - rewrite Zcompare_mult_compat; trivial. -intros p H; discriminate H. + intros x y; case x. + intros H; discriminate H. + intros p H1; unfold Zgt in |- *. + pattern 0 at 1 in |- *; rewrite <- (Zmult_0_r (Zpos p)). + rewrite Zcompare_mult_compat; trivial. + intros p H; discriminate H. Qed. +(** ** Square *) (** Simplification of square wrt order *) Lemma Zgt_square_simpl : - forall n m:Z, n >= 0 -> n * n > m * m -> n > m. + forall n m:Z, n >= 0 -> n * n > m * m -> n > m. Proof. -intros n m H0 H1. -case (dec_Zlt m n). -intro; apply Zlt_gt; trivial. -intros H2; cut (m >= n). -intros H. -elim Zgt_not_le with (1 := H1). -apply Zge_le. -apply Zmult_ge_compat; auto. -apply Znot_lt_ge; trivial. + intros n m H0 H1. + case (dec_Zlt m n). + intro; apply Zlt_gt; trivial. + intros H2; cut (m >= n). + intros H. + elim Zgt_not_le with (1 := H1). + apply Zge_le. + apply Zmult_ge_compat; auto. + apply Znot_lt_ge; trivial. Qed. Lemma Zlt_square_simpl : - forall n m:Z, 0 <= n -> m * m < n * n -> m < n. + forall n m:Z, 0 <= n -> m * m < n * n -> m < n. Proof. -intros x y H0 H1. -apply Zgt_lt. -apply Zgt_square_simpl; try apply Zle_ge; try apply Zlt_gt; assumption. + intros x y H0 H1. + apply Zgt_lt. + apply Zgt_square_simpl; try apply Zle_ge; try apply Zlt_gt; assumption. Qed. -(** Equivalence between inequalities *) +(** * Equivalence between inequalities *) Lemma Zle_plus_swap : forall n m p:Z, n + p <= m <-> n <= m - p. Proof. - intros x y z; intros. split. intro. rewrite <- (Zplus_0_r x). rewrite <- (Zplus_opp_r z). - rewrite Zplus_assoc. exact (Zplus_le_compat_r _ _ _ H). - intro. rewrite <- (Zplus_0_r y). rewrite <- (Zplus_opp_l z). rewrite Zplus_assoc. - apply Zplus_le_compat_r. assumption. + intros x y z; intros. split. intro. rewrite <- (Zplus_0_r x). rewrite <- (Zplus_opp_r z). + rewrite Zplus_assoc. exact (Zplus_le_compat_r _ _ _ H). + intro. rewrite <- (Zplus_0_r y). rewrite <- (Zplus_opp_l z). rewrite Zplus_assoc. + apply Zplus_le_compat_r. assumption. Qed. Lemma Zlt_plus_swap : forall n m p:Z, n + p < m <-> n < m - p. Proof. - intros x y z; intros. split. intro. unfold Zminus in |- *. rewrite Zplus_comm. rewrite <- (Zplus_0_l x). - rewrite <- (Zplus_opp_l z). rewrite Zplus_assoc_reverse. apply Zplus_lt_compat_l. rewrite Zplus_comm. - assumption. - intro. rewrite Zplus_comm. rewrite <- (Zplus_0_l y). rewrite <- (Zplus_opp_r z). - rewrite Zplus_assoc_reverse. apply Zplus_lt_compat_l. rewrite Zplus_comm. assumption. + intros x y z; intros. split. intro. unfold Zminus in |- *. rewrite Zplus_comm. rewrite <- (Zplus_0_l x). + rewrite <- (Zplus_opp_l z). rewrite Zplus_assoc_reverse. apply Zplus_lt_compat_l. rewrite Zplus_comm. + assumption. + intro. rewrite Zplus_comm. rewrite <- (Zplus_0_l y). rewrite <- (Zplus_opp_r z). + rewrite Zplus_assoc_reverse. apply Zplus_lt_compat_l. rewrite Zplus_comm. assumption. Qed. Lemma Zeq_plus_swap : forall n m p:Z, n + p = m <-> n = m - p. Proof. -intros x y z; intros. split. intro. apply Zplus_minus_eq. symmetry in |- *. rewrite Zplus_comm. + intros x y z; intros. split. intro. apply Zplus_minus_eq. symmetry in |- *. rewrite Zplus_comm. assumption. -intro. rewrite H. unfold Zminus in |- *. rewrite Zplus_assoc_reverse. + intro. rewrite H. unfold Zminus in |- *. rewrite Zplus_assoc_reverse. rewrite Zplus_opp_l. apply Zplus_0_r. Qed. Lemma Zlt_minus_simpl_swap : forall n m:Z, 0 < m -> n - m < n. Proof. -intros n m H; apply Zplus_lt_reg_l with (p := m); rewrite Zplus_minus; - pattern n at 1 in |- *; rewrite <- (Zplus_0_r n); - rewrite (Zplus_comm m n); apply Zplus_lt_compat_l; - assumption. + intros n m H; apply Zplus_lt_reg_l with (p := m); rewrite Zplus_minus; + pattern n at 1 in |- *; rewrite <- (Zplus_0_r n); + rewrite (Zplus_comm m n); apply Zplus_lt_compat_l; + assumption. Qed. Lemma Zlt_0_minus_lt : forall n m:Z, 0 < n - m -> m < n. Proof. -intros n m H; apply Zplus_lt_reg_l with (p := - m); rewrite Zplus_opp_l; - rewrite Zplus_comm; exact H. + intros n m H; apply Zplus_lt_reg_l with (p := - m); rewrite Zplus_opp_l; + rewrite Zplus_comm; exact H. Qed. Lemma Zle_0_minus_le : forall n m:Z, 0 <= n - m -> m <= n. Proof. -intros n m H; apply Zplus_le_reg_l with (p := - m); rewrite Zplus_opp_l; - rewrite Zplus_comm; exact H. + intros n m H; apply Zplus_le_reg_l with (p := - m); rewrite Zplus_opp_l; + rewrite Zplus_comm; exact H. Qed. Lemma Zle_minus_le_0 : forall n m:Z, m <= n -> 0 <= n - m. Proof. -intros n m H; unfold Zminus; apply Zplus_le_reg_r with (p := m); -rewrite <- Zplus_assoc; rewrite Zplus_opp_l; rewrite Zplus_0_r; exact H. + intros n m H; unfold Zminus; apply Zplus_le_reg_r with (p := m); + rewrite <- Zplus_assoc; rewrite Zplus_opp_l; rewrite Zplus_0_r; exact H. Qed. -(* For compatibility *) +(** For compatibility *) Notation Zlt_O_minus_lt := Zlt_0_minus_lt (only parsing). diff --git a/theories/ZArith/Zpower.v b/theories/ZArith/Zpower.v index 70a2bd45..446f663c 100644 --- a/theories/ZArith/Zpower.v +++ b/theories/ZArith/Zpower.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zpower.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: Zpower.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import ZArith_base. Require Import Omega. @@ -15,81 +15,84 @@ Open Local Scope Z_scope. Section section1. +(** * Definition of powers over [Z]*) + (** [Zpower_nat z n] is the n-th power of [z] when [n] is an unary integer (type [nat]) and [z] a signed integer (type [Z]) *) -Definition Zpower_nat (z:Z) (n:nat) := iter_nat n Z (fun x:Z => z * x) 1. - -(** [Zpower_nat_is_exp] says [Zpower_nat] is a morphism for - [plus : nat->nat] and [Zmult : Z->Z] *) - -Lemma Zpower_nat_is_exp : - forall (n m:nat) (z:Z), - Zpower_nat z (n + m) = Zpower_nat z n * Zpower_nat z m. - -intros; elim n; - [ simpl in |- *; elim (Zpower_nat z m); auto with zarith - | unfold Zpower_nat in |- *; intros; simpl in |- *; rewrite H; - apply Zmult_assoc ]. -Qed. - -(** [Zpower_pos z n] is the n-th power of [z] when [n] is an binary - integer (type [positive]) and [z] a signed integer (type [Z]) *) - -Definition Zpower_pos (z:Z) (n:positive) := iter_pos n Z (fun x:Z => z * x) 1. - -(** This theorem shows that powers of unary and binary integers - are the same thing, modulo the function convert : [positive -> nat] *) - -Theorem Zpower_pos_nat : - forall (z:Z) (p:positive), Zpower_pos z p = Zpower_nat z (nat_of_P p). - -intros; unfold Zpower_pos in |- *; unfold Zpower_nat in |- *; - apply iter_nat_of_P. -Qed. - -(** Using the theorem [Zpower_pos_nat] and the lemma [Zpower_nat_is_exp] we - deduce that the function [[n:positive](Zpower_pos z n)] is a morphism - for [add : positive->positive] and [Zmult : Z->Z] *) - -Theorem Zpower_pos_is_exp : - forall (n m:positive) (z:Z), - Zpower_pos z (n + m) = Zpower_pos z n * Zpower_pos z m. - -intros. -rewrite (Zpower_pos_nat z n). -rewrite (Zpower_pos_nat z m). -rewrite (Zpower_pos_nat z (n + m)). -rewrite (nat_of_P_plus_morphism n m). -apply Zpower_nat_is_exp. -Qed. - -Definition Zpower (x y:Z) := - match y with - | Zpos p => Zpower_pos x p - | Z0 => 1 - | Zneg p => 0 - end. - -Infix "^" := Zpower : Z_scope. - -Hint Immediate Zpower_nat_is_exp: zarith. -Hint Immediate Zpower_pos_is_exp: zarith. -Hint Unfold Zpower_pos: zarith. -Hint Unfold Zpower_nat: zarith. - -Lemma Zpower_exp : - forall x n m:Z, n >= 0 -> m >= 0 -> x ^ (n + m) = x ^ n * x ^ m. -destruct n; destruct m; auto with zarith. -simpl in |- *; intros; apply Zred_factor0. -simpl in |- *; auto with zarith. -intros; compute in H0; absurd (Datatypes.Lt = Datatypes.Lt); auto with zarith. -intros; compute in H0; absurd (Datatypes.Lt = Datatypes.Lt); auto with zarith. -Qed. + Definition Zpower_nat (z:Z) (n:nat) := iter_nat n Z (fun x:Z => z * x) 1. + + (** [Zpower_nat_is_exp] says [Zpower_nat] is a morphism for + [plus : nat->nat] and [Zmult : Z->Z] *) + + Lemma Zpower_nat_is_exp : + forall (n m:nat) (z:Z), + Zpower_nat z (n + m) = Zpower_nat z n * Zpower_nat z m. + Proof. + intros; elim n; + [ simpl in |- *; elim (Zpower_nat z m); auto with zarith + | unfold Zpower_nat in |- *; intros; simpl in |- *; rewrite H; + apply Zmult_assoc ]. + Qed. + + (** [Zpower_pos z n] is the n-th power of [z] when [n] is an binary + integer (type [positive]) and [z] a signed integer (type [Z]) *) + + Definition Zpower_pos (z:Z) (n:positive) := iter_pos n Z (fun x:Z => z * x) 1. + + (** This theorem shows that powers of unary and binary integers + are the same thing, modulo the function convert : [positive -> nat] *) + + Theorem Zpower_pos_nat : + forall (z:Z) (p:positive), Zpower_pos z p = Zpower_nat z (nat_of_P p). + Proof. + intros; unfold Zpower_pos in |- *; unfold Zpower_nat in |- *; + apply iter_nat_of_P. + Qed. + + (** Using the theorem [Zpower_pos_nat] and the lemma [Zpower_nat_is_exp] we + deduce that the function [[n:positive](Zpower_pos z n)] is a morphism + for [add : positive->positive] and [Zmult : Z->Z] *) + + Theorem Zpower_pos_is_exp : + forall (n m:positive) (z:Z), + Zpower_pos z (n + m) = Zpower_pos z n * Zpower_pos z m. + Proof. + intros. + rewrite (Zpower_pos_nat z n). + rewrite (Zpower_pos_nat z m). + rewrite (Zpower_pos_nat z (n + m)). + rewrite (nat_of_P_plus_morphism n m). + apply Zpower_nat_is_exp. + Qed. + + Definition Zpower (x y:Z) := + match y with + | Zpos p => Zpower_pos x p + | Z0 => 1 + | Zneg p => 0 + end. + + Infix "^" := Zpower : Z_scope. + + Hint Immediate Zpower_nat_is_exp: zarith. + Hint Immediate Zpower_pos_is_exp: zarith. + Hint Unfold Zpower_pos: zarith. + Hint Unfold Zpower_nat: zarith. + + Lemma Zpower_exp : + forall x n m:Z, n >= 0 -> m >= 0 -> x ^ (n + m) = x ^ n * x ^ m. + Proof. + destruct n; destruct m; auto with zarith. + simpl in |- *; intros; apply Zred_factor0. + simpl in |- *; auto with zarith. + intros; compute in H0; absurd (Datatypes.Lt = Datatypes.Lt); auto with zarith. + intros; compute in H0; absurd (Datatypes.Lt = Datatypes.Lt); auto with zarith. + Qed. End section1. -(* Exporting notation "^" *) +(** Exporting notation "^" *) Infix "^" := Zpower : Z_scope. @@ -100,273 +103,283 @@ Hint Unfold Zpower_nat: zarith. Section Powers_of_2. -(** For the powers of two, that will be widely used, a more direct - calculus is possible. We will also prove some properties such - as [(x:positive) x < 2^x] that are true for all integers bigger - than 2 but more difficult to prove and useless. *) - -(** [shift n m] computes [2^n * m], or [m] shifted by [n] positions *) - -Definition shift_nat (n:nat) (z:positive) := iter_nat n positive xO z. -Definition shift_pos (n z:positive) := iter_pos n positive xO z. -Definition shift (n:Z) (z:positive) := - match n with - | Z0 => z - | Zpos p => iter_pos p positive xO z - | Zneg p => z - end. - -Definition two_power_nat (n:nat) := Zpos (shift_nat n 1). -Definition two_power_pos (x:positive) := Zpos (shift_pos x 1). - -Lemma two_power_nat_S : - forall n:nat, two_power_nat (S n) = 2 * two_power_nat n. -intro; simpl in |- *; apply refl_equal. -Qed. - -Lemma shift_nat_plus : - forall (n m:nat) (x:positive), - shift_nat (n + m) x = shift_nat n (shift_nat m x). - -intros; unfold shift_nat in |- *; apply iter_nat_plus. -Qed. - -Theorem shift_nat_correct : - forall (n:nat) (x:positive), Zpos (shift_nat n x) = Zpower_nat 2 n * Zpos x. - -unfold shift_nat in |- *; simple induction n; - [ simpl in |- *; trivial with zarith - | intros; replace (Zpower_nat 2 (S n0)) with (2 * Zpower_nat 2 n0); - [ rewrite <- Zmult_assoc; rewrite <- (H x); simpl in |- *; reflexivity - | auto with zarith ] ]. -Qed. - -Theorem two_power_nat_correct : - forall n:nat, two_power_nat n = Zpower_nat 2 n. - -intro n. -unfold two_power_nat in |- *. -rewrite (shift_nat_correct n). -omega. -Qed. + (** * Powers of 2 *) + + (** For the powers of two, that will be widely used, a more direct + calculus is possible. We will also prove some properties such + as [(x:positive) x < 2^x] that are true for all integers bigger + than 2 but more difficult to prove and useless. *) + + (** [shift n m] computes [2^n * m], or [m] shifted by [n] positions *) + + Definition shift_nat (n:nat) (z:positive) := iter_nat n positive xO z. + Definition shift_pos (n z:positive) := iter_pos n positive xO z. + Definition shift (n:Z) (z:positive) := + match n with + | Z0 => z + | Zpos p => iter_pos p positive xO z + | Zneg p => z + end. + + Definition two_power_nat (n:nat) := Zpos (shift_nat n 1). + Definition two_power_pos (x:positive) := Zpos (shift_pos x 1). + + Lemma two_power_nat_S : + forall n:nat, two_power_nat (S n) = 2 * two_power_nat n. + Proof. + intro; simpl in |- *; apply refl_equal. + Qed. + + Lemma shift_nat_plus : + forall (n m:nat) (x:positive), + shift_nat (n + m) x = shift_nat n (shift_nat m x). + Proof. + intros; unfold shift_nat in |- *; apply iter_nat_plus. + Qed. + + Theorem shift_nat_correct : + forall (n:nat) (x:positive), Zpos (shift_nat n x) = Zpower_nat 2 n * Zpos x. + Proof. + unfold shift_nat in |- *; simple induction n; + [ simpl in |- *; trivial with zarith + | intros; replace (Zpower_nat 2 (S n0)) with (2 * Zpower_nat 2 n0); + [ rewrite <- Zmult_assoc; rewrite <- (H x); simpl in |- *; reflexivity + | auto with zarith ] ]. + Qed. + + Theorem two_power_nat_correct : + forall n:nat, two_power_nat n = Zpower_nat 2 n. + Proof. + intro n. + unfold two_power_nat in |- *. + rewrite (shift_nat_correct n). + omega. + Qed. + + (** Second we show that [two_power_pos] and [two_power_nat] are the same *) + Lemma shift_pos_nat : + forall p x:positive, shift_pos p x = shift_nat (nat_of_P p) x. + Proof. + unfold shift_pos in |- *. + unfold shift_nat in |- *. + intros; apply iter_nat_of_P. + Qed. + + Lemma two_power_pos_nat : + forall p:positive, two_power_pos p = two_power_nat (nat_of_P p). + Proof. + intro; unfold two_power_pos in |- *; unfold two_power_nat in |- *. + apply f_equal with (f := Zpos). + apply shift_pos_nat. + Qed. + + (** Then we deduce that [two_power_pos] is also correct *) + + Theorem shift_pos_correct : + forall p x:positive, Zpos (shift_pos p x) = Zpower_pos 2 p * Zpos x. + Proof. + intros. + rewrite (shift_pos_nat p x). + rewrite (Zpower_pos_nat 2 p). + apply shift_nat_correct. + Qed. + + Theorem two_power_pos_correct : + forall x:positive, two_power_pos x = Zpower_pos 2 x. + Proof. + intro. + rewrite two_power_pos_nat. + rewrite Zpower_pos_nat. + apply two_power_nat_correct. + Qed. + + (** Some consequences *) + + Theorem two_power_pos_is_exp : + forall x y:positive, + two_power_pos (x + y) = two_power_pos x * two_power_pos y. + Proof. + intros. + rewrite (two_power_pos_correct (x + y)). + rewrite (two_power_pos_correct x). + rewrite (two_power_pos_correct y). + apply Zpower_pos_is_exp. + Qed. + + (** The exponentiation [z -> 2^z] for [z] a signed integer. + For convenience, we assume that [2^z = 0] for all [z < 0] + We could also define a inductive type [Log_result] with + 3 contructors [ Zero | Pos positive -> | minus_infty] + but it's more complexe and not so useful. *) -(** Second we show that [two_power_pos] and [two_power_nat] are the same *) -Lemma shift_pos_nat : - forall p x:positive, shift_pos p x = shift_nat (nat_of_P p) x. - -unfold shift_pos in |- *. -unfold shift_nat in |- *. -intros; apply iter_nat_of_P. -Qed. - -Lemma two_power_pos_nat : - forall p:positive, two_power_pos p = two_power_nat (nat_of_P p). - -intro; unfold two_power_pos in |- *; unfold two_power_nat in |- *. -apply f_equal with (f := Zpos). -apply shift_pos_nat. -Qed. - -(** Then we deduce that [two_power_pos] is also correct *) - -Theorem shift_pos_correct : - forall p x:positive, Zpos (shift_pos p x) = Zpower_pos 2 p * Zpos x. - -intros. -rewrite (shift_pos_nat p x). -rewrite (Zpower_pos_nat 2 p). -apply shift_nat_correct. -Qed. - -Theorem two_power_pos_correct : - forall x:positive, two_power_pos x = Zpower_pos 2 x. - -intro. -rewrite two_power_pos_nat. -rewrite Zpower_pos_nat. -apply two_power_nat_correct. -Qed. - -(** Some consequences *) - -Theorem two_power_pos_is_exp : - forall x y:positive, - two_power_pos (x + y) = two_power_pos x * two_power_pos y. -intros. -rewrite (two_power_pos_correct (x + y)). -rewrite (two_power_pos_correct x). -rewrite (two_power_pos_correct y). -apply Zpower_pos_is_exp. -Qed. - -(** The exponentiation [z -> 2^z] for [z] a signed integer. - For convenience, we assume that [2^z = 0] for all [z < 0] - We could also define a inductive type [Log_result] with - 3 contructors [ Zero | Pos positive -> | minus_infty] - but it's more complexe and not so useful. *) - -Definition two_p (x:Z) := - match x with - | Z0 => 1 - | Zpos y => two_power_pos y - | Zneg y => 0 - end. - -Theorem two_p_is_exp : - forall x y:Z, 0 <= x -> 0 <= y -> two_p (x + y) = two_p x * two_p y. -simple induction x; - [ simple induction y; simpl in |- *; auto with zarith - | simple induction y; - [ unfold two_p in |- *; rewrite (Zmult_comm (two_power_pos p) 1); - rewrite (Zmult_1_l (two_power_pos p)); auto with zarith - | unfold Zplus in |- *; unfold two_p in |- *; intros; - apply two_power_pos_is_exp - | intros; unfold Zle in H0; unfold Zcompare in H0; - absurd (Datatypes.Gt = Datatypes.Gt); trivial with zarith ] - | simple induction y; - [ simpl in |- *; auto with zarith - | intros; unfold Zle in H; unfold Zcompare in H; - absurd (Datatypes.Gt = Datatypes.Gt); trivial with zarith - | intros; unfold Zle in H; unfold Zcompare in H; - absurd (Datatypes.Gt = Datatypes.Gt); trivial with zarith ] ]. -Qed. - -Lemma two_p_gt_ZERO : forall x:Z, 0 <= x -> two_p x > 0. -simple induction x; intros; - [ simpl in |- *; omega - | simpl in |- *; unfold two_power_pos in |- *; apply Zorder.Zgt_pos_0 - | absurd (0 <= Zneg p); - [ simpl in |- *; unfold Zle in |- *; unfold Zcompare in |- *; - do 2 unfold not in |- *; auto with zarith - | assumption ] ]. -Qed. - -Lemma two_p_S : forall x:Z, 0 <= x -> two_p (Zsucc x) = 2 * two_p x. -intros; unfold Zsucc in |- *. -rewrite (two_p_is_exp x 1 H (Zorder.Zle_0_pos 1)). -apply Zmult_comm. -Qed. - -Lemma two_p_pred : forall x:Z, 0 <= x -> two_p (Zpred x) < two_p x. -intros; apply natlike_ind with (P := fun x:Z => two_p (Zpred x) < two_p x); - [ simpl in |- *; unfold Zlt in |- *; auto with zarith - | intros; elim (Zle_lt_or_eq 0 x0 H0); - [ intros; - replace (two_p (Zpred (Zsucc x0))) with (two_p (Zsucc (Zpred x0))); - [ rewrite (two_p_S (Zpred x0)); - [ rewrite (two_p_S x0); [ omega | assumption ] - | apply Zorder.Zlt_0_le_0_pred; assumption ] - | rewrite <- (Zsucc_pred x0); rewrite <- (Zpred_succ x0); - trivial with zarith ] - | intro Hx0; rewrite <- Hx0; simpl in |- *; unfold Zlt in |- *; - auto with zarith ] - | assumption ]. -Qed. - -Lemma Zlt_lt_double : forall x y:Z, 0 <= x < y -> x < 2 * y. -intros; omega. Qed. - -End Powers_of_2. + Definition two_p (x:Z) := + match x with + | Z0 => 1 + | Zpos y => two_power_pos y + | Zneg y => 0 + end. + + Theorem two_p_is_exp : + forall x y:Z, 0 <= x -> 0 <= y -> two_p (x + y) = two_p x * two_p y. + Proof. + simple induction x; + [ simple induction y; simpl in |- *; auto with zarith + | simple induction y; + [ unfold two_p in |- *; rewrite (Zmult_comm (two_power_pos p) 1); + rewrite (Zmult_1_l (two_power_pos p)); auto with zarith + | unfold Zplus in |- *; unfold two_p in |- *; intros; + apply two_power_pos_is_exp + | intros; unfold Zle in H0; unfold Zcompare in H0; + absurd (Datatypes.Gt = Datatypes.Gt); trivial with zarith ] + | simple induction y; + [ simpl in |- *; auto with zarith + | intros; unfold Zle in H; unfold Zcompare in H; + absurd (Datatypes.Gt = Datatypes.Gt); trivial with zarith + | intros; unfold Zle in H; unfold Zcompare in H; + absurd (Datatypes.Gt = Datatypes.Gt); trivial with zarith ] ]. + Qed. + + Lemma two_p_gt_ZERO : forall x:Z, 0 <= x -> two_p x > 0. + Proof. + simple induction x; intros; + [ simpl in |- *; omega + | simpl in |- *; unfold two_power_pos in |- *; apply Zorder.Zgt_pos_0 + | absurd (0 <= Zneg p); + [ simpl in |- *; unfold Zle in |- *; unfold Zcompare in |- *; + do 2 unfold not in |- *; auto with zarith + | assumption ] ]. + Qed. + + Lemma two_p_S : forall x:Z, 0 <= x -> two_p (Zsucc x) = 2 * two_p x. + Proof. + intros; unfold Zsucc in |- *. + rewrite (two_p_is_exp x 1 H (Zorder.Zle_0_pos 1)). + apply Zmult_comm. + Qed. + + Lemma two_p_pred : forall x:Z, 0 <= x -> two_p (Zpred x) < two_p x. + Proof. + intros; apply natlike_ind with (P := fun x:Z => two_p (Zpred x) < two_p x); + [ simpl in |- *; unfold Zlt in |- *; auto with zarith + | intros; elim (Zle_lt_or_eq 0 x0 H0); + [ intros; + replace (two_p (Zpred (Zsucc x0))) with (two_p (Zsucc (Zpred x0))); + [ rewrite (two_p_S (Zpred x0)); + [ rewrite (two_p_S x0); [ omega | assumption ] + | apply Zorder.Zlt_0_le_0_pred; assumption ] + | rewrite <- (Zsucc_pred x0); rewrite <- (Zpred_succ x0); + trivial with zarith ] + | intro Hx0; rewrite <- Hx0; simpl in |- *; unfold Zlt in |- *; + auto with zarith ] + | assumption ]. + Qed. + + Lemma Zlt_lt_double : forall x y:Z, 0 <= x < y -> x < 2 * y. + intros; omega. Qed. + + End Powers_of_2. Hint Resolve two_p_gt_ZERO: zarith. Hint Immediate two_p_pred two_p_S: zarith. Section power_div_with_rest. -(** Division by a power of two. - To [n:Z] and [p:positive], [q],[r] are associated such that - [n = 2^p.q + r] and [0 <= r < 2^p] *) - -(** Invariant: [d*q + r = d'*q + r /\ d' = 2*d /\ 0<= r < d /\ 0 <= r' < d'] *) -Definition Zdiv_rest_aux (qrd:Z * Z * Z) := - let (qr, d) := qrd in - let (q, r) := qr in - (match q with - | Z0 => (0, r) - | Zpos xH => (0, d + r) - | Zpos (xI n) => (Zpos n, d + r) - | Zpos (xO n) => (Zpos n, r) - | Zneg xH => (-1, d + r) - | Zneg (xI n) => (Zneg n - 1, d + r) - | Zneg (xO n) => (Zneg n, r) - end, 2 * d). - -Definition Zdiv_rest (x:Z) (p:positive) := - let (qr, d) := iter_pos p _ Zdiv_rest_aux (x, 0, 1) in qr. - -Lemma Zdiv_rest_correct1 : - forall (x:Z) (p:positive), - let (qr, d) := iter_pos p _ Zdiv_rest_aux (x, 0, 1) in d = two_power_pos p. - -intros x p; rewrite (iter_nat_of_P p _ Zdiv_rest_aux (x, 0, 1)); - rewrite (two_power_pos_nat p); elim (nat_of_P p); - simpl in |- *; - [ trivial with zarith - | intro n; rewrite (two_power_nat_S n); unfold Zdiv_rest_aux at 2 in |- *; - elim (iter_nat n (Z * Z * Z) Zdiv_rest_aux (x, 0, 1)); - destruct a; intros; apply f_equal with (f := fun z:Z => 2 * z); - assumption ]. -Qed. - -Lemma Zdiv_rest_correct2 : - forall (x:Z) (p:positive), - let (qr, d) := iter_pos p _ Zdiv_rest_aux (x, 0, 1) in - let (q, r) := qr in x = q * d + r /\ 0 <= r < d. - -intros; - apply iter_pos_invariant with - (f := Zdiv_rest_aux) - (Inv := fun qrd:Z * Z * Z => - let (qr, d) := qrd in + (** * Division by a power of two. *) + + (** To [n:Z] and [p:positive], [q],[r] are associated such that + [n = 2^p.q + r] and [0 <= r < 2^p] *) + + (** Invariant: [d*q + r = d'*q + r /\ d' = 2*d /\ 0<= r < d /\ 0 <= r' < d'] *) + Definition Zdiv_rest_aux (qrd:Z * Z * Z) := + let (qr, d) := qrd in + let (q, r) := qr in + (match q with + | Z0 => (0, r) + | Zpos xH => (0, d + r) + | Zpos (xI n) => (Zpos n, d + r) + | Zpos (xO n) => (Zpos n, r) + | Zneg xH => (-1, d + r) + | Zneg (xI n) => (Zneg n - 1, d + r) + | Zneg (xO n) => (Zneg n, r) + end, 2 * d). + + Definition Zdiv_rest (x:Z) (p:positive) := + let (qr, d) := iter_pos p _ Zdiv_rest_aux (x, 0, 1) in qr. + + Lemma Zdiv_rest_correct1 : + forall (x:Z) (p:positive), + let (qr, d) := iter_pos p _ Zdiv_rest_aux (x, 0, 1) in d = two_power_pos p. + Proof. + intros x p; rewrite (iter_nat_of_P p _ Zdiv_rest_aux (x, 0, 1)); + rewrite (two_power_pos_nat p); elim (nat_of_P p); + simpl in |- *; + [ trivial with zarith + | intro n; rewrite (two_power_nat_S n); unfold Zdiv_rest_aux at 2 in |- *; + elim (iter_nat n (Z * Z * Z) Zdiv_rest_aux (x, 0, 1)); + destruct a; intros; apply f_equal with (f := fun z:Z => 2 * z); + assumption ]. + Qed. + + Lemma Zdiv_rest_correct2 : + forall (x:Z) (p:positive), + let (qr, d) := iter_pos p _ Zdiv_rest_aux (x, 0, 1) in + let (q, r) := qr in x = q * d + r /\ 0 <= r < d. + Proof. + intros; + apply iter_pos_invariant with + (f := Zdiv_rest_aux) + (Inv := fun qrd:Z * Z * Z => + let (qr, d) := qrd in let (q, r) := qr in x = q * d + r /\ 0 <= r < d); - [ intro x0; elim x0; intro y0; elim y0; intros q r d; - unfold Zdiv_rest_aux in |- *; elim q; - [ omega - | destruct p0; - [ rewrite BinInt.Zpos_xI; intro; elim H; intros; split; - [ rewrite H0; rewrite Zplus_assoc; rewrite Zmult_plus_distr_l; - rewrite Zmult_1_l; rewrite Zmult_assoc; - rewrite (Zmult_comm (Zpos p0) 2); apply refl_equal - | omega ] - | rewrite BinInt.Zpos_xO; intro; elim H; intros; split; - [ rewrite H0; rewrite Zmult_assoc; rewrite (Zmult_comm (Zpos p0) 2); - apply refl_equal - | omega ] - | omega ] - | destruct p0; - [ rewrite BinInt.Zneg_xI; unfold Zminus in |- *; intro; elim H; intros; - split; - [ rewrite H0; rewrite Zplus_assoc; - apply f_equal with (f := fun z:Z => z + r); - do 2 rewrite Zmult_plus_distr_l; rewrite Zmult_assoc; - rewrite (Zmult_comm (Zneg p0) 2); rewrite <- Zplus_assoc; - apply f_equal with (f := fun z:Z => 2 * Zneg p0 * d + z); - omega - | omega ] - | rewrite BinInt.Zneg_xO; unfold Zminus in |- *; intro; elim H; intros; - split; - [ rewrite H0; rewrite Zmult_assoc; rewrite (Zmult_comm (Zneg p0) 2); - apply refl_equal - | omega ] - | omega ] ] - | omega ]. -Qed. - -Inductive Zdiv_rest_proofs (x:Z) (p:positive) : Set := + [ intro x0; elim x0; intro y0; elim y0; intros q r d; + unfold Zdiv_rest_aux in |- *; elim q; + [ omega + | destruct p0; + [ rewrite BinInt.Zpos_xI; intro; elim H; intros; split; + [ rewrite H0; rewrite Zplus_assoc; rewrite Zmult_plus_distr_l; + rewrite Zmult_1_l; rewrite Zmult_assoc; + rewrite (Zmult_comm (Zpos p0) 2); apply refl_equal + | omega ] + | rewrite BinInt.Zpos_xO; intro; elim H; intros; split; + [ rewrite H0; rewrite Zmult_assoc; rewrite (Zmult_comm (Zpos p0) 2); + apply refl_equal + | omega ] + | omega ] + | destruct p0; + [ rewrite BinInt.Zneg_xI; unfold Zminus in |- *; intro; elim H; intros; + split; + [ rewrite H0; rewrite Zplus_assoc; + apply f_equal with (f := fun z:Z => z + r); + do 2 rewrite Zmult_plus_distr_l; rewrite Zmult_assoc; + rewrite (Zmult_comm (Zneg p0) 2); rewrite <- Zplus_assoc; + apply f_equal with (f := fun z:Z => 2 * Zneg p0 * d + z); + omega + | omega ] + | rewrite BinInt.Zneg_xO; unfold Zminus in |- *; intro; elim H; intros; + split; + [ rewrite H0; rewrite Zmult_assoc; rewrite (Zmult_comm (Zneg p0) 2); + apply refl_equal + | omega ] + | omega ] ] + | omega ]. + Qed. + + Inductive Zdiv_rest_proofs (x:Z) (p:positive) : Set := Zdiv_rest_proof : - forall q r:Z, - x = q * two_power_pos p + r -> - 0 <= r -> r < two_power_pos p -> Zdiv_rest_proofs x p. - -Lemma Zdiv_rest_correct : forall (x:Z) (p:positive), Zdiv_rest_proofs x p. -intros x p. -generalize (Zdiv_rest_correct1 x p); generalize (Zdiv_rest_correct2 x p). -elim (iter_pos p (Z * Z * Z) Zdiv_rest_aux (x, 0, 1)). -simple induction a. -intros. -elim H; intros H1 H2; clear H. -rewrite H0 in H1; rewrite H0 in H2; elim H2; intros; - apply Zdiv_rest_proof with (q := a0) (r := b); assumption. -Qed. + forall q r:Z, + x = q * two_power_pos p + r -> + 0 <= r -> r < two_power_pos p -> Zdiv_rest_proofs x p. + + Lemma Zdiv_rest_correct : forall (x:Z) (p:positive), Zdiv_rest_proofs x p. + Proof. + intros x p. + generalize (Zdiv_rest_correct1 x p); generalize (Zdiv_rest_correct2 x p). + elim (iter_pos p (Z * Z * Z) Zdiv_rest_aux (x, 0, 1)). + simple induction a. + intros. + elim H; intros H1 H2; clear H. + rewrite H0 in H1; rewrite H0 in H2; elim H2; intros; + apply Zdiv_rest_proof with (q := a0) (r := b); assumption. + Qed. End power_div_with_rest. \ No newline at end of file diff --git a/theories/ZArith/Zsqrt.v b/theories/ZArith/Zsqrt.v index cf4acb5f..9893bed3 100644 --- a/theories/ZArith/Zsqrt.v +++ b/theories/ZArith/Zsqrt.v @@ -6,11 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zsqrt.v 6199 2004-10-11 11:39:18Z herbelin $ *) +(* $Id: Zsqrt.v 9245 2006-10-17 12:53:34Z notin $ *) +Require Import ZArithRing. Require Import Omega. Require Export ZArith_base. -Require Export ZArithRing. Open Local Scope Z_scope. (**********************************************************************) @@ -20,73 +20,73 @@ Open Local Scope Z_scope. `2*(POS ...)+1`, but only when ... is not made only with xO, XI, or xH. *) Ltac compute_POS := match goal with - | |- context [(Zpos (xI ?X1))] => + | |- context [(Zpos (xI ?X1))] => match constr:X1 with - | context [1%positive] => fail 1 - | _ => rewrite (BinInt.Zpos_xI X1) + | context [1%positive] => fail 1 + | _ => rewrite (BinInt.Zpos_xI X1) end - | |- context [(Zpos (xO ?X1))] => + | |- context [(Zpos (xO ?X1))] => match constr:X1 with - | context [1%positive] => fail 1 - | _ => rewrite (BinInt.Zpos_xO X1) + | context [1%positive] => fail 1 + | _ => rewrite (BinInt.Zpos_xO X1) end end. Inductive sqrt_data (n:Z) : Set := - c_sqrt : forall s r:Z, n = s * s + r -> 0 <= r <= 2 * s -> sqrt_data n. + c_sqrt : forall s r:Z, n = s * s + r -> 0 <= r <= 2 * s -> sqrt_data n. Definition sqrtrempos : forall p:positive, sqrt_data (Zpos p). -refine - (fix sqrtrempos (p:positive) : sqrt_data (Zpos p) := - match p return sqrt_data (Zpos p) with - | xH => c_sqrt 1 1 0 _ _ - | xO xH => c_sqrt 2 1 1 _ _ - | xI xH => c_sqrt 3 1 2 _ _ - | xO (xO p') => - match sqrtrempos p' with - | c_sqrt s' r' Heq Hint => - match Z_le_gt_dec (4 * s' + 1) (4 * r') with - | left Hle => - c_sqrt (Zpos (xO (xO p'))) (2 * s' + 1) + refine + (fix sqrtrempos (p:positive) : sqrt_data (Zpos p) := + match p return sqrt_data (Zpos p) with + | xH => c_sqrt 1 1 0 _ _ + | xO xH => c_sqrt 2 1 1 _ _ + | xI xH => c_sqrt 3 1 2 _ _ + | xO (xO p') => + match sqrtrempos p' with + | c_sqrt s' r' Heq Hint => + match Z_le_gt_dec (4 * s' + 1) (4 * r') with + | left Hle => + c_sqrt (Zpos (xO (xO p'))) (2 * s' + 1) (4 * r' - (4 * s' + 1)) _ _ - | right Hgt => c_sqrt (Zpos (xO (xO p'))) (2 * s') (4 * r') _ _ - end - end - | xO (xI p') => - match sqrtrempos p' with - | c_sqrt s' r' Heq Hint => - match Z_le_gt_dec (4 * s' + 1) (4 * r' + 2) with - | left Hle => - c_sqrt (Zpos (xO (xI p'))) (2 * s' + 1) + | right Hgt => c_sqrt (Zpos (xO (xO p'))) (2 * s') (4 * r') _ _ + end + end + | xO (xI p') => + match sqrtrempos p' with + | c_sqrt s' r' Heq Hint => + match Z_le_gt_dec (4 * s' + 1) (4 * r' + 2) with + | left Hle => + c_sqrt (Zpos (xO (xI p'))) (2 * s' + 1) (4 * r' + 2 - (4 * s' + 1)) _ _ - | right Hgt => - c_sqrt (Zpos (xO (xI p'))) (2 * s') (4 * r' + 2) _ _ - end - end - | xI (xO p') => - match sqrtrempos p' with - | c_sqrt s' r' Heq Hint => - match Z_le_gt_dec (4 * s' + 1) (4 * r' + 1) with - | left Hle => - c_sqrt (Zpos (xI (xO p'))) (2 * s' + 1) + | right Hgt => + c_sqrt (Zpos (xO (xI p'))) (2 * s') (4 * r' + 2) _ _ + end + end + | xI (xO p') => + match sqrtrempos p' with + | c_sqrt s' r' Heq Hint => + match Z_le_gt_dec (4 * s' + 1) (4 * r' + 1) with + | left Hle => + c_sqrt (Zpos (xI (xO p'))) (2 * s' + 1) (4 * r' + 1 - (4 * s' + 1)) _ _ - | right Hgt => - c_sqrt (Zpos (xI (xO p'))) (2 * s') (4 * r' + 1) _ _ - end - end - | xI (xI p') => - match sqrtrempos p' with - | c_sqrt s' r' Heq Hint => - match Z_le_gt_dec (4 * s' + 1) (4 * r' + 3) with - | left Hle => - c_sqrt (Zpos (xI (xI p'))) (2 * s' + 1) + | right Hgt => + c_sqrt (Zpos (xI (xO p'))) (2 * s') (4 * r' + 1) _ _ + end + end + | xI (xI p') => + match sqrtrempos p' with + | c_sqrt s' r' Heq Hint => + match Z_le_gt_dec (4 * s' + 1) (4 * r' + 3) with + | left Hle => + c_sqrt (Zpos (xI (xI p'))) (2 * s' + 1) (4 * r' + 3 - (4 * s' + 1)) _ _ | right Hgt => c_sqrt (Zpos (xI (xI p'))) (2 * s') (4 * r' + 3) _ _ end end end); clear sqrtrempos; repeat compute_POS; - try (try rewrite Heq; ring; fail); try omega. + try (try rewrite Heq; ring); try omega. Defined. (** Define with integer input, but with a strong (readable) specification. *) @@ -94,70 +94,71 @@ Definition Zsqrt : forall x:Z, 0 <= x -> {s : Z & {r : Z | x = s * s + r /\ s * s <= x < (s + 1) * (s + 1)}}. -refine - (fun x => - match - x - return + refine + (fun x => + match + x + return 0 <= x -> {s : Z & {r : Z | x = s * s + r /\ s * s <= x < (s + 1) * (s + 1)}} - with - | Zpos p => - fun h => - match sqrtrempos p with - | c_sqrt s r Heq Hint => - existS + with + | Zpos p => + fun h => + match sqrtrempos p with + | c_sqrt s r Heq Hint => + existS (fun s:Z => - {r : Z | - Zpos p = s * s + r /\ s * s <= Zpos p < (s + 1) * (s + 1)}) + {r : Z | + Zpos p = s * s + r /\ s * s <= Zpos p < (s + 1) * (s + 1)}) s (exist - (fun r:Z => - Zpos p = s * s + r /\ - s * s <= Zpos p < (s + 1) * (s + 1)) r _) - end - | Zneg p => - fun h => - False_rec + (fun r:Z => + Zpos p = s * s + r /\ + s * s <= Zpos p < (s + 1) * (s + 1)) r _) + end + | Zneg p => + fun h => + False_rec {s : Z & - {r : Z | - Zneg p = s * s + r /\ s * s <= Zneg p < (s + 1) * (s + 1)}} + {r : Z | + Zneg p = s * s + r /\ s * s <= Zneg p < (s + 1) * (s + 1)}} (h (refl_equal Datatypes.Gt)) - | Z0 => - fun h => - existS + | Z0 => + fun h => + existS (fun s:Z => - {r : Z | 0 = s * s + r /\ s * s <= 0 < (s + 1) * (s + 1)}) 0 + {r : Z | 0 = s * s + r /\ s * s <= 0 < (s + 1) * (s + 1)}) 0 (exist (fun r:Z => 0 = 0 * 0 + r /\ 0 * 0 <= 0 < (0 + 1) * (0 + 1)) 0 _) end); try omega. -split; [ omega | rewrite Heq; ring ((s + 1) * (s + 1)); omega ]. +split; [ omega | rewrite Heq; ring_simplify ((s + 1) * (s + 1)); omega ]. Defined. (** Define a function of type Z->Z that computes the integer square root, but only for positive numbers, and 0 for others. *) Definition Zsqrt_plain (x:Z) : Z := match x with - | Zpos p => + | Zpos p => match Zsqrt (Zpos p) (Zorder.Zle_0_pos p) with - | existS s _ => s + | existS s _ => s end - | Zneg p => 0 - | Z0 => 0 + | Zneg p => 0 + | Z0 => 0 end. (** A basic theorem about Zsqrt_plain *) Theorem Zsqrt_interval : - forall n:Z, - 0 <= n -> - Zsqrt_plain n * Zsqrt_plain n <= n < - (Zsqrt_plain n + 1) * (Zsqrt_plain n + 1). -intros x; case x. -unfold Zsqrt_plain in |- *; omega. -intros p; unfold Zsqrt_plain in |- *; - case (Zsqrt (Zpos p) (Zorder.Zle_0_pos p)). -intros s [r [Heq Hint]] Hle; assumption. -intros p Hle; elim Hle; auto. + forall n:Z, + 0 <= n -> + Zsqrt_plain n * Zsqrt_plain n <= n < + (Zsqrt_plain n + 1) * (Zsqrt_plain n + 1). +Proof. + intros x; case x. + unfold Zsqrt_plain in |- *; omega. + intros p; unfold Zsqrt_plain in |- *; + case (Zsqrt (Zpos p) (Zorder.Zle_0_pos p)). + intros s [r [Heq Hint]] Hle; assumption. + intros p Hle; elim Hle; auto. Qed. diff --git a/theories/ZArith/Zwf.v b/theories/ZArith/Zwf.v index 4ff663fb..bd617204 100644 --- a/theories/ZArith/Zwf.v +++ b/theories/ZArith/Zwf.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zwf.v 5920 2004-07-16 20:01:26Z herbelin $ *) +(* $Id: Zwf.v 9245 2006-10-17 12:53:34Z notin $ *) Require Import ZArith_base. Require Export Wf_nat. @@ -26,35 +26,35 @@ Definition Zwf (c x y:Z) := c <= y /\ x < y. Section wf_proof. -Variable c : Z. - -(** The proof of well-foundness is classic: we do the proof by induction - on a measure in nat, which is here [|x-c|] *) - -Let f (z:Z) := Zabs_nat (z - c). - -Lemma Zwf_well_founded : well_founded (Zwf c). -red in |- *; intros. -assert (forall (n:nat) (a:Z), (f a < n)%nat \/ a < c -> Acc (Zwf c) a). -clear a; simple induction n; intros. -(** n= 0 *) -case H; intros. -case (lt_n_O (f a)); auto. -apply Acc_intro; unfold Zwf in |- *; intros. -assert False; omega || contradiction. -(** inductive case *) -case H0; clear H0; intro; auto. -apply Acc_intro; intros. -apply H. -unfold Zwf in H1. -case (Zle_or_lt c y); intro; auto with zarith. -left. -red in H0. -apply lt_le_trans with (f a); auto with arith. -unfold f in |- *. -apply Zabs.Zabs_nat_lt; omega. -apply (H (S (f a))); auto. -Qed. + Variable c : Z. + + (** The proof of well-foundness is classic: we do the proof by induction + on a measure in nat, which is here [|x-c|] *) + + Let f (z:Z) := Zabs_nat (z - c). + + Lemma Zwf_well_founded : well_founded (Zwf c). + red in |- *; intros. + assert (forall (n:nat) (a:Z), (f a < n)%nat \/ a < c -> Acc (Zwf c) a). + clear a; simple induction n; intros. + (** n= 0 *) + case H; intros. + case (lt_n_O (f a)); auto. + apply Acc_intro; unfold Zwf in |- *; intros. + assert False; omega || contradiction. + (** inductive case *) + case H0; clear H0; intro; auto. + apply Acc_intro; intros. + apply H. + unfold Zwf in H1. + case (Zle_or_lt c y); intro; auto with zarith. + left. + red in H0. + apply lt_le_trans with (f a); auto with arith. + unfold f in |- *. + apply Zabs.Zabs_nat_lt; omega. + apply (H (S (f a))); auto. + Qed. End wf_proof. @@ -72,25 +72,25 @@ Definition Zwf_up (c x y:Z) := y < x <= c. Section wf_proof_up. -Variable c : Z. + Variable c : Z. -(** The proof of well-foundness is classic: we do the proof by induction - on a measure in nat, which is here [|c-x|] *) + (** The proof of well-foundness is classic: we do the proof by induction + on a measure in nat, which is here [|c-x|] *) -Let f (z:Z) := Zabs_nat (c - z). + Let f (z:Z) := Zabs_nat (c - z). -Lemma Zwf_up_well_founded : well_founded (Zwf_up c). -Proof. -apply well_founded_lt_compat with (f := f). -unfold Zwf_up, f in |- *. -intros. -apply Zabs.Zabs_nat_lt. -unfold Zminus in |- *. split. -apply Zle_left; intuition. -apply Zplus_lt_compat_l; unfold Zlt in |- *; rewrite <- Zcompare_opp; - intuition. -Qed. + Lemma Zwf_up_well_founded : well_founded (Zwf_up c). + Proof. + apply well_founded_lt_compat with (f := f). + unfold Zwf_up, f in |- *. + intros. + apply Zabs.Zabs_nat_lt. + unfold Zminus in |- *. split. + apply Zle_left; intuition. + apply Zplus_lt_compat_l; unfold Zlt in |- *; rewrite <- Zcompare_opp; + intuition. + Qed. End wf_proof_up. -Hint Resolve Zwf_up_well_founded: datatypes v62. \ No newline at end of file +Hint Resolve Zwf_up_well_founded: datatypes v62. diff --git a/theories/ZArith/auxiliary.v b/theories/ZArith/auxiliary.v index 28cbd1e4..726fb45a 100644 --- a/theories/ZArith/auxiliary.v +++ b/theories/ZArith/auxiliary.v @@ -6,11 +6,11 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: auxiliary.v 5920 2004-07-16 20:01:26Z herbelin $ i*) +(*i $Id: auxiliary.v 9302 2006-10-27 21:21:17Z barras $ i*) (** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) -Require Export Arith. +Require Export Arith_base. Require Import BinInt. Require Import Zorder. Require Import Decidable. @@ -19,132 +19,134 @@ Require Export Compare_dec. Open Local Scope Z_scope. -(**********************************************************************) -(** Moving terms from one side to the other of an inequality *) +(***************************************************************) +(** * Moving terms from one side to the other of an inequality *) Theorem Zne_left : forall n m:Z, Zne n m -> Zne (n + - m) 0. Proof. -intros x y; unfold Zne in |- *; unfold not in |- *; intros H1 H2; apply H1; - apply Zplus_reg_l with (- y); rewrite Zplus_opp_l; - rewrite Zplus_comm; trivial with arith. + intros x y; unfold Zne in |- *; unfold not in |- *; intros H1 H2; apply H1; + apply Zplus_reg_l with (- y); rewrite Zplus_opp_l; + rewrite Zplus_comm; trivial with arith. Qed. Theorem Zegal_left : forall n m:Z, n = m -> n + - m = 0. Proof. -intros x y H; apply (Zplus_reg_l y); rewrite Zplus_permute; - rewrite Zplus_opp_r; do 2 rewrite Zplus_0_r; assumption. + intros x y H; apply (Zplus_reg_l y); rewrite Zplus_permute; + rewrite Zplus_opp_r; do 2 rewrite Zplus_0_r; assumption. Qed. Theorem Zle_left : forall n m:Z, n <= m -> 0 <= m + - n. Proof. -intros x y H; replace 0 with (x + - x). -apply Zplus_le_compat_r; trivial. -apply Zplus_opp_r. + intros x y H; replace 0 with (x + - x). + apply Zplus_le_compat_r; trivial. + apply Zplus_opp_r. Qed. Theorem Zle_left_rev : forall n m:Z, 0 <= m + - n -> n <= m. Proof. -intros x y H; apply Zplus_le_reg_r with (- x). -rewrite Zplus_opp_r; trivial. + intros x y H; apply Zplus_le_reg_r with (- x). + rewrite Zplus_opp_r; trivial. Qed. Theorem Zlt_left_rev : forall n m:Z, 0 < m + - n -> n < m. Proof. -intros x y H; apply Zplus_lt_reg_r with (- x). -rewrite Zplus_opp_r; trivial. + intros x y H; apply Zplus_lt_reg_r with (- x). + rewrite Zplus_opp_r; trivial. Qed. Theorem Zlt_left : forall n m:Z, n < m -> 0 <= m + -1 + - n. Proof. -intros x y H; apply Zle_left; apply Zsucc_le_reg; - change (Zsucc x <= Zsucc (Zpred y)) in |- *; rewrite <- Zsucc_pred; - apply Zlt_le_succ; assumption. + intros x y H; apply Zle_left; apply Zsucc_le_reg; + change (Zsucc x <= Zsucc (Zpred y)) in |- *; rewrite <- Zsucc_pred; + apply Zlt_le_succ; assumption. Qed. Theorem Zlt_left_lt : forall n m:Z, n < m -> 0 < m + - n. Proof. -intros x y H; replace 0 with (x + - x). -apply Zplus_lt_compat_r; trivial. -apply Zplus_opp_r. + intros x y H; replace 0 with (x + - x). + apply Zplus_lt_compat_r; trivial. + apply Zplus_opp_r. Qed. Theorem Zge_left : forall n m:Z, n >= m -> 0 <= n + - m. Proof. -intros x y H; apply Zle_left; apply Zge_le; assumption. + intros x y H; apply Zle_left; apply Zge_le; assumption. Qed. Theorem Zgt_left : forall n m:Z, n > m -> 0 <= n + -1 + - m. Proof. -intros x y H; apply Zlt_left; apply Zgt_lt; assumption. + intros x y H; apply Zlt_left; apply Zgt_lt; assumption. Qed. Theorem Zgt_left_gt : forall n m:Z, n > m -> n + - m > 0. Proof. -intros x y H; replace 0 with (y + - y). -apply Zplus_gt_compat_r; trivial. -apply Zplus_opp_r. + intros x y H; replace 0 with (y + - y). + apply Zplus_gt_compat_r; trivial. + apply Zplus_opp_r. Qed. Theorem Zgt_left_rev : forall n m:Z, n + - m > 0 -> n > m. Proof. -intros x y H; apply Zplus_gt_reg_r with (- y). -rewrite Zplus_opp_r; trivial. + intros x y H; apply Zplus_gt_reg_r with (- y). + rewrite Zplus_opp_r; trivial. Qed. (**********************************************************************) -(** Factorization lemmas *) +(** * Factorization lemmas *) Theorem Zred_factor0 : forall n:Z, n = n * 1. -intro x; rewrite (Zmult_1_r x); reflexivity. + intro x; rewrite (Zmult_1_r x); reflexivity. Qed. Theorem Zred_factor1 : forall n:Z, n + n = n * 2. Proof. -exact Zplus_diag_eq_mult_2. + exact Zplus_diag_eq_mult_2. Qed. Theorem Zred_factor2 : forall n m:Z, n + n * m = n * (1 + m). - -intros x y; pattern x at 1 in |- *; rewrite <- (Zmult_1_r x); - rewrite <- Zmult_plus_distr_r; trivial with arith. +Proof. + intros x y; pattern x at 1 in |- *; rewrite <- (Zmult_1_r x); + rewrite <- Zmult_plus_distr_r; trivial with arith. Qed. Theorem Zred_factor3 : forall n m:Z, n * m + n = n * (1 + m). - -intros x y; pattern x at 2 in |- *; rewrite <- (Zmult_1_r x); - rewrite <- Zmult_plus_distr_r; rewrite Zplus_comm; - trivial with arith. +Proof. + intros x y; pattern x at 2 in |- *; rewrite <- (Zmult_1_r x); + rewrite <- Zmult_plus_distr_r; rewrite Zplus_comm; + trivial with arith. Qed. + Theorem Zred_factor4 : forall n m p:Z, n * m + n * p = n * (m + p). -intros x y z; symmetry in |- *; apply Zmult_plus_distr_r. +Proof. + intros x y z; symmetry in |- *; apply Zmult_plus_distr_r. Qed. Theorem Zred_factor5 : forall n m:Z, n * 0 + m = m. - -intros x y; rewrite <- Zmult_0_r_reverse; auto with arith. +Proof. + intros x y; rewrite <- Zmult_0_r_reverse; auto with arith. Qed. Theorem Zred_factor6 : forall n:Z, n = n + 0. - -intro; rewrite Zplus_0_r; trivial with arith. +Proof. + intro; rewrite Zplus_0_r; trivial with arith. Qed. Theorem Zle_mult_approx : - forall n m p:Z, n > 0 -> p > 0 -> 0 <= m -> 0 <= m * n + p. - -intros x y z H1 H2 H3; apply Zle_trans with (m := y * x); - [ apply Zmult_gt_0_le_0_compat; assumption - | pattern (y * x) at 1 in |- *; rewrite <- Zplus_0_r; - apply Zplus_le_compat_l; apply Zlt_le_weak; apply Zgt_lt; - assumption ]. + forall n m p:Z, n > 0 -> p > 0 -> 0 <= m -> 0 <= m * n + p. +Proof. + intros x y z H1 H2 H3; apply Zle_trans with (m := y * x); + [ apply Zmult_gt_0_le_0_compat; assumption + | pattern (y * x) at 1 in |- *; rewrite <- Zplus_0_r; + apply Zplus_le_compat_l; apply Zlt_le_weak; apply Zgt_lt; + assumption ]. Qed. Theorem Zmult_le_approx : - forall n m p:Z, n > 0 -> n > p -> 0 <= m * n + p -> 0 <= m. - -intros x y z H1 H2 H3; apply Zlt_succ_le; apply Zmult_gt_0_lt_0_reg_r with x; - [ assumption - | apply Zle_lt_trans with (1 := H3); rewrite <- Zmult_succ_l_reverse; - apply Zplus_lt_compat_l; apply Zgt_lt; assumption ]. - + forall n m p:Z, n > 0 -> n > p -> 0 <= m * n + p -> 0 <= m. +Proof. + intros x y z H1 H2 H3; apply Zlt_succ_le; apply Zmult_gt_0_lt_0_reg_r with x; + [ assumption + | apply Zle_lt_trans with (1 := H3); rewrite <- Zmult_succ_l_reverse; + apply Zplus_lt_compat_l; apply Zgt_lt; assumption ]. Qed. + -- cgit v1.2.3