aboutsummaryrefslogtreecommitdiff
path: root/src/Reflection/Z
diff options
context:
space:
mode:
Diffstat (limited to 'src/Reflection/Z')
-rw-r--r--src/Reflection/Z/BoundsInterpretations.v25
-rw-r--r--src/Reflection/Z/CNotations.v42
-rw-r--r--src/Reflection/Z/Interpretations128/Relations.v11
-rw-r--r--src/Reflection/Z/Interpretations128/RelationsCombinations.v375
-rw-r--r--src/Reflection/Z/Interpretations64/Relations.v10
-rw-r--r--src/Reflection/Z/Interpretations64/RelationsCombinations.v375
-rw-r--r--src/Reflection/Z/InterpretationsGen.v183
-rw-r--r--src/Reflection/Z/JavaNotations.v42
-rw-r--r--src/Reflection/Z/OpInversion.v4
-rw-r--r--src/Reflection/Z/Reify.v31
-rw-r--r--src/Reflection/Z/Syntax.v46
-rw-r--r--src/Reflection/Z/Syntax/Equality.v127
-rw-r--r--src/Reflection/Z/Syntax/Util.v77
13 files changed, 656 insertions, 692 deletions
diff --git a/src/Reflection/Z/BoundsInterpretations.v b/src/Reflection/Z/BoundsInterpretations.v
index 8da4ef39f..722ee40ec 100644
--- a/src/Reflection/Z/BoundsInterpretations.v
+++ b/src/Reflection/Z/BoundsInterpretations.v
@@ -123,17 +123,18 @@ Module Import Bounds.
Definition interp_op {src dst} (f : op src dst) : interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst
:= match f in op src dst return interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst with
- | OpConst v => fun _ => SmartBuildBounds None v v
- | Add => fun xy => add (bit_width_of_base_type TZ) (fst xy) (snd xy)
- | Sub => fun xy => sub (bit_width_of_base_type TZ) (fst xy) (snd xy)
- | Mul => fun xy => mul (bit_width_of_base_type TZ) (fst xy) (snd xy)
- | Shl => fun xy => shl (bit_width_of_base_type TZ) (fst xy) (snd xy)
- | Shr => fun xy => shr (bit_width_of_base_type TZ) (fst xy) (snd xy)
- | Land => fun xy => land (bit_width_of_base_type TZ) (fst xy) (snd xy)
- | Lor => fun xy => lor (bit_width_of_base_type TZ) (fst xy) (snd xy)
- | Neg int_width => fun x => neg (bit_width_of_base_type TZ) int_width x
- | Cmovne => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne (bit_width_of_base_type TZ) x y z w
- | Cmovle => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle (bit_width_of_base_type TZ) x y z w
+ | OpConst TZ v => fun _ => SmartBuildBounds None v v
+ | Add T => fun xy => add (bit_width_of_base_type T) (fst xy) (snd xy)
+ | Sub T => fun xy => sub (bit_width_of_base_type T) (fst xy) (snd xy)
+ | Mul T => fun xy => mul (bit_width_of_base_type T) (fst xy) (snd xy)
+ | Shl T => fun xy => shl (bit_width_of_base_type T) (fst xy) (snd xy)
+ | Shr T => fun xy => shr (bit_width_of_base_type T) (fst xy) (snd xy)
+ | Land T => fun xy => land (bit_width_of_base_type T) (fst xy) (snd xy)
+ | Lor T => fun xy => lor (bit_width_of_base_type T) (fst xy) (snd xy)
+ | Neg T int_width => fun x => neg (bit_width_of_base_type T) int_width x
+ | Cmovne T => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne (bit_width_of_base_type T) x y z w
+ | Cmovle T => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle (bit_width_of_base_type T) x y z w
+ | Cast _ T => fun x => SmartRebuildBounds (bit_width_of_base_type T) x
end%bounds.
Ltac inversion_bounds :=
@@ -163,12 +164,10 @@ Module Import Bounds.
| Some b' => bounds_to_base_type' b'
end.
- (*
Definition ComputeBounds {t} (e : Expr base_type op t)
(input_bounds : interp_flat_type interp_base_type (domain t))
: interp_flat_type interp_base_type (codomain t)
:= Interp (@interp_op) e input_bounds.
- *)
Definition bound_is_goodb : forall t, interp_base_type t -> bool
:= fun t bs
diff --git a/src/Reflection/Z/CNotations.v b/src/Reflection/Z/CNotations.v
index 764094c99..bfd173094 100644
--- a/src/Reflection/Z/CNotations.v
+++ b/src/Reflection/Z/CNotations.v
@@ -44,18 +44,18 @@ Notation "'(uint32_t)' x" := (Op (Cast _ (TWord 5)) (Var x)).
Notation "'(uint64_t)' x" := (Op (Cast _ (TWord 6)) (Var x)).
Notation "'(uint128_t)' x" := (Op (Cast _ (TWord 7)) (Var x)).
*)
-Notation "x + y" := (Op (Add) (Pair x y)).
-Notation "x + y" := (Op (Add) (Pair (Var x) y)).
-Notation "x + y" := (Op (Add) (Pair x (Var y))).
-Notation "x + y" := (Op (Add) (Pair (Var x) (Var y))).
-Notation "x - y" := (Op (Sub) (Pair x y)).
-Notation "x - y" := (Op (Sub) (Pair (Var x) y)).
-Notation "x - y" := (Op (Sub) (Pair x (Var y))).
-Notation "x - y" := (Op (Sub) (Pair (Var x) (Var y))).
-Notation "x * y" := (Op (Mul) (Pair x y)).
-Notation "x * y" := (Op (Mul) (Pair (Var x) y)).
-Notation "x * y" := (Op (Mul) (Pair x (Var y))).
-Notation "x * y" := (Op (Mul) (Pair (Var x) (Var y))).
+Notation "x + y" := (Op (Add _) (Pair x y)).
+Notation "x + y" := (Op (Add _) (Pair (Var x) y)).
+Notation "x + y" := (Op (Add _) (Pair x (Var y))).
+Notation "x + y" := (Op (Add _) (Pair (Var x) (Var y))).
+Notation "x - y" := (Op (Sub _) (Pair x y)).
+Notation "x - y" := (Op (Sub _) (Pair (Var x) y)).
+Notation "x - y" := (Op (Sub _) (Pair x (Var y))).
+Notation "x - y" := (Op (Sub _) (Pair (Var x) (Var y))).
+Notation "x * y" := (Op (Mul _) (Pair x y)).
+Notation "x * y" := (Op (Mul _) (Pair (Var x) y)).
+Notation "x * y" := (Op (Mul _) (Pair x (Var y))).
+Notation "x * y" := (Op (Mul _) (Pair (Var x) (Var y))).
(* python:
<<
for opn, op in (('*', 'Mul'), ('+', 'Add'), ('&', 'Land')):
@@ -119,20 +119,18 @@ Notation "x + y" := (Op (Add (TWord 7)) (Pair x (Op (Cast _ (TWord 7)) (Var y)))
Notation "x + y" := (Op (Add (TWord 7)) (Pair (Var x) (Op (Cast _ (TWord 7)) y))).
Notation "x + y" := (Op (Add (TWord 7)) (Pair (Var x) (Op (Cast _ (TWord 7)) (Var y)))).
*)
-Notation "x >> y" := (Op (Shr) (Pair x y)).
-Notation "x >> y" := (Op (Shr) (Pair (Var x) y)).
-Notation "x >> y" := (Op (Shr) (Pair x (Var y))).
-Notation "x >> y" := (Op (Shr) (Pair (Var x) (Var y))).
-(*
+Notation "x >> y" := (Op (Shr _) (Pair x y)).
+Notation "x >> y" := (Op (Shr _) (Pair (Var x) y)).
+Notation "x >> y" := (Op (Shr _) (Pair x (Var y))).
+Notation "x >> y" := (Op (Shr _) (Pair (Var x) (Var y))).
Notation "x >> y" := (Op (Shr _) (Pair x (Op (Cast _ _) y))).
Notation "x >> y" := (Op (Shr _) (Pair (Var x) (Op (Cast _ _) y))).
Notation "x >> y" := (Op (Shr _) (Pair x (Op (Cast _ _) (Var y)))).
Notation "x >> y" := (Op (Shr _) (Pair (Var x) (Op (Cast _ _) (Var y)))).
-*)
-Notation "x & y" := (Op (Land) (Pair x y)).
-Notation "x & y" := (Op (Land) (Pair (Var x) y)).
-Notation "x & y" := (Op (Land) (Pair x (Var y))).
-Notation "x & y" := (Op (Land) (Pair (Var x) (Var y))).
+Notation "x & y" := (Op (Land _) (Pair x y)).
+Notation "x & y" := (Op (Land _) (Pair (Var x) y)).
+Notation "x & y" := (Op (Land _) (Pair x (Var y))).
+Notation "x & y" := (Op (Land _) (Pair (Var x) (Var y))).
(*
Notation "x & y" := (Op (Land (TWord 5)) (Pair (Op (Cast _ (TWord 5)) x) y)).
Notation "x & y" := (Op (Land (TWord 5)) (Pair (Op (Cast _ (TWord 5)) x) (Var y))).
diff --git a/src/Reflection/Z/Interpretations128/Relations.v b/src/Reflection/Z/Interpretations128/Relations.v
index 7f6f67fa2..8ea7de125 100644
--- a/src/Reflection/Z/Interpretations128/Relations.v
+++ b/src/Reflection/Z/Interpretations128/Relations.v
@@ -340,11 +340,12 @@ Local Ltac unfold_related_const :=
Lemma related_wordW_op : related_op related_wordW (@BoundedWordW.interp_op) (@WordW.interp_op).
Proof.
- (let op := fresh in intros ?? op; destruct op; simpl);
+ (let op := fresh in intros ?? op; destruct op; simpl); destruct_head' base_type;
try first [ apply related_wordW_t_map1
| apply related_wordW_t_map2
| apply related_wordW_t_map4
- | unfold_related_const; break_innermost_match; reflexivity ].
+ | unfold_related_const; break_innermost_match; reflexivity
+ | exact (fun _ _ x => x) ].
Qed.
Lemma related_bounds_t_map1 opW opB pf
@@ -411,7 +412,7 @@ Local Ltac related_const_op_t :=
Lemma related_bounds_op : related_op related_bounds (@BoundedWordW.interp_op) (@ZBounds.interp_op).
Proof.
- let op := fresh in intros ?? op; destruct op; simpl.
+ let op := fresh in intros ?? op; destruct op; simpl; destruct_head' base_type.
{ related_const_op_t. }
{ apply related_bounds_t_map2; intros; destruct_head' option; reflexivity. }
{ apply related_bounds_t_map2; intros; destruct_head' option; reflexivity. }
@@ -423,6 +424,7 @@ Proof.
{ apply related_bounds_t_map1; intros; destruct_head' option; unfold ZBounds.neg; break_match; reflexivity. }
{ apply related_bounds_t_map4; intros; destruct_head' option; reflexivity. }
{ apply related_bounds_t_map4; intros; destruct_head' option; reflexivity. }
+ { exact (fun _ _ x => x). }
Qed.
Local Ltac WordW.Rewrites.wordW_util_arith ::=
@@ -541,7 +543,7 @@ Local Arguments ZBounds.neg _ !_ / .
Lemma related_Z_op : related_op related_Z (@BoundedWordW.interp_op) (@Z.interp_op).
Proof.
- let op := fresh in intros ?? op; destruct op; simpl.
+ let op := fresh in intros ?? op; destruct op; simpl; destruct_head' base_type.
{ related_const_op_t. }
{ apply related_Z_t_map2; related_Z_op_fin_t. }
{ apply related_Z_t_map2; related_Z_op_fin_t. }
@@ -553,6 +555,7 @@ Proof.
{ apply related_Z_t_map1; related_Z_op_fin_t. }
{ apply related_Z_t_map4; related_Z_op_fin_t. }
{ apply related_Z_t_map4; related_Z_op_fin_t. }
+ { exact (fun _ _ x => x). }
Qed.
Create HintDb interp_related discriminated.
diff --git a/src/Reflection/Z/Interpretations128/RelationsCombinations.v b/src/Reflection/Z/Interpretations128/RelationsCombinations.v
index 68fca675e..6e7eb2865 100644
--- a/src/Reflection/Z/Interpretations128/RelationsCombinations.v
+++ b/src/Reflection/Z/Interpretations128/RelationsCombinations.v
@@ -1,9 +1,9 @@
Require Import Coq.ZArith.ZArith.
+Require Import Coq.Classes.RelationClasses.
Require Import Crypto.Reflection.Z.Syntax.
Require Import Crypto.Reflection.Syntax.
Require Import Crypto.Reflection.SmartMap.
Require Import Crypto.Reflection.Relations.
-Require Import Crypto.Reflection.Application.
Require Import Crypto.Reflection.Z.InterpretationsGen.
Require Import Crypto.Reflection.Z.Interpretations128.
Require Import Crypto.Reflection.Z.Interpretations128.Relations.
@@ -14,36 +14,6 @@ Require Import Crypto.Util.Prod.
Require Import Crypto.Util.Tactics.
Module Relations.
- Section lift.
- Context {interp_base_type1 interp_base_type2 : base_type -> Type}
- (R : forall t, interp_base_type1 t -> interp_base_type2 t -> Prop).
-
- Definition interp_type_rel_pointwise2_uncurried
- {t : type base_type}
- := match t return interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> _ with
- | Tflat T => fun f g => interp_flat_type_rel_pointwise (t:=T) R f g
- | Arrow A B
- => fun f g
- => forall x y, interp_flat_type_rel_pointwise R x y
- -> interp_flat_type_rel_pointwise R (ApplyInterpedAll f x) (ApplyInterpedAll g y)
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2
- {t f g}
- : interp_type_rel_pointwise2 (t:=t) R f g
- <-> interp_type_rel_pointwise2_uncurried (t:=t) f g.
- Proof.
- unfold interp_type_rel_pointwise2_uncurried.
- induction t as [|A B IHt]; [ reflexivity | ].
- { simpl; unfold Morphisms.respectful_hetero in *; destruct B.
- { reflexivity. }
- { setoid_rewrite IHt; clear IHt.
- split; intro H; intros.
- { destruct_head_hnf' prod; simpl in *; intuition. }
- { eapply (H (_, _) (_, _)); simpl in *; intuition. } } }
- Qed.
- End lift.
-
Section proj.
Context {interp_base_type1 interp_base_type2}
(proj : forall t : base_type, interp_base_type1 t -> interp_base_type2 t).
@@ -51,43 +21,27 @@ Module Relations.
Let R {t : flat_type base_type} f g :=
SmartVarfMap (t:=t) proj f = g.
- Definition interp_type_rel_pointwise2_uncurried_proj
+ Definition interp_type_rel_pointwise_uncurried_proj
{t : type base_type}
: interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> Prop with
- | Tflat T => @R _
- | Arrow A B
- => fun f g
- => forall x : interp_flat_type interp_base_type1 (all_binders_for (Arrow A B)),
- let y := SmartVarfMap proj x in
- let fx := ApplyInterpedAll f x in
- let gy := ApplyInterpedAll g y in
- @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj
+ := fun f g
+ => forall x : interp_flat_type interp_base_type1 (domain t),
+ let y := SmartVarfMap proj x in
+ let fx := f x in
+ let gy := g y in
+ @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj
{t : type base_type}
- {f : interp_type interp_base_type1 t}
+ {f}
{g}
- : interp_type_rel_pointwise2 (t:=t) (fun t => @R _) f g
- -> interp_type_rel_pointwise2_uncurried_proj (t:=t) f g.
+ : (forall x y, @R (domain t) x y -> @R (codomain t) (f x) (g y))
+ -> interp_type_rel_pointwise_uncurried_proj (t:=t) f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit;
- [ solve [ trivial | reflexivity ] | reflexivity | ].
- intros [HA HB].
- specialize (IHA _ _ HA); specialize (IHB _ _ HB).
- unfold R in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress subst
- | reflexivity ]. }
- { destruct B; intros H ?; apply IHt, H; clear IHt;
- repeat first [ reflexivity
- | progress simpl in *
- | progress unfold R, LiftOption.of' in *
- | progress break_match ]. }
+ unfold interp_type_rel_pointwise_uncurried_proj.
+ destruct t as [A B]; simpl in *.
+ subst R; simpl in *.
+ eauto.
Qed.
End proj.
@@ -102,49 +56,28 @@ Module Relations.
| None => True
end.
- Definition interp_type_rel_pointwise2_uncurried_proj_option
+ Definition interp_type_rel_pointwise_uncurried_proj_option
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type interp_base_type2 t -> Prop with
- | Tflat T => @R _
- | Arrow A B
- => fun f g
- => forall x : interp_flat_type (fun _ => interp_base_type1) (all_binders_for (Arrow A B)),
- let y := SmartVarfMap proj_option x in
- let fx := ApplyInterpedAll f (LiftOption.to' (Some x)) in
- let gy := ApplyInterpedAll g y in
- @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj_option
+ := fun f g
+ => forall x : interp_flat_type (fun _ => interp_base_type1) (domain t),
+ let y := SmartVarfMap proj_option x in
+ let fx := f (LiftOption.to' (Some x)) in
+ let gy := g y in
+ @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj_option
{t : type base_type}
- {f : interp_type (LiftOption.interp_base_type' interp_base_type1) t}
+ {f}
{g}
- : interp_type_rel_pointwise2 (t:=t) (fun t => @R _) f g
- -> interp_type_rel_pointwise2_uncurried_proj_option (t:=t) f g.
+ : (forall x y, @R (domain t) x y -> @R (codomain t) (f x) (g y))
+ -> interp_type_rel_pointwise_uncurried_proj_option (t:=t) f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj_option.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit;
- [ solve [ trivial | reflexivity ] | reflexivity | ].
- intros [HA HB].
- specialize (IHA _ _ HA); specialize (IHB _ _ HB).
- unfold R in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. }
- { destruct B; intros H ?; apply IHt, H; clear IHt.
- { repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of' in *
- | progress break_match
- | reflexivity ]. }
- { simpl in *; break_match; reflexivity. } }
+ unfold interp_type_rel_pointwise_uncurried_proj_option.
+ destruct t as [A B]; simpl in *.
+ subst R; simpl in *.
+ intros H x; apply H; simpl.
+ rewrite LiftOption.of'_to'; reflexivity.
Qed.
End proj_option.
@@ -162,52 +95,58 @@ Module Relations.
| None, _ => False
end.
- Definition interp_type_rel_pointwise2_uncurried_proj_option2
+ Definition interp_type_rel_pointwise_uncurried_proj_option2
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type (LiftOption.interp_base_type' interp_base_type2) t -> Prop
- := match t return interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type (LiftOption.interp_base_type' interp_base_type2) t -> Prop with
- | Tflat T => @R _
- | Arrow A B
- => fun f g
- => forall x : interp_flat_type (fun _ => interp_base_type1) (all_binders_for (Arrow A B)),
- let y := SmartVarfMap (fun _ => proj) x in
- let fx := ApplyInterpedAll f (LiftOption.to' (Some x)) in
- let gy := ApplyInterpedAll g (LiftOption.to' (Some y)) in
- @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj_option2
+ := fun f g
+ => forall x : interp_flat_type (fun _ => interp_base_type1) (domain t),
+ let y := SmartVarfMap (fun _ => proj) x in
+ let fx := f (LiftOption.to' (Some x)) in
+ let gy := g (LiftOption.to' (Some y)) in
+ @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj_option2
{t : type base_type}
- {f : interp_type (LiftOption.interp_base_type' interp_base_type1) t}
- {g : interp_type (LiftOption.interp_base_type' interp_base_type2) t}
- : interp_type_rel_pointwise2 (t:=t) (fun t => @R _) f g
- -> interp_type_rel_pointwise2_uncurried_proj_option2 (t:=t) f g.
+ {f}
+ {g}
+ : (forall x y, @R (domain t) x y -> @R (codomain t) (f x) (g y))
+ -> interp_type_rel_pointwise_uncurried_proj_option2 (t:=t) f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj_option2.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit;
- [ solve [ trivial | reflexivity ] | reflexivity | ].
- intros [HA HB].
- specialize (IHA _ _ HA); specialize (IHB _ _ HB).
- unfold R in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. }
- { destruct B; intros H ?; apply IHt, H; clear IHt.
- { repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of' in *
- | progress break_match
- | reflexivity ]. }
- { simpl in *; break_match; reflexivity. } }
+ unfold interp_type_rel_pointwise_uncurried_proj_option2.
+ destruct t as [A B]; simpl in *.
+ subst R; simpl in *.
+ intros H x; apply H; simpl.
+ rewrite !LiftOption.of'_to'; reflexivity.
Qed.
End proj_option2.
+ Local Ltac t proj012 :=
+ repeat match goal with
+ | _ => progress cbv beta in *
+ | _ => progress break_match; try tauto; []
+ | _ => progress subst
+ | [ H : _ |- _ ]
+ => first [ rewrite !LiftOption.lift_relation_flat_type_pointwise in H
+ by (eassumption || rewrite LiftOption.of'_to'; reflexivity)
+ | rewrite !LiftOption.lift_relation2_flat_type_pointwise in H
+ by (eassumption || rewrite LiftOption.of'_to'; reflexivity)
+ | rewrite !@lift_interp_flat_type_rel_pointwise_f_eq_id2 in H
+ | rewrite !@lift_interp_flat_type_rel_pointwise_f_eq in H ]
+ | _ => progress unfold proj_eq_rel in *
+ | _ => progress specialize_by reflexivity
+ | _ => rewrite SmartVarfMap_compose
+ | _ => setoid_rewrite proj012
+ | [ |- context G[fun x y => ?f x y] ]
+ => let G' := context G[f] in change G'
+ | [ |- context G[fun (_ : ?T) x => ?f x] ]
+ => let G' := context G[fun _ : T => f] in change G'
+ | [ H : context G[fun (_ : ?T) x => ?f x] |- _ ]
+ => let G' := context G[fun _ : T => f] in change G' in H
+ | _ => rewrite_hyp <- !*; []
+ | _ => reflexivity
+ | _ => rewrite interp_flat_type_rel_pointwise_SmartVarfMap
+ end.
+
Section proj_from_option2.
Context {interp_base_type0 : Type} {interp_base_type1 interp_base_type2 : base_type -> Type}
(proj01 : forall t, interp_base_type0 -> interp_base_type1 t)
@@ -217,64 +156,41 @@ Module Relations.
Let R {t : flat_type base_type} f g :=
proj_eq_rel (SmartVarfMap proj (t:=t)) f g.
- Definition interp_type_rel_pointwise2_uncurried_proj_from_option2
+ Definition interp_type_rel_pointwise_uncurried_proj_from_option2
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type0) t -> interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type _ t -> interp_type _ t -> interp_type _ t -> Prop with
- | Tflat T => fun f0 f g => match LiftOption.of' f0 with
- | Some _ => True
- | None => False
- end -> @R _ f g
- | Arrow A B
- => fun f0 f g
- => forall x : interp_flat_type (fun _ => interp_base_type0) (all_binders_for (Arrow A B)),
- let x' := SmartVarfMap proj01 x in
- let y' := SmartVarfMap proj x' in
- let fx := ApplyInterpedAll f x' in
- let gy := ApplyInterpedAll g y' in
- let f0x := LiftOption.of' (ApplyInterpedAll f0 (LiftOption.to' (Some x))) in
- match f0x with
- | Some _ => True
- | None => False
- end
- -> @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj_from_option2
+ := fun f0 f g
+ => forall x : interp_flat_type (fun _ => interp_base_type0) (domain t),
+ let x' := SmartVarfMap proj01 x in
+ let y' := SmartVarfMap proj x' in
+ let fx := f x' in
+ let gy := g y' in
+ let f0x := LiftOption.of' (f0 (LiftOption.to' (Some x))) in
+ match f0x with
+ | Some _ => True
+ | None => False
+ end
+ -> @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj_from_option2
{t : type base_type}
{f0}
{f : interp_type interp_base_type1 t}
{g : interp_type interp_base_type2 t}
(proj012 : forall t x, proj t (proj01 t x) = proj02 t x)
- : interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj01 t))) f0 f
- -> interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
- -> interp_type_rel_pointwise2_uncurried_proj_from_option2 (t:=t) f0 f g.
+ : interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj01 t))) f0 f
+ -> interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
+ -> interp_type_rel_pointwise_uncurried_proj_from_option2 (t:=t) f0 f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj_from_option2.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit; try reflexivity.
- { cbv [LiftOption.lift_relation proj_eq_rel R].
- break_match; try tauto; intros; subst.
- apply proj012. }
- { intros [HA HB] [HA' HB'] Hrel.
- specialize (IHA _ _ _ HA HA'); specialize (IHB _ _ _ HB HB').
- unfold R, proj_eq_rel in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. } }
- { destruct B; intros H0 H1 ?; apply IHt; clear IHt; first [ apply H0 | apply H1 ];
- repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of', proj_eq_rel, LiftOption.lift_relation in *
- | break_match; rewrite <- ?proj012; reflexivity ]. }
+ unfold interp_type_rel_pointwise_uncurried_proj_from_option2, Morphisms.respectful_hetero.
+ intros H0 H1 x.
+ specialize (H0 (LiftOption.to' (Some x)) (SmartVarfMap proj01 x)).
+ specialize (H1 (LiftOption.to' (Some x)) (SmartVarfMap proj02 x)).
+ subst R.
+ t proj012.
Qed.
End proj_from_option2.
- Global Arguments uncurry_interp_type_rel_pointwise2_proj_from_option2 {_ _ _ _ _} proj {t f0 f g} _ _ _.
+ Global Arguments uncurry_interp_type_rel_pointwise_proj_from_option2 {_ _ _ _ _} proj {t f0 f g} _ _ _.
Section proj1_from_option2.
Context {interp_base_type0 interp_base_type1 : Type} {interp_base_type2 : base_type -> Type}
@@ -282,70 +198,43 @@ Module Relations.
(proj02 : forall t, interp_base_type0 -> interp_base_type2 t)
(R : forall t, interp_base_type1 -> interp_base_type2 t -> Prop).
- Definition interp_type_rel_pointwise2_uncurried_proj1_from_option2
+ Definition interp_type_rel_pointwise_uncurried_proj1_from_option2
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type0) t -> interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type _ t -> interp_type _ t -> interp_type _ t -> Prop with
- | Tflat T => fun f0 f g => match LiftOption.of' f0 with
- | Some _ => True
- | None => False
- end -> match LiftOption.of' f with
- | Some f' => interp_flat_type_rel_pointwise (@R) f' g
- | None => True
- end
- | Arrow A B
- => fun f0 f g
- => forall x : interp_flat_type (fun _ => interp_base_type0) (all_binders_for (Arrow A B)),
- let x' := SmartVarfMap (fun _ => proj01) x in
- let y' := SmartVarfMap proj02 x in
- let fx := LiftOption.of' (ApplyInterpedAll f (LiftOption.to' (Some x'))) in
- let gy := ApplyInterpedAll g y' in
- let f0x := LiftOption.of' (ApplyInterpedAll f0 (LiftOption.to' (Some x))) in
- match f0x with
- | Some _ => True
- | None => False
- end
- -> match fx with
- | Some fx' => interp_flat_type_rel_pointwise (@R) fx' gy
- | None => True
- end
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj1_from_option2
+ := fun f0 f g
+ => forall x : interp_flat_type (fun _ => interp_base_type0) (domain t),
+ let x' := SmartVarfMap (fun _ => proj01) x in
+ let y' := SmartVarfMap proj02 x in
+ let fx := LiftOption.of' (f (LiftOption.to' (Some x'))) in
+ let gy := g y' in
+ let f0x := LiftOption.of' (f0 (LiftOption.to' (Some x))) in
+ match f0x with
+ | Some _ => True
+ | None => False
+ end
+ -> match fx with
+ | Some fx' => interp_flat_type_rel_pointwise (@R) fx' gy
+ | None => True
+ end.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj1_from_option2
{t : type base_type}
{f0}
{f : interp_type (LiftOption.interp_base_type' interp_base_type1) t}
{g : interp_type interp_base_type2 t}
- (proj012R : forall t x, @R _ (proj01 x) (proj02 t x))
- : interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation2 (proj_eq_rel proj01)) f0 f
- -> interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
- -> interp_type_rel_pointwise2_uncurried_proj1_from_option2 (t:=t) f0 f g.
+ (proj012R : forall t, Reflexive (fun x y => @R _ (proj01 x) (proj02 t y)))
+ : interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation2 (proj_eq_rel proj01)) f0 f
+ -> interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
+ -> interp_type_rel_pointwise_uncurried_proj1_from_option2 (t:=t) f0 f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj1_from_option2.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit; try reflexivity.
- { cbv [LiftOption.lift_relation proj_eq_rel LiftOption.lift_relation2].
- break_match; try tauto; intros; subst.
- apply proj012R. }
- { intros [HA HB] [HA' HB'] Hrel.
- specialize (IHA _ _ _ HA HA'); specialize (IHB _ _ _ HB HB').
- unfold proj_eq_rel in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. } }
- { destruct B; intros H0 H1 ?; apply IHt; clear IHt; first [ apply H0 | apply H1 ];
- repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of', proj_eq_rel, LiftOption.lift_relation in *
- | break_match; reflexivity ]. }
+ unfold interp_type_rel_pointwise_uncurried_proj1_from_option2, Morphisms.respectful_hetero.
+ intros H0 H1 x.
+ specialize (H0 (LiftOption.to' (Some x)) (LiftOption.to' (Some (SmartVarfMap (fun _ => proj01) x)))).
+ specialize (H1 (LiftOption.to' (Some x)) (SmartVarfMap proj02 x)).
+ t proj012.
Qed.
End proj1_from_option2.
- Global Arguments uncurry_interp_type_rel_pointwise2_proj1_from_option2 {_ _ _ _ _} R {t f0 f g} _ _ _.
+ Global Arguments uncurry_interp_type_rel_pointwise_proj1_from_option2 {_ _ _ _ _} R {t f0 f g} _ _ _.
Section combine_related.
Lemma related_flat_transitivity {interp_base_type1 interp_base_type2 interp_base_type3}
diff --git a/src/Reflection/Z/Interpretations64/Relations.v b/src/Reflection/Z/Interpretations64/Relations.v
index 02934c46a..3491c9be5 100644
--- a/src/Reflection/Z/Interpretations64/Relations.v
+++ b/src/Reflection/Z/Interpretations64/Relations.v
@@ -341,10 +341,12 @@ Local Ltac unfold_related_const :=
Lemma related_wordW_op : related_op related_wordW (@BoundedWordW.interp_op) (@WordW.interp_op).
Proof.
(let op := fresh in intros ?? op; destruct op; simpl);
+ destruct_head' base_type;
try first [ apply related_wordW_t_map1
| apply related_wordW_t_map2
| apply related_wordW_t_map4
- | unfold_related_const; break_innermost_match; reflexivity ].
+ | unfold_related_const; break_innermost_match; reflexivity
+ | exact (fun _ _ x => x) ].
Qed.
Lemma related_bounds_t_map1 opW opB pf
@@ -411,7 +413,7 @@ Local Ltac related_const_op_t :=
Lemma related_bounds_op : related_op related_bounds (@BoundedWordW.interp_op) (@ZBounds.interp_op).
Proof.
- let op := fresh in intros ?? op; destruct op; simpl.
+ let op := fresh in intros ?? op; destruct op; simpl; destruct_head' base_type.
{ related_const_op_t. }
{ apply related_bounds_t_map2; intros; destruct_head' option; reflexivity. }
{ apply related_bounds_t_map2; intros; destruct_head' option; reflexivity. }
@@ -423,6 +425,7 @@ Proof.
{ apply related_bounds_t_map1; intros; destruct_head' option; unfold ZBounds.neg; break_match; reflexivity. }
{ apply related_bounds_t_map4; intros; destruct_head' option; reflexivity. }
{ apply related_bounds_t_map4; intros; destruct_head' option; reflexivity. }
+ { exact (fun _ _ x => x). }
Qed.
Local Ltac WordW.Rewrites.wordW_util_arith ::=
@@ -541,7 +544,7 @@ Local Arguments ZBounds.neg _ !_ / .
Lemma related_Z_op : related_op related_Z (@BoundedWordW.interp_op) (@Z.interp_op).
Proof.
- let op := fresh in intros ?? op; destruct op; simpl.
+ let op := fresh in intros ?? op; destruct op; simpl; destruct_head' base_type.
{ related_const_op_t. }
{ apply related_Z_t_map2; related_Z_op_fin_t. }
{ apply related_Z_t_map2; related_Z_op_fin_t. }
@@ -553,6 +556,7 @@ Proof.
{ apply related_Z_t_map1; related_Z_op_fin_t. }
{ apply related_Z_t_map4; related_Z_op_fin_t. }
{ apply related_Z_t_map4; related_Z_op_fin_t. }
+ { exact (fun _ _ x => x). }
Qed.
Create HintDb interp_related discriminated.
diff --git a/src/Reflection/Z/Interpretations64/RelationsCombinations.v b/src/Reflection/Z/Interpretations64/RelationsCombinations.v
index 3a95bcc51..2e05b18de 100644
--- a/src/Reflection/Z/Interpretations64/RelationsCombinations.v
+++ b/src/Reflection/Z/Interpretations64/RelationsCombinations.v
@@ -1,9 +1,9 @@
Require Import Coq.ZArith.ZArith.
+Require Import Coq.Classes.RelationClasses.
Require Import Crypto.Reflection.Z.Syntax.
Require Import Crypto.Reflection.Syntax.
Require Import Crypto.Reflection.SmartMap.
Require Import Crypto.Reflection.Relations.
-Require Import Crypto.Reflection.Application.
Require Import Crypto.Reflection.Z.InterpretationsGen.
Require Import Crypto.Reflection.Z.Interpretations64.
Require Import Crypto.Reflection.Z.Interpretations64.Relations.
@@ -14,36 +14,6 @@ Require Import Crypto.Util.Prod.
Require Import Crypto.Util.Tactics.
Module Relations.
- Section lift.
- Context {interp_base_type1 interp_base_type2 : base_type -> Type}
- (R : forall t, interp_base_type1 t -> interp_base_type2 t -> Prop).
-
- Definition interp_type_rel_pointwise2_uncurried
- {t : type base_type}
- := match t return interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> _ with
- | Tflat T => fun f g => interp_flat_type_rel_pointwise (t:=T) R f g
- | Arrow A B
- => fun f g
- => forall x y, interp_flat_type_rel_pointwise R x y
- -> interp_flat_type_rel_pointwise R (ApplyInterpedAll f x) (ApplyInterpedAll g y)
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2
- {t f g}
- : interp_type_rel_pointwise2 (t:=t) R f g
- <-> interp_type_rel_pointwise2_uncurried (t:=t) f g.
- Proof.
- unfold interp_type_rel_pointwise2_uncurried.
- induction t as [|A B IHt]; [ reflexivity | ].
- { simpl; unfold Morphisms.respectful_hetero in *; destruct B.
- { reflexivity. }
- { setoid_rewrite IHt; clear IHt.
- split; intro H; intros.
- { destruct_head_hnf' prod; simpl in *; intuition. }
- { eapply (H (_, _) (_, _)); simpl in *; intuition. } } }
- Qed.
- End lift.
-
Section proj.
Context {interp_base_type1 interp_base_type2}
(proj : forall t : base_type, interp_base_type1 t -> interp_base_type2 t).
@@ -51,43 +21,27 @@ Module Relations.
Let R {t : flat_type base_type} f g :=
SmartVarfMap (t:=t) proj f = g.
- Definition interp_type_rel_pointwise2_uncurried_proj
+ Definition interp_type_rel_pointwise_uncurried_proj
{t : type base_type}
: interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> Prop with
- | Tflat T => @R _
- | Arrow A B
- => fun f g
- => forall x : interp_flat_type interp_base_type1 (all_binders_for (Arrow A B)),
- let y := SmartVarfMap proj x in
- let fx := ApplyInterpedAll f x in
- let gy := ApplyInterpedAll g y in
- @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj
+ := fun f g
+ => forall x : interp_flat_type interp_base_type1 (domain t),
+ let y := SmartVarfMap proj x in
+ let fx := f x in
+ let gy := g y in
+ @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj
{t : type base_type}
- {f : interp_type interp_base_type1 t}
+ {f}
{g}
- : interp_type_rel_pointwise2 (t:=t) (fun t => @R _) f g
- -> interp_type_rel_pointwise2_uncurried_proj (t:=t) f g.
+ : (forall x y, @R (domain t) x y -> @R (codomain t) (f x) (g y))
+ -> interp_type_rel_pointwise_uncurried_proj (t:=t) f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit;
- [ solve [ trivial | reflexivity ] | reflexivity | ].
- intros [HA HB].
- specialize (IHA _ _ HA); specialize (IHB _ _ HB).
- unfold R in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress subst
- | reflexivity ]. }
- { destruct B; intros H ?; apply IHt, H; clear IHt;
- repeat first [ reflexivity
- | progress simpl in *
- | progress unfold R, LiftOption.of' in *
- | progress break_match ]. }
+ unfold interp_type_rel_pointwise_uncurried_proj.
+ destruct t as [A B]; simpl in *.
+ subst R; simpl in *.
+ eauto.
Qed.
End proj.
@@ -102,49 +56,28 @@ Module Relations.
| None => True
end.
- Definition interp_type_rel_pointwise2_uncurried_proj_option
+ Definition interp_type_rel_pointwise_uncurried_proj_option
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type interp_base_type2 t -> Prop with
- | Tflat T => @R _
- | Arrow A B
- => fun f g
- => forall x : interp_flat_type (fun _ => interp_base_type1) (all_binders_for (Arrow A B)),
- let y := SmartVarfMap proj_option x in
- let fx := ApplyInterpedAll f (LiftOption.to' (Some x)) in
- let gy := ApplyInterpedAll g y in
- @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj_option
+ := fun f g
+ => forall x : interp_flat_type (fun _ => interp_base_type1) (domain t),
+ let y := SmartVarfMap proj_option x in
+ let fx := f (LiftOption.to' (Some x)) in
+ let gy := g y in
+ @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj_option
{t : type base_type}
- {f : interp_type (LiftOption.interp_base_type' interp_base_type1) t}
+ {f}
{g}
- : interp_type_rel_pointwise2 (t:=t) (fun t => @R _) f g
- -> interp_type_rel_pointwise2_uncurried_proj_option (t:=t) f g.
+ : (forall x y, @R (domain t) x y -> @R (codomain t) (f x) (g y))
+ -> interp_type_rel_pointwise_uncurried_proj_option (t:=t) f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj_option.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit;
- [ solve [ trivial | reflexivity ] | reflexivity | ].
- intros [HA HB].
- specialize (IHA _ _ HA); specialize (IHB _ _ HB).
- unfold R in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. }
- { destruct B; intros H ?; apply IHt, H; clear IHt.
- { repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of' in *
- | progress break_match
- | reflexivity ]. }
- { simpl in *; break_match; reflexivity. } }
+ unfold interp_type_rel_pointwise_uncurried_proj_option.
+ destruct t as [A B]; simpl in *.
+ subst R; simpl in *.
+ intros H x; apply H; simpl.
+ rewrite LiftOption.of'_to'; reflexivity.
Qed.
End proj_option.
@@ -162,52 +95,58 @@ Module Relations.
| None, _ => False
end.
- Definition interp_type_rel_pointwise2_uncurried_proj_option2
+ Definition interp_type_rel_pointwise_uncurried_proj_option2
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type (LiftOption.interp_base_type' interp_base_type2) t -> Prop
- := match t return interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type (LiftOption.interp_base_type' interp_base_type2) t -> Prop with
- | Tflat T => @R _
- | Arrow A B
- => fun f g
- => forall x : interp_flat_type (fun _ => interp_base_type1) (all_binders_for (Arrow A B)),
- let y := SmartVarfMap (fun _ => proj) x in
- let fx := ApplyInterpedAll f (LiftOption.to' (Some x)) in
- let gy := ApplyInterpedAll g (LiftOption.to' (Some y)) in
- @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj_option2
+ := fun f g
+ => forall x : interp_flat_type (fun _ => interp_base_type1) (domain t),
+ let y := SmartVarfMap (fun _ => proj) x in
+ let fx := f (LiftOption.to' (Some x)) in
+ let gy := g (LiftOption.to' (Some y)) in
+ @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj_option2
{t : type base_type}
- {f : interp_type (LiftOption.interp_base_type' interp_base_type1) t}
- {g : interp_type (LiftOption.interp_base_type' interp_base_type2) t}
- : interp_type_rel_pointwise2 (t:=t) (fun t => @R _) f g
- -> interp_type_rel_pointwise2_uncurried_proj_option2 (t:=t) f g.
+ {f}
+ {g}
+ : (forall x y, @R (domain t) x y -> @R (codomain t) (f x) (g y))
+ -> interp_type_rel_pointwise_uncurried_proj_option2 (t:=t) f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj_option2.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit;
- [ solve [ trivial | reflexivity ] | reflexivity | ].
- intros [HA HB].
- specialize (IHA _ _ HA); specialize (IHB _ _ HB).
- unfold R in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. }
- { destruct B; intros H ?; apply IHt, H; clear IHt.
- { repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of' in *
- | progress break_match
- | reflexivity ]. }
- { simpl in *; break_match; reflexivity. } }
+ unfold interp_type_rel_pointwise_uncurried_proj_option2.
+ destruct t as [A B]; simpl in *.
+ subst R; simpl in *.
+ intros H x; apply H; simpl.
+ rewrite !LiftOption.of'_to'; reflexivity.
Qed.
End proj_option2.
+ Local Ltac t proj012 :=
+ repeat match goal with
+ | _ => progress cbv beta in *
+ | _ => progress break_match; try tauto; []
+ | _ => progress subst
+ | [ H : _ |- _ ]
+ => first [ rewrite !LiftOption.lift_relation_flat_type_pointwise in H
+ by (eassumption || rewrite LiftOption.of'_to'; reflexivity)
+ | rewrite !LiftOption.lift_relation2_flat_type_pointwise in H
+ by (eassumption || rewrite LiftOption.of'_to'; reflexivity)
+ | rewrite !@lift_interp_flat_type_rel_pointwise_f_eq_id2 in H
+ | rewrite !@lift_interp_flat_type_rel_pointwise_f_eq in H ]
+ | _ => progress unfold proj_eq_rel in *
+ | _ => progress specialize_by reflexivity
+ | _ => rewrite SmartVarfMap_compose
+ | _ => setoid_rewrite proj012
+ | [ |- context G[fun x y => ?f x y] ]
+ => let G' := context G[f] in change G'
+ | [ |- context G[fun (_ : ?T) x => ?f x] ]
+ => let G' := context G[fun _ : T => f] in change G'
+ | [ H : context G[fun (_ : ?T) x => ?f x] |- _ ]
+ => let G' := context G[fun _ : T => f] in change G' in H
+ | _ => rewrite_hyp <- !*; []
+ | _ => reflexivity
+ | _ => rewrite interp_flat_type_rel_pointwise_SmartVarfMap
+ end.
+
Section proj_from_option2.
Context {interp_base_type0 : Type} {interp_base_type1 interp_base_type2 : base_type -> Type}
(proj01 : forall t, interp_base_type0 -> interp_base_type1 t)
@@ -217,64 +156,41 @@ Module Relations.
Let R {t : flat_type base_type} f g :=
proj_eq_rel (SmartVarfMap proj (t:=t)) f g.
- Definition interp_type_rel_pointwise2_uncurried_proj_from_option2
+ Definition interp_type_rel_pointwise_uncurried_proj_from_option2
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type0) t -> interp_type interp_base_type1 t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type _ t -> interp_type _ t -> interp_type _ t -> Prop with
- | Tflat T => fun f0 f g => match LiftOption.of' f0 with
- | Some _ => True
- | None => False
- end -> @R _ f g
- | Arrow A B
- => fun f0 f g
- => forall x : interp_flat_type (fun _ => interp_base_type0) (all_binders_for (Arrow A B)),
- let x' := SmartVarfMap proj01 x in
- let y' := SmartVarfMap proj x' in
- let fx := ApplyInterpedAll f x' in
- let gy := ApplyInterpedAll g y' in
- let f0x := LiftOption.of' (ApplyInterpedAll f0 (LiftOption.to' (Some x))) in
- match f0x with
- | Some _ => True
- | None => False
- end
- -> @R _ fx gy
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj_from_option2
+ := fun f0 f g
+ => forall x : interp_flat_type (fun _ => interp_base_type0) (domain t),
+ let x' := SmartVarfMap proj01 x in
+ let y' := SmartVarfMap proj x' in
+ let fx := f x' in
+ let gy := g y' in
+ let f0x := LiftOption.of' (f0 (LiftOption.to' (Some x))) in
+ match f0x with
+ | Some _ => True
+ | None => False
+ end
+ -> @R _ fx gy.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj_from_option2
{t : type base_type}
{f0}
{f : interp_type interp_base_type1 t}
{g : interp_type interp_base_type2 t}
(proj012 : forall t x, proj t (proj01 t x) = proj02 t x)
- : interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj01 t))) f0 f
- -> interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
- -> interp_type_rel_pointwise2_uncurried_proj_from_option2 (t:=t) f0 f g.
+ : interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj01 t))) f0 f
+ -> interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
+ -> interp_type_rel_pointwise_uncurried_proj_from_option2 (t:=t) f0 f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj_from_option2.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit; try reflexivity.
- { cbv [LiftOption.lift_relation proj_eq_rel R].
- break_match; try tauto; intros; subst.
- apply proj012. }
- { intros [HA HB] [HA' HB'] Hrel.
- specialize (IHA _ _ _ HA HA'); specialize (IHB _ _ _ HB HB').
- unfold R, proj_eq_rel in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. } }
- { destruct B; intros H0 H1 ?; apply IHt; clear IHt; first [ apply H0 | apply H1 ];
- repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of', proj_eq_rel, LiftOption.lift_relation in *
- | break_match; rewrite <- ?proj012; reflexivity ]. }
+ unfold interp_type_rel_pointwise_uncurried_proj_from_option2, Morphisms.respectful_hetero.
+ intros H0 H1 x.
+ specialize (H0 (LiftOption.to' (Some x)) (SmartVarfMap proj01 x)).
+ specialize (H1 (LiftOption.to' (Some x)) (SmartVarfMap proj02 x)).
+ subst R.
+ t proj012.
Qed.
End proj_from_option2.
- Global Arguments uncurry_interp_type_rel_pointwise2_proj_from_option2 {_ _ _ _ _} proj {t f0 f g} _ _ _.
+ Global Arguments uncurry_interp_type_rel_pointwise_proj_from_option2 {_ _ _ _ _} proj {t f0 f g} _ _ _.
Section proj1_from_option2.
Context {interp_base_type0 interp_base_type1 : Type} {interp_base_type2 : base_type -> Type}
@@ -282,70 +198,43 @@ Module Relations.
(proj02 : forall t, interp_base_type0 -> interp_base_type2 t)
(R : forall t, interp_base_type1 -> interp_base_type2 t -> Prop).
- Definition interp_type_rel_pointwise2_uncurried_proj1_from_option2
+ Definition interp_type_rel_pointwise_uncurried_proj1_from_option2
{t : type base_type}
: interp_type (LiftOption.interp_base_type' interp_base_type0) t -> interp_type (LiftOption.interp_base_type' interp_base_type1) t -> interp_type interp_base_type2 t -> Prop
- := match t return interp_type _ t -> interp_type _ t -> interp_type _ t -> Prop with
- | Tflat T => fun f0 f g => match LiftOption.of' f0 with
- | Some _ => True
- | None => False
- end -> match LiftOption.of' f with
- | Some f' => interp_flat_type_rel_pointwise (@R) f' g
- | None => True
- end
- | Arrow A B
- => fun f0 f g
- => forall x : interp_flat_type (fun _ => interp_base_type0) (all_binders_for (Arrow A B)),
- let x' := SmartVarfMap (fun _ => proj01) x in
- let y' := SmartVarfMap proj02 x in
- let fx := LiftOption.of' (ApplyInterpedAll f (LiftOption.to' (Some x'))) in
- let gy := ApplyInterpedAll g y' in
- let f0x := LiftOption.of' (ApplyInterpedAll f0 (LiftOption.to' (Some x))) in
- match f0x with
- | Some _ => True
- | None => False
- end
- -> match fx with
- | Some fx' => interp_flat_type_rel_pointwise (@R) fx' gy
- | None => True
- end
- end.
-
- Lemma uncurry_interp_type_rel_pointwise2_proj1_from_option2
+ := fun f0 f g
+ => forall x : interp_flat_type (fun _ => interp_base_type0) (domain t),
+ let x' := SmartVarfMap (fun _ => proj01) x in
+ let y' := SmartVarfMap proj02 x in
+ let fx := LiftOption.of' (f (LiftOption.to' (Some x'))) in
+ let gy := g y' in
+ let f0x := LiftOption.of' (f0 (LiftOption.to' (Some x))) in
+ match f0x with
+ | Some _ => True
+ | None => False
+ end
+ -> match fx with
+ | Some fx' => interp_flat_type_rel_pointwise (@R) fx' gy
+ | None => True
+ end.
+
+ Lemma uncurry_interp_type_rel_pointwise_proj1_from_option2
{t : type base_type}
{f0}
{f : interp_type (LiftOption.interp_base_type' interp_base_type1) t}
{g : interp_type interp_base_type2 t}
- (proj012R : forall t x, @R _ (proj01 x) (proj02 t x))
- : interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation2 (proj_eq_rel proj01)) f0 f
- -> interp_type_rel_pointwise2 (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
- -> interp_type_rel_pointwise2_uncurried_proj1_from_option2 (t:=t) f0 f g.
+ (proj012R : forall t, Reflexive (fun x y => @R _ (proj01 x) (proj02 t y)))
+ : interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation2 (proj_eq_rel proj01)) f0 f
+ -> interp_type_rel_pointwise (t:=t) (LiftOption.lift_relation (fun t => proj_eq_rel (proj02 t))) f0 g
+ -> interp_type_rel_pointwise_uncurried_proj1_from_option2 (t:=t) f0 f g.
Proof.
- unfold interp_type_rel_pointwise2_uncurried_proj1_from_option2.
- induction t as [t|A B IHt]; simpl; unfold Morphisms.respectful_hetero in *.
- { induction t as [t| |A IHA B IHB]; simpl; destruct_head_hnf' unit; try reflexivity.
- { cbv [LiftOption.lift_relation proj_eq_rel LiftOption.lift_relation2].
- break_match; try tauto; intros; subst.
- apply proj012R. }
- { intros [HA HB] [HA' HB'] Hrel.
- specialize (IHA _ _ _ HA HA'); specialize (IHB _ _ _ HB HB').
- unfold proj_eq_rel in *.
- repeat first [ progress destruct_head_hnf' prod
- | progress simpl in *
- | progress unfold LiftOption.of' in *
- | progress break_match
- | progress break_match_hyps
- | progress inversion_prod
- | progress inversion_option
- | reflexivity
- | progress intuition subst ]. } }
- { destruct B; intros H0 H1 ?; apply IHt; clear IHt; first [ apply H0 | apply H1 ];
- repeat first [ progress simpl in *
- | progress unfold R, LiftOption.of', proj_eq_rel, LiftOption.lift_relation in *
- | break_match; reflexivity ]. }
+ unfold interp_type_rel_pointwise_uncurried_proj1_from_option2, Morphisms.respectful_hetero.
+ intros H0 H1 x.
+ specialize (H0 (LiftOption.to' (Some x)) (LiftOption.to' (Some (SmartVarfMap (fun _ => proj01) x)))).
+ specialize (H1 (LiftOption.to' (Some x)) (SmartVarfMap proj02 x)).
+ t proj012.
Qed.
End proj1_from_option2.
- Global Arguments uncurry_interp_type_rel_pointwise2_proj1_from_option2 {_ _ _ _ _} R {t f0 f g} _ _ _.
+ Global Arguments uncurry_interp_type_rel_pointwise_proj1_from_option2 {_ _ _ _ _} R {t f0 f g} _ _ _.
Section combine_related.
Lemma related_flat_transitivity {interp_base_type1 interp_base_type2 interp_base_type3}
diff --git a/src/Reflection/Z/InterpretationsGen.v b/src/Reflection/Z/InterpretationsGen.v
index f11837e60..6fa2ff8da 100644
--- a/src/Reflection/Z/InterpretationsGen.v
+++ b/src/Reflection/Z/InterpretationsGen.v
@@ -3,7 +3,7 @@ Require Import Coq.ZArith.ZArith.
Require Import Crypto.Reflection.Z.Syntax.
Require Import Crypto.Reflection.Syntax.
Require Import Crypto.Reflection.SmartMap.
-Require Import Crypto.Reflection.Application.
+Require Import Crypto.Reflection.Relations.
Require Import Crypto.ModularArithmetic.ModularBaseSystemListZOperations.
Require Import Crypto.Util.Equality.
Require Import Crypto.Util.ZUtil.
@@ -53,9 +53,7 @@ Module InterpretationsGen (Bit : BitSize).
:= option (interp_flat_type (fun _ => T) t).
Definition interp_base_type' (t : base_type)
- := match t with
- | TZ => option T
- end.
+ := option T.
Definition of' {t} : Syntax.interp_flat_type interp_base_type' t -> interp_flat_type t
:= @smart_interp_flat_map
@@ -69,41 +67,115 @@ Module InterpretationsGen (Bit : BitSize).
end)
t.
+ Lemma of'_pair {A B} x
+ : @of' (A * B) x = match of' (fst x), of' (snd x) with
+ | Some x', Some y' => Some (x', y')
+ | _, _ => None
+ end.
+ Proof. reflexivity. Qed.
+
Fixpoint to' {t} : interp_flat_type t -> Syntax.interp_flat_type interp_base_type' t
:= match t return interp_flat_type t -> Syntax.interp_flat_type interp_base_type' t with
- | Tbase TZ => fun x => x
+ | Tbase _ => fun x => x
| Unit => fun _ => tt
| Prod A B => fun x => (@to' A (option_map (@fst _ _) x),
@to' B (option_map (@snd _ _) x))
end.
- Definition lift_relation {interp_base_type2}
- (R : forall t, T -> interp_base_type2 t -> Prop)
- : forall t, interp_base_type' t -> interp_base_type2 t -> Prop
- := fun t x y => match of' (t:=Tbase t) x with
- | Some x' => R t x' y
- | None => True
- end.
-
- Definition Some {t} (x : T) : interp_base_type' t
- := match t with
- | TZ => Some x
- end.
+ Lemma of'_to' {t} v : of' (@to' t (Some v)) = Some v.
+ Proof.
+ induction t;
+ repeat first [ progress simpl
+ | progress destruct_head_hnf prod
+ | progress destruct_head_hnf unit
+ | progress destruct_head base_type
+ | rewrite of'_pair
+ | rewrite_hyp !*
+ | reflexivity ].
+ Qed.
+
+ Section lift_relation.
+ Context {interp_base_type2 : base_type -> Type}
+ (R : forall t, T -> interp_base_type2 t -> Prop).
+ Definition lift_relation
+ : forall t, interp_base_type' t -> interp_base_type2 t -> Prop
+ := fun t x y => match of' (t:=Tbase t) x with
+ | Some x' => R t x' y
+ | None => True
+ end.
+
+ Lemma lift_relation_flat_type_pointwise t x y x'
+ (Hx : of' x = Some x')
+ : interp_flat_type_rel_pointwise lift_relation x y
+ <-> interp_flat_type_rel_pointwise (t:=t) R x' y.
+ Proof.
+ induction t; simpl; try tauto.
+ { unfold lift_relation; rewrite Hx; reflexivity. }
+ { rewrite of'_pair in Hx.
+ destruct (of' (fst x)) eqn:?, (of' (snd x)) eqn:?; try congruence.
+ inversion_option; subst.
+ destruct_head_hnf prod; split_iff; intuition eauto. }
+ Qed.
+
+ Lemma lift_relation_type_pointwise t f g f'
+ (Hx : forall x x', of' x = Some x' -> of' (f x) = Some (f' x'))
+ : interp_type_rel_pointwise lift_relation f g
+ -> interp_type_rel_pointwise (t:=t) R f' g.
+ Proof.
+ destruct t; simpl; unfold Morphisms.respectful_hetero.
+ intros H x y p; specialize (H (to' (Some x)) y).
+ eapply lift_relation_flat_type_pointwise in p; [ | apply of'_to'.. ].
+ specialize (H p).
+ eapply lift_relation_flat_type_pointwise in H; [ exact H | ].
+ erewrite Hx; [ reflexivity | ].
+ rewrite of'_to'; reflexivity.
+ Qed.
+ End lift_relation.
End lift_option.
Global Arguments of' {T t} _.
Global Arguments to' {T t} _.
- Global Arguments Some {T t} _.
Global Arguments lift_relation {T _} R _ _ _.
Section lift_option2.
- Context (T U : Type).
- Definition lift_relation2 (R : T -> U -> Prop)
+ Context (T U : Type) (R : T -> U -> Prop).
+ Definition lift_relation2
: forall t, interp_base_type' T t -> interp_base_type' U t -> Prop
:= fun t x y => match of' (t:=Tbase t) x, of' (t:=Tbase t) y with
| Datatypes.Some x', Datatypes.Some y' => R x' y'
| None, None => True
| _, _ => False
end.
+
+ Lemma lift_relation2_flat_type_pointwise t x y x' y'
+ (Hx : of' x = Datatypes.Some x')
+ (Hy : of' y = Datatypes.Some y')
+ : interp_flat_type_rel_pointwise lift_relation2 x y
+ <-> interp_flat_type_rel_pointwise (t:=t) (fun _ => R) x' y'.
+ Proof.
+ induction t; simpl; try tauto.
+ { unfold lift_relation2; rewrite Hx, Hy; reflexivity. }
+ { rewrite of'_pair in Hx, Hy.
+ destruct (of' (fst x)) eqn:?, (of' (snd x)) eqn:?; try congruence.
+ destruct (of' (fst y)) eqn:?, (of' (snd y)) eqn:?; try congruence.
+ inversion_option; subst.
+ destruct_head_hnf prod; split_iff; intuition eauto. }
+ Qed.
+
+ Lemma lift_relation2_type_pointwise t f g f' g'
+ (Hx : forall x x', of' x = Datatypes.Some x' -> of' (f x) = Datatypes.Some (f' x'))
+ (Hy : forall x x', of' x = Datatypes.Some x' -> of' (g x) = Datatypes.Some (g' x'))
+ : interp_type_rel_pointwise lift_relation2 f g
+ -> interp_type_rel_pointwise (t:=t) (fun _ => R) f' g'.
+ Proof.
+ destruct t; simpl; unfold Morphisms.respectful_hetero.
+ intros H x y p; specialize (H (to' (Datatypes.Some x)) (to' (Datatypes.Some y))).
+ eapply lift_relation2_flat_type_pointwise in p; [ | apply of'_to'.. ].
+ specialize (H p).
+ eapply lift_relation2_flat_type_pointwise in H; [ exact H | .. ];
+ [ erewrite Hx; [ reflexivity | ]
+ | erewrite Hy; [ reflexivity | ] ];
+ rewrite of'_to'; reflexivity.
+ Qed.
End lift_option2.
Global Arguments lift_relation2 {T U} R _ _ _.
End LiftOption.
@@ -271,17 +343,18 @@ Module InterpretationsGen (Bit : BitSize).
end.
Definition interp_op {src dst} (f : op src dst) : interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst
:= match f in op src dst return interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst with
- | OpConst v => fun _ => ZToWordW v
- | Add => fun xy => fst xy + snd xy
- | Sub => fun xy => fst xy - snd xy
- | Mul => fun xy => fst xy * snd xy
- | Shl => fun xy => fst xy << snd xy
- | Shr => fun xy => fst xy >> snd xy
- | Land => fun xy => land (fst xy) (snd xy)
- | Lor => fun xy => lor (fst xy) (snd xy)
- | Neg int_width => fun x => neg int_width x
- | Cmovne => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
- | Cmovle => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle x y z w
+ | OpConst TZ v => fun _ => ZToWordW v
+ | Add TZ => fun xy => fst xy + snd xy
+ | Sub TZ => fun xy => fst xy - snd xy
+ | Mul TZ => fun xy => fst xy * snd xy
+ | Shl TZ => fun xy => fst xy << snd xy
+ | Shr TZ => fun xy => fst xy >> snd xy
+ | Land TZ => fun xy => land (fst xy) (snd xy)
+ | Lor TZ => fun xy => lor (fst xy) (snd xy)
+ | Neg TZ int_width => fun x => neg int_width x
+ | Cmovne TZ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
+ | Cmovle TZ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle x y z w
+ | Cast TZ TZ => fun x => x
end%wordW.
Definition of_Z ty : Z.interp_base_type ty -> interp_base_type ty
@@ -416,20 +489,21 @@ Module InterpretationsGen (Bit : BitSize).
End Notations.
Definition interp_base_type (ty : base_type) : Type
- := LiftOption.interp_base_type' bounds ty.
+ := option bounds.
Definition interp_op {src dst} (f : op src dst) : interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst
:= match f in op src dst return interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst with
- | OpConst v => fun _ => SmartBuildBounds v v
- | Add => fun xy => fst xy + snd xy
- | Sub => fun xy => fst xy - snd xy
- | Mul => fun xy => fst xy * snd xy
- | Shl => fun xy => fst xy << snd xy
- | Shr => fun xy => fst xy >> snd xy
- | Land => fun xy => land (fst xy) (snd xy)
- | Lor => fun xy => lor (fst xy) (snd xy)
- | Neg int_width => fun x => neg int_width x
- | Cmovne => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
- | Cmovle => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle x y z w
+ | OpConst TZ v => fun _ => SmartBuildBounds v v
+ | Add _ => fun xy => fst xy + snd xy
+ | Sub _ => fun xy => fst xy - snd xy
+ | Mul _ => fun xy => fst xy * snd xy
+ | Shl _ => fun xy => fst xy << snd xy
+ | Shr _ => fun xy => fst xy >> snd xy
+ | Land _ => fun xy => land (fst xy) (snd xy)
+ | Lor _ => fun xy => lor (fst xy) (snd xy)
+ | Neg _ int_width => fun x => neg int_width x
+ | Cmovne _ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
+ | Cmovle _ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle x y z w
+ | Cast _ _ => fun x => x
end%bounds.
Definition of_wordW ty : WordW.interp_base_type ty -> interp_base_type ty
@@ -804,17 +878,18 @@ Module InterpretationsGen (Bit : BitSize).
Definition interp_op {src dst} (f : op src dst) : interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst
:= match f in op src dst return interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst with
- | OpConst v => fun _ => SmartBuildBoundedWord v
- | Add => fun xy => fst xy + snd xy
- | Sub => fun xy => fst xy - snd xy
- | Mul => fun xy => fst xy * snd xy
- | Shl => fun xy => fst xy << snd xy
- | Shr => fun xy => fst xy >> snd xy
- | Land => fun xy => land (fst xy) (snd xy)
- | Lor => fun xy => lor (fst xy) (snd xy)
- | Neg int_width => fun x => neg int_width x
- | Cmovne => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
- | Cmovle => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle x y z w
+ | OpConst TZ v => fun _ => SmartBuildBoundedWord v
+ | Add TZ => fun xy => fst xy + snd xy
+ | Sub TZ => fun xy => fst xy - snd xy
+ | Mul TZ => fun xy => fst xy * snd xy
+ | Shl TZ => fun xy => fst xy << snd xy
+ | Shr TZ => fun xy => fst xy >> snd xy
+ | Land TZ => fun xy => land (fst xy) (snd xy)
+ | Lor TZ => fun xy => lor (fst xy) (snd xy)
+ | Neg TZ int_width => fun x => neg int_width x
+ | Cmovne TZ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
+ | Cmovle TZ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovle x y z w
+ | Cast TZ TZ => fun x => x
end%bounded_word.
End BoundedWordW.
diff --git a/src/Reflection/Z/JavaNotations.v b/src/Reflection/Z/JavaNotations.v
index 4a33a6330..8dc23ec82 100644
--- a/src/Reflection/Z/JavaNotations.v
+++ b/src/Reflection/Z/JavaNotations.v
@@ -40,18 +40,18 @@ Notation "'(int)' x" := (Op (Cast _ (TWord 5)) (Var x)).
Notation "'M32' & x" := (Op (Cast _ (TWord 6)) (Var x)).
Notation "'(uint128_t)' x" := (Op (Cast _ (TWord 7)) (Var x)).
*)
-Notation "x + y" := (Op (Add) (Pair x y)).
-Notation "x + y" := (Op (Add) (Pair (Var x) y)).
-Notation "x + y" := (Op (Add) (Pair x (Var y))).
-Notation "x + y" := (Op (Add) (Pair (Var x) (Var y))).
-Notation "x - y" := (Op (Sub) (Pair x y)).
-Notation "x - y" := (Op (Sub) (Pair (Var x) y)).
-Notation "x - y" := (Op (Sub) (Pair x (Var y))).
-Notation "x - y" := (Op (Sub) (Pair (Var x) (Var y))).
-Notation "x * y" := (Op (Mul) (Pair x y)).
-Notation "x * y" := (Op (Mul) (Pair (Var x) y)).
-Notation "x * y" := (Op (Mul) (Pair x (Var y))).
-Notation "x * y" := (Op (Mul) (Pair (Var x) (Var y))).
+Notation "x + y" := (Op (Add _) (Pair x y)).
+Notation "x + y" := (Op (Add _) (Pair (Var x) y)).
+Notation "x + y" := (Op (Add _) (Pair x (Var y))).
+Notation "x + y" := (Op (Add _) (Pair (Var x) (Var y))).
+Notation "x - y" := (Op (Sub _) (Pair x y)).
+Notation "x - y" := (Op (Sub _) (Pair (Var x) y)).
+Notation "x - y" := (Op (Sub _) (Pair x (Var y))).
+Notation "x - y" := (Op (Sub _) (Pair (Var x) (Var y))).
+Notation "x * y" := (Op (Mul _) (Pair x y)).
+Notation "x * y" := (Op (Mul _) (Pair (Var x) y)).
+Notation "x * y" := (Op (Mul _) (Pair x (Var y))).
+Notation "x * y" := (Op (Mul _) (Pair (Var x) (Var y))).
(* python:
<<
for opn, op in (('*', 'Mul'), ('+', 'Add'), ('&', 'Land')):
@@ -115,20 +115,18 @@ Notation "x + y" := (Op (Add (TWord 7)) (Pair x (Op (Cast _ (TWord 7)) (Var y)))
Notation "x + y" := (Op (Add (TWord 7)) (Pair (Var x) (Op (Cast _ (TWord 7)) y))).
Notation "x + y" := (Op (Add (TWord 7)) (Pair (Var x) (Op (Cast _ (TWord 7)) (Var y)))).
*)
-Notation "x >>> y" := (Op (Shr) (Pair x y)).
-Notation "x >>> y" := (Op (Shr) (Pair (Var x) y)).
-Notation "x >>> y" := (Op (Shr) (Pair x (Var y))).
-Notation "x >>> y" := (Op (Shr) (Pair (Var x) (Var y))).
-(*
+Notation "x >>> y" := (Op (Shr _) (Pair x y)).
+Notation "x >>> y" := (Op (Shr _) (Pair (Var x) y)).
+Notation "x >>> y" := (Op (Shr _) (Pair x (Var y))).
+Notation "x >>> y" := (Op (Shr _) (Pair (Var x) (Var y))).
Notation "x >>> y" := (Op (Shr _) (Pair x (Op (Cast _ _) y))).
Notation "x >>> y" := (Op (Shr _) (Pair (Var x) (Op (Cast _ _) y))).
Notation "x >>> y" := (Op (Shr _) (Pair x (Op (Cast _ _) (Var y)))).
Notation "x >>> y" := (Op (Shr _) (Pair (Var x) (Op (Cast _ _) (Var y)))).
-*)
-Notation "x & y" := (Op (Land) (Pair x y)).
-Notation "x & y" := (Op (Land) (Pair (Var x) y)).
-Notation "x & y" := (Op (Land) (Pair x (Var y))).
-Notation "x & y" := (Op (Land) (Pair (Var x) (Var y))).
+Notation "x & y" := (Op (Land _) (Pair x y)).
+Notation "x & y" := (Op (Land _) (Pair (Var x) y)).
+Notation "x & y" := (Op (Land _) (Pair x (Var y))).
+Notation "x & y" := (Op (Land _) (Pair (Var x) (Var y))).
(*
Notation "x & y" := (Op (Land (TWord 6)) (Pair (Op (Cast _ (TWord 6)) x) y)).
Notation "x & y" := (Op (Land (TWord 6)) (Pair (Op (Cast _ (TWord 6)) x) (Var y))).
diff --git a/src/Reflection/Z/OpInversion.v b/src/Reflection/Z/OpInversion.v
index 3ef7b7e5a..6b2cdd85b 100644
--- a/src/Reflection/Z/OpInversion.v
+++ b/src/Reflection/Z/OpInversion.v
@@ -19,9 +19,9 @@ Ltac invert_op := repeat invert_op_step.
Ltac invert_match_op_step :=
match goal with
- | [ |- appcontext[match ?e with OpConst _ => _ | _ => _ end] ]
+ | [ |- appcontext[match ?e with OpConst _ _ => _ | _ => _ end] ]
=> invert_one_op e
- | [ H : appcontext[match ?e with OpConst _ => _ | _ => _ end] |- _ ]
+ | [ H : appcontext[match ?e with OpConst _ _ => _ | _ => _ end] |- _ ]
=> invert_one_op e
end.
diff --git a/src/Reflection/Z/Reify.v b/src/Reflection/Z/Reify.v
index e200b2e9e..84bc6f078 100644
--- a/src/Reflection/Z/Reify.v
+++ b/src/Reflection/Z/Reify.v
@@ -10,22 +10,24 @@ Require Import Crypto.Reflection.Inline.
Require Import Crypto.Reflection.InlineInterp.
Require Import Crypto.Reflection.Linearize.
Require Import Crypto.Reflection.LinearizeInterp.
+Require Import Crypto.Reflection.Eta.
+Require Import Crypto.Reflection.EtaInterp.
Ltac base_reify_op op op_head extra ::=
lazymatch op_head with
- | @Z.add => constr:(reify_op op op_head 2 Add)
- | @Z.mul => constr:(reify_op op op_head 2 Mul)
- | @Z.sub => constr:(reify_op op op_head 2 Sub)
- | @Z.shiftl => constr:(reify_op op op_head 2 Shl)
- | @Z.shiftr => constr:(reify_op op op_head 2 Shr)
- | @Z.land => constr:(reify_op op op_head 2 Land)
- | @Z.lor => constr:(reify_op op op_head 2 Lor)
- | @ModularBaseSystemListZOperations.cmovne => constr:(reify_op op op_head 4 Cmovne)
- | @ModularBaseSystemListZOperations.cmovl => constr:(reify_op op op_head 4 Cmovle)
+ | @Z.add => constr:(reify_op op op_head 2 (Add TZ))
+ | @Z.mul => constr:(reify_op op op_head 2 (Mul TZ))
+ | @Z.sub => constr:(reify_op op op_head 2 (Sub TZ))
+ | @Z.shiftl => constr:(reify_op op op_head 2 (Shl TZ))
+ | @Z.shiftr => constr:(reify_op op op_head 2 (Shr TZ))
+ | @Z.land => constr:(reify_op op op_head 2 (Land TZ))
+ | @Z.lor => constr:(reify_op op op_head 2 (Lor TZ))
+ | @ModularBaseSystemListZOperations.cmovne => constr:(reify_op op op_head 4 (Cmovne TZ))
+ | @ModularBaseSystemListZOperations.cmovl => constr:(reify_op op op_head 4 (Cmovle TZ))
| @ModularBaseSystemListZOperations.neg
=> lazymatch extra with
| @ModularBaseSystemListZOperations.neg ?int_width _
- => constr:(reify_op op op_head 1 (Neg int_width))
+ => constr:(reify_op op op_head 1 (Neg TZ int_width))
| _ => fail 100 "Anomaly: In Reflection.Z.base_reify_op: head is neg but body is wrong:" extra
end
end.
@@ -36,12 +38,13 @@ Ltac base_reify_type T ::=
Ltac Reify' e := Reflection.Reify.Reify' base_type interp_base_type op e.
Ltac Reify e :=
let v := Reflection.Reify.Reify base_type interp_base_type op make_const e in
- constr:((*Inline _*) ((*CSE _*) (InlineConst is_const (Linearize v)))).
-Ltac prove_InlineConst_Linearize_Compile_correct :=
+ constr:(ExprEta ((*Inline _*) ((*CSE _*) (InlineConst is_const (Linearize v))))).
+Ltac prove_ExprEta_InlineConst_Linearize_Compile_correct :=
fun _
=> intros;
+ rewrite ?InterpExprEta;
lazymatch goal with
- | [ |- ?R (@Syntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op ?t (InlineConst ?is_const (Linearize _))) _ ]
+ | [ |- ?R (@Syntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op ?t (InlineConst ?is_const (Linearize _)) ?x) _ ]
=> etransitivity;
[ apply (@InterpInlineConst base_type_code interp_base_type op interp_op is_const t);
reflect_Wf base_type_eq_semidec_is_dec op_beq_bl
@@ -50,4 +53,4 @@ Ltac prove_InlineConst_Linearize_Compile_correct :=
| prove_compile_correct () ] ]
end.
Ltac Reify_rhs :=
- Reflection.Reify.Reify_rhs_gen Reify prove_InlineConst_Linearize_Compile_correct interp_op ltac:(fun tac => tac ()).
+ Reflection.Reify.Reify_rhs_gen Reify prove_ExprEta_InlineConst_Linearize_Compile_correct interp_op ltac:(fun tac => tac ()).
diff --git a/src/Reflection/Z/Syntax.v b/src/Reflection/Z/Syntax.v
index 2060c6852..9b009386c 100644
--- a/src/Reflection/Z/Syntax.v
+++ b/src/Reflection/Z/Syntax.v
@@ -16,17 +16,18 @@ Definition interp_base_type (v : base_type) : Type :=
end.
Inductive op : flat_type base_type -> flat_type base_type -> Type :=
-| OpConst (z : Z) : op Unit tZ
-| Add : op (tZ * tZ) tZ
-| Sub : op (tZ * tZ) tZ
-| Mul : op (tZ * tZ) tZ
-| Shl : op (tZ * tZ) tZ
-| Shr : op (tZ * tZ) tZ
-| Land : op (tZ * tZ) tZ
-| Lor : op (tZ * tZ) tZ
-| Neg (int_width : Z) : op tZ tZ
-| Cmovne : op (tZ * tZ * tZ * tZ) tZ
-| Cmovle : op (tZ * tZ * tZ * tZ) tZ.
+| OpConst {T} (z : interp_base_type T) : op Unit (Tbase T)
+| Add T : op (Tbase T * Tbase T) (Tbase T)
+| Sub T : op (Tbase T * Tbase T) (Tbase T)
+| Mul T : op (Tbase T * Tbase T) (Tbase T)
+| Shl T : op (Tbase T * Tbase T) (Tbase T)
+| Shr T : op (Tbase T * Tbase T) (Tbase T)
+| Land T : op (Tbase T * Tbase T) (Tbase T)
+| Lor T : op (Tbase T * Tbase T) (Tbase T)
+| Neg T (int_width : Z) : op (Tbase T) (Tbase T)
+| Cmovne T : op (Tbase T * Tbase T * Tbase T * Tbase T) (Tbase T)
+| Cmovle T : op (Tbase T * Tbase T * Tbase T * Tbase T) (Tbase T)
+| Cast T1 T2 : op (Tbase T1) (Tbase T2).
Definition interpToZ {t} : interp_base_type t -> Z
:= match t with
@@ -45,15 +46,16 @@ Local Notation eta4 x := (eta3 (fst x), snd x).
Definition interp_op src dst (f : op src dst) : interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst
:= match f in op src dst return interp_flat_type interp_base_type src -> interp_flat_type interp_base_type dst with
- | OpConst v => fun _ => v
- | Add => fun xy => fst xy + snd xy
- | Sub => fun xy => fst xy - snd xy
- | Mul => fun xy => fst xy * snd xy
- | Shl => fun xy => Z.shiftl (fst xy) (snd xy)
- | Shr => fun xy => Z.shiftr (fst xy) (snd xy)
- | Land => fun xy => Z.land (fst xy) (snd xy)
- | Lor => fun xy => Z.lor (fst xy) (snd xy)
- | Neg int_width => fun x => ModularBaseSystemListZOperations.neg int_width x
- | Cmovne => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
- | Cmovle => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovl x y z w
+ | OpConst _ v => fun _ => v
+ | Add TZ => fun xy => fst xy + snd xy
+ | Sub TZ => fun xy => fst xy - snd xy
+ | Mul TZ => fun xy => fst xy * snd xy
+ | Shl TZ => fun xy => Z.shiftl (fst xy) (snd xy)
+ | Shr TZ => fun xy => Z.shiftr (fst xy) (snd xy)
+ | Land TZ => fun xy => Z.land (fst xy) (snd xy)
+ | Lor TZ => fun xy => Z.lor (fst xy) (snd xy)
+ | Neg TZ int_width => fun x => ModularBaseSystemListZOperations.neg int_width x
+ | Cmovne TZ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovne x y z w
+ | Cmovle TZ => fun xyzw => let '(x, y, z, w) := eta4 xyzw in cmovl x y z w
+ | Cast _ _ => cast_const
end%Z.
diff --git a/src/Reflection/Z/Syntax/Equality.v b/src/Reflection/Z/Syntax/Equality.v
index 3043deae1..ff3ed9b67 100644
--- a/src/Reflection/Z/Syntax/Equality.v
+++ b/src/Reflection/Z/Syntax/Equality.v
@@ -1,10 +1,15 @@
Require Import Coq.ZArith.ZArith.
Require Import Crypto.Reflection.Syntax.
+Require Import Crypto.Reflection.TypeInversion.
Require Import Crypto.Reflection.Equality.
Require Import Crypto.Reflection.Z.Syntax.
Require Import Crypto.Util.Decidable.
Require Import Crypto.Util.PartiallyReifiedProp.
Require Import Crypto.Util.HProp.
+Require Import Crypto.Util.Tactics.BreakMatch.
+Require Import Crypto.Util.Tactics.DestructHead.
+Require Import Crypto.Util.FixedWordSizesEquality.
+Require Import Crypto.Util.NatUtil.
Global Instance dec_eq_base_type : DecidableRel (@eq base_type)
:= base_type_eq_dec.
@@ -13,46 +18,69 @@ Global Instance dec_eq_type : DecidableRel (@eq (type base_type)) := _.
Definition base_type_eq_semidec_transparent (t1 t2 : base_type)
: option (t1 = t2)
- := Some (match t1, t2 return t1 = t2 with
- | TZ, TZ => eq_refl
- end).
+ := match base_type_eq_dec t1 t2 with
+ | left pf => Some pf
+ | right _ => None
+ end.
Lemma base_type_eq_semidec_is_dec t1 t2 : base_type_eq_semidec_transparent t1 t2 = None -> t1 <> t2.
Proof.
- unfold base_type_eq_semidec_transparent; congruence.
+ unfold base_type_eq_semidec_transparent; break_match; congruence.
Qed.
-Definition op_beq_hetero {t1 tR t1' tR'} (f : op t1 tR) (g : op t1' tR') : reified_Prop
+Definition op_beq_hetero {t1 tR t1' tR'} (f : op t1 tR) (g : op t1' tR') : bool
:= match f, g return bool with
- | OpConst v, OpConst v' => Z.eqb v v'
- | OpConst _, _ => false
- | Add, Add => true
- | Add, _ => false
- | Sub, Sub => true
- | Sub, _ => false
- | Mul, Mul => true
- | Mul, _ => false
- | Shl, Shl => true
- | Shl, _ => false
- | Shr, Shr => true
- | Shr, _ => false
- | Land, Land => true
- | Land, _ => false
- | Lor, Lor => true
- | Lor, _ => false
- | Neg n, Neg m => Z.eqb n m
- | Neg _, _ => false
- | Cmovne, Cmovne => true
- | Cmovne, _ => false
- | Cmovle, Cmovle => true
- | Cmovle, _ => false
- end.
+ | OpConst TZ v, OpConst TZ v' => Z.eqb v v'
+ | OpConst _ _, _ => false
+ | Add T1, Add T2
+ | Sub T1, Sub T2
+ | Mul T1, Mul T2
+ | Shl T1, Shl T2
+ | Shr T1, Shr T2
+ | Land T1, Land T2
+ | Lor T1, Lor T2
+ | Cmovne T1, Cmovne T2
+ | Cmovle T1, Cmovle T2
+ => base_type_beq T1 T2
+ | Neg T1 n, Neg T2 m
+ => base_type_beq T1 T2 && Z.eqb n m
+ | Cast T1 T2, Cast T1' T2'
+ => base_type_beq T1 T1' && base_type_beq T2 T2'
+ | Add _, _ => false
+ | Sub _, _ => false
+ | Mul _, _ => false
+ | Shl _, _ => false
+ | Shr _, _ => false
+ | Land _, _ => false
+ | Lor _, _ => false
+ | Neg _ _, _ => false
+ | Cmovne _, _ => false
+ | Cmovle _, _ => false
+ | Cast _ _, _ => false
+ end%bool.
-Definition op_beq t1 tR (f g : op t1 tR) : reified_Prop
+Definition op_beq t1 tR (f g : op t1 tR) : bool
:= Eval cbv [op_beq_hetero] in op_beq_hetero f g.
Definition op_beq_hetero_type_eq {t1 tR t1' tR'} f g : to_prop (@op_beq_hetero t1 tR t1' tR' f g) -> t1 = t1' /\ tR = tR'.
Proof.
- destruct f, g; simpl; try solve [ repeat constructor | intros [] ].
+ destruct f, g;
+ repeat match goal with
+ | _ => progress unfold op_beq_hetero in *
+ | _ => simpl; intro; exfalso; assumption
+ | _ => solve [ repeat constructor ]
+ | _ => progress destruct_head base_type
+ | [ |- context[reified_Prop_of_bool ?b] ]
+ => let H := fresh in destruct (Sumbool.sumbool_of_bool b) as [H|H]; rewrite H
+ | [ H : nat_beq _ _ = true |- _ ] => apply internal_nat_dec_bl in H; subst
+ | [ H : wordT_beq_hetero _ _ = true |- _ ] => apply wordT_beq_bl in H; subst
+ | [ H : wordT_beq_hetero _ _ = true |- _ ] => apply wordT_beq_hetero_bl in H; destruct H; subst
+ | [ H : andb ?x ?y = true |- _ ]
+ => assert (x = true /\ y = true) by (destruct x, y; simpl in *; repeat constructor; exfalso; clear -H; abstract congruence);
+ clear H
+ | [ H : and _ _ |- _ ] => destruct H
+ | [ H : false = true |- _ ] => exfalso; clear -H; abstract congruence
+ | [ H : true = false |- _ ] => exfalso; clear -H; abstract congruence
+ end.
Defined.
Definition op_beq_hetero_type_eqs {t1 tR t1' tR'} f g : to_prop (@op_beq_hetero t1 tR t1' tR' f g) -> t1 = t1'
@@ -68,22 +96,29 @@ Definition op_beq_hetero_eq {t1 tR t1' tR'} f g
_ (op_beq_hetero_type_eqs f g pf)
= g.
Proof.
- destruct f, g; simpl; try solve [ reflexivity | intros [] ];
- unfold op_beq_hetero; simpl;
- repeat match goal with
- | [ |- context[to_prop (reified_Prop_of_bool ?x)] ]
- => destruct (Sumbool.sumbool_of_bool x) as [P|P]
- | [ H : NatUtil.nat_beq _ _ = true |- _ ]
- => apply NatUtil.internal_nat_dec_bl in H
- | [ H : Z.eqb _ _ = true |- _ ]
- => apply Z.eqb_eq in H
- | _ => progress subst
- | _ => reflexivity
- | [ H : ?x = false |- context[reified_Prop_of_bool ?x] ]
- => rewrite H
- | _ => progress simpl @to_prop
- | _ => tauto
- end.
+ destruct f, g;
+ repeat match goal with
+ | _ => solve [ intros [] ]
+ | _ => reflexivity
+ | [ H : False |- _ ] => exfalso; assumption
+ | _ => intro
+ | [ |- context[op_beq_hetero_type_eqd ?f ?g ?pf] ]
+ => generalize (op_beq_hetero_type_eqd f g pf), (op_beq_hetero_type_eqs f g pf)
+ | _ => intro
+ | _ => progress eliminate_hprop_eq
+ | _ => progress inversion_flat_type
+ | _ => progress unfold op_beq_hetero in *
+ | _ => progress simpl in *
+ | [ H : context[andb ?x ?y] |- _ ]
+ => destruct x eqn:?, y eqn:?; simpl in H
+ | [ H : Z.eqb _ _ = true |- _ ] => apply Z.eqb_eq in H
+ | [ H : to_prop (reified_Prop_of_bool ?b) |- _ ] => destruct b eqn:?; compute in H
+ | _ => progress subst
+ | _ => progress break_match_hyps
+ | [ H : wordT_beq_hetero _ _ = true |- _ ] => apply wordT_beq_bl in H; subst
+ | [ H : wordT_beq_hetero _ _ = true |- _ ] => apply wordT_beq_hetero_bl in H; destruct H; subst
+ | _ => congruence
+ end.
Qed.
Lemma op_beq_bl : forall t1 tR x y, to_prop (op_beq t1 tR x y) -> x = y.
diff --git a/src/Reflection/Z/Syntax/Util.v b/src/Reflection/Z/Syntax/Util.v
index 42569daf8..1d591658f 100644
--- a/src/Reflection/Z/Syntax/Util.v
+++ b/src/Reflection/Z/Syntax/Util.v
@@ -1,4 +1,5 @@
Require Import Crypto.Reflection.Syntax.
+Require Import Crypto.Reflection.Wf.
Require Import Crypto.Reflection.TypeUtil.
Require Import Crypto.Reflection.TypeInversion.
Require Import Crypto.Reflection.Z.Syntax.
@@ -9,17 +10,85 @@ Require Import Crypto.Util.Tactics.DestructHead.
Require Import Crypto.Util.Notations.
Definition make_const t : interp_base_type t -> op Unit (Tbase t)
- := match t with TZ => OpConst end.
+ := OpConst.
Definition is_const s d (v : op s d) : bool
- := match v with OpConst _ => true | _ => false end.
+ := match v with OpConst _ _ => true | _ => false end.
Arguments is_const [s d] v.
Definition is_cast s d (v : op s d) : bool
- := false.
+ := match v with Cast _ _ => true | _ => false end.
Arguments is_cast [s d] v.
Definition base_type_leb (v1 v2 : base_type) : bool
- := true.
+ := match v1, v2 with
+ | _, TZ => true
+ end.
Definition base_type_min := base_type_min base_type_leb.
Global Arguments base_type_min !_ !_ / .
Global Arguments TypeUtil.base_type_min _ _ _ / .
+
+Definition Castb {var} A A' (v : exprf base_type op (var:=var) (Tbase A))
+ : exprf base_type op (var:=var) (Tbase A')
+ := Op (Cast A A') v.
+
+Local Notation Se opv := (Some (existT _ (_, _) opv)) (only parsing).
+
+Definition genericize_op src dst (opc : op src dst) (t_in t_out : base_type)
+ : option { src'dst' : _ & op (fst src'dst') (snd src'dst') }
+ := match opc with
+ | OpConst T z => Se (OpConst z)
+ | Add T => Se (Add t_out)
+ | Sub T => Se (Sub t_in)
+ | Mul T => Se (Mul t_out)
+ | Shl T => Se (Shl t_out)
+ | Shr T => Se (Shr t_in)
+ | Land T => Se (Land t_out)
+ | Lor T => Se (Lor t_out)
+ | Neg T int_width => Se (Neg t_out int_width)
+ | Cmovne T => Se (Cmovne t_out)
+ | Cmovle T => Se (Cmovle t_out)
+ | Cast T1 T2 => None
+ end.
+
+Lemma cast_const_id {t} v
+ : @cast_const t t v = v.
+Proof.
+ destruct t; simpl; trivial.
+Qed.
+
+Lemma cast_const_idempotent {a b c} v
+ : base_type_min b (base_type_min a c) = base_type_min a c
+ -> @cast_const b c (@cast_const a b v) = @cast_const a c v.
+Proof.
+ repeat first [ reflexivity
+ | congruence
+ | progress destruct_head' base_type
+ | progress simpl
+ | progress break_match
+ | progress subst
+ | intro
+ | match goal with
+ | [ H : ?leb _ _ = true |- _ ] => apply Compare_dec.leb_complete in H
+ | [ H : ?leb _ _ = false |- _ ] => apply Compare_dec.leb_iff_conv in H
+ end
+ | rewrite ZToWord_wordToZ_ZToWord by omega *
+ | rewrite wordToZ_ZToWord_wordToZ by omega * ].
+Qed.
+
+Lemma is_cast_correct s d opc
+ : forall e,
+ @is_cast (Tbase s) (Tbase d) opc = true
+ -> Syntax.interp_op _ _ opc (interpf Syntax.interp_op e)
+ = interpf Syntax.interp_op (Castb s d e).
+Proof.
+ preinvert_one_type opc; intros ? opc.
+ pose (fun x y => op y x) as op'.
+ change op with (fun x y => op' y x) in opc; cbv beta in opc.
+ preinvert_one_type opc; intros ? opc; subst op'; cbv beta in *.
+ destruct opc; try exact I; simpl; try congruence.
+Qed.
+
+Lemma wff_Castb {var1 var2 G A A'} {e1 e2 : exprf base_type op (Tbase A)}
+ (Hwf : wff (var1:=var1) (var2:=var2) G e1 e2)
+ : wff G (Castb A A' e1) (Castb A A' e2).
+Proof. constructor; assumption. Qed.