aboutsummaryrefslogtreecommitdiffhomepage
path: root/theories/NArith
diff options
context:
space:
mode:
authorGravatar letouzey <letouzey@85f007b7-540e-0410-9357-904b9bb8a0f7>2010-11-18 18:02:20 +0000
committerGravatar letouzey <letouzey@85f007b7-540e-0410-9357-904b9bb8a0f7>2010-11-18 18:02:20 +0000
commit59726c5343613379d38a9409af044d85cca130ed (patch)
tree185cef19334e67de344b6417a07c11ad61ed0c46 /theories/NArith
parent16cf970765096f55a03efad96100add581ce0edb (diff)
Some more revision of {P,N,Z}Arith + bitwise ops in Ndigits
Initial plan was only to add shiftl/shiftr/land/... to N and other number type, this is only partly done, but this work has diverged into a big reorganisation and improvement session of PArith,NArith,ZArith. Bool/Bool: add lemmas orb_diag (a||a = a) and andb_diag (a&&a = a) PArith/BinPos: - added a power function Ppow - iterator iter_pos moved from Zmisc to here + some lemmas - added Psize_pos, which is 1+log2, used to define Nlog2/Zlog2 - more lemmas on Pcompare and succ/+/* and order, allow to simplify a lot some old proofs elsewhere. - new/revised results on Pminus (including some direct proof of stuff from Pnat) PArith/Pnat: - more direct proofs (limit the need of stuff about Pmult_nat). - provide nicer names for some lemmas (eg. Pplus_plus instead of nat_of_P_plus_morphism), compatibility notations provided. - kill some too-specific lemmas unused in stdlib + contribs NArith/BinNat: - N_of_nat, nat_of_N moved from Nnat to here. - a lemma relating Npred and Nminus - revised definitions and specification proofs of Npow and Nlog2 NArith/Nnat: - shorter proofs. - stuff about Z_of_N is moved to Znat. This way, NArith is entirely independent from ZArith. NArith/Ndigits: - added bitwise operations Nand Nor Ndiff Nshiftl Nshiftr - revised proofs about Nxor, still using functional bit stream - use the same approach to prove properties of Nand Nor Ndiff ZArith/BinInt: huge simplification of Zplus_assoc + cosmetic stuff ZArith/Zcompare: nicer proofs of ugly things like Zcompare_Zplus_compat ZArith/Znat: some nicer proofs and names, received stuff about Z_of_N ZArith/Zmisc: almost empty new, only contain stuff about badly-named iter. Should be reformed more someday. ZArith/Zlog_def: Zlog2 is now based on Psize_pos, this factorizes proofs and avoid slowdown due to adding 1 in Z instead of in positive Zarith/Zpow_def: Zpower_opt is renamed more modestly Zpower_alt as long as I dont't know why it's slower on powers of two. Elsewhere: propagate new names + some nicer proofs NB: Impact on compatibility is probably non-zero, but should be really moderate. We'll see on contribs, but a few Require here and there might be necessary. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@13651 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'theories/NArith')
-rw-r--r--theories/NArith/BinNat.v161
-rw-r--r--theories/NArith/Ndigits.v688
-rw-r--r--theories/NArith/Nnat.v332
3 files changed, 619 insertions, 562 deletions
diff --git a/theories/NArith/BinNat.v b/theories/NArith/BinNat.v
index eb89fb20d..51c5b462b 100644
--- a/theories/NArith/BinNat.v
+++ b/theories/NArith/BinNat.v
@@ -152,6 +152,20 @@ Definition Nmax (n n' : N) := match Ncompare n n' with
| Gt => n
end.
+(** Translation from [N] to [nat] and back. *)
+
+Definition nat_of_N (a:N) :=
+ match a with
+ | N0 => O
+ | Npos p => nat_of_P p
+ end.
+
+Definition N_of_nat (n:nat) :=
+ match n with
+ | O => N0
+ | S n' => Npos (P_of_succ_nat n')
+ end.
+
(** Decidability of equality. *)
Definition N_eq_dec : forall n m : N, { n = m } + { n <> m }.
@@ -229,7 +243,7 @@ Qed.
Theorem Npred_succ : forall n : N, Npred (Nsucc n) = n.
Proof.
-destruct n as [| p]; simpl. reflexivity.
+intros [| p]; simpl. reflexivity.
case_eq (Psucc p); try (intros q H; rewrite <- H; now rewrite Ppred_succ).
intro H; false_hyp H Psucc_not_one.
Qed.
@@ -249,7 +263,7 @@ Qed.
Theorem Nplus_comm : forall n m:N, n + m = m + n.
Proof.
intros.
-destruct n; destruct m; simpl in |- *; try reflexivity.
+destruct n; destruct m; simpl; try reflexivity.
rewrite Pplus_comm; reflexivity.
Qed.
@@ -259,51 +273,49 @@ intros.
destruct n; try reflexivity.
destruct m; try reflexivity.
destruct p; try reflexivity.
-simpl in |- *; rewrite Pplus_assoc; reflexivity.
+simpl; rewrite Pplus_assoc; reflexivity.
Qed.
Theorem Nplus_succ : forall n m:N, Nsucc n + m = Nsucc (n + m).
Proof.
-destruct n; destruct m.
- simpl in |- *; reflexivity.
- unfold Nsucc, Nplus in |- *; rewrite <- Pplus_one_succ_l; reflexivity.
- simpl in |- *; reflexivity.
- simpl in |- *; rewrite Pplus_succ_permute_l; reflexivity.
+destruct n, m.
+ simpl; reflexivity.
+ unfold Nsucc, Nplus; rewrite <- Pplus_one_succ_l; reflexivity.
+ simpl; reflexivity.
+ simpl; rewrite Pplus_succ_permute_l; reflexivity.
Qed.
Theorem Nsucc_0 : forall n : N, Nsucc n <> N0.
Proof.
-intro n; elim n; simpl Nsucc; intros; discriminate.
+now destruct n.
Qed.
Theorem Nsucc_inj : forall n m:N, Nsucc n = Nsucc m -> n = m.
Proof.
-destruct n; destruct m; simpl in |- *; intro H; reflexivity || injection H;
- clear H; intro H.
- symmetry in H; contradiction Psucc_not_one with p.
- contradiction Psucc_not_one with p.
- rewrite Psucc_inj with (1 := H); reflexivity.
+intros [|p] [|q] H; simpl in *; trivial; injection H; clear H; intro H.
+ now elim (Psucc_not_one q).
+ now elim (Psucc_not_one p).
+ apply Psucc_inj in H. now f_equal.
Qed.
Theorem Nplus_reg_l : forall n m p:N, n + m = n + p -> m = p.
Proof.
-intro n; pattern n in |- *; apply Nind; clear n; simpl in |- *.
+ induction n using Nind.
trivial.
- intros n IHn m p H0; do 2 rewrite Nplus_succ in H0.
- apply IHn; apply Nsucc_inj; assumption.
+ intros m p H; rewrite 2 Nplus_succ in H.
+ apply Nsucc_inj in H. now apply IHn.
Qed.
(** Properties of subtraction. *)
Lemma Nminus_N0_Nle : forall n n' : N, n - n' = N0 <-> n <= n'.
Proof.
-destruct n as [| p]; destruct n' as [| q]; unfold Nle; simpl;
-split; intro H; try discriminate; try reflexivity.
+intros [| p] [| q]; unfold Nle; simpl;
+split; intro H; try easy.
now elim H.
-intro H1; apply Pminus_mask_Gt in H1. destruct H1 as [h [H1 _]].
-rewrite H1 in H; discriminate.
-case_eq (Pcompare p q Eq); intro H1; rewrite H1 in H; try now elim H.
-assert (H2 : p = q); [now apply Pcompare_Eq_eq |]. now rewrite H2, Pminus_mask_diag.
+contradict H. now destruct (Pminus_mask_Gt _ _ H) as (h & -> & _).
+destruct (Pcompare_spec p q); try now elim H.
+subst. now rewrite Pminus_mask_diag.
now rewrite Pminus_mask_Lt.
Qed.
@@ -314,10 +326,15 @@ Qed.
Theorem Nminus_succ_r : forall n m : N, n - (Nsucc m) = Npred (n - m).
Proof.
-destruct n as [| p]; destruct m as [| q]; try reflexivity.
+intros [|p] [|q]; trivial.
now destruct p.
simpl. rewrite Pminus_mask_succ_r, Pminus_mask_carry_spec.
-now destruct (Pminus_mask p q) as [| r |]; [| destruct r |].
+now destruct (Pminus_mask p q) as [|[r|r|]|].
+Qed.
+
+Theorem Npred_minus : forall n, Npred n = Nminus n (Npos 1).
+Proof.
+ intros [|[p|p|]]; trivial.
Qed.
(** Properties of multiplication *)
@@ -334,21 +351,17 @@ Qed.
Theorem Nmult_Sn_m : forall n m : N, (Nsucc n) * m = m + n * m.
Proof.
-destruct n as [| n]; destruct m as [| m]; simpl; auto.
-rewrite Pmult_Sn_m; reflexivity.
+intros [|n] [|m]; simpl; trivial. now rewrite Pmult_Sn_m.
Qed.
Theorem Nmult_1_r : forall n:N, n * Npos 1%positive = n.
Proof.
-destruct n; simpl in |- *; try reflexivity.
-rewrite Pmult_1_r; reflexivity.
+intros [|n]; simpl; trivial. now rewrite Pmult_1_r.
Qed.
Theorem Nmult_comm : forall n m:N, n * m = m * n.
Proof.
-intros.
-destruct n; destruct m; simpl in |- *; try reflexivity.
-rewrite Pmult_comm; reflexivity.
+intros [|n] [|m]; simpl; trivial. now rewrite Pmult_comm.
Qed.
Theorem Nmult_assoc : forall n m p:N, n * (m * p) = n * m * p.
@@ -357,7 +370,7 @@ intros.
destruct n; try reflexivity.
destruct m; try reflexivity.
destruct p; try reflexivity.
-simpl in |- *; rewrite Pmult_assoc; reflexivity.
+simpl; rewrite Pmult_assoc; reflexivity.
Qed.
Theorem Nmult_plus_distr_r : forall n m p:N, (n + m) * p = n * p + m * p.
@@ -365,7 +378,7 @@ Proof.
intros.
destruct n; try reflexivity.
destruct m; destruct p; try reflexivity.
-simpl in |- *; rewrite Pmult_plus_distr_r; reflexivity.
+simpl; rewrite Pmult_plus_distr_r; reflexivity.
Qed.
Theorem Nmult_plus_distr_l : forall n m p:N, p * (n + m) = p * n + p * m.
@@ -400,7 +413,7 @@ Qed.
Theorem Ncompare_Eq_eq : forall n m:N, (n ?= m) = Eq -> n = m.
Proof.
-destruct n as [| n]; destruct m as [| m]; simpl in |- *; intro H;
+destruct n as [| n]; destruct m as [| m]; simpl; intro H;
reflexivity || (try discriminate H).
rewrite (Pcompare_Eq_eq n m H); reflexivity.
Qed.
@@ -509,22 +522,6 @@ Proof.
now apply (Pplus_lt_mono_l p).
Qed.
-Lemma Nmult_lt_mono_l : forall n m p, N0<n -> m<p -> n*m<n*p.
-Proof.
- intros [|n] m p. discriminate. intros _.
- destruct m, p; try discriminate. auto.
- simpl.
- apply Pmult_lt_mono_l.
-Qed.
-
-Lemma Nmult_le_mono_l : forall n m p, m<=p -> n*m<=n*p.
-Proof.
- intros [|n] m p. intros _ H. discriminate.
- intros. apply Nle_lteq. apply Nle_lteq in H. destruct H; [left|right].
- now apply Nmult_lt_mono_l.
- congruence.
-Qed.
-
(** 0 is the least natural number *)
Theorem Ncompare_0 : forall n : N, Ncompare n N0 <> Lt.
@@ -567,9 +564,10 @@ Qed.
(** Power *)
Definition Npow n p :=
- match p with
- | N0 => Npos 1
- | Npos p => Piter_op Nmult p n
+ match p, n with
+ | N0, _ => Npos 1
+ | _, N0 => N0
+ | Npos p, Npos q => Npos (Ppow q p)
end.
Infix "^" := Npow : N_scope.
@@ -579,53 +577,32 @@ Proof. reflexivity. Qed.
Lemma Npow_succ_r : forall n p, n^(Nsucc p) = n * n^p.
Proof.
- intros n p; destruct p; simpl.
- now rewrite Nmult_1_r.
- apply Piter_op_succ. apply Nmult_assoc.
+ intros [|q] [|p]; simpl; trivial; f_equal.
+ apply Ppow_succ_r.
Qed.
(** Base-2 logarithm *)
-Fixpoint Plog2_N (p:positive) : N :=
- match p with
- | p~0 => Nsucc (Plog2_N p)
- | p~1 => Nsucc (Plog2_N p)
- | 1 => N0
- end%positive.
-
Definition Nlog2 n :=
match n with
- | N0 => N0
- | Npos p => Plog2_N p
+ | N0 => N0
+ | Npos 1 => N0
+ | Npos (p~0) => Npos (Psize_pos p)
+ | Npos (p~1) => Npos (Psize_pos p)
end.
-Lemma Plog2_N_spec : forall p,
- (Npos 2)^(Plog2_N p) <= Npos p < (Npos 2)^(Nsucc (Plog2_N p)).
-Proof.
- induction p; simpl; try rewrite 2 Npow_succ_r.
- (* p~1 *)
- change (Npos p~1) with (Nsucc (Npos 2 * Npos p)).
- split; destruct IHp as [LE LT].
- apply Nle_trans with (Npos 2 * Npos p).
- now apply Nmult_le_mono_l.
- apply Nle_lteq. left.
- apply Ncompare_n_Sm. now right.
- apply Nle_succ_l. apply Nle_succ_l in LT.
- change (Nsucc (Nsucc (Npos 2 * Npos p))) with (Npos 2 * (Nsucc (Npos p))).
- now apply Nmult_le_mono_l.
- (* p~0 *)
- change (Npos p~0) with (Npos 2 * Npos p).
- split; destruct IHp.
- now apply Nmult_le_mono_l.
- now apply Nmult_lt_mono_l.
- (* 1 *)
- now split.
-Qed.
-
Lemma Nlog2_spec : forall n, N0 < n ->
(Npos 2)^(Nlog2 n) <= n < (Npos 2)^(Nsucc (Nlog2 n)).
Proof.
- intros [|n] Hn. discriminate. apply Plog2_N_spec.
+ intros [|[p|p|]] H; discriminate H || clear H; simpl; split.
+ eapply Nle_trans with (Npos (p~0)).
+ apply Psize_pos_le.
+ apply Nle_lteq; left. exact (Pcompare_p_Sp (p~0)).
+ apply Psize_pos_gt.
+ apply Psize_pos_le.
+ apply Psize_pos_gt.
+ discriminate.
+ reflexivity.
Qed.
Lemma Nlog2_nonpos : forall n, n<=N0 -> Nlog2 n = N0.
@@ -643,8 +620,8 @@ Definition Neven n :=
end.
Definition Nodd n := negb (Neven n).
-Local Notation "1" := (Npos xH) : N_scope.
-Local Notation "2" := (Npos (xO xH)) : N_scope.
+Local Notation "1" := (Npos 1) : N_scope.
+Local Notation "2" := (Npos 2) : N_scope.
Lemma Neven_spec : forall n, Neven n = true <-> exists m, n=2*m.
Proof.
diff --git a/theories/NArith/Ndigits.v b/theories/NArith/Ndigits.v
index 1992268ab..98e88c6a2 100644
--- a/theories/NArith/Ndigits.v
+++ b/theories/NArith/Ndigits.v
@@ -6,308 +6,542 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-Require Import Bool Setoid Bvector BinPos BinNat.
+Require Import Bool Morphisms Setoid Bvector BinPos BinNat Wf_nat
+ Pnat Nnat Ndiv_def.
+
+Local Open Scope positive_scope.
(** Operation over bits of a [N] number. *)
-(** [xor] *)
+(** Logical [or] *)
+
+Fixpoint Por (p q : positive) : positive :=
+ match p, q with
+ | 1, q~0 => q~1
+ | 1, _ => q
+ | p~0, 1 => p~1
+ | _, 1 => p
+ | p~0, q~0 => (Por p q)~0
+ | p~0, q~1 => (Por p q)~1
+ | p~1, q~0 => (Por p q)~1
+ | p~1, q~1 => (Por p q)~1
+ end.
-Fixpoint Pxor (p1 p2:positive) : N :=
- match p1, p2 with
- | xH, xH => N0
- | xH, xO p2 => Npos (xI p2)
- | xH, xI p2 => Npos (xO p2)
- | xO p1, xH => Npos (xI p1)
- | xO p1, xO p2 => Ndouble (Pxor p1 p2)
- | xO p1, xI p2 => Ndouble_plus_one (Pxor p1 p2)
- | xI p1, xH => Npos (xO p1)
- | xI p1, xO p2 => Ndouble_plus_one (Pxor p1 p2)
- | xI p1, xI p2 => Ndouble (Pxor p1 p2)
+Definition Nor n m :=
+ match n, m with
+ | N0, _ => m
+ | _, N0 => n
+ | Npos p, Npos q => Npos (Por p q)
+ end.
+
+(** Logical [and] *)
+
+Fixpoint Pand (p q : positive) : N :=
+ match p, q with
+ | 1, q~0 => N0
+ | 1, _ => Npos 1
+ | p~0, 1 => N0
+ | _, 1 => Npos 1
+ | p~0, q~0 => Ndouble (Pand p q)
+ | p~0, q~1 => Ndouble (Pand p q)
+ | p~1, q~0 => Ndouble (Pand p q)
+ | p~1, q~1 => Ndouble_plus_one (Pand p q)
end.
-Definition Nxor (n n':N) :=
- match n, n' with
- | N0, _ => n'
+Definition Nand n m :=
+ match n, m with
+ | N0, _ => N0
+ | _, N0 => N0
+ | Npos p, Npos q => Pand p q
+ end.
+
+(** Logical [diff] *)
+
+Fixpoint Pdiff (p q:positive) : N :=
+ match p, q with
+ | 1, q~0 => Npos 1
+ | 1, _ => N0
+ | _~0, 1 => Npos p
+ | p~1, 1 => Npos (p~0)
+ | p~0, q~0 => Ndouble (Pdiff p q)
+ | p~0, q~1 => Ndouble (Pdiff p q)
+ | p~1, q~1 => Ndouble (Pdiff p q)
+ | p~1, q~0 => Ndouble_plus_one (Pdiff p q)
+ end.
+
+Fixpoint Ndiff n m :=
+ match n, m with
+ | N0, _ => N0
| _, N0 => n
- | Npos p, Npos p' => Pxor p p'
+ | Npos p, Npos q => Pdiff p q
+ end.
+
+(** [xor] *)
+
+Fixpoint Pxor (p q:positive) : N :=
+ match p, q with
+ | 1, 1 => N0
+ | 1, q~0 => Npos (q~1)
+ | 1, q~1 => Npos (q~0)
+ | p~0, 1 => Npos (p~1)
+ | p~0, q~0 => Ndouble (Pxor p q)
+ | p~0, q~1 => Ndouble_plus_one (Pxor p q)
+ | p~1, 1 => Npos (p~0)
+ | p~1, q~0 => Ndouble_plus_one (Pxor p q)
+ | p~1, q~1 => Ndouble (Pxor p q)
+ end.
+
+Definition Nxor (n m:N) :=
+ match n, m with
+ | N0, _ => m
+ | _, N0 => n
+ | Npos p, Npos q => Pxor p q
+ end.
+
+(** For proving properties of these operations, we will use
+ an equivalence with functional streams of bit, cf [eqf] below *)
+
+(** Shift *)
+
+Definition Nshiftl_nat (a:N)(n:nat) := iter_nat n _ Ndouble a.
+
+Definition Nshiftr_nat (a:N)(n:nat) := iter_nat n _ Ndiv2 a.
+
+Definition Nshiftr a n :=
+ match n with
+ | N0 => a
+ | Npos p => iter_pos p _ Ndiv2 a
+ end.
+
+Definition Nshiftl a n :=
+ match a, n with
+ | _, N0 => a
+ | N0, _ => a
+ | Npos p, Npos q => Npos (iter_pos q _ xO p)
end.
-Lemma Nxor_neutral_left : forall n:N, Nxor N0 n = n.
+(** Checking whether a particular bit is set on not *)
+
+Fixpoint Pbit (p:positive) : nat -> bool :=
+ match p with
+ | 1 => fun n => match n with
+ | O => true
+ | S _ => false
+ end
+ | p~0 => fun n => match n with
+ | O => false
+ | S n' => Pbit p n'
+ end
+ | p~1 => fun n => match n with
+ | O => true
+ | S n' => Pbit p n'
+ end
+ end.
+
+Definition Nbit (a:N) :=
+ match a with
+ | N0 => fun _ => false
+ | Npos p => Pbit p
+ end.
+
+(** Same, but with index in N *)
+
+Fixpoint Ptestbit p n :=
+ match p, n with
+ | p~0, N0 => false
+ | _, N0 => true
+ | 1, _ => false
+ | p~0, _ => Ptestbit p (Npred n)
+ | p~1, _ => Ptestbit p (Npred n)
+ end.
+
+Definition Ntestbit a n :=
+ match a with
+ | N0 => false
+ | Npos p => Ptestbit p n
+ end.
+
+Local Close Scope positive_scope.
+Local Open Scope N_scope.
+
+(** Equivalence of Pbit and Ptestbit *)
+
+Lemma Ptestbit_Pbit :
+ forall p n, Ptestbit p (N_of_nat n) = Pbit p n.
Proof.
- trivial.
+ induction p as [p IH|p IH| ]; intros n; simpl.
+ rewrite <- N_of_pred, IH; destruct n; trivial.
+ rewrite <- N_of_pred, IH; destruct n; trivial.
+ destruct n; trivial.
Qed.
-Lemma Nxor_neutral_right : forall n:N, Nxor n N0 = n.
+Lemma Ntestbit_Nbit : forall a n, Ntestbit a (N_of_nat n) = Nbit a n.
Proof.
- destruct n; trivial.
+ destruct a. trivial. apply Ptestbit_Pbit.
Qed.
-Lemma Nxor_comm : forall n n':N, Nxor n n' = Nxor n' n.
+Lemma Pbit_Ptestbit :
+ forall p n, Pbit p (nat_of_N n) = Ptestbit p n.
Proof.
- destruct n; destruct n'; simpl; auto.
- generalize p0; clear p0; induction p as [p Hrecp| p Hrecp| ]; simpl;
- auto.
- destruct p0; trivial; rewrite Hrecp; trivial.
- destruct p0; trivial; rewrite Hrecp; trivial.
- destruct p0 as [p| p| ]; simpl; auto.
+ intros; now rewrite <- Ptestbit_Pbit, N_of_nat_of_N.
Qed.
-Lemma Nxor_nilpotent : forall n:N, Nxor n n = N0.
+Lemma Nbit_Ntestbit :
+ forall a n, Nbit a (nat_of_N n) = Ntestbit a n.
Proof.
- destruct n; trivial.
- simpl. induction p as [p IHp| p IHp| ]; trivial.
- simpl. rewrite IHp; reflexivity.
- simpl. rewrite IHp; reflexivity.
+ destruct a. trivial. apply Pbit_Ptestbit.
Qed.
-(** Checking whether a particular bit is set on not *)
+(** Equivalence of shifts, N and nat versions *)
-Fixpoint Pbit (p:positive) : nat -> bool :=
- match p with
- | xH => fun n:nat => match n with
- | O => true
- | S _ => false
- end
- | xO p =>
- fun n:nat => match n with
- | O => false
- | S n' => Pbit p n'
- end
- | xI p => fun n:nat => match n with
- | O => true
- | S n' => Pbit p n'
- end
- end.
+Lemma Nshiftr_nat_equiv :
+ forall a n, Nshiftr_nat a (nat_of_N n) = Nshiftr a n.
+Proof.
+ intros a [|n]; simpl; unfold Nshiftr_nat.
+ trivial.
+ symmetry. apply iter_nat_of_P.
+Qed.
-Definition Nbit (a:N) :=
- match a with
- | N0 => fun _ => false
- | Npos p => Pbit p
- end.
+Lemma Nshiftr_equiv_nat :
+ forall a n, Nshiftr a (N_of_nat n) = Nshiftr_nat a n.
+Proof.
+ intros. now rewrite <- Nshiftr_nat_equiv, nat_of_N_of_nat.
+Qed.
+
+Lemma Nshiftl_nat_equiv :
+ forall a n, Nshiftl_nat a (nat_of_N n) = Nshiftl a n.
+Proof.
+ intros [|a] [|n]; simpl; unfold Nshiftl_nat; trivial.
+ apply iter_nat_invariant; intros; now subst.
+ rewrite <- iter_nat_of_P. symmetry. now apply iter_pos_swap_gen.
+Qed.
+
+Lemma Nshiftl_equiv_nat :
+ forall a n, Nshiftl a (N_of_nat n) = Nshiftl_nat a n.
+Proof.
+ intros. now rewrite <- Nshiftl_nat_equiv, nat_of_N_of_nat.
+Qed.
+
+(** Correctness proofs for shifts *)
-(** Auxiliary results about streams of bits *)
+Lemma Nshiftl_mult_pow : forall a n, Nshiftl a n = a * 2^n.
+Proof.
+ intros [|a] [|n]; simpl; trivial.
+ now rewrite Pmult_1_r.
+ f_equal.
+ set (f x := Pmult x a).
+ rewrite Pmult_comm. fold (f (2^n))%positive.
+ change a with (f xH).
+ unfold Ppow. symmetry. now apply iter_pos_swap_gen.
+Qed.
+
+(*
+Lemma Nshiftr_div_pow : forall a n, Nshiftr a n = a / 2^n.
+*)
+
+(** Equality over functional streams of bits *)
Definition eqf (f g:nat -> bool) := forall n:nat, f n = g n.
-Lemma eqf_sym : forall f f':nat -> bool, eqf f f' -> eqf f' f.
+Instance eqf_equiv : Equivalence eqf.
+Proof.
+ split; congruence.
+Qed.
+
+Local Infix "==" := eqf (at level 70, no associativity).
+
+(** If two numbers produce the same stream of bits, they are equal. *)
+
+Local Notation Step H := (fun n => H (S n)).
+
+Lemma Pbit_faithful_0 : forall p, ~(Pbit p == (fun _ => false)).
Proof.
- unfold eqf. intros. rewrite H. reflexivity.
+ induction p as [p IHp|p IHp| ]; intros H; try discriminate (H O).
+ apply (IHp (Step H)).
Qed.
-Lemma eqf_refl : forall f:nat -> bool, eqf f f.
+Lemma Pbit_faithful : forall p p', Pbit p == Pbit p' -> p = p'.
Proof.
- unfold eqf. trivial.
+ induction p as [p IHp|p IHp| ]; intros [p'|p'|] H; trivial;
+ try discriminate (H O).
+ f_equal. apply (IHp _ (Step H)).
+ destruct (Pbit_faithful_0 _ (Step H)).
+ f_equal. apply (IHp _ (Step H)).
+ symmetry in H. destruct (Pbit_faithful_0 _ (Step H)).
Qed.
-Lemma eqf_trans :
- forall f f' f'':nat -> bool, eqf f f' -> eqf f' f'' -> eqf f f''.
+Lemma Nbit_faithful : forall n n', Nbit n == Nbit n' -> n = n'.
Proof.
- unfold eqf. intros. rewrite H. exact (H0 n).
+ intros [|p] [|p'] H; trivial.
+ symmetry in H. destruct (Pbit_faithful_0 _ H).
+ destruct (Pbit_faithful_0 _ H).
+ f_equal. apply Pbit_faithful, H.
Qed.
+Lemma Nbit_faithful_iff : forall n n', Nbit n == Nbit n' <-> n = n'.
+Proof.
+ split. apply Nbit_faithful. intros; now subst.
+Qed.
+
+
+(** Bit operations for functional streams of bits *)
+
+Definition orf (f g:nat -> bool) (n:nat) := (f n) || (g n).
+Definition andf (f g:nat -> bool) (n:nat) := (f n) && (g n).
+Definition difff (f g:nat -> bool) (n:nat) := (f n) && negb (g n).
Definition xorf (f g:nat -> bool) (n:nat) := xorb (f n) (g n).
-Lemma xorf_eq :
- forall f f', eqf (xorf f f') (fun n => false) -> eqf f f'.
+Instance eqf_orf : Proper (eqf==>eqf==>eqf) orf.
Proof.
- unfold eqf, xorf. intros. apply xorb_eq, H.
+ unfold orf. congruence.
Qed.
-Lemma xorf_assoc :
- forall f f' f'',
- eqf (xorf (xorf f f') f'') (xorf f (xorf f' f'')).
+Instance eqf_andf : Proper (eqf==>eqf==>eqf) andf.
Proof.
- unfold eqf, xorf. intros. apply xorb_assoc.
+ unfold andf. congruence.
Qed.
-Lemma eqf_xorf :
- forall f f' f'' f''',
- eqf f f' -> eqf f'' f''' -> eqf (xorf f f'') (xorf f' f''').
+Instance eqf_difff : Proper (eqf==>eqf==>eqf) difff.
Proof.
- unfold eqf, xorf. intros. rewrite H. rewrite H0. reflexivity.
+ unfold difff. congruence.
Qed.
-(** End of auxilliary results *)
+Instance eqf_xorf : Proper (eqf==>eqf==>eqf) xorf.
+Proof.
+ unfold xorf. congruence.
+Qed.
-(** This part is aimed at proving that if two numbers produce
- the same stream of bits, then they are equal. *)
+(** We now describe the semantics of [Nxor] and other bitwise
+ operations in terms of bit streams. *)
-Lemma Nbit_faithful_1 : forall a:N, eqf (Nbit N0) (Nbit a) -> N0 = a.
+Lemma Pxor_semantics : forall p p',
+ Nbit (Pxor p p') == xorf (Pbit p) (Pbit p').
Proof.
- destruct a. trivial.
- induction p as [p IHp| p IHp| ]; intro H.
- absurd (N0 = Npos p). discriminate.
- exact (IHp (fun n => H (S n))).
- absurd (N0 = Npos p). discriminate.
- exact (IHp (fun n => H (S n))).
- absurd (false = true). discriminate.
- exact (H 0).
+ induction p as [p IHp|p IHp|]; intros [p'|p'|] [|n]; trivial; simpl;
+ (specialize (IHp p'); destruct Pxor; trivial; apply (IHp n)) ||
+ (unfold xorf; now rewrite ?xorb_false_l, ?xorb_false_r).
Qed.
-Lemma Nbit_faithful_2 :
- forall a:N, eqf (Nbit (Npos 1)) (Nbit a) -> Npos 1 = a.
+Lemma Nxor_semantics : forall a a',
+ Nbit (Nxor a a') == xorf (Nbit a) (Nbit a').
Proof.
- destruct a. intros. absurd (true = false). discriminate.
- exact (H 0).
- destruct p. intro H. absurd (N0 = Npos p). discriminate.
- exact (Nbit_faithful_1 (Npos p) (fun n:nat => H (S n))).
- intros. absurd (true = false). discriminate.
- exact (H 0).
- trivial.
+ intros [|p] [|p'] n; simpl; unfold xorf; trivial.
+ now rewrite xorb_false_l.
+ now rewrite xorb_false_r.
+ apply Pxor_semantics.
Qed.
-Lemma Nbit_faithful_3 :
- forall (a:N) (p:positive),
- (forall p':positive, eqf (Nbit (Npos p)) (Nbit (Npos p')) -> p = p') ->
- eqf (Nbit (Npos (xO p))) (Nbit a) -> Npos (xO p) = a.
+Lemma Por_semantics : forall p p',
+ Pbit (Por p p') == orf (Pbit p) (Pbit p').
Proof.
- destruct a; intros. cut (eqf (Nbit N0) (Nbit (Npos (xO p)))).
- intro. rewrite (Nbit_faithful_1 (Npos (xO p)) H1). reflexivity.
- unfold eqf. intro. unfold eqf in H0. rewrite H0. reflexivity.
- destruct p. discriminate (H0 O).
- rewrite (H p (fun n => H0 (S n))). reflexivity.
- discriminate (H0 0).
+ induction p as [p IHp|p IHp|]; intros [p'|p'|] [|n]; trivial;
+ unfold orf; apply (IHp p' n) || now rewrite orb_false_r.
Qed.
-Lemma Nbit_faithful_4 :
- forall (a:N) (p:positive),
- (forall p':positive, eqf (Nbit (Npos p)) (Nbit (Npos p')) -> p = p') ->
- eqf (Nbit (Npos (xI p))) (Nbit a) -> Npos (xI p) = a.
+Lemma Nor_semantics : forall a a',
+ Nbit (Nor a a') == orf (Nbit a) (Nbit a').
Proof.
- destruct a; intros. cut (eqf (Nbit N0) (Nbit (Npos (xI p)))).
- intro. rewrite (Nbit_faithful_1 (Npos (xI p)) H1). reflexivity.
- intro. rewrite H0. reflexivity.
- destruct p. rewrite (H p (fun n:nat => H0 (S n))). reflexivity.
- discriminate (H0 0).
- cut (eqf (Nbit (Npos 1)) (Nbit (Npos (xI p0)))).
- intro. discriminate (Nbit_faithful_1 (Npos p0) (fun n:nat => H1 (S n))).
- intro. rewrite H0. reflexivity.
+ intros [|p] [|p'] n; simpl; unfold orf; trivial.
+ now rewrite orb_false_r.
+ apply Por_semantics.
Qed.
-Lemma Nbit_faithful : forall a a':N, eqf (Nbit a) (Nbit a') -> a = a'.
+Lemma Pand_semantics : forall p p',
+ Nbit (Pand p p') == andf (Pbit p) (Pbit p').
Proof.
- destruct a. exact Nbit_faithful_1.
- induction p. intros a' H. apply Nbit_faithful_4. intros.
- assert (Npos p = Npos p') by exact (IHp (Npos p') H0).
- inversion H1. reflexivity.
- assumption.
- intros. apply Nbit_faithful_3. intros.
- assert (Npos p = Npos p') by exact (IHp (Npos p') H0).
- inversion H1. reflexivity.
- assumption.
- exact Nbit_faithful_2.
+ induction p as [p IHp|p IHp|]; intros [p'|p'|] [|n]; trivial; simpl;
+ (specialize (IHp p'); destruct Pand; trivial; apply (IHp n)) ||
+ (unfold andf; now rewrite andb_false_r).
Qed.
-(** We now describe the semantics of [Nxor] in terms of bit streams. *)
+Lemma Nand_semantics : forall a a',
+ Nbit (Nand a a') == andf (Nbit a) (Nbit a').
+Proof.
+ intros [|p] [|p'] n; simpl; unfold andf; trivial.
+ now rewrite andb_false_r.
+ apply Pand_semantics.
+Qed.
-Lemma Nxor_sem_1 : forall a':N, Nbit (Nxor N0 a') 0 = Nbit a' 0.
+Lemma Pdiff_semantics : forall p p',
+ Nbit (Pdiff p p') == difff (Pbit p) (Pbit p').
Proof.
- trivial.
+ induction p as [p IHp|p IHp|]; intros [p'|p'|] [|n]; trivial; simpl;
+ (specialize (IHp p'); destruct Pdiff; trivial; apply (IHp n)) ||
+ (unfold difff; simpl; now rewrite andb_true_r).
Qed.
-Lemma Nxor_sem_2 :
- forall a':N, Nbit (Nxor (Npos 1) a') 0 = negb (Nbit a' 0).
+Lemma Ndiff_semantics : forall a a',
+ Nbit (Ndiff a a') == difff (Nbit a) (Nbit a').
Proof.
- intro. destruct a'. trivial.
- destruct p; trivial.
+ intros [|p] [|p'] n; simpl; unfold difff; trivial.
+ simpl. now rewrite andb_true_r.
+ apply Pdiff_semantics.
Qed.
-Lemma Nxor_sem_3 :
- forall (p:positive) (a':N),
- Nbit (Nxor (Npos (xO p)) a') 0 = Nbit a' 0.
+Hint Rewrite Nxor_semantics Nor_semantics
+ Nand_semantics Ndiff_semantics : bitwise_semantics.
+
+Ltac bitwise_semantics :=
+ apply Nbit_faithful; autorewrite with bitwise_semantics;
+ intro n; unfold xorf, orf, andf, difff.
+
+(** Now, we can easily deduce properties of [Nxor] and others
+ from properties of [xorb] and others. *)
+
+Lemma Nxor_eq : forall a a', Nxor a a' = 0 -> a = a'.
Proof.
- intros. destruct a'. trivial.
- simpl. destruct p0; trivial.
- destruct (Pxor p p0); trivial.
- destruct (Pxor p p0); trivial.
+ intros a a' H. bitwise_semantics. apply xorb_eq.
+ rewrite <- Nbit_faithful_iff, Nxor_semantics in H. apply H.
Qed.
-Lemma Nxor_sem_4 :
- forall (p:positive) (a':N),
- Nbit (Nxor (Npos (xI p)) a') 0 = negb (Nbit a' 0).
+Lemma Nxor_nilpotent : forall a, Nxor a a = 0.
Proof.
- intros. destruct a'. trivial.
- simpl. destruct p0; trivial.
- destruct (Pxor p p0); trivial.
- destruct (Pxor p p0); trivial.
+ intros. bitwise_semantics. apply xorb_nilpotent.
Qed.
-Lemma Nxor_sem_5 :
- forall a a':N, Nbit (Nxor a a') 0 = xorf (Nbit a) (Nbit a') 0.
+Lemma Nxor_0_l : forall n, Nxor 0 n = n.
Proof.
- destruct a; intro. change (Nbit a' 0 = xorb false (Nbit a' 0)). rewrite false_xorb. trivial.
- destruct p. apply Nxor_sem_4.
- change (Nbit (Nxor (Npos (xO p)) a') 0 = xorb false (Nbit a' 0)).
- rewrite false_xorb. apply Nxor_sem_3. apply Nxor_sem_2.
+ trivial.
Qed.
+Notation Nxor_neutral_left := Nxor_0_l (only parsing).
-Lemma Nxor_sem_6 :
- forall n:nat,
- (forall a a':N, Nbit (Nxor a a') n = xorf (Nbit a) (Nbit a') n) ->
- forall a a':N,
- Nbit (Nxor a a') (S n) = xorf (Nbit a) (Nbit a') (S n).
+Lemma Nxor_0_r : forall n, Nxor n 0 = n.
Proof.
- intros.
-(* pose proof (fun p1 p2 => H (Npos p1) (Npos p2)) as H'. clear H. rename H' into H.*)
- generalize (fun p1 p2 => H (Npos p1) (Npos p2)); clear H; intro H.
- unfold xorf in *.
- destruct a as [|p]. simpl Nbit; rewrite false_xorb. reflexivity.
- destruct a' as [|p0].
- simpl Nbit; rewrite xorb_false. reflexivity.
- destruct p. destruct p0; simpl Nbit in *.
- rewrite <- H; simpl; case (Pxor p p0); trivial.
- rewrite <- H; simpl; case (Pxor p p0); trivial.
- rewrite xorb_false. reflexivity.
- destruct p0; simpl Nbit in *.
- rewrite <- H; simpl; case (Pxor p p0); trivial.
- rewrite <- H; simpl; case (Pxor p p0); trivial.
- rewrite xorb_false. reflexivity.
- simpl Nbit. rewrite false_xorb. destruct p0; trivial.
-Qed.
-
-Lemma Nxor_semantics :
- forall a a':N, eqf (Nbit (Nxor a a')) (xorf (Nbit a) (Nbit a')).
-Proof.
- unfold eqf. intros; generalize a, a'. induction n.
- apply Nxor_sem_5. apply Nxor_sem_6; assumption.
-Qed.
-
-(** Consequences:
- - only equal numbers lead to a null xor
- - xor is associative
-*)
+ destruct n; trivial.
+Qed.
+Notation Nxor_neutral_right := Nxor_0_r (only parsing).
-Lemma Nxor_eq : forall a a':N, Nxor a a' = N0 -> a = a'.
+Lemma Nxor_comm : forall a a', Nxor a a' = Nxor a' a.
Proof.
- intros. apply Nbit_faithful, xorf_eq. apply eqf_trans with (f' := Nbit (Nxor a a')).
- apply eqf_sym, Nxor_semantics.
- rewrite H. unfold eqf. trivial.
+ intros. bitwise_semantics. apply xorb_comm.
Qed.
Lemma Nxor_assoc :
- forall a a' a'':N, Nxor (Nxor a a') a'' = Nxor a (Nxor a' a'').
-Proof.
- intros. apply Nbit_faithful.
- apply eqf_trans with (xorf (xorf (Nbit a) (Nbit a')) (Nbit a'')).
- apply eqf_trans with (xorf (Nbit (Nxor a a')) (Nbit a'')).
- apply Nxor_semantics.
- apply eqf_xorf. apply Nxor_semantics.
- apply eqf_refl.
- apply eqf_trans with (xorf (Nbit a) (xorf (Nbit a') (Nbit a''))).
- apply xorf_assoc.
- apply eqf_trans with (xorf (Nbit a) (Nbit (Nxor a' a''))).
- apply eqf_xorf. apply eqf_refl.
- apply eqf_sym, Nxor_semantics.
- apply eqf_sym, Nxor_semantics.
+ forall a a' a'', Nxor (Nxor a a') a'' = Nxor a (Nxor a' a'').
+Proof.
+ intros. bitwise_semantics. apply xorb_assoc.
+Qed.
+
+Lemma Nor_0_l : forall n, Nor 0 n = n.
+Proof.
+ trivial.
+Qed.
+
+Lemma Nor_0_r : forall n, Nor n 0 = n.
+Proof.
+ destruct n; trivial.
+Qed.
+
+Lemma Nor_comm : forall a a', Nor a a' = Nor a' a.
+Proof.
+ intros. bitwise_semantics. apply orb_comm.
+Qed.
+
+Lemma Nor_assoc :
+ forall a a' a'', Nor a (Nor a' a'') = Nor (Nor a a') a''.
+Proof.
+ intros. bitwise_semantics. apply orb_assoc.
+Qed.
+
+Lemma Nor_diag : forall a, Nor a a = a.
+Proof.
+ intros. bitwise_semantics. apply orb_diag.
+Qed.
+
+Lemma Nand_0_l : forall n, Nand 0 n = 0.
+Proof.
+ trivial.
+Qed.
+
+Lemma Nand_0_r : forall n, Nand n 0 = 0.
+Proof.
+ destruct n; trivial.
+Qed.
+
+Lemma Nand_comm : forall a a', Nand a a' = Nand a' a.
+Proof.
+ intros. bitwise_semantics. apply andb_comm.
+Qed.
+
+Lemma Nand_assoc :
+ forall a a' a'', Nand a (Nand a' a'') = Nand (Nand a a') a''.
+Proof.
+ intros. bitwise_semantics. apply andb_assoc.
+Qed.
+
+Lemma Nand_diag : forall a, Nand a a = a.
+Proof.
+ intros. bitwise_semantics. apply andb_diag.
+Qed.
+
+Lemma Ndiff_0_l : forall n, Ndiff 0 n = 0.
+Proof.
+ trivial.
Qed.
+Lemma Ndiff_0_r : forall n, Ndiff n 0 = n.
+Proof.
+ destruct n; trivial.
+Qed.
+
+Lemma Ndiff_diag : forall a, Ndiff a a = 0.
+Proof.
+ intros. bitwise_semantics. apply andb_negb_r.
+Qed.
+
+Lemma Nor_and_distr_l : forall a b c,
+ Nor (Nand a b) c = Nand (Nor a c) (Nor b c).
+Proof.
+ intros. bitwise_semantics. apply orb_andb_distrib_l.
+Qed.
+
+Lemma Nor_and_distr_r : forall a b c,
+ Nor a (Nand b c) = Nand (Nor a b) (Nor a c).
+Proof.
+ intros. bitwise_semantics. apply orb_andb_distrib_r.
+Qed.
+
+Lemma Nand_or_distr_l : forall a b c,
+ Nand (Nor a b) c = Nor (Nand a c) (Nand b c).
+Proof.
+ intros. bitwise_semantics. apply andb_orb_distrib_l.
+Qed.
+
+Lemma Nand_or_distr_r : forall a b c,
+ Nand a (Nor b c) = Nor (Nand a b) (Nand a c).
+Proof.
+ intros. bitwise_semantics. apply andb_orb_distrib_r.
+Qed.
+
+Lemma Ndiff_diff_l : forall a b c,
+ Ndiff (Ndiff a b) c = Ndiff a (Nor b c).
+Proof.
+ intros. bitwise_semantics. now rewrite negb_orb, andb_assoc.
+Qed.
+
+Lemma Nor_diff_and : forall a b,
+ Nor (Ndiff a b) (Nand a b) = a.
+Proof.
+ intros. bitwise_semantics.
+ now rewrite <- andb_orb_distrib_r, orb_comm, orb_negb_r, andb_true_r.
+Qed.
+
+Lemma Nand_diff : forall a b,
+ Nand (Ndiff a b) b = 0.
+Proof.
+ intros. bitwise_semantics.
+ now rewrite <-andb_assoc, (andb_comm (negb _)), andb_negb_r, andb_false_r.
+Qed.
+
+Local Close Scope N_scope.
+
(** Checking whether a number is odd, i.e.
if its lower bit is set. *)
Definition Nbit0 (n:N) :=
match n with
| N0 => false
- | Npos (xO _) => false
+ | Npos (_~0) => false
| _ => true
end.
@@ -358,7 +592,7 @@ Qed.
Lemma Nxor_bit0 :
forall a a':N, Nbit0 (Nxor a a') = xorb (Nbit0 a) (Nbit0 a').
Proof.
- intros. rewrite <- Nbit0_correct, (Nxor_semantics a a' 0).
+ intros. rewrite <- Nbit0_correct, (Nxor_semantics a a' O).
unfold xorf. rewrite Nbit0_correct, Nbit0_correct. reflexivity.
Qed.
@@ -554,7 +788,7 @@ Qed.
(** Number of digits in a number *)
Definition Nsize (n:N) : nat := match n with
- | N0 => 0%nat
+ | N0 => O
| Npos p => Psize p
end.
@@ -719,18 +953,40 @@ induction n; simpl in *; intros; destruct p; auto with arith.
inversion H; inversion H1.
Qed.
-(** Xor is the same in the two worlds. *)
+(** Binary bitwise operations are the same in the two worlds. *)
Lemma Nxor_BVxor : forall n (bv bv' : Bvector n),
Bv2N _ (BVxor _ bv bv') = Nxor (Bv2N _ bv) (Bv2N _ bv').
Proof.
-induction n.
-intros.
+induction n; intros bv bv'.
+rewrite (V0_eq _ bv), (V0_eq _ bv'); simpl; auto.
+rewrite (VSn_eq _ _ bv), (VSn_eq _ _ bv'); simpl; auto.
+rewrite IHn.
+destruct (Vhead bool n bv), (Vhead bool n bv'),
+ (Bv2N n (Vtail bool n bv)), (Bv2N n (Vtail bool n bv'));
+ simpl; auto.
+Qed.
+
+Lemma Nor_BVor : forall n (bv bv' : Bvector n),
+ Bv2N _ (BVor _ bv bv') = Nor (Bv2N _ bv) (Bv2N _ bv').
+Proof.
+induction n; intros bv bv'.
rewrite (V0_eq _ bv), (V0_eq _ bv'); simpl; auto.
-intros.
rewrite (VSn_eq _ _ bv), (VSn_eq _ _ bv'); simpl; auto.
rewrite IHn.
-destruct (Vhead bool n bv); destruct (Vhead bool n bv');
- destruct (Bv2N n (Vtail bool n bv)); destruct (Bv2N n (Vtail bool n bv')); simpl; auto.
+destruct (Vhead bool n bv), (Vhead bool n bv'),
+ (Bv2N n (Vtail bool n bv)), (Bv2N n (Vtail bool n bv'));
+ simpl; auto.
Qed.
+Lemma Nand_BVand : forall n (bv bv' : Bvector n),
+ Bv2N _ (BVand _ bv bv') = Nand (Bv2N _ bv) (Bv2N _ bv').
+Proof.
+induction n; intros bv bv'.
+rewrite (V0_eq _ bv), (V0_eq _ bv'); simpl; auto.
+rewrite (VSn_eq _ _ bv), (VSn_eq _ _ bv'); simpl; auto.
+rewrite IHn.
+destruct (Vhead bool n bv), (Vhead bool n bv'),
+ (Bv2N n (Vtail bool n bv)), (Bv2N n (Vtail bool n bv'));
+ simpl; auto.
+Qed.
diff --git a/theories/NArith/Nnat.v b/theories/NArith/Nnat.v
index 93fdfff7a..05ca4a550 100644
--- a/theories/NArith/Nnat.v
+++ b/theories/NArith/Nnat.v
@@ -6,149 +6,86 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-Require Import Arith_base.
-Require Import Compare_dec.
-Require Import Sumbool.
-Require Import Div2.
-Require Import Min.
-Require Import Max.
-Require Import BinPos.
-Require Import BinNat.
-Require Import BinInt.
-Require Import Pnat.
-Require Import Znat.
-
-(** Translation from [N] to [nat] and back. *)
-
-Definition nat_of_N (a:N) :=
- match a with
- | N0 => 0%nat
- | Npos p => nat_of_P p
- end.
-
-Definition N_of_nat (n:nat) :=
- match n with
- | O => N0
- | S n' => Npos (P_of_succ_nat n')
- end.
+Require Import Arith_base Compare_dec Sumbool Div2 Min Max.
+Require Import BinPos BinNat Pnat.
Lemma N_of_nat_of_N : forall a:N, N_of_nat (nat_of_N a) = a.
Proof.
destruct a as [| p]. reflexivity.
- simpl in |- *. elim (ZL4 p). intros n H. rewrite H. simpl in |- *.
- rewrite <- nat_of_P_o_P_of_succ_nat_eq_succ in H.
+ simpl. elim (nat_of_P_is_S p). intros n H. rewrite H. simpl.
+ rewrite <- nat_of_P_of_succ_nat in H.
rewrite nat_of_P_inj with (1 := H). reflexivity.
Qed.
Lemma nat_of_N_of_nat : forall n:nat, nat_of_N (N_of_nat n) = n.
Proof.
induction n. trivial.
- intros. simpl in |- *. apply nat_of_P_o_P_of_succ_nat_eq_succ.
+ intros. simpl. apply nat_of_P_of_succ_nat.
Qed.
-(** Interaction of this translation and usual operations. *)
-
-Lemma nat_of_Ndouble : forall a, nat_of_N (Ndouble a) = 2*(nat_of_N a).
+Lemma nat_of_N_inj : forall n n', nat_of_N n = nat_of_N n' -> n = n'.
Proof.
- destruct a; simpl nat_of_N; auto.
- apply nat_of_P_xO.
+ intros n n' H.
+ rewrite <- (N_of_nat_of_N n), <- (N_of_nat_of_N n'). now f_equal.
Qed.
-Lemma N_of_double : forall n, N_of_nat (2*n) = Ndouble (N_of_nat n).
+Lemma N_of_nat_inj : forall n n', N_of_nat n = N_of_nat n' -> n = n'.
Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- rewrite <- nat_of_Ndouble.
- apply N_of_nat_of_N.
+ intros n n' H.
+ rewrite <- (nat_of_N_of_nat n), <- (nat_of_N_of_nat n'). now f_equal.
Qed.
-Lemma nat_of_Ndouble_plus_one :
- forall a, nat_of_N (Ndouble_plus_one a) = S (2*(nat_of_N a)).
+Hint Rewrite nat_of_N_of_nat N_of_nat_of_N : Nnat.
+
+(** Interaction of this translation and usual operations. *)
+
+Lemma nat_of_Ndouble : forall a, nat_of_N (Ndouble a) = 2*(nat_of_N a).
Proof.
- destruct a; simpl nat_of_N; auto.
- apply nat_of_P_xI.
+ destruct a; simpl nat_of_N; trivial. apply nat_of_P_xO.
Qed.
-Lemma N_of_double_plus_one :
- forall n, N_of_nat (S (2*n)) = Ndouble_plus_one (N_of_nat n).
+Lemma nat_of_Ndouble_plus_one :
+ forall a, nat_of_N (Ndouble_plus_one a) = S (2*(nat_of_N a)).
Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- rewrite <- nat_of_Ndouble_plus_one.
- apply N_of_nat_of_N.
+ destruct a; simpl nat_of_N; trivial. apply nat_of_P_xI.
Qed.
Lemma nat_of_Nsucc : forall a, nat_of_N (Nsucc a) = S (nat_of_N a).
Proof.
destruct a; simpl.
apply nat_of_P_xH.
- apply nat_of_P_succ_morphism.
-Qed.
-
-Lemma N_of_S : forall n, N_of_nat (S n) = Nsucc (N_of_nat n).
-Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- rewrite <- nat_of_Nsucc.
- apply N_of_nat_of_N.
+ apply Psucc_S.
Qed.
Lemma nat_of_Nplus :
forall a a', nat_of_N (Nplus a a') = (nat_of_N a)+(nat_of_N a').
Proof.
destruct a; destruct a'; simpl; auto.
- apply nat_of_P_plus_morphism.
+ apply Pplus_plus.
Qed.
-Lemma N_of_plus :
- forall n n', N_of_nat (n+n') = Nplus (N_of_nat n) (N_of_nat n').
+Lemma nat_of_Nmult :
+ forall a a', nat_of_N (Nmult a a') = (nat_of_N a)*(nat_of_N a').
Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- pattern n' at 1; rewrite <- (nat_of_N_of_nat n').
- rewrite <- nat_of_Nplus.
- apply N_of_nat_of_N.
+ destruct a; destruct a'; simpl; auto.
+ apply Pmult_mult.
Qed.
Lemma nat_of_Nminus :
forall a a', nat_of_N (Nminus a a') = ((nat_of_N a)-(nat_of_N a'))%nat.
Proof.
- destruct a; destruct a'; simpl; auto with arith.
- case_eq (Pcompare p p0 Eq); simpl; intros.
- rewrite (Pcompare_Eq_eq _ _ H); auto with arith.
- rewrite Pminus_mask_diag. simpl. apply minus_n_n.
- rewrite Pminus_mask_Lt. pose proof (nat_of_P_lt_Lt_compare_morphism _ _ H). simpl.
- symmetry; apply not_le_minus_0. auto with arith. assumption.
- pose proof (Pminus_mask_Gt p p0 H) as H1. destruct H1 as [q [H1 _]]. rewrite H1; simpl.
- replace q with (Pminus p p0) by (unfold Pminus; now rewrite H1).
- apply nat_of_P_minus_morphism; auto.
-Qed.
-
-Lemma N_of_minus :
- forall n n', N_of_nat (n-n') = Nminus (N_of_nat n) (N_of_nat n').
-Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- pattern n' at 1; rewrite <- (nat_of_N_of_nat n').
- rewrite <- nat_of_Nminus.
- apply N_of_nat_of_N.
-Qed.
-
-Lemma nat_of_Nmult :
- forall a a', nat_of_N (Nmult a a') = (nat_of_N a)*(nat_of_N a').
-Proof.
- destruct a; destruct a'; simpl; auto.
- apply nat_of_P_mult_morphism.
+ intros [|a] [|a']; simpl; auto with arith.
+ destruct (Pcompare_spec a a').
+ subst. now rewrite Pminus_mask_diag, <- minus_n_n.
+ rewrite Pminus_mask_Lt by trivial. apply Plt_lt in H.
+ simpl; symmetry; apply not_le_minus_0; auto with arith.
+ destruct (Pminus_mask_Gt a a' (ZC2 _ _ H)) as (q & -> & Hq & _).
+ simpl. apply plus_minus. now rewrite <- Hq, Pplus_plus.
Qed.
-Lemma N_of_mult :
- forall n n', N_of_nat (n*n') = Nmult (N_of_nat n) (N_of_nat n').
+Lemma nat_of_Npred : forall a, nat_of_N (Npred a) = pred (nat_of_N a).
Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- pattern n' at 1; rewrite <- (nat_of_N_of_nat n').
- rewrite <- nat_of_Nmult.
- apply N_of_nat_of_N.
+ intros. rewrite pred_of_minus, Npred_minus. apply nat_of_Nminus.
Qed.
Lemma nat_of_Ndiv2 :
@@ -162,205 +99,92 @@ Proof.
rewrite div2_double; auto.
Qed.
-Lemma N_of_div2 :
- forall n, N_of_nat (div2 n) = Ndiv2 (N_of_nat n).
-Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- rewrite <- nat_of_Ndiv2.
- apply N_of_nat_of_N.
-Qed.
-
Lemma nat_of_Ncompare :
forall a a', Ncompare a a' = nat_compare (nat_of_N a) (nat_of_N a').
Proof.
- destruct a; destruct a'; simpl.
- reflexivity.
- assert (NZ : 0 < nat_of_P p) by auto using lt_O_nat_of_P.
- destruct nat_of_P; [inversion NZ|auto].
- assert (NZ : 0 < nat_of_P p) by auto using lt_O_nat_of_P.
- destruct nat_of_P; [inversion NZ|auto].
- apply nat_of_P_compare_morphism.
-Qed.
-
-Lemma N_of_nat_compare :
- forall n n', nat_compare n n' = Ncompare (N_of_nat n) (N_of_nat n').
-Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- pattern n' at 1; rewrite <- (nat_of_N_of_nat n').
- symmetry; apply nat_of_Ncompare.
-Qed.
-
-Lemma nat_of_Nmin :
- forall a a', nat_of_N (Nmin a a') = min (nat_of_N a) (nat_of_N a').
-Proof.
- intros; unfold Nmin; rewrite nat_of_Ncompare.
- rewrite nat_compare_equiv; unfold nat_compare_alt.
- destruct (lt_eq_lt_dec (nat_of_N a) (nat_of_N a')) as [[|]|];
- simpl; intros; symmetry; auto with arith.
- apply min_l; rewrite e; auto with arith.
-Qed.
-
-Lemma N_of_min :
- forall n n', N_of_nat (min n n') = Nmin (N_of_nat n) (N_of_nat n').
-Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- pattern n' at 1; rewrite <- (nat_of_N_of_nat n').
- rewrite <- nat_of_Nmin.
- apply N_of_nat_of_N.
+ destruct a; destruct a'; simpl; trivial.
+ now destruct (nat_of_P_is_S p) as (n,->).
+ now destruct (nat_of_P_is_S p) as (n,->).
+ apply Pcompare_nat_compare.
Qed.
Lemma nat_of_Nmax :
forall a a', nat_of_N (Nmax a a') = max (nat_of_N a) (nat_of_N a').
Proof.
- intros; unfold Nmax; rewrite nat_of_Ncompare.
- rewrite nat_compare_equiv; unfold nat_compare_alt.
- destruct (lt_eq_lt_dec (nat_of_N a) (nat_of_N a')) as [[|]|];
- simpl; intros; symmetry; auto with arith.
- apply max_r; rewrite e; auto with arith.
-Qed.
-
-Lemma N_of_max :
- forall n n', N_of_nat (max n n') = Nmax (N_of_nat n) (N_of_nat n').
-Proof.
- intros.
- pattern n at 1; rewrite <- (nat_of_N_of_nat n).
- pattern n' at 1; rewrite <- (nat_of_N_of_nat n').
- rewrite <- nat_of_Nmax.
- apply N_of_nat_of_N.
+ intros; unfold Nmax; rewrite nat_of_Ncompare. symmetry.
+ case nat_compare_spec; intros H; try rewrite H; auto with arith.
Qed.
-(** Properties concerning [Z_of_N] *)
-
-Lemma Z_of_nat_of_N : forall n:N, Z_of_nat (nat_of_N n) = Z_of_N n.
-Proof.
- destruct n; simpl; auto; symmetry; apply Zpos_eq_Z_of_nat_o_nat_of_P.
-Qed.
-
-Lemma Z_of_N_eq : forall n m, n = m -> Z_of_N n = Z_of_N m.
-Proof.
- intros; f_equal; assumption.
-Qed.
-
-Lemma Z_of_N_eq_rev : forall n m, Z_of_N n = Z_of_N m -> n = m.
-Proof.
- intros [|n] [|m]; simpl; intros; try discriminate; congruence.
-Qed.
-
-Lemma Z_of_N_eq_iff : forall n m, n = m <-> Z_of_N n = Z_of_N m.
-Proof.
- split; [apply Z_of_N_eq | apply Z_of_N_eq_rev].
-Qed.
-
-Lemma Z_of_N_le : forall n m, (n<=m)%N -> (Z_of_N n <= Z_of_N m)%Z.
-Proof.
- intros [|n] [|m]; simpl; auto.
-Qed.
-
-Lemma Z_of_N_le_rev : forall n m, (Z_of_N n <= Z_of_N m)%Z -> (n<=m)%N.
-Proof.
- intros [|n] [|m]; simpl; auto.
-Qed.
-
-Lemma Z_of_N_le_iff : forall n m, (n<=m)%N <-> (Z_of_N n <= Z_of_N m)%Z.
-Proof.
- split; [apply Z_of_N_le | apply Z_of_N_le_rev].
-Qed.
-
-Lemma Z_of_N_lt : forall n m, (n<m)%N -> (Z_of_N n < Z_of_N m)%Z.
-Proof.
- intros [|n] [|m]; simpl; auto.
-Qed.
-
-Lemma Z_of_N_lt_rev : forall n m, (Z_of_N n < Z_of_N m)%Z -> (n<m)%N.
-Proof.
- intros [|n] [|m]; simpl; auto.
-Qed.
-
-Lemma Z_of_N_lt_iff : forall n m, (n<m)%N <-> (Z_of_N n < Z_of_N m)%Z.
-Proof.
- split; [apply Z_of_N_lt | apply Z_of_N_lt_rev].
-Qed.
-
-Lemma Z_of_N_ge : forall n m, (n>=m)%N -> (Z_of_N n >= Z_of_N m)%Z.
-Proof.
- intros [|n] [|m]; simpl; auto.
-Qed.
-
-Lemma Z_of_N_ge_rev : forall n m, (Z_of_N n >= Z_of_N m)%Z -> (n>=m)%N.
-Proof.
- intros [|n] [|m]; simpl; auto.
-Qed.
-
-Lemma Z_of_N_ge_iff : forall n m, (n>=m)%N <-> (Z_of_N n >= Z_of_N m)%Z.
-Proof.
- split; [apply Z_of_N_ge | apply Z_of_N_ge_rev].
-Qed.
-
-Lemma Z_of_N_gt : forall n m, (n>m)%N -> (Z_of_N n > Z_of_N m)%Z.
+Lemma nat_of_Nmin :
+ forall a a', nat_of_N (Nmin a a') = min (nat_of_N a) (nat_of_N a').
Proof.
- intros [|n] [|m]; simpl; auto.
+ intros; unfold Nmin; rewrite nat_of_Ncompare. symmetry.
+ case nat_compare_spec; intros H; try rewrite H; auto with arith.
Qed.
-Lemma Z_of_N_gt_rev : forall n m, (Z_of_N n > Z_of_N m)%Z -> (n>m)%N.
-Proof.
- intros [|n] [|m]; simpl; auto.
-Qed.
+Hint Rewrite nat_of_Ndouble nat_of_Ndouble_plus_one
+ nat_of_Nsucc nat_of_Nplus nat_of_Nmult nat_of_Nminus
+ nat_of_Npred nat_of_Ndiv2 nat_of_Nmax nat_of_Nmin : Nnat.
-Lemma Z_of_N_gt_iff : forall n m, (n>m)%N <-> (Z_of_N n > Z_of_N m)%Z.
+Lemma N_of_double : forall n, N_of_nat (2*n) = Ndouble (N_of_nat n).
Proof.
- split; [apply Z_of_N_gt | apply Z_of_N_gt_rev].
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_of_nat : forall n:nat, Z_of_N (N_of_nat n) = Z_of_nat n.
+Lemma N_of_double_plus_one :
+ forall n, N_of_nat (S (2*n)) = Ndouble_plus_one (N_of_nat n).
Proof.
- destruct n; simpl; auto.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_pos : forall p:positive, Z_of_N (Npos p) = Zpos p.
+Lemma N_of_S : forall n, N_of_nat (S n) = Nsucc (N_of_nat n).
Proof.
- destruct p; simpl; auto.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_abs : forall z:Z, Z_of_N (Zabs_N z) = Zabs z.
+Lemma N_of_pred : forall n, N_of_nat (pred n) = Npred (N_of_nat n).
Proof.
- destruct z; simpl; auto.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_le_0 : forall n, (0 <= Z_of_N n)%Z.
+Lemma N_of_plus :
+ forall n n', N_of_nat (n+n') = Nplus (N_of_nat n) (N_of_nat n').
Proof.
- destruct n; intro; discriminate.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_plus : forall n m:N, Z_of_N (n+m) = (Z_of_N n + Z_of_N m)%Z.
+Lemma N_of_minus :
+ forall n n', N_of_nat (n-n') = Nminus (N_of_nat n) (N_of_nat n').
Proof.
- destruct n; destruct m; auto.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_mult : forall n m:N, Z_of_N (n*m) = (Z_of_N n * Z_of_N m)%Z.
+Lemma N_of_mult :
+ forall n n', N_of_nat (n*n') = Nmult (N_of_nat n) (N_of_nat n').
Proof.
- destruct n; destruct m; auto.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_minus : forall n m:N, Z_of_N (n-m) = Zmax 0 (Z_of_N n - Z_of_N m).
+Lemma N_of_div2 :
+ forall n, N_of_nat (div2 n) = Ndiv2 (N_of_nat n).
Proof.
- intros; do 3 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nminus; apply inj_minus.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_succ : forall n:N, Z_of_N (Nsucc n) = Zsucc (Z_of_N n).
+Lemma N_of_nat_compare :
+ forall n n', nat_compare n n' = Ncompare (N_of_nat n) (N_of_nat n').
Proof.
- intros; do 2 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nsucc; apply inj_S.
+ intros. rewrite nat_of_Ncompare. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_min : forall n m:N, Z_of_N (Nmin n m) = Zmin (Z_of_N n) (Z_of_N m).
+Lemma N_of_min :
+ forall n n', N_of_nat (min n n') = Nmin (N_of_nat n) (N_of_nat n').
Proof.
- intros; do 3 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nmin; apply inj_min.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-Lemma Z_of_N_max : forall n m:N, Z_of_N (Nmax n m) = Zmax (Z_of_N n) (Z_of_N m).
+Lemma N_of_max :
+ forall n n', N_of_nat (max n n') = Nmax (N_of_nat n) (N_of_nat n').
Proof.
- intros; do 3 rewrite <- Z_of_nat_of_N; rewrite nat_of_Nmax; apply inj_max.
+ intros. apply nat_of_N_inj. now autorewrite with Nnat.
Qed.
-