diff options
Diffstat (limited to 'theories/ZArith')
37 files changed, 5812 insertions, 7410 deletions
diff --git a/theories/ZArith/BinInt.v b/theories/ZArith/BinInt.v index e2b89d84..eeec9042 100644 --- a/theories/ZArith/BinInt.v +++ b/theories/ZArith/BinInt.v @@ -1,1158 +1,1759 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: BinInt.v 14641 2011-11-06 11:59:10Z herbelin $ i*) +Require Export BinNums BinPos Pnat. +Require Import BinNat Bool Plus Mult Equalities GenericMinMax + OrdersFacts ZAxioms ZProperties. +Require BinIntDef. (***********************************************************) -(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) +(** * Binary Integers *) (***********************************************************) -Require Export BinPos. -Require Export Pnat. -Require Import BinNat. -Require Import Plus. -Require Import Mult. - -Unset Boxed Definitions. - -(*****************************) -(** * Binary integer numbers *) - -Inductive Z : Set := - | Z0 : Z - | Zpos : positive -> Z - | Zneg : positive -> 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 *) - -Definition Zdouble_plus_one (x:Z) := - match x with - | Z0 => Zpos 1 - | Zpos p => Zpos p~1 - | Zneg p => Zneg (Pdouble_minus_one p) - end. - -Definition Zdouble_minus_one (x:Z) := - match x with - | Z0 => Zneg 1 - | Zneg p => Zneg p~1 - | Zpos p => Zpos (Pdouble_minus_one p) - end. - -Definition Zdouble (x:Z) := - match x with - | Z0 => Z0 - | Zpos p => Zpos p~0 - | Zneg p => Zneg p~0 - end. - -Open Local Scope positive_scope. - -Fixpoint ZPminus (x y:positive) {struct y} : Z := - match x, y with - | p~1, q~1 => Zdouble (ZPminus p q) - | p~1, q~0 => Zdouble_plus_one (ZPminus p q) - | p~1, 1 => Zpos p~0 - | p~0, q~1 => Zdouble_minus_one (ZPminus p q) - | p~0, q~0 => Zdouble (ZPminus p q) - | p~0, 1 => Zpos (Pdouble_minus_one p) - | 1, q~1 => Zneg q~0 - | 1, q~0 => Zneg (Pdouble_minus_one q) - | 1, 1 => Z0 - end. - -Close Local Scope positive_scope. - -(** ** Addition on integers *) - -Definition Zplus (x y:Z) := - match x, y with - | Z0, y => y - | Zpos x', Z0 => Zpos x' - | Zneg x', Z0 => Zneg 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') - end - | Zneg x', Zpos y' => - match (x' ?= y')%positive Eq with - | Eq => Z0 - | Lt => Zpos (y' - x') - | Gt => Zneg (x' - y') - end - | Zneg x', Zneg y' => Zneg (x' + y') - end. - -Infix "+" := Zplus : Z_scope. - -(** ** Opposite *) - -Definition Zopp (x:Z) := - match x with - | Z0 => Z0 - | Zpos x => Zneg x - | Zneg x => Zpos x - end. - -Notation "- x" := (Zopp x) : Z_scope. - -(** ** Successor on integers *) - -Definition Zsucc (x:Z) := (x + Zpos 1)%Z. - -(** ** Predecessor on integers *) - -Definition Zpred (x:Z) := (x + Zneg 1)%Z. - -(** ** Subtraction on integers *) - -Definition Zminus (m n:Z) := (m + - n)%Z. - -Infix "-" := Zminus : Z_scope. - -(** ** 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') - end. - -Infix "*" := Zmult : Z_scope. - -(** ** 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) - end. - -Infix "?=" := Zcompare (at level 70, no associativity) : Z_scope. +(** Initial author: Pierre Crégut, CNET, Lannion, France *) -Ltac elim_compare com1 com2 := - case (Dcompare (com1 ?= com2)%Z); - [ idtac | let x := fresh "H" in - (intro x; case x; clear x) ]. +(** The type [Z] and its constructors [Z0] and [Zpos] and [Zneg] + are now defined in [BinNums.v] *) -(** ** Sign function *) +Local Open Scope Z_scope. -Definition Zsgn (z:Z) : Z := - match z with - | Z0 => Z0 - | Zpos p => Zpos 1 - | Zneg p => Zneg 1 - end. +(** Every definitions and early properties about binary integers + are placed in a module [Z] for qualification purpose. *) -(** ** Direct, easier to handle variants of successor and addition *) +Module Z + <: ZAxiomsSig + <: UsualOrderedTypeFull + <: UsualDecidableTypeFull + <: TotalOrder. -Definition Zsucc' (x:Z) := - match x with - | Z0 => Zpos 1 - | Zpos x' => Zpos (Psucc x') - | Zneg x' => ZPminus 1 x' - end. +(** * Definitions of operations, now in a separate file *) -Definition Zpred' (x:Z) := - match x with - | Z0 => Zneg 1 - | Zpos x' => ZPminus x' 1 - | Zneg x' => Zneg (Psucc x') - end. +Include BinIntDef.Z. -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') - end. +(** When including property functors, only inline t eq zero one two *) -Open Local Scope Z_scope. +Set Inline Level 30. -(**********************************************************************) -(** ** Inductive specification of Z *) +(** * Logic Predicates *) -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. -Proof. - 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. - intro n; exact (Hs (Zpos n)). - apply Pind with (P := fun p => P (Zneg p)). - change (P (Zpred' Z0)) in |- *; apply Hp; apply H0. - intro n; exact (Hp (Zneg n)). -Qed. +Definition eq := @Logic.eq Z. +Definition eq_equiv := @eq_equivalence Z. -(**********************************************************************) -(** * Misc properties about binary integer operations *) +Definition lt x y := (x ?= y) = Lt. +Definition gt x y := (x ?= y) = Gt. +Definition le x y := (x ?= y) <> Gt. +Definition ge x y := (x ?= y) <> Lt. +Infix "<=" := le : Z_scope. +Infix "<" := lt : Z_scope. +Infix ">=" := ge : Z_scope. +Infix ">" := gt : Z_scope. -(**********************************************************************) -(** ** Properties of opposite on binary integer numbers *) +Notation "x <= y <= z" := (x <= y /\ y <= z) : Z_scope. +Notation "x <= y < z" := (x <= y /\ y < z) : Z_scope. +Notation "x < y < z" := (x < y /\ y < z) : Z_scope. +Notation "x < y <= z" := (x < y /\ y <= z) : Z_scope. + +Definition divide x y := exists z, y = z*x. +Notation "( x | y )" := (divide x y) (at level 0). + +Definition Even a := exists b, a = 2*b. +Definition Odd a := exists b, a = 2*b+1. -Theorem Zopp_0 : Zopp Z0 = Z0. +(** * Decidability of equality. *) + +Definition eq_dec (x y : Z) : {x = y} + {x <> y}. Proof. - reflexivity. + decide equality; apply Pos.eq_dec. +Defined. + +(** * Properties of [pos_sub] *) + +(** [pos_sub] can be written in term of positive comparison + and subtraction (cf. earlier definition of addition of Z) *) + +Lemma pos_sub_spec p q : + pos_sub p q = + match (p ?= q)%positive with + | Eq => 0 + | Lt => neg (q - p) + | Gt => pos (p - q) + end. +Proof. + revert q. induction p; destruct q; simpl; trivial; + rewrite ?Pos.compare_xI_xI, ?Pos.compare_xO_xI, + ?Pos.compare_xI_xO, ?Pos.compare_xO_xO, IHp; simpl; + case Pos.compare_spec; intros; simpl; trivial; + (now rewrite Pos.sub_xI_xI) || (now rewrite Pos.sub_xO_xO) || + (now rewrite Pos.sub_xO_xI) || (now rewrite Pos.sub_xI_xO) || + subst; unfold Pos.sub; simpl; now rewrite Pos.sub_mask_diag. Qed. -Theorem Zopp_neg : forall p:positive, - Zneg p = Zpos p. +Lemma pos_sub_discr p q : + match pos_sub p q with + | Z0 => p = q + | pos k => p = q + k + | neg k => q = p + k + end%positive. Proof. - reflexivity. + rewrite pos_sub_spec. + case Pos.compare_spec; auto; intros; + now rewrite Pos.add_comm, Pos.sub_add. Qed. -(** [opp] is involutive *) +(** Particular cases of the previous result *) -Theorem Zopp_involutive : forall n:Z, - - n = n. +Lemma pos_sub_diag p : pos_sub p p = 0. Proof. - intro x; destruct x; reflexivity. + now rewrite pos_sub_spec, Pos.compare_refl. Qed. -(** Injectivity of the opposite *) +Lemma pos_sub_lt p q : (p < q)%positive -> pos_sub p q = neg (q - p). +Proof. + intros H. now rewrite pos_sub_spec, H. +Qed. -Theorem Zopp_inj : forall n m:Z, - n = - m -> n = m. +Lemma pos_sub_gt p q : (q < p)%positive -> pos_sub p q = pos (p - q). 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 H. now rewrite pos_sub_spec, Pos.compare_antisym, H. Qed. -(**********************************************************************) -(** ** Other properties of binary integer numbers *) +(** The opposite of [pos_sub] is [pos_sub] with reversed arguments *) -Lemma ZL0 : 2%nat = (1 + 1)%nat. +Lemma pos_sub_opp p q : - pos_sub p q = pos_sub q p. Proof. - reflexivity. + revert q; induction p; destruct q; simpl; trivial; + rewrite <- IHp; now destruct pos_sub. Qed. -(**********************************************************************) -(** * Properties of the addition on integers *) +(** In the following module, we group results that are needed now + to prove specifications of operations, but will also be provided + later by the generic functor of properties. *) -(** ** Zero is left neutral for addition *) +Module Import Private_BootStrap. -Theorem Zplus_0_l : forall n:Z, Z0 + n = n. -Proof. - intro x; destruct x; reflexivity. -Qed. +(** * Properties of addition *) -(** ** Zero is right neutral for addition *) +(** ** Zero is neutral for addition *) -Theorem Zplus_0_r : forall n:Z, n + Z0 = n. +Lemma add_0_r n : n + 0 = n. Proof. - intro x; destruct x; reflexivity. + now destruct n. Qed. (** ** Addition is commutative *) -Theorem Zplus_comm : forall n m:Z, n + m = m + n. +Lemma add_comm n m : n + m = m + n. Proof. - 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. + destruct n, m; simpl; trivial; now rewrite Pos.add_comm. Qed. (** ** Opposite distributes over addition *) -Theorem Zopp_plus_distr : forall n m:Z, - (n + m) = - n + - m. +Lemma opp_add_distr n m : - (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. + destruct n, m; simpl; trivial using pos_sub_opp. Qed. -Theorem Zopp_succ : forall n:Z, Zopp (Zsucc n) = Zpred (Zopp n). +(** ** Opposite is injective *) + +Lemma opp_inj n m : -n = -m -> n = m. Proof. -intro; unfold Zsucc; now rewrite Zopp_plus_distr. + destruct n, m; simpl; intros H; destr_eq H; now f_equal. +Qed. + +(** ** Addition is associative *) + +Lemma pos_sub_add p q r : + pos_sub (p + q) r = pos p + pos_sub q r. +Proof. + simpl. rewrite !pos_sub_spec. + case (Pos.compare_spec q r); intros E0. + - (* q = r *) + subst. + assert (H := Pos.lt_add_r r p). + rewrite Pos.add_comm in H. apply Pos.lt_gt in H. + now rewrite H, Pos.add_sub. + - (* q < r *) + rewrite pos_sub_spec. + assert (Hr : (r = (r-q)+q)%positive) by (now rewrite Pos.sub_add). + rewrite Hr at 1. rewrite Pos.add_compare_mono_r. + case Pos.compare_spec; intros E1; trivial; f_equal. + rewrite Pos.add_comm. apply Pos.sub_add_distr. + rewrite Hr, Pos.add_comm. now apply Pos.add_lt_mono_r. + symmetry. apply Pos.sub_sub_distr; trivial. + - (* r < q *) + assert (LT : (r < p + q)%positive). + { apply Pos.lt_trans with q; trivial. + rewrite Pos.add_comm. apply Pos.lt_add_r. } + apply Pos.lt_gt in LT. rewrite LT. f_equal. + symmetry. now apply Pos.add_sub_assoc. +Qed. + +Lemma add_assoc n m p : n + (m + p) = n + m + p. +Proof. + assert (AUX : forall x y z, pos x + (y + z) = pos x + y + z). + { intros x [|y|y] [|z|z]; rewrite ?add_0_r; trivial. + - simpl. now rewrite Pos.add_assoc. + - simpl (_ + neg _). symmetry. apply pos_sub_add. + - simpl (neg _ + _); simpl (_ + neg _). + now rewrite (add_comm _ (pos _)), <- 2 pos_sub_add, Pos.add_comm. + - apply opp_inj. rewrite !opp_add_distr. simpl opp. + simpl (neg _ + _); simpl (_ + neg _). + rewrite add_comm, Pos.add_comm. apply pos_sub_add. } + destruct n. + - trivial. + - apply AUX. + - apply opp_inj. rewrite !opp_add_distr. simpl opp. apply AUX. +Qed. + +(** ** Subtraction and successor *) + +Lemma sub_succ_l n m : succ n - m = succ (n - m). +Proof. + unfold sub, succ. now rewrite <- 2 add_assoc, (add_comm 1). Qed. (** ** Opposite is inverse for addition *) -Theorem Zplus_opp_r : forall n:Z, n + - n = Z0. +Lemma add_opp_diag_r n : n + - n = 0. Proof. - intro x; destruct x as [| p| p]; simpl in |- *; - [ reflexivity - | rewrite (Pcompare_refl p); reflexivity - | rewrite (Pcompare_refl p); reflexivity ]. + destruct n; simpl; trivial; now rewrite pos_sub_diag. Qed. -Theorem Zplus_opp_l : forall n:Z, - n + n = Z0. +Lemma add_opp_diag_l n : - n + n = 0. Proof. - intro; rewrite Zplus_comm; apply Zplus_opp_r. + rewrite add_comm. apply add_opp_diag_r. Qed. -Hint Local Resolve Zplus_0_l Zplus_0_r. +(** ** Commutativity of multiplication *) -(** ** Addition is associative *) +Lemma mul_comm n m : n * m = m * n. +Proof. + destruct n, m; simpl; trivial; f_equal; apply Pos.mul_comm. +Qed. -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 ] ] ]. -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 ]. -Qed. - - -Lemma Zplus_assoc_reverse : forall n m p:Z, n + m + p = n + (m + p). -Proof. - intros; symmetry in |- *; apply Zplus_assoc. -Qed. - -(** ** 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. -Qed. - -(** ** 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 ]. -Qed. - -(** ** 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. -Qed. - -Lemma Zplus_succ_r_reverse : forall n m:Z, Zsucc (n + m) = n + Zsucc m. -Proof. - intros n m; unfold Zsucc in |- *; rewrite Zplus_assoc; trivial with arith. +(** ** Associativity of multiplication *) + +Lemma mul_assoc n m p : n * (m * p) = n * m * p. +Proof. + destruct n, m, p; simpl; trivial; f_equal; apply Pos.mul_assoc. Qed. -Notation Zplus_succ_r := Zplus_succ_r_reverse (only parsing). +(** Multiplication and constants *) -Lemma Zplus_succ_comm : forall n m:Z, Zsucc n + m = n + Zsucc m. +Lemma mul_1_l n : 1 * n = n. Proof. - unfold Zsucc in |- *; intros n m; rewrite <- Zplus_assoc; - rewrite (Zplus_comm (Zpos 1)); trivial with arith. + now destruct n. Qed. -(** ** Misc properties, usually redundant or non natural *) +Lemma mul_1_r n : n * 1 = n. +Proof. + destruct n; simpl; now rewrite ?Pos.mul_1_r. +Qed. + +(** ** Multiplication and Opposite *) -Lemma Zplus_0_r_reverse : forall n:Z, n = n + Z0. +Lemma mul_opp_l n m : - n * m = - (n * m). Proof. - symmetry in |- *; apply Zplus_0_r. + now destruct n, m. Qed. -Lemma Zplus_0_simpl_l : forall n m:Z, n + Z0 = m -> n = m. +Lemma mul_opp_r n m : n * - m = - (n * m). Proof. - intros n m; rewrite Zplus_0_r; intro; assumption. + now destruct n, m. Qed. -Lemma Zplus_0_simpl_l_reverse : forall n m:Z, n = m + Z0 -> n = m. +Lemma mul_opp_opp n m : - n * - m = n * m. Proof. - intros n m; rewrite Zplus_0_r; intro; assumption. + now destruct n, m. Qed. -Lemma Zplus_eq_compat : forall n m p q:Z, n = m -> p = q -> n + p = m + q. +Lemma mul_opp_comm n m : - n * m = n * - m. Proof. - intros; rewrite H; rewrite H0; reflexivity. + now destruct n, m. Qed. -Lemma Zplus_opp_expand : forall n m p:Z, n + - m = n + - p + (p + - m). +(** ** Distributivity of multiplication over addition *) + +Lemma mul_add_distr_pos (p:positive) n m : + pos p * (n + m) = pos p * n + pos p * m. Proof. - intros x y z. - rewrite <- (Zplus_assoc x). - rewrite (Zplus_assoc (- z)). - rewrite Zplus_opp_l. - reflexivity. + destruct n as [|n|n], m as [|m|m]; simpl; trivial; + rewrite ?pos_sub_spec, ?Pos.mul_compare_mono_l; try case Pos.compare_spec; + intros; now rewrite ?Pos.mul_add_distr_l, ?Pos.mul_sub_distr_l. Qed. -(************************************************************************) -(** * Properties of successor and predecessor on binary integer numbers *) +Lemma mul_add_distr_l n m p : n * (m + p) = n * m + n * p. +Proof. + destruct n as [|n|n]. trivial. + apply mul_add_distr_pos. + change (neg n) with (- pos n). + rewrite !mul_opp_l, <- opp_add_distr. f_equal. + apply mul_add_distr_pos. +Qed. -Theorem Zsucc_discr : forall n:Z, n <> Zsucc n. +Lemma mul_add_distr_r n m p : (n + m) * p = n * p + m * p. 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 ]. + rewrite !(mul_comm _ p). apply mul_add_distr_l. Qed. -Theorem Zpos_succ_morphism : - forall p:positive, Zpos (Psucc p) = Zsucc (Zpos p). +(** ** Basic properties of divisibility *) + +Lemma divide_Zpos p q : (pos p|pos q) <-> (p|q)%positive. Proof. - intro; rewrite Pplus_one_succ_r; unfold Zsucc in |- *; simpl in |- *; - trivial with arith. + split. + intros ([ |r|r],H); simpl in *; destr_eq H. exists r; auto. + intros (r,H). exists (pos r); simpl; now f_equal. Qed. -(** ** Successor and predecessor are inverse functions *) +Lemma divide_Zpos_Zneg_r n p : (n|pos p) <-> (n|neg p). +Proof. + split; intros (m,H); exists (-m); now rewrite mul_opp_l, <- H. +Qed. -Theorem Zsucc_pred : forall n:Z, n = Zsucc (Zpred n). +Lemma divide_Zpos_Zneg_l n p : (pos p|n) <-> (neg p|n). Proof. - intros n; unfold Zsucc, Zpred in |- *; rewrite <- Zplus_assoc; simpl in |- *; - rewrite Zplus_0_r; trivial with arith. + split; intros (m,H); exists (-m); now rewrite mul_opp_l, <- mul_opp_r. Qed. -Hint Immediate Zsucc_pred: zarith. +(** ** Conversions between [Z.testbit] and [N.testbit] *) -Theorem Zpred_succ : forall n:Z, n = Zpred (Zsucc n). +Lemma testbit_of_N a n : + testbit (of_N a) (of_N n) = N.testbit a n. Proof. - intros m; unfold Zpred, Zsucc in |- *; rewrite <- Zplus_assoc; simpl in |- *; - rewrite Zplus_comm; auto with arith. + destruct a as [|a], n; simpl; trivial. now destruct a. Qed. -Theorem Zsucc_inj : forall n m:Z, Zsucc n = Zsucc m -> n = m. +Lemma testbit_of_N' a n : 0<=n -> + testbit (of_N a) n = N.testbit a (to_N n). 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. + intro Hn. rewrite <- testbit_of_N. f_equal. + destruct n; trivial; now destruct Hn. Qed. -(*************************************************************************) -(** ** Properties of the direct definition of successor and predecessor *) +Lemma testbit_Zpos a n : 0<=n -> + testbit (pos a) n = N.testbit (N.pos a) (to_N n). +Proof. + intro Hn. now rewrite <- testbit_of_N'. +Qed. -Theorem Zsucc_succ' : forall n:Z, Zsucc n = Zsucc' n. +Lemma testbit_Zneg a n : 0<=n -> + testbit (neg a) n = negb (N.testbit (Pos.pred_N a) (to_N n)). Proof. -destruct n as [| p | p]; simpl. -reflexivity. -now rewrite Pplus_one_succ_r. -now destruct p as [q | q |]. + intro Hn. + rewrite <- testbit_of_N' by trivial. + destruct n as [ |n|n]; + [ | simpl; now destruct (Pos.pred_N a) | now destruct Hn]. + unfold testbit. + now destruct a as [|[ | | ]| ]. Qed. -Theorem Zpred_pred' : forall n:Z, Zpred n = Zpred' n. +End Private_BootStrap. + +(** * Proofs of specifications *) + +(** ** Specification of constants *) + +Lemma one_succ : 1 = succ 0. Proof. -destruct n as [| p | p]; simpl. reflexivity. -now destruct p as [q | q |]. -now rewrite Pplus_one_succ_r. Qed. -Theorem Zsucc'_inj : forall n m:Z, Zsucc' n = Zsucc' m -> n = m. +Lemma two_succ : 2 = succ 1. Proof. -intros n m; do 2 rewrite <- Zsucc_succ'; now apply Zsucc_inj. +reflexivity. Qed. -Theorem Zsucc'_pred' : forall n:Z, Zsucc' (Zpred' n) = n. +(** ** Specification of addition *) + +Lemma add_0_l n : 0 + n = n. Proof. -intro; rewrite <- Zsucc_succ'; rewrite <- Zpred_pred'; -symmetry; apply Zsucc_pred. + now destruct n. Qed. -Theorem Zpred'_succ' : forall n:Z, Zpred' (Zsucc' n) = n. +Lemma add_succ_l n m : succ n + m = succ (n + m). Proof. -intro; apply Zsucc'_inj; now rewrite Zsucc'_pred'. + unfold succ. now rewrite 2 (add_comm _ 1), add_assoc. Qed. -Theorem Zpred'_inj : forall n m:Z, Zpred' n = Zpred' m -> n = m. +(** ** Specification of opposite *) + +Lemma opp_0 : -0 = 0. Proof. -intros n m H. -rewrite <- (Zsucc'_pred' n); rewrite <- (Zsucc'_pred' m); now rewrite H. + reflexivity. Qed. -Theorem Zsucc'_discr : forall n:Z, n <> Zsucc' n. +Lemma opp_succ n : -(succ n) = pred (-n). Proof. - intro x; destruct x; simpl in |- *. - discriminate. - injection; apply Psucc_discr. - destruct p; simpl in |- *. - discriminate. - intro H; symmetry in H; injection H; apply double_moins_un_xO_discr. - discriminate. + unfold succ, pred. apply opp_add_distr. Qed. -(** Misc properties, usually redundant or non natural *) +(** ** Specification of successor and predecessor *) -Lemma Zsucc_eq_compat : forall n m:Z, n = m -> Zsucc n = Zsucc m. +Lemma succ_pred n : succ (pred n) = n. Proof. - intros n m H; rewrite H; reflexivity. + unfold succ, pred. now rewrite <- add_assoc, add_opp_diag_r, add_0_r. Qed. -Lemma Zsucc_inj_contrapositive : forall n m:Z, n <> m -> Zsucc n <> Zsucc m. +Lemma pred_succ n : pred (succ n) = n. Proof. - unfold not in |- *; intros n m H1 H2; apply H1; apply Zsucc_inj; assumption. + unfold succ, pred. now rewrite <- add_assoc, add_opp_diag_r, add_0_r. Qed. -(**********************************************************************) -(** * Properties of subtraction on binary integer numbers *) +(** ** Specification of subtraction *) -(** ** [minus] and [Z0] *) - -Lemma Zminus_0_r : forall n:Z, n - Z0 = n. +Lemma sub_0_r n : n - 0 = n. Proof. - intro; unfold Zminus in |- *; simpl in |- *; rewrite Zplus_0_r; - trivial with arith. + apply add_0_r. Qed. -Lemma Zminus_0_l_reverse : forall n:Z, n = n - Z0. +Lemma sub_succ_r n m : n - succ m = pred (n - m). Proof. - intro; symmetry in |- *; apply Zminus_0_r. + unfold sub, succ, pred. now rewrite opp_add_distr, add_assoc. Qed. -Lemma Zminus_diag : forall n:Z, n - n = Z0. +(** ** Specification of multiplication *) + +Lemma mul_0_l n : 0 * n = 0. Proof. - intro; unfold Zminus in |- *; rewrite Zplus_opp_r; trivial with arith. + reflexivity. Qed. -Lemma Zminus_diag_reverse : forall n:Z, Z0 = n - n. +Lemma mul_succ_l n m : succ n * m = n * m + m. Proof. - intro; symmetry in |- *; apply Zminus_diag. + unfold succ. now rewrite mul_add_distr_r, mul_1_l. Qed. +(** ** Specification of comparisons and order *) -(** ** Relating [minus] with [plus] and [Zsucc] *) +Lemma eqb_eq n m : (n =? m) = true <-> n = m. +Proof. + destruct n, m; simpl; try (now split); rewrite Pos.eqb_eq; + split; (now injection 1) || (intros; now f_equal). +Qed. -Lemma Zminus_plus_distr : forall n m p:Z, n - (m + p) = n - m - p. +Lemma ltb_lt n m : (n <? m) = true <-> n < m. Proof. -intros; unfold Zminus; rewrite Zopp_plus_distr; apply Zplus_assoc. + unfold ltb, lt. destruct compare; easy'. Qed. -Lemma Zminus_succ_l : forall n m:Z, Zsucc (n - m) = Zsucc n - m. +Lemma leb_le n m : (n <=? m) = true <-> n <= m. Proof. - intros n m; unfold Zminus, Zsucc in |- *; rewrite (Zplus_comm n (- m)); - rewrite <- Zplus_assoc; apply Zplus_comm. + unfold leb, le. destruct compare; easy'. Qed. -Lemma Zminus_succ_r : forall n m:Z, n - (Zsucc m) = Zpred (n - m). +Lemma compare_eq_iff n m : (n ?= m) = Eq <-> n = m. Proof. -intros; unfold Zsucc; now rewrite Zminus_plus_distr. +destruct n, m; simpl; rewrite ?CompOpp_iff, ?Pos.compare_eq_iff; + split; congruence. Qed. -Lemma Zplus_minus_eq : forall n m p:Z, n = m + p -> p = n - m. +Lemma compare_sub n m : (n ?= m) = (n - m ?= 0). 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. + destruct n as [|n|n], m as [|m|m]; simpl; trivial; + rewrite <- ? Pos.compare_antisym, ?pos_sub_spec; + case Pos.compare_spec; trivial. Qed. -Lemma Zminus_plus : forall n m:Z, n + m - n = m. +Lemma compare_antisym n m : (m ?= n) = CompOpp (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. +destruct n, m; simpl; trivial; now rewrite <- ?Pos.compare_antisym. Qed. -Lemma Zplus_minus : forall n m:Z, n + (m - n) = m. +Lemma compare_lt_iff n m : (n ?= m) = Lt <-> n < m. +Proof. reflexivity. Qed. + +Lemma compare_le_iff n m : (n ?= m) <> Gt <-> n <= m. +Proof. reflexivity. Qed. + +(** Some more advanced properties of comparison and orders, + including [compare_spec] and [lt_irrefl] and [lt_eq_cases]. *) + +Include BoolOrderFacts. + +(** Remaining specification of [lt] and [le] *) + +Lemma lt_succ_r n m : n < succ m <-> n<=m. Proof. - unfold Zminus in |- *; intros n m; rewrite Zplus_permute; rewrite Zplus_opp_r; - apply Zplus_0_r. + unfold lt, le. rewrite compare_sub, sub_succ_r. + rewrite (compare_sub n m). + destruct (n-m) as [|[ | | ]|]; easy'. Qed. -Lemma Zminus_plus_simpl_l : forall n m p:Z, p + n - (p + m) = n - m. +(** ** Specification of minimum and maximum *) + +Lemma max_l n m : m<=n -> max n m = n. 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. + unfold le, max. rewrite (compare_antisym n m). + case compare; intuition. Qed. -Lemma Zminus_plus_simpl_l_reverse : forall n m p:Z, n - m = p + n - (p + m). +Lemma max_r n m : n<=m -> max n m = m. Proof. - intros; symmetry in |- *; apply Zminus_plus_simpl_l. + unfold le, max. case compare_spec; intuition. Qed. -Lemma Zminus_plus_simpl_r : forall n m p:Z, n + p - (m + p) = n - m. +Lemma min_l n m : n<=m -> min n m = n. 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. + unfold le, min. case compare_spec; intuition. Qed. -Lemma Zpos_minus_morphism : forall a b:positive, Pcompare a b Eq = Lt -> - Zpos (b-a) = Zpos b - Zpos a. +Lemma min_r n m : m<=n -> min n m = m. Proof. - intros. - simpl. - change Eq with (CompOpp Eq). - rewrite <- Pcompare_antisym. - rewrite H; simpl; auto. + unfold le, min. + rewrite (compare_antisym n m). case compare_spec; intuition. Qed. -(** ** Misc redundant properties *) +(** ** Specification of absolute value *) -Lemma Zeq_minus : forall n m:Z, n = m -> n - m = Z0. +Lemma abs_eq n : 0 <= n -> abs n = n. Proof. - intros x y H; rewrite H; symmetry in |- *; apply Zminus_diag_reverse. + destruct n; trivial. now destruct 1. Qed. -Lemma Zminus_eq : forall n m:Z, n - m = Z0 -> n = m. +Lemma abs_neq n : n <= 0 -> abs n = - n. Proof. - intros x y H; rewrite <- (Zplus_minus y x); rewrite H; apply Zplus_0_r. + destruct n; trivial. now destruct 1. Qed. +(** ** Specification of sign *) -(**********************************************************************) -(** * Properties of multiplication on binary integer numbers *) - -Theorem Zpos_mult_morphism : - forall p q:positive, Zpos (p*q) = Zpos p * Zpos q. +Lemma sgn_null n : n = 0 -> sgn n = 0. Proof. - auto. + intros. now subst. Qed. -(** ** One is neutral for multiplication *) - -Theorem Zmult_1_l : forall n:Z, Zpos 1 * n = n. +Lemma sgn_pos n : 0 < n -> sgn n = 1. Proof. - intro x; destruct x; reflexivity. + now destruct n. Qed. -Theorem Zmult_1_r : forall n:Z, n * Zpos 1 = n. +Lemma sgn_neg n : n < 0 -> sgn n = -1. Proof. - intro x; destruct x; simpl in |- *; try rewrite Pmult_1_r; reflexivity. + now destruct n. Qed. -(** ** Zero property of multiplication *) +(** ** Specification of power *) -Theorem Zmult_0_l : forall n:Z, Z0 * n = Z0. +Lemma pow_0_r n : n^0 = 1. Proof. - intro x; destruct x; reflexivity. + reflexivity. Qed. -Theorem Zmult_0_r : forall n:Z, n * Z0 = Z0. +Lemma pow_succ_r n m : 0<=m -> n^(succ m) = n * n^m. Proof. - intro x; destruct x; reflexivity. + destruct m as [|m|m]; (now destruct 1) || (intros _); simpl; trivial. + unfold pow_pos. now rewrite Pos.add_comm, Pos.iter_add. Qed. -Hint Local Resolve Zmult_0_l Zmult_0_r. +Lemma pow_neg_r n m : m<0 -> n^m = 0. +Proof. + now destruct m. +Qed. -Lemma Zmult_0_r_reverse : forall n:Z, Z0 = n * Z0. +(** For folding back a [pow_pos] into a [pow] *) + +Lemma pow_pos_fold n p : pow_pos n p = n ^ (pos p). Proof. - intro x; destruct x; reflexivity. + reflexivity. Qed. -(** ** Commutativity of multiplication *) +(** ** Specification of square *) -Theorem Zmult_comm : forall n m:Z, n * m = m * n. +Lemma square_spec n : square n = n * n. Proof. - intros x y; destruct x as [| p| p]; destruct y as [| q| q]; simpl in |- *; - try rewrite (Pmult_comm p q); reflexivity. + destruct n; trivial; simpl; f_equal; apply Pos.square_spec. Qed. -(** ** Associativity of multiplication *) +(** ** Specification of square root *) -Theorem Zmult_assoc : forall n m p:Z, n * (m * p) = n * m * p. +Lemma sqrtrem_spec n : 0<=n -> + let (s,r) := sqrtrem n in n = s*s + r /\ 0 <= r <= 2*s. Proof. - intros x y z; destruct x; destruct y; destruct z; simpl in |- *; - try rewrite Pmult_assoc; reflexivity. + destruct n. now repeat split. + generalize (Pos.sqrtrem_spec p). simpl. + destruct 1; simpl; subst; now repeat split. + now destruct 1. Qed. -Lemma Zmult_assoc_reverse : forall n m p:Z, n * m * p = n * (m * p). +Lemma sqrt_spec n : 0<=n -> + let s := sqrt n in s*s <= n < (succ s)*(succ s). Proof. - intros n m p; rewrite Zmult_assoc; trivial with arith. + destruct n. now repeat split. unfold sqrt. + intros _. simpl succ. rewrite Pos.add_1_r. apply (Pos.sqrt_spec p). + now destruct 1. Qed. -(** ** Associativity mixed with commutativity *) +Lemma sqrt_neg n : n<0 -> sqrt n = 0. +Proof. + now destruct n. +Qed. -Theorem Zmult_permute : forall n m p:Z, n * (m * p) = m * (n * p). +Lemma sqrtrem_sqrt n : fst (sqrtrem n) = sqrt n. Proof. - intros x y z; rewrite (Zmult_assoc y x z); rewrite (Zmult_comm y x). - apply Zmult_assoc. + destruct n; try reflexivity. + unfold sqrtrem, sqrt, Pos.sqrt. + destruct (Pos.sqrtrem p) as (s,r). now destruct r. Qed. -(** ** Z is integral *) +(** ** Specification of logarithm *) -Theorem Zmult_integral_l : forall n m:Z, n <> Z0 -> m * n = Z0 -> m = Z0. +Lemma log2_spec n : 0 < n -> 2^(log2 n) <= n < 2^(succ (log2 n)). Proof. - 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. + assert (Pow : forall p q, pos (p^q) = (pos p)^(pos q)). + { intros. now apply Pos.iter_swap_gen. } + destruct n as [|[p|p|]|]; intros Hn; split; try easy; unfold log2; + simpl succ; rewrite ?Pos.add_1_r, <- Pow. + change (2^Pos.size p <= Pos.succ (p~0))%positive. + apply Pos.lt_le_incl, Pos.lt_succ_r, Pos.size_le. + apply Pos.size_gt. + apply Pos.size_le. + apply Pos.size_gt. Qed. - -Theorem Zmult_integral : forall n m:Z, n * m = Z0 -> n = Z0 \/ m = Z0. +Lemma log2_nonpos n : n<=0 -> log2 n = 0. Proof. - intros x y; destruct x; destruct y; auto; simpl in |- *; intro H; - discriminate H. + destruct n as [|p|p]; trivial; now destruct 1. Qed. +(** Specification of parity functions *) + +Lemma even_spec n : even n = true <-> Even n. +Proof. + split. + exists (div2 n). now destruct n as [|[ | | ]|[ | | ]]. + intros (m,->). now destruct m. +Qed. -Lemma Zmult_1_inversion_l : - forall n m:Z, n * m = Zpos 1 -> n = Zpos 1 \/ n = Zneg 1. +Lemma odd_spec n : odd n = true <-> Odd n. 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). + split. + exists (div2 n). destruct n as [|[ | | ]|[ | | ]]; simpl; try easy. + now rewrite Pos.pred_double_succ. + intros (m,->). now destruct m as [|[ | | ]|[ | | ]]. Qed. (** ** Multiplication and Doubling *) -Lemma Zdouble_mult : forall z, Zdouble z = (Zpos 2) * z. +Lemma double_spec n : double n = 2*n. +Proof. + reflexivity. +Qed. + +Lemma succ_double_spec n : succ_double n = 2*n + 1. +Proof. + now destruct n. +Qed. + +Lemma pred_double_spec n : pred_double n = 2*n - 1. +Proof. + now destruct n. +Qed. + +(** ** Correctness proofs for Trunc division *) + +Lemma pos_div_eucl_eq a b : 0 < b -> + let (q, r) := pos_div_eucl a b in pos a = q * b + r. +Proof. + intros Hb. + induction a; unfold pos_div_eucl; fold pos_div_eucl. + - (* ~1 *) + destruct pos_div_eucl as (q,r). + change (pos a~1) with (2*(pos a)+1). + rewrite IHa, mul_add_distr_l, mul_assoc. + destruct ltb. + now rewrite add_assoc. + rewrite mul_add_distr_r, mul_1_l, <- !add_assoc. f_equal. + unfold sub. now rewrite (add_comm _ (-b)), add_assoc, add_opp_diag_r. + - (* ~0 *) + destruct pos_div_eucl as (q,r). + change (pos a~0) with (2*pos a). + rewrite IHa, mul_add_distr_l, mul_assoc. + destruct ltb. + trivial. + rewrite mul_add_distr_r, mul_1_l, <- !add_assoc. f_equal. + unfold sub. now rewrite (add_comm _ (-b)), add_assoc, add_opp_diag_r. + - (* 1 *) + case leb_spec; trivial. + intros Hb'. + destruct b as [|b|b]; try easy; clear Hb. + replace b with 1%positive; trivial. + apply Pos.le_antisym. apply Pos.le_1_l. now apply Pos.lt_succ_r. +Qed. + +Lemma div_eucl_eq a b : b<>0 -> + let (q, r) := div_eucl a b in a = b * q + r. +Proof. + destruct a as [ |a|a], b as [ |b|b]; unfold div_eucl; trivial; + (now destruct 1) || intros _; + generalize (pos_div_eucl_eq a (pos b) (eq_refl _)); + destruct pos_div_eucl as (q,r); rewrite mul_comm. + - (* pos pos *) + trivial. + - (* pos neg *) + intros ->. + destruct r as [ |r|r]; rewrite <- !mul_opp_comm; trivial; + rewrite mul_add_distr_l, mul_1_r, <- add_assoc; f_equal; + now rewrite add_assoc, add_opp_diag_r. + - (* neg pos *) + change (neg a) with (- pos a). intros ->. + rewrite (opp_add_distr _ r), <- mul_opp_r. + destruct r as [ |r|r]; trivial; + rewrite opp_add_distr, mul_add_distr_l, <- add_assoc; f_equal; + unfold sub; now rewrite add_assoc, mul_opp_r, mul_1_r, add_opp_diag_l. + - (* neg neg *) + change (neg a) with (- pos a). intros ->. + now rewrite opp_add_distr, <- mul_opp_l. +Qed. + +Lemma div_mod a b : b<>0 -> a = b*(a/b) + (a mod b). +Proof. + intros Hb. generalize (div_eucl_eq a b Hb). + unfold div, modulo. now destruct div_eucl. +Qed. + +Lemma pos_div_eucl_bound a b : 0<b -> 0 <= snd (pos_div_eucl a b) < b. +Proof. + assert (AUX : forall m p, m < pos (p~0) -> m - pos p < pos p). + intros m p. unfold lt. + rewrite (compare_sub m), (compare_sub _ (pos _)). unfold sub. + rewrite <- add_assoc. simpl opp; simpl (neg _ + _). + now rewrite Pos.add_diag. + intros Hb. + destruct b as [|b|b]; discriminate Hb || clear Hb. + induction a; unfold pos_div_eucl; fold pos_div_eucl. + (* ~1 *) + destruct pos_div_eucl as (q,r). + simpl in IHa; destruct IHa as (Hr,Hr'). + case ltb_spec; intros H; unfold snd. split; trivial. now destruct r. + split. unfold le. + now rewrite compare_antisym, <- compare_sub, <- compare_antisym. + apply AUX. rewrite <- succ_double_spec. + destruct r; try easy. unfold lt in *; simpl in *. + now rewrite Pos.compare_xI_xO, Hr'. + (* ~0 *) + destruct pos_div_eucl as (q,r). + simpl in IHa; destruct IHa as (Hr,Hr'). + case ltb_spec; intros H; unfold snd. split; trivial. now destruct r. + split. unfold le. + now rewrite compare_antisym, <- compare_sub, <- compare_antisym. + apply AUX. destruct r; try easy. + (* 1 *) + case leb_spec; intros H; simpl; split; try easy. + red; simpl. now apply Pos.le_succ_l. +Qed. + +Lemma mod_pos_bound a b : 0 < b -> 0 <= a mod b < b. +Proof. + destruct b as [|b|b]; try easy; intros _. + destruct a as [|a|a]; unfold modulo, div_eucl. + now split. + now apply pos_div_eucl_bound. + generalize (pos_div_eucl_bound a (pos b) (eq_refl _)). + destruct pos_div_eucl as (q,r); unfold snd; intros (Hr,Hr'). + destruct r as [|r|r]; (now destruct Hr) || clear Hr. + now split. + split. unfold le. + now rewrite compare_antisym, <- compare_sub, <- compare_antisym, Hr'. + unfold lt in *; simpl in *. rewrite pos_sub_gt by trivial. + simpl. now apply Pos.sub_decr. +Qed. + +Definition mod_bound_pos a b (_:0<=a) := mod_pos_bound a b. + +Lemma mod_neg_bound a b : b < 0 -> b < a mod b <= 0. +Proof. + destruct b as [|b|b]; try easy; intros _. + destruct a as [|a|a]; unfold modulo, div_eucl. + now split. + generalize (pos_div_eucl_bound a (pos b) (eq_refl _)). + destruct pos_div_eucl as (q,r); unfold snd; intros (Hr,Hr'). + destruct r as [|r|r]; (now destruct Hr) || clear Hr. + now split. + split. + unfold lt in *; simpl in *. rewrite pos_sub_lt by trivial. + rewrite <- Pos.compare_antisym. now apply Pos.sub_decr. + change (neg b - neg r <= 0). unfold le, lt in *. + rewrite <- compare_sub. simpl in *. + now rewrite <- Pos.compare_antisym, Hr'. + generalize (pos_div_eucl_bound a (pos b) (eq_refl _)). + destruct pos_div_eucl as (q,r); unfold snd; intros (Hr,Hr'). + split; destruct r; try easy. + red; simpl; now rewrite <- Pos.compare_antisym. +Qed. + +(** ** Correctness proofs for Floor division *) + +Theorem quotrem_eq a b : let (q,r) := quotrem a b in a = q * b + r. Proof. - reflexivity. + destruct a as [|a|a], b as [|b|b]; simpl; trivial; + generalize (N.pos_div_eucl_spec a (N.pos b)); case N.pos_div_eucl; trivial; + intros q r; + try change (neg a) with (-pos a); + change (pos a) with (of_N (N.pos a)); intros ->; now destruct q, r. Qed. -Lemma Zdouble_plus_one_mult : forall z, - Zdouble_plus_one z = (Zpos 2) * z + (Zpos 1). +Lemma quot_rem' a b : a = b*(a÷b) + rem a b. Proof. - destruct z; simpl; auto with zarith. + rewrite mul_comm. generalize (quotrem_eq a b). + unfold quot, rem. now destruct quotrem. Qed. -(** ** Multiplication and Opposite *) +Lemma quot_rem a b : b<>0 -> a = b*(a÷b) + rem a b. +Proof. intros _. apply quot_rem'. Qed. -Theorem Zopp_mult_distr_l : forall n m:Z, - (n * m) = - n * m. +Lemma rem_bound_pos a b : 0<=a -> 0<b -> 0 <= rem a b < b. Proof. - intros x y; destruct x; destruct y; reflexivity. + intros Ha Hb. + destruct b as [|b|b]; (now discriminate Hb) || clear Hb; + destruct a as [|a|a]; (now destruct Ha) || clear Ha. + compute. now split. + unfold rem, quotrem. + assert (H := N.pos_div_eucl_remainder a (N.pos b)). + destruct N.pos_div_eucl as (q,[|r]); simpl; split; try easy. + now apply H. Qed. -Theorem Zopp_mult_distr_r : forall n m:Z, - (n * m) = n * - m. +Lemma rem_opp_l' a b : rem (-a) b = - (rem a b). Proof. - intros x y; rewrite (Zmult_comm x y); rewrite Zopp_mult_distr_l; - apply Zmult_comm. + destruct a, b; trivial; unfold rem; simpl; + now destruct N.pos_div_eucl as (q,[|r]). Qed. -Lemma Zopp_mult_distr_l_reverse : forall n m:Z, - n * m = - (n * m). +Lemma rem_opp_r' a b : rem a (-b) = rem a b. Proof. - intros x y; symmetry in |- *; apply Zopp_mult_distr_l. + destruct a, b; trivial; unfold rem; simpl; + now destruct N.pos_div_eucl as (q,[|r]). Qed. -Theorem Zmult_opp_comm : forall n m:Z, - n * m = n * - m. +Lemma rem_opp_l a b : b<>0 -> rem (-a) b = - (rem a b). +Proof. intros _. apply rem_opp_l'. Qed. + +Lemma rem_opp_r a b : b<>0 -> rem a (-b) = rem a b. +Proof. intros _. apply rem_opp_r'. Qed. + +(** ** Correctness proofs for gcd *) + +Lemma ggcd_gcd a b : fst (ggcd a b) = gcd a b. Proof. - intros x y; rewrite Zopp_mult_distr_l_reverse; rewrite Zopp_mult_distr_r; - trivial with arith. + destruct a as [ |p|p], b as [ |q|q]; simpl; auto; + generalize (Pos.ggcd_gcd p q); destruct Pos.ggcd as (g,(aa,bb)); + simpl; congruence. Qed. -Theorem Zmult_opp_opp : forall n m:Z, - n * - m = n * m. +Lemma ggcd_correct_divisors a b : + let '(g,(aa,bb)) := ggcd a b in + a = g*aa /\ b = g*bb. Proof. - intros x y; destruct x; destruct y; reflexivity. + destruct a as [ |p|p], b as [ |q|q]; simpl; rewrite ?Pos.mul_1_r; auto; + generalize (Pos.ggcd_correct_divisors p q); + destruct Pos.ggcd as (g,(aa,bb)); simpl; destruct 1; now subst. Qed. -Theorem Zopp_eq_mult_neg_1 : forall n:Z, - n = n * Zneg 1. +Lemma gcd_divide_l a b : (gcd a b | a). Proof. - intro x; induction x; intros; rewrite Zmult_comm; auto with arith. + rewrite <- ggcd_gcd. generalize (ggcd_correct_divisors a b). + destruct ggcd as (g,(aa,bb)); simpl. intros (H,_). exists aa. + now rewrite mul_comm. Qed. -(** ** Distributivity of multiplication over addition *) +Lemma gcd_divide_r a b : (gcd a b | b). +Proof. + rewrite <- ggcd_gcd. generalize (ggcd_correct_divisors a b). + destruct ggcd as (g,(aa,bb)); simpl. intros (_,H). exists bb. + now rewrite mul_comm. +Qed. -Lemma weak_Zmult_plus_distr_r : - forall (p:positive) (n m:Z), Zpos p * (n + m) = Zpos p * n + Zpos p * m. +Lemma gcd_greatest a b c : (c|a) -> (c|b) -> (c | gcd a b). 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) ] ]). + assert (H : forall p q r, (r|pos p) -> (r|pos q) -> (r|pos (Pos.gcd p q))). + { intros p q [|r|r] H H'. + destruct H; now rewrite mul_comm in *. + apply divide_Zpos, Pos.gcd_greatest; now apply divide_Zpos. + apply divide_Zpos_Zneg_l, divide_Zpos, Pos.gcd_greatest; + now apply divide_Zpos, divide_Zpos_Zneg_l. + } + destruct a, b; simpl; auto; intros; try apply H; trivial; + now apply divide_Zpos_Zneg_r. Qed. -Theorem Zmult_plus_distr_r : forall n m p:Z, n * (m + p) = n * m + n * p. +Lemma gcd_nonneg a b : 0 <= gcd a b. 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 ]. + now destruct a, b. Qed. -Theorem Zmult_plus_distr_l : forall n m p:Z, (n + m) * p = n * p + m * p. +(** ggcd and opp : an auxiliary result used in QArith *) + +Theorem ggcd_opp a b : + ggcd (-a) b = (let '(g,(aa,bb)) := ggcd a b in (g,(-aa,bb))). Proof. - intros n m p; rewrite Zmult_comm; rewrite Zmult_plus_distr_r; - do 2 rewrite (Zmult_comm p); trivial with arith. + destruct a as [|a|a], b as [|b|b]; unfold ggcd, opp; auto; + destruct (Pos.ggcd a b) as (g,(aa,bb)); auto. Qed. -(** ** Distributivity of multiplication over subtraction *) +(** ** Proofs of specifications for bitwise operations *) -Lemma Zmult_minus_distr_r : forall n m p:Z, (n - m) * p = n * p - m * p. +Lemma div2_spec a : div2 a = shiftr a 1. Proof. - intros x y z; unfold Zminus in |- *. - rewrite <- Zopp_mult_distr_l_reverse. - apply Zmult_plus_distr_l. + reflexivity. Qed. +Lemma testbit_0_l n : testbit 0 n = false. +Proof. + now destruct n. +Qed. -Lemma Zmult_minus_distr_l : forall n m p:Z, p * (n - m) = p * n - p * m. +Lemma testbit_neg_r a n : n<0 -> testbit a n = false. 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. + now destruct n. Qed. -(** ** Simplification of multiplication for non-zero integers *) +Lemma testbit_odd_0 a : testbit (2*a+1) 0 = true. +Proof. + now destruct a as [|a|[a|a|]]. +Qed. -Lemma Zmult_reg_l : forall n m p:Z, p <> Z0 -> p * n = p * m -> n = m. +Lemma testbit_even_0 a : testbit (2*a) 0 = false. 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. + now destruct a. Qed. -Lemma Zmult_reg_r : forall n m p:Z, p <> Z0 -> n * p = m * p -> n = m. +Lemma testbit_odd_succ a n : 0<=n -> + testbit (2*a+1) (succ n) = testbit a n. Proof. - intros x y z Hz. - rewrite (Zmult_comm x z). - rewrite (Zmult_comm y z). - intro; apply Zmult_reg_l with z; assumption. + destruct n as [|n|n]; (now destruct 1) || intros _. + destruct a as [|[a|a|]|[a|a|]]; simpl; trivial. now destruct a. + unfold testbit; simpl. + destruct a as [|a|[a|a|]]; simpl; trivial; + rewrite ?Pos.add_1_r, ?Pos.pred_N_succ; now destruct n. Qed. -(** ** Addition and multiplication by 2 *) +Lemma testbit_even_succ a n : 0<=n -> + testbit (2*a) (succ n) = testbit a n. +Proof. + destruct n as [|n|n]; (now destruct 1) || intros _. + destruct a as [|[a|a|]|[a|a|]]; simpl; trivial. now destruct a. + unfold testbit; simpl. + destruct a as [|a|[a|a|]]; simpl; trivial; + rewrite ?Pos.add_1_r, ?Pos.pred_N_succ; now destruct n. +Qed. -Lemma Zplus_diag_eq_mult_2 : forall n:Z, n + n = n * Zpos 2. +(** Correctness proofs about [Z.shiftr] and [Z.shiftl] *) + +Lemma shiftr_spec_aux a n m : 0<=n -> 0<=m -> + testbit (shiftr a n) m = testbit a (m+n). Proof. - intros x; pattern x at 1 2 in |- *; rewrite <- (Zmult_1_r x); - rewrite <- Zmult_plus_distr_r; reflexivity. + intros Hn Hm. unfold shiftr. + destruct n as [ |n|n]; (now destruct Hn) || clear Hn; simpl. + now rewrite add_0_r. + assert (forall p, to_N (m + pos p) = (to_N m + N.pos p)%N). + destruct m; trivial; now destruct Hm. + assert (forall p, 0 <= m + pos p). + destruct m; easy || now destruct Hm. + destruct a as [ |a|a]. + (* a = 0 *) + replace (Pos.iter n div2 0) with 0 + by (apply Pos.iter_invariant; intros; subst; trivial). + now rewrite 2 testbit_0_l. + (* a > 0 *) + change (pos a) with (of_N (N.pos a)) at 1. + rewrite <- (Pos.iter_swap_gen _ _ _ N.div2) by now intros [|[ | | ]]. + rewrite testbit_Zpos, testbit_of_N', H; trivial. + exact (N.shiftr_spec' (N.pos a) (N.pos n) (to_N m)). + (* a < 0 *) + rewrite <- (Pos.iter_swap_gen _ _ _ Pos.div2_up) by trivial. + rewrite 2 testbit_Zneg, H; trivial. f_equal. + rewrite (Pos.iter_swap_gen _ _ _ _ N.div2) by exact N.pred_div2_up. + exact (N.shiftr_spec' (Pos.pred_N a) (N.pos n) (to_N m)). Qed. -(** ** Multiplication and successor *) +Lemma shiftl_spec_low a n m : m<n -> + testbit (shiftl a n) m = false. +Proof. + intros H. destruct n as [|n|n], m as [|m|m]; try easy; simpl shiftl. + destruct (Pos.succ_pred_or n) as [-> | <-]; + rewrite ?Pos.iter_succ; apply testbit_even_0. + destruct a as [ |a|a]. + (* a = 0 *) + replace (Pos.iter n (mul 2) 0) with 0 + by (apply Pos.iter_invariant; intros; subst; trivial). + apply testbit_0_l. + (* a > 0 *) + rewrite <- (Pos.iter_swap_gen _ _ _ xO) by trivial. + rewrite testbit_Zpos by easy. + exact (N.shiftl_spec_low (N.pos a) (N.pos n) (N.pos m) H). + (* a < 0 *) + rewrite <- (Pos.iter_swap_gen _ _ _ xO) by trivial. + rewrite testbit_Zneg by easy. + now rewrite (N.pos_pred_shiftl_low a (N.pos n)). +Qed. + +Lemma shiftl_spec_high a n m : 0<=m -> n<=m -> + testbit (shiftl a n) m = testbit a (m-n). +Proof. + intros Hm H. + destruct n as [ |n|n]. simpl. now rewrite sub_0_r. + (* n > 0 *) + destruct m as [ |m|m]; try (now destruct H). + assert (0 <= pos m - pos n). + red. now rewrite compare_antisym, <- compare_sub, <- compare_antisym. + assert (EQ : to_N (pos m - pos n) = (N.pos m - N.pos n)%N). + red in H. simpl in H. simpl to_N. + rewrite pos_sub_spec, Pos.compare_antisym. + destruct (Pos.compare_spec n m) as [H'|H'|H']; try (now destruct H). + subst. now rewrite N.sub_diag. + simpl. destruct (Pos.sub_mask_pos' m n H') as (p & -> & <-). + f_equal. now rewrite Pos.add_comm, Pos.add_sub. + destruct a; unfold shiftl. + (* ... a = 0 *) + replace (Pos.iter n (mul 2) 0) with 0 + by (apply Pos.iter_invariant; intros; subst; trivial). + now rewrite 2 testbit_0_l. + (* ... a > 0 *) + rewrite <- (Pos.iter_swap_gen _ _ _ xO) by trivial. + rewrite 2 testbit_Zpos, EQ by easy. + exact (N.shiftl_spec_high' (N.pos p) (N.pos n) (N.pos m) H). + (* ... a < 0 *) + rewrite <- (Pos.iter_swap_gen _ _ _ xO) by trivial. + rewrite 2 testbit_Zneg, EQ by easy. f_equal. + simpl to_N. + rewrite <- N.shiftl_spec_high by easy. + now apply (N.pos_pred_shiftl_high p (N.pos n)). + (* n < 0 *) + unfold sub. simpl. + now apply (shiftr_spec_aux a (pos n) m). +Qed. + +Lemma shiftr_spec a n m : 0<=m -> + testbit (shiftr a n) m = testbit a (m+n). +Proof. + intros Hm. + destruct (leb_spec 0 n). + now apply shiftr_spec_aux. + destruct (leb_spec (-n) m) as [LE|GT]. + unfold shiftr. + rewrite (shiftl_spec_high a (-n) m); trivial. now destruct n. + unfold shiftr. + rewrite (shiftl_spec_low a (-n) m); trivial. + rewrite testbit_neg_r; trivial. + red in GT. rewrite compare_sub in GT. now destruct n. +Qed. + +(** Correctness proofs for bitwise operations *) + +Lemma lor_spec a b n : + testbit (lor a b) n = testbit a n || testbit b n. +Proof. + destruct (leb_spec 0 n) as [Hn|Hn]; [|now rewrite !testbit_neg_r]. + destruct a as [ |a|a], b as [ |b|b]; + rewrite ?testbit_0_l, ?orb_false_r; trivial; unfold lor; + rewrite ?testbit_Zpos, ?testbit_Zneg, ?N.pos_pred_succ by trivial. + now rewrite <- N.lor_spec. + now rewrite N.ldiff_spec, negb_andb, negb_involutive, orb_comm. + now rewrite N.ldiff_spec, negb_andb, negb_involutive. + now rewrite N.land_spec, negb_andb. +Qed. + +Lemma land_spec a b n : + testbit (land a b) n = testbit a n && testbit b n. +Proof. + destruct (leb_spec 0 n) as [Hn|Hn]; [|now rewrite !testbit_neg_r]. + destruct a as [ |a|a], b as [ |b|b]; + rewrite ?testbit_0_l, ?andb_false_r; trivial; unfold land; + rewrite ?testbit_Zpos, ?testbit_Zneg, ?testbit_of_N', ?N.pos_pred_succ + by trivial. + now rewrite <- N.land_spec. + now rewrite N.ldiff_spec. + now rewrite N.ldiff_spec, andb_comm. + now rewrite N.lor_spec, negb_orb. +Qed. + +Lemma ldiff_spec a b n : + testbit (ldiff a b) n = testbit a n && negb (testbit b n). +Proof. + destruct (leb_spec 0 n) as [Hn|Hn]; [|now rewrite !testbit_neg_r]. + destruct a as [ |a|a], b as [ |b|b]; + rewrite ?testbit_0_l, ?andb_true_r; trivial; unfold ldiff; + rewrite ?testbit_Zpos, ?testbit_Zneg, ?testbit_of_N', ?N.pos_pred_succ + by trivial. + now rewrite <- N.ldiff_spec. + now rewrite N.land_spec, negb_involutive. + now rewrite N.lor_spec, negb_orb. + now rewrite N.ldiff_spec, negb_involutive, andb_comm. +Qed. + +Lemma lxor_spec a b n : + testbit (lxor a b) n = xorb (testbit a n) (testbit b n). +Proof. + destruct (leb_spec 0 n) as [Hn|Hn]; [|now rewrite !testbit_neg_r]. + destruct a as [ |a|a], b as [ |b|b]; + rewrite ?testbit_0_l, ?xorb_false_l, ?xorb_false_r; trivial; unfold lxor; + rewrite ?testbit_Zpos, ?testbit_Zneg, ?testbit_of_N', ?N.pos_pred_succ + by trivial. + now rewrite <- N.lxor_spec. + now rewrite N.lxor_spec, negb_xorb_r. + now rewrite N.lxor_spec, negb_xorb_l. + now rewrite N.lxor_spec, xorb_negb_negb. +Qed. -Lemma Zmult_succ_r : forall n m:Z, n * Zsucc m = n * m + n. +(** ** Induction principles based on successor / predecessor *) + +Lemma peano_ind (P : Z -> Prop) : + P 0 -> + (forall x, P x -> P (succ x)) -> + (forall x, P x -> P (pred x)) -> + forall z, P z. 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 H0 Hs Hp z; destruct z. + assumption. + induction p using Pos.peano_ind. + now apply (Hs 0). + rewrite <- Pos.add_1_r. + now apply (Hs (pos p)). + induction p using Pos.peano_ind. + now apply (Hp 0). + rewrite <- Pos.add_1_r. + now apply (Hp (neg p)). Qed. -Lemma Zmult_succ_r_reverse : forall n m:Z, n * m + n = n * Zsucc m. +Lemma bi_induction (P : Z -> Prop) : + Proper (eq ==> iff) P -> + P 0 -> + (forall x, P x <-> P (succ x)) -> + forall z, P z. Proof. - intros; symmetry in |- *; apply Zmult_succ_r. + intros _ H0 Hs. induction z using peano_ind. + assumption. + now apply -> Hs. + apply Hs. now rewrite succ_pred. Qed. -Lemma Zmult_succ_l : forall n m:Z, Zsucc n * m = n * m + m. + +(** * Proofs of morphisms, obvious since eq is Leibniz *) + +Local Obligation Tactic := simpl_relation. +Program Definition succ_wd : Proper (eq==>eq) succ := _. +Program Definition pred_wd : Proper (eq==>eq) pred := _. +Program Definition opp_wd : Proper (eq==>eq) opp := _. +Program Definition add_wd : Proper (eq==>eq==>eq) add := _. +Program Definition sub_wd : Proper (eq==>eq==>eq) sub := _. +Program Definition mul_wd : Proper (eq==>eq==>eq) mul := _. +Program Definition lt_wd : Proper (eq==>eq==>iff) lt := _. +Program Definition div_wd : Proper (eq==>eq==>eq) div := _. +Program Definition mod_wd : Proper (eq==>eq==>eq) modulo := _. +Program Definition quot_wd : Proper (eq==>eq==>eq) quot := _. +Program Definition rem_wd : Proper (eq==>eq==>eq) rem := _. +Program Definition pow_wd : Proper (eq==>eq==>eq) pow := _. +Program Definition testbit_wd : Proper (eq==>eq==>Logic.eq) testbit := _. + +(** The Bind Scope prevents Z to stay associated with abstract_scope. + (TODO FIX) *) + +Include ZProp. Bind Scope Z_scope with Z. +Include UsualMinMaxLogicalProperties <+ UsualMinMaxDecProperties. + +(** In generic statements, the predicates [lt] and [le] have been + favored, whereas [gt] and [ge] don't even exist in the abstract + layers. The use of [gt] and [ge] is hence not recommended. We provide + here the bare minimal results to related them with [lt] and [le]. *) + +Lemma gt_lt_iff n m : n > m <-> m < n. Proof. - intros n m; unfold Zsucc in |- *; rewrite Zmult_plus_distr_l; - rewrite Zmult_1_l; trivial with arith. + unfold lt, gt. now rewrite compare_antisym, CompOpp_iff. Qed. -Lemma Zmult_succ_l_reverse : forall n m:Z, n * m + m = Zsucc n * m. +Lemma gt_lt n m : n > m -> m < n. Proof. - intros; symmetry in |- *; apply Zmult_succ_l. + apply gt_lt_iff. Qed. +Lemma lt_gt n m : n < m -> m > n. +Proof. + apply gt_lt_iff. +Qed. +Lemma ge_le_iff n m : n >= m <-> m <= n. +Proof. + unfold le, ge. now rewrite compare_antisym, CompOpp_iff. +Qed. -(** ** Misc redundant properties *) +Lemma ge_le n m : n >= m -> m <= n. +Proof. + apply ge_le_iff. +Qed. -Lemma Z_eq_mult : forall n m:Z, m = Z0 -> m * n = Z0. +Lemma le_ge n m : n <= m -> m >= n. Proof. - intros x y H; rewrite H; auto with arith. + apply ge_le_iff. Qed. +(** We provide a tactic converting from one style to the other. *) +Ltac swap_greater := rewrite ?gt_lt_iff in *; rewrite ?ge_le_iff in *. -(**********************************************************************) -(** * Relating binary positive numbers and binary integers *) +(** Similarly, the boolean comparisons [ltb] and [leb] are favored + over their dual [gtb] and [geb]. We prove here the equivalence + and a few minimal results. *) -Lemma Zpos_eq : forall p q:positive, p = q -> Zpos p = Zpos q. +Lemma gtb_ltb n m : (n >? m) = (m <? n). Proof. - intros; f_equal; auto. + unfold gtb, ltb. rewrite compare_antisym. now case compare. Qed. -Lemma Zpos_eq_rev : forall p q:positive, Zpos p = Zpos q -> p = q. +Lemma geb_leb n m : (n >=? m) = (m <=? n). Proof. - inversion 1; auto. + unfold geb, leb. rewrite compare_antisym. now case compare. Qed. -Lemma Zpos_eq_iff : forall p q:positive, p = q <-> Zpos p = Zpos q. +Lemma gtb_lt n m : (n >? m) = true <-> m < n. Proof. - split; [apply Zpos_eq|apply Zpos_eq_rev]. + rewrite gtb_ltb. apply ltb_lt. Qed. -Lemma Zpos_xI : forall p:positive, Zpos p~1 = Zpos 2 * Zpos p + Zpos 1. +Lemma geb_le n m : (n >=? m) = true <-> m <= n. Proof. - intro; apply refl_equal. + rewrite geb_leb. apply leb_le. Qed. -Lemma Zpos_xO : forall p:positive, Zpos p~0 = Zpos 2 * Zpos p. +Lemma gtb_spec n m : BoolSpec (m<n) (n<=m) (n >? m). Proof. - intro; apply refl_equal. + rewrite gtb_ltb. apply ltb_spec. Qed. -Lemma Zneg_xI : forall p:positive, Zneg p~1 = Zpos 2 * Zneg p - Zpos 1. +Lemma geb_spec n m : BoolSpec (m<=n) (n<m) (n >=? m). Proof. - intro; apply refl_equal. + rewrite geb_leb. apply leb_spec. Qed. -Lemma Zneg_xO : forall p:positive, Zneg p~0 = Zpos 2 * Zneg p. +(** TODO : to add in Numbers ? *) + +Lemma add_reg_l n m p : n + m = n + p -> m = p. Proof. - reflexivity. + exact (proj1 (add_cancel_l m p n)). Qed. -Lemma Zpos_plus_distr : forall p q:positive, Zpos (p + q) = Zpos p + Zpos q. +Lemma mul_reg_l n m p : p <> 0 -> p * n = p * m -> n = m. Proof. - intros p p'; destruct p; - [ destruct p' as [p0| p0| ] - | destruct p' as [p0| p0| ] - | destruct p' as [p| p| ] ]; reflexivity. + exact (fun Hp => proj1 (mul_cancel_l n m p Hp)). Qed. -Lemma Zneg_plus_distr : forall p q:positive, Zneg (p + q) = Zneg p + Zneg q. +Lemma mul_reg_r n m p : p <> 0 -> n * p = m * p -> n = m. Proof. - intros p p'; destruct p; - [ destruct p' as [p0| p0| ] - | destruct p' as [p0| p0| ] - | destruct p' as [p| p| ] ]; reflexivity. + exact (fun Hp => proj1 (mul_cancel_r n m p Hp)). Qed. -(**********************************************************************) -(** * Order relations *) +Lemma opp_eq_mul_m1 n : - n = n * -1. +Proof. + rewrite mul_comm. now destruct n. +Qed. -Definition Zlt (x y:Z) := (x ?= y) = Lt. -Definition Zgt (x y:Z) := (x ?= y) = Gt. -Definition Zle (x y:Z) := (x ?= y) <> Gt. -Definition Zge (x y:Z) := (x ?= y) <> Lt. -Definition Zne (x y:Z) := x <> y. +Lemma add_diag n : n + n = 2 * n. +Proof. + change 2 with (1+1). now rewrite mul_add_distr_r, !mul_1_l. +Qed. + +(** * Comparison and opposite *) -Infix "<=" := Zle : Z_scope. -Infix "<" := Zlt : Z_scope. -Infix ">=" := Zge : Z_scope. -Infix ">" := Zgt : Z_scope. +Lemma compare_opp n m : (- n ?= - m) = (m ?= n). +Proof. + destruct n, m; simpl; trivial; intros; now rewrite <- Pos.compare_antisym. +Qed. +(** * Comparison and addition *) + +Lemma add_compare_mono_l n m p : (n + m ?= n + p) = (m ?= p). +Proof. + rewrite (compare_sub m p), compare_sub. f_equal. + unfold sub. rewrite opp_add_distr, (add_comm n m), add_assoc. + f_equal. now rewrite <- add_assoc, add_opp_diag_r, add_0_r. +Qed. + +End Z. + +(** Re-export Notations *) + +Infix "+" := Z.add : Z_scope. +Notation "- x" := (Z.opp x) : Z_scope. +Infix "-" := Z.sub : Z_scope. +Infix "*" := Z.mul : Z_scope. +Infix "^" := Z.pow : Z_scope. +Infix "/" := Z.div : Z_scope. +Infix "mod" := Z.modulo (at level 40, no associativity) : Z_scope. +Infix "÷" := Z.quot (at level 40, left associativity) : Z_scope. +Infix "?=" := Z.compare (at level 70, no associativity) : Z_scope. +Infix "=?" := Z.eqb (at level 70, no associativity) : Z_scope. +Infix "<=?" := Z.leb (at level 70, no associativity) : Z_scope. +Infix "<?" := Z.ltb (at level 70, no associativity) : Z_scope. +Infix ">=?" := Z.geb (at level 70, no associativity) : Z_scope. +Infix ">?" := Z.gtb (at level 70, no associativity) : Z_scope. +Notation "( x | y )" := (Z.divide x y) (at level 0) : Z_scope. +Infix "<=" := Z.le : Z_scope. +Infix "<" := Z.lt : Z_scope. +Infix ">=" := Z.ge : Z_scope. +Infix ">" := Z.gt : Z_scope. Notation "x <= y <= z" := (x <= y /\ y <= z) : Z_scope. Notation "x <= y < z" := (x <= y /\ y < z) : Z_scope. Notation "x < y < z" := (x < y /\ y < z) : Z_scope. Notation "x < y <= z" := (x < y /\ y <= z) : Z_scope. -(**********************************************************************) -(** * 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 - end. - -Definition Zabs (z:Z) : Z := - match z with - | Z0 => Z0 - | Zpos p => Zpos p - | Zneg p => Zpos p - end. - -(**********************************************************************) -(** * From [nat] to [Z] *) - -Definition Z_of_nat (x:nat) := - match x with - | 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 - end. - -Definition Z_of_N (x:N) := - match x with - | N0 => Z0 - | Npos p => Zpos p - end. +(** Conversions from / to positive numbers *) + +Module Pos2Z. + +Lemma id p : Z.to_pos (Z.pos p) = p. +Proof. reflexivity. Qed. + +Lemma inj p q : Z.pos p = Z.pos q -> p = q. +Proof. now injection 1. Qed. + +Lemma inj_iff p q : Z.pos p = Z.pos q <-> p = q. +Proof. split. apply inj. intros; now f_equal. Qed. + +Lemma is_pos p : 0 < Z.pos p. +Proof. reflexivity. Qed. + +Lemma is_nonneg p : 0 <= Z.pos p. +Proof. easy. Qed. + +Lemma inj_1 : Z.pos 1 = 1. +Proof. reflexivity. Qed. + +Lemma inj_xO p : Z.pos p~0 = 2 * Z.pos p. +Proof. reflexivity. Qed. + +Lemma inj_xI p : Z.pos p~1 = 2 * Z.pos p + 1. +Proof. reflexivity. Qed. + +Lemma inj_succ p : Z.pos (Pos.succ p) = Z.succ (Z.pos p). +Proof. simpl. now rewrite Pos.add_1_r. Qed. + +Lemma inj_add p q : Z.pos (p+q) = Z.pos p + Z.pos q. +Proof. reflexivity. Qed. + +Lemma inj_sub p q : (p < q)%positive -> + Z.pos (q-p) = Z.pos q - Z.pos p. +Proof. intros. simpl. now rewrite Z.pos_sub_gt. Qed. + +Lemma inj_sub_max p q : Z.pos (p - q) = Z.max 1 (Z.pos p - Z.pos q). +Proof. + simpl. rewrite Z.pos_sub_spec. case Pos.compare_spec; intros. + - subst; now rewrite Pos.sub_diag. + - now rewrite Pos.sub_lt. + - now destruct (p-q)%positive. +Qed. + +Lemma inj_pred p : p <> 1%positive -> + Z.pos (Pos.pred p) = Z.pred (Z.pos p). +Proof. destruct p; easy || now destruct 1. Qed. + +Lemma inj_mul p q : Z.pos (p*q) = Z.pos p * Z.pos q. +Proof. reflexivity. Qed. + +Lemma inj_pow_pos p q : Z.pos (p^q) = Z.pow_pos (Z.pos p) q. +Proof. now apply Pos.iter_swap_gen. Qed. + +Lemma inj_pow p q : Z.pos (p^q) = (Z.pos p)^(Z.pos q). +Proof. apply inj_pow_pos. Qed. + +Lemma inj_square p : Z.pos (Pos.square p) = Z.square (Z.pos p). +Proof. reflexivity. Qed. + +Lemma inj_compare p q : (p ?= q)%positive = (Z.pos p ?= Z.pos q). +Proof. reflexivity. Qed. + +Lemma inj_leb p q : (p <=? q)%positive = (Z.pos p <=? Z.pos q). +Proof. reflexivity. Qed. + +Lemma inj_ltb p q : (p <? q)%positive = (Z.pos p <? Z.pos q). +Proof. reflexivity. Qed. + +Lemma inj_eqb p q : (p =? q)%positive = (Z.pos p =? Z.pos q). +Proof. reflexivity. Qed. + +Lemma inj_max p q : Z.pos (Pos.max p q) = Z.max (Z.pos p) (Z.pos q). +Proof. + unfold Z.max, Pos.max. rewrite inj_compare. now case Z.compare_spec. +Qed. + +Lemma inj_min p q : Z.pos (Pos.min p q) = Z.min (Z.pos p) (Z.pos q). +Proof. + unfold Z.min, Pos.min. rewrite inj_compare. now case Z.compare_spec. +Qed. + +Lemma inj_sqrt p : Z.pos (Pos.sqrt p) = Z.sqrt (Z.pos p). +Proof. reflexivity. Qed. + +Lemma inj_gcd p q : Z.pos (Pos.gcd p q) = Z.gcd (Z.pos p) (Z.pos q). +Proof. reflexivity. Qed. + +Definition inj_divide p q : (Z.pos p|Z.pos q) <-> (p|q)%positive. +Proof. apply Z.Private_BootStrap.divide_Zpos. Qed. + +Lemma inj_testbit a n : 0<=n -> + Z.testbit (Z.pos a) n = N.testbit (N.pos a) (Z.to_N n). +Proof. apply Z.Private_BootStrap.testbit_Zpos. Qed. + +(** Some results concerning Z.neg *) + +Lemma inj_neg p q : Z.neg p = Z.neg q -> p = q. +Proof. now injection 1. Qed. + +Lemma inj_neg_iff p q : Z.neg p = Z.neg q <-> p = q. +Proof. split. apply inj_neg. intros; now f_equal. Qed. + +Lemma neg_is_neg p : Z.neg p < 0. +Proof. reflexivity. Qed. + +Lemma neg_is_nonpos p : Z.neg p <= 0. +Proof. easy. Qed. + +Lemma neg_xO p : Z.neg p~0 = 2 * Z.neg p. +Proof. reflexivity. Qed. + +Lemma neg_xI p : Z.neg p~1 = 2 * Z.neg p - 1. +Proof. reflexivity. Qed. + +Lemma opp_neg p : - Z.neg p = Z.pos p. +Proof. reflexivity. Qed. + +Lemma opp_pos p : - Z.pos p = Z.neg p. +Proof. reflexivity. Qed. + +Lemma add_neg_neg p q : Z.neg p + Z.neg q = Z.neg (p+q). +Proof. reflexivity. Qed. + +Lemma add_pos_neg p q : Z.pos p + Z.neg q = Z.pos_sub p q. +Proof. reflexivity. Qed. + +Lemma add_neg_pos p q : Z.neg p + Z.pos q = Z.pos_sub q p. +Proof. reflexivity. Qed. + +Lemma divide_pos_neg_r n p : (n|Z.pos p) <-> (n|Z.neg p). +Proof. apply Z.Private_BootStrap.divide_Zpos_Zneg_r. Qed. + +Lemma divide_pos_neg_l n p : (Z.pos p|n) <-> (Z.neg p|n). +Proof. apply Z.Private_BootStrap.divide_Zpos_Zneg_l. Qed. + +Lemma testbit_neg a n : 0<=n -> + Z.testbit (Z.neg a) n = negb (N.testbit (Pos.pred_N a) (Z.to_N n)). +Proof. apply Z.Private_BootStrap.testbit_Zneg. Qed. + +End Pos2Z. + +Module Z2Pos. + +Lemma id x : 0 < x -> Z.pos (Z.to_pos x) = x. +Proof. now destruct x. Qed. + +Lemma inj x y : 0 < x -> 0 < y -> Z.to_pos x = Z.to_pos y -> x = y. +Proof. + destruct x; simpl; try easy. intros _ H ->. now apply id. +Qed. + +Lemma inj_iff x y : 0 < x -> 0 < y -> (Z.to_pos x = Z.to_pos y <-> x = y). +Proof. split. now apply inj. intros; now f_equal. Qed. + +Lemma to_pos_nonpos x : x <= 0 -> Z.to_pos x = 1%positive. +Proof. destruct x; trivial. now destruct 1. Qed. + +Lemma inj_1 : Z.to_pos 1 = 1%positive. +Proof. reflexivity. Qed. + +Lemma inj_double x : 0 < x -> + Z.to_pos (Z.double x) = (Z.to_pos x)~0%positive. +Proof. now destruct x. Qed. + +Lemma inj_succ_double x : 0 < x -> + Z.to_pos (Z.succ_double x) = (Z.to_pos x)~1%positive. +Proof. now destruct x. Qed. + +Lemma inj_succ x : 0 < x -> Z.to_pos (Z.succ x) = Pos.succ (Z.to_pos x). +Proof. + destruct x; try easy. simpl. now rewrite Pos.add_1_r. +Qed. + +Lemma inj_add x y : 0 < x -> 0 < y -> + Z.to_pos (x+y) = (Z.to_pos x + Z.to_pos y)%positive. +Proof. destruct x; easy || now destruct y. Qed. + +Lemma inj_sub x y : 0 < x < y -> + Z.to_pos (y-x) = (Z.to_pos y - Z.to_pos x)%positive. +Proof. + destruct x; try easy. destruct y; try easy. simpl. + intros. now rewrite Z.pos_sub_gt. +Qed. + +Lemma inj_pred x : 1 < x -> Z.to_pos (Z.pred x) = Pos.pred (Z.to_pos x). +Proof. now destruct x as [|[x|x|]|]. Qed. + +Lemma inj_mul x y : 0 < x -> 0 < y -> + Z.to_pos (x*y) = (Z.to_pos x * Z.to_pos y)%positive. +Proof. destruct x; easy || now destruct y. Qed. + +Lemma inj_pow x y : 0 < x -> 0 < y -> + Z.to_pos (x^y) = (Z.to_pos x ^ Z.to_pos y)%positive. +Proof. + intros. apply Pos2Z.inj. rewrite Pos2Z.inj_pow, !id; trivial. + apply Z.pow_pos_nonneg. trivial. now apply Z.lt_le_incl. +Qed. + +Lemma inj_pow_pos x p : 0 < x -> + Z.to_pos (Z.pow_pos x p) = ((Z.to_pos x)^p)%positive. +Proof. intros. now apply (inj_pow x (Z.pos p)). Qed. + +Lemma inj_compare x y : 0 < x -> 0 < y -> + (x ?= y) = (Z.to_pos x ?= Z.to_pos y)%positive. +Proof. destruct x; easy || now destruct y. Qed. + +Lemma inj_leb x y : 0 < x -> 0 < y -> + (x <=? y) = (Z.to_pos x <=? Z.to_pos y)%positive. +Proof. destruct x; easy || now destruct y. Qed. + +Lemma inj_ltb x y : 0 < x -> 0 < y -> + (x <? y) = (Z.to_pos x <? Z.to_pos y)%positive. +Proof. destruct x; easy || now destruct y. Qed. + +Lemma inj_eqb x y : 0 < x -> 0 < y -> + (x =? y) = (Z.to_pos x =? Z.to_pos y)%positive. +Proof. destruct x; easy || now destruct y. Qed. + +Lemma inj_max x y : + Z.to_pos (Z.max x y) = Pos.max (Z.to_pos x) (Z.to_pos y). +Proof. + destruct x; simpl; try rewrite Pos.max_1_l. + - now destruct y. + - destruct y; simpl; now rewrite ?Pos.max_1_r, <- ?Pos2Z.inj_max. + - destruct y; simpl; rewrite ?Pos.max_1_r; trivial. + apply to_pos_nonpos. now apply Z.max_lub. +Qed. + +Lemma inj_min x y : + Z.to_pos (Z.min x y) = Pos.min (Z.to_pos x) (Z.to_pos y). +Proof. + destruct x; simpl; try rewrite Pos.min_1_l. + - now destruct y. + - destruct y; simpl; now rewrite ?Pos.min_1_r, <- ?Pos2Z.inj_min. + - destruct y; simpl; rewrite ?Pos.min_1_r; trivial. + apply to_pos_nonpos. apply Z.min_le_iff. now left. +Qed. + +Lemma inj_sqrt x : Z.to_pos (Z.sqrt x) = Pos.sqrt (Z.to_pos x). +Proof. now destruct x. Qed. + +Lemma inj_gcd x y : 0 < x -> 0 < y -> + Z.to_pos (Z.gcd x y) = Pos.gcd (Z.to_pos x) (Z.to_pos y). +Proof. destruct x; easy || now destruct y. Qed. + +End Z2Pos. + +(** Compatibility Notations *) + +Notation Zdouble_plus_one := Z.succ_double (compat "8.3"). +Notation Zdouble_minus_one := Z.pred_double (compat "8.3"). +Notation Zdouble := Z.double (compat "8.3"). +Notation ZPminus := Z.pos_sub (compat "8.3"). +Notation Zsucc' := Z.succ (compat "8.3"). +Notation Zpred' := Z.pred (compat "8.3"). +Notation Zplus' := Z.add (compat "8.3"). +Notation Zplus := Z.add (compat "8.3"). (* Slightly incompatible *) +Notation Zopp := Z.opp (compat "8.3"). +Notation Zsucc := Z.succ (compat "8.3"). +Notation Zpred := Z.pred (compat "8.3"). +Notation Zminus := Z.sub (compat "8.3"). +Notation Zmult := Z.mul (compat "8.3"). +Notation Zcompare := Z.compare (compat "8.3"). +Notation Zsgn := Z.sgn (compat "8.3"). +Notation Zle := Z.le (compat "8.3"). +Notation Zge := Z.ge (compat "8.3"). +Notation Zlt := Z.lt (compat "8.3"). +Notation Zgt := Z.gt (compat "8.3"). +Notation Zmax := Z.max (compat "8.3"). +Notation Zmin := Z.min (compat "8.3"). +Notation Zabs := Z.abs (compat "8.3"). +Notation Zabs_nat := Z.abs_nat (compat "8.3"). +Notation Zabs_N := Z.abs_N (compat "8.3"). +Notation Z_of_nat := Z.of_nat (compat "8.3"). +Notation Z_of_N := Z.of_N (compat "8.3"). + +Notation Zind := Z.peano_ind (compat "8.3"). +Notation Zopp_0 := Z.opp_0 (compat "8.3"). +Notation Zopp_involutive := Z.opp_involutive (compat "8.3"). +Notation Zopp_inj := Z.opp_inj (compat "8.3"). +Notation Zplus_0_l := Z.add_0_l (compat "8.3"). +Notation Zplus_0_r := Z.add_0_r (compat "8.3"). +Notation Zplus_comm := Z.add_comm (compat "8.3"). +Notation Zopp_plus_distr := Z.opp_add_distr (compat "8.3"). +Notation Zopp_succ := Z.opp_succ (compat "8.3"). +Notation Zplus_opp_r := Z.add_opp_diag_r (compat "8.3"). +Notation Zplus_opp_l := Z.add_opp_diag_l (compat "8.3"). +Notation Zplus_assoc := Z.add_assoc (compat "8.3"). +Notation Zplus_permute := Z.add_shuffle3 (compat "8.3"). +Notation Zplus_reg_l := Z.add_reg_l (compat "8.3"). +Notation Zplus_succ_l := Z.add_succ_l (compat "8.3"). +Notation Zplus_succ_comm := Z.add_succ_comm (compat "8.3"). +Notation Zsucc_discr := Z.neq_succ_diag_r (compat "8.3"). +Notation Zsucc_inj := Z.succ_inj (compat "8.3"). +Notation Zsucc'_inj := Z.succ_inj (compat "8.3"). +Notation Zsucc'_pred' := Z.succ_pred (compat "8.3"). +Notation Zpred'_succ' := Z.pred_succ (compat "8.3"). +Notation Zpred'_inj := Z.pred_inj (compat "8.3"). +Notation Zsucc'_discr := Z.neq_succ_diag_r (compat "8.3"). +Notation Zminus_0_r := Z.sub_0_r (compat "8.3"). +Notation Zminus_diag := Z.sub_diag (compat "8.3"). +Notation Zminus_plus_distr := Z.sub_add_distr (compat "8.3"). +Notation Zminus_succ_r := Z.sub_succ_r (compat "8.3"). +Notation Zminus_plus := Z.add_simpl_l (compat "8.3"). +Notation Zmult_0_l := Z.mul_0_l (compat "8.3"). +Notation Zmult_0_r := Z.mul_0_r (compat "8.3"). +Notation Zmult_1_l := Z.mul_1_l (compat "8.3"). +Notation Zmult_1_r := Z.mul_1_r (compat "8.3"). +Notation Zmult_comm := Z.mul_comm (compat "8.3"). +Notation Zmult_assoc := Z.mul_assoc (compat "8.3"). +Notation Zmult_permute := Z.mul_shuffle3 (compat "8.3"). +Notation Zmult_1_inversion_l := Z.mul_eq_1 (compat "8.3"). +Notation Zdouble_mult := Z.double_spec (compat "8.3"). +Notation Zdouble_plus_one_mult := Z.succ_double_spec (compat "8.3"). +Notation Zopp_mult_distr_l_reverse := Z.mul_opp_l (compat "8.3"). +Notation Zmult_opp_opp := Z.mul_opp_opp (compat "8.3"). +Notation Zmult_opp_comm := Z.mul_opp_comm (compat "8.3"). +Notation Zopp_eq_mult_neg_1 := Z.opp_eq_mul_m1 (compat "8.3"). +Notation Zmult_plus_distr_r := Z.mul_add_distr_l (compat "8.3"). +Notation Zmult_plus_distr_l := Z.mul_add_distr_r (compat "8.3"). +Notation Zmult_minus_distr_r := Z.mul_sub_distr_r (compat "8.3"). +Notation Zmult_reg_l := Z.mul_reg_l (compat "8.3"). +Notation Zmult_reg_r := Z.mul_reg_r (compat "8.3"). +Notation Zmult_succ_l := Z.mul_succ_l (compat "8.3"). +Notation Zmult_succ_r := Z.mul_succ_r (compat "8.3"). + +Notation Zpos_xI := Pos2Z.inj_xI (compat "8.3"). +Notation Zpos_xO := Pos2Z.inj_xO (compat "8.3"). +Notation Zneg_xI := Pos2Z.neg_xI (compat "8.3"). +Notation Zneg_xO := Pos2Z.neg_xO (compat "8.3"). +Notation Zopp_neg := Pos2Z.opp_neg (compat "8.3"). +Notation Zpos_succ_morphism := Pos2Z.inj_succ (compat "8.3"). +Notation Zpos_mult_morphism := Pos2Z.inj_mul (compat "8.3"). +Notation Zpos_minus_morphism := Pos2Z.inj_sub (compat "8.3"). +Notation Zpos_eq_rev := Pos2Z.inj (compat "8.3"). +Notation Zpos_plus_distr := Pos2Z.inj_add (compat "8.3"). +Notation Zneg_plus_distr := Pos2Z.add_neg_neg (compat "8.3"). + +Notation Z := Z (only parsing). +Notation Z_rect := Z_rect (only parsing). +Notation Z_rec := Z_rec (only parsing). +Notation Z_ind := Z_ind (only parsing). +Notation Z0 := Z0 (only parsing). +Notation Zpos := Zpos (only parsing). +Notation Zneg := Zneg (only parsing). + +(** Compatibility lemmas. These could be notations, + but scope information would be lost. +*) + +Notation SYM1 lem := (fun n => eq_sym (lem n)). +Notation SYM2 lem := (fun n m => eq_sym (lem n m)). +Notation SYM3 lem := (fun n m p => eq_sym (lem n m p)). + +Lemma Zplus_assoc_reverse : forall n m p, n+m+p = n+(m+p). +Proof (SYM3 Z.add_assoc). +Lemma Zplus_succ_r_reverse : forall n m, Z.succ (n+m) = n+Z.succ m. +Proof (SYM2 Z.add_succ_r). +Notation Zplus_succ_r := Zplus_succ_r_reverse (only parsing). +Lemma Zplus_0_r_reverse : forall n, n = n + 0. +Proof (SYM1 Z.add_0_r). +Lemma Zplus_eq_compat : forall n m p q, n=m -> p=q -> n+p=m+q. +Proof (f_equal2 Z.add). +Lemma Zsucc_pred : forall n, n = Z.succ (Z.pred n). +Proof (SYM1 Z.succ_pred). +Lemma Zpred_succ : forall n, n = Z.pred (Z.succ n). +Proof (SYM1 Z.pred_succ). +Lemma Zsucc_eq_compat : forall n m, n = m -> Z.succ n = Z.succ m. +Proof (f_equal Z.succ). +Lemma Zminus_0_l_reverse : forall n, n = n - 0. +Proof (SYM1 Z.sub_0_r). +Lemma Zminus_diag_reverse : forall n, 0 = n-n. +Proof (SYM1 Z.sub_diag). +Lemma Zminus_succ_l : forall n m, Z.succ (n - m) = Z.succ n - m. +Proof (SYM2 Z.sub_succ_l). +Lemma Zplus_minus_eq : forall n m p, n = m + p -> p = n - m. +Proof. intros. now apply Z.add_move_l. Qed. +Lemma Zplus_minus : forall n m, n + (m - n) = m. +Proof (fun n m => eq_trans (Z.add_comm n (m-n)) (Z.sub_add n m)). +Lemma Zminus_plus_simpl_l : forall n m p, p + n - (p + m) = n - m. +Proof (fun n m p => Z.add_add_simpl_l_l p n m). +Lemma Zminus_plus_simpl_l_reverse : forall n m p, n - m = p + n - (p + m). +Proof (SYM3 Zminus_plus_simpl_l). +Lemma Zminus_plus_simpl_r : forall n m p, n + p - (m + p) = n - m. +Proof (fun n m p => Z.add_add_simpl_r_r n p m). +Lemma Zeq_minus : forall n m, n = m -> n - m = 0. +Proof (fun n m => proj2 (Z.sub_move_0_r n m)). +Lemma Zminus_eq : forall n m, n - m = 0 -> n = m. +Proof (fun n m => proj1 (Z.sub_move_0_r n m)). +Lemma Zmult_0_r_reverse : forall n, 0 = n * 0. +Proof (SYM1 Z.mul_0_r). +Lemma Zmult_assoc_reverse : forall n m p, n * m * p = n * (m * p). +Proof (SYM3 Z.mul_assoc). +Lemma Zmult_integral : forall n m, n * m = 0 -> n = 0 \/ m = 0. +Proof (fun n m => proj1 (Z.mul_eq_0 n m)). +Lemma Zmult_integral_l : forall n m, n <> 0 -> m * n = 0 -> m = 0. +Proof (fun n m H H' => Z.mul_eq_0_l m n H' H). +Lemma Zopp_mult_distr_l : forall n m, - (n * m) = - n * m. +Proof (SYM2 Z.mul_opp_l). +Lemma Zopp_mult_distr_r : forall n m, - (n * m) = n * - m. +Proof (SYM2 Z.mul_opp_r). +Lemma Zmult_minus_distr_l : forall n m p, p * (n - m) = p * n - p * m. +Proof (fun n m p => Z.mul_sub_distr_l p n m). +Lemma Zmult_succ_r_reverse : forall n m, n * m + n = n * Z.succ m. +Proof (SYM2 Z.mul_succ_r). +Lemma Zmult_succ_l_reverse : forall n m, n * m + m = Z.succ n * m. +Proof (SYM2 Z.mul_succ_l). +Lemma Zpos_eq : forall p q, p = q -> Z.pos p = Z.pos q. +Proof. congruence. Qed. +Lemma Zpos_eq_iff : forall p q, p = q <-> Z.pos p = Z.pos q. +Proof (fun p q => iff_sym (Pos2Z.inj_iff p q)). + +Hint Immediate Zsucc_pred: zarith. + +(* Not kept : +Zplus_0_simpl_l +Zplus_0_simpl_l_reverse +Zplus_opp_expand +Zsucc_inj_contrapositive +Zsucc_succ' +Zpred_pred' +*) + +(* No compat notation for : +weak_assoc (now Z.add_assoc_pos) +weak_Zmult_plus_distr_r (now Z.mul_add_distr_pos) +*) + +(** Obsolete stuff *) + +Definition Zne (x y:Z) := x <> y. (* TODO : to remove someday ? *) + +Ltac elim_compare com1 com2 := + case (Dcompare (com1 ?= com2)%Z); + [ idtac | let x := fresh "H" in + (intro x; case x; clear x) ]. + +Lemma ZL0 : 2%nat = (1 + 1)%nat. +Proof. + reflexivity. +Qed. + +Lemma Zplus_diag_eq_mult_2 n : n + n = n * 2. +Proof. + rewrite Z.mul_comm. apply Z.add_diag. +Qed. + +Lemma Z_eq_mult n m : m = 0 -> m * n = 0. +Proof. + intros; now subst. +Qed. diff --git a/theories/ZArith/BinIntDef.v b/theories/ZArith/BinIntDef.v new file mode 100644 index 00000000..958ce2ef --- /dev/null +++ b/theories/ZArith/BinIntDef.v @@ -0,0 +1,619 @@ +(* -*- coding: utf-8 -*- *) +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +Require Export BinNums. +Require Import BinPos BinNat. + +Local Open Scope Z_scope. + +(***********************************************************) +(** * Binary Integers, Definitions of Operations *) +(***********************************************************) + +(** Initial author: Pierre Crégut, CNET, Lannion, France *) + +Module Z. + +Definition t := Z. + +(** ** Nicer names [Z.pos] and [Z.neg] for contructors *) + +Notation pos := Zpos. +Notation neg := Zneg. + +(** ** Constants *) + +Definition zero := 0. +Definition one := 1. +Definition two := 2. + +(** ** Doubling and variants *) + +Definition double x := + match x with + | 0 => 0 + | pos p => pos p~0 + | neg p => neg p~0 + end. + +Definition succ_double x := + match x with + | 0 => 1 + | pos p => pos p~1 + | neg p => neg (Pos.pred_double p) + end. + +Definition pred_double x := + match x with + | 0 => -1 + | neg p => neg p~1 + | pos p => pos (Pos.pred_double p) + end. + +(** ** Subtraction of positive into Z *) + +Fixpoint pos_sub (x y:positive) {struct y} : Z := + match x, y with + | p~1, q~1 => double (pos_sub p q) + | p~1, q~0 => succ_double (pos_sub p q) + | p~1, 1 => pos p~0 + | p~0, q~1 => pred_double (pos_sub p q) + | p~0, q~0 => double (pos_sub p q) + | p~0, 1 => pos (Pos.pred_double p) + | 1, q~1 => neg q~0 + | 1, q~0 => neg (Pos.pred_double q) + | 1, 1 => Z0 + end%positive. + +(** ** Addition *) + +Definition add x y := + match x, y with + | 0, y => y + | x, 0 => x + | pos x', pos y' => pos (x' + y') + | pos x', neg y' => pos_sub x' y' + | neg x', pos y' => pos_sub y' x' + | neg x', neg y' => neg (x' + y') + end. + +Infix "+" := add : Z_scope. + +(** ** Opposite *) + +Definition opp x := + match x with + | 0 => 0 + | pos x => neg x + | neg x => pos x + end. + +Notation "- x" := (opp x) : Z_scope. + +(** ** Successor *) + +Definition succ x := x + 1. + +(** ** Predecessor *) + +Definition pred x := x + -1. + +(** ** Subtraction *) + +Definition sub m n := m + -n. + +Infix "-" := sub : Z_scope. + +(** ** Multiplication *) + +Definition mul x y := + match x, y with + | 0, _ => 0 + | _, 0 => 0 + | pos x', pos y' => pos (x' * y') + | pos x', neg y' => neg (x' * y') + | neg x', pos y' => neg (x' * y') + | neg x', neg y' => pos (x' * y') + end. + +Infix "*" := mul : Z_scope. + +(** ** Power function *) + +Definition pow_pos (z:Z) (n:positive) := Pos.iter n (mul z) 1. + +Definition pow x y := + match y with + | pos p => pow_pos x p + | 0 => 1 + | neg _ => 0 + end. + +Infix "^" := pow : Z_scope. + +(** ** Square *) + +Definition square x := + match x with + | 0 => 0 + | pos p => pos (Pos.square p) + | neg p => pos (Pos.square p) + end. + +(** ** Comparison *) + +Definition compare x y := + match x, y with + | 0, 0 => Eq + | 0, pos y' => Lt + | 0, neg y' => Gt + | pos x', 0 => Gt + | pos x', pos y' => (x' ?= y')%positive + | pos x', neg y' => Gt + | neg x', 0 => Lt + | neg x', pos y' => Lt + | neg x', neg y' => CompOpp ((x' ?= y')%positive) + end. + +Infix "?=" := compare (at level 70, no associativity) : Z_scope. + +(** ** Sign function *) + +Definition sgn z := + match z with + | 0 => 0 + | pos p => 1 + | neg p => -1 + end. + +(** Boolean equality and comparisons *) + +Definition leb x y := + match x ?= y with + | Gt => false + | _ => true + end. + +Definition ltb x y := + match x ?= y with + | Lt => true + | _ => false + end. + +(** Nota: [geb] and [gtb] are provided for compatibility, + but [leb] and [ltb] should rather be used instead, since + more results will be available on them. *) + +Definition geb x y := + match x ?= y with + | Lt => false + | _ => true + end. + +Definition gtb x y := + match x ?= y with + | Gt => true + | _ => false + end. + +Fixpoint eqb x y := + match x, y with + | 0, 0 => true + | pos p, pos q => Pos.eqb p q + | neg p, neg q => Pos.eqb p q + | _, _ => false + end. + +Infix "=?" := eqb (at level 70, no associativity) : Z_scope. +Infix "<=?" := leb (at level 70, no associativity) : Z_scope. +Infix "<?" := ltb (at level 70, no associativity) : Z_scope. +Infix ">=?" := geb (at level 70, no associativity) : Z_scope. +Infix ">?" := gtb (at level 70, no associativity) : Z_scope. + +(** ** Minimum and maximum *) + +Definition max n m := + match n ?= m with + | Eq | Gt => n + | Lt => m + end. + +Definition min n m := + match n ?= m with + | Eq | Lt => n + | Gt => m + end. + +(** ** Absolute value *) + +Definition abs z := + match z with + | 0 => 0 + | pos p => pos p + | neg p => pos p + end. + +(** ** Conversions *) + +(** From [Z] to [nat] via absolute value *) + +Definition abs_nat (z:Z) : nat := + match z with + | 0 => 0%nat + | pos p => Pos.to_nat p + | neg p => Pos.to_nat p + end. + +(** From [Z] to [N] via absolute value *) + +Definition abs_N (z:Z) : N := + match z with + | 0 => 0%N + | pos p => N.pos p + | neg p => N.pos p + end. + +(** From [Z] to [nat] by rounding negative numbers to 0 *) + +Definition to_nat (z:Z) : nat := + match z with + | pos p => Pos.to_nat p + | _ => O + end. + +(** From [Z] to [N] by rounding negative numbers to 0 *) + +Definition to_N (z:Z) : N := + match z with + | pos p => N.pos p + | _ => 0%N + end. + +(** From [nat] to [Z] *) + +Definition of_nat (n:nat) : Z := + match n with + | O => 0 + | S n => pos (Pos.of_succ_nat n) + end. + +(** From [N] to [Z] *) + +Definition of_N (n:N) : Z := + match n with + | 0%N => 0 + | N.pos p => pos p + end. + +(** From [Z] to [positive] by rounding nonpositive numbers to 1 *) + +Definition to_pos (z:Z) : positive := + match z with + | pos p => p + | _ => 1%positive + end. + +(** ** Iteration of a function + + By convention, iterating a negative number of times is identity. +*) + +Definition iter (n:Z) {A} (f:A -> A) (x:A) := + match n with + | pos p => Pos.iter p f x + | _ => x + end. + +(** ** Euclidean divisions for binary integers *) + +(** Concerning the many possible variants of integer divisions, + see the headers of the generic files [ZDivFloor], [ZDivTrunc], + [ZDivEucl], and the article by R. Boute mentioned there. + We provide here two flavours, Floor and Trunc, while + the Euclid convention can be found in file Zeuclid.v + For non-zero b, they all satisfy [a = b*(a/b) + (a mod b)] + and [ |a mod b| < |b| ], but the sign of the modulo will differ + when [a<0] and/or [b<0]. +*) + +(** ** Floor division *) + +(** [div_eucl] provides a Truncated-Toward-Bottom (a.k.a Floor) + Euclidean division. Its projections are named [div] (noted "/") + and [modulo] (noted with an infix "mod"). + These functions correspond to the `div` and `mod` of Haskell. + This is the historical convention of Coq. + + The main properties of this convention are : + - we have [sgn (a mod b) = sgn (b)] + - [div a b] is the greatest integer smaller or equal to the exact + fraction [a/b]. + - there is no easy sign rule. + + In addition, note that we arbitrary take [a/0 = 0] and [a mod 0 = 0]. +*) + +(** First, a division for positive numbers. Even if the second + argument is a Z, the answer is arbitrary is it isn't a Zpos. *) + +Fixpoint pos_div_eucl (a:positive) (b:Z) : Z * Z := + match a with + | xH => if 2 <=? b then (0, 1) else (1, 0) + | xO a' => + let (q, r) := pos_div_eucl a' b in + let r' := 2 * r in + if r' <? b then (2 * q, r') else (2 * q + 1, r' - b) + | xI a' => + let (q, r) := pos_div_eucl a' b in + let r' := 2 * r + 1 in + if r' <? b then (2 * q, r') else (2 * q + 1, r' - b) + end. + +(** Then the general euclidean division *) + +Definition div_eucl (a b:Z) : Z * Z := + match a, b with + | 0, _ => (0, 0) + | _, 0 => (0, 0) + | pos a', pos _ => pos_div_eucl a' b + | neg a', pos _ => + let (q, r) := pos_div_eucl a' b in + match r with + | 0 => (- q, 0) + | _ => (- (q + 1), b - r) + end + | neg a', neg b' => + let (q, r) := pos_div_eucl a' (pos b') in (q, - r) + | pos a', neg b' => + let (q, r) := pos_div_eucl a' (pos b') in + match r with + | 0 => (- q, 0) + | _ => (- (q + 1), b + r) + end + end. + +Definition div (a b:Z) : Z := let (q, _) := div_eucl a b in q. +Definition modulo (a b:Z) : Z := let (_, r) := div_eucl a b in r. + +Infix "/" := div : Z_scope. +Infix "mod" := modulo (at level 40, no associativity) : Z_scope. + + +(** ** Trunc Division *) + +(** [quotrem] provides a Truncated-Toward-Zero Euclidean division. + Its projections are named [quot] (noted "÷") and [rem]. + These functions correspond to the `quot` and `rem` of Haskell. + This division convention is used in most programming languages, + e.g. Ocaml. + + With this convention: + - we have [sgn(a rem b) = sgn(a)] + - sign rule for division: [quot (-a) b = quot a (-b) = -(quot a b)] + - and for modulo: [a rem (-b) = a rem b] and [(-a) rem b = -(a rem b)] + + Note that we arbitrary take here [quot a 0 = 0] and [a rem 0 = a]. +*) + +Definition quotrem (a b:Z) : Z * Z := + match a, b with + | 0, _ => (0, 0) + | _, 0 => (0, a) + | pos a, pos b => + let (q, r) := N.pos_div_eucl a (N.pos b) in (of_N q, of_N r) + | neg a, pos b => + let (q, r) := N.pos_div_eucl a (N.pos b) in (-of_N q, - of_N r) + | pos a, neg b => + let (q, r) := N.pos_div_eucl a (N.pos b) in (-of_N q, of_N r) + | neg a, neg b => + let (q, r) := N.pos_div_eucl a (N.pos b) in (of_N q, - of_N r) + end. + +Definition quot a b := fst (quotrem a b). +Definition rem a b := snd (quotrem a b). + +Infix "÷" := quot (at level 40, left associativity) : Z_scope. +(** No infix notation for rem, otherwise it becomes a keyword *) + + +(** ** Parity functions *) + +Definition even z := + match z with + | 0 => true + | pos (xO _) => true + | neg (xO _) => true + | _ => false + end. + +Definition odd z := + match z with + | 0 => false + | pos (xO _) => false + | neg (xO _) => false + | _ => true + end. + + +(** ** Division by two *) + +(** [div2] performs rounding toward bottom, it is hence a particular + case of [div], and for all relative number [n] we have: + [n = 2 * div2 n + if odd n then 1 else 0]. *) + +Definition div2 z := + match z with + | 0 => 0 + | pos 1 => 0 + | pos p => pos (Pos.div2 p) + | neg p => neg (Pos.div2_up p) + end. + +(** [quot2] performs rounding toward zero, it is hence a particular + case of [quot], and for all relative number [n] we have: + [n = 2 * quot2 n + if odd n then sgn n else 0]. *) + +Definition quot2 (z:Z) := + match z with + | 0 => 0 + | pos 1 => 0 + | pos p => pos (Pos.div2 p) + | neg 1 => 0 + | neg p => neg (Pos.div2 p) + end. + +(** NB: [Z.quot2] used to be named [Z.div2] in Coq <= 8.3 *) + + +(** * Base-2 logarithm *) + +Definition log2 z := + match z with + | pos (p~1) => pos (Pos.size p) + | pos (p~0) => pos (Pos.size p) + | _ => 0 + end. + + +(** ** Square root *) + +Definition sqrtrem n := + match n with + | 0 => (0, 0) + | pos p => + match Pos.sqrtrem p with + | (s, IsPos r) => (pos s, pos r) + | (s, _) => (pos s, 0) + end + | neg _ => (0,0) + end. + +Definition sqrt n := + match n with + | pos p => pos (Pos.sqrt p) + | _ => 0 + end. + + +(** ** Greatest Common Divisor *) + +Definition gcd a b := + match a,b with + | 0, _ => abs b + | _, 0 => abs a + | pos a, pos b => pos (Pos.gcd a b) + | pos a, neg b => pos (Pos.gcd a b) + | neg a, pos b => pos (Pos.gcd a b) + | neg a, neg b => pos (Pos.gcd a b) + end. + +(** A generalized gcd, also computing division of a and b by gcd. *) + +Definition ggcd a b : Z*(Z*Z) := + match a,b with + | 0, _ => (abs b,(0, sgn b)) + | _, 0 => (abs a,(sgn a, 0)) + | pos a, pos b => + let '(g,(aa,bb)) := Pos.ggcd a b in (pos g, (pos aa, pos bb)) + | pos a, neg b => + let '(g,(aa,bb)) := Pos.ggcd a b in (pos g, (pos aa, neg bb)) + | neg a, pos b => + let '(g,(aa,bb)) := Pos.ggcd a b in (pos g, (neg aa, pos bb)) + | neg a, neg b => + let '(g,(aa,bb)) := Pos.ggcd a b in (pos g, (neg aa, neg bb)) + end. + + +(** ** Bitwise functions *) + +(** When accessing the bits of negative numbers, all functions + below will use the two's complement representation. For instance, + [-1] will correspond to an infinite stream of true bits. If this + isn't what you're looking for, you can use [abs] first and then + access the bits of the absolute value. +*) + +(** [testbit] : accessing the [n]-th bit of a number [a]. + For negative [n], we arbitrarily answer [false]. *) + +Definition testbit a n := + match n with + | 0 => odd a + | pos p => + match a with + | 0 => false + | pos a => Pos.testbit a (N.pos p) + | neg a => negb (N.testbit (Pos.pred_N a) (N.pos p)) + end + | neg _ => false + end. + +(** Shifts + + Nota: a shift to the right by [-n] will be a shift to the left + by [n], and vice-versa. + + For fulfilling the two's complement convention, shifting to + the right a negative number should correspond to a division + by 2 with rounding toward bottom, hence the use of [div2] + instead of [quot2]. +*) + +Definition shiftl a n := + match n with + | 0 => a + | pos p => Pos.iter p (mul 2) a + | neg p => Pos.iter p div2 a + end. + +Definition shiftr a n := shiftl a (-n). + +(** Bitwise operations [lor] [land] [ldiff] [lxor] *) + +Definition lor a b := + match a, b with + | 0, _ => b + | _, 0 => a + | pos a, pos b => pos (Pos.lor a b) + | neg a, pos b => neg (N.succ_pos (N.ldiff (Pos.pred_N a) (N.pos b))) + | pos a, neg b => neg (N.succ_pos (N.ldiff (Pos.pred_N b) (N.pos a))) + | neg a, neg b => neg (N.succ_pos (N.land (Pos.pred_N a) (Pos.pred_N b))) + end. + +Definition land a b := + match a, b with + | 0, _ => 0 + | _, 0 => 0 + | pos a, pos b => of_N (Pos.land a b) + | neg a, pos b => of_N (N.ldiff (N.pos b) (Pos.pred_N a)) + | pos a, neg b => of_N (N.ldiff (N.pos a) (Pos.pred_N b)) + | neg a, neg b => neg (N.succ_pos (N.lor (Pos.pred_N a) (Pos.pred_N b))) + end. + +Definition ldiff a b := + match a, b with + | 0, _ => 0 + | _, 0 => a + | pos a, pos b => of_N (Pos.ldiff a b) + | neg a, pos b => neg (N.succ_pos (N.lor (Pos.pred_N a) (N.pos b))) + | pos a, neg b => of_N (N.land (N.pos a) (Pos.pred_N b)) + | neg a, neg b => of_N (N.ldiff (Pos.pred_N b) (Pos.pred_N a)) + end. + +Definition lxor a b := + match a, b with + | 0, _ => b + | _, 0 => a + | pos a, pos b => of_N (Pos.lxor a b) + | neg a, pos b => neg (N.succ_pos (N.lxor (Pos.pred_N a) (N.pos b))) + | pos a, neg b => neg (N.succ_pos (N.lxor (N.pos a) (Pos.pred_N b))) + | neg a, neg b => of_N (N.lxor (Pos.pred_N a) (Pos.pred_N b)) + end. + +End Z.
\ No newline at end of file diff --git a/theories/ZArith/Int.v b/theories/ZArith/Int.v index c0123ca8..99ecd150 100644 --- a/theories/ZArith/Int.v +++ b/theories/ZArith/Int.v @@ -6,8 +6,6 @@ (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) -(* $Id: Int.v 12363 2009-09-28 15:04:07Z letouzey $ *) - (** * An light axiomatization of integers (used in FSetAVL). *) (** We define a signature for an integer datatype based on [Z]. @@ -18,28 +16,26 @@ Require Import ZArith. Delimit Scope Int_scope with I. - +Local Open Scope Int_scope. (** * a specification of integers *) Module Type Int. - Open Scope Int_scope. - - Parameter int : Set. + Parameter t : Set. + Bind Scope Int_scope with t. - Parameter i2z : int -> Z. - Arguments Scope i2z [ Int_scope ]. + Parameter i2z : t -> Z. - 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. + Parameter _0 : t. + Parameter _1 : t. + Parameter _2 : t. + Parameter _3 : t. + Parameter plus : t -> t -> t. + Parameter opp : t -> t. + Parameter minus : t -> t -> t. + Parameter mult : t -> t -> t. + Parameter max : t -> t -> t. Notation "0" := _0 : Int_scope. Notation "1" := _1 : Int_scope. @@ -56,10 +52,10 @@ Module Type Int. 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" := (i2z x <= i2z y)%Z : Int_scope. + Notation "x < y" := (i2z x < i2z y)%Z : Int_scope. + Notation "x >= y" := (i2z x >= i2z y)%Z : Int_scope. + Notation "x > y" := (i2z x > i2z 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. @@ -67,41 +63,39 @@ Module Type Int. (** 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 }. + Axiom gt_le_dec : forall x y : t, {x > y} + {x <= y}. + Axiom ge_lt_dec : forall x y : t, {x >= y} + {x < y}. + Axiom eq_dec : forall x y : t, { 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. *) + nonetheless since the translation to [Z] for using automatic tactic + is easier. *) - Axiom i2z_eq : forall n p : int, n == p -> n = p. + Axiom i2z_eq : forall n p : t, 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). + Axiom i2z_0 : i2z _0 = 0%Z. + Axiom i2z_1 : i2z _1 = 1%Z. + Axiom i2z_2 : i2z _2 = 2%Z. + Axiom i2z_3 : i2z _3 = 3%Z. + Axiom i2z_plus : forall n p, i2z (n + p) = (i2z n + i2z p)%Z. + Axiom i2z_opp : forall n, i2z (-n) = (-i2z n)%Z. + Axiom i2z_minus : forall n p, i2z (n - p) = (i2z n - i2z p)%Z. + Axiom i2z_mult : forall n p, i2z (n * p) = (i2z n * i2z p)%Z. + Axiom i2z_max : forall n p, i2z (max n p) = Z.max (i2z n) (i2z p). End Int. (** * Facts and tactics using [Int] *) -Module MoreInt (I:Int). - Import I. - - Open Scope Int_scope. +Module MoreInt (Import I:Int). + Local Notation int := I.t. (** A magic (but costly) tactic that goes from [int] back to the [Z] friendly world ... *) @@ -110,13 +104,14 @@ Module MoreInt (I:Int). 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. + | H : ?a = ?b |- _ => + generalize (f_equal i2z H); + try autorewrite with i2z; clear H; intro H; i2z + | |- ?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 *) @@ -126,14 +121,14 @@ Module MoreInt (I:Int). Anyhow, [i2z_refl] is enough for applying [romega]. *) Ltac i2z_gen := match goal with - | |- (eq (A:=int) ?a ?b) => apply (i2z_eq a b); i2z_gen - | H : (eq (A:=int) ?a ?b) |- _ => + | |- ?a = ?b => apply (i2z_eq a b); i2z_gen + | H : ?a = ?b |- _ => generalize (f_equal i2z H); clear H; i2z_gen - | H : (eq (A:=Z) ?a ?b) |- _ => revert H; i2z_gen - | H : (Zlt ?a ?b) |- _ => revert H; i2z_gen - | H : (Zle ?a ?b) |- _ => revert H; i2z_gen - | H : (Zgt ?a ?b) |- _ => revert H; i2z_gen - | H : (Zge ?a ?b) |- _ => revert H; i2z_gen + | H : eq (A:=Z) ?a ?b |- _ => revert H; i2z_gen + | H : Z.lt ?a ?b |- _ => revert H; i2z_gen + | H : Z.le ?a ?b |- _ => revert H; i2z_gen + | H : Z.gt ?a ?b |- _ => revert H; i2z_gen + | H : Z.ge ?a ?b |- _ => revert H; i2z_gen | H : _ -> ?X |- _ => (* A [Set] or [Type] part cannot be dealt with easily using the [ExprP] datatype. So we forget it, leaving @@ -203,11 +198,11 @@ Module MoreInt (I:Int). 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) + | (?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) + | (Z.max ?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. @@ -222,10 +217,10 @@ Module MoreInt (I:Int). | (?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<?y)%Z => 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 < ?y)%Z => 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. @@ -252,7 +247,7 @@ Module MoreInt (I:Int). | 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) + | EZmax e1 e2 => Z.max (ez2z e1) (ez2z e2) | EZopp e => (-(ez2z e))%Z | EZofI e => i2z (ei2i e) | EZraw z => z @@ -362,30 +357,29 @@ End MoreInt. (** It's always nice to know that our [Int] interface is realizable :-) *) Module Z_as_Int <: Int. - Open Scope Z_scope. - Definition int := Z. + Local Open Scope Z_scope. + Definition t := 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 plus := Z.add. + Definition opp := Z.opp. + Definition minus := Z.sub. + Definition mult := Z.mul. + Definition max := Z.max. 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. + Definition eq_dec := Z.eq_dec. + Definition i2z : t -> 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. + Lemma i2z_plus n p : i2z (n + p) = i2z n + i2z p. Proof. auto. Qed. + Lemma i2z_opp n : i2z (- n) = - i2z n. Proof. auto. Qed. + Lemma i2z_minus n p : i2z (n - p) = i2z n - i2z p. Proof. auto. Qed. + Lemma i2z_mult n p : i2z (n * p) = i2z n * i2z p. Proof. auto. Qed. + Lemma i2z_max n p : i2z (max n p) = Z.max (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 0fe6d623..3935e124 100644 --- a/theories/ZArith/Wf_Z.v +++ b/theories/ZArith/Wf_Z.v @@ -1,123 +1,83 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Wf_Z.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - Require Import BinInt. Require Import Zcompare. Require Import Zorder. Require Import Znat. Require Import Zmisc. Require Import Wf_nat. -Open Local Scope Z_scope. +Local Open Scope Z_scope. (** Our purpose is to write an induction shema for {0,1,2,...} similar to the [nat] schema (Theorem [Natlike_rec]). For that the following implications will be used : << - (n:nat)(Q n)==(n:nat)(P (inject_nat n)) ===> (x:Z)`x > 0) -> (P x) + ∀n:nat, Q n == ∀n:nat, P (Z.of_nat n) ===> ∀x:Z, x <= 0 -> P x /\ || || - (Q O) (n:nat)(Q n)->(Q (S n)) <=== (P 0) (x:Z) (P x) -> (P (Zs x)) + (Q O) ∧ (∀n:nat, Q n -> Q (S n)) <=== (P 0) ∧ (∀x:Z, P x -> P (Z.succ x)) - <=== (inject_nat (S n))=(Zs (inject_nat n)) + <=== (Z.of_nat (S n) = Z.succ (Z.of_nat n)) - <=== inject_nat_complete + <=== Z_of_nat_complete >> 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. -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}. +Lemma Z_of_nat_complete (x : Z) : + 0 <= x -> exists n : nat, x = Z.of_nat n. 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 ]. + intros H. exists (Z.to_nat x). symmetry. now apply Z2Nat.id. Qed. -Lemma Z_of_nat_complete_inf : - forall x:Z, 0 <= x -> {n : nat | x = Z_of_nat n}. +Lemma Z_of_nat_complete_inf (x : Z) : + 0 <= x -> {n : nat | x = Z.of_nat n}. 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 ] ]. + intros H. exists (Z.to_nat x). symmetry. now apply Z2Nat.id. 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. + (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. + intros P H x Hx. now destruct (Z_of_nat_complete x Hx) as (n,->). 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. + (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_inf x H0). - intros Hn; elim Hn; intros. - rewrite p; apply H. + intros P H x Hx. now destruct (Z_of_nat_complete_inf x Hx) as (n,->). 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. + (forall x:Z, 0 <= x -> P x -> P (Z.succ x)) -> + forall x:Z, 0 <= x -> P x. 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 ]. + intros P Ho Hrec x Hx; apply Z_of_nat_prop; trivial. + induction n. exact Ho. + rewrite Nat2Z.inj_succ. apply Hrec; trivial using Nat2Z.is_nonneg. 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. + (forall x:Z, 0 <= x -> P x -> P (Z.succ x)) -> + forall x:Z, 0 <= x -> P x. 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 ]. + intros P Ho Hrec x Hx; apply Z_of_nat_set; trivial. + induction n. exact Ho. + rewrite Nat2Z.inj_succ. apply Hrec; trivial using Nat2Z.is_nonneg. Qed. Section Efficient_Rec. @@ -129,76 +89,62 @@ Section Efficient_Rec. 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. + apply well_founded_lt_compat with Z.to_nat. + intros x y (Hx,H). apply Z2Nat.inj_lt; Z.order. 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. + (forall z:Z, 0 <= z -> P z -> P (Z.succ 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. + intros P Ho Hrec. + induction z as [z IH] using (well_founded_induction_type R_wf). + destruct z; intros Hz. + - apply Ho. + - set (y:=Z.pred (Zpos p)). + assert (LE : 0 <= y) by (unfold y; now apply Z.lt_le_pred). + assert (EQ : Zpos p = Z.succ y) by (unfold y; now rewrite Z.succ_pred). + rewrite EQ. apply Hrec, IH; trivial. + split; trivial. unfold y; apply Z.lt_pred_l. + - now destruct Hz. Qed. - (** A variant of the previous using [Zpred] instead of [Zs]. *) + (** A variant of the previous using [Z.pred] instead of [Z.succ]. *) 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. + (forall z:Z, 0 < z -> P (Z.pred 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. + intros P Ho Hrec. + induction z as [z IH] using (well_founded_induction_type R_wf). + destruct z; intros Hz. + - apply Ho. + - assert (EQ : 0 <= Z.pred (Zpos p)) by now apply Z.lt_le_pred. + apply Hrec. easy. apply IH; trivial. split; trivial. + apply Z.lt_pred_l. + - now destruct Hz. Qed. - (** A more general induction principle on non-negative numbers using [Zlt]. *) + (** A more general induction principle on non-negative numbers using [Z.lt]. *) 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. + intros P Hrec. + induction x as [x IH] using (well_founded_induction_type R_wf). + destruct x; intros Hx. + - apply Hrec; trivial. intros y (Hy,Hy'). + assert (0 < 0) by now apply Z.le_lt_trans with y. + discriminate. + - apply Hrec; trivial. intros y (Hy,Hy'). + apply IH; trivial. now split. + - now destruct Hx. Defined. Lemma Zlt_0_ind : @@ -209,7 +155,7 @@ Section Efficient_Rec. exact Zlt_0_rec. Qed. - (** Obsolete version of [Zlt] induction principle on non-negative numbers *) + (** Obsolete version of [Z.lt] induction principle on non-negative numbers *) Lemma Z_lt_rec : forall P:Z -> Type, @@ -227,29 +173,22 @@ Section Efficient_Rec. exact Z_lt_rec. Qed. - (** An even more general induction principle using [Zlt]. *) + (** An even more general induction principle using [Z.lt]. *) 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. + intros P z Hrec x Hx. + rewrite <- (Z.sub_simpl_r x z). apply Z.le_0_sub in Hx. + pattern (x - z); apply Zlt_0_rec; trivial. + clear x Hx. intros x IH Hx. + apply Hrec. intros y (Hy,Hy'). + rewrite <- (Z.sub_simpl_r y z). apply IH; split. + now rewrite Z.le_0_sub. + now apply Z.lt_sub_lt_add_r. + now rewrite <- (Z.add_le_mono_r 0 x z). Qed. Lemma Zlt_lower_bound_ind : diff --git a/theories/ZArith/ZArith.v b/theories/ZArith/ZArith.v index bc79e373..033dc11f 100644 --- a/theories/ZArith/ZArith.v +++ b/theories/ZArith/ZArith.v @@ -1,21 +1,22 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ZArith.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - (** Library for manipulating integers based on binary encoding *) Require Export ZArith_base. +(** Extra definitions *) + +Require Export Zpow_def. + (** Extra modules using [Omega] or [Ring]. *) Require Export Zcomplements. -Require Export Zsqrt. Require Export Zpower. Require Export Zdiv. Require Export Zlogarithm. diff --git a/theories/ZArith/ZArith_base.v b/theories/ZArith/ZArith_base.v index 8cdae80d..38b6c44d 100644 --- a/theories/ZArith/ZArith_base.v +++ b/theories/ZArith/ZArith_base.v @@ -1,17 +1,16 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: ZArith_base.v 14641 2011-11-06 11:59:10Z herbelin $ *) - (** Library for manipulating integers based on binary encoding. These are the basic modules, required by [Omega] and [Ring] for instance. The full library is [ZArith]. *) +Require Export BinNums. Require Export BinPos. Require Export BinNat. Require Export BinInt. @@ -29,8 +28,8 @@ Require Export Zbool. Require Export Zmisc. Require Export Wf_Z. -Hint Resolve Zle_refl Zplus_comm Zplus_assoc Zmult_comm Zmult_assoc Zplus_0_l - Zplus_0_r Zmult_1_l Zplus_opp_l Zplus_opp_r Zmult_plus_distr_l - Zmult_plus_distr_r: zarith. +Hint Resolve Z.le_refl Z.add_comm Z.add_assoc Z.mul_comm Z.mul_assoc Z.add_0_l + Z.add_0_r Z.mul_1_l Z.add_opp_diag_l Z.add_opp_diag_r Z.mul_add_distr_l + Z.mul_add_distr_r: zarith. Require Export Zhints. diff --git a/theories/ZArith/ZArith_dec.v b/theories/ZArith/ZArith_dec.v index b6766640..ff4f5e7b 100644 --- a/theories/ZArith/ZArith_dec.v +++ b/theories/ZArith/ZArith_dec.v @@ -1,19 +1,17 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: ZArith_dec.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - Require Import Sumbool. Require Import BinInt. Require Import Zorder. Require Import Zcompare. -Open Local Scope Z_scope. +Local Open Scope Z_scope. (* begin hide *) (* Trivial, to deprecate? *) @@ -23,68 +21,43 @@ Proof. Defined. (* end hide *) -Lemma Zcompare_rect : - forall (P:Type) (n m:Z), - ((n ?= m) = Eq -> P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P. +Lemma Zcompare_rect (P:Type) (n m:Z) : + ((n ?= m) = Eq -> P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P. Proof. - intros * H1 H2 H3. + intros H1 H2 H3. destruct (n ?= m); auto. Defined. -Lemma Zcompare_rec : - forall (P:Set) (n m:Z), - ((n ?= m) = Eq -> P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P. -Proof. - intro; apply Zcompare_rect. -Defined. +Lemma Zcompare_rec (P:Set) (n m:Z) : + ((n ?= m) = Eq -> P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P. +Proof. apply Zcompare_rect. Defined. + +Notation Z_eq_dec := Z.eq_dec (compat "8.3"). Section decidability. Variables x y : Z. - (** * Decidability of equality on binary integers *) - - Definition Z_eq_dec : {x = y} + {x <> y}. - Proof. - decide equality; apply positive_eq_dec. - 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. + unfold Z.lt; case Z.compare; (now left) || (now right). 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. + unfold Z.le; case Z.compare; (now left) || (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. + unfold Z.gt; case Z.compare; (now left) || (now right). 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. + unfold Z.ge; case Z.compare; (now left) || (right; tauto). Defined. Definition Z_lt_ge_dec : {x < y} + {x >= y}. @@ -94,16 +67,15 @@ Section decidability. 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. + * now left. + * right; now apply Z.ge_le. Defined. 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. + intro. right. Z.swap_greater. now apply Z.nle_gt. Defined. Definition Z_gt_le_dec : {x > y} + {x <= y}. @@ -114,15 +86,15 @@ Section decidability. 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. + intro. right. Z.swap_greater. now apply Z.lt_nge. 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. right. elim (Z.compare_eq_iff x y); auto with arith. + intro. left. elim (Z.compare_eq_iff x y); auto with arith. intro H1. absurd (x > y); auto with arith. Defined. @@ -139,8 +111,8 @@ Proof. assumption. intro. right. - apply Zle_lt_trans with (m := x). - apply Zge_le. + apply Z.le_lt_trans with (m := x). + apply Z.ge_le. assumption. assumption. Defined. @@ -149,20 +121,16 @@ 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. + - now left. + - right. + apply Z.add_lt_mono_l with (p := x). + now rewrite Z.add_0_r. 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 ]; + [ right; apply Z.add_lt_mono_l with (p := x); rewrite Z.add_0_r | left ]; assumption. Defined. @@ -174,7 +142,7 @@ Proof. left. assumption. intro H0. - generalize (Zge_le _ _ H0). + generalize (Z.ge_le _ _ H0). intro. case (Z_le_lt_eq_dec _ _ H1). intro. @@ -183,7 +151,7 @@ Proof. intro. apply False_rec. apply H. - symmetry in |- *. + symmetry . assumption. Defined. @@ -196,17 +164,17 @@ Proof. left. assumption. intro H. - generalize (Zge_le _ _ H). + generalize (Z.ge_le _ _ H). intro H0. case (Z_le_lt_eq_dec y x H0). intro H1. left. right. - apply Zlt_gt. + apply Z.lt_gt. assumption. intro. right. - symmetry in |- *. + symmetry . assumption. Defined. @@ -214,7 +182,7 @@ 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; + case (Z.eq_dec x y); intro H; [ right; assumption | left; apply (not_Zeq_inf _ _ H) ]. Defined. @@ -222,12 +190,12 @@ Defined. (* To deprecate ? *) Corollary 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. Corollary Z_notzerop : forall (x:Z), {x <> 0} + {x = 0}. Proof (fun x => sumbool_not _ _ (Z_zerop x)). Corollary Z_noteq_dec : forall (x y:Z), {x <> y} + {x = y}. -Proof (fun x y => sumbool_not _ _ (Z_eq_dec x y)). +Proof (fun x y => sumbool_not _ _ (Z.eq_dec x y)). (* end hide *) diff --git a/theories/ZArith/ZOdiv.v b/theories/ZArith/ZOdiv.v index 70f6866e..17c5bae3 100644 --- a/theories/ZArith/ZOdiv.v +++ b/theories/ZArith/ZOdiv.v @@ -1,947 +1,88 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) - -Require Import BinPos BinNat Nnat ZArith_base ROmega ZArithRing. Require Export ZOdiv_def. -Require Zdiv. - -Open Scope Z_scope. - -(** This file provides results about the Round-Toward-Zero Euclidean - division [ZOdiv_eucl], whose projections are [ZOdiv] and [ZOmod]. - Definition of this division can be found in file [ZOdiv_def]. - - This division and the one defined in Zdiv agree only on positive - numbers. Otherwise, Zdiv performs Round-Toward-Bottom. - - The current approach is compatible with the division of usual - programming languages such as Ocaml. In addition, it has nicer - properties with respect to opposite and other usual operations. -*) - -(** Since ZOdiv and Zdiv are not meant to be used concurrently, - we reuse the same notation. *) - -Infix "/" := ZOdiv : Z_scope. -Infix "mod" := ZOmod (at level 40, no associativity) : Z_scope. - -Infix "/" := Ndiv : N_scope. -Infix "mod" := Nmod (at level 40, no associativity) : N_scope. - -(** Auxiliary results on the ad-hoc comparison [NPgeb]. *) - -Lemma NPgeb_Zge : forall (n:N)(p:positive), - NPgeb n p = true -> Z_of_N n >= Zpos p. -Proof. - destruct n as [|n]; simpl; intros. - discriminate. - red; simpl; destruct Pcompare; now auto. -Qed. - -Lemma NPgeb_Zlt : forall (n:N)(p:positive), - NPgeb n p = false -> Z_of_N n < Zpos p. -Proof. - destruct n as [|n]; simpl; intros. - red; auto. - red; simpl; destruct Pcompare; now auto. -Qed. - -(** * Relation between division on N and on Z. *) - -Lemma Ndiv_Z0div : forall a b:N, - Z_of_N (a/b) = (Z_of_N a / Z_of_N b). -Proof. - intros. - destruct a; destruct b; simpl; auto. - unfold Ndiv, ZOdiv; simpl; destruct Pdiv_eucl; auto. -Qed. - -Lemma Nmod_Z0mod : forall a b:N, - Z_of_N (a mod b) = (Z_of_N a) mod (Z_of_N b). -Proof. - intros. - destruct a; destruct b; simpl; auto. - unfold Nmod, ZOmod; simpl; destruct Pdiv_eucl; auto. -Qed. - -(** * Characterization of this euclidean division. *) - -(** First, the usual equation [a=q*b+r]. Notice that [a mod 0] - has been chosen to be [a], so this equation holds even for [b=0]. -*) - -Theorem N_div_mod_eq : forall a b, - a = (b * (Ndiv a b) + (Nmod a b))%N. -Proof. - intros; generalize (Ndiv_eucl_correct a b). - unfold Ndiv, Nmod; destruct Ndiv_eucl; simpl. - intro H; rewrite H; rewrite Nmult_comm; auto. -Qed. - -Theorem ZO_div_mod_eq : forall a b, - a = b * (ZOdiv a b) + (ZOmod a b). -Proof. - intros; generalize (ZOdiv_eucl_correct a b). - unfold ZOdiv, ZOmod; destruct ZOdiv_eucl; simpl. - intro H; rewrite H; rewrite Zmult_comm; auto. -Qed. - -(** Then, the inequalities constraining the remainder. *) - -Theorem Pdiv_eucl_remainder : forall a b:positive, - Z_of_N (snd (Pdiv_eucl a b)) < Zpos b. -Proof. - induction a; cbv beta iota delta [Pdiv_eucl]; fold Pdiv_eucl; cbv zeta. - intros b; generalize (IHa b); case Pdiv_eucl. - intros q1 r1 Hr1; simpl in Hr1. - case_eq (NPgeb (2*r1+1) b); intros; unfold snd. - romega with *. - apply NPgeb_Zlt; auto. - intros b; generalize (IHa b); case Pdiv_eucl. - intros q1 r1 Hr1; simpl in Hr1. - case_eq (NPgeb (2*r1) b); intros; unfold snd. - romega with *. - apply NPgeb_Zlt; auto. - destruct b; simpl; romega with *. -Qed. - -Theorem Nmod_lt : forall (a b:N), b<>0%N -> - (a mod b < b)%N. -Proof. - destruct b as [ |b]; intro H; try solve [elim H;auto]. - destruct a as [ |a]; try solve [compute;auto]; unfold Nmod, Ndiv_eucl. - generalize (Pdiv_eucl_remainder a b); destruct Pdiv_eucl; simpl. - romega with *. -Qed. - -(** The remainder is bounded by the divisor, in term of absolute values *) - -Theorem ZOmod_lt : forall a b:Z, b<>0 -> - Zabs (a mod b) < Zabs b. -Proof. - destruct b as [ |b|b]; intro H; try solve [elim H;auto]; - destruct a as [ |a|a]; try solve [compute;auto]; unfold ZOmod, ZOdiv_eucl; - generalize (Pdiv_eucl_remainder a b); destruct Pdiv_eucl; simpl; - try rewrite Zabs_Zopp; rewrite Zabs_eq; auto; apply Z_of_N_le_0. -Qed. - -(** The sign of the remainder is the one of [a]. Due to the possible - nullity of [a], a general result is to be stated in the following form: -*) - -Theorem ZOmod_sgn : forall a b:Z, - 0 <= Zsgn (a mod b) * Zsgn a. -Proof. - destruct b as [ |b|b]; destruct a as [ |a|a]; simpl; auto with zarith; - unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; - simpl; destruct n0; simpl; auto with zarith. -Qed. - -(** This can also be said in a simplier way: *) - -Theorem Zsgn_pos_iff : forall z, 0 <= Zsgn z <-> 0 <= z. -Proof. - destruct z; simpl; intuition auto with zarith. -Qed. - -Theorem ZOmod_sgn2 : forall a b:Z, - 0 <= (a mod b) * a. -Proof. - intros; rewrite <-Zsgn_pos_iff, Zsgn_Zmult; apply ZOmod_sgn. -Qed. - -(** Reformulation of [ZOdiv_lt] and [ZOmod_sgn] in 2 - then 4 particular cases. *) - -Theorem ZOmod_lt_pos : forall a b:Z, 0<=a -> b<>0 -> - 0 <= a mod b < Zabs b. -Proof. - intros. - assert (0 <= a mod b). - generalize (ZOmod_sgn a b). - destruct (Zle_lt_or_eq 0 a H). - rewrite <- Zsgn_pos in H1; rewrite H1; romega with *. - subst a; simpl; auto. - generalize (ZOmod_lt a b H0); romega with *. -Qed. - -Theorem ZOmod_lt_neg : forall a b:Z, a<=0 -> b<>0 -> - -Zabs b < a mod b <= 0. -Proof. - intros. - assert (a mod b <= 0). - generalize (ZOmod_sgn a b). - destruct (Zle_lt_or_eq a 0 H). - rewrite <- Zsgn_neg in H1; rewrite H1; romega with *. - subst a; simpl; auto. - generalize (ZOmod_lt a b H0); romega with *. -Qed. - -Theorem ZOmod_lt_pos_pos : forall a b:Z, 0<=a -> 0<b -> 0 <= a mod b < b. -Proof. - intros; generalize (ZOmod_lt_pos a b); romega with *. -Qed. - -Theorem ZOmod_lt_pos_neg : forall a b:Z, 0<=a -> b<0 -> 0 <= a mod b < -b. -Proof. - intros; generalize (ZOmod_lt_pos a b); romega with *. -Qed. - -Theorem ZOmod_lt_neg_pos : forall a b:Z, a<=0 -> 0<b -> -b < a mod b <= 0. -Proof. - intros; generalize (ZOmod_lt_neg a b); romega with *. -Qed. - -Theorem ZOmod_lt_neg_neg : forall a b:Z, a<=0 -> b<0 -> b < a mod b <= 0. -Proof. - intros; generalize (ZOmod_lt_neg a b); romega with *. -Qed. - -(** * Division and Opposite *) - -(* The precise equalities that are invalid with "historic" Zdiv. *) - -Theorem ZOdiv_opp_l : forall a b:Z, (-a)/b = -(a/b). -Proof. - destruct a; destruct b; simpl; auto; - unfold ZOdiv, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. -Qed. - -Theorem ZOdiv_opp_r : forall a b:Z, a/(-b) = -(a/b). -Proof. - destruct a; destruct b; simpl; auto; - unfold ZOdiv, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. -Qed. - -Theorem ZOmod_opp_l : forall a b:Z, (-a) mod b = -(a mod b). -Proof. - destruct a; destruct b; simpl; auto; - unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. -Qed. - -Theorem ZOmod_opp_r : forall a b:Z, a mod (-b) = a mod b. -Proof. - destruct a; destruct b; simpl; auto; - unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. -Qed. - -Theorem ZOdiv_opp_opp : forall a b:Z, (-a)/(-b) = a/b. -Proof. - destruct a; destruct b; simpl; auto; - unfold ZOdiv, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. -Qed. - -Theorem ZOmod_opp_opp : forall a b:Z, (-a) mod (-b) = -(a mod b). -Proof. - destruct a; destruct b; simpl; auto; - unfold ZOmod, ZOdiv_eucl; destruct Pdiv_eucl; simpl; auto with zarith. -Qed. - -(** * Unicity results *) - -Definition Remainder a b r := - (0 <= a /\ 0 <= r < Zabs b) \/ (a <= 0 /\ -Zabs b < r <= 0). - -Definition Remainder_alt a b r := - Zabs r < Zabs b /\ 0 <= r * a. - -Lemma Remainder_equiv : forall a b r, - Remainder a b r <-> Remainder_alt a b r. -Proof. - unfold Remainder, Remainder_alt; intuition. - romega with *. - romega with *. - rewrite <-(Zmult_opp_opp). - apply Zmult_le_0_compat; romega. - assert (0 <= Zsgn r * Zsgn a) by (rewrite <-Zsgn_Zmult, Zsgn_pos_iff; auto). - destruct r; simpl Zsgn in *; romega with *. -Qed. - -Theorem ZOdiv_mod_unique_full: - forall a b q r, Remainder a b r -> - a = b*q + r -> q = a/b /\ r = a mod b. -Proof. - destruct 1 as [(H,H0)|(H,H0)]; intros. - apply Zdiv.Zdiv_mod_unique with b; auto. - apply ZOmod_lt_pos; auto. - romega with *. - rewrite <- H1; apply ZO_div_mod_eq. - - rewrite <- (Zopp_involutive a). - rewrite ZOdiv_opp_l, ZOmod_opp_l. - generalize (Zdiv.Zdiv_mod_unique b (-q) (-a/b) (-r) (-a mod b)). - generalize (ZOmod_lt_pos (-a) b). - rewrite <-ZO_div_mod_eq, <-Zopp_mult_distr_r, <-Zopp_plus_distr, <-H1. - romega with *. -Qed. - -Theorem ZOdiv_unique_full: - forall a b q r, Remainder a b r -> - a = b*q + r -> q = a/b. -Proof. - intros; destruct (ZOdiv_mod_unique_full a b q r); auto. -Qed. - -Theorem ZOdiv_unique: - forall a b q r, 0 <= a -> 0 <= r < b -> - a = b*q + r -> q = a/b. -Proof. - intros; eapply ZOdiv_unique_full; eauto. - red; romega with *. -Qed. - -Theorem ZOmod_unique_full: - forall a b q r, Remainder a b r -> - a = b*q + r -> r = a mod b. -Proof. - intros; destruct (ZOdiv_mod_unique_full a b q r); auto. -Qed. - -Theorem ZOmod_unique: - forall a b q r, 0 <= a -> 0 <= r < b -> - a = b*q + r -> r = a mod b. -Proof. - intros; eapply ZOmod_unique_full; eauto. - red; romega with *. -Qed. - -(** * Basic values of divisions and modulo. *) - -Lemma ZOmod_0_l: forall a, 0 mod a = 0. -Proof. - destruct a; simpl; auto. -Qed. - -Lemma ZOmod_0_r: forall a, a mod 0 = a. -Proof. - destruct a; simpl; auto. -Qed. - -Lemma ZOdiv_0_l: forall a, 0/a = 0. -Proof. - destruct a; simpl; auto. -Qed. - -Lemma ZOdiv_0_r: forall a, a/0 = 0. -Proof. - destruct a; simpl; auto. -Qed. - -Lemma ZOmod_1_r: forall a, a mod 1 = 0. -Proof. - intros; symmetry; apply ZOmod_unique_full with a; auto with zarith. - rewrite Remainder_equiv; red; simpl; auto with zarith. -Qed. - -Lemma ZOdiv_1_r: forall a, a/1 = a. -Proof. - intros; symmetry; apply ZOdiv_unique_full with 0; auto with zarith. - rewrite Remainder_equiv; red; simpl; auto with zarith. -Qed. - -Hint Resolve ZOmod_0_l ZOmod_0_r ZOdiv_0_l ZOdiv_0_r ZOdiv_1_r ZOmod_1_r - : zarith. - -Lemma ZOdiv_1_l: forall a, 1 < a -> 1/a = 0. -Proof. - intros; symmetry; apply ZOdiv_unique with 1; auto with zarith. -Qed. - -Lemma ZOmod_1_l: forall a, 1 < a -> 1 mod a = 1. -Proof. - intros; symmetry; apply ZOmod_unique with 0; auto with zarith. -Qed. - -Lemma ZO_div_same : forall a:Z, a<>0 -> a/a = 1. -Proof. - intros; symmetry; apply ZOdiv_unique_full with 0; auto with *. - rewrite Remainder_equiv; red; simpl; romega with *. -Qed. - -Lemma ZO_mod_same : forall a, a mod a = 0. -Proof. - destruct a; intros; symmetry. - compute; auto. - apply ZOmod_unique with 1; auto with *; romega with *. - apply ZOmod_unique_full with 1; auto with *; red; romega with *. -Qed. - -Lemma ZO_mod_mult : forall a b, (a*b) mod b = 0. -Proof. - intros a b; destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; simpl; rewrite ZOmod_0_r; auto with zarith. - symmetry; apply ZOmod_unique_full with a; [ red; romega with * | ring ]. -Qed. - -Lemma ZO_div_mult : forall a b:Z, b <> 0 -> (a*b)/b = a. -Proof. - intros; symmetry; apply ZOdiv_unique_full with 0; auto with zarith; - [ red; romega with * | ring]. -Qed. - -(** * Order results about ZOmod and ZOdiv *) - -(* Division of positive numbers is positive. *) - -Lemma ZO_div_pos: forall a b, 0 <= a -> 0 <= b -> 0 <= a/b. -Proof. - intros. - destruct (Zle_lt_or_eq 0 b H0). - assert (H2:=ZOmod_lt_pos_pos a b H H1). - rewrite (ZO_div_mod_eq a b) in H. - destruct (Z_lt_le_dec (a/b) 0); auto. - assert (b*(a/b) <= -b). - replace (-b) with (b*-1); [ | ring]. - apply Zmult_le_compat_l; auto with zarith. - romega. - subst b; rewrite ZOdiv_0_r; auto. -Qed. - -(** As soon as the divisor is greater or equal than 2, - the division is strictly decreasing. *) - -Lemma ZO_div_lt : forall a b:Z, 0 < a -> 2 <= b -> a/b < a. -Proof. - intros. - assert (Hb : 0 < b) by romega. - assert (H1 : 0 <= a/b) by (apply ZO_div_pos; auto with zarith). - assert (H2 : 0 <= a mod b < b) by (apply ZOmod_lt_pos_pos; auto with zarith). - destruct (Zle_lt_or_eq 0 (a/b) H1) as [H3|H3]; [ | rewrite <- H3; auto]. - pattern a at 2; rewrite (ZO_div_mod_eq a b). - apply Zlt_le_trans with (2*(a/b)). - romega. - apply Zle_trans with (b*(a/b)). - apply Zmult_le_compat_r; auto. - romega. -Qed. - -(** A division of a small number by a bigger one yields zero. *) - -Theorem ZOdiv_small: forall a b, 0 <= a < b -> a/b = 0. -Proof. - intros a b H; apply sym_equal; apply ZOdiv_unique with a; auto with zarith. -Qed. - -(** Same situation, in term of modulo: *) - -Theorem ZOmod_small: forall a n, 0 <= a < n -> a mod n = a. -Proof. - intros a b H; apply sym_equal; apply ZOmod_unique with 0; auto with zarith. -Qed. - -(** [Zge] is compatible with a positive division. *) - -Lemma ZO_div_monotone_pos : forall a b c:Z, 0<=c -> 0<=a<=b -> a/c <= b/c. -Proof. - intros. - destruct H0. - destruct (Zle_lt_or_eq 0 c H); - [ clear H | subst c; do 2 rewrite ZOdiv_0_r; auto]. - generalize (ZO_div_mod_eq a c). - generalize (ZOmod_lt_pos_pos a c H0 H2). - generalize (ZO_div_mod_eq b c). - generalize (ZOmod_lt_pos_pos b c (Zle_trans _ _ _ H0 H1) H2). - intros. - elim (Z_le_gt_dec (a / c) (b / c)); auto with zarith. - intro. - absurd (a - b >= 1). - omega. - replace (a-b) with (c * (a/c-b/c) + a mod c - b mod c) by - (symmetry; pattern a at 1; rewrite H5; pattern b at 1; rewrite H3; ring). - assert (c * (a / c - b / c) >= c * 1). - apply Zmult_ge_compat_l. - omega. - omega. - assert (c * 1 = c). - ring. - omega. -Qed. - -Lemma ZO_div_monotone : forall a b c, 0<=c -> a<=b -> a/c <= b/c. -Proof. - intros. - destruct (Z_le_gt_dec 0 a). - apply ZO_div_monotone_pos; auto with zarith. - destruct (Z_le_gt_dec 0 b). - apply Zle_trans with 0. - apply Zle_left_rev. - simpl. - rewrite <- ZOdiv_opp_l. - apply ZO_div_pos; auto with zarith. - apply ZO_div_pos; auto with zarith. - rewrite <-(Zopp_involutive a), (ZOdiv_opp_l (-a)). - rewrite <-(Zopp_involutive b), (ZOdiv_opp_l (-b)). - generalize (ZO_div_monotone_pos (-b) (-a) c H). - romega. -Qed. - -(** With our choice of division, rounding of (a/b) is always done toward zero: *) - -Lemma ZO_mult_div_le : forall a b:Z, 0 <= a -> 0 <= b*(a/b) <= a. -Proof. - intros a b Ha. - destruct b as [ |b|b]. - simpl; auto with zarith. - split. - apply Zmult_le_0_compat; auto with zarith. - apply ZO_div_pos; auto with zarith. - generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_pos_pos a (Zpos b) Ha); romega with *. - change (Zneg b) with (-Zpos b); rewrite ZOdiv_opp_r, Zmult_opp_opp. - split. - apply Zmult_le_0_compat; auto with zarith. - apply ZO_div_pos; auto with zarith. - generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_pos_pos a (Zpos b) Ha); romega with *. -Qed. - -Lemma ZO_mult_div_ge : forall a b:Z, a <= 0 -> a <= b*(a/b) <= 0. -Proof. - intros a b Ha. - destruct b as [ |b|b]. - simpl; auto with zarith. - split. - generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_neg_pos a (Zpos b) Ha); romega with *. - apply Zle_left_rev; unfold Zplus. - rewrite Zopp_mult_distr_r, <-ZOdiv_opp_l. - apply Zmult_le_0_compat; auto with zarith. - apply ZO_div_pos; auto with zarith. - change (Zneg b) with (-Zpos b); rewrite ZOdiv_opp_r, Zmult_opp_opp. - split. - generalize (ZO_div_mod_eq a (Zpos b)) (ZOmod_lt_neg_pos a (Zpos b) Ha); romega with *. - apply Zle_left_rev; unfold Zplus. - rewrite Zopp_mult_distr_r, <-ZOdiv_opp_l. - apply Zmult_le_0_compat; auto with zarith. - apply ZO_div_pos; auto with zarith. -Qed. - -(** The previous inequalities between [b*(a/b)] and [a] are exact - iff the modulo is zero. *) - -Lemma ZO_div_exact_full_1 : forall a b:Z, a = b*(a/b) -> a mod b = 0. -Proof. - intros; generalize (ZO_div_mod_eq a b); romega. -Qed. - -Lemma ZO_div_exact_full_2 : forall a b:Z, a mod b = 0 -> a = b*(a/b). -Proof. - intros; generalize (ZO_div_mod_eq a b); romega. -Qed. - -(** A modulo cannot grow beyond its starting point. *) - -Theorem ZOmod_le: forall a b, 0 <= a -> 0 <= b -> a mod b <= a. -Proof. - intros a b H1 H2. - destruct (Zle_lt_or_eq _ _ H2). - case (Zle_or_lt b a); intros H3. - case (ZOmod_lt_pos_pos a b); auto with zarith. - rewrite ZOmod_small; auto with zarith. - subst; rewrite ZOmod_0_r; auto with zarith. -Qed. - -(** Some additionnal inequalities about Zdiv. *) - -Theorem ZOdiv_le_upper_bound: - forall a b q, 0 < b -> a <= q*b -> a/b <= q. -Proof. - intros. - rewrite <- (ZO_div_mult q b); auto with zarith. - apply ZO_div_monotone; auto with zarith. -Qed. - -Theorem ZOdiv_lt_upper_bound: - forall a b q, 0 <= a -> 0 < b -> a < q*b -> a/b < q. -Proof. - intros a b q H1 H2 H3. - apply Zmult_lt_reg_r with b; auto with zarith. - apply Zle_lt_trans with (2 := H3). - pattern a at 2; rewrite (ZO_div_mod_eq a b); auto with zarith. - rewrite (Zmult_comm b); case (ZOmod_lt_pos_pos a b); auto with zarith. -Qed. - -Theorem ZOdiv_le_lower_bound: - forall a b q, 0 < b -> q*b <= a -> q <= a/b. -Proof. - intros. - rewrite <- (ZO_div_mult q b); auto with zarith. - apply ZO_div_monotone; auto with zarith. -Qed. - -Theorem ZOdiv_sgn: forall a b, - 0 <= Zsgn (a/b) * Zsgn a * Zsgn b. -Proof. - destruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith; - unfold ZOdiv; simpl; destruct Pdiv_eucl; simpl; destruct n; simpl; auto with zarith. -Qed. - -(** * Relations between usual operations and Zmod and Zdiv *) - -(** First, a result that used to be always valid with Zdiv, - but must be restricted here. - For instance, now (9+(-5)*2) mod 2 = -1 <> 1 = 9 mod 2 *) - -Lemma ZO_mod_plus : forall a b c:Z, - 0 <= (a+b*c) * a -> - (a + b * c) mod c = a mod c. -Proof. - intros; destruct (Z_eq_dec a 0) as [Ha|Ha]. - subst; simpl; rewrite ZOmod_0_l; apply ZO_mod_mult. - intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. - subst; do 2 rewrite ZOmod_0_r; romega. - symmetry; apply ZOmod_unique_full with (a/c+b); auto with zarith. - rewrite Remainder_equiv; split. - apply ZOmod_lt; auto. - apply Zmult_le_0_reg_r with (a*a); eauto. - destruct a; simpl; auto with zarith. - replace ((a mod c)*(a+b*c)*(a*a)) with (((a mod c)*a)*((a+b*c)*a)) by ring. - apply Zmult_le_0_compat; auto. - apply ZOmod_sgn2. - rewrite Zmult_plus_distr_r, Zmult_comm. - generalize (ZO_div_mod_eq a c); romega. -Qed. - -Lemma ZO_div_plus : forall a b c:Z, - 0 <= (a+b*c) * a -> c<>0 -> - (a + b * c) / c = a / c + b. -Proof. - intros; destruct (Z_eq_dec a 0) as [Ha|Ha]. - subst; simpl; apply ZO_div_mult; auto. - symmetry. - apply ZOdiv_unique_full with (a mod c); auto with zarith. - rewrite Remainder_equiv; split. - apply ZOmod_lt; auto. - apply Zmult_le_0_reg_r with (a*a); eauto. - destruct a; simpl; auto with zarith. - replace ((a mod c)*(a+b*c)*(a*a)) with (((a mod c)*a)*((a+b*c)*a)) by ring. - apply Zmult_le_0_compat; auto. - apply ZOmod_sgn2. - rewrite Zmult_plus_distr_r, Zmult_comm. - generalize (ZO_div_mod_eq a c); romega. -Qed. - -Theorem ZO_div_plus_l: forall a b c : Z, - 0 <= (a*b+c)*c -> b<>0 -> - b<>0 -> (a * b + c) / b = a + c / b. -Proof. - intros a b c; rewrite Zplus_comm; intros; rewrite ZO_div_plus; - try apply Zplus_comm; auto with zarith. -Qed. - -(** Cancellations. *) - -Lemma ZOdiv_mult_cancel_r : forall a b c:Z, - c<>0 -> (a*c)/(b*c) = a/b. -Proof. - intros a b c Hc. - destruct (Z_eq_dec b 0). - subst; simpl; do 2 rewrite ZOdiv_0_r; auto. - symmetry. - apply ZOdiv_unique_full with ((a mod b)*c); auto with zarith. - rewrite Remainder_equiv. - split. - do 2 rewrite Zabs_Zmult. - apply Zmult_lt_compat_r. - romega with *. - apply ZOmod_lt; auto. - replace ((a mod b)*c*(a*c)) with (((a mod b)*a)*(c*c)) by ring. - apply Zmult_le_0_compat. - apply ZOmod_sgn2. - destruct c; simpl; auto with zarith. - pattern a at 1; rewrite (ZO_div_mod_eq a b); ring. -Qed. - -Lemma ZOdiv_mult_cancel_l : forall a b c:Z, - c<>0 -> (c*a)/(c*b) = a/b. -Proof. - intros. - rewrite (Zmult_comm c a); rewrite (Zmult_comm c b). - apply ZOdiv_mult_cancel_r; auto. -Qed. - -Lemma ZOmult_mod_distr_l: forall a b c, - (c*a) mod (c*b) = c * (a mod b). -Proof. - intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. - subst; simpl; rewrite ZOmod_0_r; auto. - destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; repeat rewrite Zmult_0_r || rewrite ZOmod_0_r; auto. - assert (c*b <> 0). - contradict Hc; eapply Zmult_integral_l; eauto. - rewrite (Zplus_minus_eq _ _ _ (ZO_div_mod_eq (c*a) (c*b))). - rewrite (Zplus_minus_eq _ _ _ (ZO_div_mod_eq a b)). - rewrite ZOdiv_mult_cancel_l; auto with zarith. - ring. -Qed. - -Lemma ZOmult_mod_distr_r: forall a b c, - (a*c) mod (b*c) = (a mod b) * c. -Proof. - intros; repeat rewrite (fun x => (Zmult_comm x c)). - apply ZOmult_mod_distr_l; auto. -Qed. - -(** Operations modulo. *) - -Theorem ZOmod_mod: forall a n, (a mod n) mod n = a mod n. -Proof. - intros. - generalize (ZOmod_sgn2 a n). - pattern a at 2 4; rewrite (ZO_div_mod_eq a n); auto with zarith. - rewrite Zplus_comm; rewrite (Zmult_comm n). - intros. - apply sym_equal; apply ZO_mod_plus; auto with zarith. - rewrite Zmult_comm; auto. -Qed. - -Theorem ZOmult_mod: forall a b n, - (a * b) mod n = ((a mod n) * (b mod n)) mod n. -Proof. - intros. - generalize (Zmult_le_0_compat _ _ (ZOmod_sgn2 a n) (ZOmod_sgn2 b n)). - pattern a at 2 3; rewrite (ZO_div_mod_eq a n); auto with zarith. - pattern b at 2 3; rewrite (ZO_div_mod_eq b n); auto with zarith. - set (A:=a mod n); set (B:=b mod n); set (A':=a/n); set (B':=b/n). - replace (A*(n*A'+A)*(B*(n*B'+B))) with (((n*A' + A) * (n*B' + B))*(A*B)) - by ring. - replace ((n*A' + A) * (n*B' + B)) - with (A*B + (A'*B+B'*A+n*A'*B')*n) by ring. - intros. - apply ZO_mod_plus; auto with zarith. -Qed. - -(** addition and modulo - - Generally speaking, unlike with Zdiv, we don't have - (a+b) mod n = (a mod n + b mod n) mod n - for any a and b. - For instance, take (8 + (-10)) mod 3 = -2 whereas - (8 mod 3 + (-10 mod 3)) mod 3 = 1. *) - -Theorem ZOplus_mod: forall a b n, - 0 <= a * b -> - (a + b) mod n = (a mod n + b mod n) mod n. -Proof. - assert (forall a b n, 0<a -> 0<b -> - (a + b) mod n = (a mod n + b mod n) mod n). - intros a b n Ha Hb. - assert (H : 0<=a+b) by (romega with * ); revert H. - pattern a at 1 2; rewrite (ZO_div_mod_eq a n); auto with zarith. - pattern b at 1 2; rewrite (ZO_div_mod_eq b n); auto with zarith. - replace ((n * (a / n) + a mod n) + (n * (b / n) + b mod n)) - with ((a mod n + b mod n) + (a / n + b / n) * n) by ring. - intros. - apply ZO_mod_plus; auto with zarith. - apply Zmult_le_0_compat; auto with zarith. - apply Zplus_le_0_compat. - apply Zmult_le_reg_r with a; auto with zarith. - simpl; apply ZOmod_sgn2; auto. - apply Zmult_le_reg_r with b; auto with zarith. - simpl; apply ZOmod_sgn2; auto. - (* general situation *) - intros a b n Hab. - destruct (Z_eq_dec a 0). - subst; simpl; symmetry; apply ZOmod_mod. - destruct (Z_eq_dec b 0). - subst; simpl; do 2 rewrite Zplus_0_r; symmetry; apply ZOmod_mod. - assert (0<a /\ 0<b \/ a<0 /\ b<0). - destruct a; destruct b; simpl in *; intuition; romega with *. - destruct H0. - apply H; intuition. - rewrite <-(Zopp_involutive a), <-(Zopp_involutive b). - rewrite <- Zopp_plus_distr; rewrite ZOmod_opp_l. - rewrite (ZOmod_opp_l (-a)),(ZOmod_opp_l (-b)). - match goal with |- _ = (-?x+-?y) mod n => - rewrite <-(Zopp_plus_distr x y), ZOmod_opp_l end. - f_equal; apply H; auto with zarith. -Qed. - -Lemma ZOplus_mod_idemp_l: forall a b n, - 0 <= a * b -> - (a mod n + b) mod n = (a + b) mod n. -Proof. - intros. - rewrite ZOplus_mod. - rewrite ZOmod_mod. - symmetry. - apply ZOplus_mod; auto. - destruct (Z_eq_dec a 0). - subst; rewrite ZOmod_0_l; auto. - destruct (Z_eq_dec b 0). - subst; rewrite Zmult_0_r; auto with zarith. - apply Zmult_le_reg_r with (a*b). - assert (a*b <> 0). - intro Hab. - rewrite (Zmult_integral_l _ _ n1 Hab) in n0; auto with zarith. - auto with zarith. - simpl. - replace (a mod n * b * (a*b)) with ((a mod n * a)*(b*b)) by ring. - apply Zmult_le_0_compat. - apply ZOmod_sgn2. - destruct b; simpl; auto with zarith. -Qed. - -Lemma ZOplus_mod_idemp_r: forall a b n, - 0 <= a*b -> - (b + a mod n) mod n = (b + a) mod n. -Proof. - intros. - rewrite Zplus_comm, (Zplus_comm b a). - apply ZOplus_mod_idemp_l; auto. -Qed. - -Lemma ZOmult_mod_idemp_l: forall a b n, (a mod n * b) mod n = (a * b) mod n. -Proof. - intros; rewrite ZOmult_mod, ZOmod_mod, <- ZOmult_mod; auto. -Qed. - -Lemma ZOmult_mod_idemp_r: forall a b n, (b * (a mod n)) mod n = (b * a) mod n. -Proof. - intros; rewrite ZOmult_mod, ZOmod_mod, <- ZOmult_mod; auto. -Qed. - -(** Unlike with Zdiv, the following result is true without restrictions. *) - -Lemma ZOdiv_ZOdiv : forall a b c, (a/b)/c = a/(b*c). -Proof. - (* particular case: a, b, c positive *) - assert (forall a b c, a>0 -> b>0 -> c>0 -> (a/b)/c = a/(b*c)). - intros a b c H H0 H1. - pattern a at 2;rewrite (ZO_div_mod_eq a b). - pattern (a/b) at 2;rewrite (ZO_div_mod_eq (a/b) c). - replace (b * (c * (a / b / c) + (a / b) mod c) + a mod b) with - ((a / b / c)*(b * c) + (b * ((a / b) mod c) + a mod b)) by ring. - assert (b*c<>0). - intro H2; - assert (H3: c <> 0) by auto with zarith; - rewrite (Zmult_integral_l _ _ H3 H2) in H0; auto with zarith. - assert (0<=a/b) by (apply (ZO_div_pos a b); auto with zarith). - assert (0<=a mod b < b) by (apply ZOmod_lt_pos_pos; auto with zarith). - assert (0<=(a/b) mod c < c) by - (apply ZOmod_lt_pos_pos; auto with zarith). - rewrite ZO_div_plus_l; auto with zarith. - rewrite (ZOdiv_small (b * ((a / b) mod c) + a mod b)). - ring. - split. - apply Zplus_le_0_compat;auto with zarith. - apply Zle_lt_trans with (b * ((a / b) mod c) + (b-1)). - apply Zplus_le_compat;auto with zarith. - apply Zle_lt_trans with (b * (c-1) + (b - 1)). - apply Zplus_le_compat;auto with zarith. - replace (b * (c - 1) + (b - 1)) with (b*c-1);try ring;auto with zarith. - repeat (apply Zmult_le_0_compat || apply Zplus_le_0_compat); auto with zarith. - apply (ZO_div_pos (a/b) c); auto with zarith. - (* b c positive, a general *) - assert (forall a b c, b>0 -> c>0 -> (a/b)/c = a/(b*c)). - intros; destruct a as [ |a|a]; try reflexivity. - apply H; auto with zarith. - change (Zneg a) with (-Zpos a); repeat rewrite ZOdiv_opp_l. - f_equal; apply H; auto with zarith. - (* c positive, a b general *) - assert (forall a b c, c>0 -> (a/b)/c = a/(b*c)). - intros; destruct b as [ |b|b]. - repeat rewrite ZOdiv_0_r; reflexivity. - apply H0; auto with zarith. - change (Zneg b) with (-Zpos b); - repeat (rewrite ZOdiv_opp_r || rewrite ZOdiv_opp_l || rewrite <- Zopp_mult_distr_l). - f_equal; apply H0; auto with zarith. - (* a b c general *) - intros; destruct c as [ |c|c]. - rewrite Zmult_0_r; repeat rewrite ZOdiv_0_r; reflexivity. - apply H1; auto with zarith. - change (Zneg c) with (-Zpos c); - rewrite <- Zopp_mult_distr_r; do 2 rewrite ZOdiv_opp_r. - f_equal; apply H1; auto with zarith. -Qed. - -(** A last inequality: *) - -Theorem ZOdiv_mult_le: - forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a/b) <= (c*a)/b. -Proof. - intros a b c Ha Hb Hc. - destruct (Zle_lt_or_eq _ _ Ha); - [ | subst; rewrite ZOdiv_0_l, Zmult_0_r, ZOdiv_0_l; auto]. - destruct (Zle_lt_or_eq _ _ Hb); - [ | subst; rewrite ZOdiv_0_r, ZOdiv_0_r, Zmult_0_r; auto]. - destruct (Zle_lt_or_eq _ _ Hc); - [ | subst; rewrite ZOdiv_0_l; auto]. - case (ZOmod_lt_pos_pos a b); auto with zarith; intros Hu1 Hu2. - case (ZOmod_lt_pos_pos c b); auto with zarith; intros Hv1 Hv2. - apply Zmult_le_reg_r with b; auto with zarith. - rewrite <- Zmult_assoc. - replace (a / b * b) with (a - a mod b). - replace (c * a / b * b) with (c * a - (c * a) mod b). - rewrite Zmult_minus_distr_l. - unfold Zminus; apply Zplus_le_compat_l. - match goal with |- - ?X <= -?Y => assert (Y <= X); auto with zarith end. - apply Zle_trans with ((c mod b) * (a mod b)); auto with zarith. - rewrite ZOmult_mod; auto with zarith. - apply (ZOmod_le ((c mod b) * (a mod b)) b); auto with zarith. - apply Zmult_le_compat_r; auto with zarith. - apply (ZOmod_le c b); auto. - pattern (c * a) at 1; rewrite (ZO_div_mod_eq (c * a) b); try ring; - auto with zarith. - pattern a at 1; rewrite (ZO_div_mod_eq a b); try ring; auto with zarith. -Qed. - -(** ZOmod is related to divisibility (see more in Znumtheory) *) - -Lemma ZOmod_divides : forall a b, - a mod b = 0 <-> exists c, a = b*c. -Proof. - split; intros. - exists (a/b). - pattern a at 1; rewrite (ZO_div_mod_eq a b). - rewrite H; auto with zarith. - destruct H as [c Hc]. - destruct (Z_eq_dec b 0). - subst b; simpl in *; subst a; auto. - symmetry. - apply ZOmod_unique_full with c; auto with zarith. - red; romega with *. -Qed. - -(** * Interaction with "historic" Zdiv *) - -(** They agree at least on positive numbers: *) - -Theorem ZOdiv_eucl_Zdiv_eucl_pos : forall a b:Z, 0 <= a -> 0 < b -> - a/b = Zdiv.Zdiv a b /\ a mod b = Zdiv.Zmod a b. -Proof. - intros. - apply Zdiv.Zdiv_mod_unique with b. - apply ZOmod_lt_pos; auto with zarith. - rewrite Zabs_eq; auto with *; apply Zdiv.Z_mod_lt; auto with *. - rewrite <- Zdiv.Z_div_mod_eq; auto with *. - symmetry; apply ZO_div_mod_eq; auto with *. -Qed. - -Theorem ZOdiv_Zdiv_pos : forall a b, 0 <= a -> 0 <= b -> - a/b = Zdiv.Zdiv a b. -Proof. - intros a b Ha Hb. - destruct (Zle_lt_or_eq _ _ Hb). - generalize (ZOdiv_eucl_Zdiv_eucl_pos a b Ha H); intuition. - subst; rewrite ZOdiv_0_r, Zdiv.Zdiv_0_r; reflexivity. -Qed. - -Theorem ZOmod_Zmod_pos : forall a b, 0 <= a -> 0 < b -> - a mod b = Zdiv.Zmod a b. -Proof. - intros a b Ha Hb; generalize (ZOdiv_eucl_Zdiv_eucl_pos a b Ha Hb); - intuition. -Qed. - -(** Modulos are null at the same places *) - -Theorem ZOmod_Zmod_zero : forall a b, b<>0 -> - (a mod b = 0 <-> Zdiv.Zmod a b = 0). -Proof. - intros. - rewrite ZOmod_divides, Zdiv.Zmod_divides; intuition. -Qed. +Require Import BinInt Zquot. + +Notation ZO_div_mod_eq := Z.quot_rem' (only parsing). +Notation ZOmod_lt := Zrem_lt (only parsing). +Notation ZOmod_sgn := Zrem_sgn (only parsing). +Notation ZOmod_sgn2 := Zrem_sgn2 (only parsing). +Notation ZOmod_lt_pos := Zrem_lt_pos (only parsing). +Notation ZOmod_lt_neg := Zrem_lt_neg (only parsing). +Notation ZOmod_lt_pos_pos := Zrem_lt_pos_pos (only parsing). +Notation ZOmod_lt_pos_neg := Zrem_lt_pos_neg (only parsing). +Notation ZOmod_lt_neg_pos := Zrem_lt_neg_pos (only parsing). +Notation ZOmod_lt_neg_neg := Zrem_lt_neg_neg (only parsing). + +Notation ZOdiv_opp_l := Zquot_opp_l (only parsing). +Notation ZOdiv_opp_r := Zquot_opp_r (only parsing). +Notation ZOmod_opp_l := Zrem_opp_l (only parsing). +Notation ZOmod_opp_r := Zrem_opp_r (only parsing). +Notation ZOdiv_opp_opp := Zquot_opp_opp (only parsing). +Notation ZOmod_opp_opp := Zrem_opp_opp (only parsing). + +Notation Remainder := Remainder (only parsing). +Notation Remainder_alt := Remainder_alt (only parsing). +Notation Remainder_equiv := Remainder_equiv (only parsing). +Notation ZOdiv_mod_unique_full := Zquot_mod_unique_full (only parsing). +Notation ZOdiv_unique_full := Zquot_unique_full (only parsing). +Notation ZOdiv_unique := Zquot_unique (only parsing). +Notation ZOmod_unique_full := Zrem_unique_full (only parsing). +Notation ZOmod_unique := Zrem_unique (only parsing). + +Notation ZOmod_0_l := Zrem_0_l (only parsing). +Notation ZOmod_0_r := Zrem_0_r (only parsing). +Notation ZOdiv_0_l := Zquot_0_l (only parsing). +Notation ZOdiv_0_r := Zquot_0_r (only parsing). +Notation ZOmod_1_r := Zrem_1_r (only parsing). +Notation ZOdiv_1_r := Zquot_1_r (only parsing). +Notation ZOdiv_1_l := Zquot_1_l (only parsing). +Notation ZOmod_1_l := Zrem_1_l (only parsing). +Notation ZO_div_same := Z_quot_same (only parsing). +Notation ZO_mod_same := Z_rem_same (only parsing). +Notation ZO_mod_mult := Z_rem_mult (only parsing). +Notation ZO_div_mult := Z_quot_mult (only parsing). + +Notation ZO_div_pos := Z_quot_pos (only parsing). +Notation ZO_div_lt := Z_quot_lt (only parsing). +Notation ZOdiv_small := Zquot_small (only parsing). +Notation ZOmod_small := Zrem_small (only parsing). +Notation ZO_div_monotone := Z_quot_monotone (only parsing). +Notation ZO_mult_div_le := Z_mult_quot_le (only parsing). +Notation ZO_mult_div_ge := Z_mult_quot_ge (only parsing). +Definition ZO_div_exact_full_1 a b := proj1 (Z_quot_exact_full a b). +Definition ZO_div_exact_full_2 a b := proj2 (Z_quot_exact_full a b). +Notation ZOmod_le := Zrem_le (only parsing). +Notation ZOdiv_le_upper_bound := Zquot_le_upper_bound (only parsing). +Notation ZOdiv_lt_upper_bound := Zquot_lt_upper_bound (only parsing). +Notation ZOdiv_le_lower_bound := Zquot_le_lower_bound (only parsing). +Notation ZOdiv_sgn := Zquot_sgn (only parsing). + +Notation ZO_mod_plus := Z_rem_plus (only parsing). +Notation ZO_div_plus := Z_quot_plus (only parsing). +Notation ZO_div_plus_l := Z_quot_plus_l (only parsing). +Notation ZOdiv_mult_cancel_r := Zquot_mult_cancel_r (only parsing). +Notation ZOdiv_mult_cancel_l := Zquot_mult_cancel_l (only parsing). +Notation ZOmult_mod_distr_l := Zmult_rem_distr_l (only parsing). +Notation ZOmult_mod_distr_r := Zmult_rem_distr_r (only parsing). +Notation ZOmod_mod := Zrem_rem (only parsing). +Notation ZOmult_mod := Zmult_rem (only parsing). +Notation ZOplus_mod := Zplus_rem (only parsing). +Notation ZOplus_mod_idemp_l := Zplus_rem_idemp_l (only parsing). +Notation ZOplus_mod_idemp_r := Zplus_rem_idemp_r (only parsing). +Notation ZOmult_mod_idemp_l := Zmult_rem_idemp_l (only parsing). +Notation ZOmult_mod_idemp_r := Zmult_rem_idemp_r (only parsing). +Notation ZOdiv_ZOdiv := Zquot_Zquot (only parsing). +Notation ZOdiv_mult_le := Zquot_mult_le (only parsing). +Notation ZOmod_divides := Zrem_divides (only parsing). + +Notation ZOdiv_eucl_Zdiv_eucl_pos := Zquotrem_Zdiv_eucl_pos (only parsing). +Notation ZOdiv_Zdiv_pos := Zquot_Zdiv_pos (only parsing). +Notation ZOmod_Zmod_pos := Zrem_Zmod_pos (only parsing). +Notation ZOmod_Zmod_zero := Zrem_Zmod_zero (only parsing). diff --git a/theories/ZArith/ZOdiv_def.v b/theories/ZArith/ZOdiv_def.v index 71d6cad4..38d25797 100644 --- a/theories/ZArith/ZOdiv_def.v +++ b/theories/ZArith/ZOdiv_def.v @@ -1,136 +1,15 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) +Require Import BinInt. -Require Import BinPos BinNat Nnat ZArith_base. +Notation ZOdiv_eucl := Z.quotrem (only parsing). +Notation ZOdiv := Z.quot (only parsing). +Notation ZOmod := Z.rem (only parsing). -Open Scope Z_scope. - -Definition NPgeb (a:N)(b:positive) := - match a with - | N0 => false - | Npos na => match Pcompare na b Eq with Lt => false | _ => true end - end. - -Fixpoint Pdiv_eucl (a b:positive) : N * N := - match a with - | xH => - match b with xH => (1, 0)%N | _ => (0, 1)%N end - | xO a' => - let (q, r) := Pdiv_eucl a' b in - let r' := (2 * r)%N in - if (NPgeb r' b) then (2 * q + 1, (Nminus r' (Npos b)))%N - else (2 * q, r')%N - | xI a' => - let (q, r) := Pdiv_eucl a' b in - let r' := (2 * r + 1)%N in - if (NPgeb r' b) then (2 * q + 1, (Nminus r' (Npos b)))%N - else (2 * q, r')%N - end. - -Definition ZOdiv_eucl (a b:Z) : Z * Z := - match a, b with - | Z0, _ => (Z0, Z0) - | _, Z0 => (Z0, a) - | Zpos na, Zpos nb => - let (nq, nr) := Pdiv_eucl na nb in - (Z_of_N nq, Z_of_N nr) - | Zneg na, Zpos nb => - let (nq, nr) := Pdiv_eucl na nb in - (Zopp (Z_of_N nq), Zopp (Z_of_N nr)) - | Zpos na, Zneg nb => - let (nq, nr) := Pdiv_eucl na nb in - (Zopp (Z_of_N nq), Z_of_N nr) - | Zneg na, Zneg nb => - let (nq, nr) := Pdiv_eucl na nb in - (Z_of_N nq, Zopp (Z_of_N nr)) - end. - -Definition ZOdiv a b := fst (ZOdiv_eucl a b). -Definition ZOmod a b := snd (ZOdiv_eucl a b). - - -Definition Ndiv_eucl (a b:N) : N * N := - match a, b with - | N0, _ => (N0, N0) - | _, N0 => (N0, a) - | Npos na, Npos nb => Pdiv_eucl na nb - end. - -Definition Ndiv a b := fst (Ndiv_eucl a b). -Definition Nmod a b := snd (Ndiv_eucl a b). - - -(* Proofs of specifications for these euclidean divisions. *) - -Theorem NPgeb_correct: forall (a:N)(b:positive), - if NPgeb a b then a = (Nminus a (Npos b) + Npos b)%N else True. -Proof. - destruct a; intros; simpl; auto. - generalize (Pcompare_Eq_eq p b). - case_eq (Pcompare p b Eq); intros; auto. - rewrite H0; auto. - now rewrite Pminus_mask_diag. - destruct (Pminus_mask_Gt p b H) as [d [H2 [H3 _]]]. - rewrite H2. rewrite <- H3. - simpl; f_equal; apply Pplus_comm. -Qed. - -Hint Rewrite Z_of_N_plus Z_of_N_mult Z_of_N_minus Zmult_1_l Zmult_assoc - Zmult_plus_distr_l Zmult_plus_distr_r : zdiv. -Hint Rewrite <- Zplus_assoc : zdiv. - -Theorem Pdiv_eucl_correct: forall a b, - let (q,r) := Pdiv_eucl a b in - Zpos a = Z_of_N q * Zpos b + Z_of_N r. -Proof. - induction a; cbv beta iota delta [Pdiv_eucl]; fold Pdiv_eucl; cbv zeta. - intros b; generalize (IHa b); case Pdiv_eucl. - intros q1 r1 Hq1. - generalize (NPgeb_correct (2 * r1 + 1) b); case NPgeb; intros H. - set (u := Nminus (2 * r1 + 1) (Npos b)) in * |- *. - assert (HH: Z_of_N u = (Z_of_N (2 * r1 + 1) - Zpos b)%Z). - rewrite H; autorewrite with zdiv; simpl. - rewrite Zplus_comm, Zminus_plus; trivial. - rewrite HH; autorewrite with zdiv; simpl Z_of_N. - rewrite Zpos_xI, Hq1. - autorewrite with zdiv; f_equal; rewrite Zplus_minus; trivial. - rewrite Zpos_xI, Hq1; autorewrite with zdiv; auto. - intros b; generalize (IHa b); case Pdiv_eucl. - intros q1 r1 Hq1. - generalize (NPgeb_correct (2 * r1) b); case NPgeb; intros H. - set (u := Nminus (2 * r1) (Npos b)) in * |- *. - assert (HH: Z_of_N u = (Z_of_N (2 * r1) - Zpos b)%Z). - rewrite H; autorewrite with zdiv; simpl. - rewrite Zplus_comm, Zminus_plus; trivial. - rewrite HH; autorewrite with zdiv; simpl Z_of_N. - rewrite Zpos_xO, Hq1. - autorewrite with zdiv; f_equal; rewrite Zplus_minus; trivial. - rewrite Zpos_xO, Hq1; autorewrite with zdiv; auto. - destruct b; auto. -Qed. - -Theorem ZOdiv_eucl_correct: forall a b, - let (q,r) := ZOdiv_eucl a b in a = q * b + r. -Proof. - destruct a; destruct b; simpl; auto; - generalize (Pdiv_eucl_correct p p0); case Pdiv_eucl; auto; intros; - try change (Zneg p) with (Zopp (Zpos p)); rewrite H. - destruct n; auto. - repeat (rewrite Zopp_plus_distr || rewrite Zopp_mult_distr_l); trivial. - repeat (rewrite Zopp_plus_distr || rewrite Zopp_mult_distr_r); trivial. -Qed. - -Theorem Ndiv_eucl_correct: forall a b, - let (q,r) := Ndiv_eucl a b in a = (q * b + r)%N. -Proof. - destruct a; destruct b; simpl; auto; - generalize (Pdiv_eucl_correct p p0); case Pdiv_eucl; auto; intros; - destruct n; destruct n0; simpl; simpl in H; try discriminate; - injection H; intros; subst; trivial. -Qed. +Notation ZOdiv_eucl_correct := Z.quotrem_eq. diff --git a/theories/ZArith/ZOrderedType.v b/theories/ZArith/ZOrderedType.v deleted file mode 100644 index de4e4e98..00000000 --- a/theories/ZArith/ZOrderedType.v +++ /dev/null @@ -1,60 +0,0 @@ -(************************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) -(* \VV/ **************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(************************************************************************) - -Require Import BinInt Zcompare Zorder Zbool ZArith_dec - Equalities Orders OrdersTac. - -Local Open Scope Z_scope. - -(** * DecidableType structure for binary integers *) - -Module Z_as_UBE <: UsualBoolEq. - Definition t := Z. - Definition eq := @eq Z. - Definition eqb := Zeq_bool. - Definition eqb_eq x y := iff_sym (Zeq_is_eq_bool x y). -End Z_as_UBE. - -Module Z_as_DT <: UsualDecidableTypeFull := Make_UDTF Z_as_UBE. - -(** Note that the last module fulfills by subtyping many other - interfaces, such as [DecidableType] or [EqualityType]. *) - - -(** * OrderedType structure for binary integers *) - -Module Z_as_OT <: OrderedTypeFull. - Include Z_as_DT. - Definition lt := Zlt. - Definition le := Zle. - Definition compare := Zcompare. - - Instance lt_strorder : StrictOrder Zlt. - Proof. split; [ exact Zlt_irrefl | exact Zlt_trans ]. Qed. - - Instance lt_compat : Proper (Logic.eq==>Logic.eq==>iff) Zlt. - Proof. repeat red; intros; subst; auto. Qed. - - Definition le_lteq := Zle_lt_or_eq_iff. - Definition compare_spec := Zcompare_spec. - -End Z_as_OT. - -(** Note that [Z_as_OT] can also be seen as a [UsualOrderedType] - and a [OrderedType] (and also as a [DecidableType]). *) - - - -(** * An [order] tactic for integers *) - -Module ZOrder := OTF_to_OrderTac Z_as_OT. -Ltac z_order := ZOrder.order. - -(** Note that [z_order] is domain-agnostic: it will not prove - [1<=2] or [x<=x+x], but rather things like [x<=y -> y<=x -> x=y]. *) - diff --git a/theories/ZArith/Zabs.v b/theories/ZArith/Zabs.v index 0f6e62b7..08d1a931 100644 --- a/theories/ZArith/Zabs.v +++ b/theories/ZArith/Zabs.v @@ -1,226 +1,106 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zabs.v 14641 2011-11-06 11:59:10Z herbelin $ i*) -(** Binary Integers (Pierre Crégut (CNET, Lannion, France) *) +(** Binary Integers : properties of absolute value *) +(** Initial author : Pierre Crégut (CNET, Lannion, France) *) + +(** THIS FILE IS DEPRECATED. + It is now almost entirely made of compatibility formulations + for results already present in BinInt.Z. *) Require Import Arith_base. Require Import BinPos. Require Import BinInt. +Require Import Zcompare. Require Import Zorder. -Require Import Zmax. Require Import Znat. Require Import ZArith_dec. -Open Local Scope Z_scope. +Local Open Scope Z_scope. (**********************************************************************) (** * Properties of absolute value *) -Lemma Zabs_eq : forall n:Z, 0 <= n -> Zabs n = n. -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. -Qed. - -Theorem Zabs_Zopp : forall n:Z, Zabs (- n) = Zabs n. -Proof. - intros z; case z; simpl in |- *; auto. -Qed. +Notation Zabs_eq := Z.abs_eq (compat "8.3"). +Notation Zabs_non_eq := Z.abs_neq (compat "8.3"). +Notation Zabs_Zopp := Z.abs_opp (compat "8.3"). +Notation Zabs_pos := Z.abs_nonneg (compat "8.3"). +Notation Zabs_involutive := Z.abs_involutive (compat "8.3"). +Notation Zabs_eq_case := Z.abs_eq_cases (compat "8.3"). +Notation Zabs_triangle := Z.abs_triangle (compat "8.3"). +Notation Zsgn_Zabs := Z.sgn_abs (compat "8.3"). +Notation Zabs_Zsgn := Z.abs_sgn (compat "8.3"). +Notation Zabs_Zmult := Z.abs_mul (compat "8.3"). +Notation Zabs_square := Z.abs_square (compat "8.3"). (** * 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). + (n >= 0 -> P n) -> (n <= 0 -> P (- n)) -> P (Z.abs 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. apply Z.abs_case_strong; Z.swap_greater; trivial. + intros x y Hx; now subst. Qed. -Theorem Zabs_intro : forall P (n:Z), P (- n) -> P n -> P (Zabs n). +Theorem Zabs_intro : forall P (n:Z), P (- n) -> P n -> P (Z.abs n). Proof. - intros P z; case z; simpl in |- *; auto. + now destruct n. Qed. -Definition Zabs_dec : forall x:Z, {x = Zabs x} + {x = - Zabs x}. +Definition Zabs_dec : forall x:Z, {x = Z.abs x} + {x = - Z.abs x}. Proof. - intro x; destruct x; auto with arith. + destruct x; auto. Defined. -Lemma Zabs_pos : forall n:Z, 0 <= Zabs n. - intro x; destruct x; auto with arith; compute in |- *; intros H; inversion H. -Qed. - -Lemma Zabs_involutive : forall x:Z, Zabs (Zabs x) = Zabs x. -Proof. - intros; apply Zabs_eq; apply Zabs_pos. -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. -Qed. - -Lemma Zabs_spec : forall x:Z, - 0 <= x /\ Zabs x = x \/ - 0 > x /\ Zabs x = -x. -Proof. - intros; unfold Zabs, Zle, Zgt; destruct x; simpl; intuition discriminate. -Qed. - -(** * 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. -Qed. - -(** * 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. -Qed. - -Lemma Zabs_Zsgn : forall n:Z, Zabs n * Zsgn n = n. -Proof. - 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. -Qed. - -Theorem Zabs_square : forall a, Zabs a * Zabs a = a * a. +Lemma Zabs_spec x : + 0 <= x /\ Z.abs x = x \/ + 0 > x /\ Z.abs x = -x. Proof. - destruct a; simpl; auto. -Qed. - -(** * Results about absolute value in nat. *) - -Theorem inj_Zabs_nat : forall z:Z, Z_of_nat (Zabs_nat z) = Zabs z. -Proof. - destruct z; simpl; auto; symmetry; apply Zpos_eq_Z_of_nat_o_nat_of_P. -Qed. - -Theorem Zabs_nat_Z_of_nat: forall n, Zabs_nat (Z_of_nat n) = n. -Proof. - destruct n; simpl; auto. - apply nat_of_P_o_P_of_succ_nat_eq_succ. -Qed. - -Lemma Zabs_nat_mult: forall n m:Z, Zabs_nat (n*m) = (Zabs_nat n * Zabs_nat m)%nat. -Proof. - intros; apply inj_eq_rev. - rewrite inj_mult; repeat rewrite inj_Zabs_nat; apply Zabs_Zmult. -Qed. - -Lemma Zabs_nat_Zsucc: - forall p, 0 <= p -> Zabs_nat (Zsucc p) = S (Zabs_nat p). -Proof. - intros; apply inj_eq_rev. - rewrite inj_S; repeat rewrite inj_Zabs_nat, Zabs_eq; auto with zarith. -Qed. - -Lemma Zabs_nat_Zplus: - forall x y, 0<=x -> 0<=y -> Zabs_nat (x+y) = (Zabs_nat x + Zabs_nat y)%nat. -Proof. - intros; apply inj_eq_rev. - rewrite inj_plus; repeat rewrite inj_Zabs_nat, Zabs_eq; auto with zarith. - apply Zplus_le_0_compat; auto. -Qed. - -Lemma Zabs_nat_Zminus: - forall x y, 0 <= x <= y -> Zabs_nat (y - x) = (Zabs_nat y - Zabs_nat x)%nat. -Proof. - intros x y (H,H'). - assert (0 <= y) by (apply Zle_trans with x; auto). - assert (0 <= y-x) by (apply Zle_minus_le_0; auto). - apply inj_eq_rev. - rewrite inj_minus; repeat rewrite inj_Zabs_nat, Zabs_eq; auto. - rewrite Zmax_right; auto. -Qed. - -Lemma Zabs_nat_le : - forall n m:Z, 0 <= n <= m -> (Zabs_nat n <= Zabs_nat m)%nat. -Proof. - intros n m (H,H'); apply inj_le_rev. - repeat rewrite inj_Zabs_nat, Zabs_eq; auto. - apply Zle_trans with n; auto. -Qed. - -Lemma Zabs_nat_lt : - forall n m:Z, 0 <= n < m -> (Zabs_nat n < Zabs_nat m)%nat. -Proof. - intros n m (H,H'); apply inj_lt_rev. - repeat rewrite inj_Zabs_nat, Zabs_eq; auto. - apply Zlt_le_weak; apply Zle_lt_trans with n; auto. + Z.swap_greater. apply Z.abs_spec. Qed. (** * Some results about the sign function. *) -Lemma Zsgn_Zmult : forall a b, Zsgn (a*b) = Zsgn a * Zsgn b. -Proof. - destruct a; destruct b; simpl; auto. -Qed. - -Lemma Zsgn_Zopp : forall a, Zsgn (-a) = - Zsgn a. -Proof. - destruct a; simpl; auto. -Qed. +Notation Zsgn_Zmult := Z.sgn_mul (compat "8.3"). +Notation Zsgn_Zopp := Z.sgn_opp (compat "8.3"). +Notation Zsgn_pos := Z.sgn_pos_iff (compat "8.3"). +Notation Zsgn_neg := Z.sgn_neg_iff (compat "8.3"). +Notation Zsgn_null := Z.sgn_null_iff (compat "8.3"). (** A characterization of the sign function: *) -Lemma Zsgn_spec : forall x:Z, - 0 < x /\ Zsgn x = 1 \/ - 0 = x /\ Zsgn x = 0 \/ - 0 > x /\ Zsgn x = -1. +Lemma Zsgn_spec x : + 0 < x /\ Z.sgn x = 1 \/ + 0 = x /\ Z.sgn x = 0 \/ + 0 > x /\ Z.sgn x = -1. Proof. - intros; unfold Zsgn, Zle, Zgt; destruct x; compute; intuition. + intros. Z.swap_greater. apply Z.sgn_spec. Qed. -Lemma Zsgn_pos : forall x:Z, Zsgn x = 1 <-> 0 < x. -Proof. - destruct x; now intuition. -Qed. +(** Compatibility *) -Lemma Zsgn_neg : forall x:Z, Zsgn x = -1 <-> x < 0. +Notation inj_Zabs_nat := Zabs2Nat.id_abs (compat "8.3"). +Notation Zabs_nat_Z_of_nat := Zabs2Nat.id (compat "8.3"). +Notation Zabs_nat_mult := Zabs2Nat.inj_mul (compat "8.3"). +Notation Zabs_nat_Zsucc := Zabs2Nat.inj_succ (compat "8.3"). +Notation Zabs_nat_Zplus := Zabs2Nat.inj_add (compat "8.3"). +Notation Zabs_nat_Zminus := (fun n m => Zabs2Nat.inj_sub m n) (compat "8.3"). +Notation Zabs_nat_compare := Zabs2Nat.inj_compare (compat "8.3"). + +Lemma Zabs_nat_le n m : 0 <= n <= m -> (Z.abs_nat n <= Z.abs_nat m)%nat. Proof. - destruct x; now intuition. + intros (H,H'). apply Zabs2Nat.inj_le; trivial. now transitivity n. Qed. -Lemma Zsgn_null : forall x:Z, Zsgn x = 0 <-> x = 0. +Lemma Zabs_nat_lt n m : 0 <= n < m -> (Z.abs_nat n < Z.abs_nat m)%nat. Proof. - destruct x; now intuition. + intros (H,H'). apply Zabs2Nat.inj_lt; trivial. + transitivity n; trivial. now apply Z.lt_le_incl. Qed. - diff --git a/theories/ZArith/Zbool.v b/theories/ZArith/Zbool.v index a4eebfb2..f20bc4bb 100644 --- a/theories/ZArith/Zbool.v +++ b/theories/ZArith/Zbool.v @@ -1,13 +1,11 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zbool.v 14641 2011-11-06 11:59:10Z herbelin $ *) - Require Import BinInt. Require Import Zeven. Require Import Zorder. @@ -15,8 +13,7 @@ Require Import Zcompare. Require Import ZArith_dec. Require Import Sumbool. -Unset Boxed Definitions. -Open Local Scope Z_scope. +Local Open Scope Z_scope. (** * Boolean operations from decidability of order *) (** The decidability of equality and order relations over @@ -28,7 +25,7 @@ Definition Z_ge_lt_bool (x y:Z) := bool_of_sumbool (Z_ge_lt_dec x y). Definition Z_le_gt_bool (x y:Z) := bool_of_sumbool (Z_le_gt_dec x y). Definition Z_gt_le_bool (x y:Z) := bool_of_sumbool (Z_gt_le_dec x y). -Definition Z_eq_bool (x y:Z) := bool_of_sumbool (Z_eq_dec x y). +Definition Z_eq_bool (x y:Z) := bool_of_sumbool (Z.eq_dec x y). 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). @@ -36,29 +33,13 @@ Definition Zeven_odd_bool (x:Z) := bool_of_sumbool (Zeven_odd_dec x). (**********************************************************************) (** * Boolean comparisons of binary integers *) -Definition Zle_bool (x y:Z) := - match x ?= y with - | Gt => false - | _ => true - end. +Notation Zle_bool := Z.leb (compat "8.3"). +Notation Zge_bool := Z.geb (compat "8.3"). +Notation Zlt_bool := Z.ltb (compat "8.3"). +Notation Zgt_bool := Z.gtb (compat "8.3"). -Definition Zge_bool (x y:Z) := - match x ?= y with - | Lt => false - | _ => true - end. - -Definition Zlt_bool (x y:Z) := - match x ?= y with - | Lt => true - | _ => false - end. - -Definition Zgt_bool (x y:Z) := - match x ?= y with - | Gt => true - | _ => false - end. +(** We now provide a direct [Z.eqb] that doesn't refer to [Z.compare]. + The old [Zeq_bool] is kept for compatibility. *) Definition Zeq_bool (x y:Z) := match x ?= y with @@ -74,162 +55,130 @@ Definition Zneq_bool (x y:Z) := (** Properties in term of [if ... then ... else ...] *) -Lemma Zle_cases : - forall n m:Z, if Zle_bool n m then (n <= m) else (n > m). +Lemma Zle_cases n m : if n <=? m then n <= m else n > m. Proof. - intros x y; unfold Zle_bool, Zle, Zgt in |- *. - case (x ?= y); auto; discriminate. + case Z.leb_spec; now Z.swap_greater. Qed. -Lemma Zlt_cases : - forall n m:Z, if Zlt_bool n m then (n < m) else (n >= m). +Lemma Zlt_cases n m : if n <? m then n < m else n >= m. Proof. - intros x y; unfold Zlt_bool, Zlt, Zge in |- *. - case (x ?= y); auto; discriminate. + case Z.ltb_spec; now Z.swap_greater. Qed. -Lemma Zge_cases : - forall n m:Z, if Zge_bool n m then (n >= m) else (n < m). +Lemma Zge_cases n m : if n >=? m then n >= m else n < m. Proof. - intros x y; unfold Zge_bool, Zge, Zlt in |- *. - case (x ?= y); auto; discriminate. + rewrite Z.geb_leb. case Z.leb_spec; now Z.swap_greater. Qed. -Lemma Zgt_cases : - forall n m:Z, if Zgt_bool n m then (n > m) else (n <= m). +Lemma Zgt_cases n m : if n >? m then n > m else n <= m. Proof. - intros x y; unfold Zgt_bool, Zgt, Zle in |- *. - case (x ?= y); auto; discriminate. + rewrite Z.gtb_ltb. case Z.ltb_spec; now Z.swap_greater. Qed. -(** Lemmas on [Zle_bool] used in contrib/graphs *) +(** Lemmas on [Z.leb] used in contrib/graphs *) -Lemma Zle_bool_imp_le : forall n m:Z, Zle_bool n m = true -> (n <= m). +Lemma Zle_bool_imp_le n m : (n <=? m) = true -> (n <= m). Proof. - unfold Zle_bool, Zle in |- *. intros x y. unfold not in |- *. - case (x ?= y); intros; discriminate. + apply Z.leb_le. Qed. -Lemma Zle_imp_le_bool : forall n m:Z, (n <= m) -> Zle_bool n m = true. +Lemma Zle_imp_le_bool n m : (n <= m) -> (n <=? m) = true. Proof. - unfold Zle, Zle_bool in |- *. intros x y. case (x ?= y); trivial. intro. elim (H (refl_equal _)). + apply Z.leb_le. Qed. -Lemma Zle_bool_refl : forall n:Z, Zle_bool n n = true. -Proof. - intro. apply Zle_imp_le_bool. apply Zeq_le. reflexivity. -Qed. +Notation Zle_bool_refl := Z.leb_refl (compat "8.3"). -Lemma Zle_bool_antisym : - forall n m:Z, Zle_bool n m = true -> Zle_bool m n = true -> n = m. +Lemma Zle_bool_antisym n m : + (n <=? m) = true -> (m <=? n) = true -> n = m. Proof. - intros. apply Zle_antisym. apply Zle_bool_imp_le. assumption. - apply Zle_bool_imp_le. assumption. + rewrite !Z.leb_le. apply Z.le_antisymm. 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. +Lemma Zle_bool_trans n m p : + (n <=? m) = true -> (m <=? p) = true -> (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. + rewrite !Z.leb_le. apply Z.le_trans. Qed. -Definition Zle_bool_total : - forall x y:Z, {Zle_bool x y = true} + {Zle_bool y x = true}. +Definition Zle_bool_total x y : + { x <=? y = true } + { y <=? x = true }. Proof. - intros x y; intros. unfold Zle_bool in |- *. cut ((x ?= y) = Gt <-> (y ?= x) = Lt). - case (x ?= y). left. reflexivity. - left. reflexivity. - right. rewrite (proj1 H (refl_equal _)). reflexivity. - apply Zcompare_Gt_Lt_antisym. + case_eq (x <=? y); intros H. + - left; trivial. + - right. apply Z.leb_gt in H. now apply Z.leb_le, Z.lt_le_incl. 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. +Lemma Zle_bool_plus_mono n m p q : + (n <=? m) = true -> + (p <=? q) = true -> + (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. + rewrite !Z.leb_le. apply Z.add_le_mono. Qed. -Lemma Zone_pos : Zle_bool 1 0 = false. +Lemma Zone_pos : 1 <=? 0 = false. Proof. - reflexivity. + reflexivity. Qed. -Lemma Zone_min_pos : forall n:Z, Zle_bool n 0 = false -> Zle_bool 1 n = true. +Lemma Zone_min_pos n : (n <=? 0) = false -> (1 <=? n) = true. Proof. - intros x; intros. apply Zle_imp_le_bool. change (Zsucc 0 <= x) in |- *. apply Zgt_le_succ. generalize H. - unfold Zle_bool, Zgt in |- *. case (x ?= 0). intro H0. discriminate H0. - intro H0. discriminate H0. - reflexivity. + rewrite Z.leb_le, Z.leb_gt. apply Z.le_succ_l. Qed. (** Properties in term of [iff] *) -Lemma Zle_is_le_bool : forall n m:Z, (n <= m) <-> Zle_bool n m = true. +Lemma Zle_is_le_bool n m : (n <= m) <-> (n <=? m) = true. Proof. - intros. split. intro. apply Zle_imp_le_bool. assumption. - intro. apply Zle_bool_imp_le. assumption. + symmetry. apply Z.leb_le. Qed. -Lemma Zge_is_le_bool : forall n m:Z, (n >= m) <-> Zle_bool m n = true. +Lemma Zge_is_le_bool n m : (n >= m) <-> (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. + Z.swap_greater. symmetry. apply Z.leb_le. Qed. -Lemma Zlt_is_lt_bool : forall n m:Z, (n < m) <-> Zlt_bool n m = true. +Lemma Zlt_is_lt_bool n m : (n < m) <-> (n <? m) = true. Proof. -intros n m; unfold Zlt_bool, Zlt. -destruct (n ?= m); simpl; split; now intro. + symmetry. apply Z.ltb_lt. Qed. -Lemma Zgt_is_gt_bool : forall n m:Z, (n > m) <-> Zgt_bool n m = true. +Lemma Zgt_is_gt_bool n m : (n > m) <-> (n >? m) = true. Proof. -intros n m; unfold Zgt_bool, Zgt. -destruct (n ?= m); simpl; split; now intro. + Z.swap_greater. rewrite Z.gtb_ltb. symmetry. apply Z.ltb_lt. Qed. -Lemma Zlt_is_le_bool : - forall n m:Z, (n < m) <-> Zle_bool n (m - 1) = true. +Lemma Zlt_is_le_bool n m : (n < m) <-> (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. + rewrite Z.leb_le. apply Z.lt_le_pred. Qed. -Lemma Zgt_is_le_bool : - forall n m:Z, (n > m) <-> Zle_bool m (n - 1) = true. +Lemma Zgt_is_le_bool n m : (n > m) <-> (m <=? n - 1) = true. Proof. - intros x y. apply iff_trans with (y < x). split. exact (Zgt_lt x y). - exact (Zlt_gt y x). - exact (Zlt_is_le_bool y x). + Z.swap_greater. rewrite Z.leb_le. apply Z.lt_le_pred. Qed. -Lemma Zeq_is_eq_bool : forall x y, x = y <-> Zeq_bool x y = true. +(** Properties of the deprecated [Zeq_bool] *) + +Lemma Zeq_is_eq_bool x y : x = y <-> Zeq_bool x y = true. Proof. - intros; unfold Zeq_bool. - generalize (Zcompare_Eq_iff_eq x y); destruct Zcompare; intuition; - try discriminate. + unfold Zeq_bool. + rewrite <- Z.compare_eq_iff. destruct Z.compare; now split. Qed. -Lemma Zeq_bool_eq : forall x y, Zeq_bool x y = true -> x = y. +Lemma Zeq_bool_eq x y : Zeq_bool x y = true -> x = y. Proof. - intros x y H; apply <- Zeq_is_eq_bool; auto. + apply Zeq_is_eq_bool. Qed. -Lemma Zeq_bool_neq : forall x y, Zeq_bool x y = false -> x <> y. +Lemma Zeq_bool_neq x y : Zeq_bool x y = false -> x <> y. Proof. - unfold Zeq_bool; red ; intros; subst. - rewrite Zcompare_refl in H. - discriminate. + rewrite Zeq_is_eq_bool; now destruct Zeq_bool. Qed. -Lemma Zeq_bool_if : forall x y, if Zeq_bool x y then x=y else x<>y. +Lemma Zeq_bool_if x y : if Zeq_bool x y then x=y else x<>y. Proof. - intros. generalize (Zeq_bool_eq x y)(Zeq_bool_neq x y). - destruct Zeq_bool; auto. -Qed.
\ No newline at end of file + generalize (Zeq_bool_eq x y) (Zeq_bool_neq x y). + destruct Zeq_bool; auto. +Qed. diff --git a/theories/ZArith/Zcompare.v b/theories/ZArith/Zcompare.v index ae5302ee..fe91698f 100644 --- a/theories/ZArith/Zcompare.v +++ b/theories/ZArith/Zcompare.v @@ -1,387 +1,91 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $$ i*) +(** Binary Integers : results about Z.compare *) +(** Initial author: Pierre Crégut (CNET, Lannion, France *) -(**********************************************************************) -(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) -(**********************************************************************) +(** THIS FILE IS DEPRECATED. + It is now almost entirely made of compatibility formulations + for results already present in BinInt.Z. *) -Require Export BinPos. -Require Export BinInt. -Require Import Lt. -Require Import Gt. -Require Import Plus. -Require Import Mult. +Require Export BinPos BinInt. +Require Import Lt Gt Plus Mult. (* Useless now, for compatibility only *) -Open Local Scope Z_scope. +Local Open Scope Z_scope. (***************************) (** * 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 ]. -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 ] ]. -Qed. - -Ltac destr_zcompare := - match goal with |- context [Zcompare ?x ?y] => - let H := fresh "H" in - case_eq (Zcompare x y); intro H; - [generalize (Zcompare_Eq_eq _ _ H); clear H; intro H | - change (x<y)%Z in H | - change (x>y)%Z in H ] - end. - -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 ]. -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. -Qed. - Lemma Zcompare_Gt_Lt_antisym : forall n m:Z, (n ?= m) = Gt <-> (m ?= n) = Lt. -Proof. - intros x y. - rewrite <- Zcompare_antisym. change Gt with (CompOpp Lt). - split. - auto using CompOpp_inj. - intros; f_equal; auto. -Qed. - -Lemma Zcompare_spec : forall n m, CompSpec eq Zlt n m (n ?= m). -Proof. - intros. - destruct (n?=m) as [ ]_eqn:H; constructor; auto. - apply Zcompare_Eq_eq; auto. - red; rewrite <- Zcompare_antisym, H; auto. -Qed. +Proof Z.gt_lt_iff. +Lemma Zcompare_antisym n m : CompOpp (n ?= m) = (m ?= n). +Proof eq_sym (Z.compare_antisym n m). (** * Transitivity of comparison *) Lemma Zcompare_Lt_trans : forall n m p:Z, (n ?= m) = Lt -> (m ?= p) = Lt -> (n ?= p) = Lt. -Proof. - intros x y z; case x; case y; case z; simpl; - try discriminate; auto with arith. - intros; eapply Plt_trans; eauto. - intros p q r; rewrite 3 Pcompare_antisym; simpl. - intros; eapply Plt_trans; eauto. -Qed. +Proof Z.lt_trans. Lemma Zcompare_Gt_trans : forall n m p:Z, (n ?= m) = Gt -> (m ?= p) = Gt -> (n ?= p) = Gt. Proof. - intros n m p Hnm Hmp. - apply <- Zcompare_Gt_Lt_antisym. - apply -> Zcompare_Gt_Lt_antisym in Hnm. - apply -> Zcompare_Gt_Lt_antisym in Hmp. - eapply Zcompare_Lt_trans; eauto. + intros n m p. change (n > m -> m > p -> n > p). + Z.swap_greater. intros. now transitivity m. Qed. (** * Comparison and opposite *) -Lemma Zcompare_opp : forall n m:Z, (n ?= m) = (- m ?= - n). +Lemma Zcompare_opp n m : (n ?= m) = (- m ?= - n). Proof. - intros x y; case x; case y; simpl in |- *; auto with arith; intros; - rewrite <- ZC4; trivial with arith. + symmetry. apply Z.compare_opp. Qed. -Hint Local Resolve Pcompare_refl. - (** * Comparison first-order specification *) -Lemma Zcompare_Gt_spec : - forall n m:Z, (n ?= m) = Gt -> exists h : positive, n + - m = Zpos h. +Lemma Zcompare_Gt_spec n m : (n ?= m) = Gt -> exists h, 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 ]. + rewrite Z.compare_sub. unfold Z.sub. + destruct (n+-m) as [|p|p]; try discriminate. now exists p. Qed. (** * 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). +Lemma Zcompare_plus_compat n m p : (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 ]. + apply Z.add_compare_mono_l. Qed. -Hint Local Resolve ZC4. - -Lemma weak_Zcompare_Zplus_compatible : - 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 ] ] ]. -Qed. - -Lemma Zcompare_plus_compat : forall n m p:Z, (p + n ?= p + m) = (n ?= m). +Lemma Zplus_compare_compat (r:comparison) (n m p q:Z) : + (n ?= m) = r -> (p ?= q) = r -> (n + p ?= m + q) = r. Proof. - exact (weaken_Zcompare_Zplus_compatible weak_Zcompare_Zplus_compatible). + rewrite (Z.compare_sub n), (Z.compare_sub p), (Z.compare_sub (n+p)). + unfold Z.sub. rewrite Z.opp_add_distr. rewrite Z.add_shuffle1. + destruct (n+-m), (p+-q); simpl; intros; now subst. Qed. -Lemma Zplus_compare_compat : - forall (r:comparison) (n m p q:Z), - (n ?= m) = r -> (p ?= q) = r -> (n + p ?= m + q) = r. +Lemma Zcompare_succ_Gt n : (Z.succ n ?= n) = Gt. 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 ] ]. + apply Z.lt_gt. apply Z.lt_succ_diag_r. Qed. -Lemma Zcompare_succ_Gt : forall n:Z, (Zsucc n ?= n) = Gt. +Lemma Zcompare_Gt_not_Lt n m : (n ?= m) = Gt <-> (n ?= m+1) <> Lt. Proof. - 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) ] ] ]. + change (n > m <-> n >= m+1). Z.swap_greater. symmetry. apply Z.le_succ_l. Qed. (** * Successor and comparison *) -Lemma Zcompare_succ_compat : forall n m:Z, (Zsucc n ?= Zsucc m) = (n ?= m). +Lemma Zcompare_succ_compat n m : (Z.succ n ?= Z.succ 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. + rewrite <- 2 Z.add_1_l. apply Z.add_compare_mono_l. Qed. (** * Multiplication and comparison *) @@ -389,28 +93,24 @@ Qed. Lemma Zcompare_mult_compat : 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 p [|n|n] [|m|m]; simpl; trivial; now rewrite Pos.mul_compare_mono_l. Qed. +Lemma Zmult_compare_compat_l n m p: + p > 0 -> (n ?= m) = (p * n ?= p * m). +Proof. + intros; destruct p; try discriminate. + symmetry. apply Zcompare_mult_compat. +Qed. -(** * Reverting [x ?= y] to trichotomy *) - -Lemma rename : - forall (A:Type) (P:A -> Prop) (x:A), (forall y:A, x = y -> P y) -> P x. +Lemma Zmult_compare_compat_r n m p : + p > 0 -> (n ?= m) = (n * p ?= m * p). Proof. - auto with arith. + intros; rewrite 2 (Z.mul_comm _ p); now apply Zmult_compare_compat_l. Qed. +(** * Relating [x ?= y] to [=], [<=], [<], [>=] or [>] *) + Lemma Zcompare_elim : forall (c1 c2 c3:Prop) (n m:Z), (n = m -> c1) -> @@ -421,11 +121,7 @@ Lemma Zcompare_elim : | 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. case Z.compare_spec; trivial. now Z.swap_greater. Qed. Lemma Zcompare_eq_case : @@ -436,26 +132,9 @@ Lemma Zcompare_eq_case : | Gt => c3 end. Proof. - intros c1 c2 c3 x y; intros. - rewrite H0; rewrite Zcompare_refl. - assumption. + intros. subst. now rewrite Z.compare_refl. Qed. -(** * 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). -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. -Qed. - -(** * Relating [x ?= y] to [Zle], [Zlt], [Zge] or [Zgt] *) - Lemma Zle_compare : forall n m:Z, n <= m -> match n ?= m with @@ -464,7 +143,7 @@ Lemma Zle_compare : | Gt => False end. Proof. - intros x y; unfold Zle in |- *; elim (x ?= y); auto with arith. + intros. case Z.compare_spec; trivial; Z.order. Qed. Lemma Zlt_compare : @@ -475,8 +154,7 @@ Lemma Zlt_compare : | Gt => False end. Proof. - intros x y; unfold Zlt in |- *; elim (x ?= y); intros; - discriminate || trivial with arith. + intros x y H; now rewrite H. Qed. Lemma Zge_compare : @@ -487,7 +165,7 @@ Lemma Zge_compare : | Gt => True end. Proof. - intros x y; unfold Zge in |- *; elim (x ?= y); auto with arith. + intros. now case Z.compare_spec. Qed. Lemma Zgt_compare : @@ -498,26 +176,23 @@ Lemma Zgt_compare : | Gt => True end. Proof. - intros x y; unfold Zgt in |- *; elim (x ?= y); intros; - discriminate || trivial with arith. + intros x y H; now rewrite H. Qed. -(*********************) -(** * Other properties *) +(** Compatibility notations *) -Lemma Zmult_compare_compat_l : - forall n m p:Z, p > 0 -> (n ?= m) = (p * n ?= p * m). -Proof. - 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). -Proof. - intros x y z H; rewrite (Zmult_comm x z); rewrite (Zmult_comm y z); - apply Zmult_compare_compat_l; assumption. -Qed. +Notation Zcompare_refl := Z.compare_refl (compat "8.3"). +Notation Zcompare_Eq_eq := Z.compare_eq (compat "8.3"). +Notation Zcompare_Eq_iff_eq := Z.compare_eq_iff (compat "8.3"). +Notation Zcompare_spec := Z.compare_spec (compat "8.3"). +Notation Zmin_l := Z.min_l (compat "8.3"). +Notation Zmin_r := Z.min_r (compat "8.3"). +Notation Zmax_l := Z.max_l (compat "8.3"). +Notation Zmax_r := Z.max_r (compat "8.3"). +Notation Zabs_eq := Z.abs_eq (compat "8.3"). +Notation Zabs_non_eq := Z.abs_neq (compat "8.3"). +Notation Zsgn_0 := Z.sgn_null (compat "8.3"). +Notation Zsgn_1 := Z.sgn_pos (compat "8.3"). +Notation Zsgn_m1 := Z.sgn_neg (compat "8.3"). +(** Not kept: Zcompare_egal_dec *) diff --git a/theories/ZArith/Zcomplements.v b/theories/ZArith/Zcomplements.v index ca72f8a8..b4163ef9 100644 --- a/theories/ZArith/Zcomplements.v +++ b/theories/ZArith/Zcomplements.v @@ -1,46 +1,22 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zcomplements.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - Require Import ZArithRing. Require Import ZArith_base. Require Export Omega. Require Import Wf_nat. -Open Local Scope Z_scope. +Local Open 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}. -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. -Qed. +Notation two_or_two_plus_one := Z_modulo_2 (only parsing). (**********************************************************************) (** The biggest power of 2 that is stricly less than [a] @@ -58,31 +34,14 @@ Fixpoint floor_pos (a:positive) : positive := Definition floor (a:positive) := Zpos (floor_pos a). Lemma floor_gt0 : forall p:positive, floor p > 0. -Proof. - intro. - compute in |- *. - trivial. -Qed. +Proof. reflexivity. 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. induction p; simpl. + - rewrite !Pos2Z.inj_xI, (Pos2Z.inj_xO (xO _)), Pos2Z.inj_xO. omega. + - rewrite (Pos2Z.inj_xO (xO _)), (Pos2Z.inj_xO p), Pos2Z.inj_xO. omega. + - omega. Qed. (**********************************************************************) @@ -90,41 +49,39 @@ Qed. 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, (forall m:Z, Z.abs m < Z.abs 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 ]. + cut (Q (Z.abs 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. + unfold Q; clear Q; intros. + split; apply HP. + rewrite Z.abs_eq; auto; intros. + elim (H (Z.abs 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. + rewrite Z.abs_neq, Z.opp_involutive; auto with zarith; intros. + elim (H (Z.abs 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, (forall m:Z, Z.abs m < Z.abs 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 ]. + cut (Q (Z.abs 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. + unfold Q; clear Q; intros. split; apply HP. - rewrite Zabs_eq; auto; intros. - elim (H (Zabs m)); intros; auto with zarith. + rewrite Z.abs_eq; auto; intros. + elim (H (Z.abs 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. + rewrite Z.abs_neq, Z.opp_involutive; auto with zarith; intros. + elim (H (Z.abs m)); intros; auto with zarith. elim (Zabs_dec m); intro eq; rewrite eq; trivial. Qed. @@ -134,25 +91,12 @@ Lemma Zcase_sign : 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. + destruct x; [apply Hzero|apply Hpos|apply Hneg]; easy. Qed. -Lemma sqr_pos : forall n:Z, n * n >= 0. +Lemma sqr_pos n : 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. + Z.swap_greater. apply Z.square_nonneg. Qed. (**********************************************************************) @@ -163,11 +107,11 @@ Require Import List. Fixpoint Zlength_aux (acc:Z) (A:Type) (l:list A) : Z := match l with | nil => acc - | _ :: l => Zlength_aux (Zsucc acc) A l + | _ :: l => Zlength_aux (Z.succ acc) A l end. Definition Zlength := Zlength_aux 0. -Implicit Arguments Zlength [A]. +Arguments Zlength [A] l. Section Zlength_properties. @@ -175,38 +119,33 @@ Section Zlength_properties. Implicit Type l : list A. - Lemma Zlength_correct : forall l, Zlength l = Z_of_nat (length l). + Lemma Zlength_correct 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. + assert (H : forall l acc, Zlength_aux acc A l = acc + Z.of_nat (length l)). + clear l. induction l. + auto with zarith. + intros. simpl length; simpl Zlength_aux. + rewrite IHl, Nat2Z.inj_succ; auto with zarith. + unfold Zlength. now rewrite H. Qed. Lemma Zlength_nil : Zlength (A:=A) nil = 0. - Proof. - auto. - Qed. + Proof. reflexivity. Qed. - Lemma Zlength_cons : forall (x:A) l, Zlength (x :: l) = Zsucc (Zlength l). + Lemma Zlength_cons (x:A) l : Zlength (x :: l) = Z.succ (Zlength l). Proof. - intros; do 2 rewrite Zlength_correct. - simpl (length (x :: l)) in |- *; rewrite Znat.inj_S; auto. + intros. now rewrite !Zlength_correct, <- Nat2Z.inj_succ. Qed. - Lemma Zlength_nil_inv : forall l, Zlength l = 0 -> l = nil. + Lemma Zlength_nil_inv 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; exfalso; generalize (Zle_0_nat (length l')); omega. + rewrite Zlength_correct. + destruct l as [|x l]; auto. + now rewrite <- Nat2Z.inj_0, Nat2Z.inj_iff. Qed. End Zlength_properties. -Implicit Arguments Zlength_correct [A]. -Implicit Arguments Zlength_cons [A]. -Implicit Arguments Zlength_nil_inv [A]. +Arguments Zlength_correct [A] l. +Arguments Zlength_cons [A] x l. +Arguments Zlength_nil_inv [A] l _. diff --git a/theories/ZArith/Zdigits.v b/theories/ZArith/Zdigits.v index c43b241d..fa8f5c27 100644 --- a/theories/ZArith/Zdigits.v +++ b/theories/ZArith/Zdigits.v @@ -1,14 +1,12 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zdigits.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - (** Bit vectors interpreted as integers. Contribution by Jean Duprat (ENS Lyon). *) @@ -47,17 +45,17 @@ Section VALUE_OF_BOOLEAN_VECTORS. exact 0%Z. inversion H0. - exact (bit_value a + 2 * H H2)%Z. + exact (bit_value h + 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. + exact (- bit_value h)%Z. inversion H0. - exact (bit_value a + 2 * H H2)%Z. + exact (bit_value h + 2 * H H2)%Z. Defined. End VALUE_OF_BOOLEAN_VECTORS. @@ -66,7 +64,7 @@ Section ENCODING_VALUE. (** We compute the binary value via a Horner scheme. Computation stops at the vector length without checks. - We define a function Zmod2 similar to Zdiv2 returning the + We define a function Zmod2 similar to Z.div2 returning the quotient of division z=2q+r with 0<=r<=1. The two's complement value is also computed via a Horner scheme with Zmod2, the parameter is the size minus one. @@ -90,16 +88,16 @@ Section ENCODING_VALUE. Lemma Zmod2_twice : - forall z:Z, z = (2 * Zmod2 z + bit_value (Zeven.Zodd_bool z))%Z. + forall z:Z, z = (2 * Zmod2 z + bit_value (Z.odd z))%Z. Proof. - destruct z; simpl in |- *. + destruct z; simpl. trivial. - destruct p; simpl in |- *; trivial. + destruct p; simpl; trivial. - destruct p; simpl in |- *. - destruct p as [p| p| ]; simpl in |- *. - rewrite <- (Pdouble_minus_one_o_succ_eq_xI p); trivial. + destruct p; simpl. + destruct p as [p| p| ]; simpl. + rewrite <- (Pos.pred_double_succ p); trivial. trivial. @@ -115,15 +113,15 @@ Section ENCODING_VALUE. simple induction n; intros. exact Bnil. - exact (Bcons (Zeven.Zodd_bool H0) n0 (H (Zeven.Zdiv2 H0))). + exact (Bcons (Z.odd H0) n0 (H (Z.div2 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 (Z.odd H) 0 Bnil). - exact (Bcons (Zeven.Zodd_bool H0) (S n0) (H (Zmod2 H0))). + exact (Bcons (Z.odd H0) (S n0) (H (Zmod2 H0))). Defined. End ENCODING_VALUE. @@ -136,7 +134,7 @@ Section Z_BRIC_A_BRAC. Lemma binary_value_Sn : forall (n:nat) (b:bool) (bv:Bvector n), - binary_value (S n) (Vcons bool b n bv) = + binary_value (S n) ( b :: bv) = (bit_value b + 2 * binary_value n bv)%Z. Proof. intros; auto. @@ -147,17 +145,17 @@ Section Z_BRIC_A_BRAC. (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. + destruct b; destruct z; simpl; 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 |- *. + induction bv as [| a n v IHbv]; simpl. omega. - destruct a; destruct (binary_value n v); simpl in |- *; auto. + destruct a; destruct (binary_value n v); simpl; auto. auto with zarith. Qed. @@ -176,34 +174,34 @@ Section Z_BRIC_A_BRAC. 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. + destruct p as [p| p| ]; simpl; auto. + intros; rewrite (Pos.succ_pred_double 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)). + Bcons (Z.odd z) n (Z_to_binary n (Z.div2 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. + (z >= 0)%Z -> (bit_value (Z.odd z) + 2 * Z.div2 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. + Lemma Pdiv2 : forall z:Z, (z >= 0)%Z -> (Z.div2 z >= 0)%Z. Proof. destruct z as [| p| p]. auto. destruct p; auto. - simpl in |- *; intros; omega. + simpl; intros; omega. intro H; elim H; trivial. Qed. @@ -211,39 +209,39 @@ Section Z_BRIC_A_BRAC. 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. + (z < two_power_nat (S n))%Z -> (Z.div2 z < two_power_nat n)%Z. Proof. intros. - cut (2 * Zeven.Zdiv2 z < 2 * two_power_nat n)%Z; intros. + cut (2 * Z.div2 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. + generalize (Zeven.Zodd_div2 z 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)). + Bcons (Z.odd 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. + forall z:Z, Zeven.Zeven z -> bit_value (Z.odd z) = 0%Z. Proof. - destruct z; unfold bit_value in |- *; auto. + destruct z; unfold bit_value; 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. + forall z:Z, Zeven.Zodd z -> bit_value (Z.odd z) = 1%Z. Proof. - destruct z; unfold bit_value in |- *; auto. + destruct z; unfold bit_value; auto. intros; elim H. destruct p; tauto || (intros; elim H). destruct p; tauto || (intros; elim H). @@ -312,7 +310,7 @@ Section COHERENT_VALUE. (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. + unfold two_power_nat, shift_nat; simpl; intros; omega. intros; rewrite Z_to_binary_Sn_z. rewrite binary_value_Sn. @@ -330,7 +328,7 @@ Section COHERENT_VALUE. (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. + unfold two_power_nat, shift_nat; simpl; intros. assert (z = (-1)%Z \/ z = 0%Z). omega. intuition; subst z; trivial. diff --git a/theories/ZArith/Zdiv.v b/theories/ZArith/Zdiv.v index df22371e..27fb21bc 100644 --- a/theories/ZArith/Zdiv.v +++ b/theories/ZArith/Zdiv.v @@ -1,200 +1,57 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zdiv.v 14641 2011-11-06 11:59:10Z herbelin $ i*) +(** * Euclidean Division *) -(* 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. -*) +(** Initial Contribution by Claude Marché and Xavier Urbain *) Require Export ZArith_base. -Require Import Zbool. -Require Import Omega. -Require Import ZArithRing. -Require Import Zcomplements. -Require Export Setoid. -Open Local Scope Z_scope. - -(** * Definitions of Euclidian operations *) - -(** 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 - -*) - -Unboxed Fixpoint Zdiv_eucl_POS (a:positive) (b:Z) : Z * Z := - match a with - | 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 (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) - end. - - -(** Euclidean division of integers. - - Total function than returns (0,0) when dividing by 0. -*) - -(** - - The pseudo-code is: - - if b = 0 : (0,0) - - if b <> 0 and a = 0 : (0,0) - - if b > 0 and a < 0 : let (q,r) = div_eucl_pos (-a) b in - if r = 0 then (-q,0) else (-(q+1),b-r) - - if b < 0 and a < 0 : let (q,r) = div_eucl (-a) (-b) in (q,-r) - - if b < 0 and a > 0 : let (q,r) = div_eucl a (-b) in - if r = 0 then (-q,0) else (-(q+1),b+r) - - In other word, when b is non-zero, q is chosen to be the greatest integer - smaller or equal to a/b. And sgn(r)=sgn(b) and |r| < |b| (at least when - r is not null). -*) +Require Import Zbool Omega ZArithRing Zcomplements Setoid Morphisms. +Local Open Scope Z_scope. -(* Nota: At least two others conventions also exist for euclidean division. - They all satify the equation a=b*q+r, but differ on the choice of (q,r) - on negative numbers. +(** The definition of the division is now in [BinIntDef], the initial + specifications and properties are in [BinInt]. *) - * Ocaml uses Round-Toward-Zero division: (-a)/b = a/(-b) = -(a/b). - Hence (-a) mod b = - (a mod b) - a mod (-b) = a mod b - And: |r| < |b| and sgn(r) = sgn(a) (notice the a here instead of b). +Notation Zdiv_eucl_POS := Z.pos_div_eucl (compat "8.3"). +Notation Zdiv_eucl := Z.div_eucl (compat "8.3"). +Notation Zdiv := Z.div (compat "8.3"). +Notation Zmod := Z.modulo (compat "8.3"). - * Another solution is to always pick a non-negative remainder: - a=b*q+r with 0 <= r < |b| -*) - -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 _ => - 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' => - let (q, r) := Zdiv_eucl_POS a' (Zpos b') in - match r with - | Z0 => (- q, 0) - | _ => (- (q + 1), b + r) - end - end. - - -(** Division and modulo are projections of [Zdiv_eucl] *) - -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). - -Eval compute in (Zdiv_eucl (-7) 3). +Notation Zdiv_eucl_eq := Z.div_eucl_eq (compat "8.3"). +Notation Z_div_mod_eq_full := Z.div_mod (compat "8.3"). +Notation Zmod_POS_bound := Z.pos_div_eucl_bound (compat "8.3"). +Notation Zmod_pos_bound := Z.mod_pos_bound (compat "8.3"). +Notation Zmod_neg_bound := Z.mod_neg_bound (compat "8.3"). -Eval compute in (Zdiv_eucl 7 (-3)). +(** * Main division theorems *) -Eval compute in (Zdiv_eucl (-7) (-3)). - -*) - - -(** * Main division theorem *) - -(** First a lemma for two positive arguments *) +(** NB: many things are stated twice for compatibility reasons *) 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. + let (q, r) := Z.pos_div_eucl a b in Zpos a = b * q + r /\ 0 <= r < b. Proof. -simple induction a; cbv beta iota delta [Zdiv_eucl_POS] in |- *; - fold Zdiv_eucl_POS in |- *; cbv zeta. - -intro p; case (Zdiv_eucl_POS p b); intros q r [H0 H1]. -generalize (Zgt_cases b (2 * r + 1)). -case (Zgt_bool b (2 * r + 1)); - (rewrite BinInt.Zpos_xI; rewrite H0; split; [ ring | omega ]). - -intros p; case (Zdiv_eucl_POS p b); intros q r [H0 H1]. -generalize (Zgt_cases b (2 * r)). -case (Zgt_bool b (2 * r)); rewrite BinInt.Zpos_xO; - change (Zpos (xO p)) with (2 * Zpos p) in |- *; rewrite H0; - (split; [ ring | omega ]). - -generalize (Zge_cases b 2). -case (Zge_bool b 2); (intros; split; [ try ring | omega ]). -omega. + intros b Hb a. Z.swap_greater. + generalize (Z.pos_div_eucl_eq a b Hb) (Z.pos_div_eucl_bound a b Hb). + destruct Z.pos_div_eucl. rewrite Z.mul_comm. auto. Qed. -(** Then the usual situation of a positive [b] and no restriction on [a] *) - -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. +Theorem Z_div_mod a b : + b > 0 -> + let (q, r) := Z.div_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. - change (Zneg p0) with (- Zpos p0); rewrite H1; ring. - - intros p1 [H1 H2]. - split; trivial. - change (Zneg p0) with (- Zpos p0); rewrite H1; ring. - generalize (Zorder.Zgt_pos_0 p1); omega. - - intros p1 [H1 H2]. - split; trivial. - change (Zneg p0) with (- Zpos p0); rewrite H1; ring. - generalize (Zorder.Zlt_neg_0 p1); omega. - - intros; discriminate. + Z.swap_greater. intros Hb. + assert (Hb' : b<>0) by (now destruct b). + generalize (Z.div_eucl_eq a b Hb') (Z.mod_pos_bound a b Hb). + unfold Z.modulo. destruct Z.div_eucl. auto. Qed. (** For stating the fully general result, let's give a short name @@ -204,10 +61,10 @@ Definition Remainder r b := 0 <= r < b \/ b < r <= 0. (** Another equivalent formulation: *) -Definition Remainder_alt r b := Zabs r < Zabs b /\ Zsgn r <> - Zsgn b. +Definition Remainder_alt r b := Z.abs r < Z.abs b /\ Z.sgn r <> - Z.sgn b. -(* In the last formulation, [ Zsgn r <> - Zsgn b ] is less nice than saying - [ Zsgn r = Zsgn b ], but at least it works even when [r] is null. *) +(* In the last formulation, [ Z.sgn r <> - Z.sgn b ] is less nice than saying + [ Z.sgn r = Z.sgn b ], but at least it works even when [r] is null. *) Lemma Remainder_equiv : forall r b, Remainder r b <-> Remainder_alt r b. Proof. @@ -218,90 +75,44 @@ Hint Unfold Remainder. (** Now comes the fully general result about Euclidean division. *) -Theorem Z_div_mod_full : - forall a b:Z, - b <> 0 -> let (q, r) := Zdiv_eucl a b in a = b * q + r /\ Remainder r b. +Theorem Z_div_mod_full a b : + b <> 0 -> + let (q, r) := Z.div_eucl a b in a = b * q + r /\ Remainder r b. Proof. - destruct b as [|b|b]. - (* b = 0 *) - intro H; elim H; auto. - (* b > 0 *) - intros _. - assert (Zpos b > 0) by auto with zarith. - generalize (Z_div_mod a (Zpos b) H). - destruct Zdiv_eucl as (q,r); intuition; simpl; auto. - (* b < 0 *) - intros _. - assert (Zpos b > 0) by auto with zarith. - generalize (Z_div_mod a (Zpos b) H). - unfold Remainder. - destruct a as [|a|a]. - (* a = 0 *) - simpl; intuition. - (* a > 0 *) - unfold Zdiv_eucl; destruct Zdiv_eucl_POS as (q,r). - destruct r as [|r|r]; [ | | omega with *]. - rewrite <- Zmult_opp_comm; simpl Zopp; intuition. - rewrite <- Zmult_opp_comm; simpl Zopp. - rewrite Zmult_plus_distr_r; omega with *. - (* a < 0 *) - unfold Zdiv_eucl. - generalize (Z_div_mod_POS (Zpos b) H a). - destruct Zdiv_eucl_POS as (q,r). - destruct r as [|r|r]; change (Zneg b) with (-Zpos b). - rewrite Zmult_opp_comm; omega with *. - rewrite <- Zmult_opp_comm, Zmult_plus_distr_r; - repeat rewrite Zmult_opp_comm; omega. - rewrite Zmult_opp_comm; omega with *. + intros Hb. + generalize (Z.div_eucl_eq a b Hb) + (Z.mod_pos_bound a b) (Z.mod_neg_bound a b). + unfold Z.modulo. destruct Z.div_eucl as (q,r). + intros EQ POS NEG. + split; auto. + red; destruct b. + now destruct Hb. left; now apply POS. right; now apply NEG. Qed. -(** The same results as before, stated separately in terms of Zdiv and Zmod *) - -Lemma Z_mod_remainder : forall a b:Z, b<>0 -> Remainder (a mod b) b. -Proof. - unfold Zmod; intros a b Hb; generalize (Z_div_mod_full a b Hb); auto. - destruct Zdiv_eucl; tauto. -Qed. +(** The same results as before, stated separately in terms of Z.div and Z.modulo *) -Lemma Z_mod_lt : forall a b:Z, b > 0 -> 0 <= a mod b < b. +Lemma Z_mod_remainder a b : b<>0 -> Remainder (a mod b) b. Proof. - unfold Zmod; intros a b Hb; generalize (Z_div_mod a b Hb). - destruct Zdiv_eucl; tauto. + unfold Z.modulo; intros Hb; generalize (Z_div_mod_full a b Hb); auto. + destruct Z.div_eucl; tauto. Qed. -Lemma Z_mod_neg : forall a b:Z, b < 0 -> b < a mod b <= 0. -Proof. - unfold Zmod; intros a b Hb. - assert (Hb' : b<>0) by (auto with zarith). - generalize (Z_div_mod_full a b Hb'). - destruct Zdiv_eucl. - unfold Remainder; intuition. -Qed. +Lemma Z_mod_lt a b : b > 0 -> 0 <= a mod b < b. +Proof (fun Hb => Z.mod_pos_bound a b (Z.gt_lt _ _ Hb)). -Lemma Z_div_mod_eq_full : forall a b:Z, b <> 0 -> a = b*(a/b) + (a mod b). -Proof. - unfold Zdiv, Zmod; intros a b Hb; generalize (Z_div_mod_full a b Hb). - destruct Zdiv_eucl; tauto. -Qed. +Lemma Z_mod_neg a b : b < 0 -> b < a mod b <= 0. +Proof (Z.mod_neg_bound a b). -Lemma Z_div_mod_eq : forall a b:Z, b > 0 -> a = b*(a/b) + (a mod b). +Lemma Z_div_mod_eq a b : b > 0 -> a = b*(a/b) + (a mod b). Proof. - intros; apply Z_div_mod_eq_full; auto with zarith. + intros Hb; apply Z.div_mod; auto with zarith. Qed. -Lemma Zmod_eq_full : forall a b:Z, b<>0 -> a mod b = a - (a/b)*b. -Proof. - intros. - rewrite <- Zeq_plus_swap, Zplus_comm, Zmult_comm; symmetry. - apply Z_div_mod_eq_full; auto. -Qed. +Lemma Zmod_eq_full a b : b<>0 -> a mod b = a - (a/b)*b. +Proof. intros. rewrite Z.mul_comm. now apply Z.mod_eq. Qed. -Lemma Zmod_eq : forall a b:Z, b>0 -> a mod b = a - (a/b)*b. -Proof. - intros. - rewrite <- Zeq_plus_swap, Zplus_comm, Zmult_comm; symmetry. - apply Z_div_mod_eq; auto. -Qed. +Lemma Zmod_eq a b : b>0 -> a mod b = a - (a/b)*b. +Proof. intros. apply Zmod_eq_full. now destruct b. Qed. (** Existence theorem *) @@ -309,89 +120,51 @@ Theorem Zdiv_eucl_exist : forall (b:Z)(Hb:b>0)(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). + exists (Z.div_eucl a b). exact (Z_div_mod a b Hb). Qed. -Implicit Arguments Zdiv_eucl_exist. +Arguments Zdiv_eucl_exist : default implicits. (** Uniqueness theorems *) -Theorem Zdiv_mod_unique : - forall b q1 q2 r1 r2:Z, - 0 <= r1 < Zabs b -> 0 <= r2 < Zabs b -> +Theorem Zdiv_mod_unique b q1 q2 r1 r2 : + 0 <= r1 < Z.abs b -> 0 <= r2 < Z.abs b -> b*q1+r1 = b*q2+r2 -> q1=q2 /\ r1=r2. Proof. -intros b q1 q2 r1 r2 Hr1 Hr2 H. -destruct (Z_eq_dec q1 q2) as [Hq|Hq]. +intros Hr1 Hr2 H. rewrite <- (Z.abs_sgn b), <- !Z.mul_assoc in H. +destruct (Z.div_mod_unique (Z.abs b) (Z.sgn b * q1) (Z.sgn b * q2) r1 r2); auto. split; trivial. -rewrite Hq in H; omega. -elim (Zlt_not_le (Zabs (r2 - r1)) (Zabs b)). -omega with *. -replace (r2-r1) with (b*(q1-q2)) by (rewrite Zmult_minus_distr_l; omega). -replace (Zabs b) with ((Zabs b)*1) by ring. -rewrite Zabs_Zmult. -apply Zmult_le_compat_l; auto with *. -omega with *. +apply Z.mul_cancel_l with (Z.sgn b); trivial. +rewrite Z.sgn_null_iff, <- Z.abs_0_iff. destruct Hr1; Z.order. Qed. Theorem Zdiv_mod_unique_2 : forall b q1 q2 r1 r2:Z, Remainder r1 b -> Remainder r2 b -> b*q1+r1 = b*q2+r2 -> q1=q2 /\ r1=r2. -Proof. -unfold Remainder. -intros b q1 q2 r1 r2 Hr1 Hr2 H. -destruct (Z_eq_dec q1 q2) as [Hq|Hq]. -split; trivial. -rewrite Hq in H; omega. -elim (Zlt_not_le (Zabs (r2 - r1)) (Zabs b)). -omega with *. -replace (r2-r1) with (b*(q1-q2)) by (rewrite Zmult_minus_distr_l; omega). -replace (Zabs b) with ((Zabs b)*1) by ring. -rewrite Zabs_Zmult. -apply Zmult_le_compat_l; auto with *. -omega with *. -Qed. +Proof Z.div_mod_unique. Theorem Zdiv_unique_full: forall a b q r, Remainder r b -> a = b*q + r -> q = a/b. -Proof. - intros. - assert (b <> 0) by (unfold Remainder in *; omega with *). - generalize (Z_div_mod_full a b H1). - unfold Zdiv; destruct Zdiv_eucl as (q',r'). - intros (H2,H3); rewrite H2 in H0. - destruct (Zdiv_mod_unique_2 b q q' r r'); auto. -Qed. +Proof Z.div_unique. Theorem Zdiv_unique: forall a b q r, 0 <= r < b -> a = b*q + r -> q = a/b. -Proof. - intros; eapply Zdiv_unique_full; eauto. -Qed. +Proof. intros; eapply Zdiv_unique_full; eauto. Qed. Theorem Zmod_unique_full: forall a b q r, Remainder r b -> a = b*q + r -> r = a mod b. -Proof. - intros. - assert (b <> 0) by (unfold Remainder in *; omega with *). - generalize (Z_div_mod_full a b H1). - unfold Zmod; destruct Zdiv_eucl as (q',r'). - intros (H2,H3); rewrite H2 in H0. - destruct (Zdiv_mod_unique_2 b q q' r r'); auto. -Qed. +Proof Z.mod_unique. Theorem Zmod_unique: forall a b q r, 0 <= r < b -> a = b*q + r -> r = a mod b. -Proof. - intros; eapply Zmod_unique_full; eauto. -Qed. +Proof. intros; eapply Zmod_unique_full; eauto. Qed. (** * Basic values of divisions and modulo. *) @@ -415,70 +188,44 @@ Proof. destruct a; simpl; auto. Qed. +Ltac zero_or_not a := + destruct (Z.eq_dec a 0); + [subst; rewrite ?Zmod_0_l, ?Zdiv_0_l, ?Zmod_0_r, ?Zdiv_0_r; + auto with zarith|]. + Lemma Zmod_1_r: forall a, a mod 1 = 0. -Proof. - intros; symmetry; apply Zmod_unique with a; auto with zarith. -Qed. +Proof. intros. zero_or_not a. apply Z.mod_1_r. Qed. Lemma Zdiv_1_r: forall a, a/1 = a. -Proof. - intros; symmetry; apply Zdiv_unique with 0; auto with zarith. -Qed. +Proof. intros. zero_or_not a. apply Z.div_1_r. Qed. Hint Resolve Zmod_0_l Zmod_0_r Zdiv_0_l Zdiv_0_r Zdiv_1_r Zmod_1_r : zarith. Lemma Zdiv_1_l: forall a, 1 < a -> 1/a = 0. -Proof. - intros; symmetry; apply Zdiv_unique with 1; auto with zarith. -Qed. +Proof Z.div_1_l. Lemma Zmod_1_l: forall a, 1 < a -> 1 mod a = 1. -Proof. - intros; symmetry; apply Zmod_unique with 0; auto with zarith. -Qed. +Proof Z.mod_1_l. Lemma Z_div_same_full : forall a:Z, a<>0 -> a/a = 1. -Proof. - intros; symmetry; apply Zdiv_unique_full with 0; auto with *; red; omega. -Qed. +Proof Z.div_same. Lemma Z_mod_same_full : forall a, a mod a = 0. -Proof. - destruct a; intros; symmetry. - compute; auto. - apply Zmod_unique with 1; auto with *; omega with *. - apply Zmod_unique_full with 1; auto with *; red; omega with *. -Qed. +Proof. intros. zero_or_not a. apply Z.mod_same; auto. Qed. Lemma Z_mod_mult : forall a b, (a*b) mod b = 0. -Proof. - intros a b; destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; simpl; rewrite Zmod_0_r; auto. - symmetry; apply Zmod_unique_full with a; [ red; omega | ring ]. -Qed. +Proof. intros. zero_or_not b. apply Z.mod_mul. auto. Qed. Lemma Z_div_mult_full : forall a b:Z, b <> 0 -> (a*b)/b = a. -Proof. - intros; symmetry; apply Zdiv_unique_full with 0; auto with zarith; - [ red; omega | ring]. -Qed. +Proof Z.div_mul. -(** * Order results about Zmod and Zdiv *) +(** * Order results about Z.modulo and Z.div *) (* Division of positive numbers is positive. *) Lemma Z_div_pos: forall a b, b > 0 -> 0 <= a -> 0 <= a/b. -Proof. - intros. - rewrite (Z_div_mod_eq a b H) in H0. - assert (H1:=Z_mod_lt a b H). - destruct (Z_lt_le_dec (a/b) 0); auto. - assert (b*(a/b) <= -b). - replace (-b) with (b*-1); [ | ring]. - apply Zmult_le_compat_l; auto with zarith. - omega. -Qed. +Proof. intros. apply Z.div_pos; auto with zarith. Qed. Lemma Z_div_ge0: forall a b, b > 0 -> a >= 0 -> a/b >=0. Proof. @@ -489,366 +236,165 @@ Qed. the division is strictly decreasing. *) Lemma Z_div_lt : forall a b:Z, b >= 2 -> a > 0 -> 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. -Qed. - +Proof. intros. apply Z.div_lt; auto with zarith. Qed. (** A division of a small number by a bigger one yields zero. *) Theorem Zdiv_small: forall a b, 0 <= a < b -> a/b = 0. -Proof. - intros a b H; apply sym_equal; apply Zdiv_unique with a; auto with zarith. -Qed. +Proof Z.div_small. (** Same situation, in term of modulo: *) Theorem Zmod_small: forall a n, 0 <= a < n -> a mod n = a. -Proof. - intros a b H; apply sym_equal; apply Zmod_unique with 0; auto with zarith. -Qed. +Proof Z.mod_small. -(** [Zge] is compatible with a positive division. *) +(** [Z.ge] is compatible with a positive division. *) 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. - replace (b-a) with (c * (b/c-a/c) + b mod c - a mod c) by - (symmetry; pattern a at 1; rewrite H2; pattern b at 1; rewrite H0; ring). - assert (c * (b / c - a / c) >= c * 1). - apply Zmult_ge_compat_l. - omega. - omega. - assert (c * 1 = c). - ring. - omega. -Qed. +Proof. intros. apply Z.le_ge. apply Z.div_le_mono; auto with zarith. Qed. -(** Same, with [Zle]. *) +(** Same, with [Z.le]. *) Lemma Z_div_le : forall a b c:Z, c > 0 -> a <= b -> a/c <= b/c. -Proof. - intros a b c H H0. - apply Zge_le. - apply Z_div_ge; auto with *. -Qed. +Proof. intros. apply Z.div_le_mono; auto with zarith. Qed. (** With our choice of division, rounding of (a/b) is always done toward bottom: *) Lemma Z_mult_div_ge : forall a b:Z, b > 0 -> b*(a/b) <= a. -Proof. - intros a b H; generalize (Z_div_mod_eq a b H) (Z_mod_lt a b H); omega. -Qed. +Proof. intros. apply Z.mul_div_le; auto with zarith. Qed. Lemma Z_mult_div_ge_neg : forall a b:Z, b < 0 -> b*(a/b) >= a. -Proof. - intros a b H. - generalize (Z_div_mod_eq_full a _ (Zlt_not_eq _ _ H)) (Z_mod_neg a _ H); omega. -Qed. +Proof. intros. apply Z.le_ge. apply Z.mul_div_ge; auto with zarith. Qed. (** The previous inequalities are exact iff the modulo is zero. *) Lemma Z_div_exact_full_1 : forall a b:Z, a = b*(a/b) -> a mod b = 0. -Proof. - intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst b; simpl in *; subst; auto. - generalize (Z_div_mod_eq_full a b Hb); omega. -Qed. +Proof. intros a b. zero_or_not b. rewrite Z.div_exact; auto. Qed. Lemma Z_div_exact_full_2 : forall a b:Z, b <> 0 -> a mod b = 0 -> a = b*(a/b). -Proof. - intros; generalize (Z_div_mod_eq_full a b H); omega. -Qed. +Proof. intros; rewrite Z.div_exact; auto. Qed. (** A modulo cannot grow beyond its starting point. *) Theorem Zmod_le: forall a b, 0 < b -> 0 <= a -> a mod b <= a. -Proof. - intros a b H1 H2; case (Zle_or_lt b a); intros H3. - case (Z_mod_lt a b); auto with zarith. - rewrite Zmod_small; auto with zarith. -Qed. +Proof. intros. apply Z.mod_le; auto. Qed. -(** Some additionnal inequalities about Zdiv. *) +(** Some additionnal inequalities about Z.div. *) Theorem Zdiv_lt_upper_bound: forall a b q, 0 < b -> a < q*b -> a/b < q. -Proof. - intros a b q H1 H2. - apply Zmult_lt_reg_r with b; auto with zarith. - apply Zle_lt_trans with (2 := H2). - pattern a at 2; rewrite (Z_div_mod_eq a b); auto with zarith. - rewrite (Zmult_comm b); case (Z_mod_lt a b); auto with zarith. -Qed. +Proof. intros a b q; rewrite Z.mul_comm; apply Z.div_lt_upper_bound. Qed. Theorem Zdiv_le_upper_bound: forall a b q, 0 < b -> a <= q*b -> a/b <= q. -Proof. - intros. - rewrite <- (Z_div_mult_full q b); auto with zarith. - apply Z_div_le; auto with zarith. -Qed. +Proof. intros a b q; rewrite Z.mul_comm; apply Z.div_le_upper_bound. Qed. Theorem Zdiv_le_lower_bound: forall a b q, 0 < b -> q*b <= a -> q <= a/b. -Proof. - intros. - rewrite <- (Z_div_mult_full q b); auto with zarith. - apply Z_div_le; auto with zarith. -Qed. +Proof. intros a b q; rewrite Z.mul_comm; apply Z.div_le_lower_bound. Qed. (** A division of respect opposite monotonicity for the divisor *) Lemma Zdiv_le_compat_l: forall p q r, 0 <= p -> 0 < q < r -> p / r <= p / q. -Proof. - intros p q r H H1. - apply Zdiv_le_lower_bound; auto with zarith. - rewrite Zmult_comm. - pattern p at 2; rewrite (Z_div_mod_eq p r); auto with zarith. - apply Zle_trans with (r * (p / r)); auto with zarith. - apply Zmult_le_compat_r; auto with zarith. - apply Zdiv_le_lower_bound; auto with zarith. - case (Z_mod_lt p r); auto with zarith. -Qed. +Proof. intros; apply Z.div_le_compat_l; auto with zarith. Qed. Theorem Zdiv_sgn: forall a b, - 0 <= Zsgn (a/b) * Zsgn a * Zsgn b. + 0 <= Z.sgn (a/b) * Z.sgn a * Z.sgn b. Proof. destruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith; - generalize (Z_div_pos (Zpos a) (Zpos b)); unfold Zdiv, Zdiv_eucl; - destruct Zdiv_eucl_POS as (q,r); destruct r; omega with *. + generalize (Z.div_pos (Zpos a) (Zpos b)); unfold Z.div, Z.div_eucl; + destruct Z.pos_div_eucl as (q,r); destruct r; omega with *. Qed. -(** * Relations between usual operations and Zmod and Zdiv *) +(** * Relations between usual operations and Z.modulo and Z.div *) Lemma Z_mod_plus_full : forall a b c:Z, (a + b * c) mod c = a mod c. -Proof. - intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. - subst; do 2 rewrite Zmod_0_r; auto. - symmetry; apply Zmod_unique_full with (a/c+b); auto with zarith. - red; generalize (Z_mod_lt a c)(Z_mod_neg a c); omega. - rewrite Zmult_plus_distr_r, Zmult_comm. - generalize (Z_div_mod_eq_full a c Hc); omega. -Qed. +Proof. intros. zero_or_not c. apply Z.mod_add; auto. Qed. Lemma Z_div_plus_full : forall a b c:Z, c <> 0 -> (a + b * c) / c = a / c + b. -Proof. - intro; symmetry. - apply Zdiv_unique_full with (a mod c); auto with zarith. - red; generalize (Z_mod_lt a c)(Z_mod_neg a c); omega. - rewrite Zmult_plus_distr_r, Zmult_comm. - generalize (Z_div_mod_eq_full a c H); omega. -Qed. +Proof Z.div_add. Theorem Z_div_plus_full_l: forall a b c : Z, b <> 0 -> (a * b + c) / b = a + c / b. -Proof. - intros a b c H; rewrite Zplus_comm; rewrite Z_div_plus_full; - try apply Zplus_comm; auto with zarith. -Qed. +Proof Z.div_add_l. -(** [Zopp] and [Zdiv], [Zmod]. +(** [Z.opp] and [Z.div], [Z.modulo]. Due to the choice of convention for our Euclidean division, - some of the relations about [Zopp] and divisions are rather complex. *) + some of the relations about [Z.opp] and divisions are rather complex. *) Lemma Zdiv_opp_opp : forall a b:Z, (-a)/(-b) = a/b. -Proof. - intros [|a|a] [|b|b]; try reflexivity; unfold Zdiv; simpl; - destruct (Zdiv_eucl_POS a (Zpos b)); destruct z0; try reflexivity. -Qed. +Proof. intros. zero_or_not b. apply Z.div_opp_opp; auto. Qed. Lemma Zmod_opp_opp : forall a b:Z, (-a) mod (-b) = - (a mod b). -Proof. - intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; do 2 rewrite Zmod_0_r; auto. - intros; symmetry. - apply Zmod_unique_full with ((-a)/(-b)); auto. - generalize (Z_mod_remainder a b Hb); destruct 1; [right|left]; omega. - rewrite Zdiv_opp_opp. - pattern a at 1; rewrite (Z_div_mod_eq_full a b Hb); ring. -Qed. +Proof. intros. zero_or_not b. apply Z.mod_opp_opp; auto. Qed. Lemma Z_mod_zero_opp_full : forall a b:Z, a mod b = 0 -> (-a) mod b = 0. -Proof. - intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; rewrite Zmod_0_r; auto. - rewrite Z_div_exact_full_2 with a b; auto. - replace (- (b * (a / b))) with (0 + - (a / b) * b). - rewrite Z_mod_plus_full; auto. - ring. -Qed. +Proof. intros. zero_or_not b. apply Z.mod_opp_l_z; auto. Qed. Lemma Z_mod_nz_opp_full : forall a b:Z, a mod b <> 0 -> (-a) mod b = b - (a mod b). -Proof. - intros. - assert (b<>0) by (contradict H; subst; rewrite Zmod_0_r; auto). - symmetry; apply Zmod_unique_full with (-1-a/b); auto. - generalize (Z_mod_remainder a b H0); destruct 1; [left|right]; omega. - rewrite Zmult_minus_distr_l. - pattern a at 1; rewrite (Z_div_mod_eq_full a b H0); ring. -Qed. +Proof. intros. zero_or_not b. apply Z.mod_opp_l_nz; auto. Qed. Lemma Z_mod_zero_opp_r : forall a b:Z, a mod b = 0 -> a mod (-b) = 0. -Proof. - intros. - rewrite <- (Zopp_involutive a). - rewrite Zmod_opp_opp. - rewrite Z_mod_zero_opp_full; auto. -Qed. +Proof. intros. zero_or_not b. apply Z.mod_opp_r_z; auto. Qed. Lemma Z_mod_nz_opp_r : forall a b:Z, a mod b <> 0 -> a mod (-b) = (a mod b) - b. -Proof. - intros. - pattern a at 1; rewrite <- (Zopp_involutive a). - rewrite Zmod_opp_opp. - rewrite Z_mod_nz_opp_full; auto; omega. -Qed. +Proof. intros. zero_or_not b. apply Z.mod_opp_r_nz; auto. Qed. Lemma Z_div_zero_opp_full : forall a b:Z, a mod b = 0 -> (-a)/b = -(a/b). -Proof. - intros; destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; do 2 rewrite Zdiv_0_r; auto. - symmetry; apply Zdiv_unique_full with 0; auto. - red; omega. - pattern a at 1; rewrite (Z_div_mod_eq_full a b Hb). - rewrite H; ring. -Qed. +Proof. intros. zero_or_not b. apply Z.div_opp_l_z; auto. Qed. Lemma Z_div_nz_opp_full : forall a b:Z, a mod b <> 0 -> (-a)/b = -(a/b)-1. -Proof. - intros. - assert (b<>0) by (contradict H; subst; rewrite Zmod_0_r; auto). - symmetry; apply Zdiv_unique_full with (b-a mod b); auto. - generalize (Z_mod_remainder a b H0); destruct 1; [left|right]; omega. - pattern a at 1; rewrite (Z_div_mod_eq_full a b H0); ring. -Qed. +Proof. intros a b. zero_or_not b. intros; rewrite Z.div_opp_l_nz; auto. Qed. Lemma Z_div_zero_opp_r : forall a b:Z, a mod b = 0 -> a/(-b) = -(a/b). -Proof. - intros. - pattern a at 1; rewrite <- (Zopp_involutive a). - rewrite Zdiv_opp_opp. - rewrite Z_div_zero_opp_full; auto. -Qed. +Proof. intros. zero_or_not b. apply Z.div_opp_r_z; auto. Qed. Lemma Z_div_nz_opp_r : forall a b:Z, a mod b <> 0 -> a/(-b) = -(a/b)-1. -Proof. - intros. - pattern a at 1; rewrite <- (Zopp_involutive a). - rewrite Zdiv_opp_opp. - rewrite Z_div_nz_opp_full; auto; omega. -Qed. +Proof. intros a b. zero_or_not b. intros; rewrite Z.div_opp_r_nz; auto. Qed. (** Cancellations. *) -Lemma Zdiv_mult_cancel_r : forall a b c:Z, +Lemma Zdiv_mult_cancel_r : forall a b c:Z, c <> 0 -> (a*c)/(b*c) = a/b. -Proof. -assert (X: forall a b c, b > 0 -> c > 0 -> (a*c) / (b*c) = a / b). - intros a b c Hb Hc. - symmetry. - apply Zdiv_unique with ((a mod b)*c); auto with zarith. - destruct (Z_mod_lt a b Hb); split. - apply Zmult_le_0_compat; auto with zarith. - apply Zmult_lt_compat_r; auto with zarith. - pattern a at 1; rewrite (Z_div_mod_eq a b Hb); ring. -intros a b c Hc. -destruct (Z_dec b 0) as [Hb|Hb]. -destruct Hb as [Hb|Hb]; destruct (not_Zeq_inf _ _ Hc); auto with *. -rewrite <- (Zdiv_opp_opp a), <- (Zmult_opp_opp b), <-(Zmult_opp_opp a); - auto with *. -rewrite <- (Zdiv_opp_opp a), <- Zdiv_opp_opp, Zopp_mult_distr_l, - Zopp_mult_distr_l; auto with *. -rewrite <- Zdiv_opp_opp, Zopp_mult_distr_r, Zopp_mult_distr_r; auto with *. -rewrite Hb; simpl; do 2 rewrite Zdiv_0_r; auto. -Qed. +Proof. intros. zero_or_not b. apply Z.div_mul_cancel_r; auto. Qed. Lemma Zdiv_mult_cancel_l : forall a b c:Z, c<>0 -> (c*a)/(c*b) = a/b. Proof. - intros. - rewrite (Zmult_comm c a); rewrite (Zmult_comm c b). - apply Zdiv_mult_cancel_r; auto. + intros. rewrite (Z.mul_comm c b); zero_or_not b. + rewrite (Z.mul_comm b c). apply Z.div_mul_cancel_l; auto. Qed. Lemma Zmult_mod_distr_l: forall a b c, (c*a) mod (c*b) = c * (a mod b). Proof. - intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. - subst; simpl; rewrite Zmod_0_r; auto. - destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; repeat rewrite Zmult_0_r || rewrite Zmod_0_r; auto. - assert (c*b <> 0). - contradict Hc; eapply Zmult_integral_l; eauto. - rewrite (Zplus_minus_eq _ _ _ (Z_div_mod_eq_full (c*a) (c*b) H)). - rewrite (Zplus_minus_eq _ _ _ (Z_div_mod_eq_full a b Hb)). - rewrite Zdiv_mult_cancel_l; auto with zarith. - ring. + intros. zero_or_not c. rewrite (Z.mul_comm c b); zero_or_not b. + rewrite (Z.mul_comm b c). apply Z.mul_mod_distr_l; auto. Qed. Lemma Zmult_mod_distr_r: forall a b c, (a*c) mod (b*c) = (a mod b) * c. Proof. - intros; repeat rewrite (fun x => (Zmult_comm x c)). - apply Zmult_mod_distr_l; auto. + intros. zero_or_not b. rewrite (Z.mul_comm b c); zero_or_not c. + rewrite (Z.mul_comm c b). apply Z.mul_mod_distr_r; auto. Qed. (** Operations modulo. *) Theorem Zmod_mod: forall a n, (a mod n) mod n = a mod n. -Proof. - intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. - subst; do 2 rewrite Zmod_0_r; auto. - pattern a at 2; rewrite (Z_div_mod_eq_full a n); auto with zarith. - rewrite Zplus_comm; rewrite Zmult_comm. - apply sym_equal; apply Z_mod_plus_full; auto with zarith. -Qed. +Proof. intros. zero_or_not n. apply Z.mod_mod; auto. Qed. Theorem Zmult_mod: forall a b n, (a * b) mod n = ((a mod n) * (b mod n)) mod n. -Proof. - intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. - subst; do 2 rewrite Zmod_0_r; auto. - pattern a at 1; rewrite (Z_div_mod_eq_full a n); auto with zarith. - pattern b at 1; rewrite (Z_div_mod_eq_full b n); auto with zarith. - set (A:=a mod n); set (B:=b mod n); set (A':=a/n); set (B':=b/n). - replace ((n*A' + A) * (n*B' + B)) - with (A*B + (A'*B+B'*A+n*A'*B')*n) by ring. - apply Z_mod_plus_full; auto with zarith. -Qed. +Proof. intros. zero_or_not n. apply Z.mul_mod; auto. Qed. Theorem Zplus_mod: forall a b n, (a + b) mod n = (a mod n + b mod n) mod n. -Proof. - intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. - subst; do 2 rewrite Zmod_0_r; auto. - pattern a at 1; rewrite (Z_div_mod_eq_full a n); auto with zarith. - pattern b at 1; rewrite (Z_div_mod_eq_full b n); auto with zarith. - replace ((n * (a / n) + a mod n) + (n * (b / n) + b mod n)) - with ((a mod n + b mod n) + (a / n + b / n) * n) by ring. - apply Z_mod_plus_full; auto with zarith. -Qed. +Proof. intros. zero_or_not n. apply Z.add_mod; auto. Qed. Theorem Zminus_mod: forall a b n, (a - b) mod n = (a mod n - b mod n) mod n. @@ -897,54 +443,53 @@ Qed. (** For a specific number N, equality modulo N is hence a nice setoid equivalence, compatible with [+], [-] and [*]. *) -Definition eqm N a b := (a mod N = b mod N). +Section EqualityModulo. +Variable N:Z. -Lemma eqm_refl N : forall a, (eqm N) a a. +Definition eqm a b := (a mod N = b mod N). +Infix "==" := eqm (at level 70). + +Lemma eqm_refl : forall a, a == a. Proof. unfold eqm; auto. Qed. -Lemma eqm_sym N : forall a b, (eqm N) a b -> (eqm N) b a. +Lemma eqm_sym : forall a b, a == b -> b == a. Proof. unfold eqm; auto. Qed. -Lemma eqm_trans N : forall a b c, - (eqm N) a b -> (eqm N) b c -> (eqm N) a c. +Lemma eqm_trans : forall a b c, + a == b -> b == c -> a == c. Proof. unfold eqm; eauto with *. Qed. -Add Parametric Relation N : Z (eqm N) - reflexivity proved by (eqm_refl N) - symmetry proved by (eqm_sym N) - transitivity proved by (eqm_trans N) as eqm_setoid. +Instance eqm_setoid : Equivalence eqm. +Proof. + constructor; [exact eqm_refl | exact eqm_sym | exact eqm_trans]. +Qed. -Add Parametric Morphism N : Zplus - with signature (eqm N) ==> (eqm N) ==> (eqm N) as Zplus_eqm. +Instance Zplus_eqm : Proper (eqm ==> eqm ==> eqm) Z.add. Proof. - unfold eqm; intros; rewrite Zplus_mod, H, H0, <- Zplus_mod; auto. + unfold eqm; repeat red; intros. rewrite Zplus_mod, H, H0, <- Zplus_mod; auto. Qed. -Add Parametric Morphism N : Zminus - with signature (eqm N) ==> (eqm N) ==> (eqm N) as Zminus_eqm. +Instance Zminus_eqm : Proper (eqm ==> eqm ==> eqm) Z.sub. Proof. - unfold eqm; intros; rewrite Zminus_mod, H, H0, <- Zminus_mod; auto. + unfold eqm; repeat red; intros. rewrite Zminus_mod, H, H0, <- Zminus_mod; auto. Qed. -Add Parametric Morphism N : Zmult - with signature (eqm N) ==> (eqm N) ==> (eqm N) as Zmult_eqm. +Instance Zmult_eqm : Proper (eqm ==> eqm ==> eqm) Z.mul. Proof. - unfold eqm; intros; rewrite Zmult_mod, H, H0, <- Zmult_mod; auto. + unfold eqm; repeat red; intros. rewrite Zmult_mod, H, H0, <- Zmult_mod; auto. Qed. -Add Parametric Morphism N : Zopp - with signature (eqm N) ==> (eqm N) as Zopp_eqm. +Instance Zopp_eqm : Proper (eqm ==> eqm) Z.opp. Proof. - intros; change ((eqm N) (-x) (-y)) with ((eqm N) (0-x) (0-y)). - rewrite H; red; auto. + intros x y H. change ((-x)==(-y)) with ((0-x)==(0-y)). now rewrite H. Qed. -Lemma Zmod_eqm N : forall a, (eqm N) (a mod N) a. +Lemma Zmod_eqm : forall a, (a mod N) == a. Proof. intros; exact (Zmod_mod a N). Qed. -(* NB: Zmod and Zdiv are not morphisms with respect to eqm. +(* NB: Z.modulo and Z.div are not morphisms with respect to eqm. For instance, let (==) be (eqm 2). Then we have (3 == 1) but: ~ (3 mod 3 == 1 mod 3) ~ (1 mod 3 == 1 mod 1) @@ -952,32 +497,12 @@ Qed. ~ (1/3 == 1/1) *) +End EqualityModulo. + Lemma Zdiv_Zdiv : forall a b c, 0<=b -> 0<=c -> (a/b)/c = a/(b*c). Proof. - intros a b c Hb Hc. - destruct (Zle_lt_or_eq _ _ Hb); [ | subst; rewrite Zdiv_0_r, Zdiv_0_r, Zdiv_0_l; auto]. - destruct (Zle_lt_or_eq _ _ Hc); [ | subst; rewrite Zmult_0_r, Zdiv_0_r, Zdiv_0_r; auto]. - pattern a at 2;rewrite (Z_div_mod_eq_full a b);auto with zarith. - pattern (a/b) at 2;rewrite (Z_div_mod_eq_full (a/b) c);auto with zarith. - replace (b * (c * (a / b / c) + (a / b) mod c) + a mod b) with - ((a / b / c)*(b * c) + (b * ((a / b) mod c) + a mod b)) by ring. - rewrite Z_div_plus_full_l; auto with zarith. - rewrite (Zdiv_small (b * ((a / b) mod c) + a mod b)). - ring. - split. - apply Zplus_le_0_compat;auto with zarith. - apply Zmult_le_0_compat;auto with zarith. - destruct (Z_mod_lt (a/b) c);auto with zarith. - destruct (Z_mod_lt a b);auto with zarith. - apply Zle_lt_trans with (b * ((a / b) mod c) + (b-1)). - destruct (Z_mod_lt a b);auto with zarith. - apply Zle_lt_trans with (b * (c-1) + (b - 1)). - apply Zplus_le_compat;auto with zarith. - destruct (Z_mod_lt (a/b) c);auto with zarith. - replace (b * (c - 1) + (b - 1)) with (b*c-1);try ring;auto with zarith. - intro H1; - assert (H2: c <> 0) by auto with zarith; - rewrite (Zmult_integral_l _ _ H2 H1) in H; auto with zarith. + intros. zero_or_not b. rewrite Z.mul_comm. zero_or_not c. + rewrite Z.mul_comm. apply Z.div_div; auto with zarith. Qed. (** Unfortunately, the previous result isn't always true on negative numbers. @@ -988,40 +513,40 @@ Qed. Theorem Zdiv_mult_le: forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a/b) <= (c*a)/b. Proof. - intros a b c H1 H2 H3. - destruct (Zle_lt_or_eq _ _ H2); - [ | subst; rewrite Zdiv_0_r, Zdiv_0_r, Zmult_0_r; auto]. - case (Z_mod_lt a b); auto with zarith; intros Hu1 Hu2. - case (Z_mod_lt c b); auto with zarith; intros Hv1 Hv2. - apply Zmult_le_reg_r with b; auto with zarith. - rewrite <- Zmult_assoc. - replace (a / b * b) with (a - a mod b). - replace (c * a / b * b) with (c * a - (c * a) mod b). - rewrite Zmult_minus_distr_l. - unfold Zminus; apply Zplus_le_compat_l. - match goal with |- - ?X <= -?Y => assert (Y <= X); auto with zarith end. - apply Zle_trans with ((c mod b) * (a mod b)); auto with zarith. - rewrite Zmult_mod; auto with zarith. - apply (Zmod_le ((c mod b) * (a mod b)) b); auto with zarith. - apply Zmult_le_compat_r; auto with zarith. - apply (Zmod_le c b); auto. - pattern (c * a) at 1; rewrite (Z_div_mod_eq (c * a) b); try ring; - auto with zarith. - pattern a at 1; rewrite (Z_div_mod_eq a b); try ring; auto with zarith. -Qed. + intros. zero_or_not b. apply Z.div_mul_le; auto with zarith. Qed. -(** Zmod is related to divisibility (see more in Znumtheory) *) +(** Z.modulo is related to divisibility (see more in Znumtheory) *) Lemma Zmod_divides : forall a b, b<>0 -> (a mod b = 0 <-> exists c, a = b*c). Proof. - split; intros. - exists (a/b). - pattern a at 1; rewrite (Z_div_mod_eq_full a b); auto with zarith. - destruct H0 as [c Hc]. - symmetry. - apply Zmod_unique_full with c; auto with zarith. - red; omega with *. + intros. rewrite Z.mod_divide; trivial. + split; intros (c,Hc); exists c; subst; auto with zarith. +Qed. + +(** Particular case : dividing by 2 is related with parity *) + +Lemma Zdiv2_div : forall a, Z.div2 a = a/2. +Proof Z.div2_div. + +Lemma Zmod_odd : forall a, a mod 2 = if Z.odd a then 1 else 0. +Proof. + intros a. now rewrite <- Z.bit0_odd, <- Z.bit0_mod. +Qed. + +Lemma Zmod_even : forall a, a mod 2 = if Z.even a then 0 else 1. +Proof. + intros a. rewrite Zmod_odd, Zodd_even_bool. now destruct Z.even. +Qed. + +Lemma Zodd_mod : forall a, Z.odd a = Zeq_bool (a mod 2) 1. +Proof. + intros a. rewrite Zmod_odd. now destruct Z.odd. +Qed. + +Lemma Zeven_mod : forall a, Z.even a = Zeq_bool (a mod 2) 0. +Proof. + intros a. rewrite Zmod_even. now destruct Z.even. Qed. (** * Compatibility *) @@ -1068,19 +593,19 @@ Proof. intros; apply Z_mod_zero_opp_full; auto with zarith. Qed. -(** * A direct way to compute Zmod *) +(** * A direct way to compute Z.modulo *) Fixpoint Zmod_POS (a : positive) (b : Z) : Z := match a with | xI a' => let r := Zmod_POS a' b in let r' := (2 * r + 1) in - if Zgt_bool b r' then r' else (r' - b) + if r' <? b then r' else (r' - b) | xO a' => let r := Zmod_POS a' b in let r' := (2 * r) in - if Zgt_bool b r' then r' else (r' - b) - | xH => if Zge_bool b 2 then 1 else 0 + if r' <? b then r' else (r' - b) + | xH => if 2 <=? b then 1 else 0 end. Definition Zmod' a b := @@ -1105,30 +630,28 @@ Definition Zmod' a b := end. -Theorem Zmod_POS_correct: forall a b, Zmod_POS a b = (snd (Zdiv_eucl_POS a b)). +Theorem Zmod_POS_correct a b : Zmod_POS a b = snd (Z.pos_div_eucl a b). Proof. - intros a b; elim a; simpl; auto. - intros p Rec; rewrite Rec. - case (Zdiv_eucl_POS p b); intros z1 z2; simpl; auto. - match goal with |- context [Zgt_bool _ ?X] => case (Zgt_bool b X) end; auto. - intros p Rec; rewrite Rec. - case (Zdiv_eucl_POS p b); intros z1 z2; simpl; auto. - match goal with |- context [Zgt_bool _ ?X] => case (Zgt_bool b X) end; auto. - case (Zge_bool b 2); auto. + induction a as [a IH|a IH| ]; simpl; rewrite ?IH. + destruct (Z.pos_div_eucl a b) as (p,q); simpl; + case Z.ltb_spec; reflexivity. + destruct (Z.pos_div_eucl a b) as (p,q); simpl; + case Z.ltb_spec; reflexivity. + case Z.leb_spec; trivial. Qed. -Theorem Zmod'_correct: forall a b, Zmod' a b = Zmod a b. +Theorem Zmod'_correct: forall a b, Zmod' a b = a mod b. Proof. - intros a b; unfold Zmod; case a; simpl; auto. + intros a b; unfold Z.modulo; case a; simpl; auto. intros p; case b; simpl; auto. intros p1; refine (Zmod_POS_correct _ _); auto. intros p1; rewrite Zmod_POS_correct; auto. - case (Zdiv_eucl_POS p (Zpos p1)); simpl; intros z1 z2; case z2; auto. + case (Z.pos_div_eucl p (Zpos p1)); simpl; intros z1 z2; case z2; auto. intros p; case b; simpl; auto. intros p1; rewrite Zmod_POS_correct; auto. - case (Zdiv_eucl_POS p (Zpos p1)); simpl; intros z1 z2; case z2; auto. + case (Z.pos_div_eucl p (Zpos p1)); simpl; intros z1 z2; case z2; auto. intros p1; rewrite Zmod_POS_correct; simpl; auto. - case (Zdiv_eucl_POS p (Zpos p1)); auto. + case (Z.pos_div_eucl p (Zpos p1)); auto. Qed. @@ -1140,30 +663,46 @@ 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}. + {qr : Z * Z | let (q, r) := qr in a = b * q + r /\ 0 <= r < Z.abs 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 ]. + rewrite Z.abs_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 ]. + rewrite <- Z.mul_opp_comm; assumption. + rewrite Z.abs_neq; [ assumption | omega ]. Qed. -Implicit Arguments Zdiv_eucl_extended. +Arguments Zdiv_eucl_extended : default implicits. -(** A third convention: Ocaml. +(** * Division and modulo in Z agree with same in nat: *) - See files ZOdiv_def.v and ZOdiv.v. +Require Import NPeano. - Ocaml uses Round-Toward-Zero division: (-a)/b = a/(-b) = -(a/b). - Hence (-a) mod b = - (a mod b) - a mod (-b) = a mod b - And: |r| < |b| and sgn(r) = sgn(a) (notice the a here instead of b). -*) +Lemma div_Zdiv (n m: nat): m <> O -> + Z.of_nat (n / m) = Z.of_nat n / Z.of_nat m. +Proof. + intros. + apply (Zdiv_unique _ _ _ (Z.of_nat (n mod m))). + split. auto with zarith. + now apply inj_lt, Nat.mod_upper_bound. + rewrite <- Nat2Z.inj_mul, <- Nat2Z.inj_add. + now apply inj_eq, Nat.div_mod. +Qed. + +Lemma mod_Zmod (n m: nat): m <> O -> + Z.of_nat (n mod m) = (Z.of_nat n) mod (Z.of_nat m). +Proof. + intros. + apply (Zmod_unique _ _ (Z.of_nat n / Z.of_nat m)). + split. auto with zarith. + now apply inj_lt, Nat.mod_upper_bound. + rewrite <- div_Zdiv, <- Nat2Z.inj_mul, <- Nat2Z.inj_add by trivial. + now apply inj_eq, Nat.div_mod. +Qed. diff --git a/theories/ZArith/Zeuclid.v b/theories/ZArith/Zeuclid.v new file mode 100644 index 00000000..1dfe2fb3 --- /dev/null +++ b/theories/ZArith/Zeuclid.v @@ -0,0 +1,52 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +Require Import Morphisms BinInt ZDivEucl. +Local Open Scope Z_scope. + +(** * Definitions of division for binary integers, Euclid convention. *) + +(** In this convention, the remainder is always positive. + For other conventions, see [Z.div] and [Z.quot] in file [BinIntDef]. + To avoid collision with the other divisions, we place this one + under a module. +*) + +Module ZEuclid. + + Definition modulo a b := Z.modulo a (Z.abs b). + Definition div a b := (Z.sgn b) * (Z.div a (Z.abs b)). + + Instance mod_wd : Proper (eq==>eq==>eq) modulo. + Proof. congruence. Qed. + Instance div_wd : Proper (eq==>eq==>eq) div. + Proof. congruence. Qed. + + Theorem div_mod a b : b<>0 -> a = b*(div a b) + modulo a b. + Proof. + intros Hb. unfold div, modulo. + rewrite Z.mul_assoc. rewrite Z.sgn_abs. apply Z.div_mod. + now destruct b. + Qed. + + Lemma mod_always_pos a b : b<>0 -> 0 <= modulo a b < Z.abs b. + Proof. + intros Hb. unfold modulo. + apply Z.mod_pos_bound. + destruct b; compute; trivial. now destruct Hb. + Qed. + + Lemma mod_bound_pos a b : 0<=a -> 0<b -> 0 <= modulo a b < b. + Proof. + intros _ Hb. rewrite <- (Z.abs_eq b) at 3 by Z.order. + apply mod_always_pos. Z.order. + Qed. + + Include ZEuclidProp Z Z Z. + +End ZEuclid. diff --git a/theories/ZArith/Zeven.v b/theories/ZArith/Zeven.v index 883b7f15..dd48e84f 100644 --- a/theories/ZArith/Zeven.v +++ b/theories/ZArith/Zeven.v @@ -1,22 +1,25 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zeven.v 14641 2011-11-06 11:59:10Z herbelin $ i*) +(** Binary Integers : Parity and Division by Two *) +(** Initial author : Pierre Crégut (CNET, Lannion, France) *) + +(** THIS FILE IS DEPRECATED. + It is now almost entirely made of compatibility formulations + for results already present in BinInt.Z. *) Require Import BinInt. Open Scope Z_scope. -(*******************************************************************) -(** About parity: even and odd predicates on Z, division by 2 on Z *) - -(***************************************************) -(** * [Zeven], [Zodd] and their related properties *) +(** Historical formulation of even and odd predicates, based on + case analysis. We now rather recommend using [Z.Even] and + [Z.Odd], which are based on the exist predicate. *) Definition Zeven (z:Z) := match z with @@ -35,281 +38,251 @@ Definition Zodd (z:Z) := | _ => False end. -Definition Zeven_bool (z:Z) := - match z with - | Z0 => true - | Zpos (xO _) => true - | Zneg (xO _) => true - | _ => false - end. +Lemma Zeven_equiv z : Zeven z <-> Z.Even z. +Proof. + rewrite <- Z.even_spec. + destruct z as [|p|p]; try destruct p; simpl; intuition. +Qed. -Definition Zodd_bool (z:Z) := - match z with - | Z0 => false - | Zpos (xO _) => false - | Zneg (xO _) => false - | _ => true - end. +Lemma Zodd_equiv z : Zodd z <-> Z.Odd z. +Proof. + rewrite <- Z.odd_spec. + destruct z as [|p|p]; try destruct p; simpl; intuition. +Qed. + +Theorem Zeven_ex_iff n : Zeven n <-> exists m, n = 2*m. +Proof (Zeven_equiv n). + +Theorem Zodd_ex_iff n : Zodd n <-> exists m, n = 2*m + 1. +Proof (Zodd_equiv n). + +(** Boolean tests of parity (now in BinInt.Z) *) + +Notation Zeven_bool := Z.even (compat "8.3"). +Notation Zodd_bool := Z.odd (compat "8.3"). + +Lemma Zeven_bool_iff n : Z.even n = true <-> Zeven n. +Proof. + now rewrite Z.even_spec, Zeven_equiv. +Qed. + +Lemma Zodd_bool_iff n : Z.odd n = true <-> Zodd n. +Proof. + now rewrite Z.odd_spec, Zodd_equiv. +Qed. + +Ltac boolify_even_odd := rewrite <- ?Zeven_bool_iff, <- ?Zodd_bool_iff. + +Lemma Zodd_even_bool n : Z.odd n = negb (Z.even n). +Proof. + symmetry. apply Z.negb_even. +Qed. + +Lemma Zeven_odd_bool n : Z.even n = negb (Z.odd n). +Proof. + symmetry. apply Z.negb_odd. +Qed. -Definition Zeven_odd_dec : forall z:Z, {Zeven z} + {Zodd z}. +Definition Zeven_odd_dec n : {Zeven n} + {Zodd n}. 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) ]. + destruct n as [|p|p]; try destruct p; simpl; (now left) || (now right). Defined. -Definition Zeven_dec : forall z:Z, {Zeven z} + {~ Zeven z}. +Definition Zeven_dec n : {Zeven n} + {~ Zeven n}. 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) ]. + destruct n as [|p|p]; try destruct p; simpl; (now left) || (now right). Defined. -Definition Zodd_dec : forall z:Z, {Zodd z} + {~ Zodd z}. +Definition Zodd_dec n : {Zodd n} + {~ Zodd n}. 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) ]. + destruct n as [|p|p]; try destruct p; simpl; (now left) || (now right). Defined. -Lemma Zeven_not_Zodd : forall n:Z, Zeven n -> ~ Zodd n. +Lemma Zeven_not_Zodd n : Zeven n -> ~ Zodd n. Proof. - intro z; destruct z; [ idtac | destruct p | destruct p ]; compute in |- *; - trivial. + boolify_even_odd. rewrite <- Z.negb_odd. destruct Z.odd; intuition. Qed. -Lemma Zodd_not_Zeven : forall n:Z, Zodd n -> ~ Zeven n. +Lemma Zodd_not_Zeven n : Zodd n -> ~ Zeven n. Proof. - intro z; destruct z; [ idtac | destruct p | destruct p ]; compute in |- *; - trivial. + boolify_even_odd. rewrite <- Z.negb_odd. destruct Z.odd; intuition. Qed. -Lemma Zeven_Sn : forall n:Z, Zodd n -> Zeven (Zsucc n). +Lemma Zeven_Sn n : Zodd n -> Zeven (Z.succ 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. + boolify_even_odd. now rewrite Z.even_succ. Qed. -Lemma Zodd_Sn : forall n:Z, Zeven n -> Zodd (Zsucc n). +Lemma Zodd_Sn n : Zeven n -> Zodd (Z.succ 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. + boolify_even_odd. now rewrite Z.odd_succ. Qed. -Lemma Zeven_pred : forall n:Z, Zodd n -> Zeven (Zpred n). +Lemma Zeven_pred n : Zodd n -> Zeven (Z.pred 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. + boolify_even_odd. now rewrite Z.even_pred. Qed. -Lemma Zodd_pred : forall n:Z, Zeven n -> Zodd (Zpred n). +Lemma Zodd_pred n : Zeven n -> Zodd (Z.pred 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. + boolify_even_odd. now rewrite Z.odd_pred. Qed. Hint Unfold Zeven Zodd: zarith. +Notation Zeven_bool_succ := Z.even_succ (compat "8.3"). +Notation Zeven_bool_pred := Z.even_pred (compat "8.3"). +Notation Zodd_bool_succ := Z.odd_succ (compat "8.3"). +Notation Zodd_bool_pred := Z.odd_pred (compat "8.3"). (******************************************************************) -(** * Definition of [Zdiv2] and properties wrt [Zeven] and [Zodd] *) +(** * Definition of [Z.quot2], [Z.div2] 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] *) +Notation Zdiv2 := Z.div2 (compat "8.3"). +Notation Zquot2 := Z.quot2 (compat "8.3"). -Definition Zdiv2 (z:Z) := - match z with - | Z0 => 0 - | Zpos xH => 0 - | Zpos p => Zpos (Pdiv2 p) - | Zneg xH => 0 - | Zneg p => Zneg (Pdiv2 p) - end. +(** Properties of [Z.div2] *) -Lemma Zeven_div2 : forall n:Z, Zeven n -> n = 2 * Zdiv2 n. +Lemma Zdiv2_odd_eqn n : n = 2*(Z.div2 n) + if Z.odd n then 1 else 0. +Proof (Z.div2_odd n). + +Lemma Zeven_div2 n : Zeven n -> n = 2 * Z.div2 n. 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. + boolify_even_odd. rewrite <- Z.negb_odd, Bool.negb_true_iff. + intros Hn. rewrite (Zdiv2_odd_eqn n) at 1. now rewrite Hn, Z.add_0_r. Qed. -Lemma Zodd_div2 : forall n:Z, n >= 0 -> Zodd n -> n = 2 * Zdiv2 n + 1. +Lemma Zodd_div2 n : Zodd n -> n = 2 * Z.div2 n + 1. 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); red in |- *; auto with arith. + boolify_even_odd. + intros Hn. rewrite (Zdiv2_odd_eqn n) at 1. now rewrite Hn. Qed. -Lemma Zodd_div2_neg : - forall n:Z, n <= 0 -> Zodd n -> n = 2 * Zdiv2 n - 1. +(** Properties of [Z.quot2] *) + +(** TODO: move to Numbers someday *) + +Lemma Zquot2_odd_eqn n : n = 2*(Z.quot2 n) + if Z.odd n then Z.sgn n else 0. Proof. - intro x; destruct x. - intros. absurd (Zodd 0); red in |- *; auto with arith. - intros. absurd (Zneg p >= 0); red in |- *; auto with arith. - destruct p; auto with arith. - intros. absurd (Zodd (Zneg (xO p))); red in |- *; auto with arith. + now destruct n as [ |[p|p| ]|[p|p| ]]. Qed. -Lemma Z_modulo_2 : - forall n:Z, {y : Z | n = 2 * y} + {y : Z | n = 2 * y + 1}. +Lemma Zeven_quot2 n : Zeven n -> n = 2 * Z.quot2 n. 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 Hn. apply Zeven_bool_iff in Hn. + rewrite (Zquot2_odd_eqn n) at 1. + now rewrite Zodd_even_bool, Hn, Z.add_0_r. Qed. -Lemma Zsplit2 : - forall n:Z, - {p : Z * Z | - let (x1, x2) := p in n = x1 + x2 /\ (x1 = x2 \/ x2 = x1 + 1)}. +Lemma Zodd_quot2 n : n >= 0 -> Zodd n -> n = 2 * Z.quot2 n + 1. 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. + intros Hn Hn'. apply Zodd_bool_iff in Hn'. + rewrite (Zquot2_odd_eqn n) at 1. rewrite Hn'. f_equal. + destruct n; (now destruct Hn) || easy. Qed. +Lemma Zodd_quot2_neg n : n <= 0 -> Zodd n -> n = 2 * Z.quot2 n - 1. +Proof. + intros Hn Hn'. apply Zodd_bool_iff in Hn'. + rewrite (Zquot2_odd_eqn n) at 1; rewrite Hn'. unfold Z.sub. f_equal. + destruct n; (now destruct Hn) || easy. +Qed. -Theorem Zeven_ex: forall n, Zeven n -> exists m, n = 2 * m. +Lemma Zquot2_opp n : Z.quot2 (-n) = - Z.quot2 n. Proof. - intro n; exists (Zdiv2 n); apply Zeven_div2; auto. + now destruct n as [ |[p|p| ]|[p|p| ]]. Qed. -Theorem Zodd_ex: forall n, Zodd n -> exists m, n = 2 * m + 1. +Lemma Zquot2_quot n : Z.quot2 n = n ÷ 2. Proof. - destruct n; intros. - inversion H. - exists (Zdiv2 (Zpos p)). - apply Zodd_div2; simpl; auto; compute; inversion 1. - exists (Zdiv2 (Zneg p) - 1). - unfold Zminus. - rewrite Zmult_plus_distr_r. - rewrite <- Zplus_assoc. - assert (Zneg p <= 0) by (compute; inversion 1). - exact (Zodd_div2_neg _ H0 H). + assert (AUX : forall m, 0 < m -> Z.quot2 m = m ÷ 2). + { intros m Hm. + apply Z.quot_unique with (if Z.odd m then Z.sgn m else 0). + now apply Z.lt_le_incl. + rewrite Z.sgn_pos by trivial. + destruct (Z.odd m); now split. + apply Zquot2_odd_eqn. } + destruct (Z.lt_trichotomy 0 n) as [POS|[NUL|NEG]]. + - now apply AUX. + - now subst. + - apply Z.opp_inj. rewrite <- Z.quot_opp_l, <- Zquot2_opp. + apply AUX. now destruct n. easy. Qed. -Theorem Zeven_2p: forall p, Zeven (2 * p). +(** More properties of parity *) + +Lemma Z_modulo_2 n : {y | n = 2 * y} + {y | n = 2 * y + 1}. Proof. - destruct p; simpl; auto. + destruct (Zeven_odd_dec n) as [Hn|Hn]. + - left. exists (Z.div2 n). exact (Zeven_div2 n Hn). + - right. exists (Z.div2 n). exact (Zodd_div2 n Hn). Qed. -Theorem Zodd_2p_plus_1: forall p, Zodd (2 * p + 1). +Lemma Zsplit2 n : + {p : Z * Z | let (x1, x2) := p in n = x1 + x2 /\ (x1 = x2 \/ x2 = x1 + 1)}. Proof. - destruct p; simpl; auto. - destruct p; simpl; auto. + destruct (Z_modulo_2 n) as [(y,Hy)|(y,Hy)]; + rewrite <- Z.add_diag in Hy. + - exists (y, y). split. assumption. now left. + - exists (y, y + 1). split. now rewrite Z.add_assoc. now right. Qed. -Theorem Zeven_plus_Zodd: forall a b, - Zeven a -> Zodd b -> Zodd (a + b). +Theorem Zeven_ex n : Zeven n -> exists m, n = 2 * m. Proof. - intros a b H1 H2; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. - case Zodd_ex with (1 := H2); intros y H4; try rewrite H4; auto. - replace (2 * x + (2 * y + 1)) with (2 * (x + y) + 1); try apply Zodd_2p_plus_1; auto with zarith. - rewrite Zmult_plus_distr_r, Zplus_assoc; auto. + exists (Z.div2 n); apply Zeven_div2; auto. Qed. -Theorem Zeven_plus_Zeven: forall a b, - Zeven a -> Zeven b -> Zeven (a + b). +Theorem Zodd_ex n : Zodd n -> exists m, n = 2 * m + 1. Proof. - intros a b H1 H2; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. - case Zeven_ex with (1 := H2); intros y H4; try rewrite H4; auto. - replace (2 * x + 2 * y) with (2 * (x + y)); try apply Zeven_2p; auto with zarith. - apply Zmult_plus_distr_r; auto. + exists (Z.div2 n); apply Zodd_div2; auto. Qed. -Theorem Zodd_plus_Zeven: forall a b, - Zodd a -> Zeven b -> Zodd (a + b). +Theorem Zeven_2p p : Zeven (2 * p). Proof. - intros a b H1 H2; rewrite Zplus_comm; apply Zeven_plus_Zodd; auto. + now destruct p. Qed. -Theorem Zodd_plus_Zodd: forall a b, - Zodd a -> Zodd b -> Zeven (a + b). +Theorem Zodd_2p_plus_1 p : Zodd (2 * p + 1). Proof. - intros a b H1 H2; case Zodd_ex with (1 := H1); intros x H3; try rewrite H3; auto. - case Zodd_ex with (1 := H2); intros y H4; try rewrite H4; auto. - replace ((2 * x + 1) + (2 * y + 1)) with (2 * (x + y + 1)); try apply Zeven_2p; auto. - (* ring part *) - do 2 rewrite Zmult_plus_distr_r; auto. - repeat rewrite <- Zplus_assoc; f_equal. - rewrite (Zplus_comm 1). - repeat rewrite <- Zplus_assoc; auto. + destruct p as [|p|p]; now try destruct p. Qed. -Theorem Zeven_mult_Zeven_l: forall a b, - Zeven a -> Zeven (a * b). +Theorem Zeven_plus_Zodd a b : Zeven a -> Zodd b -> Zodd (a + b). Proof. - intros a b H1; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. - replace (2 * x * b) with (2 * (x * b)); try apply Zeven_2p; auto with zarith. - (* ring part *) - apply Zmult_assoc. + boolify_even_odd. rewrite <- Z.negb_odd, Bool.negb_true_iff. + intros Ha Hb. now rewrite Z.odd_add, Ha, Hb. Qed. -Theorem Zeven_mult_Zeven_r: forall a b, - Zeven b -> Zeven (a * b). +Theorem Zeven_plus_Zeven a b : Zeven a -> Zeven b -> Zeven (a + b). Proof. - intros a b H1; case Zeven_ex with (1 := H1); intros x H3; try rewrite H3; auto. - replace (a * (2 * x)) with (2 * (x * a)); try apply Zeven_2p; auto. - (* ring part *) - rewrite (Zmult_comm x a). - do 2 rewrite Zmult_assoc. - rewrite (Zmult_comm 2 a); auto. + boolify_even_odd. intros Ha Hb. now rewrite Z.even_add, Ha, Hb. Qed. -Hint Rewrite Zmult_plus_distr_r Zmult_plus_distr_l - Zplus_assoc Zmult_1_r Zmult_1_l : Zexpand. +Theorem Zodd_plus_Zeven a b : Zodd a -> Zeven b -> Zodd (a + b). +Proof. + intros. rewrite Z.add_comm. now apply Zeven_plus_Zodd. +Qed. + +Theorem Zodd_plus_Zodd a b : Zodd a -> Zodd b -> Zeven (a + b). +Proof. + boolify_even_odd. rewrite <- 2 Z.negb_even, 2 Bool.negb_true_iff. + intros Ha Hb. now rewrite Z.even_add, Ha, Hb. +Qed. + +Theorem Zeven_mult_Zeven_l a b : Zeven a -> Zeven (a * b). +Proof. + boolify_even_odd. intros Ha. now rewrite Z.even_mul, Ha. +Qed. + +Theorem Zeven_mult_Zeven_r a b : Zeven b -> Zeven (a * b). +Proof. + intros. rewrite Z.mul_comm. now apply Zeven_mult_Zeven_l. +Qed. -Theorem Zodd_mult_Zodd: forall a b, - Zodd a -> Zodd b -> Zodd (a * b). +Theorem Zodd_mult_Zodd a b : Zodd a -> Zodd b -> Zodd (a * b). Proof. - intros a b H1 H2; case Zodd_ex with (1 := H1); intros x H3; try rewrite H3; auto. - case Zodd_ex with (1 := H2); intros y H4; try rewrite H4; auto. - replace ((2 * x + 1) * (2 * y + 1)) with (2 * (2 * x * y + x + y) + 1); try apply Zodd_2p_plus_1; auto. - (* ring part *) - autorewrite with Zexpand; f_equal. - repeat rewrite <- Zplus_assoc; f_equal. - repeat rewrite <- Zmult_assoc; f_equal. - repeat rewrite Zmult_assoc; f_equal; apply Zmult_comm. + boolify_even_odd. intros Ha Hb. now rewrite Z.odd_mul, Ha, Hb. Qed. (* for compatibility *) diff --git a/theories/ZArith/Zgcd_alt.v b/theories/ZArith/Zgcd_alt.v index 86fe0ef9..40d2b129 100644 --- a/theories/ZArith/Zgcd_alt.v +++ b/theories/ZArith/Zgcd_alt.v @@ -1,23 +1,21 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zgcd_alt.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - -(** * Zgcd_alt : an alternate version of Zgcd, based on Euler's algorithm *) +(** * Zgcd_alt : an alternate version of Z.gcd, based on Euclid's algorithm *) (** Author: Pierre Letouzey *) -(** The alternate [Zgcd_alt] given here used to be the main [Zgcd] - function (see file [Znumtheory]), but this main [Zgcd] is now +(** The alternate [Zgcd_alt] given here used to be the main [Z.gcd] + function (see file [Znumtheory]), but this main [Z.gcd] is now based on a modern binary-efficient algorithm. This earlier - version, based on Euler's algorithm of iterated modulo, is kept + version, based on Euclid's algorithm of iterated modulo, is kept here due to both its intrinsic interest and its use as reference point when proving gcd on Int31 numbers *) @@ -37,22 +35,22 @@ Open Scope Z_scope. match n with | O => 1 (* arbitrary, since n should be big enough *) | S n => match a with - | Z0 => Zabs b - | Zpos _ => Zgcdn n (Zmod b a) a - | Zneg a => Zgcdn n (Zmod b (Zpos a)) (Zpos a) + | Z0 => Z.abs b + | Zpos _ => Zgcdn n (Z.modulo b a) a + | Zneg a => Zgcdn n (Z.modulo b (Zpos a)) (Zpos a) end end. Definition Zgcd_bound (a:Z) := match a with | Z0 => S O - | Zpos p => let n := Psize p in (n+n)%nat - | Zneg p => let n := Psize p in (n+n)%nat + | Zpos p => let n := Pos.size_nat p in (n+n)%nat + | Zneg p => let n := Pos.size_nat p in (n+n)%nat end. Definition Zgcd_alt a b := Zgcdn (Zgcd_bound a) a b. - (** A first obvious fact : [Zgcd a b] is positive. *) + (** A first obvious fact : [Z.gcd a b] is positive. *) Lemma Zgcdn_pos : forall n a b, 0 <= Zgcdn n a b. @@ -64,28 +62,28 @@ Open Scope Z_scope. Lemma Zgcd_alt_pos : forall a b, 0 <= Zgcd_alt a b. Proof. - intros; unfold Zgcd; apply Zgcdn_pos; auto. + intros; unfold Z.gcd; apply Zgcdn_pos; auto. Qed. - (** We now prove that Zgcd is indeed a gcd. *) + (** We now prove that Z.gcd is indeed a gcd. *) (** 1) We prove a weaker & easier bound. *) Lemma Zgcdn_linear_bound : forall n a b, - Zabs a < Z_of_nat n -> Zis_gcd a b (Zgcdn n a b). + Z.abs a < Z.of_nat n -> Zis_gcd a b (Zgcdn n a b). Proof. induction n. simpl; intros. - exfalso; generalize (Zabs_pos a); omega. + exfalso; generalize (Z.abs_nonneg a); omega. destruct a; intros; simpl; [ generalize (Zis_gcd_0_abs b); intuition | | ]; - unfold Zmod; - generalize (Z_div_mod b (Zpos p) (refl_equal Gt)); - destruct (Zdiv_eucl b (Zpos p)) as (q,r); + unfold Z.modulo; + generalize (Z_div_mod b (Zpos p) (eq_refl Gt)); + destruct (Z.div_eucl b (Zpos p)) as (q,r); intros (H0,H1); - rewrite inj_S in H; simpl Zabs in H; - (assert (H2: Zabs r < Z_of_nat n) by - (rewrite Zabs_eq; auto with zarith)); + rewrite Nat2Z.inj_succ in H; simpl Z.abs in H; + (assert (H2: Z.abs r < Z.of_nat n) by + (rewrite Z.abs_eq; auto with zarith)); assert (IH:=IHn r (Zpos p) H2); clear IHn; simpl in IH |- *; rewrite H0. @@ -124,7 +122,7 @@ Open Scope Z_scope. Proof. induction 1. auto with zarith. - apply Zle_trans with (fibonacci m); auto. + apply Z.le_trans with (fibonacci m); auto. clear. destruct m. simpl; auto with zarith. @@ -144,53 +142,38 @@ Open Scope Z_scope. fibonacci (S (S n)) <= b. Proof. induction n. - simpl; intros. - destruct a; omega. - intros. - destruct a; [simpl in *; omega| | destruct H; discriminate]. - revert H1; revert H0. - set (m:=S n) in *; (assert (m=S n) by auto); clearbody m. - pattern m at 2; rewrite H0. - simpl Zgcdn. - unfold Zmod; generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). - destruct (Zdiv_eucl b (Zpos p)) as (q,r). - intros (H1,H2). - destruct H2. - destruct (Zle_lt_or_eq _ _ H2). - generalize (IHn _ _ (conj H4 H3)). - intros H5 H6 H7. - replace (fibonacci (S (S m))) with (fibonacci (S m) + fibonacci m) by auto. - assert (r = Zpos p * (-q) + b) by (rewrite H1; ring). - destruct H5; auto. - pattern r at 1; rewrite H8. - apply Zis_gcd_sym. - apply Zis_gcd_for_euclid2; auto. - apply Zis_gcd_sym; auto. - split; auto. - rewrite H1. - apply Zplus_le_compat; auto. - apply Zle_trans with (Zpos p * 1); auto. - ring_simplify (Zpos p * 1); auto. - apply Zmult_le_compat_l. - destruct q. - omega. - assert (0 < Zpos p0) by (compute; auto). - omega. - assert (Zpos p * Zneg p0 < 0) by (compute; auto). - omega. - compute; intros; discriminate. - (* r=0 *) - subst r. - simpl; rewrite H0. - intros. - simpl in H4. - simpl in H5. - destruct n. - simpl in H5. - simpl. - omega. - simpl in H5. - elim H5; auto. + intros [|a|a]; intros; simpl; omega. + intros [|a|a] b (Ha,Ha'); [simpl; omega | | easy ]. + remember (S n) as m. + rewrite Heqm at 2. simpl Zgcdn. + unfold Z.modulo; generalize (Z_div_mod b (Zpos a) eq_refl). + destruct (Z.div_eucl b (Zpos a)) as (q,r). + intros (EQ,(Hr,Hr')). + Z.le_elim Hr. + - (* r > 0 *) + replace (fibonacci (S (S m))) with (fibonacci (S m) + fibonacci m) by auto. + intros. + destruct (IHn r (Zpos a) (conj Hr Hr')); auto. + + assert (EQ' : r = Zpos a * (-q) + b) by (rewrite EQ; ring). + rewrite EQ' at 1. + apply Zis_gcd_sym. + apply Zis_gcd_for_euclid2; auto. + apply Zis_gcd_sym; auto. + + split; auto. + rewrite EQ. + apply Z.add_le_mono; auto. + apply Z.le_trans with (Zpos a * 1); auto. + now rewrite Z.mul_1_r. + apply Z.mul_le_mono_nonneg_l; auto with zarith. + change 1 with (Z.succ 0). apply Z.le_succ_l. + destruct q; auto with zarith. + assert (Zpos a * Zneg p < 0) by now compute. omega. + - (* r = 0 *) + clear IHn EQ Hr'; intros _. + subst r; simpl; rewrite Heqm. + destruct n. + + simpl. omega. + + now destruct 1. Qed. (** 3b) We reformulate the previous result in a more positive way. *) @@ -201,18 +184,18 @@ Open Scope Z_scope. Proof. destruct a; [ destruct 1; exfalso; omega | | destruct 1; discriminate]. cut (forall k n b, - k = (S (nat_of_P p) - n)%nat -> + k = (S (Pos.to_nat p) - n)%nat -> 0 < Zpos p < b -> Zpos p < fibonacci (S n) -> Zis_gcd (Zpos p) b (Zgcdn n (Zpos p) b)). destruct 2; eauto. clear n; induction k. intros. - assert (nat_of_P p < n)%nat by omega. + assert (Pos.to_nat p < n)%nat by omega. apply Zgcdn_linear_bound. simpl. generalize (inj_le _ _ H2). - rewrite inj_S. - rewrite <- Zpos_eq_Z_of_nat_o_nat_of_P; auto. + rewrite Nat2Z.inj_succ. + rewrite positive_nat_Z; auto. omega. intros. generalize (Zgcdn_worst_is_fibonacci n (Zpos p) b H0); intros. @@ -235,77 +218,69 @@ Open Scope Z_scope. induction p; [ | | compute; auto ]; simpl Zgcd_bound in *; rewrite plus_comm; simpl plus; - set (n:= (Psize p+Psize p)%nat) in *; simpl; + set (n:= (Pos.size_nat p+Pos.size_nat p)%nat) in *; simpl; assert (n <> O) by (unfold n; destruct p; simpl; auto). destruct n as [ |m]; [elim H; auto| ]. - generalize (fibonacci_pos m); rewrite Zpos_xI; omega. + generalize (fibonacci_pos m); rewrite Pos2Z.inj_xI; omega. destruct n as [ |m]; [elim H; auto| ]. - generalize (fibonacci_pos m); rewrite Zpos_xO; omega. + generalize (fibonacci_pos m); rewrite Pos2Z.inj_xO; omega. Qed. (* 5) the end: we glue everything together and take care of situations not corresponding to [0<a<b]. *) - Lemma Zgcdn_is_gcd : - forall n a b, (Zgcd_bound a <= n)%nat -> - Zis_gcd a b (Zgcdn n a b). + Lemma Zgcd_bound_opp a : Zgcd_bound (-a) = Zgcd_bound a. + Proof. + now destruct a. + Qed. + + Lemma Zgcdn_opp n a b : Zgcdn n (-a) b = Zgcdn n a b. + Proof. + induction n; simpl; auto. + destruct a; simpl; auto. + Qed. + + Lemma Zgcdn_is_gcd_pos n a b : (Zgcd_bound (Zpos a) <= n)%nat -> + Zis_gcd (Zpos a) b (Zgcdn n (Zpos a) b). + Proof. + intros. + generalize (Zgcd_bound_fibonacci (Zpos a)). + simpl Zgcd_bound in *. + remember (Pos.size_nat a+Pos.size_nat a)%nat as m. + assert (1 < m)%nat. + { rewrite Heqm; destruct a; simpl; rewrite 1?plus_comm; + auto with arith. } + destruct m as [ |m]; [inversion H0; auto| ]. + destruct n as [ |n]; [inversion H; auto| ]. + simpl Zgcdn. + unfold Z.modulo. + generalize (Z_div_mod b (Zpos a) (eq_refl Gt)). + destruct (Z.div_eucl b (Zpos a)) as (q,r). + intros (->,(H1,H2)) H3. + apply Zis_gcd_for_euclid2. + Z.le_elim H1. + + apply Zgcdn_ok_before_fibonacci; auto. + apply Z.lt_le_trans with (fibonacci (S m)); + [ omega | apply fibonacci_incr; auto]. + + subst r; simpl. + destruct m as [ |m]; [exfalso; omega| ]. + destruct n as [ |n]; [exfalso; omega| ]. + simpl; apply Zis_gcd_sym; apply Zis_gcd_0. + Qed. + + Lemma Zgcdn_is_gcd n a b : + (Zgcd_bound a <= n)%nat -> Zis_gcd a b (Zgcdn n a b). Proof. - destruct a; intros. - simpl in H. - destruct n; [exfalso; omega | ]. - simpl; generalize (Zis_gcd_0_abs b); intuition. - (*Zpos*) - generalize (Zgcd_bound_fibonacci (Zpos p)). - simpl Zgcd_bound in *. - remember (Psize p+Psize p)%nat as m. - assert (1 < m)%nat. - rewrite Heqm; destruct p; simpl; rewrite 1? plus_comm; - auto with arith. - destruct m as [ |m]; [inversion H0; auto| ]. - destruct n as [ |n]; [inversion H; auto| ]. - simpl Zgcdn. - unfold Zmod. - generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). - destruct (Zdiv_eucl b (Zpos p)) as (q,r). - intros (H2,H3) H4. - rewrite H2. - apply Zis_gcd_for_euclid2. - destruct H3. - destruct (Zle_lt_or_eq _ _ H1). - apply Zgcdn_ok_before_fibonacci; auto. - apply Zlt_le_trans with (fibonacci (S m)); [ omega | apply fibonacci_incr; auto]. - subst r; simpl. - destruct m as [ |m]; [exfalso; omega| ]. - destruct n as [ |n]; [exfalso; omega| ]. - simpl; apply Zis_gcd_sym; apply Zis_gcd_0. - (*Zneg*) - generalize (Zgcd_bound_fibonacci (Zpos p)). - simpl Zgcd_bound in *. - remember (Psize p+Psize p)%nat as m. - assert (1 < m)%nat. - rewrite Heqm; destruct p; simpl; rewrite 1? plus_comm; - auto with arith. - destruct m as [ |m]; [inversion H0; auto| ]. - destruct n as [ |n]; [inversion H; auto| ]. - simpl Zgcdn. - unfold Zmod. - generalize (Z_div_mod b (Zpos p) (refl_equal Gt)). - destruct (Zdiv_eucl b (Zpos p)) as (q,r). - intros (H1,H2) H3. - rewrite H1. - apply Zis_gcd_minus. - apply Zis_gcd_sym. - apply Zis_gcd_for_euclid2. - destruct H2. - destruct (Zle_lt_or_eq _ _ H2). - apply Zgcdn_ok_before_fibonacci; auto. - apply Zlt_le_trans with (fibonacci (S m)); [ omega | apply fibonacci_incr; auto]. - subst r; simpl. - destruct m as [ |m]; [exfalso; omega| ]. - destruct n as [ |n]; [exfalso; omega| ]. - simpl; apply Zis_gcd_sym; apply Zis_gcd_0. + destruct a. + - simpl; intros. + destruct n; [exfalso; omega | ]. + simpl; generalize (Zis_gcd_0_abs b); intuition. + - apply Zgcdn_is_gcd_pos. + - rewrite <- Zgcd_bound_opp, <- Zgcdn_opp. + intros. apply Zis_gcd_minus, Zis_gcd_sym. simpl Z.opp. + now apply Zgcdn_is_gcd_pos. Qed. Lemma Zgcd_is_gcd : diff --git a/theories/ZArith/Zhints.v b/theories/ZArith/Zhints.v index c2348967..8b879fbe 100644 --- a/theories/ZArith/Zhints.v +++ b/theories/ZArith/Zhints.v @@ -1,13 +1,11 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zhints.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - (** This file centralizes the lemmas about [Z], classifying them according to the way they can be used in automatic search *) @@ -45,495 +43,59 @@ Hint Resolve (** Should clearly be declared as hints *) (** Lemmas ending by eq *) - Zsucc_eq_compat (* :(n,m:Z)`n = m`->`(Zs n) = (Zs m)` *) - - (** 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 *) - 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 *) - Zle_0_nat (* :(n:nat)`0 <= (inject_nat n)` *) - Zorder.Zle_0_pos (* :(p:positive)`0 <= (POS p)` *) - Zle_refl (* :(n:Z)`n <= n` *) - Zle_succ (* :(n:Z)`n <= (Zs n)` *) - Zsucc_le_compat (* :(n,m:Z)`m <= n`->`(Zs m) <= (Zs n)` *) - Zle_pred (* :(n:Z)`(Zpred n) <= n` *) - Zle_min_l (* :(n,m:Z)`(Zmin n m) <= n` *) - Zle_min_r (* :(n,m:Z)`(Zmin n m) <= m` *) - Zplus_le_compat_l (* :(n,m,p:Z)`n <= m`->`p+n <= p+m` *) - Zplus_le_compat_r (* :(a,b,c:Z)`a <= b`->`a+c <= b+c` *) - Zabs_pos (* :(x:Z)`0 <= |x|` *) + Zsucc_eq_compat (* n = m -> Z.succ n = Z.succ m *) + + (** Lemmas ending by Z.gt *) + Zsucc_gt_compat (* m > n -> Z.succ m > Z.succ n *) + Zgt_succ (* Z.succ n > n *) + Zorder.Zgt_pos_0 (* Z.pos p > 0 *) + Zplus_gt_compat_l (* n > m -> p+n > p+m *) + Zplus_gt_compat_r (* n > m -> n+p > m+p *) + + (** Lemmas ending by Z.lt *) + Pos2Z.is_pos (* 0 < Z.pos p *) + Z.lt_succ_diag_r (* n < Z.succ n *) + Zsucc_lt_compat (* n < m -> Z.succ n < Z.succ m *) + Z.lt_pred_l (* Z.pred n < n *) + Zplus_lt_compat_l (* n < m -> p+n < p+m *) + Zplus_lt_compat_r (* n < m -> n+p < m+p *) + + (** Lemmas ending by Z.le *) + Nat2Z.is_nonneg (* 0 <= Z.of_nat n *) + Pos2Z.is_nonneg (* 0 <= Z.pos p *) + Z.le_refl (* n <= n *) + Z.le_succ_diag_r (* n <= Z.succ n *) + Zsucc_le_compat (* m <= n -> Z.succ m <= Z.succ n *) + Z.le_pred_l (* Z.pred n <= n *) + Z.le_min_l (* Z.min n m <= n *) + Z.le_min_r (* Z.min n m <= m *) + Zplus_le_compat_l (* n <= m -> p+n <= p+m *) + Zplus_le_compat_r (* a <= b -> a+c <= b+c *) + Z.abs_nonneg (* 0 <= |x| *) (** ** Irreversible simplification lemmas *) (** Probably to be declared as hints, when no other simplification is possible *) (** 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` *) + Z_eq_mult (* y = 0 -> y*x = 0 *) + Zplus_eq_compat (* n = m -> p = q -> n+p = m+q *) - (** 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` *) + (** Lemmas ending by Z.ge *) + Zorder.Zmult_ge_compat_r (* a >= b -> c >= 0 -> a*c >= b*c *) + Zorder.Zmult_ge_compat_l (* 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` *) + a >= c -> b >= d -> c >= 0 -> d >= 0 -> a*b >= c*d *) - (** 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 Z.lt *) + Zorder.Zmult_gt_0_compat (* a > 0 -> b > 0 -> a*b > 0 *) + Z.lt_lt_succ_r (* n < m -> n < Z.succ m *) - (** 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` *) - Zplus_le_0_compat (* :(x,y:Z)`0 <= x`->`0 <= y`->`0 <= x+y` *) - Zle_le_succ (* :(x,y:Z)`x <= y`->`x <= (Zs y)` *) - Zplus_le_compat (* :(n,m,p,q:Z)`n <= m`->`p <= q`->`n+p <= m+q` *) + (** Lemmas ending by Z.le *) + Z.mul_nonneg_nonneg (* 0 <= x -> 0 <= y -> 0 <= x*y *) + Zorder.Zmult_le_compat_r (* a <= b -> 0 <= c -> a*c <= b*c *) + Zorder.Zmult_le_compat_l (* a <= b -> 0 <= c -> c*a <= c*b *) + Z.add_nonneg_nonneg (* 0 <= x -> 0 <= y -> 0 <= x+y *) + Z.le_le_succ_r (* x <= y -> x <= Z.succ y *) + Z.add_le_mono (* n <= m -> p <= q -> n+p <= m+q *) : zarith. - -(**********************************************************************) -(** * Reversible lemmas relating operators *) -(** Probably to be declared as hints but need to define precedences *) - -(** ** Conversion between comparisons/predicates and arithmetic operators *) - -(** 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 *) -(** -<< -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 *) -(** -<< -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 *) -(** -<< -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)` ->> -*) - -(** ** Conversion between nat comparisons and Z comparisons *) - -(** Lemmas ending by eq *) -(** -<< -inj_eq: (x,y:nat)x=y->`(inject_nat x) = (inject_nat y)` ->> -*) - -(** Lemmas ending by Zge *) -(** -<< -inj_ge: (x,y:nat)(ge x y)->`(inject_nat x) >= (inject_nat y)` ->> -*) - -(** Lemmas ending by Zgt *) -(** -<< -inj_gt: (x,y:nat)(gt x y)->`(inject_nat x) > (inject_nat y)` ->> -*) - -(** Lemmas ending by Zlt *) -(** -<< -inj_lt: (x,y:nat)(lt x y)->`(inject_nat x) < (inject_nat y)` ->> -*) - -(** Lemmas ending by Zle *) -(** -<< -inj_le: (x,y:nat)(le x y)->`(inject_nat x) <= (inject_nat y)` ->> -*) - -(** ** Conversion between comparisons *) - -(** 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 *) -(** -<< -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 *) -(** -<< -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 *) -(** -<< -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` -Zgt_S_le: (n,p:Z)`(Zs p) > n`->`n <= p` -Zge_le: (m,n:Z)`m >= n`->`n <= m` -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` ->> -*) - -(** ** Irreversible simplification involving several comparaisons *) -(** useful with clear precedences *) - -(** 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` ->> -*) - -(** ** What is decreasing here ? *) - -(** Lemmas ending by eq *) -(** -<< -Zplus_minus: (n,m,p:Z)`n = m+p`->`p = n-m` ->> -*) - -(** Lemmas ending by Zgt *) -(** -<< -Zgt_pred: (n,p:Z)`p > (Zs n)`->`(Zpred p) > n` ->> -*) - -(** Lemmas ending by Zlt *) -(** -<< -Zlt_pred: (n,p:Z)`(Zs n) < p`->`n < (Zpred p)` ->> -*) - -(**********************************************************************) -(** * Useful Bottom-up lemmas *) - -(** ** Bottom-up simplification: should be used *) - -(** 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 *) -(** -<< -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` ->> -*) - -(** 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` ->> -*) - -(** 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` >> *) - -(** ** Bottom-up irreversible (syntactic) simplification *) - -(** Lemmas ending by Zle *) -(** -<< -Zle_trans_S: (n,m:Z)`(Zs n) <= m`->`n <= m` ->> -*) - -(** ** Other unclearly simplifying lemmas *) - -(** 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 *) - -(* Hints Immediate *) -(** Lemmas ending by eq *) -(** -<< -Zle_antisym: (n,m:Z)`n <= m`->`m <= n`->`n = m` ->> -*) - -(** Lemmas ending by Zge *) -(** -<< -Zge_trans: (n,m,p:Z)`n >= m`->`m >= p`->`n >= p` ->> -*) - -(** 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 *) -(** -<< -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 *) -(** -<< -Zle_trans: (n,m,p:Z)`n <= m`->`m <= p`->`n <= p` ->> -*) - - -(**********************************************************************) -(** * Unclear or too specific lemmas *) -(** Not to be used ? *) - -(** ** Irreversible and too specific (not enough regular) *) - -(** 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 ? *) - -(** Lemmas ending by Zge *) -(** -<< -Zge_mult_simpl: (a,b,c:Z)`c > 0`->`a*c >= b*c`->`a >= b` ->> -*) - -(** 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 *) -(** -<< -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` ->> -*) - -(** ** Reversible but too specific ? *) - -(** 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 *) - -(** 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` -Zmult_n_1: (n:Z)`n*1 = n` -Zminus_plus: (n,m:Z)`n+m-n = m` -Zle_plus_minus: (n,m:Z)`n+(m-n) = m` -Zopp_Zopp: (x:Z)`(-(-x)) = x` -Zero_left: (x:Z)`0+x = x` -Zero_right: (x:Z)`x+0 = x` -Zplus_inverse_r: (x:Z)`x+(-x) = 0` -Zplus_inverse_l: (x:Z)`(-x)+x = 0` -Zopp_intro: (x,y:Z)`(-x) = (-y)`->`x = y` -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) *) - -(** -<< -Zpred_Sn: (m:Z)`m = (Zpred (Zs m))` -Zs_pred: (n:Z)`n = (Zs (Zpred n))` -Zplus_n_O: (n:Z)`n = n+0` -Zmult_n_O: (n:Z)`0 = n*0` -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) *) - -(** -<< -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))` -Zplus_assoc_l: (n,m,p:Z)`n+(m+p) = n+m+p` -Zplus_assoc_r: (n,m,p:Z)`n+m+p = n+(m+p)` -Zplus_permute: (n,m,p:Z)`n+(m+p) = m+(n+p)` -Zplus_Snm_nSm: (n,m:Z)`(Zs n)+m = n+(Zs m)` -Zminus_plus_simpl: (n,m,p:Z)`n-m = p+n-(p+m)` -Zminus_Sn_m: (n,m:Z)`(Zs (n-m)) = (Zs n)-m` -Zmult_plus_distr_l: (n,m,p:Z)`(n+m)*p = n*p+m*p` -Zmult_minus_distr: (n,m,p:Z)`(n-m)*p = n*p-m*p` -Zmult_assoc_r: (n,m,p:Z)`n*m*p = n*(m*p)` -Zmult_assoc_l: (n,m,p:Z)`n*(m*p) = n*m*p` -Zmult_permute: (n,m,p:Z)`n*(m*p) = m*(n*p)` -Zmult_Sm_n: (n,m:Z)`n*m+m = (Zs n)*m` -Zmult_Zplus_distr: (x,y,z:Z)`x*(y+z) = x*y+x*z` -Zmult_plus_distr: (n,m,p:Z)`(n+m)*p = n*p+m*p` -Zopp_Zplus: (x,y:Z)`(-(x+y)) = (-x)+(-y)` -Zplus_sym: (x,y:Z)`x+y = y+x` -Zplus_assoc: (x,y,z:Z)`x+(y+z) = x+y+z` -Zmult_sym: (x,y:Z)`x*y = y*x` -Zmult_assoc: (x,y,z:Z)`x*(y*z) = x*y*z` -Zopp_Zmult: (x,y:Z)`(-x)*y = (-(x*y))` -Zplus_S_n: (x,y:Z)`(Zs x)+y = (Zs (x+y))` -Zopp_one: (x:Z)`(-x) = x*(-1)` -Zopp_Zmult_r: (x,y:Z)`(-(x*y)) = x*(-y)` -Zmult_Zopp_left: (x,y:Z)`(-x)*y = x*(-y)` -Zopp_Zmult_l: (x,y:Z)`(-(x*y)) = (-x)*y` -Zred_factor1: (x:Z)`x+x = x*2` -Zred_factor2: (x,y:Z)`x+x*y = x*(1+y)` -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 *) -(** -<< -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 ? *) -(** -<< -Zred_factor5: (x,y:Z)`x*0+y = y` ->> -*) - diff --git a/theories/ZArith/Zlogarithm.v b/theories/ZArith/Zlogarithm.v index 59e76830..319e2c26 100644 --- a/theories/ZArith/Zlogarithm.v +++ b/theories/ZArith/Zlogarithm.v @@ -1,17 +1,21 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zlogarithm.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - (**********************************************************************) -(** The integer logarithms with base 2. - There are three logarithms, +(** The integer logarithms with base 2. *) + +(** THIS FILE IS DEPRECATED. + Please rather use [Z.log2] (or [Z.log2_up]), which + are defined in [BinIntDef], and whose properties can + be found in [BinInt.Z]. *) + +(* There are three logarithms defined here, depending on the rounding of the real 2-based logarithm: - [Log_inf]: [y = (Log_inf x) iff 2^y <= x < 2^(y+1)] i.e. [Log_inf x] is the biggest integer that is smaller than [Log x] @@ -20,11 +24,8 @@ - [Log_nearest]: [y= (Log_nearest x) iff 2^(y-1/2) < x <= 2^(y+1/2)] i.e. [Log_nearest x] is the integer nearest from [Log x] *) -Require Import ZArith_base. -Require Import Omega. -Require Import Zcomplements. -Require Import Zpower. -Open Local Scope Z_scope. +Require Import ZArith_base Omega Zcomplements Zpower. +Local Open Scope Z_scope. Section Log_pos. (* Log of positive integers *) @@ -32,43 +33,64 @@ Section Log_pos. (* Log of positive integers *) 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 *) + | xH => 0 (* 1 *) + | xO q => Z.succ (log_inf q) (* 2n *) + | xI q => Z.succ (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 *) + | xO n => Z.succ (log_sup n) (* 2n *) + | xI n => Z.succ (Z.succ (log_inf n)) (* 2n+1 *) end. Hint Unfold log_inf log_sup. + Lemma Psize_log_inf : forall p, Zpos (Pos.size p) = Z.succ (log_inf p). + Proof. + induction p; simpl; now rewrite ?Pos2Z.inj_succ, ?IHp. + Qed. + + Lemma Zlog2_log_inf : forall p, Z.log2 (Zpos p) = log_inf p. + Proof. + unfold Z.log2. destruct p; simpl; trivial; apply Psize_log_inf. + Qed. + + Lemma Zlog2_up_log_sup : forall p, Z.log2_up (Zpos p) = log_sup p. + Proof. + induction p; simpl. + - change (Zpos p~1) with (2*(Zpos p)+1). + rewrite Z.log2_up_succ_double, Zlog2_log_inf; try easy. + unfold Z.succ. now rewrite !(Z.add_comm _ 1), Z.add_assoc. + - change (Zpos p~0) with (2*Zpos p). + now rewrite Z.log2_up_double, IHp. + - reflexivity. + Qed. + (** Then we give the specifications of [log_inf] and [log_sup] and prove their validity *) - Hint Resolve Zle_trans: zarith. + Hint Resolve Z.le_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)). + 0 <= log_inf x /\ two_p (log_inf x) <= Zpos x < two_p (Z.succ (log_inf x)). Proof. - simple induction x; intros; simpl in |- *; + simple induction x; intros; simpl; [ elim H; intros Hp HR; clear H; split; [ auto with zarith - | rewrite two_p_S with (x := Zsucc (log_inf p)) by (apply Zle_le_succ; trivial); + | rewrite two_p_S with (x := Z.succ (log_inf p)) by (apply Z.le_le_succ_r; trivial); rewrite two_p_S by trivial; - rewrite two_p_S in HR by trivial; rewrite (BinInt.Zpos_xI p); + rewrite two_p_S in HR by trivial; rewrite (BinInt.Pos2Z.inj_xI p); omega ] | elim H; intros Hp HR; clear H; split; [ auto with zarith - | rewrite two_p_S with (x := Zsucc (log_inf p)) by (apply Zle_le_succ; trivial); + | rewrite two_p_S with (x := Z.succ (log_inf p)) by (apply Z.le_le_succ_r; trivial); rewrite two_p_S by trivial; - rewrite two_p_S in HR by trivial; rewrite (BinInt.Zpos_xO p); + rewrite two_p_S in HR by trivial; rewrite (BinInt.Pos2Z.inj_xO p); omega ] - | unfold two_power_pos in |- *; unfold shift_pos in |- *; simpl in |- *; + | unfold two_power_pos; unfold shift_pos; simpl; omega ]. Qed. @@ -81,7 +103,7 @@ Section Log_pos. (* Log of positive integers *) Lemma log_sup_correct1 : forall p:positive, 0 <= log_sup p. Proof. - simple induction p; intros; simpl in |- *; auto with zarith. + simple induction p; intros; simpl; auto with zarith. Qed. (** For every [p], either [p] is a power of two and [(log_inf p)=(log_sup p)] @@ -90,46 +112,46 @@ Section Log_pos. (* Log of positive integers *) 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). + else log_sup p = Z.succ (log_inf p). Proof. simple induction p; intros; - [ elim H; right; simpl in |- *; + [ elim H; right; simpl; rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite BinInt.Zpos_xI; unfold Zsucc in |- *; omega + rewrite BinInt.Pos2Z.inj_xI; unfold Z.succ; omega | elim H; clear H; intro Hif; - [ left; simpl in |- *; + [ left; simpl; 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 |- *; + | right; simpl; rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite BinInt.Zpos_xO; unfold Zsucc in |- *; + rewrite BinInt.Pos2Z.inj_xO; unfold Z.succ; omega ] | left; auto ]. Qed. Theorem log_sup_correct2 : - forall x:positive, two_p (Zpred (log_sup x)) < Zpos x <= two_p (log_sup x). + forall x:positive, two_p (Z.pred (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 ]. + split; [ apply two_p_pred; apply log_sup_correct1 | apply Z.le_refl ]. intros [E1 E2]; rewrite E2. - rewrite <- (Zpred_succ (log_inf x)). + rewrite (Z.pred_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. + simple induction p; simpl; intros; omega. Qed. - Lemma log_sup_le_Slog_inf : forall p:positive, log_sup p <= Zsucc (log_inf p). + Lemma log_sup_le_Slog_inf : forall p:positive, log_sup p <= Z.succ (log_inf p). Proof. - simple induction p; simpl in |- *; intros; omega. + simple induction p; simpl; intros; omega. Qed. (** Now it's possible to specify and build the [Log] rounded to the nearest *) @@ -139,22 +161,20 @@ Section Log_pos. (* Log of positive integers *) | xH => 0 | xO xH => 1 | xI xH => 2 - | xO y => Zsucc (log_near y) - | xI y => Zsucc (log_near y) + | xO y => Z.succ (log_near y) + | xI y => Z.succ (log_near y) end. Theorem log_near_correct1 : forall p:positive, 0 <= log_near p. Proof. - simple induction p; simpl in |- *; intros; + simple induction p; simpl; 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 ]. + intros; apply Z.le_le_succ_r. + generalize H0; now elim p1. + intros; apply Z.le_le_succ_r. + generalize H0; now elim p1. Qed. Theorem log_near_correct2 : @@ -162,9 +182,9 @@ Section Log_pos. (* Log of positive integers *) Proof. simple induction p. intros p0 [Einf| Esup]. - simpl in |- *. rewrite Einf. + simpl. rewrite Einf. case p0; [ left | left | right ]; reflexivity. - simpl in |- *; rewrite Esup. + simpl; rewrite Esup. elim (log_sup_log_inf p0). generalize (log_inf_le_log_sup p0). generalize (log_sup_le_Slog_inf p0). @@ -172,10 +192,10 @@ Section Log_pos. (* Log of positive integers *) intros; omega. case p0; intros; auto with zarith. intros p0 [Einf| Esup]. - simpl in |- *. + simpl. repeat rewrite Einf. case p0; intros; auto with zarith. - simpl in |- *. + simpl. repeat rewrite Esup. case p0; intros; auto with zarith. auto. @@ -196,20 +216,20 @@ Section divers. 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 ]. + simple induction x; simpl; + [ apply Z.le_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. + 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 ]. + [ try trivial | rewrite Nat2Z.inj_succ; rewrite <- H; reflexivity ]. Qed. - Lemma log_sup_shift_nat : forall n:nat, log_sup (shift_nat n 1) = Z_of_nat n. + 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 ]. + [ try trivial | rewrite Nat2Z.inj_succ; rewrite <- H; reflexivity ]. Qed. (** [Is_power p] means that p is a power of two *) @@ -225,21 +245,21 @@ Section divers. Proof. split; [ elim p; - [ simpl in |- *; tauto - | simpl in |- *; intros; generalize (H H0); intro H1; elim H1; + [ simpl; tauto + | simpl; 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 ]. + | intros; elim H; intros; rewrite H0; elim x; intros; simpl; 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; right; simpl; tauto | intros; elim H; - [ intros; left; simpl in |- *; exact H0 - | intros; right; simpl in |- *; exact H0 ] - | left; simpl in |- *; trivial ]. + [ intros; left; simpl; exact H0 + | intros; right; simpl; exact H0 ] + | left; simpl; trivial ]. Qed. End divers. diff --git a/theories/ZArith/Zmax.v b/theories/ZArith/Zmax.v index cb2fcf26..31880c17 100644 --- a/theories/ZArith/Zmax.v +++ b/theories/ZArith/Zmax.v @@ -1,106 +1,60 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmax.v 14641 2011-11-06 11:59:10Z herbelin $ i*) -(** THIS FILE IS DEPRECATED. Use [Zminmax] instead. *) - -Require Export BinInt Zorder Zminmax. - -Open Local Scope Z_scope. - -(** [Zmax] is now [Zminmax.Zmax]. Code that do things like - [unfold Zmin.Zmin] will have to be adapted, and neither - a [Definition] or a [Notation] here can help much. *) - - -(** * Characterization of maximum on binary integer numbers *) - -Definition Zmax_case := Z.max_case. -Definition Zmax_case_strong := Z.max_case_strong. - -Lemma Zmax_spec : forall x y, - x >= y /\ Zmax x y = x \/ x < y /\ Zmax x y = y. +(** THIS FILE IS DEPRECATED. *) + +Require Export BinInt Zcompare Zorder. + +Local Open Scope Z_scope. + +(** Definition [Z.max] is now [BinInt.Z.max]. *) + +(** Exact compatibility *) + +Notation Zmax_case := Z.max_case (compat "8.3"). +Notation Zmax_case_strong := Z.max_case_strong (compat "8.3"). +Notation Zmax_right := Z.max_r (compat "8.3"). +Notation Zle_max_l := Z.le_max_l (compat "8.3"). +Notation Zle_max_r := Z.le_max_r (compat "8.3"). +Notation Zmax_lub := Z.max_lub (compat "8.3"). +Notation Zmax_lub_lt := Z.max_lub_lt (compat "8.3"). +Notation Zle_max_compat_r := Z.max_le_compat_r (compat "8.3"). +Notation Zle_max_compat_l := Z.max_le_compat_l (compat "8.3"). +Notation Zmax_idempotent := Z.max_id (compat "8.3"). +Notation Zmax_n_n := Z.max_id (compat "8.3"). +Notation Zmax_comm := Z.max_comm (compat "8.3"). +Notation Zmax_assoc := Z.max_assoc (compat "8.3"). +Notation Zmax_irreducible_dec := Z.max_dec (compat "8.3"). +Notation Zmax_le_prime := Z.max_le (compat "8.3"). +Notation Zsucc_max_distr := Z.succ_max_distr (compat "8.3"). +Notation Zmax_SS := Z.succ_max_distr (compat "8.3"). +Notation Zplus_max_distr_l := Z.add_max_distr_l (compat "8.3"). +Notation Zplus_max_distr_r := Z.add_max_distr_r (compat "8.3"). +Notation Zmax_plus := Z.add_max_distr_r (compat "8.3"). +Notation Zmax1 := Z.le_max_l (compat "8.3"). +Notation Zmax2 := Z.le_max_r (compat "8.3"). +Notation Zmax_irreducible_inf := Z.max_dec (compat "8.3"). +Notation Zmax_le_prime_inf := Z.max_le (compat "8.3"). +Notation Zpos_max := Pos2Z.inj_max (compat "8.3"). +Notation Zpos_minus := Pos2Z.inj_sub_max (compat "8.3"). + +(** Slightly different lemmas *) + +Lemma Zmax_spec x y : + x >= y /\ Z.max x y = x \/ x < y /\ Z.max x y = y. Proof. - intros x y. rewrite Zge_iff_le. destruct (Z.max_spec x y); auto. + Z.swap_greater. destruct (Z.max_spec x y); auto. Qed. -Lemma Zmax_left : forall n m, n>=m -> Zmax n m = n. -Proof. intros x y. rewrite Zge_iff_le. apply Zmax_l. Qed. - -Definition Zmax_right : forall n m, n<=m -> Zmax n m = m := Zmax_r. - -(** * Least upper bound properties of max *) - -Definition Zle_max_l : forall n m, n <= Zmax n m := Z.le_max_l. -Definition Zle_max_r : forall n m, m <= Zmax n m := Z.le_max_r. - -Definition Zmax_lub : forall n m p, n <= p -> m <= p -> Zmax n m <= p - := Z.max_lub. - -Definition Zmax_lub_lt : forall n m p:Z, n < p -> m < p -> Zmax n m < p - := Z.max_lub_lt. - - -(** * Compatibility with order *) - -Definition Zle_max_compat_r : forall n m p, n <= m -> Zmax n p <= Zmax m p - := Z.max_le_compat_r. - -Definition Zle_max_compat_l : forall n m p, n <= m -> Zmax p n <= Zmax p m - := Z.max_le_compat_l. - +Lemma Zmax_left n m : n>=m -> Z.max n m = n. +Proof. Z.swap_greater. apply Z.max_l. Qed. -(** * Semi-lattice properties of max *) - -Definition Zmax_idempotent : forall n, Zmax n n = n := Z.max_id. -Definition Zmax_comm : forall n m, Zmax n m = Zmax m n := Z.max_comm. -Definition Zmax_assoc : forall n m p, Zmax n (Zmax m p) = Zmax (Zmax n m) p - := Z.max_assoc. - -(** * Additional properties of max *) - -Lemma Zmax_irreducible_dec : forall n m, {Zmax n m = n} + {Zmax n m = m}. -Proof. exact Z.max_dec. Qed. - -Definition Zmax_le_prime : forall n m p, p <= Zmax n m -> p <= n \/ p <= m - := Z.max_le. - - -(** * Operations preserving max *) - -Definition Zsucc_max_distr : - forall n m:Z, Zsucc (Zmax n m) = Zmax (Zsucc n) (Zsucc m) - := Z.succ_max_distr. - -Definition Zplus_max_distr_l : forall n m p:Z, Zmax (p + n) (p + m) = p + Zmax n m - := Z.plus_max_distr_l. - -Definition Zplus_max_distr_r : forall n m p:Z, Zmax (n + p) (m + p) = Zmax n m + p - := Z.plus_max_distr_r. - -(** * Maximum and Zpos *) - -Definition Zpos_max : forall p q, Zpos (Pmax p q) = Zmax (Zpos p) (Zpos q) - := Z.pos_max. - -Definition Zpos_max_1 : forall p, Zmax 1 (Zpos p) = Zpos p - := Z.pos_max_1. - -(** * Characterization of Pminus in term of Zminus and Zmax *) - -Definition Zpos_minus : - forall p q, Zpos (Pminus p q) = Zmax 1 (Zpos p - Zpos q) - := Zpos_minus. - -(* begin hide *) -(* Compatibility *) -Notation Zmax1 := Zle_max_l (only parsing). -Notation Zmax2 := Zle_max_r (only parsing). -Notation Zmax_irreducible_inf := Zmax_irreducible_dec (only parsing). -Notation Zmax_le_prime_inf := Zmax_le_prime (only parsing). -(* end hide *) +Lemma Zpos_max_1 p : Z.max 1 (Z.pos p) = Z.pos p. +Proof. + now destruct p. +Qed. diff --git a/theories/ZArith/Zmin.v b/theories/ZArith/Zmin.v index 7b9ad469..30b88d8f 100644 --- a/theories/ZArith/Zmin.v +++ b/theories/ZArith/Zmin.v @@ -1,90 +1,57 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmin.v 14641 2011-11-06 11:59:10Z herbelin $ i*) -(** THIS FILE IS DEPRECATED. Use [Zminmax] instead. *) +(** THIS FILE IS DEPRECATED. *) -Require Import BinInt Zorder Zminmax. +Require Import BinInt Zcompare Zorder. -Open Local Scope Z_scope. +Local Open Scope Z_scope. -(** [Zmin] is now [Zminmax.Zmin]. Code that do things like - [unfold Zmin.Zmin] will have to be adapted, and neither - a [Definition] or a [Notation] here can help much. *) +(** Definition [Z.min] is now [BinInt.Z.min]. *) +(** Exact compatibility *) -(** * Characterization of the minimum on binary integer numbers *) +Notation Zmin_case := Z.min_case (compat "8.3"). +Notation Zmin_case_strong := Z.min_case_strong (compat "8.3"). +Notation Zle_min_l := Z.le_min_l (compat "8.3"). +Notation Zle_min_r := Z.le_min_r (compat "8.3"). +Notation Zmin_glb := Z.min_glb (compat "8.3"). +Notation Zmin_glb_lt := Z.min_glb_lt (compat "8.3"). +Notation Zle_min_compat_r := Z.min_le_compat_r (compat "8.3"). +Notation Zle_min_compat_l := Z.min_le_compat_l (compat "8.3"). +Notation Zmin_idempotent := Z.min_id (compat "8.3"). +Notation Zmin_n_n := Z.min_id (compat "8.3"). +Notation Zmin_comm := Z.min_comm (compat "8.3"). +Notation Zmin_assoc := Z.min_assoc (compat "8.3"). +Notation Zmin_irreducible_inf := Z.min_dec (compat "8.3"). +Notation Zsucc_min_distr := Z.succ_min_distr (compat "8.3"). +Notation Zmin_SS := Z.succ_min_distr (compat "8.3"). +Notation Zplus_min_distr_r := Z.add_min_distr_r (compat "8.3"). +Notation Zmin_plus := Z.add_min_distr_r (compat "8.3"). +Notation Zpos_min := Pos2Z.inj_min (compat "8.3"). -Definition Zmin_case := Z.min_case. -Definition Zmin_case_strong := Z.min_case_strong. +(** Slightly different lemmas *) -Lemma Zmin_spec : forall x y, - x <= y /\ Zmin x y = x \/ x > y /\ Zmin x y = y. +Lemma Zmin_spec x y : + x <= y /\ Z.min x y = x \/ x > y /\ Z.min x y = y. Proof. - intros x y. rewrite Zgt_iff_lt, Z.min_comm. destruct (Z.min_spec y x); auto. + Z.swap_greater. rewrite Z.min_comm. destruct (Z.min_spec y x); auto. Qed. -(** * Greatest lower bound properties of min *) - -Definition Zle_min_l : forall n m, Zmin n m <= n := Z.le_min_l. -Definition Zle_min_r : forall n m, Zmin n m <= m := Z.le_min_r. - -Definition Zmin_glb : forall n m p, p <= n -> p <= m -> p <= Zmin n m - := Z.min_glb. -Definition Zmin_glb_lt : forall n m p, p < n -> p < m -> p < Zmin n m - := Z.min_glb_lt. - -(** * Compatibility with order *) - -Definition Zle_min_compat_r : forall n m p, n <= m -> Zmin n p <= Zmin m p - := Z.min_le_compat_r. -Definition Zle_min_compat_l : forall n m p, n <= m -> Zmin p n <= Zmin p m - := Z.min_le_compat_l. - -(** * Semi-lattice properties of min *) - -Definition Zmin_idempotent : forall n, Zmin n n = n := Z.min_id. -Notation Zmin_n_n := Zmin_idempotent (only parsing). -Definition Zmin_comm : forall n m, Zmin n m = Zmin m n := Z.min_comm. -Definition Zmin_assoc : forall n m p, Zmin n (Zmin m p) = Zmin (Zmin n m) p - := Z.min_assoc. - -(** * Additional properties of min *) - -Lemma Zmin_irreducible_inf : forall n m, {Zmin n m = n} + {Zmin n m = m}. -Proof. exact Z.min_dec. Qed. - -Lemma Zmin_irreducible : forall n m, Zmin n m = n \/ Zmin n m = m. -Proof. intros; destruct (Z.min_dec n m); auto. Qed. - -Notation Zmin_or := Zmin_irreducible (only parsing). - -Lemma Zmin_le_prime_inf : forall n m p, Zmin n m <= p -> {n <= p} + {m <= p}. -Proof. intros n m p; apply Zmin_case; auto. Qed. - -(** * Operations preserving min *) - -Definition Zsucc_min_distr : - forall n m, Zsucc (Zmin n m) = Zmin (Zsucc n) (Zsucc m) - := Z.succ_min_distr. - -Notation Zmin_SS := Z.succ_min_distr (only parsing). - -Definition Zplus_min_distr_r : - forall n m p, Zmin (n + p) (m + p) = Zmin n m + p - := Z.plus_min_distr_r. - -Notation Zmin_plus := Z.plus_min_distr_r (only parsing). - -(** * Minimum and Zpos *) - -Definition Zpos_min : forall p q, Zpos (Pmin p q) = Zmin (Zpos p) (Zpos q) - := Z.pos_min. +Lemma Zmin_irreducible n m : Z.min n m = n \/ Z.min n m = m. +Proof. destruct (Z.min_dec n m); auto. Qed. +Notation Zmin_or := Zmin_irreducible (compat "8.3"). +Lemma Zmin_le_prime_inf n m p : Z.min n m <= p -> {n <= p} + {m <= p}. +Proof. apply Z.min_case; auto. Qed. +Lemma Zpos_min_1 p : Z.min 1 (Zpos p) = 1. +Proof. + now destruct p. +Qed. diff --git a/theories/ZArith/Zminmax.v b/theories/ZArith/Zminmax.v index 5aebcc55..ce589e28 100644 --- a/theories/ZArith/Zminmax.v +++ b/theories/ZArith/Zminmax.v @@ -1,202 +1,22 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -Require Import Orders BinInt Zcompare Zorder ZOrderedType - GenericMinMax. - -(** * Maximum and Minimum of two [Z] numbers *) - -Local Open Scope Z_scope. - -Unboxed Definition Zmax (n m:Z) := - match n ?= m with - | Eq | Gt => n - | Lt => m - end. - -Unboxed Definition Zmin (n m:Z) := - match n ?= m with - | Eq | Lt => n - | Gt => m - end. - -(** The functions [Zmax] and [Zmin] implement indeed - a maximum and a minimum *) - -Lemma Zmax_l : forall x y, y<=x -> Zmax x y = x. -Proof. - unfold Zle, Zmax. intros x y. rewrite <- (Zcompare_antisym x y). - destruct (x ?= y); intuition. -Qed. - -Lemma Zmax_r : forall x y, x<=y -> Zmax x y = y. -Proof. - unfold Zle, Zmax. intros x y. generalize (Zcompare_Eq_eq x y). - destruct (x ?= y); intuition. -Qed. - -Lemma Zmin_l : forall x y, x<=y -> Zmin x y = x. -Proof. - unfold Zle, Zmin. intros x y. generalize (Zcompare_Eq_eq x y). - destruct (x ?= y); intuition. -Qed. - -Lemma Zmin_r : forall x y, y<=x -> Zmin x y = y. -Proof. - unfold Zle, Zmin. intros x y. - rewrite <- (Zcompare_antisym x y). generalize (Zcompare_Eq_eq x y). - destruct (x ?= y); intuition. -Qed. - -Module ZHasMinMax <: HasMinMax Z_as_OT. - Definition max := Zmax. - Definition min := Zmin. - Definition max_l := Zmax_l. - Definition max_r := Zmax_r. - Definition min_l := Zmin_l. - Definition min_r := Zmin_r. -End ZHasMinMax. - -Module Z. - -(** We obtain hence all the generic properties of max and min. *) - -Include UsualMinMaxProperties Z_as_OT ZHasMinMax. - -(** * Properties specific to the [Z] domain *) - -(** Compatibilities (consequences of monotonicity) *) - -Lemma plus_max_distr_l : forall n m p, Zmax (p + n) (p + m) = p + Zmax n m. -Proof. - intros. apply max_monotone. - intros x y. apply Zplus_le_compat_l. -Qed. - -Lemma plus_max_distr_r : forall n m p, Zmax (n + p) (m + p) = Zmax n m + p. -Proof. - intros. rewrite (Zplus_comm n p), (Zplus_comm m p), (Zplus_comm _ p). - apply plus_max_distr_l. -Qed. - -Lemma plus_min_distr_l : forall n m p, Zmin (p + n) (p + m) = p + Zmin n m. -Proof. - intros. apply Z.min_monotone. - intros x y. apply Zplus_le_compat_l. -Qed. - -Lemma plus_min_distr_r : forall n m p, Zmin (n + p) (m + p) = Zmin n m + p. -Proof. - intros. rewrite (Zplus_comm n p), (Zplus_comm m p), (Zplus_comm _ p). - apply plus_min_distr_l. -Qed. - -Lemma succ_max_distr : forall n m, Zsucc (Zmax n m) = Zmax (Zsucc n) (Zsucc m). -Proof. - unfold Zsucc. intros. symmetry. apply plus_max_distr_r. -Qed. - -Lemma succ_min_distr : forall n m, Zsucc (Zmin n m) = Zmin (Zsucc n) (Zsucc m). -Proof. - unfold Zsucc. intros. symmetry. apply plus_min_distr_r. -Qed. - -Lemma pred_max_distr : forall n m, Zpred (Zmax n m) = Zmax (Zpred n) (Zpred m). -Proof. - unfold Zpred. intros. symmetry. apply plus_max_distr_r. -Qed. - -Lemma pred_min_distr : forall n m, Zsucc (Zmin n m) = Zmin (Zsucc n) (Zsucc m). -Proof. - unfold Zpred. intros. symmetry. apply plus_min_distr_r. -Qed. - -(** Anti-monotonicity swaps the role of [min] and [max] *) - -Lemma opp_max_distr : forall n m : Z, -(Zmax n m) = Zmin (- n) (- m). -Proof. - intros. symmetry. apply min_max_antimonotone. - intros x x'. red. red. rewrite <- Zcompare_opp; auto. -Qed. - -Lemma opp_min_distr : forall n m : Z, - (Zmin n m) = Zmax (- n) (- m). -Proof. - intros. symmetry. apply max_min_antimonotone. - intros x x'. red. red. rewrite <- Zcompare_opp; auto. -Qed. - -Lemma minus_max_distr_l : forall n m p, Zmax (p - n) (p - m) = p - Zmin n m. -Proof. - unfold Zminus. intros. rewrite opp_min_distr. apply plus_max_distr_l. -Qed. - -Lemma minus_max_distr_r : forall n m p, Zmax (n - p) (m - p) = Zmax n m - p. -Proof. - unfold Zminus. intros. apply plus_max_distr_r. -Qed. - -Lemma minus_min_distr_l : forall n m p, Zmin (p - n) (p - m) = p - Zmax n m. -Proof. - unfold Zminus. intros. rewrite opp_max_distr. apply plus_min_distr_l. -Qed. - -Lemma minus_min_distr_r : forall n m p, Zmin (n - p) (m - p) = Zmin n m - p. -Proof. - unfold Zminus. intros. apply plus_min_distr_r. -Qed. - -(** Compatibility with [Zpos] *) - -Lemma pos_max : forall p q, Zpos (Pmax p q) = Zmax (Zpos p) (Zpos q). -Proof. - intros; unfold Zmax, Pmax; simpl; generalize (Pcompare_Eq_eq p q). - destruct Pcompare; auto. - intro H; rewrite H; auto. -Qed. - -Lemma pos_min : forall p q, Zpos (Pmin p q) = Zmin (Zpos p) (Zpos q). -Proof. - intros; unfold Zmin, Pmin; simpl; generalize (Pcompare_Eq_eq p q). - destruct Pcompare; auto. -Qed. - -Lemma pos_max_1 : forall p, Zmax 1 (Zpos p) = Zpos p. -Proof. - intros; unfold Zmax; simpl; destruct p; simpl; auto. -Qed. - -Lemma pos_min_1 : forall p, Zmin 1 (Zpos p) = 1. -Proof. - intros; unfold Zmax; simpl; destruct p; simpl; auto. -Qed. - -End Z. - - -(** * Characterization of Pminus in term of Zminus and Zmax *) - -Lemma Zpos_minus : forall p q, Zpos (Pminus p q) = Zmax 1 (Zpos p - Zpos q). -Proof. - intros; simpl. destruct (Pcompare p q Eq) as [ ]_eqn:H. - rewrite (Pcompare_Eq_eq _ _ H). - unfold Pminus; rewrite Pminus_mask_diag; reflexivity. - rewrite Pminus_Lt; auto. - symmetry. apply Z.pos_max_1. -Qed. +Require Import Orders BinInt Zcompare Zorder. +(** THIS FILE IS DEPRECATED. *) (*begin hide*) (* Compatibility with names of the old Zminmax file *) -Notation Zmin_max_absorption_r_r := Z.min_max_absorption (only parsing). -Notation Zmax_min_absorption_r_r := Z.max_min_absorption (only parsing). -Notation Zmax_min_distr_r := Z.max_min_distr (only parsing). -Notation Zmin_max_distr_r := Z.min_max_distr (only parsing). -Notation Zmax_min_modular_r := Z.max_min_modular (only parsing). -Notation Zmin_max_modular_r := Z.min_max_modular (only parsing). -Notation max_min_disassoc := Z.max_min_disassoc (only parsing). -(*end hide*)
\ No newline at end of file +Notation Zmin_max_absorption_r_r := Z.min_max_absorption (compat "8.3"). +Notation Zmax_min_absorption_r_r := Z.max_min_absorption (compat "8.3"). +Notation Zmax_min_distr_r := Z.max_min_distr (compat "8.3"). +Notation Zmin_max_distr_r := Z.min_max_distr (compat "8.3"). +Notation Zmax_min_modular_r := Z.max_min_modular (compat "8.3"). +Notation Zmin_max_modular_r := Z.min_max_modular (compat "8.3"). +Notation max_min_disassoc := Z.max_min_disassoc (compat "8.3"). +(*end hide*) diff --git a/theories/ZArith/Zmisc.v b/theories/ZArith/Zmisc.v index a8872bd5..d0ec1916 100644 --- a/theories/ZArith/Zmisc.v +++ b/theories/ZArith/Zmisc.v @@ -1,91 +1,29 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zmisc.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - Require Import Wf_nat. Require Import BinInt. Require Import Zcompare. Require Import Zorder. Require Import Bool. -Open Local Scope Z_scope. +Local Open Scope Z_scope. (**********************************************************************) (** Iterators *) (** [n]th iteration of the function [f] *) -Fixpoint iter_pos (n:positive) (A:Type) (f:A -> A) (x:A) : 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)) - end. - -Definition iter (n:Z) (A:Type) (f:A -> A) (x:A) := - match n with - | Z0 => x - | Zpos p => iter_pos p A f x - | Zneg p => x - end. - -Theorem iter_nat_of_P : - forall (p:positive) (A:Type) (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 ]. -Qed. +Notation iter := @Z.iter (compat "8.3"). Lemma iter_nat_of_Z : forall n A f x, 0 <= n -> - iter n A f x = iter_nat (Zabs_nat n) A f x. + Z.iter n f x = iter_nat (Z.abs_nat n) A f x. +Proof. intros n A f x; case n; auto. -intros p _; unfold iter, Zabs_nat; apply iter_nat_of_P. +intros p _; unfold Z.iter, Z.abs_nat; apply Pos2Nat.inj_iter. intros p abs; case abs; trivial. Qed. - -Theorem iter_pos_plus : - forall (p q:positive) (A:Type) (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. -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:Type) (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 ]. -Qed. - -Theorem iter_pos_invariant : - forall (p:positive) (A:Type) (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. -Qed. diff --git a/theories/ZArith/Znat.v b/theories/ZArith/Znat.v index 9585b6f6..27b7e6a0 100644 --- a/theories/ZArith/Znat.v +++ b/theories/ZArith/Znat.v @@ -1,286 +1,1017 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Znat.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - (** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) Require Export Arith_base. -Require Import BinPos. -Require Import BinInt. -Require Import Zcompare. -Require Import Zorder. -Require Import Decidable. -Require Import Peano_dec. -Require Import Min Max Zmin Zmax. -Require Export Compare_dec. +Require Import BinPos BinInt BinNat Pnat Nnat. + +Local Open Scope Z_scope. + +(** Conversions between integers and natural numbers + + Seven sections: + - chains of conversions (combining two conversions) + - module N2Z : from N to Z + - module Z2N : from Z to N (negative numbers rounded to 0) + - module Zabs2N : from Z to N (via the absolute value) + - module Nat2Z : from nat to Z + - module Z2Nat : from Z to nat (negative numbers rounded to 0) + - module Zabs2Nat : from Z to nat (via the absolute value) +*) + +(** * Chains of conversions *) + +(** When combining successive conversions, we have the following + commutative diagram: +<< + ---> Nat ---- + | ^ | + | | v + Pos ---------> Z + | | ^ + | v | + ----> N ----- +>> +*) + +Lemma nat_N_Z n : Z.of_N (N.of_nat n) = Z.of_nat n. +Proof. + now destruct n. +Qed. -Open Local Scope Z_scope. +Lemma N_nat_Z n : Z.of_nat (N.to_nat n) = Z.of_N n. +Proof. + destruct n; trivial. simpl. + destruct (Pos2Nat.is_succ p) as (m,H). + rewrite H. simpl. f_equal. now apply SuccNat2Pos.inv. +Qed. -Definition neq (x y:nat) := x <> y. +Lemma positive_nat_Z p : Z.of_nat (Pos.to_nat p) = Zpos p. +Proof. + destruct (Pos2Nat.is_succ p) as (n,H). + rewrite H. simpl. f_equal. now apply SuccNat2Pos.inv. +Qed. + +Lemma positive_N_Z p : Z.of_N (Npos p) = Zpos p. +Proof. + reflexivity. +Qed. + +Lemma positive_N_nat p : N.to_nat (Npos p) = Pos.to_nat p. +Proof. + reflexivity. +Qed. + +Lemma positive_nat_N p : N.of_nat (Pos.to_nat p) = Npos p. +Proof. + destruct (Pos2Nat.is_succ p) as (n,H). + rewrite H. simpl. f_equal. now apply SuccNat2Pos.inv. +Qed. + +Lemma Z_N_nat n : N.to_nat (Z.to_N n) = Z.to_nat n. +Proof. + now destruct n. +Qed. + +Lemma Z_nat_N n : N.of_nat (Z.to_nat n) = Z.to_N n. +Proof. + destruct n; simpl; trivial. apply positive_nat_N. +Qed. + +Lemma Zabs_N_nat n : N.to_nat (Z.abs_N n) = Z.abs_nat n. +Proof. + now destruct n. +Qed. + +Lemma Zabs_nat_N n : N.of_nat (Z.abs_nat n) = Z.abs_N n. +Proof. + destruct n; simpl; trivial; apply positive_nat_N. +Qed. + + +(** * Conversions between [Z] and [N] *) + +Module N2Z. + +(** [Z.of_N] is a bijection between [N] and non-negative [Z], + with [Z.to_N] (or [Z.abs_N]) as reciprocal. + See [Z2N.id] below for the dual equation. *) + +Lemma id n : Z.to_N (Z.of_N n) = n. +Proof. + now destruct n. +Qed. + +(** [Z.of_N] is hence injective *) + +Lemma inj n m : Z.of_N n = Z.of_N m -> n = m. +Proof. + destruct n, m; simpl; congruence. +Qed. + +Lemma inj_iff n m : Z.of_N n = Z.of_N m <-> n = m. +Proof. + split. apply inj. intros; now f_equal. +Qed. + +(** [Z.of_N] produce non-negative integers *) + +Lemma is_nonneg n : 0 <= Z.of_N n. +Proof. + now destruct n. +Qed. + +(** [Z.of_N], basic equations *) + +Lemma inj_0 : Z.of_N 0 = 0. +Proof. + reflexivity. +Qed. + +Lemma inj_pos p : Z.of_N (Npos p) = Zpos p. +Proof. + reflexivity. +Qed. + +(** [Z.of_N] and usual operations. *) + +Lemma inj_compare n m : (Z.of_N n ?= Z.of_N m) = (n ?= m)%N. +Proof. + now destruct n, m. +Qed. + +Lemma inj_le n m : (n<=m)%N <-> Z.of_N n <= Z.of_N m. +Proof. + unfold Z.le. now rewrite inj_compare. +Qed. + +Lemma inj_lt n m : (n<m)%N <-> Z.of_N n < Z.of_N m. +Proof. + unfold Z.lt. now rewrite inj_compare. +Qed. + +Lemma inj_ge n m : (n>=m)%N <-> Z.of_N n >= Z.of_N m. +Proof. + unfold Z.ge. now rewrite inj_compare. +Qed. + +Lemma inj_gt n m : (n>m)%N <-> Z.of_N n > Z.of_N m. +Proof. + unfold Z.gt. now rewrite inj_compare. +Qed. + +Lemma inj_abs_N z : Z.of_N (Z.abs_N z) = Z.abs z. +Proof. + now destruct z. +Qed. + +Lemma inj_add n m : Z.of_N (n+m) = Z.of_N n + Z.of_N m. +Proof. + now destruct n, m. +Qed. + +Lemma inj_mul n m : Z.of_N (n*m) = Z.of_N n * Z.of_N m. +Proof. + now destruct n, m. +Qed. + +Lemma inj_sub_max n m : Z.of_N (n-m) = Z.max 0 (Z.of_N n - Z.of_N m). +Proof. + destruct n as [|n], m as [|m]; simpl; trivial. + rewrite Z.pos_sub_spec, Pos.compare_sub_mask. unfold Pos.sub. + now destruct (Pos.sub_mask n m). +Qed. + +Lemma inj_sub n m : (m<=n)%N -> Z.of_N (n-m) = Z.of_N n - Z.of_N m. +Proof. + intros H. rewrite inj_sub_max. + unfold N.le in H. + rewrite N.compare_antisym, <- inj_compare, Z.compare_sub in H. + destruct (Z.of_N n - Z.of_N m); trivial; now destruct H. +Qed. + +Lemma inj_succ n : Z.of_N (N.succ n) = Z.succ (Z.of_N n). +Proof. + destruct n. trivial. simpl. now rewrite Pos.add_1_r. +Qed. + +Lemma inj_pred_max n : Z.of_N (N.pred n) = Z.max 0 (Z.pred (Z.of_N n)). +Proof. + unfold Z.pred. now rewrite N.pred_sub, inj_sub_max. +Qed. + +Lemma inj_pred n : (0<n)%N -> Z.of_N (N.pred n) = Z.pred (Z.of_N n). +Proof. + intros H. unfold Z.pred. rewrite N.pred_sub, inj_sub; trivial. + now apply N.le_succ_l in H. +Qed. + +Lemma inj_min n m : Z.of_N (N.min n m) = Z.min (Z.of_N n) (Z.of_N m). +Proof. + unfold Z.min, N.min. rewrite inj_compare. now case N.compare. +Qed. + +Lemma inj_max n m : Z.of_N (N.max n m) = Z.max (Z.of_N n) (Z.of_N m). +Proof. + unfold Z.max, N.max. rewrite inj_compare. + case N.compare_spec; intros; subst; trivial. +Qed. + +Lemma inj_div n m : Z.of_N (n/m) = Z.of_N n / Z.of_N m. +Proof. + destruct m as [|m]. now destruct n. + apply Z.div_unique_pos with (Z.of_N (n mod (Npos m))). + split. apply is_nonneg. apply inj_lt. now apply N.mod_lt. + rewrite <- inj_mul, <- inj_add. f_equal. now apply N.div_mod. +Qed. + +Lemma inj_mod n m : (m<>0)%N -> Z.of_N (n mod m) = (Z.of_N n) mod (Z.of_N m). +Proof. + intros Hm. + apply Z.mod_unique_pos with (Z.of_N (n / m)). + split. apply is_nonneg. apply inj_lt. now apply N.mod_lt. + rewrite <- inj_mul, <- inj_add. f_equal. now apply N.div_mod. +Qed. + +Lemma inj_quot n m : Z.of_N (n/m) = Z.of_N n ÷ Z.of_N m. +Proof. + destruct m. + - now destruct n. + - rewrite Z.quot_div_nonneg, inj_div; trivial. apply is_nonneg. easy. +Qed. + +Lemma inj_rem n m : Z.of_N (n mod m) = Z.rem (Z.of_N n) (Z.of_N m). +Proof. + destruct m. + - now destruct n. + - rewrite Z.rem_mod_nonneg, inj_mod; trivial. easy. apply is_nonneg. easy. +Qed. + +Lemma inj_div2 n : Z.of_N (N.div2 n) = Z.div2 (Z.of_N n). +Proof. + destruct n as [|p]; trivial. now destruct p. +Qed. + +Lemma inj_quot2 n : Z.of_N (N.div2 n) = Z.quot2 (Z.of_N n). +Proof. + destruct n as [|p]; trivial. now destruct p. +Qed. + +Lemma inj_pow n m : Z.of_N (n^m) = (Z.of_N n)^(Z.of_N m). +Proof. + destruct n, m; trivial. now rewrite Z.pow_0_l. apply Pos2Z.inj_pow. +Qed. + +Lemma inj_testbit a n : + Z.testbit (Z.of_N a) (Z.of_N n) = N.testbit a n. +Proof. apply Z.Private_BootStrap.testbit_of_N. Qed. + +End N2Z. + +Module Z2N. + +(** [Z.to_N] is a bijection between non-negative [Z] and [N], + with [Pos.of_N] as reciprocal. + See [N2Z.id] above for the dual equation. *) + +Lemma id n : 0<=n -> Z.of_N (Z.to_N n) = n. +Proof. + destruct n; (now destruct 1) || trivial. +Qed. + +(** [Z.to_N] is hence injective for non-negative integers. *) + +Lemma inj n m : 0<=n -> 0<=m -> Z.to_N n = Z.to_N m -> n = m. +Proof. + intros. rewrite <- (id n), <- (id m) by trivial. now f_equal. +Qed. + +Lemma inj_iff n m : 0<=n -> 0<=m -> (Z.to_N n = Z.to_N m <-> n = m). +Proof. + intros. split. now apply inj. intros; now subst. +Qed. + +(** [Z.to_N], basic equations *) + +Lemma inj_0 : Z.to_N 0 = 0%N. +Proof. + reflexivity. +Qed. + +Lemma inj_pos n : Z.to_N (Zpos n) = Npos n. +Proof. + reflexivity. +Qed. + +Lemma inj_neg n : Z.to_N (Zneg n) = 0%N. +Proof. + reflexivity. +Qed. + +(** [Z.to_N] and operations *) + +Lemma inj_add n m : 0<=n -> 0<=m -> Z.to_N (n+m) = (Z.to_N n + Z.to_N m)%N. +Proof. + destruct n, m; trivial; (now destruct 1) || (now destruct 2). +Qed. + +Lemma inj_mul n m : 0<=n -> 0<=m -> Z.to_N (n*m) = (Z.to_N n * Z.to_N m)%N. +Proof. + destruct n, m; trivial; (now destruct 1) || (now destruct 2). +Qed. + +Lemma inj_succ n : 0<=n -> Z.to_N (Z.succ n) = N.succ (Z.to_N n). +Proof. + unfold Z.succ. intros. rewrite inj_add by easy. apply N.add_1_r. +Qed. + +Lemma inj_sub n m : 0<=m -> Z.to_N (n - m) = (Z.to_N n - Z.to_N m)%N. +Proof. + destruct n as [|n|n], m as [|m|m]; trivial; try (now destruct 1). + intros _. simpl. + rewrite Z.pos_sub_spec, Pos.compare_sub_mask. unfold Pos.sub. + now destruct (Pos.sub_mask n m). +Qed. + +Lemma inj_pred n : Z.to_N (Z.pred n) = N.pred (Z.to_N n). +Proof. + unfold Z.pred. rewrite <- N.sub_1_r. now apply (inj_sub n 1). +Qed. + +Lemma inj_compare n m : 0<=n -> 0<=m -> + (Z.to_N n ?= Z.to_N m)%N = (n ?= m). +Proof. + intros Hn Hm. now rewrite <- N2Z.inj_compare, !id. +Qed. + +Lemma inj_le n m : 0<=n -> 0<=m -> (n<=m <-> (Z.to_N n <= Z.to_N m)%N). +Proof. + intros Hn Hm. unfold Z.le, N.le. now rewrite inj_compare. +Qed. + +Lemma inj_lt n m : 0<=n -> 0<=m -> (n<m <-> (Z.to_N n < Z.to_N m)%N). +Proof. + intros Hn Hm. unfold Z.lt, N.lt. now rewrite inj_compare. +Qed. + +Lemma inj_min n m : Z.to_N (Z.min n m) = N.min (Z.to_N n) (Z.to_N m). +Proof. + destruct n, m; simpl; trivial; unfold Z.min, N.min; simpl; + now case Pos.compare. +Qed. + +Lemma inj_max n m : Z.to_N (Z.max n m) = N.max (Z.to_N n) (Z.to_N m). +Proof. + destruct n, m; simpl; trivial; unfold Z.max, N.max; simpl. + case Pos.compare_spec; intros; subst; trivial. + now case Pos.compare. +Qed. + +Lemma inj_div n m : 0<=n -> 0<=m -> Z.to_N (n/m) = (Z.to_N n / Z.to_N m)%N. +Proof. + destruct n, m; trivial; intros Hn Hm; + (now destruct Hn) || (now destruct Hm) || clear. + simpl. rewrite <- (N2Z.id (_ / _)). f_equal. now rewrite N2Z.inj_div. +Qed. + +Lemma inj_mod n m : 0<=n -> 0<m -> + Z.to_N (n mod m) = ((Z.to_N n) mod (Z.to_N m))%N. +Proof. + destruct n, m; trivial; intros Hn Hm; + (now destruct Hn) || (now destruct Hm) || clear. + simpl. rewrite <- (N2Z.id (_ mod _)). f_equal. now rewrite N2Z.inj_mod. +Qed. + +Lemma inj_quot n m : 0<=n -> 0<=m -> Z.to_N (n÷m) = (Z.to_N n / Z.to_N m)%N. +Proof. + destruct m. + - now destruct n. + - intros. now rewrite Z.quot_div_nonneg, inj_div. + - now destruct 2. +Qed. + +Lemma inj_rem n m :0<=n -> 0<=m -> + Z.to_N (Z.rem n m) = ((Z.to_N n) mod (Z.to_N m))%N. +Proof. + destruct m. + - now destruct n. + - intros. now rewrite Z.rem_mod_nonneg, inj_mod. + - now destruct 2. +Qed. -(************************************************) -(** Properties of the injection from nat into Z *) +Lemma inj_div2 n : Z.to_N (Z.div2 n) = N.div2 (Z.to_N n). +Proof. + destruct n as [|p|p]; trivial. now destruct p. +Qed. + +Lemma inj_quot2 n : Z.to_N (Z.quot2 n) = N.div2 (Z.to_N n). +Proof. + destruct n as [|p|p]; trivial; now destruct p. +Qed. + +Lemma inj_pow n m : 0<=n -> 0<=m -> Z.to_N (n^m) = ((Z.to_N n)^(Z.to_N m))%N. +Proof. + destruct m. + - trivial. + - intros. now rewrite <- (N2Z.id (_ ^ _)), N2Z.inj_pow, id. + - now destruct 2. +Qed. + +Lemma inj_testbit a n : 0<=n -> + Z.testbit (Z.of_N a) n = N.testbit a (Z.to_N n). +Proof. apply Z.Private_BootStrap.testbit_of_N'. Qed. + +End Z2N. + +Module Zabs2N. + +(** Results about [Z.abs_N], converting absolute values of [Z] integers + to [N]. *) + +Lemma abs_N_spec n : Z.abs_N n = Z.to_N (Z.abs n). +Proof. + now destruct n. +Qed. + +Lemma abs_N_nonneg n : 0<=n -> Z.abs_N n = Z.to_N n. +Proof. + destruct n; trivial; now destruct 1. +Qed. + +Lemma id_abs n : Z.of_N (Z.abs_N n) = Z.abs n. +Proof. + now destruct n. +Qed. + +Lemma id n : Z.abs_N (Z.of_N n) = n. +Proof. + now destruct n. +Qed. + +(** [Z.abs_N], basic equations *) + +Lemma inj_0 : Z.abs_N 0 = 0%N. +Proof. + reflexivity. +Qed. + +Lemma inj_pos p : Z.abs_N (Zpos p) = Npos p. +Proof. + reflexivity. +Qed. + +Lemma inj_neg p : Z.abs_N (Zneg p) = Npos p. +Proof. + reflexivity. +Qed. + +(** [Z.abs_N] and usual operations, with non-negative integers *) + +Lemma inj_opp n : Z.abs_N (-n) = Z.abs_N n. +Proof. + now destruct n. +Qed. + +Lemma inj_succ n : 0<=n -> Z.abs_N (Z.succ n) = N.succ (Z.abs_N n). +Proof. + intros. rewrite !abs_N_nonneg; trivial. now apply Z2N.inj_succ. + now apply Z.le_le_succ_r. +Qed. + +Lemma inj_add n m : 0<=n -> 0<=m -> Z.abs_N (n+m) = (Z.abs_N n + Z.abs_N m)%N. +Proof. + intros. rewrite !abs_N_nonneg; trivial. now apply Z2N.inj_add. + now apply Z.add_nonneg_nonneg. +Qed. + +Lemma inj_mul n m : Z.abs_N (n*m) = (Z.abs_N n * Z.abs_N m)%N. +Proof. + now destruct n, m. +Qed. + +Lemma inj_sub n m : 0<=m<=n -> Z.abs_N (n-m) = (Z.abs_N n - Z.abs_N m)%N. +Proof. + intros (Hn,H). rewrite !abs_N_nonneg; trivial. now apply Z2N.inj_sub. + Z.order. + now apply Z.le_0_sub. +Qed. + +Lemma inj_pred n : 0<n -> Z.abs_N (Z.pred n) = N.pred (Z.abs_N n). +Proof. + intros. rewrite !abs_N_nonneg. now apply Z2N.inj_pred. + Z.order. + apply Z.lt_succ_r. now rewrite Z.succ_pred. +Qed. + +Lemma inj_compare n m : 0<=n -> 0<=m -> + (Z.abs_N n ?= Z.abs_N m)%N = (n ?= m). +Proof. + intros. rewrite !abs_N_nonneg by trivial. now apply Z2N.inj_compare. +Qed. + +Lemma inj_le n m : 0<=n -> 0<=m -> (n<=m <-> (Z.abs_N n <= Z.abs_N m)%N). +Proof. + intros Hn Hm. unfold Z.le, N.le. now rewrite inj_compare. +Qed. + +Lemma inj_lt n m : 0<=n -> 0<=m -> (n<m <-> (Z.abs_N n < Z.abs_N m)%N). +Proof. + intros Hn Hm. unfold Z.lt, N.lt. now rewrite inj_compare. +Qed. + +Lemma inj_min n m : 0<=n -> 0<=m -> + Z.abs_N (Z.min n m) = N.min (Z.abs_N n) (Z.abs_N m). +Proof. + intros. rewrite !abs_N_nonneg; trivial. now apply Z2N.inj_min. + now apply Z.min_glb. +Qed. + +Lemma inj_max n m : 0<=n -> 0<=m -> + Z.abs_N (Z.max n m) = N.max (Z.abs_N n) (Z.abs_N m). +Proof. + intros. rewrite !abs_N_nonneg; trivial. now apply Z2N.inj_max. + transitivity n; trivial. apply Z.le_max_l. +Qed. + +Lemma inj_quot n m : Z.abs_N (n÷m) = ((Z.abs_N n) / (Z.abs_N m))%N. +Proof. + assert (forall p q, Z.abs_N (Zpos p ÷ Zpos q) = (Npos p / Npos q)%N). + intros. rewrite abs_N_nonneg. now apply Z2N.inj_quot. now apply Z.quot_pos. + destruct n, m; trivial; simpl. + - trivial. + - now rewrite <- Pos2Z.opp_pos, Z.quot_opp_r, inj_opp. + - now rewrite <- Pos2Z.opp_pos, Z.quot_opp_l, inj_opp. + - now rewrite <- 2 Pos2Z.opp_pos, Z.quot_opp_opp. +Qed. + +Lemma inj_rem n m : Z.abs_N (Z.rem n m) = ((Z.abs_N n) mod (Z.abs_N m))%N. +Proof. + assert + (forall p q, Z.abs_N (Z.rem (Zpos p) (Zpos q)) = ((Npos p) mod (Npos q))%N). + intros. rewrite abs_N_nonneg. now apply Z2N.inj_rem. now apply Z.rem_nonneg. + destruct n, m; trivial; simpl. + - trivial. + - now rewrite <- Pos2Z.opp_pos, Z.rem_opp_r. + - now rewrite <- Pos2Z.opp_pos, Z.rem_opp_l, inj_opp. + - now rewrite <- 2 Pos2Z.opp_pos, Z.rem_opp_opp, inj_opp. +Qed. + +Lemma inj_pow n m : 0<=m -> Z.abs_N (n^m) = ((Z.abs_N n)^(Z.abs_N m))%N. +Proof. + intros Hm. rewrite abs_N_spec, Z.abs_pow, Z2N.inj_pow, <- abs_N_spec; trivial. + f_equal. symmetry; now apply abs_N_nonneg. apply Z.abs_nonneg. +Qed. + +(** [Z.abs_N] and usual operations, statements with [Z.abs] *) + +Lemma inj_succ_abs n : Z.abs_N (Z.succ (Z.abs n)) = N.succ (Z.abs_N n). +Proof. + destruct n; simpl; trivial; now rewrite Pos.add_1_r. +Qed. + +Lemma inj_add_abs n m : + Z.abs_N (Z.abs n + Z.abs m) = (Z.abs_N n + Z.abs_N m)%N. +Proof. + now destruct n, m. +Qed. + +Lemma inj_mul_abs n m : + Z.abs_N (Z.abs n * Z.abs m) = (Z.abs_N n * Z.abs_N m)%N. +Proof. + now destruct n, m. +Qed. + +End Zabs2N. + + +(** * Conversions between [Z] and [nat] *) + +Module Nat2Z. + +(** [Z.of_nat], basic equations *) + +Lemma inj_0 : Z.of_nat 0 = 0. +Proof. + reflexivity. +Qed. + +Lemma inj_succ n : Z.of_nat (S n) = Z.succ (Z.of_nat n). +Proof. + destruct n. trivial. simpl. apply Pos2Z.inj_succ. +Qed. + +(** [Z.of_N] produce non-negative integers *) + +Lemma is_nonneg n : 0 <= Z.of_nat n. +Proof. + now induction n. +Qed. + +(** [Z.of_nat] is a bijection between [nat] and non-negative [Z], + with [Z.to_nat] (or [Z.abs_nat]) as reciprocal. + See [Z2Nat.id] below for the dual equation. *) + +Lemma id n : Z.to_nat (Z.of_nat n) = n. +Proof. + now rewrite <- nat_N_Z, <- Z_N_nat, N2Z.id, Nat2N.id. +Qed. + +(** [Z.of_nat] is hence injective *) + +Lemma inj n m : Z.of_nat n = Z.of_nat m -> n = m. +Proof. + intros H. now rewrite <- (id n), <- (id m), H. +Qed. + +Lemma inj_iff n m : Z.of_nat n = Z.of_nat m <-> n = m. +Proof. + split. apply inj. intros; now f_equal. +Qed. + +(** [Z.of_nat] and usual operations *) + +Lemma inj_compare n m : (Z.of_nat n ?= Z.of_nat m) = nat_compare n m. +Proof. + now rewrite <-!nat_N_Z, N2Z.inj_compare, <- Nat2N.inj_compare. +Qed. + +Lemma inj_le n m : (n<=m)%nat <-> Z.of_nat n <= Z.of_nat m. +Proof. + unfold Z.le. now rewrite inj_compare, nat_compare_le. +Qed. + +Lemma inj_lt n m : (n<m)%nat <-> Z.of_nat n < Z.of_nat m. +Proof. + unfold Z.lt. now rewrite inj_compare, nat_compare_lt. +Qed. + +Lemma inj_ge n m : (n>=m)%nat <-> Z.of_nat n >= Z.of_nat m. +Proof. + unfold Z.ge. now rewrite inj_compare, nat_compare_ge. +Qed. + +Lemma inj_gt n m : (n>m)%nat <-> Z.of_nat n > Z.of_nat m. +Proof. + unfold Z.gt. now rewrite inj_compare, nat_compare_gt. +Qed. + +Lemma inj_abs_nat z : Z.of_nat (Z.abs_nat z) = Z.abs z. +Proof. + destruct z; simpl; trivial; + destruct (Pos2Nat.is_succ p) as (n,H); rewrite H; simpl; f_equal; + now apply SuccNat2Pos.inv. +Qed. + +Lemma inj_add n m : Z.of_nat (n+m) = Z.of_nat n + Z.of_nat m. +Proof. + now rewrite <- !nat_N_Z, Nat2N.inj_add, N2Z.inj_add. +Qed. + +Lemma inj_mul n m : Z.of_nat (n*m) = Z.of_nat n * Z.of_nat m. +Proof. + now rewrite <- !nat_N_Z, Nat2N.inj_mul, N2Z.inj_mul. +Qed. + +Lemma inj_sub_max n m : Z.of_nat (n-m) = Z.max 0 (Z.of_nat n - Z.of_nat m). +Proof. + now rewrite <- !nat_N_Z, Nat2N.inj_sub, N2Z.inj_sub_max. +Qed. -(** Injection and successor *) +Lemma inj_sub n m : (m<=n)%nat -> Z.of_nat (n-m) = Z.of_nat n - Z.of_nat m. +Proof. + rewrite nat_compare_le, Nat2N.inj_compare. intros. + now rewrite <- !nat_N_Z, Nat2N.inj_sub, N2Z.inj_sub. +Qed. + +Lemma inj_pred_max n : Z.of_nat (pred n) = Z.max 0 (Z.pred (Z.of_nat n)). +Proof. + now rewrite <- !nat_N_Z, Nat2N.inj_pred, N2Z.inj_pred_max. +Qed. + +Lemma inj_pred n : (0<n)%nat -> Z.of_nat (pred n) = Z.pred (Z.of_nat n). +Proof. + rewrite nat_compare_lt, Nat2N.inj_compare. intros. + now rewrite <- !nat_N_Z, Nat2N.inj_pred, N2Z.inj_pred. +Qed. + +Lemma inj_min n m : Z.of_nat (min n m) = Z.min (Z.of_nat n) (Z.of_nat m). +Proof. + now rewrite <- !nat_N_Z, Nat2N.inj_min, N2Z.inj_min. +Qed. -Theorem inj_0 : Z_of_nat 0 = 0%Z. +Lemma inj_max n m : Z.of_nat (max n m) = Z.max (Z.of_nat n) (Z.of_nat m). Proof. - reflexivity. + now rewrite <- !nat_N_Z, Nat2N.inj_max, N2Z.inj_max. Qed. -Theorem inj_S : forall n:nat, Z_of_nat (S n) = Zsucc (Z_of_nat n). +End Nat2Z. + +Module Z2Nat. + +(** [Z.to_nat] is a bijection between non-negative [Z] and [nat], + with [Pos.of_nat] as reciprocal. + See [nat2Z.id] above for the dual equation. *) + +Lemma id n : 0<=n -> Z.of_nat (Z.to_nat n) = 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 ]. + intros. now rewrite <- Z_N_nat, <- nat_N_Z, N2Nat.id, Z2N.id. Qed. -(** Injection and equality. *) +(** [Z.to_nat] is hence injective for non-negative integers. *) -Theorem inj_eq : forall n m:nat, n = m -> Z_of_nat n = Z_of_nat m. +Lemma inj n m : 0<=n -> 0<=m -> Z.to_nat n = Z.to_nat m -> n = m. Proof. - intros x y H; rewrite H; trivial with arith. + intros. rewrite <- (id n), <- (id m) by trivial. now f_equal. Qed. -Theorem inj_neq : forall n m:nat, neq n m -> Zne (Z_of_nat n) (Z_of_nat m). +Lemma inj_iff n m : 0<=n -> 0<=m -> (Z.to_nat n = Z.to_nat m <-> n = 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 ]. + intros. split. now apply inj. intros; now subst. Qed. -Theorem inj_eq_rev : forall n m:nat, Z_of_nat n = Z_of_nat m -> n = m. +(** [Z.to_nat], basic equations *) + +Lemma inj_0 : Z.to_nat 0 = O. Proof. - intros x y H. - destruct (eq_nat_dec x y) as [H'|H']; auto. - exfalso. - exact (inj_neq _ _ H' H). + reflexivity. Qed. -Theorem inj_eq_iff : forall n m:nat, n=m <-> Z_of_nat n = Z_of_nat m. +Lemma inj_pos n : Z.to_nat (Zpos n) = Pos.to_nat n. Proof. - split; [apply inj_eq | apply inj_eq_rev]. + reflexivity. Qed. +Lemma inj_neg n : Z.to_nat (Zneg n) = O. +Proof. + reflexivity. +Qed. -(** Injection and order relations: *) +(** [Z.to_nat] and operations *) -(** One way ... *) +Lemma inj_add n m : 0<=n -> 0<=m -> + Z.to_nat (n+m) = (Z.to_nat n + Z.to_nat m)%nat. +Proof. + intros. now rewrite <- !Z_N_nat, Z2N.inj_add, N2Nat.inj_add. +Qed. -Theorem inj_le : forall n m:nat, (n <= m)%nat -> Z_of_nat n <= Z_of_nat m. +Lemma inj_mul n m : 0<=n -> 0<=m -> + Z.to_nat (n*m) = (Z.to_nat n * Z.to_nat m)%nat. 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. now rewrite <- !Z_N_nat, Z2N.inj_mul, N2Nat.inj_mul. Qed. -Theorem inj_lt : forall n m:nat, (n < m)%nat -> Z_of_nat n < Z_of_nat m. +Lemma inj_succ n : 0<=n -> Z.to_nat (Z.succ n) = S (Z.to_nat n). Proof. - intros x y H; apply Zgt_lt; apply Zle_succ_gt; rewrite <- inj_S; apply inj_le; - exact H. + intros. now rewrite <- !Z_N_nat, Z2N.inj_succ, N2Nat.inj_succ. Qed. -Theorem inj_ge : forall n m:nat, (n >= m)%nat -> Z_of_nat n >= Z_of_nat m. +Lemma inj_sub n m : 0<=m -> Z.to_nat (n - m) = (Z.to_nat n - Z.to_nat m)%nat. Proof. - intros x y H; apply Zle_ge; apply inj_le; apply H. + intros. now rewrite <- !Z_N_nat, Z2N.inj_sub, N2Nat.inj_sub. Qed. -Theorem inj_gt : forall n m:nat, (n > m)%nat -> Z_of_nat n > Z_of_nat m. +Lemma inj_pred n : Z.to_nat (Z.pred n) = pred (Z.to_nat n). Proof. - intros x y H; apply Zlt_gt; apply inj_lt; exact H. + now rewrite <- !Z_N_nat, Z2N.inj_pred, N2Nat.inj_pred. Qed. -(** The other way ... *) +Lemma inj_compare n m : 0<=n -> 0<=m -> + nat_compare (Z.to_nat n) (Z.to_nat m) = (n ?= m). +Proof. + intros Hn Hm. now rewrite <- Nat2Z.inj_compare, !id. +Qed. -Theorem inj_le_rev : forall n m:nat, Z_of_nat n <= Z_of_nat m -> (n <= m)%nat. +Lemma inj_le n m : 0<=n -> 0<=m -> (n<=m <-> (Z.to_nat n <= Z.to_nat m)%nat). Proof. - intros x y H. - destruct (le_lt_dec x y) as [H0|H0]; auto. - exfalso. - assert (H1:=inj_lt _ _ H0). - red in H; red in H1. - rewrite <- Zcompare_antisym in H; rewrite H1 in H; auto. + intros Hn Hm. unfold Z.le. now rewrite nat_compare_le, inj_compare. Qed. -Theorem inj_lt_rev : forall n m:nat, Z_of_nat n < Z_of_nat m -> (n < m)%nat. +Lemma inj_lt n m : 0<=n -> 0<=m -> (n<m <-> (Z.to_nat n < Z.to_nat m)%nat). Proof. - intros x y H. - destruct (le_lt_dec y x) as [H0|H0]; auto. - exfalso. - assert (H1:=inj_le _ _ H0). - red in H; red in H1. - rewrite <- Zcompare_antisym in H1; rewrite H in H1; auto. + intros Hn Hm. unfold Z.lt. now rewrite nat_compare_lt, inj_compare. Qed. -Theorem inj_ge_rev : forall n m:nat, Z_of_nat n >= Z_of_nat m -> (n >= m)%nat. +Lemma inj_min n m : Z.to_nat (Z.min n m) = min (Z.to_nat n) (Z.to_nat m). Proof. - intros x y H. - destruct (le_lt_dec y x) as [H0|H0]; auto. - exfalso. - assert (H1:=inj_gt _ _ H0). - red in H; red in H1. - rewrite <- Zcompare_antisym in H; rewrite H1 in H; auto. + now rewrite <- !Z_N_nat, Z2N.inj_min, N2Nat.inj_min. Qed. -Theorem inj_gt_rev : forall n m:nat, Z_of_nat n > Z_of_nat m -> (n > m)%nat. +Lemma inj_max n m : Z.to_nat (Z.max n m) = max (Z.to_nat n) (Z.to_nat m). Proof. - intros x y H. - destruct (le_lt_dec x y) as [H0|H0]; auto. - exfalso. - assert (H1:=inj_ge _ _ H0). - red in H; red in H1. - rewrite <- Zcompare_antisym in H1; rewrite H in H1; auto. + now rewrite <- !Z_N_nat, Z2N.inj_max, N2Nat.inj_max. Qed. -(* Both ways ... *) +End Z2Nat. -Theorem inj_le_iff : forall n m:nat, (n<=m)%nat <-> Z_of_nat n <= Z_of_nat m. +Module Zabs2Nat. + +(** Results about [Z.abs_nat], converting absolute values of [Z] integers + to [nat]. *) + +Lemma abs_nat_spec n : Z.abs_nat n = Z.to_nat (Z.abs n). Proof. - split; [apply inj_le | apply inj_le_rev]. + now destruct n. Qed. -Theorem inj_lt_iff : forall n m:nat, (n<m)%nat <-> Z_of_nat n < Z_of_nat m. +Lemma abs_nat_nonneg n : 0<=n -> Z.abs_nat n = Z.to_nat n. Proof. - split; [apply inj_lt | apply inj_lt_rev]. + destruct n; trivial; now destruct 1. Qed. -Theorem inj_ge_iff : forall n m:nat, (n>=m)%nat <-> Z_of_nat n >= Z_of_nat m. +Lemma id_abs n : Z.of_nat (Z.abs_nat n) = Z.abs n. Proof. - split; [apply inj_ge | apply inj_ge_rev]. + rewrite <-Zabs_N_nat, N_nat_Z. apply Zabs2N.id_abs. Qed. -Theorem inj_gt_iff : forall n m:nat, (n>m)%nat <-> Z_of_nat n > Z_of_nat m. +Lemma id n : Z.abs_nat (Z.of_nat n) = n. Proof. - split; [apply inj_gt | apply inj_gt_rev]. + now rewrite <-Zabs_N_nat, <-nat_N_Z, Zabs2N.id, Nat2N.id. Qed. -(** Injection and usual operations *) +(** [Z.abs_nat], basic equations *) -Theorem inj_plus : forall n m:nat, Z_of_nat (n + m) = Z_of_nat n + Z_of_nat m. +Lemma inj_0 : Z.abs_nat 0 = 0%nat. 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 ]. + reflexivity. Qed. -Theorem inj_mult : forall n m:nat, Z_of_nat (n * m) = Z_of_nat n * Z_of_nat m. +Lemma inj_pos p : Z.abs_nat (Zpos p) = Pos.to_nat p. 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 ]. + reflexivity. Qed. -Theorem inj_minus1 : - forall n m:nat, (m <= n)%nat -> Z_of_nat (n - m) = Z_of_nat n - Z_of_nat m. +Lemma inj_neg p : Z.abs_nat (Zneg p) = Pos.to_nat p. 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. + reflexivity. Qed. -Theorem inj_minus2 : forall n m:nat, (m > n)%nat -> Z_of_nat (n - m) = 0. +(** [Z.abs_nat] and usual operations, with non-negative integers *) + +Lemma inj_succ n : 0<=n -> Z.abs_nat (Z.succ n) = S (Z.abs_nat n). Proof. - intros x y H; rewrite not_le_minus_0; - [ trivial with arith | apply gt_not_le; assumption ]. + intros. now rewrite <- !Zabs_N_nat, Zabs2N.inj_succ, N2Nat.inj_succ. Qed. -Theorem inj_minus : forall n m:nat, - Z_of_nat (minus n m) = Zmax 0 (Z_of_nat n - Z_of_nat m). +Lemma inj_add n m : 0<=n -> 0<=m -> + Z.abs_nat (n+m) = (Z.abs_nat n + Z.abs_nat m)%nat. Proof. - intros. - rewrite Zmax_comm. - unfold Zmax. - destruct (le_lt_dec m n) as [H|H]. + intros. now rewrite <- !Zabs_N_nat, Zabs2N.inj_add, N2Nat.inj_add. +Qed. + +Lemma inj_mul n m : Z.abs_nat (n*m) = (Z.abs_nat n * Z.abs_nat m)%nat. +Proof. + destruct n, m; simpl; trivial using Pos2Nat.inj_mul. +Qed. + +Lemma inj_sub n m : 0<=m<=n -> + Z.abs_nat (n-m) = (Z.abs_nat n - Z.abs_nat m)%nat. +Proof. + intros. now rewrite <- !Zabs_N_nat, Zabs2N.inj_sub, N2Nat.inj_sub. +Qed. - rewrite (inj_minus1 _ _ H). - assert (H':=Zle_minus_le_0 _ _ (inj_le _ _ H)). - unfold Zle in H'. - rewrite <- Zcompare_antisym in H'. - destruct Zcompare; simpl in *; intuition. +Lemma inj_pred n : 0<n -> Z.abs_nat (Z.pred n) = pred (Z.abs_nat n). +Proof. + intros. now rewrite <- !Zabs_N_nat, Zabs2N.inj_pred, N2Nat.inj_pred. +Qed. - rewrite (inj_minus2 _ _ H). - assert (H':=Zplus_lt_compat_r _ _ (- Z_of_nat m) (inj_lt _ _ H)). - rewrite Zplus_opp_r in H'. - unfold Zminus; rewrite H'; auto. +Lemma inj_compare n m : 0<=n -> 0<=m -> + nat_compare (Z.abs_nat n) (Z.abs_nat m) = (n ?= m). +Proof. + intros. now rewrite <- !Zabs_N_nat, <- N2Nat.inj_compare, Zabs2N.inj_compare. Qed. -Theorem inj_min : forall n m:nat, - Z_of_nat (min n m) = Zmin (Z_of_nat n) (Z_of_nat m). +Lemma inj_le n m : 0<=n -> 0<=m -> (n<=m <-> (Z.abs_nat n <= Z.abs_nat m)%nat). Proof. - induction n; destruct m; try (compute; auto; fail). - simpl min. - do 3 rewrite inj_S. - rewrite <- Zsucc_min_distr; f_equal; auto. + intros Hn Hm. unfold Z.le. now rewrite nat_compare_le, inj_compare. Qed. -Theorem inj_max : forall n m:nat, - Z_of_nat (max n m) = Zmax (Z_of_nat n) (Z_of_nat m). +Lemma inj_lt n m : 0<=n -> 0<=m -> (n<m <-> (Z.abs_nat n < Z.abs_nat m)%nat). Proof. - induction n; destruct m; try (compute; auto; fail). - simpl max. - do 3 rewrite inj_S. - rewrite <- Zsucc_max_distr; f_equal; auto. + intros Hn Hm. unfold Z.lt. now rewrite nat_compare_lt, inj_compare. Qed. -(** Composition of injections **) +Lemma inj_min n m : 0<=n -> 0<=m -> + Z.abs_nat (Z.min n m) = min (Z.abs_nat n) (Z.abs_nat m). +Proof. + intros. now rewrite <- !Zabs_N_nat, Zabs2N.inj_min, N2Nat.inj_min. +Qed. -Theorem Zpos_eq_Z_of_nat_o_nat_of_P : - forall p:positive, Zpos p = Z_of_nat (nat_of_P p). +Lemma inj_max n m : 0<=n -> 0<=m -> + Z.abs_nat (Z.max n m) = max (Z.abs_nat n) (Z.abs_nat m). 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. now rewrite <- !Zabs_N_nat, Zabs2N.inj_max, N2Nat.inj_max. Qed. -(** Misc *) +(** [Z.abs_nat] and usual operations, statements with [Z.abs] *) -Theorem intro_Z : - forall n:nat, exists y : Z, Z_of_nat n = y /\ 0 <= y * 1 + 0. +Lemma inj_succ_abs n : Z.abs_nat (Z.succ (Z.abs n)) = S (Z.abs_nat n). 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 ]. + now rewrite <- !Zabs_N_nat, Zabs2N.inj_succ_abs, N2Nat.inj_succ. Qed. -Lemma Zpos_P_of_succ_nat : forall n:nat, - Zpos (P_of_succ_nat n) = Zsucc (Z_of_nat n). +Lemma inj_add_abs n m : + Z.abs_nat (Z.abs n + Z.abs m) = (Z.abs_nat n + Z.abs_nat m)%nat. +Proof. + now rewrite <- !Zabs_N_nat, Zabs2N.inj_add_abs, N2Nat.inj_add. +Qed. + +Lemma inj_mul_abs n m : + Z.abs_nat (Z.abs n * Z.abs m) = (Z.abs_nat n * Z.abs_nat m)%nat. +Proof. + now rewrite <- !Zabs_N_nat, Zabs2N.inj_mul_abs, N2Nat.inj_mul. +Qed. + +End Zabs2Nat. + + +(** Compatibility *) + +Definition neq (x y:nat) := x <> y. + +Lemma inj_neq n m : neq n m -> Zne (Z.of_nat n) (Z.of_nat m). +Proof. intros H H'. now apply H, Nat2Z.inj. Qed. + +Lemma Zpos_P_of_succ_nat n : Zpos (Pos.of_succ_nat n) = Z.succ (Z.of_nat n). +Proof (Nat2Z.inj_succ n). + +(** For these one, used in omega, a Definition is necessary *) + +Definition inj_eq := (f_equal Z.of_nat). +Definition inj_le n m := proj1 (Nat2Z.inj_le n m). +Definition inj_lt n m := proj1 (Nat2Z.inj_lt n m). +Definition inj_ge n m := proj1 (Nat2Z.inj_ge n m). +Definition inj_gt n m := proj1 (Nat2Z.inj_gt n m). + +(** For the others, a Notation is fine *) + +Notation inj_0 := Nat2Z.inj_0 (compat "8.3"). +Notation inj_S := Nat2Z.inj_succ (compat "8.3"). +Notation inj_compare := Nat2Z.inj_compare (compat "8.3"). +Notation inj_eq_rev := Nat2Z.inj (compat "8.3"). +Notation inj_eq_iff := (fun n m => iff_sym (Nat2Z.inj_iff n m)) (compat "8.3"). +Notation inj_le_iff := Nat2Z.inj_le (compat "8.3"). +Notation inj_lt_iff := Nat2Z.inj_lt (compat "8.3"). +Notation inj_ge_iff := Nat2Z.inj_ge (compat "8.3"). +Notation inj_gt_iff := Nat2Z.inj_gt (compat "8.3"). +Notation inj_le_rev := (fun n m => proj2 (Nat2Z.inj_le n m)) (compat "8.3"). +Notation inj_lt_rev := (fun n m => proj2 (Nat2Z.inj_lt n m)) (compat "8.3"). +Notation inj_ge_rev := (fun n m => proj2 (Nat2Z.inj_ge n m)) (compat "8.3"). +Notation inj_gt_rev := (fun n m => proj2 (Nat2Z.inj_gt n m)) (compat "8.3"). +Notation inj_plus := Nat2Z.inj_add (compat "8.3"). +Notation inj_mult := Nat2Z.inj_mul (compat "8.3"). +Notation inj_minus1 := Nat2Z.inj_sub (compat "8.3"). +Notation inj_minus := Nat2Z.inj_sub_max (compat "8.3"). +Notation inj_min := Nat2Z.inj_min (compat "8.3"). +Notation inj_max := Nat2Z.inj_max (compat "8.3"). + +Notation Z_of_nat_of_P := positive_nat_Z (compat "8.3"). +Notation Zpos_eq_Z_of_nat_o_nat_of_P := + (fun p => eq_sym (positive_nat_Z p)) (compat "8.3"). + +Notation Z_of_nat_of_N := N_nat_Z (compat "8.3"). +Notation Z_of_N_of_nat := nat_N_Z (compat "8.3"). + +Notation Z_of_N_eq := (f_equal Z.of_N) (compat "8.3"). +Notation Z_of_N_eq_rev := N2Z.inj (compat "8.3"). +Notation Z_of_N_eq_iff := (fun n m => iff_sym (N2Z.inj_iff n m)) (compat "8.3"). +Notation Z_of_N_compare := N2Z.inj_compare (compat "8.3"). +Notation Z_of_N_le_iff := N2Z.inj_le (compat "8.3"). +Notation Z_of_N_lt_iff := N2Z.inj_lt (compat "8.3"). +Notation Z_of_N_ge_iff := N2Z.inj_ge (compat "8.3"). +Notation Z_of_N_gt_iff := N2Z.inj_gt (compat "8.3"). +Notation Z_of_N_le := (fun n m => proj1 (N2Z.inj_le n m)) (compat "8.3"). +Notation Z_of_N_lt := (fun n m => proj1 (N2Z.inj_lt n m)) (compat "8.3"). +Notation Z_of_N_ge := (fun n m => proj1 (N2Z.inj_ge n m)) (compat "8.3"). +Notation Z_of_N_gt := (fun n m => proj1 (N2Z.inj_gt n m)) (compat "8.3"). +Notation Z_of_N_le_rev := (fun n m => proj2 (N2Z.inj_le n m)) (compat "8.3"). +Notation Z_of_N_lt_rev := (fun n m => proj2 (N2Z.inj_lt n m)) (compat "8.3"). +Notation Z_of_N_ge_rev := (fun n m => proj2 (N2Z.inj_ge n m)) (compat "8.3"). +Notation Z_of_N_gt_rev := (fun n m => proj2 (N2Z.inj_gt n m)) (compat "8.3"). +Notation Z_of_N_pos := N2Z.inj_pos (compat "8.3"). +Notation Z_of_N_abs := N2Z.inj_abs_N (compat "8.3"). +Notation Z_of_N_le_0 := N2Z.is_nonneg (compat "8.3"). +Notation Z_of_N_plus := N2Z.inj_add (compat "8.3"). +Notation Z_of_N_mult := N2Z.inj_mul (compat "8.3"). +Notation Z_of_N_minus := N2Z.inj_sub_max (compat "8.3"). +Notation Z_of_N_succ := N2Z.inj_succ (compat "8.3"). +Notation Z_of_N_min := N2Z.inj_min (compat "8.3"). +Notation Z_of_N_max := N2Z.inj_max (compat "8.3"). +Notation Zabs_of_N := Zabs2N.id (compat "8.3"). +Notation Zabs_N_succ_abs := Zabs2N.inj_succ_abs (compat "8.3"). +Notation Zabs_N_succ := Zabs2N.inj_succ (compat "8.3"). +Notation Zabs_N_plus_abs := Zabs2N.inj_add_abs (compat "8.3"). +Notation Zabs_N_plus := Zabs2N.inj_add (compat "8.3"). +Notation Zabs_N_mult_abs := Zabs2N.inj_mul_abs (compat "8.3"). +Notation Zabs_N_mult := Zabs2N.inj_mul (compat "8.3"). + +Theorem inj_minus2 : forall n m:nat, (m > n)%nat -> Z.of_nat (n - m) = 0. Proof. - intros. - unfold Z_of_nat. - destruct n. - simpl; auto. - simpl (P_of_succ_nat (S n)). - apply Zpos_succ_morphism. + intros. rewrite not_le_minus_0; auto with arith. Qed. diff --git a/theories/ZArith/Znumtheory.v b/theories/ZArith/Znumtheory.v index 26ff4251..c1e01451 100644 --- a/theories/ZArith/Znumtheory.v +++ b/theories/ZArith/Znumtheory.v @@ -1,349 +1,217 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Znumtheory.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - Require Import ZArith_base. Require Import ZArithRing. Require Import Zcomplements. Require Import Zdiv. Require Import Wf_nat. -Open Local Scope Z_scope. + +(** For compatibility reasons, this Open Scope isn't local as it should *) + +Open Scope Z_scope. (** This file contains some notions of number theory upon Z numbers: - - a divisibility predicate [Zdivide] + - a divisibility predicate [Z.divide] - a gcd predicate [gcd] - Euclid algorithm [euclid] - a relatively prime predicate [rel_prime] - a prime predicate [prime] - - an efficient [Zgcd] function + - properties of the efficient [Z.gcd] function *) -(** * Divisibility *) +Notation Zgcd := Z.gcd (compat "8.3"). +Notation Zggcd := Z.ggcd (compat "8.3"). +Notation Zggcd_gcd := Z.ggcd_gcd (compat "8.3"). +Notation Zggcd_correct_divisors := Z.ggcd_correct_divisors (compat "8.3"). +Notation Zgcd_divide_l := Z.gcd_divide_l (compat "8.3"). +Notation Zgcd_divide_r := Z.gcd_divide_r (compat "8.3"). +Notation Zgcd_greatest := Z.gcd_greatest (compat "8.3"). +Notation Zgcd_nonneg := Z.gcd_nonneg (compat "8.3"). +Notation Zggcd_opp := Z.ggcd_opp (compat "8.3"). -Inductive Zdivide (a b:Z) : Prop := - Zdivide_intro : forall q:Z, b = q * a -> Zdivide a b. +(** The former specialized inductive predicate [Z.divide] is now + a generic existential predicate. *) -(** Syntax for divisibility *) +Notation Zdivide := Z.divide (compat "8.3"). -Notation "( a | b )" := (Zdivide a b) (at level 0) : Z_scope. +(** Its former constructor is now a pseudo-constructor. *) -(** Results concerning divisibility*) +Definition Zdivide_intro a b q (H:b=q*a) : Z.divide a b := ex_intro _ q H. -Lemma Zdivide_refl : forall a:Z, (a | a). -Proof. - intros; apply Zdivide_intro with 1; ring. -Qed. - -Lemma Zone_divide : forall a:Z, (1 | a). -Proof. - intros; apply Zdivide_intro with a; ring. -Qed. - -Lemma Zdivide_0 : forall a:Z, (a | 0). -Proof. - 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. -Qed. +(** Results concerning divisibility*) -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. -Qed. +Notation Zdivide_refl := Z.divide_refl (compat "8.3"). +Notation Zone_divide := Z.divide_1_l (compat "8.3"). +Notation Zdivide_0 := Z.divide_0_r (compat "8.3"). +Notation Zmult_divide_compat_l := Z.mul_divide_mono_l (compat "8.3"). +Notation Zmult_divide_compat_r := Z.mul_divide_mono_r (compat "8.3"). +Notation Zdivide_plus_r := Z.divide_add_r (compat "8.3"). +Notation Zdivide_minus_l := Z.divide_sub_r (compat "8.3"). +Notation Zdivide_mult_l := Z.divide_mul_l (compat "8.3"). +Notation Zdivide_mult_r := Z.divide_mul_r (compat "8.3"). +Notation Zdivide_factor_r := Z.divide_factor_l (compat "8.3"). +Notation Zdivide_factor_l := Z.divide_factor_r (compat "8.3"). -Hint Resolve Zmult_divide_compat_l Zmult_divide_compat_r: zarith. +Lemma Zdivide_opp_r a b : (a | b) -> (a | - b). +Proof. apply Z.divide_opp_r. Qed. -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. -Qed. +Lemma Zdivide_opp_r_rev a b : (a | - b) -> (a | b). +Proof. apply Z.divide_opp_r. 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. -Qed. +Lemma Zdivide_opp_l a b : (a | b) -> (- a | b). +Proof. apply Z.divide_opp_l. 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. -Qed. +Lemma Zdivide_opp_l_rev a b : (- a | b) -> (a | b). +Proof. apply Z.divide_opp_l. 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. -Qed. +Theorem Zdivide_Zabs_l a b : (Z.abs a | b) -> (a | b). +Proof. apply Z.divide_abs_l. 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. -Qed. +Theorem Zdivide_Zabs_inv_l a b : (a | b) -> (Z.abs a | b). +Proof. apply Z.divide_abs_l. 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. -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. -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. -Qed. - -Lemma Zdivide_factor_r : forall a b:Z, (a | a * b). -Proof. - 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. -Qed. - -Hint Resolve Zdivide_plus_r Zdivide_opp_r Zdivide_opp_r_rev Zdivide_opp_l - Zdivide_opp_l_rev Zdivide_minus_l Zdivide_mult_l Zdivide_mult_r - Zdivide_factor_r Zdivide_factor_l: zarith. +Hint Resolve Z.divide_refl Z.divide_1_l Z.divide_0_r: zarith. +Hint Resolve Z.mul_divide_mono_l Z.mul_divide_mono_r: zarith. +Hint Resolve Z.divide_add_r Zdivide_opp_r Zdivide_opp_r_rev Zdivide_opp_l + Zdivide_opp_l_rev Z.divide_sub_r Z.divide_mul_l Z.divide_mul_r + Z.divide_factor_l Z.divide_factor_r: zarith. (** Auxiliary result. *) -Lemma Zmult_one : forall x y:Z, x >= 0 -> x * y = 1 -> x = 1. +Lemma Zmult_one x y : x >= 0 -> x * y = 1 -> x = 1. Proof. - 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)). - apply Zge_le; assumption. - apply Zorder.Zlt_neg_0. + Z.swap_greater. apply Z.eq_mul_1_nonneg. Qed. (** Only [1] and [-1] divide [1]. *) -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. -Qed. +Notation Zdivide_1 := Z.divide_1_r (compat "8.3"). (** If [a] divides [b] and [b] divides [a] then [a] is [b] or [-b]. *) -Lemma Zdivide_antisym : forall a b:Z, (a | b) -> (b | a) -> a = b \/ a = - b. -Proof. - simple induction 1; intros. - inversion H1. - rewrite H0 in H2; clear H H1. - case (Z_zerop a); intro. - left; rewrite H0; rewrite e; ring. - assert (Hqq0 : q0 * q = 1). - apply Zmult_reg_l with a. - assumption. - ring_simplify. - pattern a at 2 in |- *; rewrite H2; ring. - assert (q | 1). - rewrite <- Hqq0; auto with zarith. - elim (Zdivide_1 q H); intros. - rewrite H1 in H0; left; omega. - rewrite H1 in H0; right; omega. -Qed. - -Theorem Zdivide_trans: forall a b c, (a | b) -> (b | c) -> (a | c). -Proof. - intros a b c [d H1] [e H2]; exists (d * e); auto with zarith. - rewrite H2; rewrite H1; ring. -Qed. +Notation Zdivide_antisym := Z.divide_antisym (compat "8.3"). +Notation Zdivide_trans := Z.divide_trans (compat "8.3"). (** If [a] divides [b] and [b<>0] then [|a| <= |b|]. *) -Lemma Zdivide_bounds : forall a b:Z, (a | b) -> b <> 0 -> Zabs a <= Zabs b. +Lemma Zdivide_bounds a b : (a | b) -> b <> 0 -> Z.abs a <= Z.abs 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. + intros H Hb. + rewrite <- Z.divide_abs_l, <- Z.divide_abs_r in H. + apply Z.abs_pos in Hb. + now apply Z.divide_pos_le. Qed. -(** [Zdivide] can be expressed using [Zmod]. *) +(** [Z.divide] can be expressed using [Z.modulo]. *) Lemma Zmod_divide : forall a b, b<>0 -> a mod b = 0 -> (b | a). Proof. - intros a b NZ EQ. - apply Zdivide_intro with (a/b). - rewrite (Z_div_mod_eq_full a b NZ) at 1. - rewrite EQ; ring. + apply Z.mod_divide. Qed. Lemma Zdivide_mod : forall a b, (b | a) -> a mod b = 0. Proof. - intros a b (c,->); apply Z_mod_mult. -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 (c,->); apply Z_mod_mult. Qed. -Theorem Zdivide_Zdiv_eq: forall a b : Z, - 0 < a -> (a | b) -> b = a * (b / a). -Proof. - intros a b Hb Hc. - pattern b at 1; rewrite (Z_div_mod_eq b a); auto with zarith. - rewrite (Zdivide_mod b a); auto with zarith. -Qed. +(** [Z.divide] is hence decidable *) -Theorem Zdivide_Zdiv_eq_2: forall a b c : Z, - 0 < a -> (a | b) -> (c * b)/a = c * (b / a). +Lemma Zdivide_dec a b : {(a | b)} + {~ (a | b)}. Proof. - intros a b c H1 H2. - inversion H2 as [z Hz]. - rewrite Hz; rewrite Zmult_assoc. - repeat rewrite Z_div_mult; auto with zarith. -Qed. + destruct (Z.eq_dec a 0) as [Ha|Ha]. + destruct (Z.eq_dec b 0) as [Hb|Hb]. + left; subst; apply Z.divide_0_r. + right. subst. contradict Hb. now apply Z.divide_0_l. + destruct (Z.eq_dec (b mod a) 0). + left. now apply Z.mod_divide. + right. now rewrite <- Z.mod_divide. +Defined. -Theorem Zdivide_Zabs_l: forall a b, (Zabs a | b) -> (a | b). +Theorem Zdivide_Zdiv_eq a b : 0 < a -> (a | b) -> b = a * (b / a). Proof. - intros a b [x H]; subst b. - pattern (Zabs a); apply Zabs_intro. - exists (- x); ring. - exists x; ring. + intros Ha H. + rewrite (Z.div_mod b a) at 1; auto with zarith. + rewrite Zdivide_mod; auto with zarith. Qed. -Theorem Zdivide_Zabs_inv_l: forall a b, (a | b) -> (Zabs a | b). +Theorem Zdivide_Zdiv_eq_2 a b c : + 0 < a -> (a | b) -> (c * b) / a = c * (b / a). Proof. - intros a b [x H]; subst b. - pattern (Zabs a); apply Zabs_intro. - exists (- x); ring. - exists x; ring. + intros. apply Z.divide_div_mul_exact; auto with zarith. Qed. Theorem Zdivide_le: forall a b : Z, 0 <= a -> 0 < b -> (a | b) -> a <= b. Proof. - intros a b H1 H2 [q H3]; subst b. - case (Zle_lt_or_eq 0 a); auto with zarith; intros H3. - case (Zle_lt_or_eq 0 q); auto with zarith. - apply (Zmult_le_0_reg_r a); auto with zarith. - intros H4; apply Zle_trans with (1 * a); auto with zarith. - intros H4; subst q; omega. + intros. now apply Z.divide_pos_le. Qed. -Theorem Zdivide_Zdiv_lt_pos: forall a b : Z, +Theorem Zdivide_Zdiv_lt_pos a b : 1 < a -> 0 < b -> (a | b) -> 0 < b / a < b . Proof. - intros a b H1 H2 H3; split. - apply Zmult_lt_reg_r with a; auto with zarith. - rewrite (Zmult_comm (Zdiv b a)); rewrite <- Zdivide_Zdiv_eq; auto with zarith. - apply Zmult_lt_reg_r with a; auto with zarith. - repeat rewrite (fun x => Zmult_comm x a); auto with zarith. + intros H1 H2 H3; split. + apply Z.mul_pos_cancel_l with a; auto with zarith. rewrite <- Zdivide_Zdiv_eq; auto with zarith. - pattern b at 1; replace b with (1 * b); auto with zarith. - apply Zmult_lt_compat_r; auto with zarith. + now apply Z.div_lt. Qed. -Lemma Zmod_div_mod: forall n m a, 0 < n -> 0 < m -> - (n | m) -> a mod n = (a mod m) mod n. +Lemma Zmod_div_mod n m a: + 0 < n -> 0 < m -> (n | m) -> a mod n = (a mod m) mod n. Proof. - intros n m a H1 H2 H3. - pattern a at 1; rewrite (Z_div_mod_eq a m); auto with zarith. - case H3; intros q Hq; pattern m at 1; rewrite Hq. - rewrite (Zmult_comm q). - rewrite Zplus_mod; auto with zarith. - rewrite <- Zmult_assoc; rewrite Zmult_mod; auto with zarith. - rewrite Z_mod_same; try rewrite Zmult_0_l; auto with zarith. - rewrite (Zmod_small 0); auto with zarith. - rewrite Zplus_0_l; rewrite Zmod_mod; auto with zarith. + intros H1 H2 (p,Hp). + rewrite (Z.div_mod a m) at 1; auto with zarith. + rewrite Hp at 1. + rewrite Z.mul_shuffle0, Z.add_comm, Z.mod_add; auto with zarith. Qed. -Lemma Zmod_divide_minus: forall a b c : Z, 0 < b -> - a mod b = c -> (b | a - c). +Lemma Zmod_divide_minus a b c: + 0 < b -> a mod b = c -> (b | a - c). Proof. - intros a b c H H1; apply Zmod_divide; auto with zarith. + intros H H1. apply Z.mod_divide; auto with zarith. rewrite Zminus_mod; auto with zarith. - rewrite H1; pattern c at 1; rewrite <- (Zmod_small c b); auto with zarith. - rewrite Zminus_diag; apply Zmod_small; auto with zarith. - subst; apply Z_mod_lt; auto with zarith. + rewrite H1. rewrite <- (Z.mod_small c b) at 1. + rewrite Z.sub_diag, Z.mod_0_l; auto with zarith. + subst. now apply Z.mod_pos_bound. Qed. -Lemma Zdivide_mod_minus: forall a b c : Z, 0 <= c < b -> - (b | a - c) -> a mod b = c. +Lemma Zdivide_mod_minus a b c: + 0 <= c < b -> (b | a - c) -> a mod b = c. Proof. - intros a b c (H1, H2) H3; assert (0 < b); try apply Zle_lt_trans with c; auto. + intros (H1, H2) H3. + assert (0 < b) by Z.order. replace a with ((a - c) + c); auto with zarith. - rewrite Zplus_mod; auto with zarith. - rewrite (Zdivide_mod (a -c) b); try rewrite Zplus_0_l; auto with zarith. - rewrite Zmod_mod; try apply Zmod_small; auto with zarith. + rewrite Z.add_mod; auto with zarith. + rewrite (Zdivide_mod (a-c) b); try rewrite Z.add_0_l; auto with zarith. + rewrite Z.mod_mod; try apply Zmod_small; auto with zarith. Qed. (** * Greatest common divisor (gcd). *) -(** There is no unicity of the gcd; hence we define the predicate [gcd a b d] - expressing that [d] is a gcd of [a] and [b]. - (We show later that the [gcd] is actually unique if we discard its sign.) *) +(** There is no unicity of the gcd; hence we define the predicate + [Zis_gcd a b g] expressing that [g] is a gcd of [a] and [b]. + (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. +Inductive Zis_gcd (a b g:Z) : Prop := + Zis_gcd_intro : + (g | a) -> + (g | b) -> + (forall x, (x | a) -> (x | b) -> (x | g)) -> + Zis_gcd a b g. (** Trivial properties of [gcd] *) -Lemma Zis_gcd_sym : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a d. +Lemma Zis_gcd_sym : forall a b d, Zis_gcd a b d -> Zis_gcd b a d. Proof. - simple induction 1; constructor; intuition. + induction 1; constructor; intuition. Qed. -Lemma Zis_gcd_0 : forall a:Z, Zis_gcd a 0 a. +Lemma Zis_gcd_0 : forall a, Zis_gcd a 0 a. Proof. constructor; auto with zarith. Qed. @@ -358,19 +226,18 @@ Proof. constructor; auto with zarith. Qed. -Lemma Zis_gcd_minus : forall a b d:Z, Zis_gcd a (- b) d -> Zis_gcd b a d. +Lemma Zis_gcd_minus : forall a b d, Zis_gcd a (- b) d -> Zis_gcd b a d. Proof. - simple induction 1; constructor; intuition. + induction 1; constructor; intuition. Qed. -Lemma Zis_gcd_opp : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a (- d). +Lemma Zis_gcd_opp : forall a b d, Zis_gcd a b d -> Zis_gcd b a (- d). Proof. - simple induction 1; constructor; intuition. + induction 1; constructor; intuition. Qed. -Lemma Zis_gcd_0_abs : forall a:Z, Zis_gcd 0 a (Zabs a). +Lemma Zis_gcd_0_abs a : Zis_gcd 0 a (Z.abs 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. @@ -381,12 +248,10 @@ Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. Theorem Zis_gcd_unique: forall a b c d : Z, Zis_gcd a b c -> Zis_gcd a b d -> c = d \/ c = (- d). Proof. -intros a b c d H1 H2. -inversion_clear H1 as [Hc1 Hc2 Hc3]. -inversion_clear H2 as [Hd1 Hd2 Hd3]. -assert (H3: Zdivide c d); auto. -assert (H4: Zdivide d c); auto. -apply Zdivide_antisym; auto. +intros a b c d [Hc1 Hc2 Hc3] [Hd1 Hd2 Hd3]. +assert (c|d) by auto. +assert (d|c) by auto. +apply Z.divide_antisym; auto. Qed. @@ -429,7 +294,7 @@ Section extended_euclid_algorithm. (** 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)]. + [u1*a+u2*b=u3] and [v1*a+v2*b=v3] and [gcd(u3,v3)=gcd(a,b)]. *) Lemma euclid_rec : @@ -440,7 +305,7 @@ Section extended_euclid_algorithm. 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 |- *. + intros v3 Hv3; generalize Hv3; pattern v3. apply Zlt_0_rec. clear v3 Hv3; intros. elim (Z_zerop x); intro. @@ -454,8 +319,8 @@ Section extended_euclid_algorithm. 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. + unfold q. + intro eq; pattern u3 at 2; 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 @@ -492,7 +357,7 @@ Proof. 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). + exact (Z.divide_antisym d d' Hdd' Hd'd). Qed. (** * Bezout's coefficients *) @@ -519,14 +384,15 @@ Qed. 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. + intros a b c d; simple induction 1. constructor; auto with zarith. + intros x Ha Hb. + elim (Zis_gcd_bezout a b d H). intros u v Huv. + elim Ha; intros a' Ha'. + elim Hb; intros b' Hb'. + apply Zdivide_intro with (u * a' + v * b'). + rewrite <- Huv. replace (c * (u * a + v * b)) with (u * (c * a) + v * (c * b)). - rewrite H6; rewrite H7; ring. + rewrite Ha'; rewrite Hb'; ring. ring. Qed. @@ -584,21 +450,21 @@ Lemma rel_prime_cross_prod : 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). + elim (Z.divide_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. + rewrite Z.mul_comm in H3. + apply Z.mul_reg_l with d; auto with zarith. intros; omega. apply Gauss with a. rewrite H3. auto with zarith. - red in |- *; auto with zarith. + red; auto with zarith. apply Gauss with c. - rewrite Zmult_comm. + rewrite Z.mul_comm. rewrite <- H3. auto with zarith. - red in |- *; auto with zarith. + red; auto with zarith. Qed. (** After factorization by a gcd, the original numbers are relatively prime. *) @@ -613,7 +479,7 @@ Proof. elim H1; intros. elim H4; intros. rewrite H2 in H6; subst b; omega. - unfold rel_prime in |- *. + unfold rel_prime. destruct H1. destruct H1 as (a',H1). destruct H3 as (b',H3). @@ -625,14 +491,14 @@ Proof. 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. + destruct (H4 (x*g)) as (x',Hx'). + exists xa; rewrite Z.mul_assoc; rewrite <- H5; auto. + exists xb; rewrite Z.mul_assoc; rewrite <- H6; auto. + replace g with (1*g) in Hx'; auto with zarith. + do 2 rewrite Z.mul_assoc in Hx'. + apply Z.mul_reg_r in Hx'; trivial. + rewrite Z.mul_1_r in Hx'. + exists x'; auto with zarith. Qed. Theorem rel_prime_sym: forall a b, rel_prime a b -> rel_prime b a. @@ -646,9 +512,9 @@ Theorem rel_prime_div: forall p q r, Proof. intros p q r H (u, H1); subst. inversion_clear H as [H1 H2 H3]. - red; apply Zis_gcd_intro; try apply Zone_divide. + red; apply Zis_gcd_intro; try apply Z.divide_1_l. intros x H4 H5; apply H3; auto. - apply Zdivide_mult_r; auto. + apply Z.divide_mul_r; auto. Qed. Theorem rel_prime_1: forall n, rel_prime 1 n. @@ -709,30 +575,29 @@ 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. + destruct 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. + { assert (Z.abs a <= Z.abs p) as H2. + apply Zdivide_bounds; [ assumption | omega ]. + revert H2. + pattern (Z.abs a); apply Zabs_ind; pattern (Z.abs p); 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. + - absurd (rel_prime (- a) p); intuition. + inversion H2. + assert (- a | - a) by auto with zarith. + assert (- a | p) by auto with zarith. + apply H7, Z.divide_1_r in H8; intuition. (* a = 0 *) - inversion H2. subst a; omega. + - inversion H1. 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. + - absurd (rel_prime a p); intuition. + inversion H2. + assert (a | a) by auto with zarith. + assert (a | p) by auto with zarith. + apply H7, Z.divide_1_r in H8; intuition. Qed. (** A prime number is relatively prime with any number it does not divide *) @@ -757,7 +622,7 @@ Proof. intros a p Hp [H1 H2]. apply rel_prime_sym; apply prime_rel_prime; auto. intros [q Hq]; subst a. - case (Zle_or_lt q 0); intros Hl. + case (Z.le_gt_cases q 0); intros Hl. absurd (q * p <= 0 * p); auto with zarith. absurd (1 * p <= q * p); auto with zarith. Qed. @@ -787,87 +652,79 @@ Qed. Lemma prime_2: prime 2. Proof. apply prime_intro; auto with zarith. - intros n [H1 H2]; case Zle_lt_or_eq with ( 1 := H1 ); auto with zarith; - clear H1; intros H1. - contradict H2; auto with zarith. - subst n; red; auto with zarith. - apply Zis_gcd_intro; auto with zarith. + intros n (H,H'); Z.le_elim H; auto with zarith. + - contradict H'; auto with zarith. + - subst n. constructor; auto with zarith. Qed. Theorem prime_3: prime 3. Proof. apply prime_intro; auto with zarith. - intros n [H1 H2]; case Zle_lt_or_eq with ( 1 := H1 ); auto with zarith; - clear H1; intros H1. - case (Zle_lt_or_eq 2 n); auto with zarith; clear H1; intros H1. - contradict H2; auto with zarith. - subst n; red; auto with zarith. - apply Zis_gcd_intro; auto with zarith. - intros x [q1 Hq1] [q2 Hq2]. - exists (q2 - q1). - apply trans_equal with (3 - 2); auto with zarith. - rewrite Hq1; rewrite Hq2; ring. - subst n; red; auto with zarith. - apply Zis_gcd_intro; auto with zarith. + intros n (H,H'); Z.le_elim H; auto with zarith. + - replace n with 2 by omega. + constructor; auto with zarith. + intros x (q,Hq) (q',Hq'). + exists (q' - q). ring_simplify. now rewrite <- Hq, <- Hq'. + - replace n with 1 by trivial. + constructor; auto with zarith. Qed. -Theorem prime_ge_2: forall p, prime p -> 2 <= p. +Theorem prime_ge_2 p : prime p -> 2 <= p. Proof. - intros p Hp; inversion Hp; auto with zarith. + intros (Hp,_); auto with zarith. Qed. Definition prime' p := 1<p /\ (forall n, 1<n<p -> ~ (n|p)). -Theorem prime_alt: - forall p, prime' p <-> prime p. +Lemma Z_0_1_more x : 0<=x -> x=0 \/ x=1 \/ 1<x. Proof. - split; destruct 1; intros. - (* prime -> prime' *) - constructor; auto; intros. - red; apply Zis_gcd_intro; auto with zarith; intros. - case (Zle_lt_or_eq 0 (Zabs x)); auto with zarith; intros H6. - case (Zle_lt_or_eq 1 (Zabs x)); auto with zarith; intros H7. - case (Zle_lt_or_eq (Zabs x) p); auto with zarith. - apply Zdivide_le; auto with zarith. - apply Zdivide_Zabs_inv_l; auto. - intros H8; case (H0 (Zabs x)); auto. - apply Zdivide_Zabs_inv_l; auto. - intros H8; subst p; absurd (Zabs x <= n); auto with zarith. - apply Zdivide_le; auto with zarith. - apply Zdivide_Zabs_inv_l; auto. - rewrite H7; pattern (Zabs x); apply Zabs_intro; auto with zarith. - absurd (0%Z = p); auto with zarith. - assert (x=0) by (destruct x; simpl in *; now auto). - subst x; elim H3; intro q; rewrite Zmult_0_r; auto. - (* prime' -> prime *) - split; auto; intros. - intros H2. - case (Zis_gcd_unique n p n 1); auto with zarith. - apply Zis_gcd_intro; auto with zarith. - apply H0; auto with zarith. + intros H. Z.le_elim H; auto. + apply Z.le_succ_l in H. change (1 <= x) in H. Z.le_elim H; auto. +Qed. + +Theorem prime_alt p : prime' p <-> prime p. +Proof. + split; intros (Hp,H). + - (* prime -> prime' *) + constructor; trivial; intros n Hn. + constructor; auto with zarith; intros x Hxn Hxp. + rewrite <- Z.divide_abs_l in Hxn, Hxp |- *. + assert (Hx := Z.abs_nonneg x). + set (y:=Z.abs x) in *; clearbody y; clear x; rename y into x. + destruct (Z_0_1_more x Hx) as [->|[->|Hx']]. + + exfalso. apply Z.divide_0_l in Hxn. omega. + + now exists 1. + + elim (H x); auto. + split; trivial. + apply Z.le_lt_trans with n; auto with zarith. + apply Z.divide_pos_le; auto with zarith. + - (* prime' -> prime *) + constructor; trivial. intros n Hn Hnp. + case (Zis_gcd_unique n p n 1); auto with zarith. + constructor; auto with zarith. + apply H; auto with zarith. Qed. Theorem square_not_prime: forall a, ~ prime (a * a). Proof. intros a Ha. - rewrite <- (Zabs_square a) in Ha. - assert (0 <= Zabs a) by auto with zarith. - set (b:=Zabs a) in *; clearbody b. - rewrite <- prime_alt in Ha; destruct Ha. - case (Zle_lt_or_eq 0 b); auto with zarith; intros Hza1; [ | subst; omega]. - case (Zle_lt_or_eq 1 b); auto with zarith; intros Hza2; [ | subst; omega]. - assert (Hza3 := Zmult_lt_compat_r 1 b b Hza1 Hza2). - rewrite Zmult_1_l in Hza3. - elim (H1 _ (conj Hza2 Hza3)). - exists b; auto. + rewrite <- (Z.abs_square a) in Ha. + assert (H:=Z.abs_nonneg a). + set (b:=Z.abs a) in *; clearbody b; clear a; rename b into a. + rewrite <- prime_alt in Ha; destruct Ha as (Ha,Ha'). + assert (H' : 1 < a) by now apply (Z.square_lt_simpl_nonneg 1). + apply (Ha' a). + + split; trivial. + rewrite <- (Z.mul_1_l a) at 1. apply Z.mul_lt_mono_pos_r; omega. + + exists a; auto. Qed. Theorem prime_div_prime: forall p q, prime p -> prime q -> (p | q) -> p = q. Proof. intros p q H H1 H2; - assert (Hp: 0 < p); try apply Zlt_le_trans with 2; try apply prime_ge_2; auto with zarith. - assert (Hq: 0 < q); try apply Zlt_le_trans with 2; try apply prime_ge_2; auto with zarith. + assert (Hp: 0 < p); try apply Z.lt_le_trans with 2; try apply prime_ge_2; auto with zarith. + assert (Hq: 0 < q); try apply Z.lt_le_trans with 2; try apply prime_ge_2; auto with zarith. case prime_divisors with (2 := H2); auto. intros H4; contradict Hp; subst; auto with zarith. intros [H4| [H4 | H4]]; subst; auto. @@ -875,311 +732,101 @@ Proof. contradict Hp; auto with zarith. Qed. +(** we now prove that [Z.gcd] is indeed a gcd in + the sense of [Zis_gcd]. *) -(** We could obtain a [Zgcd] function via Euclid algorithm. But we propose - here a binary version of [Zgcd], faster and executable within Coq. - - Algorithm: - - gcd 0 b = b - gcd a 0 = a - gcd (2a) (2b) = 2(gcd a b) - gcd (2a+1) (2b) = gcd (2a+1) b - gcd (2a) (2b+1) = gcd a (2b+1) - gcd (2a+1) (2b+1) = gcd (b-a) (2*a+1) - or gcd (a-b) (2*b+1), depending on whether a<b -*) - -Open Scope positive_scope. - -Fixpoint Pgcdn (n: nat) (a b : positive) : 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 - end. - -Definition Pgcd (a b: positive) := Pgcdn (Psize a + Psize b)%nat a b. - -Close Scope positive_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. - -Lemma Zgcd_is_pos : forall a b, 0 <= Zgcd a b. -Proof. - unfold Zgcd; destruct a; destruct b; auto with zarith. -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. -Qed. +Notation Zgcd_is_pos := Z.gcd_nonneg (compat "8.3"). -Lemma Pgcdn_correct : forall n a b, (Psize a + Psize b<=n)%nat -> - Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcdn n a b)). +Lemma Zgcd_is_gcd : forall a b, Zis_gcd a b (Z.gcd 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 (Zpos_minus_morphism _ _ H1). - assert (0 < Zpos a) by (compute; auto). - omega. - omega. - rewrite Zpos_xO; do 2 rewrite Zpos_xI. - rewrite Zpos_minus_morphism; 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 (Zpos_minus_morphism 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 Zpos_minus_morphism; 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. -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. + constructor. + apply Z.gcd_divide_l. + apply Z.gcd_divide_r. + apply Z.gcd_greatest. Qed. Theorem Zgcd_spec : forall x y : Z, {z : Z | Zis_gcd x y z /\ 0 <= z}. Proof. - intros x y; exists (Zgcd x y). - split; [apply Zgcd_is_gcd | apply Zgcd_is_pos]. + intros x y; exists (Z.gcd x y). + split; [apply Zgcd_is_gcd | apply Z.gcd_nonneg]. Qed. Theorem Zdivide_Zgcd: forall p q r : Z, - (p | q) -> (p | r) -> (p | Zgcd q r). + (p | q) -> (p | r) -> (p | Z.gcd q r). Proof. - intros p q r H1 H2. - assert (H3: (Zis_gcd q r (Zgcd q r))). - apply Zgcd_is_gcd. - inversion_clear H3; auto. + intros. now apply Z.gcd_greatest. Qed. Theorem Zis_gcd_gcd: forall a b c : Z, - 0 <= c -> Zis_gcd a b c -> Zgcd a b = c. + 0 <= c -> Zis_gcd a b c -> Z.gcd a b = c. Proof. intros a b c H1 H2. - case (Zis_gcd_uniqueness_apart_sign a b c (Zgcd a b)); auto. + case (Zis_gcd_uniqueness_apart_sign a b c (Z.gcd a b)); auto. apply Zgcd_is_gcd; auto. - case Zle_lt_or_eq with (1 := H1); clear H1; intros H1; subst; auto. - intros H3; subst. - generalize (Zgcd_is_pos a b); auto with zarith. - case (Zgcd a b); simpl; auto; intros; discriminate. -Qed. - -Theorem Zgcd_inv_0_l: forall x y, Zgcd x y = 0 -> x = 0. -Proof. - intros x y H. - assert (F1: Zdivide 0 x). - rewrite <- H. - generalize (Zgcd_is_gcd x y); intros HH; inversion HH; auto. - inversion F1 as [z H1]. - rewrite H1; ring. + Z.le_elim H1. + - generalize (Z.gcd_nonneg a b); auto with zarith. + - subst. now case (Z.gcd a b). Qed. -Theorem Zgcd_inv_0_r: forall x y, Zgcd x y = 0 -> y = 0. -Proof. - intros x y H. - assert (F1: Zdivide 0 y). - rewrite <- H. - generalize (Zgcd_is_gcd x y); intros HH; inversion HH; auto. - inversion F1 as [z H1]. - rewrite H1; ring. -Qed. +Notation Zgcd_inv_0_l := Z.gcd_eq_0_l (compat "8.3"). +Notation Zgcd_inv_0_r := Z.gcd_eq_0_r (compat "8.3"). Theorem Zgcd_div_swap0 : forall a b : Z, - 0 < Zgcd a b -> + 0 < Z.gcd a b -> 0 < b -> - (a / Zgcd a b) * b = a * (b/Zgcd a b). + (a / Z.gcd a b) * b = a * (b/Z.gcd a b). Proof. intros a b Hg Hb. assert (F := Zgcd_is_gcd a b); inversion F as [F1 F2 F3]. - pattern b at 2; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. - repeat rewrite Zmult_assoc; f_equal. - rewrite Zmult_comm. + pattern b at 2; rewrite (Zdivide_Zdiv_eq (Z.gcd a b) b); auto. + repeat rewrite Z.mul_assoc; f_equal. + rewrite Z.mul_comm. rewrite <- Zdivide_Zdiv_eq; auto. Qed. Theorem Zgcd_div_swap : forall a b c : Z, - 0 < Zgcd a b -> + 0 < Z.gcd a b -> 0 < b -> - (c * a) / Zgcd a b * b = c * a * (b/Zgcd a b). + (c * a) / Z.gcd a b * b = c * a * (b/Z.gcd a b). Proof. intros a b c Hg Hb. assert (F := Zgcd_is_gcd a b); inversion F as [F1 F2 F3]. - pattern b at 2; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto. - repeat rewrite Zmult_assoc; f_equal. + pattern b at 2; rewrite (Zdivide_Zdiv_eq (Z.gcd a b) b); auto. + repeat rewrite Z.mul_assoc; f_equal. rewrite Zdivide_Zdiv_eq_2; auto. - repeat rewrite <- Zmult_assoc; f_equal. - rewrite Zmult_comm. + repeat rewrite <- Z.mul_assoc; f_equal. + rewrite Z.mul_comm. rewrite <- Zdivide_Zdiv_eq; auto. Qed. -Lemma Zgcd_comm : forall a b, Zgcd a b = Zgcd b a. -Proof. - intros. - apply Zis_gcd_gcd. - apply Zgcd_is_pos. - apply Zis_gcd_sym. - apply Zgcd_is_gcd. -Qed. +Notation Zgcd_comm := Z.gcd_comm (compat "8.3"). -Lemma Zgcd_ass : forall a b c, Zgcd (Zgcd a b) c = Zgcd a (Zgcd b c). +Lemma Zgcd_ass a b c : Z.gcd (Z.gcd a b) c = Z.gcd a (Z.gcd b c). Proof. - intros. - apply Zis_gcd_gcd. - apply Zgcd_is_pos. - destruct (Zgcd_is_gcd a b). - destruct (Zgcd_is_gcd b c). - destruct (Zgcd_is_gcd a (Zgcd b c)). - constructor; eauto using Zdivide_trans. + symmetry. apply Z.gcd_assoc. Qed. -Lemma Zgcd_Zabs : forall a b, Zgcd (Zabs a) b = Zgcd a b. -Proof. - destruct a; simpl; auto. -Qed. - -Lemma Zgcd_0 : forall a, Zgcd a 0 = Zabs a. -Proof. - destruct a; simpl; auto. -Qed. +Notation Zgcd_Zabs := Z.gcd_abs_l (compat "8.3"). +Notation Zgcd_0 := Z.gcd_0_r (compat "8.3"). +Notation Zgcd_1 := Z.gcd_1_r (compat "8.3"). -Lemma Zgcd_1 : forall a, Zgcd a 1 = 1. -Proof. - intros; apply Zis_gcd_gcd; auto with zarith; apply Zis_gcd_1. -Qed. -Hint Resolve Zgcd_0 Zgcd_1 : zarith. +Hint Resolve Z.gcd_0_r Z.gcd_1_r : zarith. Theorem Zgcd_1_rel_prime : forall a b, - Zgcd a b = 1 <-> rel_prime a b. + Z.gcd a b = 1 <-> rel_prime a b. Proof. unfold rel_prime; split; intro H. rewrite <- H; apply Zgcd_is_gcd. - case (Zis_gcd_unique a b (Zgcd a b) 1); auto. + case (Zis_gcd_unique a b (Z.gcd a b) 1); auto. apply Zgcd_is_gcd. - intros H2; absurd (0 <= Zgcd a b); auto with zarith. - generalize (Zgcd_is_pos a b); auto with zarith. + intros H2; absurd (0 <= Z.gcd a b); auto with zarith. + generalize (Z.gcd_nonneg a b); auto with zarith. Qed. Definition rel_prime_dec: forall a b, { rel_prime a b }+{ ~ rel_prime a b }. Proof. - intros a b; case (Z_eq_dec (Zgcd a b) 1); intros H1. + intros a b; case (Z.eq_dec (Z.gcd a b) 1); intros H1. left; apply -> Zgcd_1_rel_prime; auto. right; contradict H1; apply <- Zgcd_1_rel_prime; auto. Defined. @@ -1197,25 +844,24 @@ Proof. intros x Hx IH; destruct IH as [F|E]. destruct (rel_prime_dec x p) as [Y|N]. left; intros n [HH1 HH2]. - case (Zgt_succ_gt_or_eq x n); auto with zarith. - intros HH3; subst x; auto. - case (Z_lt_dec 1 x); intros HH1. - right; exists x; split; auto with zarith. - left; intros n [HHH1 HHH2]; contradict HHH1; auto with zarith. - right; destruct E as (n,((H0,H2),H3)); exists n; auto with zarith. + rewrite Z.lt_succ_r in HH2. + Z.le_elim HH2; subst; auto with zarith. + - case (Z_lt_dec 1 x); intros HH1. + * right; exists x; split; auto with zarith. + * left; intros n [HHH1 HHH2]; contradict HHH1; auto with zarith. + - right; destruct E as (n,((H0,H2),H3)); exists n; auto with zarith. Defined. Definition prime_dec: forall p, { prime p }+{ ~ prime p }. Proof. intros p; case (Z_lt_dec 1 p); intros H1. - case (prime_dec_aux p p); intros H2. - left; apply prime_intro; auto. - intros n [Hn1 Hn2]; case Zle_lt_or_eq with ( 1 := Hn1 ); auto. - intros HH; subst n. - red; apply Zis_gcd_intro; auto with zarith. - right; intros H3; inversion_clear H3 as [Hp1 Hp2]. - case H2; intros n [Hn1 Hn2]; case Hn2; auto with zarith. - right; intros H3; inversion_clear H3 as [Hp1 Hp2]; case H1; auto. + + case (prime_dec_aux p p); intros H2. + * left; apply prime_intro; auto. + intros n (Hn1,Hn2). Z.le_elim Hn1; auto; subst n. + constructor; auto with zarith. + * right; intros H3; inversion_clear H3 as [Hp1 Hp2]. + case H2; intros n [Hn1 Hn2]; case Hn2; auto with zarith. + + right; intros H3; inversion_clear H3 as [Hp1 Hp2]; case H1; auto. Defined. Theorem not_prime_divide: @@ -1223,193 +869,16 @@ Theorem not_prime_divide: Proof. intros p Hp Hp1. case (prime_dec_aux p p); intros H1. - elim Hp1; constructor; auto. - intros n [Hn1 Hn2]. - case Zle_lt_or_eq with ( 1 := Hn1 ); auto with zarith. - intros H2; subst n; red; apply Zis_gcd_intro; auto with zarith. - case H1; intros n [Hn1 Hn2]. - generalize (Zgcd_is_pos n p); intros Hpos. - case (Zle_lt_or_eq 0 (Zgcd n p)); auto with zarith; intros H3. - case (Zle_lt_or_eq 1 (Zgcd n p)); auto with zarith; intros H4. - exists (Zgcd n p); split; auto. - split; auto. - apply Zle_lt_trans with n; auto with zarith. - generalize (Zgcd_is_gcd n p); intros tmp; inversion_clear tmp as [Hr1 Hr2 Hr3]. - case Hr1; intros q Hq. - case (Zle_or_lt q 0); auto with zarith; intros Ht. - absurd (n <= 0 * Zgcd n p) ; auto with zarith. - pattern n at 1; rewrite Hq; auto with zarith. - apply Zle_trans with (1 * Zgcd n p); auto with zarith. - pattern n at 2; rewrite Hq; auto with zarith. - generalize (Zgcd_is_gcd n p); intros Ht; inversion Ht; auto. - case Hn2; red. - rewrite H4; apply Zgcd_is_gcd. - generalize (Zgcd_is_gcd n p); rewrite <- H3; intros tmp; - inversion_clear tmp as [Hr1 Hr2 Hr3]. - absurd (n = 0); auto with zarith. - case Hr1; auto with zarith. -Qed. - -(** A Generalized Gcd that also computes Bezout coefficients. - The algorithm is the same as for Zgcd. *) - -Open Scope positive_scope. - -Fixpoint Pggcdn (n: nat) (a b : positive) : (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 - end. - -Definition Pggcd (a b: positive) := Pggcdn (Psize a + Psize b)%nat a b. - -Open Scope Z_scope. - -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. - - -Lemma Pggcdn_gcdn : forall 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. -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). -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. -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. -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). -Proof. - intros a b; exact (Pggcdn_correct_divisors (Psize a + Psize b)%nat a b). -Qed. - -Close Scope positive_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). -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. -Qed. - -Theorem Zggcd_opp: forall x y, - Zggcd (-x) y = let (p1,p) := Zggcd x y in - let (p2,p3) := p in - (p1,(-p2,p3)). -Proof. -intros [|x|x] [|y|y]; unfold Zggcd, Zopp; auto. -case Pggcd; intros p1 (p2, p3); auto. -case Pggcd; intros p1 (p2, p3); auto. -case Pggcd; intros p1 (p2, p3); auto. -case Pggcd; intros p1 (p2, p3); auto. + - elim Hp1; constructor; auto. + intros n (Hn1,Hn2). + Z.le_elim Hn1; auto with zarith. + subst n; constructor; auto with zarith. + - case H1; intros n (Hn1,Hn2). + destruct (Z_0_1_more _ (Z.gcd_nonneg n p)) as [H|[H|H]]. + + exfalso. apply Z.gcd_eq_0_l in H. omega. + + elim Hn2. red. rewrite <- H. apply Zgcd_is_gcd. + + exists (Z.gcd n p); split; [ split; auto | apply Z.gcd_divide_r ]. + apply Z.le_lt_trans with n; auto with zarith. + apply Z.divide_pos_le; auto with zarith. + apply Z.gcd_divide_l. Qed. diff --git a/theories/ZArith/Zorder.v b/theories/ZArith/Zorder.v index 91c16929..b1d1f8b5 100644 --- a/theories/ZArith/Zorder.v +++ b/theories/ZArith/Zorder.v @@ -1,337 +1,202 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zorder.v 14641 2011-11-06 11:59:10Z herbelin $ i*) -(** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) +(** Binary Integers : results about order predicates *) +(** Initial author : Pierre Crégut (CNET, Lannion, France) *) -Require Import BinPos. -Require Import BinInt. -Require Import Arith_base. -Require Import Decidable. -Require Import Zcompare. +(** THIS FILE IS DEPRECATED. + It is now almost entirely made of compatibility formulations + for results already present in BinInt.Z. *) -Open Local Scope Z_scope. +Require Import BinPos BinInt Decidable Zcompare. +Require Import Arith_base. (* Useless now, for compatibility only *) -Implicit Types x y z : Z. +Local Open Scope Z_scope. (*********************************************************) (** Properties of the order relations on binary integers *) (** * Trichotomy *) -Theorem Ztrichotomy_inf : forall n m:Z, {n < m} + {n = m} + {n > m}. +Theorem Ztrichotomy_inf n m : {n < m} + {n = m} + {n > m}. Proof. - 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. -Qed. + unfold ">", "<". generalize (Z.compare_eq n m). + destruct (n ?= m); [ left; right | left; left | right]; auto. +Defined. -Theorem Ztrichotomy : forall n m:Z, n < m \/ n = m \/ n > m. +Theorem Ztrichotomy n m : 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. + Z.swap_greater. apply Z.lt_trichotomy. Qed. (**********************************************************************) (** * 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 ]. -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 ] ]. -Qed. +Notation dec_eq := Z.eq_decidable (compat "8.3"). +Notation dec_Zle := Z.le_decidable (compat "8.3"). +Notation dec_Zlt := Z.lt_decidable (compat "8.3"). -Theorem dec_Zle : forall n m:Z, decidable (n <= m). +Theorem dec_Zne n m : decidable (Zne 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 ]. + destruct (Z.eq_decidable n m); [right|left]; subst; auto. Qed. -Theorem dec_Zgt : forall n m:Z, decidable (n > m). +Theorem dec_Zgt n m : decidable (n > m). Proof. - intros x y; unfold decidable, Zgt in |- *; elim (x ?= y); - [ right; discriminate | right; discriminate | auto with arith ]. + destruct (Z.lt_decidable m n); [left|right]; Z.swap_greater; auto. Qed. -Theorem dec_Zge : forall n m:Z, decidable (n >= m). +Theorem dec_Zge n m : 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 ]. + destruct (Z.le_decidable m n); [left|right]; Z.swap_greater; auto. Qed. -Theorem dec_Zlt : forall n m:Z, decidable (n < m). +Theorem not_Zeq n m : n <> m -> n < m \/ m < n. Proof. - 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 ] ]. + apply Z.lt_gt_cases. Qed. (** * 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. -Qed. +Notation Zgt_lt := Z.gt_lt (compat "8.3"). +Notation Zlt_gt := Z.lt_gt (compat "8.3"). +Notation Zge_le := Z.ge_le (compat "8.3"). +Notation Zle_ge := Z.le_ge (compat "8.3"). +Notation Zgt_iff_lt := Z.gt_lt_iff (compat "8.3"). +Notation Zge_iff_le := Z.ge_le_iff (compat "8.3"). -Lemma Zlt_gt : forall n m:Z, n < m -> m > n. +Lemma Zle_not_lt n m : n <= m -> ~ m < n. Proof. - unfold Zgt, Zlt in |- *; intros m n H; elim (Zcompare_Gt_Lt_antisym n m); - auto with arith. + apply Z.le_ngt. Qed. -Lemma Zge_le : forall n m:Z, n >= m -> m <= n. +Lemma Zlt_not_le n m : 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. + apply Z.lt_nge. 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. -Qed. - -Lemma Zle_not_gt : forall n m:Z, n <= m -> ~ n > m. +Lemma Zle_not_gt n m : n <= m -> ~ n > m. Proof. trivial. Qed. -Lemma Zgt_not_le : forall n m:Z, n > m -> ~ n <= m. -Proof. - 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. -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. -Qed. - -Lemma Znot_ge_lt : forall n m:Z, ~ n >= m -> n < m. +Lemma Zgt_not_le n m : n > m -> ~ n <= m. Proof. - unfold Zge, Zlt in |- *; intros x y H; apply dec_not_not; - [ exact (dec_Zlt x y) | assumption ]. + Z.swap_greater. apply Z.lt_nge. Qed. -Lemma Znot_lt_ge : forall n m:Z, ~ n < m -> n >= m. +Lemma Znot_ge_lt n m : ~ n >= m -> n < m. Proof. - unfold Zlt, Zge in |- *; auto with arith. + Z.swap_greater. apply Z.nle_gt. Qed. -Lemma Znot_gt_le : forall n m:Z, ~ n > m -> n <= m. +Lemma Znot_lt_ge n m : ~ n < m -> n >= m. Proof. trivial. Qed. -Lemma Znot_le_gt : forall n m:Z, ~ n <= m -> n > m. +Lemma Znot_gt_le n m: ~ n > m -> n <= m. Proof. - unfold Zle, Zgt in |- *; intros x y H; apply dec_not_not; - [ exact (dec_Zgt x y) | assumption ]. + trivial. Qed. -Lemma Zge_iff_le : forall n m:Z, n >= m <-> m <= n. +Lemma Znot_le_gt n m : ~ n <= m -> n > m. Proof. - intros x y; intros. split. intro. apply Zge_le. assumption. - intro. apply Zle_ge. assumption. + Z.swap_greater. apply Z.nle_gt. Qed. -Lemma Zgt_iff_lt : forall n m:Z, n > m <-> m < n. +Lemma not_Zne n m : ~ Zne n m -> n = m. Proof. - intros x y. split. intro. apply Zgt_lt. assumption. - intro. apply Zlt_gt. assumption. + intros H. + destruct (Z.eq_decidable n m); [assumption|now elim H]. 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. -Qed. - -Lemma Zeq_le : forall n m:Z, n = m -> n <= m. -Proof. - intros; rewrite H; apply Zle_refl. -Qed. +Notation Zle_refl := Z.le_refl (compat "8.3"). +Notation Zeq_le := Z.eq_le_incl (compat "8.3"). -Hint Resolve Zle_refl: zarith. +Hint Resolve Z.le_refl: zarith. (** Antisymmetry *) -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]]. - absurd (m > n); [ apply Zle_not_gt | apply Zlt_gt ]; assumption. - assumption. - absurd (n > m); [ apply Zle_not_gt | idtac ]; assumption. -Qed. +Notation Zle_antisym := Z.le_antisymm (compat "8.3"). (** Asymmetry *) -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 ]. -Qed. +Notation Zlt_asym := Z.lt_asymm (compat "8.3"). -Lemma Zlt_asym : forall n m:Z, n < m -> ~ m < n. +Lemma Zgt_asym n m : 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. + Z.swap_greater. apply Z.lt_asymm. Qed. (** Irreflexivity *) -Lemma Zgt_irrefl : forall n:Z, ~ n > n. -Proof. - intros n H; apply (Zgt_asym n n H H). -Qed. +Notation Zlt_irrefl := Z.lt_irrefl (compat "8.3"). +Notation Zlt_not_eq := Z.lt_neq (compat "8.3"). -Lemma Zlt_irrefl : forall n:Z, ~ n < n. +Lemma Zgt_irrefl n : ~ n > n. Proof. - 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). + Z.swap_greater. apply Z.lt_irrefl. 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. -Qed. +Notation Zlt_le_weak := Z.lt_le_incl (compat "8.3"). +Notation Zle_lt_or_eq_iff := Z.lt_eq_cases (compat "8.3"). -Lemma Zle_lt_or_eq : forall n m:Z, n <= m -> n < m \/ n = m. +Lemma Zle_lt_or_eq n m : 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 ]. -Qed. - -Lemma Zle_lt_or_eq_iff : forall n m, n <= m <-> n < m \/ n = m. -Proof. - unfold Zle, Zlt. intros. - generalize (Zcompare_Eq_iff_eq n m). - destruct (n ?= m); intuition; discriminate. + apply Z.lt_eq_cases. 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 ]. -Qed. +Notation Zle_or_lt := Z.le_gt_cases (compat "8.3"). (** Transitivity of strict orders *) -Lemma Zgt_trans : forall n m p:Z, n > m -> m > p -> n > p. -Proof. - exact Zcompare_Gt_trans. -Qed. +Notation Zlt_trans := Z.lt_trans (compat "8.3"). -Lemma Zlt_trans : forall n m p:Z, n < m -> m < p -> n < p. +Lemma Zgt_trans n m p : n > m -> m > p -> n > p. Proof. - exact Zcompare_Lt_trans. + Z.swap_greater. intros; now transitivity m. 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 ]. -Qed. +Notation Zlt_le_trans := Z.lt_le_trans (compat "8.3"). +Notation Zle_lt_trans := Z.le_lt_trans (compat "8.3"). -Lemma Zgt_le_trans : forall n m p:Z, n > m -> p <= m -> n > p. +Lemma Zle_gt_trans n m p : m <= n -> m > p -> 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 ]. -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 ]. + Z.swap_greater. Z.order. Qed. -Lemma Zle_lt_trans : forall n m p:Z, n <= m -> m < p -> n < p. +Lemma Zgt_le_trans n m p : n > m -> p <= m -> n > p. Proof. - intros n m p H1 H2; apply Zgt_lt; apply Zgt_le_trans with (m := m); - [ apply Zlt_gt; assumption | assumption ]. + Z.swap_greater. Z.order. 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). -Qed. +Notation Zle_trans := Z.le_trans (compat "8.3"). -Lemma Zge_trans : forall n m p:Z, n >= m -> m >= p -> n >= p. +Lemma Zge_trans n m p : 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. + Z.swap_greater. Z.order. Qed. -Hint Resolve Zle_trans: zarith. - +Hint Resolve Z.le_trans: zarith. (** * Compatibility of order and operations on Z *) @@ -339,700 +204,448 @@ Hint Resolve Zle_trans: zarith. (** Compatibility of successor wrt to order *) -Lemma Zsucc_le_compat : forall n m:Z, m <= n -> Zsucc m <= Zsucc n. +Lemma Zsucc_le_compat n m : m <= n -> Z.succ m <= Z.succ 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. + apply Z.succ_le_mono. Qed. -Lemma Zsucc_gt_compat : forall n m:Z, m > n -> Zsucc m > Zsucc n. +Lemma Zsucc_lt_compat n m : n < m -> Z.succ n < Z.succ m. Proof. - unfold Zgt in |- *; intros n m H; rewrite Zcompare_succ_compat; - auto with arith. + apply Z.succ_lt_mono. Qed. -Lemma Zsucc_lt_compat : forall n m:Z, n < m -> Zsucc n < Zsucc m. +Lemma Zsucc_gt_compat n m : m > n -> Z.succ m > Z.succ n. Proof. - intros n m H; apply Zgt_lt; apply Zsucc_gt_compat; apply Zlt_gt; assumption. + Z.swap_greater. apply Z.succ_lt_mono. Qed. Hint Resolve Zsucc_le_compat: zarith. (** Simplification of successor wrt to order *) -Lemma Zsucc_gt_reg : forall n m:Z, Zsucc m > Zsucc n -> m > n. +Lemma Zsucc_gt_reg n m : Z.succ m > Z.succ 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. + Z.swap_greater. apply Z.succ_lt_mono. Qed. -Lemma Zsucc_le_reg : forall n m:Z, Zsucc m <= Zsucc n -> m <= n. +Lemma Zsucc_le_reg n m : Z.succ m <= Z.succ 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. + apply Z.succ_le_mono. Qed. -Lemma Zsucc_lt_reg : forall n m:Z, Zsucc n < Zsucc m -> n < m. +Lemma Zsucc_lt_reg n m : Z.succ n < Z.succ m -> n < m. Proof. - intros n m H; apply Zgt_lt; apply Zsucc_gt_reg; apply Zlt_gt; assumption. + apply Z.succ_lt_mono. Qed. (** Special base instances of order *) -Lemma Zgt_succ : forall n:Z, Zsucc n > n. -Proof. - 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. -Qed. +Notation Zlt_succ := Z.lt_succ_diag_r (compat "8.3"). +Notation Zlt_pred := Z.lt_pred_l (compat "8.3"). -Lemma Zlt_succ : forall n:Z, n < Zsucc n. +Lemma Zgt_succ n : Z.succ n > n. Proof. - intro n; apply Zgt_lt; apply Zgt_succ. + Z.swap_greater. apply Z.lt_succ_diag_r. Qed. -Lemma Zlt_pred : forall n:Z, Zpred n < n. +Lemma Znot_le_succ n : ~ Z.succ n <= n. Proof. - intros n; apply Zsucc_lt_reg; rewrite <- Zsucc_pred; apply Zlt_succ. + apply Z.lt_nge, Z.lt_succ_diag_r. 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 ]. -Qed. +Notation Zlt_succ_r := Z.lt_succ_r (compat "8.3"). +Notation Zle_succ_l := Z.le_succ_l (compat "8.3"). -Lemma Zle_gt_succ : forall n m:Z, n <= m -> Zsucc m > n. +Lemma Zgt_le_succ n m : m > n -> Z.succ n <= m. Proof. - intros n p H; apply Zgt_le_trans with p. - apply Zgt_succ. - assumption. + Z.swap_greater. apply Z.le_succ_l. Qed. -Lemma Zle_lt_succ : forall n m:Z, n <= m -> n < Zsucc m. +Lemma Zle_gt_succ n m : n <= m -> Z.succ m > n. Proof. - intros n m H; apply Zgt_lt; apply Zle_gt_succ; assumption. + Z.swap_greater. apply Z.lt_succ_r. Qed. -Lemma Zlt_le_succ : forall n m:Z, n < m -> Zsucc n <= m. +Lemma Zle_lt_succ n m : n <= m -> n < Z.succ m. Proof. - intros n p H; apply Zgt_le_succ; apply Zlt_gt; assumption. + apply Z.lt_succ_r. Qed. -Lemma Zgt_succ_le : forall n m:Z, Zsucc m > n -> n <= m. +Lemma Zlt_le_succ n m : n < m -> Z.succ n <= m. Proof. - intros n p H; apply Zsucc_le_reg; apply Zgt_le_succ; assumption. + apply Z.le_succ_l. Qed. -Lemma Zlt_succ_le : forall n m:Z, n < Zsucc m -> n <= m. +Lemma Zgt_succ_le n m : Z.succ m > n -> n <= m. Proof. - intros n m H; apply Zgt_succ_le; apply Zlt_gt; assumption. + Z.swap_greater. apply Z.lt_succ_r. Qed. -Lemma Zle_succ_gt : forall n m:Z, Zsucc n <= m -> m > n. +Lemma Zlt_succ_le n m : n < Z.succ m -> n <= m. Proof. - intros n m H; apply Zle_gt_trans with (m := Zsucc n); - [ assumption | apply Zgt_succ ]. + apply Z.lt_succ_r. Qed. -Lemma Zlt_succ_r : forall n m, n < Zsucc m <-> n <= m. +Lemma Zle_succ_gt n m : Z.succ n <= m -> m > n. Proof. - split; [apply Zlt_succ_le | apply Zle_lt_succ]. + Z.swap_greater. apply Z.le_succ_l. 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. -Qed. - -Hint Resolve Zle_succ: zarith. +Notation Zle_succ := Z.le_succ_diag_r (compat "8.3"). +Notation Zle_pred := Z.le_pred_l (compat "8.3"). +Notation Zlt_lt_succ := Z.lt_lt_succ_r (compat "8.3"). +Notation Zle_le_succ := Z.le_le_succ_r (compat "8.3"). -Lemma Zle_pred : forall n:Z, Zpred n <= n. +Lemma Zle_succ_le n m : Z.succ n <= m -> n <= m. Proof. - intros n; pattern n at 2 in |- *; rewrite Zsucc_pred; apply Zle_succ. + intros. now apply Z.lt_le_incl, Z.le_succ_l. 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 ]. -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. -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 ]. -Qed. - -Hint Resolve Zle_le_succ: zarith. +Hint Resolve Z.le_succ_diag_r: zarith. +Hint Resolve Z.le_le_succ_r: zarith. (** Relating order wrt successor and order wrt predecessor *) -Lemma Zgt_succ_pred : forall n m:Z, m > Zsucc n -> Zpred m > n. +Lemma Zgt_succ_pred n m : m > Z.succ n -> Z.pred 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. + Z.swap_greater. apply Z.lt_succ_lt_pred. Qed. -Lemma Zlt_succ_pred : forall n m:Z, Zsucc n < m -> n < Zpred m. +Lemma Zlt_succ_pred n m : Z.succ n < m -> n < Z.pred m. Proof. - intros n p H; apply Zsucc_lt_reg; rewrite <- Zsucc_pred; assumption. + apply Z.lt_succ_lt_pred. Qed. (** Relating strict order and large order on positive *) -Lemma Zlt_0_le_0_pred : forall n:Z, 0 < n -> 0 <= Zpred n. +Lemma Zlt_0_le_0_pred n : 0 < n -> 0 <= Z.pred n. Proof. - intros x H. - rewrite (Zsucc_pred x) in H. - apply Zgt_succ_le. - apply Zlt_gt. - assumption. + apply Z.lt_le_pred. Qed. -Lemma Zgt_0_le_0_pred : forall n:Z, n > 0 -> 0 <= Zpred n. +Lemma Zgt_0_le_0_pred n : n > 0 -> 0 <= Z.pred n. Proof. - intros; apply Zlt_0_le_0_pred; apply Zgt_lt. assumption. + Z.swap_greater. apply Z.lt_le_pred. Qed. - (** Special cases of ordered integers *) -Lemma Zlt_0_1 : 0 < 1. -Proof. - change (0 < Zsucc 0) in |- *. apply Zlt_succ. -Qed. - -Lemma Zle_0_1 : 0 <= 1. -Proof. - change (0 <= Zsucc 0) in |- *. apply Zle_succ. -Qed. +Notation Zlt_0_1 := Z.lt_0_1 (compat "8.3"). +Notation Zle_0_1 := Z.le_0_1 (compat "8.3"). Lemma Zle_neg_pos : forall p q:positive, Zneg p <= Zpos q. Proof. - intros p; red in |- *; simpl in |- *; red in |- *; intros H; discriminate. + easy. Qed. Lemma Zgt_pos_0 : forall p:positive, Zpos p > 0. Proof. - unfold Zgt in |- *; trivial. + easy. Qed. -(* weaker but useful (in [Zpower] for instance) *) +(* weaker but useful (in [Z.pow] for instance) *) Lemma Zle_0_pos : forall p:positive, 0 <= Zpos p. Proof. - intro; unfold Zle in |- *; discriminate. + easy. Qed. Lemma Zlt_neg_0 : forall p:positive, Zneg p < 0. Proof. - unfold Zlt in |- *; trivial. + easy. Qed. -Lemma Zle_0_nat : forall n:nat, 0 <= Z_of_nat n. +Lemma Zle_0_nat : forall n:nat, 0 <= Z.of_nat n. Proof. - simple induction n; simpl in |- *; intros; - [ apply Zle_refl | unfold Zle in |- *; simpl in |- *; discriminate ]. + induction n; simpl; intros. apply Z.le_refl. easy. Qed. -Hint Immediate Zeq_le: zarith. - -(** Transitivity using successor *) - -Lemma Zgt_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 ]. -Qed. +Hint Immediate Z.eq_le_incl: zarith. (** Derived lemma *) -Lemma Zgt_succ_gt_or_eq : forall n m:Z, Zsucc n > m -> n > m \/ m = n. +Lemma Zgt_succ_gt_or_eq n m : Z.succ n > m -> n > m \/ m = n. Proof. - intros n m H. - assert (Hle : m <= n). - apply Zgt_succ_le; assumption. - destruct (Zle_lt_or_eq _ _ Hle) as [Hlt| Heq]. - left; apply Zlt_gt; assumption. - right; assumption. + Z.swap_greater. intros. now apply Z.lt_eq_cases, Z.lt_succ_r. Qed. (** ** 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. +Notation Zplus_lt_le_compat := Z.add_lt_le_mono (compat "8.3"). +Notation Zplus_le_lt_compat := Z.add_le_lt_mono (compat "8.3"). +Notation Zplus_le_compat := Z.add_le_mono (compat "8.3"). +Notation Zplus_lt_compat := Z.add_lt_mono (compat "8.3"). -Lemma Zplus_le_compat_r : forall n m p:Z, n <= m -> n + p <= m + p. +Lemma Zplus_gt_compat_l n m p : n > m -> p + n > p + m. Proof. - intros a b c; do 2 rewrite (fun n:Z => Zplus_comm n c); - exact (Zplus_le_compat_l a b c). + Z.swap_greater. apply Z.add_lt_mono_l. Qed. -Lemma Zplus_lt_compat_l : forall n m p:Z, n < m -> p + n < p + m. +Lemma Zplus_gt_compat_r n m p : n > m -> n + p > m + p. Proof. - unfold Zlt in |- *; intros n m p; rewrite Zcompare_plus_compat; - trivial with arith. + Z.swap_greater. apply Z.add_lt_mono_r. Qed. -Lemma Zplus_lt_compat_r : forall n m p:Z, n < m -> n + p < m + p. +Lemma Zplus_le_compat_l n m p : n <= m -> p + n <= p + m. Proof. - intros n m p H; rewrite (Zplus_comm n p); rewrite (Zplus_comm m p); - apply Zplus_lt_compat_l; trivial. + apply Z.add_le_mono_l. Qed. -Lemma Zplus_lt_le_compat : forall n m p q:Z, n < m -> p <= q -> n + p < m + q. +Lemma Zplus_le_compat_r n m p : n <= m -> n + p <= m + p. 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. + apply Z.add_le_mono_r. Qed. -Lemma Zplus_le_lt_compat : forall n m p q:Z, n <= m -> p < q -> n + p < m + q. +Lemma Zplus_lt_compat_l n m p : n < m -> p + n < p + m. 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. + apply Z.add_lt_mono_l. Qed. -Lemma Zplus_le_compat : forall n m p q:Z, n <= m -> p <= q -> n + p <= m + q. +Lemma Zplus_lt_compat_r n m p : n < m -> n + p < m + p. 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. + apply Z.add_lt_mono_r. 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. +Notation Zplus_le_0_compat := Z.add_nonneg_nonneg (compat "8.3"). (** Simplification of addition wrt to order *) -Lemma Zplus_gt_reg_l : forall n m p:Z, p + n > p + m -> n > m. +Lemma Zplus_le_reg_l n m p : p + n <= p + m -> n <= m. Proof. - unfold Zgt in |- *; intros n m p H; rewrite <- (Zcompare_plus_compat n m p); - assumption. + apply Z.add_le_mono_l. Qed. -Lemma Zplus_gt_reg_r : forall n m p:Z, n + p > m + p -> n > m. +Lemma Zplus_le_reg_r n m p : 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. + apply Z.add_le_mono_r. Qed. -Lemma Zplus_le_reg_l : forall n m p:Z, p + n <= p + m -> n <= m. +Lemma Zplus_lt_reg_l n m p : 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. + apply Z.add_lt_mono_l. Qed. -Lemma Zplus_le_reg_r : forall n m p:Z, n + p <= m + p -> n <= m. +Lemma Zplus_lt_reg_r n m p : 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. + apply Z.add_lt_mono_r. Qed. -Lemma Zplus_lt_reg_l : forall n m p:Z, p + n < p + m -> n < m. +Lemma Zplus_gt_reg_l n m p : p + n > p + m -> n > m. Proof. - unfold Zlt in |- *; intros n m p; rewrite Zcompare_plus_compat; - trivial with arith. + Z.swap_greater. apply Z.add_lt_mono_l. Qed. -Lemma Zplus_lt_reg_r : forall n m p:Z, n + p < m + p -> n < m. +Lemma Zplus_gt_reg_r n m p : 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. + Z.swap_greater. apply Z.add_lt_mono_r. 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. +Lemma Zmult_le_compat_r n m p : n <= m -> 0 <= p -> n * p <= m * p. Proof. - 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 H0; contradiction H0; reflexivity. + intros. now apply Z.mul_le_mono_nonneg_r. Qed. -Lemma Zmult_le_compat_l : forall n m p:Z, n <= m -> 0 <= p -> p * n <= p * m. +Lemma Zmult_le_compat_l n m p : 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. now apply Z.mul_le_mono_nonneg_l. Qed. -Lemma Zmult_lt_compat_r : forall n m p:Z, 0 < p -> n < m -> n * p < m * p. +Lemma Zmult_lt_compat_r n m p : 0 < p -> n < m -> n * p < m * p. Proof. - 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. - discriminate H. + apply Z.mul_lt_mono_pos_r. Qed. -Lemma Zmult_gt_compat_r : forall n m p:Z, p > 0 -> n > m -> n * p > m * p. +Lemma Zmult_gt_compat_r n m p : 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. + Z.swap_greater. apply Z.mul_lt_mono_pos_r. Qed. -Lemma Zmult_gt_0_lt_compat_r : - forall n m p:Z, p > 0 -> n < m -> n * p < m * p. +Lemma Zmult_gt_0_lt_compat_r n m p : p > 0 -> n < m -> n * p < m * p. Proof. - intros x y z; intros; apply Zmult_lt_compat_r; - [ apply Zgt_lt; assumption | assumption ]. + Z.swap_greater. apply Z.mul_lt_mono_pos_r. Qed. -Lemma Zmult_gt_0_le_compat_r : - forall n m p:Z, p > 0 -> n <= m -> n * p <= m * p. +Lemma Zmult_gt_0_le_compat_r n m p : 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. + Z.swap_greater. apply Z.mul_le_mono_pos_r. Qed. -Lemma Zmult_lt_0_le_compat_r : - forall n m p:Z, 0 < p -> n <= m -> n * p <= m * p. +Lemma Zmult_lt_0_le_compat_r n m p : 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. + apply Z.mul_le_mono_pos_r. Qed. -Lemma Zmult_gt_0_lt_compat_l : - forall n m p:Z, p > 0 -> n < m -> p * n < p * m. +Lemma Zmult_gt_0_lt_compat_l n m p : 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. + Z.swap_greater. apply Z.mul_lt_mono_pos_l. Qed. -Lemma Zmult_lt_compat_l : forall n m p:Z, 0 < p -> n < m -> p * n < p * m. +Lemma Zmult_lt_compat_l n m p : 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. + apply Z.mul_lt_mono_pos_l. Qed. -Lemma Zmult_gt_compat_l : forall n m p:Z, p > 0 -> n > m -> p * n > p * m. +Lemma Zmult_gt_compat_l n m p : 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. + Z.swap_greater. apply Z.mul_lt_mono_pos_l. Qed. -Lemma Zmult_ge_compat_r : forall n m p:Z, n >= m -> p >= 0 -> n * p >= m * p. +Lemma Zmult_ge_compat_r n m p : 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. + Z.swap_greater. intros. now apply Z.mul_le_mono_nonneg_r. Qed. -Lemma Zmult_ge_compat_l : forall n m p:Z, n >= m -> p >= 0 -> p * n >= p * m. +Lemma Zmult_ge_compat_l n m p : 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. + Z.swap_greater. intros. now apply Z.mul_le_mono_nonneg_l. Qed. -Lemma Zmult_ge_compat : - forall n m p q:Z, n >= p -> m >= q -> p >= 0 -> q >= 0 -> n * m >= p * q. +Lemma Zmult_ge_compat n m p q : + 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. + Z.swap_greater. intros. now apply Z.mul_le_mono_nonneg. Qed. -Lemma Zmult_le_compat : - forall n m p q:Z, n <= p -> m <= q -> 0 <= n -> 0 <= m -> n * m <= p * q. +Lemma Zmult_le_compat n m p q : + 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. now apply Z.mul_le_mono_nonneg. 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. +Lemma Zmult_gt_0_lt_reg_r n m p : p > 0 -> n * p < m * p -> n < m. Proof. - 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. - discriminate H. + Z.swap_greater. apply Z.mul_lt_mono_pos_r. Qed. -Lemma Zmult_lt_reg_r : forall n m p:Z, 0 < p -> n * p < m * p -> n < m. +Lemma Zmult_lt_reg_r n m p : 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. + apply Z.mul_lt_mono_pos_r. Qed. -Lemma Zmult_le_reg_r : forall n m p:Z, p > 0 -> n * p <= m * p -> n <= m. +Lemma Zmult_le_reg_r n m p : 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. - intro. rewrite H0 in Hz. contradiction (Zgt_irrefl 0). - assumption. + Z.swap_greater. apply Z.mul_le_mono_pos_r. Qed. -Lemma Zmult_lt_0_le_reg_r : forall n m p:Z, 0 < p -> n * p <= m * p -> n <= m. +Lemma Zmult_lt_0_le_reg_r n m p : 0 < p -> n * p <= m * p -> n <= m. Proof. - intros x y z; intros; apply Zmult_le_reg_r with z. - try apply Zlt_gt; assumption. - assumption. + apply Z.mul_le_mono_pos_r. Qed. - -Lemma Zmult_ge_reg_r : forall n m p:Z, p > 0 -> n * p >= m * p -> n >= m. +Lemma Zmult_ge_reg_r n m p : p > 0 -> n * p >= m * p -> n >= m. Proof. - intros a b c H1 H2; apply Zle_ge; apply Zmult_le_reg_r with c; trivial. - apply Zge_le; trivial. + Z.swap_greater. apply Z.mul_le_mono_pos_r. Qed. -Lemma Zmult_gt_reg_r : forall n m p:Z, p > 0 -> n * p > m * p -> n > m. +Lemma Zmult_gt_reg_r n m p : p > 0 -> n * p > m * p -> n > m. Proof. - intros a b c H1 H2; apply Zlt_gt; apply Zmult_gt_0_lt_reg_r with c; trivial. - apply Zgt_lt; trivial. + Z.swap_greater. apply Z.mul_lt_mono_pos_r. Qed. - -(** Compatibility of multiplication by a positive wrt to being positive *) - -Lemma Zmult_le_0_compat : forall n m:Z, 0 <= n -> 0 <= m -> 0 <= n * m. +Lemma Zmult_lt_compat n m p q : + 0 <= n < p -> 0 <= m < q -> n * m < p * q. Proof. - 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 (Hn,Hnp) (Hm,Hmq). now apply Z.mul_lt_mono_nonneg. Qed. -Lemma Zmult_gt_0_compat : forall n m:Z, n > 0 -> m > 0 -> n * m > 0. +Lemma Zmult_lt_compat2 n m p q : + 0 < n <= p -> 0 < m < q -> n * m < p * q. 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)). - rewrite Zcompare_mult_compat; trivial. - intros p H; discriminate H. + intros (Hn, Hnp) (Hm,Hmq). + apply Z.le_lt_trans with (p * m). + apply Z.mul_le_mono_pos_r; trivial. + apply Z.mul_lt_mono_pos_l; Z.order. Qed. -Lemma Zmult_lt_0_compat : forall n m:Z, 0 < n -> 0 < m -> 0 < n * m. +(** Compatibility of multiplication by a positive wrt to being positive *) + +Notation Zmult_le_0_compat := Z.mul_nonneg_nonneg (compat "8.3"). +Notation Zmult_lt_0_compat := Z.mul_pos_pos (compat "8.3"). +Notation Zmult_lt_O_compat := Z.mul_pos_pos (compat "8.3"). + +Lemma Zmult_gt_0_compat n m : n > 0 -> m > 0 -> n * m > 0. Proof. - intros a b apos bpos. - apply Zgt_lt. - apply Zmult_gt_0_compat; try apply Zlt_gt; assumption. + Z.swap_greater. apply Z.mul_pos_pos. Qed. -(** For compatibility *) -Notation Zmult_lt_O_compat := Zmult_lt_0_compat (only parsing). +(* To remove someday ... *) -Lemma Zmult_gt_0_le_0_compat : forall n m:Z, n > 0 -> 0 <= m -> 0 <= m * n. +Lemma Zmult_gt_0_le_0_compat n m : 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. + Z.swap_greater. intros. apply Z.mul_nonneg_nonneg. trivial. + now apply Z.lt_le_incl. 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. +Lemma Zmult_le_0_reg_r n m : 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 ]. + Z.swap_greater. apply Z.mul_nonneg_cancel_r. Qed. -Lemma Zmult_gt_0_lt_0_reg_r : forall n m:Z, n > 0 -> 0 < m * n -> 0 < m. +Lemma Zmult_lt_0_reg_r n m : 0 < n -> 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 ]. + apply Z.mul_pos_cancel_r. Qed. -Lemma Zmult_lt_0_reg_r : forall n m:Z, 0 < n -> 0 < m * n -> 0 < m. +Lemma Zmult_gt_0_lt_0_reg_r n m : n > 0 -> 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. + Z.swap_greater. apply Z.mul_pos_cancel_r. Qed. -Lemma Zmult_gt_0_reg_l : forall n m:Z, n > 0 -> n * m > 0 -> m > 0. +Lemma Zmult_gt_0_reg_l n m : 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. + Z.swap_greater. apply Z.mul_pos_cancel_l. Qed. (** ** Square *) (** Simplification of square wrt order *) -Lemma Zgt_square_simpl : - forall n m:Z, n >= 0 -> n * n > m * m -> n > m. +Lemma Zlt_square_simpl n m : 0 <= n -> m * m < n * n -> m < n. 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. + apply Z.square_lt_simpl_nonneg. Qed. -Lemma Zlt_square_simpl : - forall n m:Z, 0 <= n -> m * m < n * n -> m < n. +Lemma Zgt_square_simpl n m : n >= 0 -> n * n > m * m -> n > m. Proof. - intros x y H0 H1. - apply Zgt_lt. - apply Zgt_square_simpl; try apply Zle_ge; try apply Zlt_gt; assumption. + Z.swap_greater. apply Z.square_lt_simpl_nonneg. Qed. (** * 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. -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. -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. - assumption. - 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. -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. -Qed. +Notation Zle_plus_swap := Z.le_add_le_sub_r (compat "8.3"). +Notation Zlt_plus_swap := Z.lt_add_lt_sub_r (compat "8.3"). +Notation Zlt_minus_simpl_swap := Z.lt_sub_pos (compat "8.3"). -Lemma Zle_0_minus_le : forall n m:Z, 0 <= n - m -> m <= n. +Lemma Zeq_plus_swap n m p : n + p = m <-> n = m - p. Proof. - intros n m H; apply Zplus_le_reg_l with (p := - m); rewrite Zplus_opp_l; - rewrite Zplus_comm; exact H. + apply Z.add_move_r. Qed. -Lemma Zle_minus_le_0 : forall n m:Z, m <= n -> 0 <= n - m. +Lemma Zlt_0_minus_lt n m : 0 < n - m -> m < n. 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. + apply Z.lt_0_sub. Qed. -Lemma Zmult_lt_compat: - forall n m p q : Z, 0 <= n < p -> 0 <= m < q -> n * m < p * q. +Lemma Zle_0_minus_le n m : 0 <= n - m -> m <= n. Proof. - intros n m p q (H1, H2) (H3,H4). - assert (0<p) by (apply Zle_lt_trans with n; auto). - assert (0<q) by (apply Zle_lt_trans with m; auto). - case Zle_lt_or_eq with (1 := H1); intros H5; auto with zarith. - case Zle_lt_or_eq with (1 := H3); intros H6; auto with zarith. - apply Zlt_trans with (n * q). - apply Zmult_lt_compat_l; auto. - apply Zmult_lt_compat_r; auto with zarith. - rewrite <- H6; rewrite Zmult_0_r; apply Zmult_lt_0_compat; auto with zarith. - rewrite <- H5; simpl; apply Zmult_lt_0_compat; auto with zarith. + apply Z.le_0_sub. Qed. -Lemma Zmult_lt_compat2: - forall n m p q : Z, 0 < n <= p -> 0 < m < q -> n * m < p * q. +Lemma Zle_minus_le_0 n m : m <= n -> 0 <= n - m. Proof. - intros n m p q (H1, H2) (H3, H4). - apply Zle_lt_trans with (p * m). - apply Zmult_le_compat_r; auto. - apply Zlt_le_weak; auto. - apply Zmult_lt_compat_l; auto. - apply Zlt_le_trans with n; auto. + apply Z.le_0_sub. Qed. (** For compatibility *) diff --git a/theories/ZArith/Zpow_alt.v b/theories/ZArith/Zpow_alt.v new file mode 100644 index 00000000..f3eb63a8 --- /dev/null +++ b/theories/ZArith/Zpow_alt.v @@ -0,0 +1,83 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +Require Import BinInt. +Local Open Scope Z_scope. + +(** An alternative power function for Z *) + +(** This [Zpower_alt] is extensionnaly equal to [Z.pow], + but not convertible with it. The number of + multiplications is logarithmic instead of linear, but + these multiplications are bigger. Experimentally, it seems + that [Zpower_alt] is slightly quicker than [Z.pow] on average, + but can be quite slower on powers of 2. +*) + +Definition Zpower_alt n m := + match m with + | Z0 => 1 + | Zpos p => Pos.iter_op Z.mul p n + | Zneg p => 0 + end. + +Infix "^^" := Zpower_alt (at level 30, right associativity) : Z_scope. + +Lemma Piter_mul_acc : forall f, + (forall x y:Z, (f x)*y = f (x*y)) -> + forall p k, Pos.iter p f k = (Pos.iter p f 1)*k. +Proof. + intros f Hf. + induction p; simpl; intros. + - set (g := Pos.iter p f 1) in *. now rewrite !IHp, Hf, Z.mul_assoc. + - set (g := Pos.iter p f 1) in *. now rewrite !IHp, Z.mul_assoc. + - now rewrite Hf, Z.mul_1_l. +Qed. + +Lemma Piter_op_square : forall p a, + Pos.iter_op Z.mul p (a*a) = (Pos.iter_op Z.mul p a)*(Pos.iter_op Z.mul p a). +Proof. + induction p; simpl; intros; trivial. now rewrite IHp, Z.mul_shuffle1. +Qed. + +Lemma Zpower_equiv a b : a^^b = a^b. +Proof. + destruct b as [|p|p]; trivial. + unfold Zpower_alt, Z.pow, Z.pow_pos. + revert a. + induction p; simpl; intros. + - f_equal. + rewrite Piter_mul_acc. + now rewrite Piter_op_square, IHp. + intros. symmetry; apply Z.mul_assoc. + - rewrite Piter_mul_acc. + now rewrite Piter_op_square, IHp. + intros. symmetry; apply Z.mul_assoc. + - now Z.nzsimpl. +Qed. + +Lemma Zpower_alt_0_r n : n^^0 = 1. +Proof. reflexivity. Qed. + +Lemma Zpower_alt_succ_r a b : 0<=b -> a^^(Z.succ b) = a * a^^b. +Proof. + destruct b as [|b|b]; intros Hb; simpl. + - now Z.nzsimpl. + - now rewrite Pos.add_1_r, Pos.iter_op_succ by apply Z.mul_assoc. + - now elim Hb. +Qed. + +Lemma Zpower_alt_neg_r a b : b<0 -> a^^b = 0. +Proof. + now destruct b. +Qed. + +Lemma Zpower_alt_Ppow p q : (Zpos p)^^(Zpos q) = Zpos (p^q). +Proof. + now rewrite Zpower_equiv, Pos2Z.inj_pow. +Qed. diff --git a/theories/ZArith/Zpow_def.v b/theories/ZArith/Zpow_def.v index 620d6324..a1c60bf2 100644 --- a/theories/ZArith/Zpow_def.v +++ b/theories/ZArith/Zpow_def.v @@ -1,27 +1,31 @@ -Require Import ZArith_base. -Require Import Ring_theory. +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) -Open Local Scope Z_scope. +Require Import BinInt Ring_theory. +Local Open Scope Z_scope. -(** [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. +(** * Power functions over [Z] *) -Definition Zpower (x y:Z) := - match y with - | Zpos p => Zpower_pos x p - | Z0 => 1 - | Zneg p => 0 - end. +(** Nota : this file is mostly deprecated. The definition of [Z.pow] + and its usual properties are now provided by module [BinInt.Z]. *) -Lemma Zpower_theory : power_theory 1 Zmult (eq (A:=Z)) Z_of_N Zpower. +Notation Zpower_pos := Z.pow_pos (compat "8.3"). +Notation Zpower := Z.pow (compat "8.3"). +Notation Zpower_0_r := Z.pow_0_r (compat "8.3"). +Notation Zpower_succ_r := Z.pow_succ_r (compat "8.3"). +Notation Zpower_neg_r := Z.pow_neg_r (compat "8.3"). +Notation Zpower_Ppow := Pos2Z.inj_pow (compat "8.3"). + +Lemma Zpower_theory : power_theory 1 Z.mul (@eq Z) Z.of_N Z.pow. Proof. constructor. intros. destruct n;simpl;trivial. - unfold Zpower_pos. - assert (forall k, iter_pos p Z (fun x : Z => r * x) k = pow_pos Zmult r p*k). - induction p;simpl;intros;repeat rewrite IHp;trivial; - repeat rewrite Zmult_assoc;trivial. - rewrite H;rewrite Zmult_1_r;trivial. + unfold Z.pow_pos. + rewrite <- (Z.mul_1_r (pow_pos _ _ _)). generalize 1. + induction p; simpl; intros; rewrite ?IHp, ?Z.mul_assoc; trivial. Qed. - diff --git a/theories/ZArith/Zpow_facts.v b/theories/ZArith/Zpow_facts.v index 7879fe42..8ff641a3 100644 --- a/theories/ZArith/Zpow_facts.v +++ b/theories/ZArith/Zpow_facts.v @@ -1,298 +1,112 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zpow_facts.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - -Require Import ZArith_base. -Require Import ZArithRing. -Require Import Zcomplements. +Require Import ZArith_base ZArithRing Zcomplements Zdiv Znumtheory. Require Export Zpower. -Require Import Zdiv. -Require Import Znumtheory. -Open Local Scope Z_scope. +Local Open Scope Z_scope. -Lemma Zpower_pos_1_r: forall x, Zpower_pos x 1 = x. -Proof. - intros x; unfold Zpower_pos; simpl; auto with zarith. -Qed. +(** Properties of the power function over [Z] *) -Lemma Zpower_pos_1_l: forall p, Zpower_pos 1 p = 1. -Proof. - induction p. - (* xI *) - rewrite xI_succ_xO, <-Pplus_diag, Pplus_one_succ_l. - repeat rewrite Zpower_pos_is_exp. - rewrite Zpower_pos_1_r, IHp; auto. - (* xO *) - rewrite <- Pplus_diag. - repeat rewrite Zpower_pos_is_exp. - rewrite IHp; auto. - (* xH *) - rewrite Zpower_pos_1_r; auto. -Qed. +(** Nota: the usual properties of [Z.pow] are now already provided + by [BinInt.Z]. Only remain here some compatibility elements, + as well as more specific results about power and modulo and/or + primality. *) -Lemma Zpower_pos_0_l: forall p, Zpower_pos 0 p = 0. -Proof. - induction p. - change (xI p) with (1 + (xO p))%positive. - rewrite Zpower_pos_is_exp, Zpower_pos_1_r; auto. - rewrite <- Pplus_diag. - rewrite Zpower_pos_is_exp, IHp; auto. - rewrite Zpower_pos_1_r; auto. -Qed. +Lemma Zpower_pos_1_r x : Z.pow_pos x 1 = x. +Proof (Z.pow_1_r x). -Lemma Zpower_pos_pos: forall x p, - 0 < x -> 0 < Zpower_pos x p. -Proof. - induction p; intros. - (* xI *) - rewrite xI_succ_xO, <-Pplus_diag, Pplus_one_succ_l. - repeat rewrite Zpower_pos_is_exp. - rewrite Zpower_pos_1_r. - repeat apply Zmult_lt_0_compat; auto. - (* xO *) - rewrite <- Pplus_diag. - repeat rewrite Zpower_pos_is_exp. - repeat apply Zmult_lt_0_compat; auto. - (* xH *) - rewrite Zpower_pos_1_r; auto. -Qed. +Lemma Zpower_pos_1_l p : Z.pow_pos 1 p = 1. +Proof. now apply (Z.pow_1_l (Zpos p)). Qed. +Lemma Zpower_pos_0_l p : Z.pow_pos 0 p = 0. +Proof. now apply (Z.pow_0_l (Zpos p)). Qed. -Theorem Zpower_1_r: forall z, z^1 = z. -Proof. - exact Zpower_pos_1_r. -Qed. - -Theorem Zpower_1_l: forall z, 0 <= z -> 1^z = 1. -Proof. - destruct z; simpl; auto. - intros; apply Zpower_pos_1_l. - intros; compute in H; elim H; auto. -Qed. +Lemma Zpower_pos_pos x p : 0 < x -> 0 < Z.pow_pos x p. +Proof. intros. now apply (Z.pow_pos_nonneg x (Zpos p)). Qed. -Theorem Zpower_0_l: forall z, z<>0 -> 0^z = 0. -Proof. - destruct z; simpl; auto with zarith. - intros; apply Zpower_pos_0_l. -Qed. +Notation Zpower_1_r := Z.pow_1_r (compat "8.3"). +Notation Zpower_1_l := Z.pow_1_l (compat "8.3"). +Notation Zpower_0_l := Z.pow_0_l' (compat "8.3"). +Notation Zpower_0_r := Z.pow_0_r (compat "8.3"). +Notation Zpower_2 := Z.pow_2_r (compat "8.3"). +Notation Zpower_gt_0 := Z.pow_pos_nonneg (compat "8.3"). +Notation Zpower_ge_0 := Z.pow_nonneg (compat "8.3"). +Notation Zpower_Zabs := Z.abs_pow (compat "8.3"). +Notation Zpower_Zsucc := Z.pow_succ_r (compat "8.3"). +Notation Zpower_mult := Z.pow_mul_r (compat "8.3"). +Notation Zpower_le_monotone2 := Z.pow_le_mono_r (compat "8.3"). -Theorem Zpower_0_r: forall z, z^0 = 1. -Proof. - simpl; auto. -Qed. - -Theorem Zpower_2: forall z, z^2 = z * z. -Proof. - intros; ring. -Qed. - -Theorem Zpower_gt_0: forall x y, - 0 < x -> 0 <= y -> 0 < x^y. -Proof. - destruct y; simpl; auto with zarith. - intros; apply Zpower_pos_pos; auto. - intros; compute in H0; elim H0; auto. -Qed. - -Theorem Zpower_Zabs: forall a b, Zabs (a^b) = (Zabs a)^b. -Proof. - intros a b; case (Zle_or_lt 0 b). - intros Hb; pattern b; apply natlike_ind; auto with zarith. - intros x Hx Hx1; unfold Zsucc. - (repeat rewrite Zpower_exp); auto with zarith. - rewrite Zabs_Zmult; rewrite Hx1. - f_equal; auto. - replace (a ^ 1) with a; auto. - simpl; unfold Zpower_pos; simpl; rewrite Zmult_1_r; auto. - simpl; unfold Zpower_pos; simpl; rewrite Zmult_1_r; auto. - case b; simpl; auto with zarith. - intros p Hp; discriminate. -Qed. - -Theorem Zpower_Zsucc: forall p n, 0 <= n -> p^(Zsucc n) = p * p^n. -Proof. - intros p n H. - unfold Zsucc; rewrite Zpower_exp; auto with zarith. - rewrite Zpower_1_r; apply Zmult_comm. -Qed. - -Theorem Zpower_mult: forall p q r, 0 <= q -> 0 <= r -> p^(q*r) = (p^q)^r. -Proof. - intros p q r H1 H2; generalize H2; pattern r; apply natlike_ind; auto. - intros H3; rewrite Zmult_0_r; repeat rewrite Zpower_exp_0; auto. - intros r1 H3 H4 H5. - unfold Zsucc; rewrite Zpower_exp; auto with zarith. - rewrite <- H4; try rewrite Zpower_1_r; try rewrite <- Zpower_exp; try f_equal; auto with zarith. - ring. - apply Zle_ge; replace 0 with (0 * r1); try apply Zmult_le_compat_r; auto. -Qed. - -Theorem Zpower_le_monotone: forall a b c, +Theorem Zpower_le_monotone a b c : 0 < a -> 0 <= b <= c -> a^b <= a^c. -Proof. - intros a b c H (H1, H2). - rewrite <- (Zmult_1_r (a ^ b)); replace c with (b + (c - b)); auto with zarith. - rewrite Zpower_exp; auto with zarith. - apply Zmult_le_compat_l; auto with zarith. - assert (0 < a ^ (c - b)); auto with zarith. - apply Zpower_gt_0; auto with zarith. - apply Zlt_le_weak; apply Zpower_gt_0; auto with zarith. -Qed. +Proof. intros. now apply Z.pow_le_mono_r. Qed. -Theorem Zpower_lt_monotone: forall a b c, +Theorem Zpower_lt_monotone a b c : 1 < a -> 0 <= b < c -> a^b < a^c. -Proof. - intros a b c H (H1, H2). - rewrite <- (Zmult_1_r (a ^ b)); replace c with (b + (c - b)); auto with zarith. - rewrite Zpower_exp; auto with zarith. - apply Zmult_lt_compat_l; auto with zarith. - apply Zpower_gt_0; auto with zarith. - assert (0 < a ^ (c - b)); auto with zarith. - apply Zpower_gt_0; auto with zarith. - apply Zlt_le_trans with (a ^1); auto with zarith. - rewrite Zpower_1_r; auto with zarith. - apply Zpower_le_monotone; auto with zarith. -Qed. - -Theorem Zpower_gt_1 : forall x y, - 1 < x -> 0 < y -> 1 < x^y. -Proof. - intros x y H1 H2. - replace 1 with (x ^ 0) by apply Zpower_0_r. - apply Zpower_lt_monotone; auto with zarith. -Qed. +Proof. intros. apply Z.pow_lt_mono_r; auto with zarith. Qed. -Theorem Zpower_ge_0: forall x y, 0 <= x -> 0 <= x^y. -Proof. - intros x y; case y; auto with zarith. - simpl ; auto with zarith. - intros p H1; assert (H: 0 <= Zpos p); auto with zarith. - generalize H; pattern (Zpos p); apply natlike_ind; auto with zarith. - intros p1 H2 H3 _; unfold Zsucc; rewrite Zpower_exp; simpl; auto with zarith. - apply Zmult_le_0_compat; auto with zarith. - generalize H1; case x; compute; intros; auto; try discriminate. -Qed. - -Theorem Zpower_le_monotone2: - forall a b c, 0 < a -> b <= c -> a^b <= a^c. -Proof. - intros a b c H H2. - destruct (Z_le_gt_dec 0 b). - apply Zpower_le_monotone; auto. - replace (a^b) with 0. - destruct (Z_le_gt_dec 0 c). - destruct (Zle_lt_or_eq _ _ z0). - apply Zlt_le_weak;apply Zpower_gt_0;trivial. - rewrite <- H0;simpl;auto with zarith. - replace (a^c) with 0. auto with zarith. - destruct c;trivial;unfold Zgt in z0;discriminate z0. - destruct b;trivial;unfold Zgt in z;discriminate z. -Qed. +Theorem Zpower_gt_1 x y : 1 < x -> 0 < y -> 1 < x^y. +Proof. apply Z.pow_gt_1. Qed. -Theorem Zmult_power: forall p q r, 0 <= r -> - (p*q)^r = p^r * q^r. -Proof. - intros p q r H1; generalize H1; pattern r; apply natlike_ind; auto. - clear r H1; intros r H1 H2 H3. - unfold Zsucc; rewrite Zpower_exp; auto with zarith. - rewrite H2; repeat rewrite Zpower_exp; auto with zarith; ring. -Qed. +Theorem Zmult_power p q r : 0 <= r -> (p*q)^r = p^r * q^r. +Proof. intros. apply Z.pow_mul_l. Qed. -Hint Resolve Zpower_ge_0 Zpower_gt_0: zarith. +Hint Resolve Z.pow_nonneg Z.pow_pos_nonneg : zarith. -Theorem Zpower_le_monotone3: forall a b c, +Theorem Zpower_le_monotone3 a b c : 0 <= c -> 0 <= a <= b -> a^c <= b^c. -Proof. - intros a b c H (H1, H2). - generalize H; pattern c; apply natlike_ind; auto. - intros x HH HH1 _; unfold Zsucc; repeat rewrite Zpower_exp; auto with zarith. - repeat rewrite Zpower_1_r. - apply Zle_trans with (a^x * b); auto with zarith. -Qed. +Proof. intros. now apply Z.pow_le_mono_l. Qed. -Lemma Zpower_le_monotone_inv: forall a b c, +Lemma Zpower_le_monotone_inv a b c : 1 < a -> 0 < b -> a^b <= a^c -> b <= c. Proof. - intros a b c H H0 H1. - destruct (Z_le_gt_dec b c);trivial. - assert (2 <= a^b). - apply Zle_trans with (2^b). - pattern 2 at 1;replace 2 with (2^1);trivial. - apply Zpower_le_monotone;auto with zarith. - apply Zpower_le_monotone3;auto with zarith. - assert (c > 0). - destruct (Z_le_gt_dec 0 c);trivial. - destruct (Zle_lt_or_eq _ _ z0);auto with zarith. - rewrite <- H3 in H1;simpl in H1; exfalso;omega. - destruct c;try discriminate z0. simpl in H1. exfalso;omega. - assert (H4 := Zpower_lt_monotone a c b H). exfalso;omega. + intros Ha Hb H. apply (Z.pow_le_mono_r_iff a); trivial. + apply Z.lt_le_incl; apply (Z.pow_gt_1 a); trivial. + apply Z.lt_le_trans with (a^b); trivial. now apply Z.pow_gt_1. Qed. -Theorem Zpower_nat_Zpower: forall p q, 0 <= q -> - p^q = Zpower_nat p (Zabs_nat q). -Proof. - intros p1 q1; case q1; simpl. - intros _; exact (refl_equal _). - intros p2 _; apply Zpower_pos_nat. - intros p2 H1; case H1; auto. -Qed. +Notation Zpower_nat_Zpower := Zpower_nat_Zpower (only parsing). -Theorem Zpower2_lt_lin: forall n, 0 <= n -> n < 2^n. -Proof. - intros n; apply (natlike_ind (fun n => n < 2 ^n)); clear n. - simpl; auto with zarith. - intros n H1 H2; unfold Zsucc. - case (Zle_lt_or_eq _ _ H1); clear H1; intros H1. - apply Zle_lt_trans with (n + n); auto with zarith. - rewrite Zpower_exp; auto with zarith. - rewrite Zpower_1_r. - assert (tmp: forall p, p * 2 = p + p); intros; try ring; - rewrite tmp; auto with zarith. - subst n; simpl; unfold Zpower_pos; simpl; auto with zarith. -Qed. +Theorem Zpower2_lt_lin n : 0 <= n -> n < 2^n. +Proof. intros. now apply Z.pow_gt_lin_r. Qed. -Theorem Zpower2_le_lin: forall n, 0 <= n -> n <= 2^n. -Proof. - intros; apply Zlt_le_weak; apply Zpower2_lt_lin; auto. -Qed. +Theorem Zpower2_le_lin n : 0 <= n -> n <= 2^n. +Proof. intros. apply Z.lt_le_incl. now apply Z.pow_gt_lin_r. Qed. -Lemma Zpower2_Psize : - forall n p, Zpos p < 2^(Z_of_nat n) <-> (Psize p <= n)%nat. +Lemma Zpower2_Psize n p : + Zpos p < 2^(Z.of_nat n) <-> (Pos.size_nat p <= n)%nat. Proof. - induction n. - destruct p; split; intros H; discriminate H || inversion H. - destruct p; simpl Psize. - rewrite inj_S, Zpower_Zsucc; auto with zarith. - rewrite Zpos_xI; specialize IHn with p; omega. - rewrite inj_S, Zpower_Zsucc; auto with zarith. - rewrite Zpos_xO; specialize IHn with p; omega. - split; auto with arith. - intros _; apply Zpower_gt_1; auto with zarith. - rewrite inj_S; generalize (Zle_0_nat n); omega. + revert p; induction n. + destruct p; now split. + assert (Hn := Nat2Z.is_nonneg n). + destruct p; simpl Pos.size_nat. + - specialize IHn with p. + rewrite Pos2Z.inj_xI, Nat2Z.inj_succ, Z.pow_succ_r; omega. + - specialize IHn with p. + rewrite Pos2Z.inj_xO, Nat2Z.inj_succ, Z.pow_succ_r; omega. + - split; auto with zarith. + intros _. apply Z.pow_gt_1. easy. + now rewrite Nat2Z.inj_succ, Z.lt_succ_r. Qed. -(** * Zpower and modulo *) +(** * Z.pow and modulo *) -Theorem Zpower_mod: forall p q n, 0 < n -> - (p^q) mod n = ((p mod n)^q) mod n. +Theorem Zpower_mod p q n : + 0 < n -> (p^q) mod n = ((p mod n)^q) mod n. Proof. - intros p q n Hn; case (Zle_or_lt 0 q); intros H1. - generalize H1; pattern q; apply natlike_ind; auto. - intros q1 Hq1 Rec _; unfold Zsucc; repeat rewrite Zpower_exp; repeat rewrite Zpower_1_r; auto with zarith. - rewrite (fun x => (Zmult_mod x p)); try rewrite Rec; auto with zarith. - rewrite (fun x y => (Zmult_mod (x ^y))); try f_equal; auto with zarith. - f_equal; auto; apply sym_equal; apply Zmod_mod; auto with zarith. - generalize H1; case q; simpl; auto. - intros; discriminate. + intros Hn; destruct (Z.le_gt_cases 0 q) as [H1|H1]. + - pattern q; apply natlike_ind; trivial. + clear q H1. intros q Hq Rec. rewrite !Z.pow_succ_r; trivial. + rewrite Z.mul_mod_idemp_l; auto with zarith. + rewrite Z.mul_mod, Rec, <- Z.mul_mod; auto with zarith. + - rewrite !Z.pow_neg_r; auto with zarith. Qed. -(** A direct way to compute Zpower modulo **) +(** A direct way to compute Z.pow modulo **) Fixpoint Zpow_mod_pos (a: Z)(m: positive)(n : Z) : Z := match m with @@ -313,153 +127,113 @@ Fixpoint Zpow_mod_pos (a: Z)(m: positive)(n : Z) : Z := Definition Zpow_mod a m n := match m with - | 0 => 1 + | 0 => 1 mod n | Zpos p => Zpow_mod_pos a p n | Zneg p => 0 end. -Theorem Zpow_mod_pos_correct: forall a m n, 0 < n -> - Zpow_mod_pos a m n = (Zpower_pos a m) mod n. +Theorem Zpow_mod_pos_correct a m n : + n <> 0 -> Zpow_mod_pos a m n = (Z.pow_pos a m) mod n. Proof. - intros a m; elim m; simpl; auto. - intros p Rec n H1; rewrite xI_succ_xO, Pplus_one_succ_r, <-Pplus_diag; auto. - repeat rewrite Zpower_pos_is_exp; auto. - repeat rewrite Rec; auto. - rewrite Zpower_pos_1_r. - repeat rewrite (fun x => (Zmult_mod x a)); auto with zarith. - rewrite (Zmult_mod (Zpower_pos a p)); auto with zarith. - case (Zpower_pos a p mod n); auto. - intros p Rec n H1; rewrite <- Pplus_diag; auto. - repeat rewrite Zpower_pos_is_exp; auto. - repeat rewrite Rec; auto. - rewrite (Zmult_mod (Zpower_pos a p)); auto with zarith. - case (Zpower_pos a p mod n); auto. - unfold Zpower_pos; simpl; rewrite Zmult_1_r; auto with zarith. + intros Hn. induction m. + - rewrite Pos.xI_succ_xO at 2. rewrite <- Pos.add_1_r, <- Pos.add_diag. + rewrite 2 Zpower_pos_is_exp, Zpower_pos_1_r. + rewrite Z.mul_mod, (Z.mul_mod (Z.pow_pos a m)) by trivial. + rewrite <- IHm, <- Z.mul_mod by trivial. + simpl. now destruct (Zpow_mod_pos a m n). + - rewrite <- Pos.add_diag at 2. + rewrite Zpower_pos_is_exp. + rewrite Z.mul_mod by trivial. + rewrite <- IHm. + simpl. now destruct (Zpow_mod_pos a m n). + - now rewrite Zpower_pos_1_r. Qed. -Theorem Zpow_mod_correct: forall a m n, 1 < n -> 0 <= m -> - Zpow_mod a m n = (a ^ m) mod n. +Theorem Zpow_mod_correct a m n : + n <> 0 -> Zpow_mod a m n = (a ^ m) mod n. Proof. - intros a m n; case m; simpl. - intros; apply sym_equal; apply Zmod_small; auto with zarith. - intros; apply Zpow_mod_pos_correct; auto with zarith. - intros p H H1; case H1; auto. + intros Hn. destruct m; simpl. + - trivial. + - apply Zpow_mod_pos_correct; auto with zarith. + - rewrite Z.mod_0_l; auto with zarith. Qed. (* Complements about power and number theory. *) -Lemma Zpower_divide: forall p q, 0 < q -> (p | p ^ q). +Lemma Zpower_divide p q : 0 < q -> (p | p ^ q). Proof. - intros p q H; exists (p ^(q - 1)). - pattern p at 3; rewrite <- (Zpower_1_r p); rewrite <- Zpower_exp; try f_equal; auto with zarith. + exists (p^(q - 1)). + rewrite Z.mul_comm, <- Z.pow_succ_r; f_equal; auto with zarith. Qed. -Theorem rel_prime_Zpower_r: forall i p q, 0 < i -> - rel_prime p q -> rel_prime p (q^i). +Theorem rel_prime_Zpower_r i p q : + 0 <= i -> rel_prime p q -> rel_prime p (q^i). Proof. - intros i p q Hi Hpq; generalize Hi; pattern i; apply natlike_ind; auto with zarith; clear i Hi. - intros H; contradict H; auto with zarith. - intros i Hi Rec _; rewrite Zpower_Zsucc; auto. + intros Hi Hpq; pattern i; apply natlike_ind; auto with zarith. + simpl. apply rel_prime_sym, rel_prime_1. + clear i Hi. intros i Hi Rec; rewrite Z.pow_succ_r; auto. apply rel_prime_mult; auto. - case Zle_lt_or_eq with (1 := Hi); intros Hi1; subst; auto. - rewrite Zpower_0_r; apply rel_prime_sym; apply rel_prime_1. Qed. -Theorem rel_prime_Zpower: forall i j p q, 0 <= i -> 0 <= j -> - rel_prime p q -> rel_prime (p^i) (q^j). +Theorem rel_prime_Zpower i j p q : + 0 <= i -> 0 <= j -> rel_prime p q -> rel_prime (p^i) (q^j). Proof. - intros i j p q Hi; generalize Hi j p q; pattern i; apply natlike_ind; auto with zarith; clear i Hi j p q. - intros _ j p q H H1; rewrite Zpower_0_r; apply rel_prime_1. - intros n Hn Rec _ j p q Hj Hpq. - rewrite Zpower_Zsucc; auto. - case Zle_lt_or_eq with (1 := Hj); intros Hj1; subst. - apply rel_prime_sym; apply rel_prime_mult; auto. - apply rel_prime_sym; apply rel_prime_Zpower_r; auto with arith. - apply rel_prime_sym; apply Rec; auto. - rewrite Zpower_0_r; apply rel_prime_sym; apply rel_prime_1. + intros Hi Hj H. apply rel_prime_Zpower_r; trivial. + apply rel_prime_sym. apply rel_prime_Zpower_r; trivial. + now apply rel_prime_sym. Qed. -Theorem prime_power_prime: forall p q n, 0 <= n -> - prime p -> prime q -> (p | q^n) -> p = q. +Theorem prime_power_prime p q n : + 0 <= n -> prime p -> prime q -> (p | q^n) -> p = q. Proof. - intros p q n Hn Hp Hq; pattern n; apply natlike_ind; auto; clear n Hn. - rewrite Zpower_0_r; intros. - assert (2<=p) by (apply prime_ge_2; auto). - assert (p<=1) by (apply Zdivide_le; auto with zarith). - omega. - intros n1 H H1. - unfold Zsucc; rewrite Zpower_exp; try rewrite Zpower_1_r; auto with zarith. - assert (2<=p) by (apply prime_ge_2; auto). - assert (2<=q) by (apply prime_ge_2; auto). - intros H3; case prime_mult with (2 := H3); auto. - intros; apply prime_div_prime; auto. + intros Hn Hp Hq; pattern n; apply natlike_ind; auto; clear n Hn. + - simpl; intros. + assert (2<=p) by (apply prime_ge_2; auto). + assert (p<=1) by (apply Z.divide_pos_le; auto with zarith). + omega. + - intros n Hn Rec. + rewrite Z.pow_succ_r by trivial. intros. + assert (2<=p) by (apply prime_ge_2; auto). + assert (2<=q) by (apply prime_ge_2; auto). + destruct prime_mult with (2 := H); auto. + apply prime_div_prime; auto. Qed. -Theorem Zdivide_power_2: forall x p n, 0 <= n -> 0 <= x -> prime p -> - (x | p^n) -> exists m, x = p^m. +Theorem Zdivide_power_2 x p n : + 0 <= n -> 0 <= x -> prime p -> (x | p^n) -> exists m, x = p^m. Proof. - intros x p n Hn Hx; revert p n Hn; generalize Hx. + intros Hn Hx; revert p n Hn. generalize Hx. pattern x; apply Z_lt_induction; auto. clear x Hx; intros x IH Hx p n Hn Hp H. - case Zle_lt_or_eq with (1 := Hx); auto; clear Hx; intros Hx; subst. - case (Zle_lt_or_eq 1 x); auto with zarith; clear Hx; intros Hx; subst. + Z.le_elim Hx; subst. + apply Z.le_succ_l in Hx; simpl in Hx. + Z.le_elim Hx; subst. (* x > 1 *) - case (prime_dec x); intros H2. - exists 1; rewrite Zpower_1_r; apply prime_power_prime with n; auto. - case not_prime_divide with (2 := H2); auto. - intros p1 ((H3, H4), (q1, Hq1)); subst. - case (IH p1) with p n; auto with zarith. - apply Zdivide_trans with (2 := H); exists q1; auto with zarith. - intros r1 Hr1. - case (IH q1) with p n; auto with zarith. - case (Zle_lt_or_eq 0 q1). - apply Zmult_le_0_reg_r with p1; auto with zarith. + case (prime_dec x); intros Hpr. + exists 1; rewrite Z.pow_1_r; apply prime_power_prime with n; auto. + case not_prime_divide with (2 := Hpr); auto. + intros p1 ((Hp1, Hpq1),(q1,->)). + assert (Hq1 : 0 < q1) by (apply Z.mul_lt_mono_pos_r with p1; auto with zarith). + destruct (IH p1) with p n as (r1,Hr1); auto with zarith. + transitivity (q1 * p1); trivial. exists q1; auto with zarith. + destruct (IH q1) with p n as (r2,Hr2); auto with zarith. split; auto with zarith. - pattern q1 at 1; replace q1 with (q1 * 1); auto with zarith. - apply Zmult_lt_compat_l; auto with zarith. - intros H5; subst; contradict Hx; auto with zarith. - apply Zmult_le_0_reg_r with p1; auto with zarith. - apply Zdivide_trans with (2 := H); exists p1; auto with zarith. - intros r2 Hr2; exists (r2 + r1); subst. - apply sym_equal; apply Zpower_exp. - generalize Hx; case r2; simpl; auto with zarith. - intros; red; simpl; intros; discriminate. - generalize H3; case r1; simpl; auto with zarith. - intros; red; simpl; intros; discriminate. + rewrite <- (Z.mul_1_r q1) at 1. + apply Z.mul_lt_mono_pos_l; auto with zarith. + transitivity (q1 * p1); trivial. exists p1; auto with zarith. + exists (r2 + r1); subst. + symmetry. apply Z.pow_add_r. + generalize Hq1; case r2; now auto with zarith. + generalize Hp1; case r1; now auto with zarith. (* x = 1 *) - exists 0; rewrite Zpower_0_r; auto. + exists 0; rewrite Z.pow_0_r; auto. (* x = 0 *) - exists n; destruct H; rewrite Zmult_0_r in H; auto. + exists n; destruct H; rewrite Z.mul_0_r in H; auto. Qed. -(** * Zsquare: a direct definition of [z^2] *) - -Fixpoint Psquare (p: positive): positive := - match p with - | xH => xH - | xO p => xO (xO (Psquare p)) - | xI p => xI (xO (Pplus (Psquare p) p)) - end. - -Definition Zsquare p := - match p with - | Z0 => Z0 - | Zpos p => Zpos (Psquare p) - | Zneg p => Zpos (Psquare p) - end. - -Theorem Psquare_correct: forall p, Psquare p = (p * p)%positive. -Proof. - induction p; simpl; auto; f_equal; rewrite IHp. - apply trans_equal with (xO p + xO (p*p))%positive; auto. - rewrite (Pplus_comm (xO p)); auto. - rewrite Pmult_xI_permute_r; rewrite Pplus_assoc. - f_equal; auto. - symmetry; apply Pplus_diag. - symmetry; apply Pmult_xO_permute_r. -Qed. +(** * Z.square: a direct definition of [z^2] *) -Theorem Zsquare_correct: forall p, Zsquare p = p * p. -Proof. - intro p; case p; simpl; auto; intros p1; rewrite Psquare_correct; auto. -Qed. +Notation Psquare := Pos.square (compat "8.3"). +Notation Zsquare := Z.square (compat "8.3"). +Notation Psquare_correct := Pos.square_spec (compat "8.3"). +Notation Zsquare_correct := Z.square_spec (compat "8.3"). diff --git a/theories/ZArith/Zpower.v b/theories/ZArith/Zpower.v index 038748b5..0d9b08d6 100644 --- a/theories/ZArith/Zpower.v +++ b/theories/ZArith/Zpower.v @@ -1,79 +1,89 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zpower.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - -Require Import Wf_nat. -Require Import ZArith_base. +Require Import Wf_nat ZArith_base Omega Zcomplements. Require Export Zpow_def. -Require Import Omega. -Require Import Zcomplements. -Open Local Scope Z_scope. +Local Open Scope Z_scope. + +(** * Power functions over [Z] *) -Infix "^" := Zpower : Z_scope. +(** Nota : this file is mostly deprecated. The definition of [Z.pow] + and its usual properties are now provided by module [BinInt.Z]. + Powers of 2 are also available there (see [Z.shiftl] and [Z.shiftr]). + Only remain here: + - [Zpower_nat] : a power function with a [nat] exponent + - old-style powers of two, such as [two_p] + - [Zdiv_rest] : a division + modulo when the divisor is a power of 2 +*) -(** * 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. +Definition Zpower_nat (z:Z) (n:nat) := nat_iter n (Z.mul z) 1. + +Lemma Zpower_nat_0_r z : Zpower_nat z 0 = 1. +Proof. reflexivity. Qed. + +Lemma Zpower_nat_succ_r n z : Zpower_nat z (S n) = z * (Zpower_nat z n). +Proof. reflexivity. Qed. (** [Zpower_nat_is_exp] says [Zpower_nat] is a morphism for - [plus : nat->nat] and [Zmult : Z->Z] *) + [plus : nat->nat->nat] and [Z.mul : Z->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 ]. + induction n. + - intros. now rewrite Zpower_nat_0_r, Z.mul_1_l. + - intros. simpl. now rewrite 2 Zpower_nat_succ_r, IHn, Z.mul_assoc. +Qed. + +(** Conversions between powers of unary and binary integers *) + +Lemma Zpower_pos_nat (z : Z) (p : positive) : + Z.pow_pos z p = Zpower_nat z (Pos.to_nat p). +Proof. + apply Pos2Nat.inj_iter. Qed. -(** This theorem shows that powers of unary and binary integers - are the same thing, modulo the function convert : [positive -> nat] *) +Lemma Zpower_nat_Z (z : Z) (n : nat) : + Zpower_nat z n = z ^ (Z.of_nat n). +Proof. + induction n. trivial. + rewrite Zpower_nat_succ_r, Nat2Z.inj_succ, Z.pow_succ_r. + now f_equal. + apply Nat2Z.is_nonneg. +Qed. -Lemma Zpower_pos_nat : - forall (z:Z) (p:positive), Zpower_pos z p = Zpower_nat z (nat_of_P p). +Theorem Zpower_nat_Zpower z n : 0 <= n -> + z^n = Zpower_nat z (Z.abs_nat n). Proof. - intros; unfold Zpower_pos in |- *; unfold Zpower_nat in |- *; - apply iter_nat_of_P. + intros. now rewrite Zpower_nat_Z, Zabs2Nat.id_abs, Z.abs_eq. 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] *) +(** The function [(Z.pow_pos z)] is a morphism + for [Pos.add : positive->positive->positive] and [Z.mul : Z->Z->Z] *) -Lemma Zpower_pos_is_exp : - forall (n m:positive) (z:Z), - Zpower_pos z (n + m) = Zpower_pos z n * Zpower_pos z m. +Lemma Zpower_pos_is_exp (n m : positive)(z:Z) : + Z.pow_pos z (n + m) = Z.pow_pos z n * Z.pow_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. + now apply (Z.pow_add_r z (Zpos n) (Zpos m)). Qed. Hint Immediate Zpower_nat_is_exp Zpower_pos_is_exp : zarith. -Hint Unfold Zpower_pos Zpower_nat: zarith. +Hint Unfold Z.pow_pos Zpower_nat: zarith. -Theorem Zpower_exp : - forall x n m:Z, n >= 0 -> m >= 0 -> x ^ (n + m) = x ^ n * x ^ m. +Theorem Zpower_exp x n m : + n >= 0 -> m >= 0 -> x ^ (n + m) = x ^ n * x ^ m. Proof. - destruct n; destruct m; auto with zarith. - simpl; intros; apply Zred_factor0. - simpl; auto with zarith. - intros; compute in H0; elim H0; auto. - intros; compute in H; elim H; auto. + Z.swap_greater. apply Z.pow_add_r. Qed. Section Powers_of_2. @@ -81,178 +91,137 @@ Section Powers_of_2. (** * 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 *) + calculus is possible. [shift n m] computes [2^n * m], i.e. + [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_nat (n:nat) (z:positive) := nat_iter n xO z. + Definition shift_pos (n z:positive) := Pos.iter n xO z. Definition shift (n:Z) (z:positive) := match n with | Z0 => z - | Zpos p => iter_pos p positive xO z + | Zpos p => Pos.iter p 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. + Definition two_p (x:Z) := + match x with + | Z0 => 1 + | Zpos y => two_power_pos y + | Zneg y => 0 + end. + + (** Equivalence with notions defined in BinInt *) + + Lemma shift_nat_equiv n p : shift_nat n p = Pos.shiftl_nat p n. + Proof. reflexivity. Qed. + + Lemma shift_pos_equiv n p : shift_pos n p = Pos.shiftl p (Npos n). + Proof. reflexivity. Qed. + + Lemma shift_equiv n p : 0<=n -> Zpos (shift n p) = Z.shiftl (Zpos p) n. Proof. - intro; simpl in |- *; apply refl_equal. + destruct n. + - trivial. + - simpl; intros. now apply Pos.iter_swap_gen. + - now destruct 1. Qed. - Lemma shift_nat_plus : - forall (n m:nat) (x:positive), - shift_nat (n + m) x = shift_nat n (shift_nat m x). + Lemma two_power_nat_equiv n : two_power_nat n = 2 ^ (Z.of_nat n). Proof. - intros; unfold shift_nat in |- *; apply iter_nat_plus. + induction n. + - trivial. + - now rewrite Nat2Z.inj_succ, Z.pow_succ_r, <- IHn by apply Nat2Z.is_nonneg. Qed. - Theorem shift_nat_correct : - forall (n:nat) (x:positive), Zpos (shift_nat n x) = Zpower_nat 2 n * Zpos x. + Lemma two_power_pos_equiv p : two_power_pos p = 2 ^ Zpos p. 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 ] ]. + now apply Pos.iter_swap_gen. Qed. - Theorem two_power_nat_correct : - forall n:nat, two_power_nat n = Zpower_nat 2 n. + Lemma two_p_equiv x : two_p x = 2 ^ x. Proof. - intro n. - unfold two_power_nat in |- *. - rewrite (shift_nat_correct n). - omega. + destruct x; trivial. apply two_power_pos_equiv. 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. + (** Properties of these old versions of powers of two *) + + Lemma two_power_nat_S n : two_power_nat (S n) = 2 * two_power_nat n. + Proof. reflexivity. Qed. + + Lemma shift_nat_plus n m x : + shift_nat (n + m) x = shift_nat n (shift_nat m x). Proof. - unfold shift_pos in |- *. - unfold shift_nat in |- *. - intros; apply iter_nat_of_P. + apply iter_nat_plus. Qed. - Lemma two_power_pos_nat : - forall p:positive, two_power_pos p = two_power_nat (nat_of_P p). + Theorem shift_nat_correct n x : + Zpos (shift_nat n x) = Zpower_nat 2 n * Zpos x. Proof. - intro; unfold two_power_pos in |- *; unfold two_power_nat in |- *. - apply f_equal with (f := Zpos). - apply shift_pos_nat. + induction n. + - trivial. + - now rewrite Zpower_nat_succ_r, <- Z.mul_assoc, <- IHn. Qed. - (** Then we deduce that [two_power_pos] is also correct *) + Theorem two_power_nat_correct n : two_power_nat n = Zpower_nat 2 n. + Proof. + now rewrite two_power_nat_equiv, Zpower_nat_Z. + Qed. - Theorem shift_pos_correct : - forall p x:positive, Zpos (shift_pos p x) = Zpower_pos 2 p * Zpos x. + Lemma shift_pos_nat p x : shift_pos p x = shift_nat (Pos.to_nat p) x. Proof. - intros. - rewrite (shift_pos_nat p x). - rewrite (Zpower_pos_nat 2 p). - apply shift_nat_correct. + apply Pos2Nat.inj_iter. Qed. - Theorem two_power_pos_correct : - forall x:positive, two_power_pos x = Zpower_pos 2 x. + Lemma two_power_pos_nat p : two_power_pos p = two_power_nat (Pos.to_nat p). Proof. - intro. - rewrite two_power_pos_nat. - rewrite Zpower_pos_nat. - apply two_power_nat_correct. + unfold two_power_pos. now rewrite shift_pos_nat. Qed. - (** Some consequences *) + Theorem shift_pos_correct p x : + Zpos (shift_pos p x) = Z.pow_pos 2 p * Zpos x. + Proof. + now rewrite shift_pos_nat, Zpower_pos_nat, shift_nat_correct. + Qed. - Theorem two_power_pos_is_exp : - forall x y:positive, - two_power_pos (x + y) = two_power_pos x * two_power_pos y. + Theorem two_power_pos_correct x : two_power_pos x = Z.pow_pos 2 x. 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. + apply two_power_pos_equiv. 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. *) + Theorem two_power_pos_is_exp x y : + two_power_pos (x + y) = two_power_pos x * two_power_pos y. + Proof. + rewrite 3 two_power_pos_equiv. now apply (Z.pow_add_r 2 (Zpos x) (Zpos y)). + Qed. - Definition two_p (x:Z) := - match x with - | Z0 => 1 - | Zpos y => two_power_pos y - | Zneg y => 0 - end. + Lemma two_p_correct x : two_p x = 2^x. + Proof (two_p_equiv x). - Theorem two_p_is_exp : - forall x y:Z, 0 <= x -> 0 <= y -> two_p (x + y) = two_p x * two_p y. + Theorem two_p_is_exp x y : + 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 ] ]. + rewrite !two_p_equiv. apply Z.pow_add_r. Qed. - Lemma two_p_gt_ZERO : forall x:Z, 0 <= x -> two_p x > 0. + Lemma two_p_gt_ZERO x : 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 ] ]. + Z.swap_greater. rewrite two_p_equiv. now apply Z.pow_pos_nonneg. Qed. - Lemma two_p_S : forall x:Z, 0 <= x -> two_p (Zsucc x) = 2 * two_p x. + Lemma two_p_S x : 0 <= x -> two_p (Z.succ 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. + rewrite !two_p_equiv. now apply Z.pow_succ_r. Qed. - Lemma two_p_pred : forall x:Z, 0 <= x -> two_p (Zpred x) < two_p x. + Lemma two_p_pred x : 0 <= x -> two_p (Z.pred 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 ]. + rewrite !two_p_equiv. intros. apply Z.pow_lt_mono_r; auto with zarith. Qed. - Lemma Zlt_lt_double : forall x y:Z, 0 <= x < y -> x < 2 * y. - intros; omega. Qed. - - End Powers_of_2. +End Powers_of_2. Hint Resolve two_p_gt_ZERO: zarith. Hint Immediate two_p_pred two_p_S: zarith. @@ -261,100 +230,88 @@ 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] *) + (** To [x:Z] and [p:positive], [q],[r] are associated such that + [x = 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'] *) + (** 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). + let '(q,r,d) := qrd 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. + let (qr, d) := Pos.iter 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. + Lemma Zdiv_rest_correct1 (x:Z) (p:positive) : + let (_, d) := Pos.iter 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 ]. + rewrite Pos2Nat.inj_iter, two_power_pos_nat. + induction (Pos.to_nat p); simpl; trivial. + destruct (nat_iter n Zdiv_rest_aux (x,0,1)) as ((q,r),d). + unfold Zdiv_rest_aux. rewrite two_power_nat_S; now f_equal. 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. + Lemma Zdiv_rest_correct2 (x:Z) (p:positive) : + let '(q,r,d) := Pos.iter p Zdiv_rest_aux (x, 0, 1) 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 ]. + apply Pos.iter_invariant; [|omega]. + intros ((q,r),d) (H,H'). unfold Zdiv_rest_aux. + destruct q as [ |[q|q| ]|[q|q| ]]; try omega. + - rewrite Pos2Z.inj_xI, Z.mul_add_distr_r in H. + rewrite Z.mul_shuffle3, Z.mul_assoc. omega. + - rewrite Pos2Z.inj_xO in H. + rewrite Z.mul_shuffle3, Z.mul_assoc. omega. + - rewrite Pos2Z.neg_xI, Z.mul_sub_distr_r in H. + rewrite Z.mul_sub_distr_r, Z.mul_shuffle3, Z.mul_assoc. omega. + - rewrite Pos2Z.neg_xO in H. + rewrite Z.mul_shuffle3, Z.mul_assoc. omega. Qed. + (** Old-style rich specification by proof of existence *) + 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. + Lemma Zdiv_rest_correct (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. + destruct (Pos.iter p Zdiv_rest_aux (x, 0, 1)) as ((q,r),d). + intros (H1,(H2,H3)) ->. now exists q r. + Qed. + + (** Direct correctness of [Zdiv_rest] *) + + Lemma Zdiv_rest_ok x p : + let (q,r) := Zdiv_rest x p in + x = q * 2^(Zpos p) + r /\ 0 <= r < 2^(Zpos p). + Proof. + unfold Zdiv_rest. + generalize (Zdiv_rest_correct1 x p); generalize (Zdiv_rest_correct2 x p). + destruct (Pos.iter p Zdiv_rest_aux (x, 0, 1)) as ((q,r),d). + intros H ->. now rewrite two_power_pos_equiv in H. + Qed. + + (** Equivalence with [Z.shiftr] *) + + Lemma Zdiv_rest_shiftr x p : + fst (Zdiv_rest x p) = Z.shiftr x (Zpos p). + Proof. + generalize (Zdiv_rest_ok x p). destruct (Zdiv_rest x p) as (q,r). + intros (H,H'). simpl. + rewrite Z.shiftr_div_pow2 by easy. + apply Z.div_unique_pos with r; trivial. now rewrite Z.mul_comm. Qed. End power_div_with_rest. diff --git a/theories/ZArith/Zquot.v b/theories/ZArith/Zquot.v new file mode 100644 index 00000000..c02f0ae6 --- /dev/null +++ b/theories/ZArith/Zquot.v @@ -0,0 +1,453 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +Require Import Nnat ZArith_base ROmega ZArithRing Zdiv Morphisms. + +Local Open Scope Z_scope. + +(** This file provides results about the Round-Toward-Zero Euclidean + division [Z.quotrem], whose projections are [Z.quot] (noted ÷) + and [Z.rem]. + + This division and [Z.div] agree only on positive numbers. + Otherwise, [Z.div] performs Round-Toward-Bottom (a.k.a Floor). + + This [Z.quot] is compatible with the division of usual + programming languages such as Ocaml. In addition, it has nicer + properties with respect to opposite and other usual operations. + + The definition of this division is now in file [BinIntDef], + while most of the results about here are now in the main module + [BinInt.Z], thanks to the generic "Numbers" layer. Remain here: + + - some compatibility notation for old names. + + - some extra results with less preconditions (in particular + exploiting the arbitrary value of division by 0). +*) + +Notation Ndiv_Zquot := N2Z.inj_quot (compat "8.3"). +Notation Nmod_Zrem := N2Z.inj_rem (compat "8.3"). +Notation Z_quot_rem_eq := Z.quot_rem' (compat "8.3"). +Notation Zrem_lt := Z.rem_bound_abs (compat "8.3"). +Notation Zquot_unique := Z.quot_unique (compat "8.3"). +Notation Zrem_unique := Z.rem_unique (compat "8.3"). +Notation Zrem_1_r := Z.rem_1_r (compat "8.3"). +Notation Zquot_1_r := Z.quot_1_r (compat "8.3"). +Notation Zrem_1_l := Z.rem_1_l (compat "8.3"). +Notation Zquot_1_l := Z.quot_1_l (compat "8.3"). +Notation Z_quot_same := Z.quot_same (compat "8.3"). +Notation Z_quot_mult := Z.quot_mul (compat "8.3"). +Notation Zquot_small := Z.quot_small (compat "8.3"). +Notation Zrem_small := Z.rem_small (compat "8.3"). +Notation Zquot2_quot := Zquot2_quot (compat "8.3"). + +(** Particular values taken for [a÷0] and [(Z.rem a 0)]. + We avise to not rely on these arbitrary values. *) + +Lemma Zquot_0_r a : a ÷ 0 = 0. +Proof. now destruct a. Qed. + +Lemma Zrem_0_r a : Z.rem a 0 = a. +Proof. now destruct a. Qed. + +(** The following results are expressed without the [b<>0] condition + whenever possible. *) + +Lemma Zrem_0_l a : Z.rem 0 a = 0. +Proof. now destruct a. Qed. + +Lemma Zquot_0_l a : 0÷a = 0. +Proof. now destruct a. Qed. + +Hint Resolve Zrem_0_l Zrem_0_r Zquot_0_l Zquot_0_r Z.quot_1_r Z.rem_1_r + : zarith. + +Ltac zero_or_not a := + destruct (Z.eq_decidable a 0) as [->|?]; + [rewrite ?Zquot_0_l, ?Zrem_0_l, ?Zquot_0_r, ?Zrem_0_r; + auto with zarith|]. + +Lemma Z_rem_same a : Z.rem a a = 0. +Proof. zero_or_not a. now apply Z.rem_same. Qed. + +Lemma Z_rem_mult a b : Z.rem (a*b) b = 0. +Proof. zero_or_not b. now apply Z.rem_mul. Qed. + +(** * Division and Opposite *) + +(* The precise equalities that are invalid with "historic" Zdiv. *) + +Theorem Zquot_opp_l a b : (-a)÷b = -(a÷b). +Proof. zero_or_not b. now apply Z.quot_opp_l. Qed. + +Theorem Zquot_opp_r a b : a÷(-b) = -(a÷b). +Proof. zero_or_not b. now apply Z.quot_opp_r. Qed. + +Theorem Zrem_opp_l a b : Z.rem (-a) b = -(Z.rem a b). +Proof. zero_or_not b. now apply Z.rem_opp_l. Qed. + +Theorem Zrem_opp_r a b : Z.rem a (-b) = Z.rem a b. +Proof. zero_or_not b. now apply Z.rem_opp_r. Qed. + +Theorem Zquot_opp_opp a b : (-a)÷(-b) = a÷b. +Proof. zero_or_not b. now apply Z.quot_opp_opp. Qed. + +Theorem Zrem_opp_opp a b : Z.rem (-a) (-b) = -(Z.rem a b). +Proof. zero_or_not b. now apply Z.rem_opp_opp. Qed. + +(** The sign of the remainder is the one of [a]. Due to the possible + nullity of [a], a general result is to be stated in the following form: +*) + +Theorem Zrem_sgn a b : 0 <= Z.sgn (Z.rem a b) * Z.sgn a. +Proof. + zero_or_not b. + - apply Z.square_nonneg. + - zero_or_not (Z.rem a b). + rewrite Z.rem_sign_nz; trivial. apply Z.square_nonneg. +Qed. + +(** This can also be said in a simplier way: *) + +Theorem Zrem_sgn2 a b : 0 <= (Z.rem a b) * a. +Proof. + zero_or_not b. + - apply Z.square_nonneg. + - now apply Z.rem_sign_mul. +Qed. + +(** Reformulation of [Z.rem_bound_abs] in 2 then 4 particular cases. *) + +Theorem Zrem_lt_pos a b : 0<=a -> b<>0 -> 0 <= Z.rem a b < Z.abs b. +Proof. + intros; generalize (Z.rem_nonneg a b) (Z.rem_bound_abs a b); + romega with *. +Qed. + +Theorem Zrem_lt_neg a b : a<=0 -> b<>0 -> -Z.abs b < Z.rem a b <= 0. +Proof. + intros; generalize (Z.rem_nonpos a b) (Z.rem_bound_abs a b); + romega with *. +Qed. + +Theorem Zrem_lt_pos_pos a b : 0<=a -> 0<b -> 0 <= Z.rem a b < b. +Proof. + intros; generalize (Zrem_lt_pos a b); romega with *. +Qed. + +Theorem Zrem_lt_pos_neg a b : 0<=a -> b<0 -> 0 <= Z.rem a b < -b. +Proof. + intros; generalize (Zrem_lt_pos a b); romega with *. +Qed. + +Theorem Zrem_lt_neg_pos a b : a<=0 -> 0<b -> -b < Z.rem a b <= 0. +Proof. + intros; generalize (Zrem_lt_neg a b); romega with *. +Qed. + +Theorem Zrem_lt_neg_neg a b : a<=0 -> b<0 -> b < Z.rem a b <= 0. +Proof. + intros; generalize (Zrem_lt_neg a b); romega with *. +Qed. + + +(** * Unicity results *) + +Definition Remainder a b r := + (0 <= a /\ 0 <= r < Z.abs b) \/ (a <= 0 /\ -Z.abs b < r <= 0). + +Definition Remainder_alt a b r := + Z.abs r < Z.abs b /\ 0 <= r * a. + +Lemma Remainder_equiv : forall a b r, + Remainder a b r <-> Remainder_alt a b r. +Proof. + unfold Remainder, Remainder_alt; intuition. + - romega with *. + - romega with *. + - rewrite <-(Z.mul_opp_opp). apply Z.mul_nonneg_nonneg; romega. + - assert (0 <= Z.sgn r * Z.sgn a). + { rewrite <-Z.sgn_mul, Z.sgn_nonneg; auto. } + destruct r; simpl Z.sgn in *; romega with *. +Qed. + +Theorem Zquot_mod_unique_full a b q r : + Remainder a b r -> a = b*q + r -> q = a÷b /\ r = Z.rem a b. +Proof. + destruct 1 as [(H,H0)|(H,H0)]; intros. + apply Zdiv_mod_unique with b; auto. + apply Zrem_lt_pos; auto. + romega with *. + rewrite <- H1; apply Z.quot_rem'. + + rewrite <- (Z.opp_involutive a). + rewrite Zquot_opp_l, Zrem_opp_l. + generalize (Zdiv_mod_unique b (-q) (-a÷b) (-r) (Z.rem (-a) b)). + generalize (Zrem_lt_pos (-a) b). + rewrite <-Z.quot_rem', Z.mul_opp_r, <-Z.opp_add_distr, <-H1. + romega with *. +Qed. + +Theorem Zquot_unique_full a b q r : + Remainder a b r -> a = b*q + r -> q = a÷b. +Proof. + intros; destruct (Zquot_mod_unique_full a b q r); auto. +Qed. + +Theorem Zrem_unique_full a b q r : + Remainder a b r -> a = b*q + r -> r = Z.rem a b. +Proof. + intros; destruct (Zquot_mod_unique_full a b q r); auto. +Qed. + +(** * Order results about Zrem and Zquot *) + +(* Division of positive numbers is positive. *) + +Lemma Z_quot_pos a b : 0 <= a -> 0 <= b -> 0 <= a÷b. +Proof. intros. zero_or_not b. apply Z.quot_pos; auto with zarith. Qed. + +(** As soon as the divisor is greater or equal than 2, + the division is strictly decreasing. *) + +Lemma Z_quot_lt a b : 0 < a -> 2 <= b -> a÷b < a. +Proof. intros. apply Z.quot_lt; auto with zarith. Qed. + +(** [<=] is compatible with a positive division. *) + +Lemma Z_quot_monotone a b c : 0<=c -> a<=b -> a÷c <= b÷c. +Proof. intros. zero_or_not c. apply Z.quot_le_mono; auto with zarith. Qed. + +(** With our choice of division, rounding of (a÷b) is always done toward 0: *) + +Lemma Z_mult_quot_le a b : 0 <= a -> 0 <= b*(a÷b) <= a. +Proof. intros. zero_or_not b. apply Z.mul_quot_le; auto with zarith. Qed. + +Lemma Z_mult_quot_ge a b : a <= 0 -> a <= b*(a÷b) <= 0. +Proof. intros. zero_or_not b. apply Z.mul_quot_ge; auto with zarith. Qed. + +(** The previous inequalities between [b*(a÷b)] and [a] are exact + iff the modulo is zero. *) + +Lemma Z_quot_exact_full a b : a = b*(a÷b) <-> Z.rem a b = 0. +Proof. intros. zero_or_not b. intuition. apply Z.quot_exact; auto. Qed. + +(** A modulo cannot grow beyond its starting point. *) + +Theorem Zrem_le a b : 0 <= a -> 0 <= b -> Z.rem a b <= a. +Proof. intros. zero_or_not b. apply Z.rem_le; auto with zarith. Qed. + +(** Some additionnal inequalities about Zdiv. *) + +Theorem Zquot_le_upper_bound: + forall a b q, 0 < b -> a <= q*b -> a÷b <= q. +Proof. intros a b q; rewrite Z.mul_comm; apply Z.quot_le_upper_bound. Qed. + +Theorem Zquot_lt_upper_bound: + forall a b q, 0 <= a -> 0 < b -> a < q*b -> a÷b < q. +Proof. intros a b q; rewrite Z.mul_comm; apply Z.quot_lt_upper_bound. Qed. + +Theorem Zquot_le_lower_bound: + forall a b q, 0 < b -> q*b <= a -> q <= a÷b. +Proof. intros a b q; rewrite Z.mul_comm; apply Z.quot_le_lower_bound. Qed. + +Theorem Zquot_sgn: forall a b, + 0 <= Z.sgn (a÷b) * Z.sgn a * Z.sgn b. +Proof. + destruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith; + unfold Z.quot; simpl; destruct N.pos_div_eucl; simpl; destruct n; simpl; auto with zarith. +Qed. + +(** * Relations between usual operations and Zmod and Zdiv *) + +(** First, a result that used to be always valid with Zdiv, + but must be restricted here. + For instance, now (9+(-5)*2) rem 2 = -1 <> 1 = 9 rem 2 *) + +Lemma Z_rem_plus : forall a b c:Z, + 0 <= (a+b*c) * a -> + Z.rem (a + b * c) c = Z.rem a c. +Proof. intros. zero_or_not c. apply Z.rem_add; auto with zarith. Qed. + +Lemma Z_quot_plus : forall a b c:Z, + 0 <= (a+b*c) * a -> c<>0 -> + (a + b * c) ÷ c = a ÷ c + b. +Proof. intros. apply Z.quot_add; auto with zarith. Qed. + +Theorem Z_quot_plus_l: forall a b c : Z, + 0 <= (a*b+c)*c -> b<>0 -> + b<>0 -> (a * b + c) ÷ b = a + c ÷ b. +Proof. intros. apply Z.quot_add_l; auto with zarith. Qed. + +(** Cancellations. *) + +Lemma Zquot_mult_cancel_r : forall a b c:Z, + c<>0 -> (a*c)÷(b*c) = a÷b. +Proof. intros. zero_or_not b. apply Z.quot_mul_cancel_r; auto. Qed. + +Lemma Zquot_mult_cancel_l : forall a b c:Z, + c<>0 -> (c*a)÷(c*b) = a÷b. +Proof. + intros. rewrite (Z.mul_comm c b). zero_or_not b. + rewrite (Z.mul_comm b c). apply Z.quot_mul_cancel_l; auto. +Qed. + +Lemma Zmult_rem_distr_l: forall a b c, + Z.rem (c*a) (c*b) = c * (Z.rem a b). +Proof. + intros. zero_or_not c. rewrite (Z.mul_comm c b). zero_or_not b. + rewrite (Z.mul_comm b c). apply Z.mul_rem_distr_l; auto. +Qed. + +Lemma Zmult_rem_distr_r: forall a b c, + Z.rem (a*c) (b*c) = (Z.rem a b) * c. +Proof. + intros. zero_or_not b. rewrite (Z.mul_comm b c). zero_or_not c. + rewrite (Z.mul_comm c b). apply Z.mul_rem_distr_r; auto. +Qed. + +(** Operations modulo. *) + +Theorem Zrem_rem: forall a n, Z.rem (Z.rem a n) n = Z.rem a n. +Proof. intros. zero_or_not n. apply Z.rem_rem; auto. Qed. + +Theorem Zmult_rem: forall a b n, + Z.rem (a * b) n = Z.rem (Z.rem a n * Z.rem b n) n. +Proof. intros. zero_or_not n. apply Z.mul_rem; auto. Qed. + +(** addition and modulo + + Generally speaking, unlike with Zdiv, we don't have + (a+b) rem n = (a rem n + b rem n) rem n + for any a and b. + For instance, take (8 + (-10)) rem 3 = -2 whereas + (8 rem 3 + (-10 rem 3)) rem 3 = 1. *) + +Theorem Zplus_rem: forall a b n, + 0 <= a * b -> + Z.rem (a + b) n = Z.rem (Z.rem a n + Z.rem b n) n. +Proof. intros. zero_or_not n. apply Z.add_rem; auto. Qed. + +Lemma Zplus_rem_idemp_l: forall a b n, + 0 <= a * b -> + Z.rem (Z.rem a n + b) n = Z.rem (a + b) n. +Proof. intros. zero_or_not n. apply Z.add_rem_idemp_l; auto. Qed. + +Lemma Zplus_rem_idemp_r: forall a b n, + 0 <= a*b -> + Z.rem (b + Z.rem a n) n = Z.rem (b + a) n. +Proof. + intros. zero_or_not n. apply Z.add_rem_idemp_r; auto. + rewrite Z.mul_comm; auto. +Qed. + +Lemma Zmult_rem_idemp_l: forall a b n, Z.rem (Z.rem a n * b) n = Z.rem (a * b) n. +Proof. intros. zero_or_not n. apply Z.mul_rem_idemp_l; auto. Qed. + +Lemma Zmult_rem_idemp_r: forall a b n, Z.rem (b * Z.rem a n) n = Z.rem (b * a) n. +Proof. intros. zero_or_not n. apply Z.mul_rem_idemp_r; auto. Qed. + +(** Unlike with Zdiv, the following result is true without restrictions. *) + +Lemma Zquot_Zquot : forall a b c, (a÷b)÷c = a÷(b*c). +Proof. + intros. zero_or_not b. rewrite Z.mul_comm. zero_or_not c. + rewrite Z.mul_comm. apply Z.quot_quot; auto. +Qed. + +(** A last inequality: *) + +Theorem Zquot_mult_le: + forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a÷b) <= (c*a)÷b. +Proof. intros. zero_or_not b. apply Z.quot_mul_le; auto with zarith. Qed. + +(** Z.rem is related to divisibility (see more in Znumtheory) *) + +Lemma Zrem_divides : forall a b, + Z.rem a b = 0 <-> exists c, a = b*c. +Proof. + intros. zero_or_not b. firstorder. + rewrite Z.rem_divide; trivial. + split; intros (c,Hc); exists c; subst; auto with zarith. +Qed. + +(** Particular case : dividing by 2 is related with parity *) + +Lemma Zquot2_odd_remainder : forall a, + Remainder a 2 (if Z.odd a then Z.sgn a else 0). +Proof. + intros [ |p|p]. simpl. + left. simpl. auto with zarith. + left. destruct p; simpl; auto with zarith. + right. destruct p; simpl; split; now auto with zarith. +Qed. + +Lemma Zrem_odd : forall a, Z.rem a 2 = if Z.odd a then Z.sgn a else 0. +Proof. + intros. symmetry. + apply Zrem_unique_full with (Z.quot2 a). + apply Zquot2_odd_remainder. + apply Zquot2_odd_eqn. +Qed. + +Lemma Zrem_even : forall a, Z.rem a 2 = if Z.even a then 0 else Z.sgn a. +Proof. + intros a. rewrite Zrem_odd, Zodd_even_bool. now destruct Z.even. +Qed. + +Lemma Zeven_rem : forall a, Z.even a = Z.eqb (Z.rem a 2) 0. +Proof. + intros a. rewrite Zrem_even. + destruct a as [ |p|p]; trivial; now destruct p. +Qed. + +Lemma Zodd_rem : forall a, Z.odd a = negb (Z.eqb (Z.rem a 2) 0). +Proof. + intros a. rewrite Zrem_odd. + destruct a as [ |p|p]; trivial; now destruct p. +Qed. + +(** * Interaction with "historic" Zdiv *) + +(** They agree at least on positive numbers: *) + +Theorem Zquotrem_Zdiv_eucl_pos : forall a b:Z, 0 <= a -> 0 < b -> + a÷b = a/b /\ Z.rem a b = a mod b. +Proof. + intros. + apply Zdiv_mod_unique with b. + apply Zrem_lt_pos; auto with zarith. + rewrite Z.abs_eq; auto with *; apply Z_mod_lt; auto with *. + rewrite <- Z_div_mod_eq; auto with *. + symmetry; apply Z.quot_rem; auto with *. +Qed. + +Theorem Zquot_Zdiv_pos : forall a b, 0 <= a -> 0 <= b -> + a÷b = a/b. +Proof. + intros a b Ha Hb. Z.le_elim Hb. + - generalize (Zquotrem_Zdiv_eucl_pos a b Ha Hb); intuition. + - subst; now rewrite Zquot_0_r, Zdiv_0_r. +Qed. + +Theorem Zrem_Zmod_pos : forall a b, 0 <= a -> 0 < b -> + Z.rem a b = a mod b. +Proof. + intros a b Ha Hb; generalize (Zquotrem_Zdiv_eucl_pos a b Ha Hb); + intuition. +Qed. + +(** Modulos are null at the same places *) + +Theorem Zrem_Zmod_zero : forall a b, b<>0 -> + (Z.rem a b = 0 <-> a mod b = 0). +Proof. + intros. + rewrite Zrem_divides, Zmod_divides; intuition. +Qed. diff --git a/theories/ZArith/Zsqrt.v b/theories/ZArith/Zsqrt_compat.v index 1a67bbb2..a6c83241 100644 --- a/theories/ZArith/Zsqrt.v +++ b/theories/ZArith/Zsqrt_compat.v @@ -1,17 +1,26 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zsqrt.v 14641 2011-11-06 11:59:10Z herbelin $ *) - Require Import ZArithRing. Require Import Omega. Require Export ZArith_base. -Open Local Scope Z_scope. +Local Open Scope Z_scope. + +(** THIS FILE IS DEPRECATED + + Instead of the various [Zsqrt] defined here, please use rather + [Z.sqrt] (or [Z.sqrtrem]). The latter are pure functions without + proof parts, and more results are available about them. + Some equivalence proofs between the old and the new versions + can be found below. Importing ZArith will provides by default + the new versions. + +*) (**********************************************************************) (** Definition and properties of square root on Z *) @@ -23,12 +32,12 @@ Ltac compute_POS := | |- context [(Zpos (xI ?X1))] => match constr:X1 with | context [1%positive] => fail 1 - | _ => rewrite (BinInt.Zpos_xI X1) + | _ => rewrite (Pos2Z.inj_xI X1) end | |- context [(Zpos (xO ?X1))] => match constr:X1 with | context [1%positive] => fail 1 - | _ => rewrite (BinInt.Zpos_xO X1) + | _ => rewrite (Pos2Z.inj_xO X1) end end. @@ -106,7 +115,7 @@ Definition Zsqrt : fun h => match sqrtrempos p with | c_sqrt s r Heq Hint => - existS + existT (fun s:Z => {r : Z | Zpos p = s * s + r /\ s * s <= Zpos p < (s + 1) * (s + 1)}) @@ -122,10 +131,10 @@ Definition Zsqrt : {s : Z & {r : Z | Zneg p = s * s + r /\ s * s <= Zneg p < (s + 1) * (s + 1)}} - (h (refl_equal Datatypes.Gt)) + (h (eq_refl Datatypes.Gt)) | Z0 => fun h => - existS + existT (fun s:Z => {r : Z | 0 = s * s + r /\ s * s <= 0 < (s + 1) * (s + 1)}) 0 (exist @@ -140,8 +149,8 @@ Defined. Definition Zsqrt_plain (x:Z) : Z := match x with | Zpos p => - match Zsqrt (Zpos p) (Zorder.Zle_0_pos p) with - | existS s _ => s + match Zsqrt (Zpos p) (Pos2Z.is_nonneg p) with + | existT s _ => s end | Zneg p => 0 | Z0 => 0 @@ -155,12 +164,11 @@ Theorem Zsqrt_interval : 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. + intros [|p|p] Hp. + - now compute. + - unfold Zsqrt_plain. + now destruct Zsqrt as (s & r & Heq & Hint). + - now elim Hp. Qed. (** Positivity *) @@ -168,9 +176,9 @@ Qed. Theorem Zsqrt_plain_is_pos: forall n, 0 <= n -> 0 <= Zsqrt_plain n. Proof. intros n m; case (Zsqrt_interval n); auto with zarith. - intros H1 H2; case (Zle_or_lt 0 (Zsqrt_plain n)); auto. - intros H3; contradict H2; auto; apply Zle_not_lt. - apply Zle_trans with ( 2 := H1 ). + intros H1 H2; case (Z.le_gt_cases 0 (Zsqrt_plain n)); auto. + intros H3; contradict H2; auto; apply Z.le_ngt. + apply Z.le_trans with ( 2 := H1 ). replace ((Zsqrt_plain n + 1) * (Zsqrt_plain n + 1)) with (Zsqrt_plain n * Zsqrt_plain n + (2 * Zsqrt_plain n + 1)); auto with zarith. @@ -185,13 +193,13 @@ Proof. generalize (Zsqrt_plain_is_pos (a * a)); auto with zarith; intros Haa. case (Zsqrt_interval (a * a)); auto with zarith. intros H1 H2. - case (Zle_or_lt a (Zsqrt_plain (a * a))); intros H3; auto. - case Zle_lt_or_eq with (1:=H3); auto; clear H3; intros H3. - contradict H1; auto; apply Zlt_not_le; auto with zarith. - apply Zle_lt_trans with (a * Zsqrt_plain (a * a)); auto with zarith. - apply Zmult_lt_compat_r; auto with zarith. - contradict H2; auto; apply Zle_not_lt; auto with zarith. - apply Zmult_le_compat; auto with zarith. + case (Z.le_gt_cases a (Zsqrt_plain (a * a))); intros H3. + - Z.le_elim H3; auto. + contradict H1; auto; apply Z.lt_nge; auto with zarith. + apply Z.le_lt_trans with (a * Zsqrt_plain (a * a)); auto with zarith. + apply Z.mul_lt_mono_pos_r; auto with zarith. + - contradict H2; auto; apply Z.le_ngt; auto with zarith. + apply Z.mul_le_mono_nonneg; auto with zarith. Qed. (** [Zsqrt_plain] is increasing *) @@ -199,17 +207,26 @@ Qed. Theorem Zsqrt_le: forall p q, 0 <= p <= q -> Zsqrt_plain p <= Zsqrt_plain q. Proof. - intros p q [H1 H2]; case Zle_lt_or_eq with (1:=H2); clear H2; intros H2; - [ | subst q; auto with zarith]. - case (Zle_or_lt (Zsqrt_plain p) (Zsqrt_plain q)); auto; intros H3. + intros p q [H1 H2]. + Z.le_elim H2; [ | subst q; auto with zarith]. + case (Z.le_gt_cases (Zsqrt_plain p) (Zsqrt_plain q)); auto; intros H3. assert (Hp: (0 <= Zsqrt_plain q)). - apply Zsqrt_plain_is_pos; auto with zarith. + { apply Zsqrt_plain_is_pos; auto with zarith. } absurd (q <= p); auto with zarith. - apply Zle_trans with ((Zsqrt_plain q + 1) * (Zsqrt_plain q + 1)). + apply Z.le_trans with ((Zsqrt_plain q + 1) * (Zsqrt_plain q + 1)). case (Zsqrt_interval q); auto with zarith. - apply Zle_trans with (Zsqrt_plain p * Zsqrt_plain p); auto with zarith. - apply Zmult_le_compat; auto with zarith. + apply Z.le_trans with (Zsqrt_plain p * Zsqrt_plain p); auto with zarith. + apply Z.mul_le_mono_nonneg; auto with zarith. case (Zsqrt_interval p); auto with zarith. Qed. +(** Equivalence between Zsqrt_plain and [Z.sqrt] *) + +Lemma Zsqrt_equiv : forall n, Zsqrt_plain n = Z.sqrt n. +Proof. + intros. destruct (Z_le_gt_dec 0 n). + symmetry. apply Z.sqrt_unique; trivial. + now apply Zsqrt_interval. + now destruct n. +Qed.
\ No newline at end of file diff --git a/theories/ZArith/Zwf.v b/theories/ZArith/Zwf.v index 53f167e8..e07fc715 100644 --- a/theories/ZArith/Zwf.v +++ b/theories/ZArith/Zwf.v @@ -1,17 +1,15 @@ (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: Zwf.v 14641 2011-11-06 11:59:10Z herbelin $ *) - Require Import ZArith_base. Require Export Wf_nat. Require Import Omega. -Open Local Scope Z_scope. +Local Open Scope Z_scope. (** Well-founded relations on Z. *) @@ -31,28 +29,28 @@ Section wf_proof. (** 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). + Let f (z:Z) := Z.abs_nat (z - c). Lemma Zwf_well_founded : well_founded (Zwf c). - red in |- *; intros. + red; 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. + apply Acc_intro; unfold Zwf; 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. + case (Z.le_gt_cases 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. + unfold f. + apply Zabs2Nat.inj_lt; omega. apply (H (S (f a))); auto. Qed. @@ -77,18 +75,15 @@ Section wf_proof_up. (** 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) := Z.abs_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 |- *. + unfold Zwf_up, f. 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. + apply Zabs2Nat.inj_lt; try (apply Z.le_0_sub; intuition). + now apply Z.sub_lt_mono_l. Qed. End wf_proof_up. diff --git a/theories/ZArith/auxiliary.v b/theories/ZArith/auxiliary.v index ade35bef..af7d5a2e 100644 --- a/theories/ZArith/auxiliary.v +++ b/theories/ZArith/auxiliary.v @@ -1,14 +1,12 @@ (* -*- coding: utf-8 -*- *) (************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: auxiliary.v 14641 2011-11-06 11:59:10Z herbelin $ i*) - (** Binary Integers (Pierre Crégut, CNET, Lannion, France) *) Require Export Arith_base. @@ -18,96 +16,79 @@ Require Import Decidable. Require Import Peano_dec. Require Export Compare_dec. -Open Local Scope Z_scope. +Local Open Scope Z_scope. (***************************************************************) (** * 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. +Theorem Zne_left n m : 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. + unfold Zne. now rewrite <- Z.sub_move_0_r. Qed. -Theorem Zegal_left : forall n m:Z, n = m -> n + - m = 0. +Theorem Zegal_left n m : 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. + apply Z.sub_move_0_r. Qed. -Theorem Zle_left : forall n m:Z, n <= m -> 0 <= m + - n. +Theorem Zle_left n m : 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. + apply Z.le_0_sub. Qed. -Theorem Zle_left_rev : forall n m:Z, 0 <= m + - n -> n <= m. +Theorem Zle_left_rev n m : 0 <= m + - n -> n <= m. Proof. - intros x y H; apply Zplus_le_reg_r with (- x). - rewrite Zplus_opp_r; trivial. + apply Z.le_0_sub. Qed. -Theorem Zlt_left_rev : forall n m:Z, 0 < m + - n -> n < m. +Theorem Zlt_left_rev n m : 0 < m + - n -> n < m. Proof. - intros x y H; apply Zplus_lt_reg_r with (- x). - rewrite Zplus_opp_r; trivial. + apply Z.lt_0_sub. Qed. -Theorem Zlt_left : forall n m:Z, n < m -> 0 <= m + -1 + - n. +Theorem Zlt_left_lt n m : n < m -> 0 < m + - 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. + apply Z.lt_0_sub. Qed. -Theorem Zlt_left_lt : forall n m:Z, n < m -> 0 < m + - n. +Theorem Zlt_left n m : n < m -> 0 <= m + -1 + - n. Proof. - intros x y H; replace 0 with (x + - x). - apply Zplus_lt_compat_r; trivial. - apply Zplus_opp_r. + intros. rewrite Z.add_shuffle0. change (-1) with (- Z.succ 0). + now apply Z.le_0_sub, Z.le_succ_l, Z.lt_0_sub. Qed. -Theorem Zge_left : forall n m:Z, n >= m -> 0 <= n + - m. +Theorem Zge_left n m : n >= m -> 0 <= n + - m. Proof. - intros x y H; apply Zle_left; apply Zge_le; assumption. + Z.swap_greater. apply Z.le_0_sub. Qed. -Theorem Zgt_left : forall n m:Z, n > m -> 0 <= n + -1 + - m. +Theorem Zgt_left n m : n > m -> 0 <= n + -1 + - m. Proof. - intros x y H; apply Zlt_left; apply Zgt_lt; assumption. + Z.swap_greater. apply Zlt_left. Qed. -Theorem Zgt_left_gt : forall n m:Z, n > m -> n + - m > 0. +Theorem Zgt_left_gt n m : 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. + Z.swap_greater. apply Z.lt_0_sub. Qed. -Theorem Zgt_left_rev : forall n m:Z, n + - m > 0 -> n > m. +Theorem Zgt_left_rev n m : n + - m > 0 -> n > m. Proof. - intros x y H; apply Zplus_gt_reg_r with (- y). - rewrite Zplus_opp_r; trivial. + Z.swap_greater. apply Z.lt_0_sub. Qed. -Theorem Zle_mult_approx : - forall n m p:Z, n > 0 -> p > 0 -> 0 <= m -> 0 <= m * n + p. +Theorem Zle_mult_approx n m p : + 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 ]. + Z.swap_greater. intros. Z.order_pos. Qed. -Theorem Zmult_le_approx : - forall n m p:Z, n > 0 -> n > p -> 0 <= m * n + p -> 0 <= m. +Theorem Zmult_le_approx n m p : + 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 ]. + Z.swap_greater. intros. apply Z.lt_succ_r. + apply Z.mul_pos_cancel_r with n; trivial. Z.nzsimpl. + apply Z.le_lt_trans with (m*n+p); trivial. + now apply Z.add_lt_mono_l. Qed. diff --git a/theories/ZArith/vo.itarget b/theories/ZArith/vo.itarget index 3efa7055..88751cc0 100644 --- a/theories/ZArith/vo.itarget +++ b/theories/ZArith/vo.itarget @@ -1,4 +1,5 @@ auxiliary.vo +BinIntDef.vo BinInt.vo Int.vo Wf_Z.vo @@ -13,6 +14,7 @@ Zcomplements.vo Zdiv.vo Zeven.vo Zgcd_alt.vo +Zpow_alt.vo Zhints.vo Zlogarithm.vo Zmax.vo @@ -23,10 +25,11 @@ Znat.vo Znumtheory.vo ZOdiv_def.vo ZOdiv.vo +Zquot.vo Zorder.vo Zpow_def.vo Zpower.vo Zpow_facts.vo -Zsqrt.vo +Zsqrt_compat.vo Zwf.vo -ZOrderedType.vo +Zeuclid.vo |