diff options
Diffstat (limited to 'theories/ZArith/Zlogarithm.v')
-rw-r--r-- | theories/ZArith/Zlogarithm.v | 434 |
1 files changed, 210 insertions, 224 deletions
diff --git a/theories/ZArith/Zlogarithm.v b/theories/ZArith/Zlogarithm.v index 653ee951..d8f4f236 100644 --- a/theories/ZArith/Zlogarithm.v +++ b/theories/ZArith/Zlogarithm.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Zlogarithm.v 6295 2004-11-12 16:40:39Z gregoire $ i*) +(*i $Id: Zlogarithm.v 9245 2006-10-17 12:53:34Z notin $ i*) (**********************************************************************) (** The integer logarithms with base 2. @@ -27,235 +27,221 @@ Require Import Zpower. Open Local Scope Z_scope. Section Log_pos. (* Log of positive integers *) - -(** First we build [log_inf] and [log_sup] *) - -Fixpoint log_inf (p:positive) : Z := - match p with - | xH => 0 (* 1 *) - | xO q => Zsucc (log_inf q) (* 2n *) - | xI q => Zsucc (log_inf q) (* 2n+1 *) - end. - -Fixpoint log_sup (p:positive) : Z := - match p with - | xH => 0 (* 1 *) - | xO n => Zsucc (log_sup n) (* 2n *) - | xI n => Zsucc (Zsucc (log_inf n)) (* 2n+1 *) - end. - -Hint Unfold log_inf log_sup. - -(** Then we give the specifications of [log_inf] and [log_sup] + + (** First we build [log_inf] and [log_sup] *) + + Fixpoint log_inf (p:positive) : Z := + match p with + | xH => 0 (* 1 *) + | xO q => Zsucc (log_inf q) (* 2n *) + | xI q => Zsucc (log_inf q) (* 2n+1 *) + end. + + Fixpoint log_sup (p:positive) : Z := + match p with + | xH => 0 (* 1 *) + | xO n => Zsucc (log_sup n) (* 2n *) + | xI n => Zsucc (Zsucc (log_inf n)) (* 2n+1 *) + end. + + Hint Unfold log_inf log_sup. + + (** Then we give the specifications of [log_inf] and [log_sup] and prove their validity *) - -(*i Hints Resolve ZERO_le_S : zarith. i*) -Hint Resolve Zle_trans: zarith. - -Theorem log_inf_correct : - forall x:positive, - 0 <= log_inf x /\ two_p (log_inf x) <= Zpos x < two_p (Zsucc (log_inf x)). -simple induction x; intros; simpl in |- *; - [ elim H; intros Hp HR; clear H; split; - [ auto with zarith - | conditional apply Zle_le_succ; trivial rewrite - two_p_S with (x := Zsucc (log_inf p)); - conditional trivial rewrite two_p_S; - conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xI p); - omega ] - | elim H; intros Hp HR; clear H; split; - [ auto with zarith - | conditional apply Zle_le_succ; trivial rewrite - two_p_S with (x := Zsucc (log_inf p)); - conditional trivial rewrite two_p_S; - conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xO p); - omega ] - | unfold two_power_pos in |- *; unfold shift_pos in |- *; simpl in |- *; - omega ]. -Qed. - -Definition log_inf_correct1 (p:positive) := proj1 (log_inf_correct p). -Definition log_inf_correct2 (p:positive) := proj2 (log_inf_correct p). - -Opaque log_inf_correct1 log_inf_correct2. - -Hint Resolve log_inf_correct1 log_inf_correct2: zarith. - -Lemma log_sup_correct1 : forall p:positive, 0 <= log_sup p. -simple induction p; intros; simpl in |- *; auto with zarith. -Qed. - -(** For every [p], either [p] is a power of two and [(log_inf p)=(log_sup p)] - either [(log_sup p)=(log_inf p)+1] *) - -Theorem log_sup_log_inf : - forall p:positive, - IF Zpos p = two_p (log_inf p) then Zpos p = two_p (log_sup p) - else log_sup p = Zsucc (log_inf p). - -simple induction p; intros; - [ elim H; right; simpl in |- *; - rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite BinInt.Zpos_xI; unfold Zsucc in |- *; omega - | elim H; clear H; intro Hif; - [ left; simpl in |- *; - rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite (two_p_S (log_sup p0) (log_sup_correct1 p0)); - rewrite <- (proj1 Hif); rewrite <- (proj2 Hif); - auto - | right; simpl in |- *; - rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); - rewrite BinInt.Zpos_xO; unfold Zsucc in |- *; - omega ] - | left; auto ]. -Qed. - -Theorem log_sup_correct2 : - forall x:positive, two_p (Zpred (log_sup x)) < Zpos x <= two_p (log_sup x). - -intro. -elim (log_sup_log_inf x). -(* x is a power of two and [log_sup = log_inf] *) -intros [E1 E2]; rewrite E2. -split; [ apply two_p_pred; apply log_sup_correct1 | apply Zle_refl ]. -intros [E1 E2]; rewrite E2. -rewrite <- (Zpred_succ (log_inf x)). -generalize (log_inf_correct2 x); omega. -Qed. - -Lemma log_inf_le_log_sup : forall p:positive, log_inf p <= log_sup p. -simple induction p; simpl in |- *; intros; omega. -Qed. - -Lemma log_sup_le_Slog_inf : forall p:positive, log_sup p <= Zsucc (log_inf p). -simple induction p; simpl in |- *; intros; omega. -Qed. - -(** Now it's possible to specify and build the [Log] rounded to the nearest *) - -Fixpoint log_near (x:positive) : Z := - match x with - | xH => 0 - | xO xH => 1 - | xI xH => 2 - | xO y => Zsucc (log_near y) - | xI y => Zsucc (log_near y) - end. - -Theorem log_near_correct1 : forall p:positive, 0 <= log_near p. -simple induction p; simpl in |- *; intros; - [ elim p0; auto with zarith - | elim p0; auto with zarith - | trivial with zarith ]. -intros; apply Zle_le_succ. -generalize H0; elim p1; intros; simpl in |- *; - [ assumption | assumption | apply Zorder.Zle_0_pos ]. -intros; apply Zle_le_succ. -generalize H0; elim p1; intros; simpl in |- *; - [ assumption | assumption | apply Zorder.Zle_0_pos ]. -Qed. - -Theorem log_near_correct2 : - forall p:positive, log_near p = log_inf p \/ log_near p = log_sup p. -simple induction p. -intros p0 [Einf| Esup]. -simpl in |- *. rewrite Einf. -case p0; [ left | left | right ]; reflexivity. -simpl in |- *; rewrite Esup. -elim (log_sup_log_inf p0). -generalize (log_inf_le_log_sup p0). -generalize (log_sup_le_Slog_inf p0). -case p0; auto with zarith. -intros; omega. -case p0; intros; auto with zarith. -intros p0 [Einf| Esup]. -simpl in |- *. -repeat rewrite Einf. -case p0; intros; auto with zarith. -simpl in |- *. -repeat rewrite Esup. -case p0; intros; auto with zarith. -auto. -Qed. - -(*i****************** -Theorem log_near_correct: (p:positive) - `| (two_p (log_near p)) - (POS p) | <= (POS p)-(two_p (log_inf p))` - /\`| (two_p (log_near p)) - (POS p) | <= (two_p (log_sup p))-(POS p)`. -Intro. -Induction p. -Intros p0 [(Einf1,Einf2)|(Esup1,Esup2)]. -Unfold log_near log_inf log_sup. Fold log_near log_inf log_sup. -Rewrite Einf1. -Repeat Rewrite two_p_S. -Case p0; [Left | Left | Right]. - -Split. -Simpl. -Rewrite E1; Case p0; Try Reflexivity. -Compute. -Unfold log_near; Fold log_near. -Unfold log_inf; Fold log_inf. -Repeat Rewrite E1. -Split. -**********************************i*) + + Hint Resolve Zle_trans: zarith. + + Theorem log_inf_correct : + forall x:positive, + 0 <= log_inf x /\ two_p (log_inf x) <= Zpos x < two_p (Zsucc (log_inf x)). + simple induction x; intros; simpl in |- *; + [ elim H; intros Hp HR; clear H; split; + [ auto with zarith + | conditional apply Zle_le_succ; trivial rewrite + two_p_S with (x := Zsucc (log_inf p)); + conditional trivial rewrite two_p_S; + conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xI p); + omega ] + | elim H; intros Hp HR; clear H; split; + [ auto with zarith + | conditional apply Zle_le_succ; trivial rewrite + two_p_S with (x := Zsucc (log_inf p)); + conditional trivial rewrite two_p_S; + conditional trivial rewrite two_p_S in HR; rewrite (BinInt.Zpos_xO p); + omega ] + | unfold two_power_pos in |- *; unfold shift_pos in |- *; simpl in |- *; + omega ]. + Qed. + + Definition log_inf_correct1 (p:positive) := proj1 (log_inf_correct p). + Definition log_inf_correct2 (p:positive) := proj2 (log_inf_correct p). + + Opaque log_inf_correct1 log_inf_correct2. + + Hint Resolve log_inf_correct1 log_inf_correct2: zarith. + + Lemma log_sup_correct1 : forall p:positive, 0 <= log_sup p. + Proof. + simple induction p; intros; simpl in |- *; auto with zarith. + Qed. + + (** For every [p], either [p] is a power of two and [(log_inf p)=(log_sup p)] + either [(log_sup p)=(log_inf p)+1] *) + + Theorem log_sup_log_inf : + forall p:positive, + IF Zpos p = two_p (log_inf p) then Zpos p = two_p (log_sup p) + else log_sup p = Zsucc (log_inf p). + Proof. + simple induction p; intros; + [ elim H; right; simpl in |- *; + rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); + rewrite BinInt.Zpos_xI; unfold Zsucc in |- *; omega + | elim H; clear H; intro Hif; + [ left; simpl in |- *; + rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); + rewrite (two_p_S (log_sup p0) (log_sup_correct1 p0)); + rewrite <- (proj1 Hif); rewrite <- (proj2 Hif); + auto + | right; simpl in |- *; + rewrite (two_p_S (log_inf p0) (log_inf_correct1 p0)); + rewrite BinInt.Zpos_xO; unfold Zsucc in |- *; + omega ] + | left; auto ]. + Qed. + + Theorem log_sup_correct2 : + forall x:positive, two_p (Zpred (log_sup x)) < Zpos x <= two_p (log_sup x). + Proof. + intro. + elim (log_sup_log_inf x). + (* x is a power of two and [log_sup = log_inf] *) + intros [E1 E2]; rewrite E2. + split; [ apply two_p_pred; apply log_sup_correct1 | apply Zle_refl ]. + intros [E1 E2]; rewrite E2. + rewrite <- (Zpred_succ (log_inf x)). + generalize (log_inf_correct2 x); omega. + Qed. + + Lemma log_inf_le_log_sup : forall p:positive, log_inf p <= log_sup p. + Proof. + simple induction p; simpl in |- *; intros; omega. + Qed. + + Lemma log_sup_le_Slog_inf : forall p:positive, log_sup p <= Zsucc (log_inf p). + Proof. + simple induction p; simpl in |- *; intros; omega. + Qed. + + (** Now it's possible to specify and build the [Log] rounded to the nearest *) + + Fixpoint log_near (x:positive) : Z := + match x with + | xH => 0 + | xO xH => 1 + | xI xH => 2 + | xO y => Zsucc (log_near y) + | xI y => Zsucc (log_near y) + end. + + Theorem log_near_correct1 : forall p:positive, 0 <= log_near p. + Proof. + simple induction p; simpl in |- *; intros; + [ elim p0; auto with zarith + | elim p0; auto with zarith + | trivial with zarith ]. + intros; apply Zle_le_succ. + generalize H0; elim p1; intros; simpl in |- *; + [ assumption | assumption | apply Zorder.Zle_0_pos ]. + intros; apply Zle_le_succ. + generalize H0; elim p1; intros; simpl in |- *; + [ assumption | assumption | apply Zorder.Zle_0_pos ]. + Qed. + + Theorem log_near_correct2 : + forall p:positive, log_near p = log_inf p \/ log_near p = log_sup p. + Proof. + simple induction p. + intros p0 [Einf| Esup]. + simpl in |- *. rewrite Einf. + case p0; [ left | left | right ]; reflexivity. + simpl in |- *; rewrite Esup. + elim (log_sup_log_inf p0). + generalize (log_inf_le_log_sup p0). + generalize (log_sup_le_Slog_inf p0). + case p0; auto with zarith. + intros; omega. + case p0; intros; auto with zarith. + intros p0 [Einf| Esup]. + simpl in |- *. + repeat rewrite Einf. + case p0; intros; auto with zarith. + simpl in |- *. + repeat rewrite Esup. + case p0; intros; auto with zarith. + auto. + Qed. End Log_pos. Section divers. -(** Number of significative digits. *) - -Definition N_digits (x:Z) := - match x with - | Zpos p => log_inf p - | Zneg p => log_inf p - | Z0 => 0 - end. - -Lemma ZERO_le_N_digits : forall x:Z, 0 <= N_digits x. -simple induction x; simpl in |- *; - [ apply Zle_refl | exact log_inf_correct1 | exact log_inf_correct1 ]. -Qed. - -Lemma log_inf_shift_nat : forall n:nat, log_inf (shift_nat n 1) = Z_of_nat n. -simple induction n; intros; - [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. -Qed. - -Lemma log_sup_shift_nat : forall n:nat, log_sup (shift_nat n 1) = Z_of_nat n. -simple induction n; intros; - [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. -Qed. - -(** [Is_power p] means that p is a power of two *) -Fixpoint Is_power (p:positive) : Prop := - match p with - | xH => True - | xO q => Is_power q - | xI q => False - end. - -Lemma Is_power_correct : - forall p:positive, Is_power p <-> (exists y : nat, p = shift_nat y 1). - -split; - [ elim p; - [ simpl in |- *; tauto - | simpl in |- *; intros; generalize (H H0); intro H1; elim H1; - intros y0 Hy0; exists (S y0); rewrite Hy0; reflexivity - | intro; exists 0%nat; reflexivity ] - | intros; elim H; intros; rewrite H0; elim x; intros; simpl in |- *; trivial ]. -Qed. - -Lemma Is_power_or : forall p:positive, Is_power p \/ ~ Is_power p. -simple induction p; - [ intros; right; simpl in |- *; tauto - | intros; elim H; - [ intros; left; simpl in |- *; exact H0 - | intros; right; simpl in |- *; exact H0 ] - | left; simpl in |- *; trivial ]. -Qed. + (** Number of significative digits. *) + + Definition N_digits (x:Z) := + match x with + | Zpos p => log_inf p + | Zneg p => log_inf p + | Z0 => 0 + end. + + Lemma ZERO_le_N_digits : forall x:Z, 0 <= N_digits x. + Proof. + simple induction x; simpl in |- *; + [ apply Zle_refl | exact log_inf_correct1 | exact log_inf_correct1 ]. + Qed. + + Lemma log_inf_shift_nat : forall n:nat, log_inf (shift_nat n 1) = Z_of_nat n. + Proof. + simple induction n; intros; + [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. + Qed. + + Lemma log_sup_shift_nat : forall n:nat, log_sup (shift_nat n 1) = Z_of_nat n. + Proof. + simple induction n; intros; + [ try trivial | rewrite Znat.inj_S; rewrite <- H; reflexivity ]. + Qed. + + (** [Is_power p] means that p is a power of two *) + Fixpoint Is_power (p:positive) : Prop := + match p with + | xH => True + | xO q => Is_power q + | xI q => False + end. + + Lemma Is_power_correct : + forall p:positive, Is_power p <-> (exists y : nat, p = shift_nat y 1). + Proof. + split; + [ elim p; + [ simpl in |- *; tauto + | simpl in |- *; intros; generalize (H H0); intro H1; elim H1; + intros y0 Hy0; exists (S y0); rewrite Hy0; reflexivity + | intro; exists 0%nat; reflexivity ] + | intros; elim H; intros; rewrite H0; elim x; intros; simpl in |- *; trivial ]. + Qed. + + Lemma Is_power_or : forall p:positive, Is_power p \/ ~ Is_power p. + Proof. + simple induction p; + [ intros; right; simpl in |- *; tauto + | intros; elim H; + [ intros; left; simpl in |- *; exact H0 + | intros; right; simpl in |- *; exact H0 ] + | left; simpl in |- *; trivial ]. + Qed. End divers. |