(* -*- coding: utf-8 -*- *)
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
Require Export BinNums BinPos Pnat.
Require Import BinNat Bool Equalities GenericMinMax
OrdersFacts ZAxioms ZProperties.
Require BinIntDef.
(***********************************************************)
(** * Binary Integers *)
(***********************************************************)
(** Initial author: Pierre Crégut, CNET, Lannion, France *)
(** The type [Z] and its constructors [Z0] and [Zpos] and [Zneg]
are now defined in [BinNums.v] *)
Local Open Scope Z_scope.
(** Every definitions and early properties about binary integers
are placed in a module [Z] for qualification purpose. *)
Module Z
<: ZAxiomsSig
<: UsualOrderedTypeFull
<: UsualDecidableTypeFull
<: TotalOrder.
(** * Definitions of operations, now in a separate file *)
Include BinIntDef.Z.
Register add as num.Z.add.
Register opp as num.Z.opp.
Register succ as num.Z.succ.
Register pred as num.Z.pred.
Register sub as num.Z.sub.
Register mul as num.Z.mul.
Register of_nat as num.Z.of_nat.
(** When including property functors, only inline t eq zero one two *)
Set Inline Level 30.
(** * Logic Predicates *)
Definition eq := @Logic.eq Z.
Definition eq_equiv := @eq_equivalence Z.
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.
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.
Register le as num.Z.le.
Register lt as num.Z.lt.
Register ge as num.Z.ge.
Register gt as num.Z.gt.
(** * Decidability of equality. *)
Definition eq_dec (x y : Z) : {x = y} + {x <> y}.
Proof.
decide equality; apply Pos.eq_dec.
Defined.
(** * 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 := _.
(** * 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.
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.
rewrite pos_sub_spec.
case Pos.compare_spec; auto; intros;
now rewrite Pos.add_comm, Pos.sub_add.
Qed.
(** Particular cases of the previous result *)
Lemma pos_sub_diag p : pos_sub p p = 0.
Proof.
now rewrite pos_sub_spec, Pos.compare_refl.
Qed.
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.
Lemma pos_sub_gt p q : (q < p)%positive -> pos_sub p q = pos (p - q).
Proof.
intros H. now rewrite pos_sub_spec, Pos.compare_antisym, H.
Qed.
(** The opposite of [pos_sub] is [pos_sub] with reversed arguments *)
Lemma pos_sub_opp p q : - pos_sub p q = pos_sub q p.
Proof.
revert q; induction p; destruct q; simpl; trivial;
rewrite <- IHp; now destruct pos_sub.
Qed.
(** 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. *)
Module Import Private_BootStrap.
(** ** Operations and constants *)
Lemma add_0_r n : n + 0 = n.
Proof.
now destruct n.
Qed.
Lemma mul_0_r n : n * 0 = 0.
Proof.
now destruct n.
Qed.
Lemma mul_1_l n : 1 * n = n.
Proof.
now destruct n.
Qed.
(** ** Addition is commutative *)
Lemma add_comm n m : n + m = m + n.
Proof.
destruct n, m; simpl; trivial; now rewrite Pos.add_comm.
Qed.
(** ** Opposite distributes over addition *)
Lemma opp_add_distr n m : - (n + m) = - n + - m.
Proof.
destruct n, m; simpl; trivial using pos_sub_opp.
Qed.
(** ** Opposite is injective *)
Lemma opp_inj n m : -n = -m -> n = m.
Proof.
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.
Local Arguments add !x !y.
Lemma add_assoc_pos p n m : pos p + (n + m) = pos p + n + m.
Proof.
destruct n as [|n|n], m as [|m|m]; simpl; trivial.
- now rewrite Pos.add_assoc.
- symmetry. apply pos_sub_add.
- symmetry. apply add_0_r.
- now rewrite <- pos_sub_add, add_comm, <- pos_sub_add, Pos.add_comm.
- apply opp_inj. rewrite !opp_add_distr, !pos_sub_opp.
rewrite add_comm, Pos.add_comm. apply pos_sub_add.
Qed.
Lemma add_assoc n m p : n + (m + p) = n + m + p.
Proof.
destruct n.
- trivial.
- apply add_assoc_pos.
- apply opp_inj. rewrite !opp_add_distr. simpl. apply add_assoc_pos.
Qed.
(** ** Opposite is inverse for addition *)
Lemma add_opp_diag_r n : n + - n = 0.
Proof.
destruct n; simpl; trivial; now rewrite pos_sub_diag.
Qed.
(** ** Multiplication and Opposite *)
Lemma mul_opp_r n m : n * - m = - (n * m).
Proof.
now destruct n, m.
Qed.
(** ** Distributivity of multiplication over addition *)
Lemma mul_add_distr_pos (p:positive) n m :
(n + m) * pos p = n * pos p + m * pos p.
Proof.
destruct n as [|n|n], m as [|m|m]; simpl; trivial.
- now rewrite Pos.mul_add_distr_r.
- rewrite ?pos_sub_spec, ?Pos.mul_compare_mono_r; case Pos.compare_spec;
simpl; trivial; intros; now rewrite Pos.mul_sub_distr_r.
- rewrite ?pos_sub_spec, ?Pos.mul_compare_mono_r; case Pos.compare_spec;
simpl; trivial; intros; now rewrite Pos.mul_sub_distr_r.
- now rewrite Pos.mul_add_distr_r.
Qed.
Lemma mul_add_distr_r n m p : (n + m) * p = n * p + m * p.
Proof.
destruct p as [|p|p].
- now rewrite !mul_0_r.
- apply mul_add_distr_pos.
- apply opp_inj. rewrite opp_add_distr, <- !mul_opp_r.
apply mul_add_distr_pos.
Qed.
End Private_BootStrap.
(** * Proofs of specifications *)
(** ** Specification of constants *)
Lemma one_succ : 1 = succ 0.
Proof.
reflexivity.
Qed.
Lemma two_succ : 2 = succ 1.
Proof.
reflexivity.
Qed.
(** ** Specification of addition *)
Lemma add_0_l n : 0 + n = n.
Proof.
now destruct n.
Qed.
Lemma add_succ_l n m : succ n + m = succ (n + m).
Proof.
unfold succ. now rewrite 2 (add_comm _ 1), add_assoc.
Qed.
(** ** Specification of opposite *)
Lemma opp_0 : -0 = 0.
Proof.
reflexivity.
Qed.
Lemma opp_succ n : -(succ n) = pred (-n).
Proof.
unfold succ, pred. apply opp_add_distr.
Qed.
(** ** Specification of successor and predecessor *)
Local Arguments pos_sub : simpl nomatch.
Lemma succ_pred n : succ (pred n) = n.
Proof.
unfold succ, pred. now rewrite <- add_assoc, add_opp_diag_r, add_0_r.
Qed.
Lemma pred_succ n : pred (succ n) = n.
Proof.
unfold succ, pred. now rewrite <- add_assoc, add_opp_diag_r, add_0_r.
Qed.
(** ** Specification of subtraction *)
Lemma sub_0_r n : n - 0 = n.
Proof.
apply add_0_r.
Qed.
Lemma sub_succ_r n m : n - succ m = pred (n - m).
Proof.
unfold sub, succ, pred. now rewrite opp_add_distr, add_assoc.
Qed.
(** ** Specification of multiplication *)
Lemma mul_0_l n : 0 * n = 0.
Proof.
reflexivity.
Qed.
Lemma mul_succ_l n m : succ n * m = n * m + m.
Proof.
unfold succ. now rewrite mul_add_distr_r, mul_1_l.
Qed.
(** ** Specification of comparisons and order *)
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 ltb_lt n m : (n <? m) = true <-> n < m.
Proof.
unfold ltb, lt. destruct compare; easy'.
Qed.
Lemma leb_le n m : (n <=? m) = true <-> n <= m.
Proof.
unfold leb, le. destruct compare; easy'.
Qed.
Lemma compare_eq_iff n m : (n ?= m) = Eq <-> n = m.
Proof.
destruct n, m; simpl; rewrite ?CompOpp_iff, ?Pos.compare_eq_iff;
split; congruence.
Qed.
Lemma compare_sub n m : (n ?= m) = (n - m ?= 0).
Proof.
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 compare_antisym n m : (m ?= n) = CompOpp (n ?= m).
Proof.
destruct n, m; simpl; trivial; now rewrite <- ?Pos.compare_antisym.
Qed.
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 lt, le. rewrite compare_sub, sub_succ_r.
rewrite (compare_sub n m).
destruct (n-m) as [|[ | | ]|]; easy'.
Qed.
(** ** Specification of minimum and maximum *)
Lemma max_l n m : m<=n -> max n m = n.
Proof.
unfold le, max. rewrite (compare_antisym n m).
case compare; intuition.
Qed.
Lemma max_r n m : n<=m -> max n m = m.
Proof.
unfold le, max. case compare_spec; intuition.
Qed.
Lemma min_l n m : n<=m -> min n m = n.
Proof.
unfold le, min. case compare_spec; intuition.
Qed.
Lemma min_r n m : m<=n -> min n m = m.
Proof.
unfold le, min.
rewrite (compare_antisym n m). case compare_spec; intuition.
Qed.
(** ** 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 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 bi_induction (P : Z -> Prop) :
Proper (eq ==> iff) P ->
P 0 ->
(forall x, P x <-> P (succ x)) ->
forall z, P z.
Proof.
intros _ H0 Hs. induction z using peano_ind.
assumption.
now apply -> Hs.
apply Hs. now rewrite succ_pred.
Qed.
(** We can now derive all properties of basic functions and orders,
and use these properties for proving the specs of more advanced
functions. *)
Include ZBasicProp <+ UsualMinMaxLogicalProperties <+ UsualMinMaxDecProperties.
Register eq_decidable as num.Z.eq_decidable.
Register le_decidable as num.Z.le_decidable.
Register lt_decidable as num.Z.lt_decidable.
(** ** Specification of absolute value *)
Lemma abs_eq n : 0 <= n -> abs n = n.
Proof.
destruct n; trivial. now destruct 1.
Qed.
Lemma abs_neq n : n <= 0 -> abs n = - n.
Proof.
destruct n; trivial. now destruct 1.
Qed.
(** ** Specification of sign *)
Lemma sgn_null n : n = 0 -> sgn n = 0.
Proof.
intros. now subst.
Qed.
Lemma sgn_pos n : 0 < n -> sgn n = 1.
Proof.
now destruct n.
Qed.
Lemma sgn_neg n : n < 0 -> sgn n = -1.
Proof.
now destruct n.
Qed.
(** ** Specification of power *)
Lemma pow_0_r n : n^0 = 1.
Proof.
reflexivity.
Qed.
Lemma pow_succ_r n m : 0<=m -> n^(succ m) = n * n^m.
Proof.
destruct m as [|m|m]; (now destruct 1) || (intros _); simpl; trivial.
unfold pow_pos. now rewrite Pos.add_comm, Pos.iter_add.
Qed.
Lemma pow_neg_r n m : m<0 -> n^m = 0.
Proof.
now destruct m.
Qed.
(** For folding back a [pow_pos] into a [pow] *)
Lemma pow_pos_fold n p : pow_pos n p = n ^ (pos p).
Proof.
reflexivity.
Qed.
(** ** Specification of square *)
Lemma square_spec n : square n = n * n.
Proof.
destruct n; trivial; simpl; f_equal; apply Pos.square_spec.
Qed.
(** ** Specification of square root *)
Lemma sqrtrem_spec n : 0<=n ->
let (s,r) := sqrtrem n in n = s*s + r /\ 0 <= r <= 2*s.
Proof.
destruct n. now repeat split.
generalize (Pos.sqrtrem_spec p). simpl.
destruct 1; simpl; subst; now repeat split.
now destruct 1.
Qed.
Lemma sqrt_spec n : 0<=n ->
let s := sqrt n in s*s <= n < (succ s)*(succ s).
Proof.
destruct n. now repeat split. unfold sqrt.
intros _. simpl succ. rewrite Pos.add_1_r. apply (Pos.sqrt_spec p).
now destruct 1.
Qed.
Lemma sqrt_neg n : n<0 -> sqrt n = 0.
Proof.
now destruct n.
Qed.
Lemma sqrtrem_sqrt n : fst (sqrtrem n) = sqrt n.
Proof.
destruct n; try reflexivity.
unfold sqrtrem, sqrt, Pos.sqrt.
destruct (Pos.sqrtrem p) as (s,r). now destruct r.
Qed.
(** ** Specification of logarithm *)
Lemma log2_spec n : 0 < n -> 2^(log2 n) <= n < 2^(succ (log2 n)).
Proof.
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.
Lemma log2_nonpos n : n<=0 -> log2 n = 0.
Proof.
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 odd_spec n : odd n = true <-> Odd n.
Proof.
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 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) Logic.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) Logic.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) Logic.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) Logic.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.
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 quot_rem' a b : a = b*(a÷b) + rem a b.
Proof.
rewrite mul_comm. generalize (quotrem_eq a b).
unfold quot, rem. now destruct quotrem.
Qed.
Lemma quot_rem a b : b<>0 -> a = b*(a÷b) + rem a b.
Proof. intros _. apply quot_rem'. Qed.
Lemma rem_bound_pos a b : 0<=a -> 0<b -> 0 <= rem a b < b.
Proof.
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.
Lemma rem_opp_l' a b : rem (-a) b = - (rem a b).
Proof.
destruct a, b; trivial; unfold rem; simpl;
now destruct N.pos_div_eucl as (q,[|r]).
Qed.
Lemma rem_opp_r' a b : rem a (-b) = rem a b.
Proof.
destruct a, b; trivial; unfold rem; simpl;
now destruct N.pos_div_eucl as (q,[|r]).
Qed.
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.
(** ** Extra properties about [divide] *)
Lemma divide_Zpos p q : (pos p|pos q) <-> (p|q)%positive.
Proof.
split.
intros ([ |r|r],H); simpl in *; destr_eq H. exists r; auto.
intros (r,H). exists (pos r); simpl; now f_equal.
Qed.
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.
Lemma divide_Zpos_Zneg_l n p : (pos p|n) <-> (neg p|n).
Proof.
split; intros (m,H); exists (-m); now rewrite mul_opp_l, <- mul_opp_r.
Qed.
(** ** Correctness proofs for gcd *)
Lemma ggcd_gcd a b : fst (ggcd a b) = gcd a b.
Proof.
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.
Lemma ggcd_correct_divisors a b :
let '(g,(aa,bb)) := ggcd a b in
a = g*aa /\ b = g*bb.
Proof.
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.
Lemma gcd_divide_l a b : (gcd a b | a).
Proof.
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.
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 gcd_greatest a b c : (c|a) -> (c|b) -> (c | gcd a b).
Proof.
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.
Lemma gcd_nonneg a b : 0 <= gcd a b.
Proof.
now destruct a, b.
Qed.
(** 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.
destruct a as [|a|a], b as [|b|b]; unfold ggcd, opp; auto;
destruct (Pos.ggcd a b) as (g,(aa,bb)); auto.
Qed.
(** ** Extra properties about [testbit] *)
Lemma testbit_of_N a n :
testbit (of_N a) (of_N n) = N.testbit a n.
Proof.
destruct a as [|a], n; simpl; trivial. now destruct a.
Qed.
Lemma testbit_of_N' a n : 0<=n ->
testbit (of_N a) n = N.testbit a (to_N n).
Proof.
intro Hn. rewrite <- testbit_of_N. f_equal.
destruct n; trivial; now destruct Hn.
Qed.
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.
Lemma testbit_Zneg a n : 0<=n ->
testbit (neg a) n = negb (N.testbit (Pos.pred_N a) (to_N n)).
Proof.
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.
(** ** Proofs of specifications for bitwise operations *)
Lemma div2_spec a : div2 a = shiftr a 1.
Proof.
reflexivity.
Qed.
Lemma testbit_0_l n : testbit 0 n = false.
Proof.
now destruct n.
Qed.
Lemma testbit_neg_r a n : n<0 -> testbit a n = false.
Proof.
now destruct n.
Qed.
Lemma testbit_odd_0 a : testbit (2*a+1) 0 = true.
Proof.
now destruct a as [|a|[a|a|]].
Qed.
Lemma testbit_even_0 a : testbit (2*a) 0 = false.
Proof.
now destruct a.
Qed.
Lemma testbit_odd_succ a n : 0<=n ->
testbit (2*a+1) (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 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.
(** 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 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 div2 0 n) 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.
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 (mul 2) 0 n) 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 (mul 2) 0 n) 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.
(** Generic properties of advanced functions. *)
Include ZExtraProp.
(** 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.
unfold lt, gt. now rewrite compare_antisym, CompOpp_iff.
Qed.
Lemma gt_lt n m : n > m -> m < n.
Proof.
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.
Lemma ge_le n m : n >= m -> m <= n.
Proof.
apply ge_le_iff.
Qed.
Lemma le_ge n m : n <= m -> m >= n.
Proof.
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 *.
(** 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 gtb_ltb n m : (n >? m) = (m <? n).
Proof.
unfold gtb, ltb. rewrite compare_antisym. now case compare.
Qed.
Lemma geb_leb n m : (n >=? m) = (m <=? n).
Proof.
unfold geb, leb. rewrite compare_antisym. now case compare.
Qed.
Lemma gtb_lt n m : (n >? m) = true <-> m < n.
Proof.
rewrite gtb_ltb. apply ltb_lt.
Qed.
Lemma geb_le n m : (n >=? m) = true <-> m <= n.
Proof.
rewrite geb_leb. apply leb_le.
Qed.
Lemma gtb_spec n m : BoolSpec (m<n) (n<=m) (n >? m).
Proof.
rewrite gtb_ltb. apply ltb_spec.
Qed.
Lemma geb_spec n m : BoolSpec (m<=n) (n<m) (n >=? m).
Proof.
rewrite geb_leb. apply leb_spec.
Qed.
(** TODO : to add in Numbers ? *)
Lemma add_reg_l n m p : n + m = n + p -> m = p.
Proof.
exact (proj1 (add_cancel_l m p n)).
Qed.
Lemma mul_reg_l n m p : p <> 0 -> p * n = p * m -> n = m.
Proof.
exact (fun Hp => proj1 (mul_cancel_l n m p Hp)).
Qed.
Lemma mul_reg_r n m p : p <> 0 -> n * p = m * p -> n = m.
Proof.
exact (fun Hp => proj1 (mul_cancel_r n m p Hp)).
Qed.
Lemma opp_eq_mul_m1 n : - n = n * -1.
Proof.
rewrite mul_comm. now destruct n.
Qed.
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 *)
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.
(** * [testbit] in terms of comparison. *)
Lemma testbit_mod_pow2 a n i (H : 0 <= n)
: testbit (a mod 2 ^ n) i = ((i <? n) && testbit a i)%bool.
Proof.
destruct (ltb_spec i n); rewrite
?mod_pow2_bits_low, ?mod_pow2_bits_high by auto; auto.
Qed.
Lemma testbit_ones n i (H : 0 <= n)
: testbit (ones n) i = ((0 <=? i) && (i <? n))%bool.
Proof.
destruct (leb_spec 0 i), (ltb_spec i n); cbn;
rewrite ?testbit_neg_r, ?ones_spec_low, ?ones_spec_high by auto; trivial.
Qed.
Lemma testbit_ones_nonneg n i (Hn : 0 <= n) (Hi: 0 <= i)
: testbit (ones n) i = (i <? n).
Proof.
rewrite testbit_ones by auto.
destruct (leb_spec 0 i); cbn; solve
[ trivial | destruct (proj1 (Z.le_ngt _ _) Hi ltac:(eassumption)) ].
Qed.
End Z.
Bind Scope Z_scope with Z.t Z.
(** Re-export Notations *)
Numeral Notation Z Z.of_int Z.to_int : Z_scope.
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.
(** 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.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.testbit_Zpos. Qed.
(** Some results concerning Z.neg and Z.pos *)
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 inj_pos p q : Z.pos p = Z.pos q -> p = q.
Proof. now injection 1. Qed.
Lemma inj_pos_iff p q : Z.pos p = Z.pos q <-> p = q.
Proof. split. apply inj_pos. 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 pos_is_pos p : 0 < Z.pos p.
Proof. reflexivity. Qed.
Lemma pos_is_nonneg p : 0 <= Z.pos p.
Proof. easy. Qed.
Lemma neg_le_pos p q : Zneg p <= Zpos q.
Proof. easy. Qed.
Lemma neg_lt_pos p q : Zneg p < Zpos q.
Proof. easy. Qed.
Lemma neg_le_neg p q : (q <= p)%positive -> Zneg p <= Zneg q.
Proof. intros; unfold Z.le; simpl. now rewrite <- Pos.compare_antisym. Qed.
Lemma neg_lt_neg p q : (q < p)%positive -> Zneg p < Zneg q.
Proof. intros; unfold Z.lt; simpl. now rewrite <- Pos.compare_antisym. Qed.
Lemma pos_le_pos p q : (p <= q)%positive -> Zpos p <= Zpos q.
Proof. easy. Qed.
Lemma pos_lt_pos p q : (p < q)%positive -> Zpos p < Zpos q.
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 pos_xO p : Z.pos p~0 = 2 * Z.pos p.
Proof. reflexivity. Qed.
Lemma pos_xI p : Z.pos p~1 = 2 * Z.pos 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 add_pos_pos p q : Z.pos p + Z.pos q = Z.pos (p+q).
Proof. reflexivity. Qed.
Lemma divide_pos_neg_r n p : (n|Z.pos p) <-> (n|Z.neg p).
Proof. apply Z.divide_Zpos_Zneg_r. Qed.
Lemma divide_pos_neg_l n p : (Z.pos p|n) <-> (Z.neg p|n).
Proof. apply Z.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.testbit_Zneg. Qed.
Lemma testbit_pos a n : 0<=n ->
Z.testbit (Z.pos a) n = N.testbit (N.pos a) (Z.to_N n).
Proof. apply Z.testbit_Zpos. 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 (only parsing).
Notation Zdouble_minus_one := Z.pred_double (only parsing).
Notation ZPminus := Z.pos_sub (only parsing).
Notation Zplus := Z.add (only parsing). (* Slightly incompatible *)
Notation Zminus := Z.sub (only parsing).
Notation Zmult := Z.mul (only parsing).
Notation Z_of_nat := Z.of_nat (only parsing).
Notation Z_of_N := Z.of_N (only parsing).
Notation Zind := Z.peano_ind (only parsing).
Notation Zplus_0_l := Z.add_0_l (only parsing).
Notation Zplus_0_r := Z.add_0_r (only parsing).
Notation Zplus_comm := Z.add_comm (only parsing).
Notation Zopp_plus_distr := Z.opp_add_distr (only parsing).
Notation Zplus_opp_r := Z.add_opp_diag_r (only parsing).
Notation Zplus_opp_l := Z.add_opp_diag_l (only parsing).
Notation Zplus_assoc := Z.add_assoc (only parsing).
Notation Zplus_permute := Z.add_shuffle3 (only parsing).
Notation Zplus_reg_l := Z.add_reg_l (only parsing).
Notation Zplus_succ_l := Z.add_succ_l (only parsing).
Notation Zplus_succ_comm := Z.add_succ_comm (only parsing).
Notation Zsucc_discr := Z.neq_succ_diag_r (only parsing).
Notation Zsucc'_discr := Z.neq_succ_diag_r (only parsing).
Notation Zminus_0_r := Z.sub_0_r (only parsing).
Notation Zminus_diag := Z.sub_diag (only parsing).
Notation Zminus_plus_distr := Z.sub_add_distr (only parsing).
Notation Zminus_succ_r := Z.sub_succ_r (only parsing).
Notation Zminus_plus := Z.add_simpl_l (only parsing).
Notation Zmult_0_l := Z.mul_0_l (only parsing).
Notation Zmult_0_r := Z.mul_0_r (only parsing).
Notation Zmult_1_l := Z.mul_1_l (only parsing).
Notation Zmult_1_r := Z.mul_1_r (only parsing).
Notation Zmult_comm := Z.mul_comm (only parsing).
Notation Zmult_assoc := Z.mul_assoc (only parsing).
Notation Zmult_permute := Z.mul_shuffle3 (only parsing).
Notation Zmult_1_inversion_l := Z.mul_eq_1 (only parsing).
Notation Zdouble_mult := Z.double_spec (only parsing).
Notation Zdouble_plus_one_mult := Z.succ_double_spec (only parsing).
Notation Zopp_mult_distr_l_reverse := Z.mul_opp_l (only parsing).
Notation Zmult_opp_opp := Z.mul_opp_opp (only parsing).
Notation Zmult_opp_comm := Z.mul_opp_comm (only parsing).
Notation Zopp_eq_mult_neg_1 := Z.opp_eq_mul_m1 (only parsing).
Notation Zmult_plus_distr_r := Z.mul_add_distr_l (only parsing).
Notation Zmult_plus_distr_l := Z.mul_add_distr_r (only parsing).
Notation Zmult_minus_distr_r := Z.mul_sub_distr_r (only parsing).
Notation Zmult_reg_l := Z.mul_reg_l (only parsing).
Notation Zmult_reg_r := Z.mul_reg_r (only parsing).
Notation Zmult_succ_l := Z.mul_succ_l (only parsing).
Notation Zmult_succ_r := Z.mul_succ_r (only parsing).
Notation Zpos_xI := Pos2Z.inj_xI (only parsing).
Notation Zpos_xO := Pos2Z.inj_xO (only parsing).
Notation Zneg_xI := Pos2Z.neg_xI (only parsing).
Notation Zneg_xO := Pos2Z.neg_xO (only parsing).
Notation Zopp_neg := Pos2Z.opp_neg (only parsing).
Notation Zpos_succ_morphism := Pos2Z.inj_succ (only parsing).
Notation Zpos_mult_morphism := Pos2Z.inj_mul (only parsing).
Notation Zpos_minus_morphism := Pos2Z.inj_sub (only parsing).
Notation Zpos_eq_rev := Pos2Z.inj (only parsing).
Notation Zpos_plus_distr := Pos2Z.inj_add (only parsing).
Notation Zneg_plus_distr := Pos2Z.add_neg_neg (only parsing).
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 ? *)
Register Zne as plugins.omega.Zne.
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.
¤ Dauer der Verarbeitung: 0.60 Sekunden
(vorverarbeitet)
¤
|
Haftungshinweis
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.
|