Library Additions.log2_implementation
Require Import Arith.
Require Import Peano_dec.
Require Import Constants.
Require Import Mult_compl.
Require Import Wf_nat.
Require Import euclid.
Require Import Le_lt_compl.
Require Import Euclid.
Require Import shift.
Require Import Compare_dec.
Require Import imperative.
Require Import while.
Require Import two_power.
Require Import log2_spec.
Section log2_computation.
Variable n0 : nat.
Hypothesis pos_n0 : 0 < n0.
Hint Resolve pos_n0: arith.
Record state : Set := mkstate
{state_n : nat; state_p : nat; state_b : bool}.
Inductive ok : state → Prop :=
| oktrue : ∀ p : nat, n0 = two_power p → ok (mkstate one p true)
| okfalse :
∀ p : nat,
two_power p < n0 → n0 < two_power (S p) → ok (mkstate one p false).
Let init (s : state) := state_n s = n0 ∧ state_p s = 0 ∧ state_b s = true.
Inductive final : state → Prop :=
mkfinal : ∀ (p : nat) (b : bool), final (mkstate one p b).
Inductive invar : state → Prop :=
| exact :
∀ n p : nat,
n0 = two_power p × n → 0 < n → invar (mkstate n p true)
| inexact :
∀ n p : nat,
two_power p × n < n0 →
n0 < two_power p × S n → 0 < n → invar (mkstate n p false).
Definition stat_order := ltof state state_n.
Lemma decomp :
∀ s : state,
s = mkstate (state_n s) (state_p s) (state_b s).
Proof.
simple induction s; simpl in |- *; auto with arith.
Qed.
Lemma invar_inv1 :
∀ n p : nat,
invar (mkstate n p true) → n0 = two_power p × n.
Proof.
intros; inversion_clear H; auto with arith.
Qed.
Lemma invar_inv2 :
∀ n p : nat,
invar (mkstate n p false) →
two_power p × n < n0 ∧ n0 < two_power p × S n.
Proof.
intros.
inversion_clear H; split; auto with arith.
Qed.
Lemma invar_inv3 :
∀ (n p : nat) (b : bool), invar (mkstate n p b) → 0 < n.
Proof.
intros.
inversion_clear H; auto with arith.
Qed.
Lemma final_inv :
∀ (n p : nat) (b : bool),
final (mkstate n p b) → n = one.
Proof.
intros.
inversion_clear H; auto with arith.
Qed.
Lemma not_final :
∀ (n p : nat) (b : bool),
invar (mkstate n p b) → ¬ final (mkstate n p b) → one < n.
Proof.
intros.
case (le_or_lt n one); [ intro | auto with arith ].
cut (0 < n); [ intro | apply invar_inv3 with p b; auto with arith ].
case (enum1 n).
unfold two in |- *; auto with arith.
intro; absurd (0 < n); auto with arith.
rewrite H3; auto with arith.
intro; absurd (final (mkstate n p b)); [ auto with arith | idtac ].
rewrite H3; split; auto with arith.
Qed.
Lemma wf_stat_order : well_founded stat_order.
Proof.
unfold stat_order in |- *; apply well_founded_ltof.
Qed.
Hint Resolve wf_stat_order: arith.
Lemma log2_impl : log2_spec n0.
Proof.
apply Imperative with state init ok;
[
∃ (mkstate n0 0 true)
|
intros a pre; apply while_not with init invar stat_order final a;
[
simple induction s; intros state_n0 state_p0 state_b0 i;
elim (le_lt_eq_dec 1 state_n0); [ right | left | idtac ]
|
simple induction s; intros state_n0 state_p0 state_b0;
elim state_b0; intros h i; elim (Unshift state_n0);
intros m b';
[ elim b';
[ ∃ (mkstate m (S state_p0) true)
| ∃ (mkstate m (S state_p0) false) ]
| ∃ (mkstate m (S state_p0) false) ]
| idtac
| idtac
| idtac
| idtac ]
|
simple induction a; intros state_n0 state_p0 state_b0;
elim state_b0; intro h; ∃ state_p0 ].
Hint Unfold init: arith.
split; auto; split; auto.
red in |- *; intros f; inversion f; auto.
rewrite <- H0 in a0; simpl in a0.
absurd (1 < 1); auto with arith.
rewrite <- b; constructor 1.
inversion i; auto.
cut (one < state_n0).
intro n_ge_1.
2: apply not_final with state_p0 true; auto with arith.
inversion i.
split.
left.
rewrite two_power_S.
rewrite <- mult_assoc; auto with arith.
unfold shift in a0.
rewrite <- a0; auto.
unfold shift in a0.
apply quotient_positive with state_n0 two; auto.
rewrite mult_comm; exact a0.
unfold stat_order, ltof in |- ×.
apply half_lt.
apply lt_trans with one; auto with arith.
auto with arith.
cut (one < state_n0).
intro n_ge_1.
2: apply not_final with state_p0 true; auto with arith.
inversion i.
split.
right.
rewrite two_power_S.
rewrite <- mult_assoc; auto with arith.
rewrite (invar_inv1 state_n0 state_p0); auto.
rewrite b.
unfold shift in |- ×.
auto with arith.
rewrite two_power_S.
rewrite <- mult_assoc.
rewrite (invar_inv1 state_n0 state_p0); auto.
rewrite b.
unfold shift in |- ×.
apply mult_lt_l.
auto with arith.
simpl in |- *; auto with arith.
case (lt_or_Zero m); auto with arith.
intro.
absurd (one < state_n0); auto with arith.
rewrite b.
rewrite H3; simpl in |- *; auto with arith.
unfold stat_order, ltof in |- *; apply half_lt.
simpl in |- ×.
apply lt_trans with one; auto with arith.
auto with arith.
cut (one < state_n0).
intro n_ge_1.
2: apply not_final with state_p0 false; auto with arith.
inversion i.
cut (two_power (S state_p0) × m < n0).
intro n0_left'.
cut (n0 < two_power (S state_p0) × S m).
intro n0_right'.
cut (m < state_n0).
intro m_little.
split.
right; auto with arith.
case (lt_or_Zero m); auto with arith.
intro.
absurd (one < state_n0); auto with arith.
simpl in b'; elim b'; intros eg; rewrite eg.
rewrite H4; simpl in |- *; auto with arith.
rewrite H4; simpl in |- *; auto with arith.
unfold stat_order, ltof in |- ×.
simpl in |- ×.
exact m_little.
apply half_lt.
apply lt_trans with one; auto with arith.
simpl in b'; elim b'; auto with arith.
simpl in b'; elim b'; intros eg.
apply lt_trans with (two_power state_p0 × S state_n0); auto with arith.
rewrite two_power_S.
rewrite <- mult_assoc; auto with arith.
apply mult_lt_l.
auto with arith.
rewrite eg.
unfold shift in |- *; simpl in |- *; auto with arith.
replace (two_power (S state_p0) × S m) with
(two_power state_p0 × S state_n0).
elim (invar_inv2 state_n0 state_p0); auto with arith.
elim H0; auto with arith.
rewrite two_power_S.
rewrite <- mult_assoc.
simpl in |- ×.
unfold shift in |- *; simpl in |- ×.
rewrite <- plus_n_Sm.
rewrite eg; auto with arith.
apply le_lt_trans with (two_power state_p0 × state_n0); auto with arith.
simpl in b'; elim b'; intro eg.
rewrite eg.
rewrite two_power_S.
rewrite <- mult_assoc; auto with arith.
rewrite eg.
rewrite two_power_S.
rewrite <- mult_assoc; auto with arith.
simple induction s.
simple induction state_b0.
intros.
rewrite (final_inv state_n0 state_p0 true).
left.
rewrite (invar_inv1 _ _ H0).
rewrite (final_inv _ _ _ H).
auto with arith.
auto with arith.
intros.
rewrite (final_inv state_n0 state_p0 false).
right.
elim (invar_inv2 _ _ H0).
rewrite (final_inv _ _ _ H).
intros.
rewrite <- (mult_1_r (two_power state_p0)); auto with arith.
elim (invar_inv2 _ _ H0).
rewrite (final_inv _ _ _ H).
intros.
rewrite two_power_S.
exact H2.
auto with arith.
simple induction s.
simple induction state_b0.
intro.
inversion_clear H.
elim H1.
simpl in |- *; intros.
left.
rewrite H; simpl in |- ×.
rewrite <- H0; auto with arith.
simpl in H0; rewrite H0; auto with arith.
intro.
inversion_clear H.
elim H1.
intros.
simpl in H2.
discriminate H2.
auto with arith.
auto with arith.
left.
inversion h; auto.
right.
inversion h; split; auto.
Qed.
End log2_computation.
