diff options
Diffstat (limited to 'src/Compilers/Z/Bounds/InterpretationLemmas/IsBoundedBy.v')
-rw-r--r-- | src/Compilers/Z/Bounds/InterpretationLemmas/IsBoundedBy.v | 179 |
1 files changed, 171 insertions, 8 deletions
diff --git a/src/Compilers/Z/Bounds/InterpretationLemmas/IsBoundedBy.v b/src/Compilers/Z/Bounds/InterpretationLemmas/IsBoundedBy.v index 415c65406..c74c319d5 100644 --- a/src/Compilers/Z/Bounds/InterpretationLemmas/IsBoundedBy.v +++ b/src/Compilers/Z/Bounds/InterpretationLemmas/IsBoundedBy.v @@ -35,6 +35,65 @@ Proof. | word_arith_t ]. Qed. +Lemma is_bounded_by_compose T1 T2 f_v bs v f_bs fv + (H : Bounds.is_bounded_by (T:=Tbase T1) bs v) + (Hf : forall bs v, Bounds.is_bounded_by (T:=Tbase T1) bs v -> Bounds.is_bounded_by (T:=Tbase T2) (f_bs bs) (f_v v)) + (Hfv : f_v v = fv) + : Bounds.is_bounded_by (T:=Tbase T2) (f_bs bs) fv. +Proof. + subst; eauto. +Qed. + +Lemma monotone_two_corners_genb + (f : Z -> Z) + (R := fun b : bool => if b then Z.le else Basics.flip Z.le) + (Hmonotone : exists b, Proper (R b ==> Z.le) f) + x_bs x + (Hboundedx : ZRange.is_bounded_by' None x_bs x) + : ZRange.is_bounded_by' None (Bounds.two_corners f x_bs) (f x). +Proof. + unfold ZRange.is_bounded_by' in *; split; trivial. + destruct x_bs as [lx ux]; simpl in *. + destruct Hboundedx as [Hboundedx _]. + destruct_head'_ex. + repeat match goal with + | [ H : Proper (R ?b ==> Z.le) f |- _ ] + => unique assert (R b (if b then lx else x) (if b then x else lx) + /\ R b (if b then x else ux) (if b then ux else x)) + by (unfold R, Basics.flip; destruct b; omega) + end. + destruct_head' and. + repeat match goal with + | [ H : Proper (R ?b ==> Z.le) _, H' : R ?b _ _ |- _ ] + => unique pose proof (H _ _ H') + end. + destruct_head bool; split_min_max; omega. +Qed. + +Lemma monotone_two_corners_gen + (f : Z -> Z) + (Hmonotone : Proper (Z.le ==> Z.le) f \/ Proper (Basics.flip Z.le ==> Z.le) f) + x_bs x + (Hboundedx : ZRange.is_bounded_by' None x_bs x) + : ZRange.is_bounded_by' None (Bounds.two_corners f x_bs) (f x). +Proof. + eapply monotone_two_corners_genb; auto. + destruct Hmonotone; [ exists true | exists false ]; assumption. +Qed. +Lemma monotone_two_corners + (b : bool) + (f : Z -> Z) + (R := if b then Z.le else Basics.flip Z.le) + (Hmonotone : Proper (R ==> Z.le) f) + x_bs x + (Hboundedx : ZRange.is_bounded_by' None x_bs x) + : ZRange.is_bounded_by' None (Bounds.two_corners f x_bs) (f x). +Proof. + apply monotone_two_corners_genb; auto; subst R; + exists b. + intros ???; apply Hmonotone; auto. +Qed. + Lemma monotone_four_corners_genb (f : Z -> Z -> Z) (R := fun b : bool => if b then Z.le else Basics.flip Z.le) @@ -45,11 +104,19 @@ Lemma monotone_four_corners_genb (Hboundedy : ZRange.is_bounded_by' None y_bs y) : ZRange.is_bounded_by' None (Bounds.four_corners f x_bs y_bs) (f x y). Proof. - unfold ZRange.is_bounded_by' in *; split; trivial. - destruct x_bs as [lx ux], y_bs as [ly uy]; simpl in *. - destruct Hboundedx as [Hboundedx _], Hboundedy as [Hboundedy _]. - pose proof (Hmonotone1 lx); pose proof (Hmonotone1 x); pose proof (Hmonotone1 ux). - pose proof (Hmonotone2 ly); pose proof (Hmonotone2 y); pose proof (Hmonotone2 uy). + destruct x_bs as [lx ux], y_bs as [ly uy]. + unfold Bounds.four_corners. + pose proof (monotone_two_corners_genb (f lx) (Hmonotone1 _) _ _ Hboundedy) as Hmono_fl. + pose proof (monotone_two_corners_genb (f ux) (Hmonotone1 _) _ _ Hboundedy) as Hmono_fu. + repeat match goal with + | [ |- context[Bounds.two_corners ?x ?y] ] + => let l := fresh "lf" in + let u := fresh "uf" in + generalize dependent (Bounds.two_corners x y); intros [l u]; intros + end. + unfold ZRange.is_bounded_by' in *; simpl in *; split; trivial. + destruct_head'_and; destruct_head' True. + pose proof (Hmonotone2 y). destruct_head'_ex. repeat match goal with | [ H : Proper (R ?b ==> Z.le) (f _) |- _ ] @@ -65,7 +132,7 @@ Proof. repeat match goal with | [ H : Proper (R ?b ==> Z.le) _, H' : R ?b _ _ |- _ ] => unique pose proof (H _ _ H') - end. + end; cbv beta in *. destruct_head bool; split_min_max; omega. Qed. @@ -98,6 +165,88 @@ Proof. | intros ???; apply Hmonotone; auto; destruct b2; reflexivity ]. Qed. +Lemma monotone_eight_corners_genb + (f : Z -> Z -> Z -> Z) + (R := fun b : bool => if b then Z.le else Basics.flip Z.le) + (Hmonotone1 : forall x y, exists b, Proper (R b ==> Z.le) (f x y)) + (Hmonotone2 : forall x z, exists b, Proper (R b ==> Z.le) (fun y => f x y z)) + (Hmonotone3 : forall y z, exists b, Proper (R b ==> Z.le) (fun x => f x y z)) + x_bs y_bs z_bs x y z + (Hboundedx : ZRange.is_bounded_by' None x_bs x) + (Hboundedy : ZRange.is_bounded_by' None y_bs y) + (Hboundedz : ZRange.is_bounded_by' None z_bs z) + : ZRange.is_bounded_by' None (Bounds.eight_corners f x_bs y_bs z_bs) (f x y z). +Proof. + destruct x_bs as [lx ux], y_bs as [ly uy], z_bs as [lz uz]. + unfold Bounds.eight_corners. + pose proof (monotone_four_corners_genb (f lx) (Hmonotone1 _) (Hmonotone2 _) _ _ _ _ Hboundedy Hboundedz) as Hmono_fl. + pose proof (monotone_four_corners_genb (f ux) (Hmonotone1 _) (Hmonotone2 _) _ _ _ _ Hboundedy Hboundedz) as Hmono_fu. + repeat match goal with + | [ |- context[Bounds.four_corners ?x ?y ?z] ] + => let l := fresh "lf" in + let u := fresh "uf" in + generalize dependent (Bounds.four_corners x y z); intros [l u]; intros + end. + unfold ZRange.is_bounded_by' in *; simpl in *; split; trivial. + destruct_head'_and; destruct_head' True. + pose proof (Hmonotone3 y z). + destruct_head'_ex. + repeat match goal with + | [ H : Proper (R ?b ==> Z.le) (f _ _) |- _ ] + => unique assert (R b (if b then lz else z) (if b then z else lz) + /\ R b (if b then z else uz) (if b then uz else z)) + by (unfold R, Basics.flip; destruct b; omega) + | [ H : Proper (R ?b ==> Z.le) (fun y' => f _ y' _) |- _ ] + => unique assert (R b (if b then ly else y) (if b then y else ly) + /\ R b (if b then y else uy) (if b then uy else y)) + by (unfold R, Basics.flip; destruct b; omega) + | [ H : Proper (R ?b ==> Z.le) (fun x' => f x' _ _) |- _ ] + => unique assert (R b (if b then lx else x) (if b then x else lx) + /\ R b (if b then x else ux) (if b then ux else x)) + by (unfold R, Basics.flip; destruct b; omega) + end. + destruct_head' and. + repeat match goal with + | [ H : Proper (R ?b ==> Z.le) _, H' : R ?b _ _ |- _ ] + => unique pose proof (H _ _ H') + end. + destruct_head bool; split_min_max; omega. +Qed. + +Lemma monotone_eight_corners_gen + (f : Z -> Z -> Z -> Z) + (Hmonotone1 : forall x y, Proper (Z.le ==> Z.le) (f x y) \/ Proper (Basics.flip Z.le ==> Z.le) (f x y)) + (Hmonotone2 : forall x z, Proper (Z.le ==> Z.le) (fun y => f x y z) \/ Proper (Basics.flip Z.le ==> Z.le) (fun y => f x y z)) + (Hmonotone3 : forall y z, Proper (Z.le ==> Z.le) (fun x => f x y z) \/ Proper (Basics.flip Z.le ==> Z.le) (fun x => f x y z)) + x_bs y_bs z_bs x y z + (Hboundedx : ZRange.is_bounded_by' None x_bs x) + (Hboundedy : ZRange.is_bounded_by' None y_bs y) + (Hboundedz : ZRange.is_bounded_by' None z_bs z) + : ZRange.is_bounded_by' None (Bounds.eight_corners f x_bs y_bs z_bs) (f x y z). +Proof. + eapply monotone_eight_corners_genb; auto. + { intros x' y'; destruct (Hmonotone1 x' y'); [ exists true | exists false ]; assumption. } + { intros x' y'; destruct (Hmonotone2 x' y'); [ exists true | exists false ]; assumption. } + { intros x' y'; destruct (Hmonotone3 x' y'); [ exists true | exists false ]; assumption. } +Qed. +Lemma monotone_eight_corners + (b1 b2 b3 : bool) + (f : Z -> Z -> Z -> Z) + (R1 := if b1 then Z.le else Basics.flip Z.le) + (R2 := if b2 then Z.le else Basics.flip Z.le) + (R3 := if b3 then Z.le else Basics.flip Z.le) + (Hmonotone : Proper (R1 ==> R2 ==> R3 ==> Z.le) f) + x_bs y_bs z_bs x y z + (Hboundedx : ZRange.is_bounded_by' None x_bs x) + (Hboundedy : ZRange.is_bounded_by' None y_bs y) + (Hboundedz : ZRange.is_bounded_by' None z_bs z) + : ZRange.is_bounded_by' None (Bounds.eight_corners f x_bs y_bs z_bs) (f x y z). +Proof. + apply monotone_eight_corners_genb; auto; intro x'; subst R1 R2 R3; + [ exists b3 | exists b2 | exists b1 ]; + intros ???; apply Hmonotone; break_innermost_match; try reflexivity; trivial. +Qed. + Lemma monotonify2 (f : Z -> Z -> Z) (upper : Z -> Z -> Z) (Hbounded : forall a b, Z.abs (f a b) <= upper (Z.abs a) (Z.abs b)) (Hupper_monotone : Proper (Z.le ==> Z.le ==> Z.le) upper) @@ -173,7 +322,7 @@ Qed. Local Arguments N.ldiff : simpl never. Local Arguments Z.pow : simpl never. Local Arguments Z.add !_ !_. -Local Existing Instances Z.add_le_Proper Z.sub_le_flip_le_Proper Z.log2_up_le_Proper Z.pow_Zpos_le_Proper Z.sub_le_eq_Proper. +Local Existing Instances Z.add_le_Proper Z.sub_le_flip_le_Proper Z.log2_up_le_Proper Z.pow_Zpos_le_Proper Z.sub_le_eq_Proper Z.add_with_carry_le_Proper. Local Hint Extern 1 => progress cbv beta iota : typeclass_instances. Lemma is_bounded_by_interp_op t tR (opc : op t tR) (bs : interp_flat_type Bounds.interp_base_type _) @@ -181,7 +330,14 @@ Lemma is_bounded_by_interp_op t tR (opc : op t tR) (H : Bounds.is_bounded_by bs v) : Bounds.is_bounded_by (Bounds.interp_op opc bs) (Syntax.interp_op _ _ opc v). Proof. - destruct opc; apply is_bounded_by_truncation_bounds; + destruct opc; + [ apply is_bounded_by_truncation_bounds.. + | split; + cbv [Bounds.interp_op Zinterp_op Z.add_with_get_carry SmartFlatTypeMapUnInterp Bounds.add_with_get_carry Z.get_carry cast_const]; cbn [fst snd]; + [ eapply is_bounded_by_compose with (T1:=TZ) (f_v := fun v => ZToInterp (v mod _)) (v:=ZToInterp _); + [ | intros; apply is_bounded_by_truncation_bounds | simpl; reflexivity ] + | eapply is_bounded_by_compose with (T1:=TZ) (f_v := fun v => ZToInterp (v / _)) (v:=ZToInterp _); + [ | intros; apply is_bounded_by_truncation_bounds | simpl; reflexivity ] ] ]; repeat first [ progress simpl in * | progress cbv [interp_op lift_op cast_const Bounds.interp_base_type Bounds.is_bounded_by' ZRange.is_bounded_by'] in * | progress destruct_head'_prod @@ -225,4 +381,11 @@ Proof. | progress simpl in * | progress split_min_max | omega ]. } + { destruct_head Bounds.t; cbv [Bounds.zselect' Z.zselect]. + break_innermost_match; split_min_max; omega. } + { apply (@monotone_eight_corners true true true _ _ _); split; auto. } + { apply (@monotone_eight_corners true true true _ _ _); split; auto. } + { apply Z.mod_bound_min_max; auto. } + { apply (@monotone_eight_corners true true true _ _ _); split; auto. } + { auto with zarith. } Qed. |