Require Import
Coqlib Utf8
Integers DLib
LatticeSignatures
AbEnvironment
IntervalDomain.
Set Implicit Arguments.
Ltac bot :=
repeat match goal with |-
context[
match ?
a with Bot =>
_ |
NotBot _ =>
_ end] =>
case_eq a end.
Specifications of the numerical operations on sets of concrete values.
Definition lift_unop (
op:
int →
int) (
A: ℘
int) : ℘
int :=
fun i => ∃
j,
A j ∧
i = (
op j).
Definition lift_binop (
op:
int →
int →
int) (
A B: ℘
int) : ℘
int :=
fun i => ∃
a, ∃
b,
A a ∧
B b ∧
i = (
op a b).
Signature of an abstract numerical domain.
Unset Elimination Schemes.
Class num_dom (
t:
Type) :
Type :=
{
as_adom :>
adom t int
;
meet:
t →
t+⊥ →
t+⊥
;
const:
int →
t
;
booleans:
t
;
range:
t →
sign_flag →
Interval.itv+⊥
;
neg:
t →
t+⊥
;
not:
t →
t+⊥
;
notbool:
t →
t+⊥
;
boolval:
t →
t+⊥
;
add:
t →
t →
t+⊥
;
sub:
t →
t →
t+⊥
;
mul:
t →
t →
t+⊥
;
divs:
t →
t →
t+⊥
;
shl:
t →
t →
t+⊥
;
and:
t →
t →
t+⊥
;
or:
t →
t →
t+⊥
;
xor:
t →
t →
t+⊥
;
is_in_itv:
int →
int →
t →
bool
;
backward_boolval:
t →
t →
t+⊥
;
backward_notbool:
t →
t →
t+⊥
;
backward_neg:
t →
t →
t+⊥
;
backward_not:
t →
t →
t+⊥
;
backward_add:
t →
t →
t →
t+⊥ *
t+⊥
;
backward_sub:
t →
t →
t →
t+⊥ *
t+⊥
;
backward_cmp:
comparison →
t →
t →
t →
t+⊥ *
t+⊥
;
backward_cmpu:
comparison →
t →
t →
t →
t+⊥ *
t+⊥
;
backward_and:
t →
t →
t →
list (
t+⊥ *
t+⊥)
;
backward_or:
t →
t →
t →
list (
t+⊥ *
t+⊥)
}.
Definition backward_unop_correct (
t:
Type) `{
adom t int}
(
aop:
t →
t →
t+⊥)
(
op :
int →
int) :
Prop :=
∀
x y :
t,
∀
i :
int,
γ
x i →
γ
y (
op i) →
γ (
aop x y)
i.
Definition backward_binop_correct (
t:
Type) `{
adom t int}
(
aop:
t →
t →
t →
t+⊥ *
t+⊥)
(
op :
int →
int →
int) :
Prop :=
∀
x y z :
t,
∀
i j :
int,
γ
x i →
γ
y j →
γ
z (
op i j) →
let '(
u,
v) :=
aop x y z in
γ
u i ∧ γ
v j.
Definition backward_binop_list_correct (
t:
Type) `{
adom t int}
(
aop:
t →
t →
t →
list (
t+⊥ *
t+⊥))
(
op :
int →
int →
int) :
Prop :=
∀
x y z :
t,
∀
i j :
int,
γ
x i →
γ
y j →
γ
z (
op i j) →
∃
ab,
In ab (
aop x y z) ∧
γ (
fst ab)
i ∧ γ (
snd ab)
j.
Specification of an abstract numerical domain.
Class num_dom_correct t (
D:
num_dom t) :
Prop :=
{
meet_correct: ∀
x y, (γ
x) ∩ (γ
y) ⊆ γ (
meet x y)
;
const_correct: ∀
n:
int, γ (
const n)
n
;
booleans_correct0: γ
booleans Int.zero
;
booleans_correct1: γ
booleans Int.one
;
range_correct: ∀
x:
t, γ
x ⊆
ints_in_range (
range x)
;
neg_correct: ∀
x:
t,
lift_unop Int.neg (γ
x) ⊆ γ (
neg x)
;
not_correct: ∀
x:
t,
lift_unop Int.not (γ
x) ⊆ γ (
not x)
;
notbool_correct: ∀
x:
t, ∀
i, γ
x i → γ (
notbool x) (
Interval.of_bool (
Int.eq i Int.zero))
;
boolval_correct: ∀
x:
t, ∀
i, γ
x i → γ (
boolval x) (
Interval.of_bool (
negb (
Int.eq i Int.zero)))
;
add_correct: ∀
x y:
t,
lift_binop Int.add (γ
x) (γ
y) ⊆ γ (
add x y)
;
sub_correct: ∀
x y:
t,
lift_binop Int.sub (γ
x) (γ
y) ⊆ γ (
sub x y)
;
mul_correct: ∀
x y:
t,
lift_binop Int.mul (γ
x) (γ
y) ⊆ γ (
mul x y)
;
divs_correct: ∀
x y:
t,
lift_binop Int.divs (γ
x) (γ
y) ⊆ γ (
divs x y)
;
shl_correct: ∀
x y:
t,
lift_binop Int.shl (γ
x) (γ
y) ⊆ γ (
shl x y)
;
and_correct: ∀
x y:
t,
lift_binop Int.and (γ
x) (γ
y) ⊆ γ (
and x y)
;
or_correct: ∀
x y:
t,
lift_binop Int.or (γ
x) (γ
y) ⊆ γ (
or x y)
;
xor_correct: ∀
x y:
t,
lift_binop Int.xor (γ
x) (γ
y) ⊆ γ (
xor x y)
;
is_in_itv_correct (
m M:
int) : ∀
x:
t,
is_in_itv m M x =
true →
∀
i, γ
x i →
Int.lt M i =
false ∧
Int.lt i m =
false
;
backward_boolval_correct:
backward_unop_correct (
t:=
t)
backward_boolval
(
fun i => (
Interval.of_bool (
negb (
Int.eq i Int.zero))))
;
backward_notbool_correct:
backward_unop_correct (
t:=
t)
backward_notbool
(
fun i => (
Interval.of_bool (
Int.eq i Int.zero)))
;
backward_neg_correct:
backward_unop_correct (
t:=
t)
backward_neg Int.neg
;
backward_not_correct:
backward_unop_correct (
t:=
t)
backward_not Int.not
;
backward_add_correct:
backward_binop_correct (
t:=
t)
backward_add Int.add
;
backward_sub_correct:
backward_binop_correct (
t:=
t)
backward_sub Int.sub
;
backward_cmp_correct: ∀
c,
backward_binop_correct (
t:=
t) (
backward_cmp c)
(
fun i j => (
Interval.of_bool (
Int.cmp c i j)))
;
backward_cmpu_correct: ∀
c,
backward_binop_correct (
t:=
t) (
backward_cmpu c)
(
fun i j => (
Interval.of_bool (
Int.cmpu c i j)))
;
backward_and_correct:
backward_binop_list_correct (
t:=
t)
backward_and Int.and
;
backward_or_correct:
backward_binop_list_correct (
t:=
t)
backward_or Int.or
}.
Class reduction A B :
Type := { ρ:
A+⊥ →
B+⊥ → (
A *
B)+⊥ }.
Class reduction_correct A B t (
Ha:
adom A t) (
Hb:
adom B t) `{
reduction A B} :
Prop :=
{
reduction_spec a b:
γ
a ∩ γ
b ⊆
match ρ
a b with
|
Bot => ∅
|
NotBot (
u,
v) => γ
u ∩ γ
v
end
}.
Reduced product of two abstract numerical domains.
Definition botbind {
A B} (
f:
A →
B+⊥) (
a:
A+⊥) :
B+⊥ :=
match a with
|
Bot =>
Bot
|
NotBot x =>
f x
end.
Definition red_prod_unop {
A B} ρ (
opa:
A →
A+⊥) (
opb:
B →
B+⊥) :
A*
B → (
A*
B)+⊥ :=
fun x =>
match x with (
a,
b) => ρ (
opa a) (
opb b)
end.
Definition botbind2 {
A B C} (
f:
A →
B →
C+⊥) (
a:
A+⊥) (
b:
B+⊥) :
C+⊥ :=
match a,
b with
|
Bot,
_
|
_,
Bot =>
Bot
|
NotBot x,
NotBot y =>
f x y
end.
Definition red_prod_binop {
A B} ρ (
opa:
A →
A →
A+⊥) (
opb:
B →
B →
B+⊥)
: (
A*
B) → (
A*
B) → (
A*
B)+⊥ :=
fun x y =>
match x,
y with (
a,
b), (
c,
d) =>
ρ (
opa a c) (
opb b d)
end.
Definition red_prod_backop_bin {
A B} ρ (
opa:
A →
A →
A →
A+⊥ *
A+⊥) (
opb:
B →
B →
B →
B+⊥ *
B+⊥)
: (
A*
B) → (
A*
B) → (
A*
B) → (
A*
B)+⊥ * (
A*
B)+⊥ :=
fun x y z =>
match x,
y,
z with
| (
a,
b), (
c,
d), (
e,
f) =>
let '(
a',
c') :=
opa a c e in
let '(
b',
d') :=
opb b d f in
(ρ
a'
b', ρ
c'
d')
end.
Definition red_prod_backop_bin_list {
A B} ρ
(
opa:
A →
A →
A →
list (
A+⊥ *
A+⊥)) (
opb:
B →
B →
B →
list (
B+⊥ *
B+⊥))
: (
A*
B) → (
A*
B) → (
A*
B) →
list ((
A*
B)+⊥ * (
A*
B)+⊥) :=
fun x y z =>
match x,
y,
z with
| (
a,
b), (
c,
d), (
e,
f) =>
let l1 :=
opa a c e in
match opb b d f with
| (
b',
d') ::
nil =>
map (
fun ab:(
A+⊥ *
A+⊥) =>
let (
a',
c') :=
ab in
(ρ
a'
b', ρ
c'
d'))
l1
|
_ => (
NotBot x,
NotBot y) ::
nil
end
end.
Definition red_prod_backop_un {
A B} ρ (
opa:
A →
A →
A+⊥) (
opb:
B →
B →
B+⊥)
: (
A*
B) → (
A*
B) → (
A*
B)+⊥ :=
fun x y =>
match x,
y with
| (
a,
b), (
c,
d) =>
let a' :=
opa a c in
let b' :=
opb b d in
(ρ
a'
b')
end.
Definition pair_of_prod {
A B} (
x: (
A*
B)+⊥) :
A+⊥ *
B+⊥ :=
match x with
|
NotBot (
a,
b) => (
NotBot a,
NotBot b)
|
Bot => (
Bot,
Bot)
end.
Instance reduced_product_num_dom A B `{
Da:
num_dom A} `{
Db:
num_dom B}
(Ρ:
reduction A B)
:
num_dom (
A*
B) :=
{|
as_adom :=
WProd.make _ _
;
meet x :=
botbind (
fun y => ρ (
meet (
fst x) (
NotBot (
fst y))) (
meet (
snd x) (
NotBot (
snd y))))
;
const n := (
const n,
const n)
;
booleans := (
booleans,
booleans)
;
range x s :=
Interval.meet' (
range (
fst x)
s) (
range (
snd x)
s)
;
neg :=
red_prod_unop ρ
neg neg
;
not :=
red_prod_unop ρ
not not
;
notbool :=
red_prod_unop ρ
notbool notbool
;
boolval :=
red_prod_unop ρ
boolval boolval
;
add :=
red_prod_binop ρ
add add
;
sub :=
red_prod_binop ρ
sub sub
;
mul :=
red_prod_binop ρ
mul mul
;
divs :=
red_prod_binop ρ
divs divs
;
shl :=
red_prod_binop ρ
shl shl
;
and :=
red_prod_binop ρ
and and
;
or :=
red_prod_binop ρ
or or
;
xor :=
red_prod_binop ρ
xor xor
;
is_in_itv m M x :=
let '(
a,
b) :=
x in is_in_itv m M a ||
is_in_itv m M b
;
backward_boolval :=
red_prod_backop_un ρ
backward_boolval backward_boolval
;
backward_notbool :=
red_prod_backop_un ρ
backward_notbool backward_notbool
;
backward_neg :=
red_prod_backop_un ρ
backward_neg backward_neg
;
backward_not :=
red_prod_backop_un ρ
backward_not backward_not
;
backward_add :=
red_prod_backop_bin ρ
backward_add backward_add
;
backward_sub :=
red_prod_backop_bin ρ
backward_sub backward_sub
;
backward_cmp := (
fun c =>
red_prod_backop_bin ρ (
backward_cmp c) (
backward_cmp c))
;
backward_cmpu := (
fun c =>
red_prod_backop_bin ρ (
backward_cmpu c) (
backward_cmpu c))
;
backward_and :=
red_prod_backop_bin_list ρ
backward_and backward_and
;
backward_or :=
red_prod_backop_bin_list ρ
backward_or backward_or
|}.
This reducted product yields a correct abstract numerical domain.
Instance reduced_product_num_dom_correct A B `{
Da:
num_dom A} `{
Db:
num_dom B}
(
Das:
num_dom_correct Da) (
Dbs:
num_dom_correct Db)
(Ρ:
reduction A B) (Ρ
s:
reduction_correct (@
as_adom _ Da) (@
as_adom _ Db))
:
num_dom_correct (
reduced_product_num_dom A B Ρ).
Proof.
split.
intros (
a,
b) [|(
c,
d)].
intuition.
intros i [(
L&
R) (
L'&
R')].
simpl.
apply reduction_spec.
intuition auto using @
meet_correct.
simpl.
intuition auto using @
const_correct.
split;
eapply booleans_correct0.
split;
eapply booleans_correct1.
intros (
a,
b)
i (
L&
R).
unfold ints_in_range.
simpl.
split.
apply Interval.meet'
_correct;
apply range_correct;
auto.
exploit range_correct.
eapply L.
unfold ints_in_range.
intros.
unfold Interval.meet'.
destruct (
range a Unsigned);
intros;
autorw'.
intuition.
apply Interval.meet_correctu.
split. 2:
apply range_correct;
auto.
intuition.
intros (
a,
b)
i (
j & (
R&
L) & ->).
simpl.
apply reduction_spec;
split;
apply neg_correct;
eexists;
split;
eauto.
intros (
a,
b)
i (
j & (
R&
L) & ->).
simpl.
apply reduction_spec;
split;
apply not_correct;
eexists;
split;
eauto.
intros (
a,
b)
i (
L&
R).
simpl.
apply reduction_spec.
split;
apply notbool_correct;
auto.
intros (
a,
b)
i (
L&
R).
simpl.
apply reduction_spec.
split;
apply boolval_correct;
auto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply add_correct;
eexists;
eexists;
intuition;
eauto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply sub_correct;
eexists;
eexists;
intuition;
eauto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply mul_correct;
eexists;
eexists;
intuition;
eauto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply divs_correct;
eexists;
eexists;
intuition;
eauto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply shl_correct;
eexists;
eexists;
intuition;
eauto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply and_correct;
eexists;
eexists;
intuition;
eauto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply or_correct;
eexists;
eexists;
intuition;
eauto.
intros (
a,
b) (
c,
d)
i (
j &
k & (?&?) & (?&?) &->).
simpl.
apply reduction_spec;
split;
apply xor_correct;
eexists;
eexists;
intuition;
eauto.
intros m M (
a,
b).
simpl.
rewrite orb_true_iff.
destruct 1;
intros i (
U&
V).
eapply is_in_itv_correct;
eauto.
apply is_in_itv_correct with b;
eauto.
intros (
a,
b)(
c,
d)
i (?&?)(?&?).
simpl.
apply reduction_spec;
split;
apply backward_boolval_correct;
auto.
intros (
a,
b)(
c,
d)
i (?&?)(?&?).
simpl.
apply reduction_spec;
split;
apply backward_notbool_correct;
auto.
intros (
a,
b)(
c,
d)
i (?&?)(?&?).
simpl.
apply reduction_spec;
split;
apply backward_neg_correct;
auto.
intros (
a,
b)(
c,
d)
i (?&?)(?&?).
simpl.
apply reduction_spec;
split;
apply backward_not_correct;
auto.
intros (
a,
b)(
c,
d)(
e,
f)
i j (?&?)(?&?)(?&?).
pairs.
simpl.
pairs.
intros L R ?.
inj.
generalize (
backward_add_correct a c e i j).
generalize (
backward_add_correct b d f i j).
autorw'.
split;
apply reduction_spec;
intuition.
intros (
a,
b)(
c,
d)(
e,
f)
i j (?&?)(?&?)(?&?).
pairs.
simpl.
pairs.
intros L R ?.
inj.
generalize (
backward_sub_correct a c e i j).
generalize (
backward_sub_correct b d f i j).
autorw'.
split;
apply reduction_spec;
intuition.
intros X (
a,
b)(
c,
d)(
e,
f)
i j (?&?)(?&?)(?&?).
pairs.
simpl.
pairs.
intros L R ?.
inj.
generalize (
backward_cmp_correct X a c e i j).
generalize (
backward_cmp_correct X b d f i j).
autorw'.
split;
apply reduction_spec;
intuition.
intros X (
a,
b)(
c,
d)(
e,
f)
i j (?&?)(?&?)(?&?).
pairs.
simpl.
pairs.
intros L R ?.
inj.
generalize (
backward_cmpu_correct X a c e i j).
generalize (
backward_cmpu_correct X b d f i j).
autorw'.
split;
apply reduction_spec;
intuition.
intros (
a,
b)(
c,
d)(
e,
f)
i j (?&?)(?&?)(?&?).
generalize (
backward_and_correct a c e i j).
generalize (
backward_and_correct b d f i j).
intros ();
auto.
intros (
r1&
r2) (
U&?&?).
intros ();
auto.
intros (
l1&
l2) (
V&?&?).
unfold backward_and,
reduced_product_num_dom,
red_prod_backop_bin_list.
case_eq (
backward_and b d f).
intros ?.
autorw'.
intuition.
intros (?,?)
l ?.
autorw'.
destruct l.
inv U.
inj.
set (
q :=
fun ab =>
let '(
a,
c) :=
ab in (ρ
a r1, ρ
c r2)).
exists (
q (
l1,
l2)).
split.
2:
simpl;
split;
eapply reduction_spec;
intuition.
apply in_map.
auto.
intuition.
eexists.
split.
left.
reflexivity.
simpl.
intuition.
intros (
a,
b)(
c,
d)(
e,
f)
i j (?&?)(?&?)(?&?).
generalize (
backward_or_correct a c e i j).
generalize (
backward_or_correct b d f i j).
intros ();
auto.
intros (
r1&
r2) (
U&?&?).
intros ();
auto.
intros (
l1&
l2) (
V&?&?).
unfold backward_or,
reduced_product_num_dom,
red_prod_backop_bin_list.
case_eq (
backward_or b d f).
intros ?.
autorw'.
intuition.
intros (?,?)
l ?.
autorw'.
destruct l.
inv U.
inj.
set (
q :=
fun ab =>
let '(
a,
c) :=
ab in (ρ
a r1, ρ
c r2)).
exists (
q (
l1,
l2)).
split.
2:
simpl;
split;
eapply reduction_spec;
intuition.
apply in_map.
auto.
intuition.
eexists.
split.
left.
reflexivity.
simpl.
intuition.
Qed.