390 lines
10 KiB
Coq
Executable File
390 lines
10 KiB
Coq
Executable File
Require Import Coq.ZArith.ZArith.
|
|
Require Import Coq.Bool.Bool.
|
|
Require Import Coq.Lists.List.
|
|
Require Import Coq.Classes.RelationClasses.
|
|
Require Import Coq.Classes.Morphisms.
|
|
Require Import Coq.micromega.Psatz.
|
|
Require Import Permutation.
|
|
Require Import String.
|
|
From AUXLib Require Import int_auto Axioms Feq Idents List_lemma VMap.
|
|
Require Import SetsClass.SetsClass. Import SetsNotation.
|
|
From SimpleC.SL Require Import CommonAssertion Mem SeparationLogic IntLib.
|
|
Require Import Logic.LogicGenerator.demo932.Interface.
|
|
Local Open Scope Z_scope.
|
|
Local Open Scope sets.
|
|
Import ListNotations.
|
|
Local Open Scope list.
|
|
Require Import String.
|
|
Local Open Scope string.
|
|
Import naive_C_Rules.
|
|
Local Open Scope sac.
|
|
|
|
Module Aux.
|
|
|
|
Lemma Z_mod_add_carry: forall (a b m: Z),
|
|
m > 0 -> 0 <= a < m -> 0 <= b < m ->
|
|
(a + b) mod m < b ->
|
|
a + b = (a + b) mod m + m.
|
|
Proof. Admitted.
|
|
|
|
Lemma Z_mod_add_uncarry: forall (a b m: Z),
|
|
m > 0 -> 0 <= a < m -> 0 <= b < m ->
|
|
(a + b) mod m >= b ->
|
|
a + b = (a + b) mod m.
|
|
Proof. Admitted.
|
|
|
|
Lemma Z_mod_3add_carry10: forall (a b c m: Z),
|
|
m > 0 -> 0 <= a < m -> 0 <= b < m -> 0 <= c < m ->
|
|
(a + c) mod m < c ->
|
|
((a + c) mod m + b) mod m >= b ->
|
|
a + b + c = ((a + c) mod m + b) mod m + m.
|
|
Proof. Admitted.
|
|
|
|
Lemma Z_mod_3add_carry01: forall (a b c m: Z),
|
|
m > 0 -> 0 <= a < m -> 0 <= b < m -> 0 <= c < m ->
|
|
(a + c) mod m >= c ->
|
|
((a + c) mod m + b) mod m < b ->
|
|
a + b + c = ((a + c) mod m + b) mod m + m.
|
|
Proof. Admitted.
|
|
|
|
Lemma Z_mod_3add_carry11: forall (a b c m: Z),
|
|
m > 0 -> 0 <= a < m -> 0 <= b < m -> 0 <= c < m ->
|
|
(a + c) mod m < c ->
|
|
((a + c) mod m + b) mod m < b ->
|
|
a + b + c = ((a + c) mod m + b) mod m + m.
|
|
Proof. Admitted.
|
|
|
|
Lemma Z_mod_3add_carry00: forall (a b c m: Z),
|
|
m > 0 -> 0 <= a < m -> 0 <= b < m -> 0 <= c < m ->
|
|
(a + c) mod m >= c ->
|
|
((a + c) mod m + b) mod m >= b ->
|
|
a + b + c = ((a + c) mod m + b) mod m.
|
|
Proof. Admitted.
|
|
|
|
Lemma Z_of_nat_succ: forall (n: nat),
|
|
Z.of_nat (S n) = Z.of_nat n + 1.
|
|
Proof. lia. Qed.
|
|
|
|
Lemma Zpow_add_1: forall (a b: Z),
|
|
a >= 0 -> b >= 0 ->
|
|
a ^ (b + 1) = a ^ b * a.
|
|
Proof.
|
|
intros.
|
|
rewrite (Z.pow_add_r a b 1); lia.
|
|
Qed.
|
|
|
|
Lemma Zmul_mod_cancel: forall (n a b: Z),
|
|
n >= 0 -> a > 0 -> b >= 0 ->
|
|
(n * a) mod (a ^ (b + 1)) = a * (n mod (a ^ b)).
|
|
Proof.
|
|
intros.
|
|
pose proof (Z_div_mod_eq_full n (a ^ b)).
|
|
pose proof (Z.mod_bound_pos n (a ^ b) ltac:(lia) ltac:(nia)).
|
|
remember (n / a ^ b) as q eqn:Hq.
|
|
remember (n mod a ^ b) as rem eqn:Hrem.
|
|
rewrite H2.
|
|
rewrite Z.mul_add_distr_r.
|
|
rewrite (Z.mul_comm (a ^ b) q); rewrite <-Z.mul_assoc.
|
|
rewrite <-Zpow_add_1; try lia.
|
|
assert (0 <= rem * a < a ^ (b + 1)). {
|
|
rewrite Zpow_add_1; try lia.
|
|
nia.
|
|
}
|
|
rewrite <-(Zmod_unique_full (q * a ^ (b + 1) + rem * a) (a ^ (b + 1)) q (rem * a)).
|
|
+ lia.
|
|
+ unfold Remainder.
|
|
lia.
|
|
+ lia.
|
|
Qed.
|
|
|
|
Lemma Zdiv_mod_pow: forall (n a b: Z),
|
|
a > 0 -> b >= 0 -> n >= 0 ->
|
|
(n / a) mod (a ^ b) = (n mod (a ^ (b + 1))) / a.
|
|
Proof.
|
|
intros.
|
|
pose proof (Z_div_mod_eq_full n (a ^ (b + 1))).
|
|
remember (n / (a ^ (b + 1))) as q eqn:Hq.
|
|
remember (n mod a ^ (b + 1)) as rem eqn:Hrem.
|
|
assert (n / a = a ^ b * q + rem / a). {
|
|
rewrite H2.
|
|
rewrite Zpow_add_1; try lia.
|
|
pose proof (Z_div_plus_full_l (a ^ b * q) a rem ltac:(lia)).
|
|
assert (a ^ b * q * a + rem = a ^ b * a * q + rem). { lia. }
|
|
rewrite H4 in H3.
|
|
tauto.
|
|
}
|
|
apply Znumtheory.Zdivide_mod_minus.
|
|
+ pose proof (Z.mod_bound_pos n (a ^ (b + 1)) ltac:(lia) (Z.pow_pos_nonneg a (b + 1) ltac:(lia) ltac:(lia))).
|
|
rewrite <-Hrem in H4.
|
|
rewrite Zpow_add_1 in H4; try lia.
|
|
pose proof (Z.div_lt_upper_bound rem a (a ^ b) ltac:(lia) ltac:(lia)).
|
|
split; try lia.
|
|
apply (Z_div_pos rem a ltac:(lia) ltac:(lia)).
|
|
+ unfold Z.divide.
|
|
exists q.
|
|
lia.
|
|
Qed.
|
|
|
|
Lemma list_app_cons: forall (l1 l2: list Z) (a: Z),
|
|
app l1 (a :: l2) = app (app l1 (a :: nil)) l2.
|
|
Proof.
|
|
intros.
|
|
revert a l2.
|
|
induction l1.
|
|
+ intros.
|
|
rewrite app_nil_l.
|
|
reflexivity.
|
|
+ intros.
|
|
simpl in *.
|
|
specialize (IHl1 a0 l2).
|
|
rewrite IHl1.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
Lemma list_app_single_l: forall (l: list Z) (a: Z),
|
|
([a] ++ l)%list = a :: l.
|
|
Proof.
|
|
intros.
|
|
induction l.
|
|
+ simpl; reflexivity.
|
|
+ rewrite list_app_cons.
|
|
simpl.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
Lemma list_last_cons: forall (a: Z) (l: list Z),
|
|
l <> nil ->
|
|
last (a :: l) 1 = last l 1.
|
|
Proof.
|
|
intros.
|
|
destruct l.
|
|
+ contradiction.
|
|
+ simpl.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
Lemma list_last_to_Znth: forall (l: list Z),
|
|
l <> nil ->
|
|
last l 1 = Znth ((Zlength l) - 1) l 0.
|
|
Proof.
|
|
intros.
|
|
induction l.
|
|
+ contradiction.
|
|
+ destruct l.
|
|
- simpl.
|
|
rewrite Znth0_cons.
|
|
lia.
|
|
- pose proof (@nil_cons Z z l).
|
|
specialize (IHl ltac:(auto)); clear H0.
|
|
rewrite list_last_cons; [ | pose proof (@nil_cons Z z l); auto ].
|
|
rewrite IHl.
|
|
pose proof (Zlength_cons a (z :: l)).
|
|
unfold Z.succ in H0; rewrite H0; clear H0.
|
|
pose proof (Zlength_nonneg l).
|
|
pose proof (Zlength_cons z l); unfold Z.succ in H1.
|
|
pose proof (Znth_cons (Zlength (z :: l)) a (z :: l) 0 ltac:(lia)).
|
|
assert (Zlength (z :: l) + 1 - 1 = Zlength (z :: l)). { lia. }
|
|
rewrite H3; clear H3.
|
|
rewrite H2.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
Lemma Zlength_removelast: forall (l: list Z),
|
|
l <> [] ->
|
|
Zlength (removelast l) = Zlength l - 1.
|
|
Proof.
|
|
intros.
|
|
induction l.
|
|
+ contradiction.
|
|
+ destruct l.
|
|
- simpl.
|
|
rewrite Zlength_nil.
|
|
lia.
|
|
- pose proof (@nil_cons Z z l).
|
|
specialize (IHl ltac:(auto)).
|
|
assert (removelast (a :: z :: l) = a :: removelast(z :: l)). {
|
|
simpl.
|
|
reflexivity.
|
|
}
|
|
rewrite H1; clear H1.
|
|
repeat rewrite Zlength_cons; unfold Z.succ.
|
|
rewrite IHl.
|
|
rewrite Zlength_cons; unfold Z.succ.
|
|
lia.
|
|
Qed.
|
|
|
|
Lemma store_array_rec_false: forall x storeA lo hi (l: list Z),
|
|
lo > hi ->
|
|
store_array_rec storeA x lo hi l |-- [| False |].
|
|
Proof.
|
|
intros.
|
|
revert x storeA lo hi H.
|
|
induction l; intros.
|
|
+ simpl.
|
|
entailer!.
|
|
+ simpl.
|
|
specialize (IHl x storeA (lo + 1) hi ltac:(lia)).
|
|
sep_apply IHl.
|
|
entailer!.
|
|
Qed.
|
|
|
|
Lemma store_array_rec_empty: forall x storeA lo (l: list Z),
|
|
store_array_rec storeA x lo lo l |-- emp && [| l = nil |].
|
|
Proof.
|
|
intros.
|
|
destruct l.
|
|
+ simpl.
|
|
entailer!.
|
|
+ simpl.
|
|
sep_apply store_array_rec_false; [ entailer! | lia ].
|
|
Qed.
|
|
|
|
Lemma store_uint_array_rec_false: forall x lo hi l,
|
|
lo > hi ->
|
|
store_uint_array_rec x lo hi l |-- [| False |].
|
|
Proof.
|
|
intros.
|
|
unfold store_uint_array_rec.
|
|
sep_apply store_array_rec_false; [ entailer! | lia ].
|
|
Qed.
|
|
|
|
Lemma store_uint_array_rec_empty: forall x lo l,
|
|
store_uint_array_rec x lo lo l |-- emp && [| l = nil |].
|
|
Proof.
|
|
induction l.
|
|
+ unfold store_uint_array_rec.
|
|
simpl.
|
|
entailer!.
|
|
+ pose proof (store_uint_array_rec_false x (lo + 1) lo l ltac:(lia)).
|
|
unfold store_uint_array_rec in *.
|
|
simpl in *.
|
|
sep_apply H.
|
|
entailer!.
|
|
Qed.
|
|
|
|
Lemma store_uint_array_empty: forall x l,
|
|
store_uint_array x 0 l |-- emp && [| l = nil |].
|
|
Proof.
|
|
intros x l.
|
|
revert x.
|
|
induction l; intros.
|
|
+ unfold store_uint_array, store_array.
|
|
simpl.
|
|
entailer!.
|
|
+ unfold store_uint_array, store_array.
|
|
simpl.
|
|
sep_apply store_array_rec_false; [ entailer! | lia ].
|
|
Qed.
|
|
|
|
Lemma uint_array_rec_to_uint_array: forall x lo hi l,
|
|
lo <= hi ->
|
|
store_uint_array_rec x lo hi l --||--
|
|
store_uint_array (x + sizeof(UINT) * lo) (hi - lo) l.
|
|
Proof.
|
|
intros.
|
|
unfold store_uint_array_rec, store_uint_array, store_array.
|
|
pose proof (store_array_rec_base x 0 lo hi l (sizeof(UINT))
|
|
store_uint
|
|
(fun (x: addr) (lo a: Z) =>
|
|
(x + lo * sizeof(UINT)) # UInt |-> a) ltac:(reflexivity)).
|
|
assert (x + sizeof(UINT) * lo = x + lo * sizeof(UINT)). { lia. }
|
|
rewrite H1; clear H1.
|
|
assert (0 + lo = lo). { lia. }
|
|
repeat rewrite H1 in H0; clear H1.
|
|
destruct H0.
|
|
split.
|
|
+ sep_apply H0.
|
|
entailer!.
|
|
+ sep_apply H1.
|
|
entailer!.
|
|
Qed.
|
|
|
|
Lemma store_uint_array_single: forall x n a,
|
|
store_uint_array_rec x n (n + 1) [a] --||--
|
|
(x + n * sizeof(UINT)) # UInt |-> a.
|
|
Proof.
|
|
intros.
|
|
unfold store_uint_array_rec.
|
|
simpl.
|
|
split; entailer!.
|
|
Qed.
|
|
|
|
Lemma store_undef_uint_array_single: forall x n a,
|
|
(x + n * sizeof(UINT)) # UInt |-> a |--
|
|
store_undef_uint_array_rec x n (n + 1).
|
|
Proof.
|
|
intros.
|
|
unfold store_undef_uint_array_rec.
|
|
assert (Z.to_nat (n + 1 - n) = S O). { lia. }
|
|
rewrite H; clear H.
|
|
simpl.
|
|
entailer!.
|
|
sep_apply store_uint_undef_store_uint.
|
|
entailer!.
|
|
Qed.
|
|
|
|
Lemma store_uint_array_single_to_undef: forall x n a,
|
|
store_uint_array_rec x n (n + 1) [a] |--
|
|
store_undef_uint_array_rec x n (n + 1).
|
|
Proof.
|
|
intros.
|
|
pose proof (store_uint_array_single x n a).
|
|
destruct H as [H _].
|
|
sep_apply H.
|
|
sep_apply store_undef_uint_array_single.
|
|
entailer!.
|
|
Qed.
|
|
|
|
Lemma store_uint_array_divide_rec: forall x n l m,
|
|
0 <= m <= n ->
|
|
Zlength l = n ->
|
|
store_uint_array x n l --||--
|
|
store_uint_array x m (sublist 0 m l) **
|
|
store_uint_array_rec x m n (sublist m n l).
|
|
Proof.
|
|
intros.
|
|
pose proof (store_uint_array_divide x n l m H H0).
|
|
pose proof (uint_array_rec_to_uint_array x m n (sublist m n l) ltac:(lia)).
|
|
destruct H2 .
|
|
destruct H1.
|
|
rewrite Z.mul_comm in H2, H3.
|
|
rewrite H3 in H1.
|
|
rewrite <-H2 in H4.
|
|
clear H2 H3.
|
|
split; tauto.
|
|
Qed.
|
|
|
|
Lemma store_uint_array_rec_def2undef: forall x a b l,
|
|
store_uint_array_rec x a b l |--
|
|
store_undef_uint_array_rec x a b.
|
|
Proof. Admitted.
|
|
|
|
Lemma store_undef_uint_array_rec_divide: forall x l mid r,
|
|
0 <= l <= r ->
|
|
l <= mid <= r ->
|
|
store_undef_uint_array_rec x l r --||--
|
|
store_undef_uint_array_rec x l mid ** store_undef_uint_array_rec x mid r.
|
|
Proof.
|
|
intros.
|
|
unfold store_undef_uint_array_rec.
|
|
pose proof (store_undef_array_divide (x + l * sizeof(UINT)) (r - l) (mid - l) (sizeof(UINT))
|
|
(fun x => x # UInt |->_)
|
|
(fun x0 lo => (x0 + lo * sizeof(UINT)) # UInt |->_) ltac:(lia) ltac:(reflexivity)).
|
|
unfold store_undef_array in H1.
|
|
pose (fun (l: Z) (n: Z) (len: nat) => store_undef_array_rec_base x 0 l n len (sizeof(UINT))
|
|
(fun x => x # UInt |->_)
|
|
(fun x0 lo => (x0 + lo * sizeof(UINT)) # UInt |->_) ltac:(reflexivity)).
|
|
rewrite <-(l0 l r (Z.to_nat (r - l))) in H1.
|
|
rewrite <-(l0 l mid (Z.to_nat (mid - l))) in H1.
|
|
assert (r - l - (mid - l) = r - mid). { lia. }
|
|
rewrite H2 in H1; clear H2.
|
|
rewrite <-Z.add_assoc, <-Z.mul_add_distr_r in H1.
|
|
assert (l + (mid - l) = mid). { lia. }
|
|
rewrite H2 in H1; clear H2.
|
|
rewrite <-(l0 mid r (Z.to_nat (r - mid))) in H1.
|
|
repeat rewrite Z.add_0_l in H1.
|
|
clear l0.
|
|
rewrite H1.
|
|
split; entailer!.
|
|
Qed.
|
|
End Aux. |