Require Import Coqlib Values Zbits Integers Lattice.
Require Import RTL Registers Maps.
Require Eqdep_dec.
Require Import Program.
Require AST.
Inductive ibool :=
|
Bnone
|
Just (
b :
bool)
|
Any_bool
|
Btop.
Inductive cmatch :
option bool ->
ibool ->
Prop :=
|
cmatch_none :
cmatch None Bnone
|
cmatch_just :
forall b,
cmatch (
Some b) (
Just b)
|
cmatch_any:
forall b,
cmatch (
Some b)
Any_bool
|
cmatch_top:
forall ob,
cmatch ob Btop.
Unset Transparent Obligations.
Section Decidable.
Variable T:
Type.
Variable beq :
T ->
T ->
bool.
Variable beq_correct:
forall x y,
beq x y =
true ->
x =
y.
Variable beq_correct2:
forall x y,
beq x y =
false ->
x <>
y.
Definition eq_dec:
forall (
x y :
T), {
x=
y} + {
x<>
y}.
Proof.
End Decidable.
Module Interval <:
SEMILATTICE_WITHOUT_BOTTOM.
Record interval :=
mkinterval {
itv_lo :
Z.t;
itv_hi :
Z.t;
itv_ok :
itv_lo <=?
itv_hi =
true }.
Lemma itv_eq_bounds :
forall a b,
a.(
itv_lo) =
b.(
itv_lo) ->
a.(
itv_hi) =
b.(
itv_hi) ->
a =
b.
Proof.
intros.
destruct a as [
aulo auhi auok].
destruct b as [
bulo buhi buok].
cbn in *.
subst.
f_equal.
apply Eqdep_dec.UIP_dec.
decide equality.
Qed.
Definition t :=
interval.
Definition eq := @
eq t.
Lemma eq_refl:
forall x,
eq x x.
Proof.
Lemma eq_sym:
forall x y,
eq x y ->
eq y x.
Proof.
Definition eq2 a b :=
a.(
itv_lo) =
b.(
itv_lo) /\
a.(
itv_hi) =
b.(
itv_hi).
Lemma eq2_eqv:
forall a b,
eq a b <->
eq2 a b.
Proof.
unfold eq,
eq2.
intros.
split.
intuition congruence.
intros (
LO &
HI).
apply itv_eq_bounds;
assumption.
Qed.
Lemma eq_trans:
forall x y z,
eq x y ->
eq y z ->
eq x z.
Proof.
Definition beq (
a b :
t) :=
(
a.(
itv_lo) =?
b.(
itv_lo)) && (
a.(
itv_hi) =?
b.(
itv_hi)).
Lemma beq_correct:
forall x y,
beq x y =
true ->
eq x y.
Proof.
intros.
rewrite eq2_eqv.
unfold beq,
eq2 in *.
intuition lia.
Qed.
Lemma beq_correct2:
forall x y,
beq x y =
false ->
x <>
y.
Proof.
intros.
destruct x.
destruct y.
unfold beq in *.
cbn in *.
intro Z.
inv Z.
lia.
Qed.
Lemma eq_dec:
forall (
a b :
t), {
a=
b} + {
a<>
b}.
Proof.
Definition ge (
a b :
t) :=
a.(
itv_lo) <=
b.(
itv_lo) /\
a.(
itv_hi) >=
b.(
itv_hi).
Lemma ge_refl:
forall x y,
eq x y ->
ge x y.
Proof.
unfold eq,
ge.
intros.
subst.
intuition lia.
Qed.
Lemma ge_trans:
forall x y z,
ge x y ->
ge y z ->
ge x z.
Proof.
unfold ge.
intuition lia.
Qed.
Lemma ge_antisym :
forall x y,
ge x y ->
ge y x ->
eq x y.
Proof.
intros.
rewrite eq2_eqv.
unfold ge,
eq2 in *.
intuition lia.
Qed.
Program Definition lub (
a b :
t) :=
{|
itv_lo :=
Z.min a.(
itv_lo)
b.(
itv_lo);
itv_hi :=
Z.max a.(
itv_hi)
b.(
itv_hi);
itv_ok := _ |}.
Obligation 1.
Proof.
destruct a. destruct b. cbn. lia.
Qed.
Lemma ge_lub_left:
forall x y,
ge (
lub x y)
x.
Proof.
unfold ge,
lub.
cbn.
intuition lia.
Qed.
Lemma ge_lub_right:
forall x y,
ge (
lub x y)
y.
Proof.
unfold ge,
lub.
cbn.
intuition lia.
Qed.
Lemma lub_least:
forall r p q,
ge r p ->
ge r q ->
ge r (
lub p q).
Proof.
unfold ge.
intros.
destruct r.
destruct p.
destruct q.
cbn in *.
intuition lia.
Qed.
Definition zmatch z itv :=
itv.(
itv_lo) <=
z <=
itv.(
itv_hi).
Lemma zmatch_lub_left :
forall z a b (
MATCH :
zmatch z a), (
zmatch z (
lub a b)).
Proof.
destruct a,
b.
unfold zmatch,
lub;
cbn.
lia.
Qed.
Lemma zmatch_lub_right :
forall z a b (
MATCH :
zmatch z b), (
zmatch z (
lub a b)).
Proof.
destruct a,
b.
unfold zmatch,
lub;
cbn.
lia.
Qed.
Definition ge_sem a b :=
forall z, (
zmatch z b) -> (
zmatch z a).
Lemma ge_sem_eqv :
forall a b,
ge a b <->
ge_sem a b.
Proof.
unfold ge,
ge_sem,
zmatch.
intros.
destruct a.
destruct b.
cbn.
split.
-
intuition lia.
-
intro ZZ.
split.
+
apply ZZ.
lia.
+
apply Z.le_ge.
apply ZZ.
lia.
Qed.
Lemma zmatch_ge:
forall a b z,
ge a b ->
zmatch z b ->
zmatch z a.
Proof.
Definition eq_sem a b :=
forall z, (
zmatch z a) <-> (
zmatch z b).
Lemma eq_sem_eqv :
forall a b,
eq a b <->
eq_sem a b.
Proof.
Program Definition add (
a b :
t) :
t :=
{|
itv_lo :=
Z.add a.(
itv_lo)
b.(
itv_lo) ;
itv_hi :=
Z.add a.(
itv_hi)
b.(
itv_hi) ;
itv_ok := _ |}.
Next Obligation.
destruct a. destruct b. cbn. lia.
Qed.
Lemma zmatch_add :
forall (
x y :
Z.t) (
a b :
t) (
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch (
Z.add x y) (
add a b).
Proof.
destruct a.
destruct b.
unfold add,
zmatch.
cbn.
lia.
Qed.
Lemma minimal_add :
forall itv a b
(
OK :
forall (
x y :
Z.t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch (
Z.add x y)
itv),
ge itv (
add a b).
Proof.
destruct a.
destruct b.
destruct itv.
unfold zmatch,
ge.
cbn.
intros.
pose proof (
OK itv_hi0 itv_hi1).
pose proof (
OK itv_lo0 itv_lo1).
lia.
Qed.
Program Definition sub (
a b :
t) :
t :=
{|
itv_lo :=
Z.sub a.(
itv_lo)
b.(
itv_hi) ;
itv_hi :=
Z.sub a.(
itv_hi)
b.(
itv_lo) ;
itv_ok := _ |}.
Next Obligation.
destruct a. destruct b. cbn. lia.
Qed.
Lemma zmatch_sub :
forall (
x y :
Z.t) (
a b :
t) (
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch (
Z.sub x y) (
sub a b).
Proof.
destruct a.
destruct b.
unfold sub,
zmatch.
cbn.
lia.
Qed.
Lemma minimal_sub :
forall itv a b
(
OK :
forall (
x y :
Z.t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch (
Z.sub x y)
itv),
ge itv (
sub a b).
Proof.
destruct a.
destruct b.
destruct itv.
unfold zmatch,
ge.
cbn.
intros.
pose proof (
OK itv_hi0 itv_lo1).
pose proof (
OK itv_lo0 itv_hi1).
lia.
Qed.
Program Definition mul (
a b :
t) :
t :=
let c1 :=
Z.mul a.(
itv_lo)
b.(
itv_lo)
in
let c2 :=
Z.mul a.(
itv_lo)
b.(
itv_hi)
in
let c3 :=
Z.mul a.(
itv_hi)
b.(
itv_lo)
in
let c4 :=
Z.mul a.(
itv_hi)
b.(
itv_hi)
in
{|
itv_lo :=
Z.min (
Z.min c1 c2) (
Z.min c3 c4) ;
itv_hi :=
Z.max (
Z.max c1 c2) (
Z.max c3 c4) ;
itv_ok := _ |}.
Next Obligation.
destruct a.
destruct b.
unfold zmatch.
cbn.
nia.
Qed.
Lemma zmatch_mul :
forall (
x y :
Z.t) (
a b :
t) (
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch (
Z.mul x y) (
mul a b).
Proof.
Lemma minimal_mul :
forall itv a b
(
OK :
forall (
x y :
Z.t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch (
Z.mul x y)
itv),
ge itv (
mul a b).
Proof.
destruct a.
destruct b.
destruct itv.
unfold zmatch,
ge.
cbn.
intros.
pose proof (
OK itv_hi0 itv_lo1).
pose proof (
OK itv_lo0 itv_hi1).
pose proof (
OK itv_lo0 itv_lo1).
pose proof (
OK itv_hi0 itv_hi1).
lia.
Qed.
Program Definition shl (
lhs rhs :
t)
(
POS_lhs: 0 <=?
itv_lo lhs =
true)
(
POS_rhs: 0 <=?
itv_lo rhs =
true) :
t :=
mkinterval (
Z.shiftl lhs.(
itv_lo)
rhs.(
itv_lo))
(
Z.shiftl lhs.(
itv_hi)
rhs.(
itv_hi)) _.
Next Obligation.
Lemma zmatch_shl (
x y :
Z.t) (
a b :
t)
POS_a POS_b:
zmatch x a ->
zmatch y b ->
zmatch (
Z.shiftl x y) (
shl a b POS_a POS_b).
Proof.
Program Definition intconst i :=
mkinterval i i _.
Next Obligation.
lia.
Qed.
Lemma zmatch_intconst:
forall i,
zmatch i (
intconst i).
Proof.
Program Definition glb_nb (
a b :
t) :
option t :=
let lo :=
Z.max a.(
itv_lo)
b.(
itv_lo)
in
let hi :=
Z.min a.(
itv_hi)
b.(
itv_hi)
in
if zle lo hi
then Some (
mkinterval lo hi _)
else None.
Next Obligation.
lia.
Qed.
Lemma zmatch_glb_nb:
forall x a b
(
MATCHx :
zmatch x a) (
MATCHy :
zmatch x b),
exists c,
glb_nb a b =
Some c /\
zmatch x c.
Proof.
unfold zmatch,
glb_nb;
destruct a;
destruct b;
cbn;
intros.
destruct zle.
-
eexists.
split.
reflexivity.
cbn.
lia.
-
exfalso.
lia.
Qed.
Program Definition filter_less_equal (
i0 i1 :
t) :
option (
t*
t) :=
if zle i0.(
itv_lo)
i1.(
itv_hi)
then Some((
mkinterval i0.(
itv_lo) (
Z.min i0.(
itv_hi)
i1.(
itv_hi)) _),
(
mkinterval (
Z.max i0.(
itv_lo)
i1.(
itv_lo))
i1.(
itv_hi) _))
else None.
Solve Obligations with destruct i0,
i1;
cbn in *;
lia.
Lemma zmatch_filter_less_equal :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x <=
y),
exists a',
exists b',
filter_less_equal a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
unfold zmatch,
filter_less_equal.
destruct a,
b.
cbn.
intros.
destruct zle;
cbn;
cycle 1.
{
exfalso.
lia. }
eexists.
eexists.
split.
reflexivity.
cbn.
split;
lia.
Qed.
Program Definition filter_less (
i0 i1 :
t) :
option (
t*
t) :=
if zlt i0.(
itv_lo)
i1.(
itv_hi)
then Some((
mkinterval i0.(
itv_lo) (
Z.min i0.(
itv_hi) (
i1.(
itv_hi)-1)) _),
(
mkinterval (
Z.max (
i0.(
itv_lo)+1)
i1.(
itv_lo))
i1.(
itv_hi) _))
else None.
Solve Obligations with destruct i0,
i1;
cbn in *;
lia.
Lemma zmatch_filter_less :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x <
y),
exists a',
exists b',
filter_less a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
unfold zmatch,
filter_less.
destruct a,
b.
cbn.
intros.
destruct zlt;
cbn;
cycle 1.
{
exfalso.
lia. }
eexists.
eexists.
split.
reflexivity.
cbn.
split;
lia.
Qed.
Definition pair_lub ip0 ip1 :=
match ip0,
ip1 with
|
Some(
i0',
i1'),
None =>
Some(
i0',
i1')
|
None,
Some(
i0',
i1') =>
Some(
i0',
i1')
|
Some(
i0',
i1'),
Some(
i0'',
i1'') =>
Some ((
lub i0' i0''), (
lub i1' i1''))
|
None,
None =>
None
end.
Lemma zmatch_pair_lub_left :
forall (
x y :
Z.t) (
a b :
t) (
other :
option(
t*
t))
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
exists a',
exists b',
pair_lub (
Some (
a,
b))
other =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
intros.
unfold pair_lub.
destruct other as [[
a' b'] | ];
cbn.
-
eexists.
eexists.
split.
reflexivity.
split.
+
apply zmatch_lub_left.
assumption.
+
apply zmatch_lub_left.
assumption.
-
eexists.
eexists.
split.
reflexivity.
split;
assumption.
Qed.
Lemma zmatch_pair_lub_right :
forall (
other :
option(
t*
t)) (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
exists a',
exists b',
pair_lub other (
Some (
a,
b)) =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
intros.
unfold pair_lub.
destruct other as [[
a' b'] | ];
cbn.
-
eexists.
eexists.
split.
reflexivity.
split.
+
apply zmatch_lub_right.
assumption.
+
apply zmatch_lub_right.
assumption.
-
eexists.
eexists.
split.
reflexivity.
split;
assumption.
Qed.
Definition filter_not_equal i0 i1 :=
match (
filter_less i0 i1),
(
filter_less i1 i0)
with
|
Some(
i0',
i1'),
None =>
Some(
i0',
i1')
|
None,
Some(
i1',
i0') =>
Some(
i0',
i1')
|
Some(
i0',
i1'),
Some(
i1'',
i0'') =>
Some ((
lub i0' i0''), (
lub i1' i1''))
|
None,
None =>
None
end.
Lemma zmatch_filter_not_equal :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x <>
y),
exists a',
exists b',
filter_not_equal a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
intros.
unfold filter_not_equal.
assert (
x <
y \/
y <
x)
as INEQ by lia.
destruct INEQ as [
LT |
GT].
{
destruct (
zmatch_filter_less x y a b AMATCH BMATCH LT)
as (
a' &
b' &
RE &
AMATCH' &
BMATCH').
rewrite RE.
destruct (
filter_less b a)
as [[
b'' a'']| ].
{
eexists.
eexists.
eauto using zmatch_lub_left. }
eexists.
eexists.
eauto.
}
destruct (
zmatch_filter_less y x b a BMATCH AMATCH GT)
as (
b' &
a' &
RE &
BMATCH' &
AMATCH').
rewrite RE.
destruct (
filter_less a b)
as [[
a'' b'']| ].
{
eexists.
eexists.
eauto using zmatch_lub_right. }
eexists.
eexists.
eauto.
Qed.
End Interval.
Module Interval_Bot <:
SEMILATTICE.
Include ADD_BOTTOM(
Interval).
Lemma ge_glb_nb_left:
forall (
a b :
Interval.t),
ge (
Some a) (
Interval.glb_nb a b).
Proof.
Lemma ge_glb_nb_right:
forall (
a b :
Interval.t),
ge (
Some b) (
Interval.glb_nb a b).
Proof.
Definition glb (
a b :
t) :
t :=
match a,
b with
|
None, _ | _,
None =>
None
| (
Some x), (
Some y) =>
Interval.glb_nb x y
end.
Lemma glb_greatest:
forall r p q,
ge p r ->
ge q r ->
ge (
glb p q)
r.
Proof.
unfold ge.
intros until q.
intros GE0 GE1.
destruct p;
destruct q;
destruct r;
cbn;
trivial.
{
unfold Interval.glb_nb.
destruct t0 as [
lo0 hi0 LE0].
destruct t1 as [
lo1 hi1 LE1].
destruct t2 as [
lo2 hi2 LE2].
inv GE0.
inv GE1.
cbn in *.
destruct zle ;
cbn in *.
-
constructor;
cbn;
lia.
-
lia.
}
destruct Interval.glb_nb;
trivial.
Qed.
Definition eq_dec:
forall (
x y :
t), {
x =
y} + {
x <>
y}.
Proof.
End Interval_Bot.
Module Type MODULUS_TYPE.
Axiom modulus :
Z.t.
Axiom modulus_pos :
modulus > 0.
End MODULUS_TYPE.
Module Modulus_Interval(
Int_Type :
MODULUS_TYPE).
Notation modulus :=
Int_Type.modulus.
Notation modulus_positive :=
Int_Type.modulus_pos.
Record mod_interval :=
mkmod_interval {
mod_itv :
Interval.t ;
mod_lo : (0 <=?
mod_itv.(
Interval.itv_lo) =
true);
mod_hi : (
mod_itv.(
Interval.itv_hi) <?
modulus) =
true }.
Definition t :=
mod_interval.
Definition eq := @
eq t.
Lemma eq_refl :
forall x,
eq x x.
Proof.
Lemma eq_sym:
forall x y,
eq x y ->
eq y x.
Proof.
Lemma eq_trans:
forall x y z,
eq x y ->
eq y z ->
eq x z.
Proof.
Definition eq2 a b :=
a.(
mod_itv) =
b.(
mod_itv).
Lemma itv_eq_bounds :
forall a b,
a.(
mod_itv) =
b.(
mod_itv) ->
a =
b.
Proof.
destruct a.
destruct b.
cbn in *.
intro.
subst.
f_equal.
all:
apply Eqdep_dec.UIP_dec;
decide equality.
Qed.
Lemma eq2_eqv:
forall a b,
eq a b <->
eq2 a b.
Proof.
unfold eq,
eq2.
intros.
split.
intuition congruence.
intro.
apply itv_eq_bounds;
assumption.
Qed.
Definition beq (
a b :
t) :=
Interval.beq a.(
mod_itv)
b.(
mod_itv).
Lemma beq_correct:
forall x y,
beq x y =
true ->
eq x y.
Proof.
Lemma beq_correct2:
forall x y,
beq x y =
false ->
x <>
y.
Proof.
Lemma eq_dec:
forall (
a b :
t), {
a=
b} + {
a<>
b}.
Proof.
Definition ge (
a b :
t) :=
Interval.ge a.(
mod_itv)
b.(
mod_itv).
Lemma ge_refl:
forall x y,
eq x y ->
ge x y.
Proof.
Lemma ge_trans:
forall x y z,
ge x y ->
ge y z ->
ge x z.
Proof.
Lemma ge_antisym :
forall x y,
ge x y ->
ge y x ->
eq x y.
Proof.
Program Definition lub (
a b :
t) :=
mkmod_interval (
Interval.lub a.(
mod_itv)
b.(
mod_itv)) _ _.
Solve Obligations with (
destruct a;
destruct b;
cbn;
lia).
Lemma ge_lub_left:
forall x y,
ge (
lub x y)
x.
Proof.
Lemma ge_lub_right:
forall x y,
ge (
lub x y)
y.
Proof.
Lemma lub_least:
forall r p q,
ge r p ->
ge r q ->
ge r (
lub p q).
Proof.
Program Definition full_range :
t :=
mkmod_interval (
Interval.mkinterval 0 (
modulus - 1) _) _ _.
Next Obligation.
Next Obligation.
Definition zmatch z a :=
Interval.zmatch z a.(
mod_itv).
Lemma zmatch_lub_left :
forall z a b (
MATCH :
zmatch z a), (
zmatch z (
lub a b)).
Proof.
Lemma zmatch_lub_right :
forall z a b (
MATCH :
zmatch z b), (
zmatch z (
lub a b)).
Proof.
Lemma zmatch_full_range :
forall z (
RANGE : 0 <=
z <
modulus),
zmatch z full_range.
Proof.
Program Definition force (
a :
Interval.t) :
t :=
if Z_ge_lt_dec a.(
Interval.itv_lo) 0
then if Z_ge_lt_dec a.(
Interval.itv_hi)
modulus
then full_range
else mkmod_interval a _ _
else full_range.
Solve Obligations with lia.
Definition add (
a b :
t) :=
force (
Interval.add a.(
mod_itv)
b.(
mod_itv)).
Definition sub (
a b :
t) :=
force (
Interval.sub a.(
mod_itv)
b.(
mod_itv)).
Definition mul (
a b :
t) :=
force (
Interval.mul a.(
mod_itv)
b.(
mod_itv)).
Lemma zmatch_force :
forall z a,
(
Interval.zmatch z a) ->
(
zmatch (
z mod modulus) (
force a)).
Proof.
Lemma zmatch_add:
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch ((
x +
y)
mod modulus) (
add a b).
Proof.
Lemma zmatch_sub:
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch ((
x -
y)
mod modulus) (
sub a b).
Proof.
Lemma zmatch_mul:
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
zmatch ((
x *
y)
mod modulus) (
mul a b).
Proof.
Program Definition intconst i :=
mkmod_interval (
Interval.intconst (
i mod modulus)) _ _.
Next Obligation.
Next Obligation.
Lemma zmatch_intconst :
forall i,
zmatch (
i mod modulus) (
intconst i).
Proof.
Lemma zmatch_ge:
forall a b z,
ge a b ->
zmatch z b ->
zmatch z a.
Proof.
Program Definition glb_nb (
a b :
t) :
option t :=
let lo :=
Z.max a.(
mod_itv).(
Interval.itv_lo)
b.(
mod_itv).(
Interval.itv_lo)
in
let hi :=
Z.min a.(
mod_itv).(
Interval.itv_hi)
b.(
mod_itv).(
Interval.itv_hi)
in
if zle lo hi
then Some (
mkmod_interval (
Interval.mkinterval lo hi _) _ _)
else None.
Next Obligation.
lia.
Qed.
Next Obligation.
destruct a. destruct b. cbn in *. lia.
Qed.
Next Obligation.
destruct a. destruct b. cbn in *. lia.
Qed.
Lemma zmatch_glb_nb:
forall x a b
(
MATCHx :
zmatch x a) (
MATCHy :
zmatch x b),
exists c,
glb_nb a b =
Some c /\
zmatch x c.
Proof.
Program Definition filter_less_equal (
i0 i1 :
t) :
option (
t*
t) :=
if zle i0.(
mod_itv).(
Interval.itv_lo)
i1.(
mod_itv).(
Interval.itv_hi)
then Some((
mkmod_interval
(
Interval.mkinterval i0.(
mod_itv).(
Interval.itv_lo)
(
Z.min i0.(
mod_itv).(
Interval.itv_hi)
i1.(
mod_itv).(
Interval.itv_hi)) _) _ _),
(
mkmod_interval
(
Interval.mkinterval (
Z.max i0.(
mod_itv).(
Interval.itv_lo)
i1.(
mod_itv).(
Interval.itv_lo))
i1.(
mod_itv).(
Interval.itv_hi) _) _ _))
else None.
Solve Obligations with (
destruct i0,
i1,
mod_itv0,
mod_itv1;
cbn in *;
lia).
Lemma zmatch_filter_less_equal :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x <=
y),
exists a',
exists b',
filter_less_equal a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
Program Definition filter_less (
i0 i1 :
t) :
option (
t*
t) :=
if zlt i0.(
mod_itv).(
Interval.itv_lo)
i1.(
mod_itv).(
Interval.itv_hi)
then Some((
mkmod_interval
(
Interval.mkinterval i0.(
mod_itv).(
Interval.itv_lo)
(
Z.min i0.(
mod_itv).(
Interval.itv_hi)
(
i1.(
mod_itv).(
Interval.itv_hi)-1)) _) _ _),
(
mkmod_interval
(
Interval.mkinterval (
Z.max (
i0.(
mod_itv).(
Interval.itv_lo)+1)
i1.(
mod_itv).(
Interval.itv_lo))
i1.(
mod_itv).(
Interval.itv_hi) _) _ _))
else None.
Solve Obligations with (
destruct i0,
i1,
mod_itv0,
mod_itv1;
cbn in *;
lia).
Definition filter_greater (
i0 i1 :
t) :=
match filter_less i1 i0 with
|
Some(
i1',
i0') => (
Some(
i0',
i1'))
|
None =>
None
end.
Definition filter_greater_equal (
i0 i1 :
t) :=
match filter_less_equal i1 i0 with
|
Some(
i1',
i0') => (
Some(
i0',
i1'))
|
None =>
None
end.
Lemma zmatch_filter_less :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x <
y),
exists a',
exists b',
filter_less a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
unfold zmatch,
Interval.zmatch,
filter_less.
destruct a,
b,
mod_itv0,
mod_itv1.
cbn.
intros.
destruct zlt;
cbn;
cycle 1.
{
exfalso.
lia. }
eexists.
eexists.
split.
reflexivity.
cbn.
split;
lia.
Qed.
Lemma zmatch_filter_greater :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x >
y),
exists a',
exists b',
filter_greater a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
unfold filter_greater.
intros.
assert (
y <
x)
as ORDER by lia.
destruct (
zmatch_filter_less y x b a BMATCH AMATCH ORDER)
as (
b' &
a' &
RE &
MATCHB' &
MATCHA' ).
exists a'.
exists b'.
rewrite RE.
auto.
Qed.
Lemma zmatch_filter_greater_equal :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x >=
y),
exists a',
exists b',
filter_greater_equal a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
Definition filter_not_equal i0 i1 :=
match (
filter_less i0 i1),
(
filter_less i1 i0)
with
|
Some(
i0',
i1'),
None =>
Some(
i0',
i1')
|
None,
Some(
i1',
i0') =>
Some(
i0',
i1')
|
Some(
i0',
i1'),
Some(
i1'',
i0'') =>
Some ((
lub i0' i0''), (
lub i1' i1''))
|
None,
None =>
None
end.
Lemma zmatch_filter_not_equal :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x <>
y),
exists a',
exists b',
filter_not_equal a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
intros.
unfold filter_not_equal.
assert (
x <
y \/
y <
x)
as INEQ by lia.
destruct INEQ as [
LT |
GT].
{
destruct (
zmatch_filter_less x y a b AMATCH BMATCH LT)
as (
a' &
b' &
RE &
AMATCH' &
BMATCH').
rewrite RE.
destruct (
filter_less b a)
as [[
b'' a'']| ].
{
eexists.
eexists.
eauto using zmatch_lub_left. }
eexists.
eexists.
eauto.
}
destruct (
zmatch_filter_less y x b a BMATCH AMATCH GT)
as (
b' &
a' &
RE &
BMATCH' &
AMATCH').
rewrite RE.
destruct (
filter_less a b)
as [[
a'' b'']| ].
{
eexists.
eexists.
eauto using zmatch_lub_right. }
eexists.
eexists.
eauto.
Qed.
Definition filter_equal i0 i1 :=
match glb_nb i0 i1 with
|
Some x =>
Some(
x,
x)
|
None =>
None
end.
Lemma zmatch_filter_equal :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
x =
y),
exists a',
exists b',
filter_equal a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
intros.
unfold filter_equal.
subst y.
destruct (
zmatch_glb_nb x a b AMATCH BMATCH)
as (
c &
RE &
MATCH).
exists c.
exists c.
rewrite RE.
auto.
Qed.
Section FILTER_TO_ABOOL.
Variable pred:
Z.t ->
Z.t ->
bool.
Variable filter :
t ->
t ->
option (
t*
t).
Hypothesis zmatch_filter :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
pred x y =
true),
exists a',
exists b',
filter a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Variable filter_not :
t ->
t ->
option (
t*
t).
Hypothesis zmatch_filter_not :
forall (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b)
(
CMP :
pred x y =
false),
exists a',
exists b',
filter_not a b =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Definition filter_to_eval (
a b :
t) :
ibool :=
match (
filter a b), (
filter_not a b)
with
| (
Some _), (
Some _) =>
Any_bool
| (
Some _),
None =>
Just true
|
None, (
Some _) =>
Just false
|
None,
None =>
Bnone
end.
Lemma filter_to_eval_sound:
forall (
x y :
Z.t) (
a b :
t) (
AMATCH:
zmatch x a) (
BMATCH:
zmatch y b),
cmatch (
Some (
pred x y)) (
filter_to_eval a b).
Proof.
intros.
unfold filter_to_eval.
destruct (
pred x y)
eqn:
PRED.
-
pose proof (
zmatch_filter x y a b AMATCH BMATCH PRED)
as (
a' &
b' &
RE &
MATCHA' &
MATCHB').
rewrite RE.
destruct filter_not;
constructor.
-
pose proof (
zmatch_filter_not x y a b AMATCH BMATCH PRED)
as (
a' &
b' &
RE &
MATCHA' &
MATCHB').
rewrite RE.
destruct filter;
constructor.
Qed.
End FILTER_TO_ABOOL.
Definition pair_lub ip0 ip1 :=
match ip0,
ip1 with
|
Some(
i0',
i1'),
None =>
Some(
i0',
i1')
|
None,
Some(
i0',
i1') =>
Some(
i0',
i1')
|
Some(
i0',
i1'),
Some(
i0'',
i1'') =>
Some ((
lub i0' i0''), (
lub i1' i1''))
|
None,
None =>
None
end.
Lemma zmatch_pair_lub_left :
forall (
x y :
Z.t) (
a b :
t) (
other :
option(
t*
t))
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
exists a',
exists b',
pair_lub (
Some (
a,
b))
other =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
intros.
unfold pair_lub.
destruct other as [[
a' b'] | ];
cbn.
-
eexists.
eexists.
split.
reflexivity.
split.
+
apply zmatch_lub_left.
assumption.
+
apply zmatch_lub_left.
assumption.
-
eexists.
eexists.
split.
reflexivity.
split;
assumption.
Qed.
Lemma zmatch_pair_lub_right :
forall (
other :
option(
t*
t)) (
x y :
Z.t) (
a b :
t)
(
AMATCH :
zmatch x a) (
BMATCH :
zmatch y b),
exists a',
exists b',
pair_lub other (
Some (
a,
b)) =
Some(
a',
b') /\
zmatch x a' /\
zmatch y b'.
Proof.
intros.
unfold pair_lub.
destruct other as [[
a' b'] | ];
cbn.
-
eexists.
eexists.
split.
reflexivity.
split.
+
apply zmatch_lub_right.
assumption.
+
apply zmatch_lub_right.
assumption.
-
eexists.
eexists.
split.
reflexivity.
split;
assumption.
Qed.
End Modulus_Interval.
Module Modulus_Interval_Bot(
Int_Type :
MODULUS_TYPE) <:
SEMILATTICE.
Module ModInt :=
Modulus_Interval(
Int_Type).
Include ADD_BOTTOM(
ModInt).
Lemma ge_glb_nb_left:
forall (
a b :
ModInt.t),
ge (
Some a) (
ModInt.glb_nb a b).
Proof.
unfold ModInt.glb_nb,
ge.
intros.
destruct zle. 2:
constructor.
constructor;
cbn;
lia.
Qed.
Lemma ge_glb_nb_right:
forall (
a b :
ModInt.t),
ge (
Some b) (
ModInt.glb_nb a b).
Proof.
unfold ModInt.glb_nb,
ge.
intros.
destruct zle. 2:
constructor.
constructor;
cbn;
lia.
Qed.
Definition glb (
a b :
t) :
t :=
match a,
b with
|
None, _ | _,
None =>
None
| (
Some x), (
Some y) =>
ModInt.glb_nb x y
end.
Lemma glb_greatest:
forall r p q,
ge p r ->
ge q r ->
ge (
glb p q)
r.
Proof.
unfold ge.
intros until q.
intros GE0 GE1.
destruct p,
q,
r;
cbn;
trivial.
{
unfold ModInt.glb_nb.
destruct t0 as [
lo0 hi0 LE0].
destruct t1 as [
lo1 hi1 LE1].
destruct t2 as [
lo2 hi2 LE2].
inv GE0.
inv GE1.
cbn in *.
destruct zle ;
cbn in *.
-
constructor;
cbn;
lia.
-
destruct lo0,
lo1,
lo2;
cbn in *.
lia.
}
destruct ModInt.glb_nb;
trivial.
Qed.
Definition eq_dec:
forall (
x y :
t), {
x =
y} + {
x <>
y}.
Proof.
End Modulus_Interval_Bot.
Module Int_Modulus_Interval_Bot :=
Modulus_Interval_Bot(
Int).
Module Int_Modulus_Interval :=
Int_Modulus_Interval_Bot.ModInt.
Module Int64_Modulus_Interval_Bot :=
Modulus_Interval_Bot(
Int64).
Module Int64_Modulus_Interval :=
Int64_Modulus_Interval_Bot.ModInt.
Inductive ival :=
|
Itop :
ival
|
Iint :
bool ->
Int_Modulus_Interval.t ->
ival
|
Ilong :
bool ->
Int64_Modulus_Interval.t ->
ival
|
Iundef :
ival
|
Ibot :
ival.
Inductive vmatch :
val ->
ival ->
Prop :=
|
vmatch_iitv :
forall i b itv,
Int_Modulus_Interval.zmatch (
Int.unsigned i)
itv ->
vmatch (
Vint i) (
Iint b itv)
|
vmatch_undef_iitv :
forall itv,
vmatch Vundef (
Iint true itv)
|
vmatch_litv :
forall l b itv,
Int64_Modulus_Interval.zmatch (
Int64.unsigned l)
itv ->
vmatch (
Vlong l) (
Ilong b itv)
|
vmatch_undef_litv :
forall itv,
vmatch Vundef (
Ilong true itv)
|
vmatch_undef:
vmatch Vundef Iundef
|
vmatch_top :
forall v,
vmatch v Itop.
Global Hint Constructors vmatch :
ival.
Definition intconst i :
ival :=
Iint false (
Int_Modulus_Interval.intconst (
Int.unsigned i)).
Lemma intconst_sound :
forall i,
vmatch (
Vint i) (
intconst i).
Proof.
Definition longconst i :
ival :=
Ilong false (
Int64_Modulus_Interval.intconst (
Int64.unsigned i)).
Lemma longconst_sound :
forall i,
vmatch (
Vlong i) (
longconst i).
Proof.
Definition add a1 a2 :=
match a1,
a2 with
|
Iint b1 i1,
Iint b2 i2 =>
Iint (
orb b1 b2) (
Int_Modulus_Interval.add i1 i2)
| _, _ =>
Itop
end.
Lemma add_sound:
forall v w x y
(
MATCHx :
vmatch v x) (
MATCHy :
vmatch w y),
vmatch (
Val.add v w) (
add x y).
Proof.
Definition sub a1 a2 :=
match a1,
a2 with
|
Iint b1 i1,
Iint b2 i2 =>
Iint (
orb b1 b2) (
Int_Modulus_Interval.sub i1 i2)
| _, _ =>
Itop
end.
Lemma sub_sound:
forall v w x y
(
MATCHx :
vmatch v x) (
MATCHy :
vmatch w y),
vmatch (
Val.sub v w) (
sub x y).
Proof.
Definition mul a1 a2 :=
match a1,
a2 with
|
Iint b1 i1,
Iint b2 i2 =>
Iint (
orb b1 b2) (
Int_Modulus_Interval.mul i1 i2)
| _, _ =>
Itop
end.
Lemma mul_sound:
forall v w x y
(
MATCHx :
vmatch v x) (
MATCHy :
vmatch w y),
vmatch (
Val.mul v w) (
mul x y).
Proof.
Definition addl a1 a2 :=
match a1,
a2 with
|
Ilong b1 i1,
Ilong b2 i2 =>
Ilong (
orb b1 b2) (
Int64_Modulus_Interval.add i1 i2)
| _, _ =>
Itop
end.
Lemma addl_sound:
forall v w x y
(
MATCHx :
vmatch v x) (
MATCHy :
vmatch w y),
vmatch (
Val.addl v w) (
addl x y).
Proof.
Definition subl a1 a2 :=
match a1,
a2 with
|
Ilong b1 i1,
Ilong b2 i2 =>
Ilong (
orb b1 b2) (
Int64_Modulus_Interval.sub i1 i2)
| _, _ =>
Itop
end.
Lemma subl_sound:
forall v w x y
(
MATCHx :
vmatch v x) (
MATCHy :
vmatch w y),
vmatch (
Val.subl v w) (
subl x y).
Proof.
Definition mull a1 a2 :=
match a1,
a2 with
|
Ilong b1 i1,
Ilong b2 i2 =>
Ilong (
orb b1 b2) (
Int64_Modulus_Interval.mul i1 i2)
| _, _ =>
Itop
end.
Lemma mull_sound:
forall v w x y
(
MATCHx :
vmatch v x) (
MATCHy :
vmatch w y),
vmatch (
Val.mull v w) (
mull x y).
Proof.
Inductive ige :
ival ->
ival ->
Prop :=
|
Ige_int :
forall b1 i1 b2 i2,
Bool.le b2 b1 ->
Int_Modulus_Interval.ge i1 i2 ->
ige (
Iint b1 i1) (
Iint b2 i2)
|
Ige_long :
forall b1 i1 b2 i2,
Bool.le b2 b1 ->
Int64_Modulus_Interval.ge i1 i2 ->
ige (
Ilong b1 i1) (
Ilong b2 i2)
|
Ige_top :
forall x,
ige Itop x
|
Ige_undef_int :
forall i1,
ige (
Iint true i1)
Iundef
|
Ige_undef_long :
forall i1,
ige (
Ilong true i1)
Iundef
|
Ige_undef :
ige Iundef Iundef
|
Ige_bot :
forall x,
ige x Ibot.
Lemma bool_le_refl:
forall b,
Bool.le b b.
Proof.
destruct b; constructor.
Qed.
Lemma ige_refl:
forall x,
ige x x.
Proof.
Lemma bool_le_trans:
forall b1 b2 b3,
Bool.le b1 b2 ->
Bool.le b2 b3 ->
Bool.le b1 b3.
Proof.
unfold Bool.le.
intros.
destruct b1,
b2,
b3;
trivial.
Qed.
Lemma ige_trans:
forall x y z,
ige x y ->
ige y z ->
ige x z.
Proof.
Definition ilub x y :=
match x,
y with
|
Ibot,
x |
x,
Ibot =>
x
|
Iundef, (
Iint b1 i1) | (
Iint b1 i1),
Iundef =>
Iint true i1
|
Iundef,
Iundef =>
Iundef
|
Iundef, (
Ilong b1 i1) =>
Ilong true i1
| (
Ilong b1 i1),
Iundef =>
Ilong true i1
| (
Iint b1 i1), (
Iint b2 i2) =>
Iint (
orb b1 b2) (
Int_Modulus_Interval.lub i1 i2)
| (
Ilong b1 i1), (
Ilong b2 i2) =>
Ilong (
orb b1 b2) (
Int64_Modulus_Interval.lub i1 i2)
| _, _ =>
Itop
end.
Lemma orb_le1:
forall b b0,
Bool.le b (
b ||
b0).
Proof.
destruct b, b0; cbn; trivial.
Qed.
Lemma orb_le2:
forall b b0,
Bool.le b (
b0 ||
b).
Proof.
destruct b, b0; cbn; trivial.
Qed.
Lemma bool_le_true:
forall b,
Bool.le b true.
Proof.
destruct b; cbn; trivial.
Qed.
Lemma ige_lub_left :
forall x y,
ige (
ilub x y)
x.
Proof.
Lemma ige_lub_right :
forall x y,
ige (
ilub x y)
y.
Proof.
Lemma bool_le_least:
forall b1 b2 b3,
Bool.le b2 b1 ->
Bool.le b3 b1 ->
Bool.le (
b2 ||
b3)
b1.
Proof.
unfold Bool.le.
destruct b1,
b2,
b3;
cbn;
trivial.
Qed.
Lemma ilub_least:
forall r p q,
ige r p ->
ige r q ->
ige r (
ilub p q).
Proof.
Definition ieq_dec (
x y :
ival) : {
x=
y} + {
x<>
y}.
Proof.
Definition widen_down' z1 z2 :=
if Z.eq_dec z1 z2 then z1 else 0.
Definition widen_down z1 z2 :=
widen_down' z1 (
Z.min z1 z2).
Fixpoint find_first {
T:
Type} (
P :
T->
bool)
l last_resort :=
match l with
|
h::
t =>
if P h then h else find_first P t last_resort
|
nil =>
last_resort
end.
Lemma find_first_P:
forall {
T:
Type} (
P P':
T->
bool)
l last_resort
(
ALL:
List.forallb P l =
true) (
Plast:
P last_resort =
true),
P(
find_first P' l last_resort) =
true.
Proof.
induction l;
cbn. {
auto. }
intros.
rewrite andb_true_iff in ALL.
destruct ALL.
destruct (
P' a);
auto.
Qed.
Lemma find_first_P2:
forall {
T:
Type} (
P :
T->
bool)
l last_resort
(
Plast:
P last_resort =
true),
P(
find_first P l last_resort) =
true.
Proof.
induction l; cbn. { auto. } intros.
destruct (P a) eqn:DEC; auto.
Qed.
Definition find_in_ramp ramp z last_resort :=
find_first (
fun x =>
z <=?
x)
ramp last_resort.
Definition widen_up' z1 z2 (
ramp :
list Z.t)
last_resort :=
if Z.eq_dec z1 z2 then z1 else find_in_ramp ramp z2 last_resort.
Definition widen_up z1 z2 ramp last_resort :=
widen_up' z1 (
Z.max z1 z2)
ramp last_resort.
Definition int_ramp := 0 :: 1 :: 2147483646 :: 2147483647 ::
4294967294 ::
nil.
Program Definition int_widen i i0 :=
Int_Modulus_Interval.mkmod_interval
(
Interval.mkinterval
(
widen_down i.(
Int_Modulus_Interval.mod_itv).(
Interval.itv_lo)
i0.(
Int_Modulus_Interval.mod_itv).(
Interval.itv_lo))
(
widen_up i.(
Int_Modulus_Interval.mod_itv).(
Interval.itv_hi)
i0.(
Int_Modulus_Interval.mod_itv).(
Interval.itv_hi)
int_ramp
Int.max_unsigned) _)
_ _.
Next Obligation.
Next Obligation.
destruct i,
i0,
mod_itv,
mod_itv0;
cbn in *.
unfold widen_down,
widen_down'.
destruct Z.eq_dec;
lia.
Qed.
Next Obligation.
Lemma ge_int_widen_left:
forall i i0,
Int_Modulus_Interval.ge (
int_widen i i0)
i.
Proof.
Lemma ge_int_widen_right:
forall i i0,
Int_Modulus_Interval.ge (
int_widen i i0)
i0.
Proof.
Definition long_ramp := 0 :: 1 :: 2147483646 :: 2147483647 ::
4294967294 :: 4294967295 ::
9223372036854775806 :: 9223372036854775807 ::
18446744073709551614 ::
nil.
Program Definition long_widen i i0 :=
Int64_Modulus_Interval.mkmod_interval
(
Interval.mkinterval
(
widen_down i.(
Int64_Modulus_Interval.mod_itv).(
Interval.itv_lo)
i0.(
Int64_Modulus_Interval.mod_itv).(
Interval.itv_lo))
(
widen_up i.(
Int64_Modulus_Interval.mod_itv).(
Interval.itv_hi)
i0.(
Int64_Modulus_Interval.mod_itv).(
Interval.itv_hi)
long_ramp
Int64.max_unsigned) _)
_ _.
Next Obligation.
Next Obligation.
destruct i,
i0,
mod_itv,
mod_itv0;
cbn in *.
unfold widen_down,
widen_down'.
destruct Z.eq_dec;
lia.
Qed.
Next Obligation.
Lemma ge_long_widen_left:
forall i i0,
Int64_Modulus_Interval.ge (
long_widen i i0)
i.
Proof.
Lemma ge_long_widen_right:
forall i i0,
Int64_Modulus_Interval.ge (
long_widen i i0)
i0.
unfold int_widen.
destruct i,
i0,
mod_itv,
mod_itv0.
constructor;
cbn in *.
-
unfold widen_down,
widen_down'.
destruct Z.eq_dec;
lia.
-
unfold widen_up,
widen_up'.
destruct Z.eq_dec.
lia.
unfold find_in_ramp.
assert ((
fun x :
Z =>
Z.max itv_hi itv_hi0 <=?
x)
(
find_first (
fun x :
Z =>
Z.max itv_hi itv_hi0 <=?
x)
long_ramp 18446744073709551615) =
true)
as LEQ.
{
apply find_first_P2.
change Int64.modulus with 18446744073709551616
in *.
lia. }
cbn beta in LEQ.
lia.
Qed.