aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Assembly/WordizeUtil.v22
-rw-r--r--src/Reflection/Z/Interpretations.v94
-rw-r--r--src/Util/WordUtil.v371
-rw-r--r--src/Util/ZUtil.v38
4 files changed, 478 insertions, 47 deletions
diff --git a/src/Assembly/WordizeUtil.v b/src/Assembly/WordizeUtil.v
index 2727bac07..b5f246fb1 100644
--- a/src/Assembly/WordizeUtil.v
+++ b/src/Assembly/WordizeUtil.v
@@ -252,6 +252,12 @@ Section Misc.
apply N.sub_le_mono_l.
apply N_ge_0.
Qed.
+
+ Lemma log2_conv: forall z, Z.log2 z = Z.of_N (N.log2 (Z.to_N z)).
+ Proof.
+ intro z; induction z as [| |p]; auto.
+ induction p; auto.
+ Qed.
End Misc.
Section Exp.
@@ -348,7 +354,6 @@ Section Exp.
apply N.mul_le_mono_l.
assumption.
Qed.
-
End Exp.
Section Conversions.
@@ -923,6 +928,21 @@ Section TopLevel.
reflexivity.
Qed.
+ Lemma wordize_or: forall {n} (x y: word n),
+ & (wor x y) = N.lor (&x) (&y).
+ Proof.
+ intros.
+ apply N.bits_inj_iff; unfold N.eqf; intro k.
+ rewrite N.lor_spec.
+ repeat rewrite wordToN_testbit.
+ revert x y.
+ generalize (N.to_nat k) as k'; clear k.
+ induction n; intros; shatter x; shatter y; simpl; [reflexivity|].
+ induction k'; [reflexivity|].
+ rewrite IHn.
+ reflexivity.
+ Qed.
+
Lemma conv_mask: forall {n} (x: word n) (k: nat),
(k <= n)%nat ->
mask k x = x ^& (NToWord _ (N.ones (N.of_nat k))).
diff --git a/src/Reflection/Z/Interpretations.v b/src/Reflection/Z/Interpretations.v
index 8d0ab0c1b..336376c9e 100644
--- a/src/Reflection/Z/Interpretations.v
+++ b/src/Reflection/Z/Interpretations.v
@@ -1,5 +1,7 @@
(** * Interpretation of PHOAS syntax for expression trees on ℤ *)
+Require Import Bedrock.Nomega.
Require Import Coq.ZArith.ZArith.
+Require Import Coq.NArith.NArith.
Require Import Crypto.Reflection.Z.Syntax.
Require Import Crypto.Reflection.Syntax.
Require Import Crypto.Reflection.Application.
@@ -12,8 +14,11 @@ Require Crypto.Util.HList.
Require Import Crypto.Util.Bool.
Require Import Crypto.Util.Prod.
Require Import Crypto.Util.Tactics.
-Require Import Bedrock.Word.
Require Import Crypto.Util.WordUtil.
+Require Import Bedrock.Word.
+Require Import Crypto.Assembly.WordizeUtil.
+Require Import Crypto.Assembly.Evaluables.
+Require Import Crypto.Assembly.QhasmUtil.
Export Reflection.Syntax.Notations.
Local Notation eta x := (fst x, snd x).
@@ -210,17 +215,38 @@ Module Word64.
:= (forall x y z w,
bounds_statement (wop x y z w) (Zop (word64ToZ x) (word64ToZ y) (word64ToZ z) (word64ToZ w))).
+ Require Import Crypto.Assembly.WordizeUtil.
+
Lemma word64ToZ_add : bounds_2statement add Z.add. Proof. w64ToZ_t. Qed.
Lemma word64ToZ_sub : bounds_2statement sub Z.sub. Proof. w64ToZ_t. Qed.
Lemma word64ToZ_mul : bounds_2statement mul Z.mul. Proof. w64ToZ_t. Qed.
+
Lemma word64ToZ_shl : bounds_2statement shl Z.shiftl.
- Proof. w64ToZ_t. admit. Admitted.
+ Proof.
+ w64ToZ_t; w64ToZ_extra_t; unfold word64ToZ, wordBin.
+ rewrite wordToN_NToWord; [rewrite <- Z.N2Z.inj_shiftl; reflexivity|].
+ apply N2Z.inj_lt.
+ rewrite Z.N2Z.inj_shiftl.
+ destruct (Z.lt_ge_cases 0 ((word64ToZ x) << (word64ToZ y)))%Z;
+ [|eapply Z.le_lt_trans; [|apply N2Z.inj_lt, Npow2_gt0]; assumption].
+ rewrite Npow2_N, N2Z.inj_pow.
+ apply Z.log2_lt_pow2; assumption.
+ Qed.
+
Lemma word64ToZ_shr : bounds_2statement shr Z.shiftr.
- Proof. admit. Admitted.
- Lemma word64ToZ_land : bounds_2statement land Z.land.
- Proof. w64ToZ_t. Qed.
- Lemma word64ToZ_lor : bounds_2statement lor Z.lor.
- Proof. w64ToZ_t. Qed.
+ Proof.
+ w64ToZ_t; w64ToZ_extra_t; unfold word64ToZ, wordBin.
+ rewrite wordToN_NToWord; [rewrite <- Z.N2Z.inj_shiftr; reflexivity|].
+ apply N2Z.inj_lt.
+ rewrite Z.N2Z.inj_shiftr.
+ destruct (Z.lt_ge_cases 0 ((word64ToZ x) >> (word64ToZ y)))%Z;
+ [|eapply Z.le_lt_trans; [|apply N2Z.inj_lt, Npow2_gt0]; assumption].
+ rewrite Npow2_N, N2Z.inj_pow.
+ apply Z.log2_lt_pow2; assumption.
+ Qed.
+
+ Lemma word64ToZ_land : bounds_2statement land Z.land. Proof. w64ToZ_t. Qed.
+ Lemma word64ToZ_lor : bounds_2statement lor Z.lor. Proof. w64ToZ_t. Qed.
Lemma word64ToZ_neg : bounds_2statement neg ModularBaseSystemListZOperations.neg.
Proof. w64ToZ_t; w64ToZ_extra_t. Qed.
Lemma word64ToZ_cmovne : bounds_4statement cmovne ModularBaseSystemListZOperations.cmovne.
@@ -330,6 +356,7 @@ Module ZBounds.
end
| _, _, _, _ => None
end%Z.
+
Definition add' : bounds -> bounds -> bounds
:= fun x y => let (lx, ux) := x in let (ly, uy) := y in {| lower := lx + ly ; upper := ux + uy |}.
Definition add : t -> t -> t := t_map2 add'.
@@ -345,6 +372,7 @@ Module ZBounds.
Definition shr' : bounds -> bounds -> bounds
:= fun x y => let (lx, ux) := x in let (ly, uy) := y in {| lower := lx >> uy ; upper := ux >> ly |}.
Definition shr : t -> t -> t := t_map2 shr'.
+
Definition land' : bounds -> bounds -> bounds
:= fun x y => let (lx, ux) := x in let (ly, uy) := y in {| lower := 0 ; upper := Z.min ux uy |}.
Definition land : t -> t -> t := t_map2 land'.
@@ -625,6 +653,7 @@ Module BoundedWord64.
Axiom proof_admitted : False.
Local Opaque Word64.bit_width.
Hint Resolve Z.ones_nonneg : zarith.
+
Local Ltac t_start :=
repeat first [ match goal with
| [ |- forall x y l u, ?opB (Some (BoundedWordToBounds x)) (Some (BoundedWordToBounds y)) = Some _ -> let val := ?opW (value x) (value y) in _ ]
@@ -650,15 +679,10 @@ Module BoundedWord64.
| progress autorewrite with push_word64ToZ
| progress repeat apply conj
| solve [ Word64.arith ]
- | match goal with
- | [ |- appcontext[Z.min ?x ?y] ]
- => apply (Z.min_case_strong x y)
- | [ |- appcontext[Z.max ?x ?y] ]
- => apply (Z.max_case_strong x y)
- end
| progress destruct_head' or ].
- Tactic Notation "admit" := abstract case proof_admitted.
+ Ltac ktrans k := do k (etransitivity; [|eassumption]); assumption.
+ Ltac trans' := first [ assumption | ktrans ltac:1 | ktrans ltac:2 ].
(** TODO(jadep): Use the bounds lemma here to prove that if each
@@ -684,46 +708,54 @@ Module BoundedWord64.
(Tuple.map BoundedWordToBounds y) (Tuple.map BoundedWordToBounds z))).
Proof. Admitted.
+ Local Ltac kill_assumptions :=
+ repeat split; abstract (cbn; assumption).
+
+ (* TODO (rsloan): not entirely sure what's the best way to match on these... *)
+ Local Ltac apply_update lem lower0 value0 upper0 lower1 value1 upper1 := first
+ [ apply (lem 64 lower1 value1 upper1 lower0 value0 upper0); kill_assumptions
+ | apply (lem 64 lower0 value0 upper0 lower1 value1 upper1); kill_assumptions].
Definition add : t -> t -> t.
Proof.
- refine (t_map2 Word64.add ZBounds.add _); t_start; admit.
+ refine (t_map2 Word64.add ZBounds.add _); t_start;
+ apply_update @add_valid_update lower0 value0 upper0 lower1 value1 upper1.
Defined.
Definition sub : t -> t -> t.
Proof.
refine (t_map2 Word64.sub ZBounds.sub _); t_start;
- admit.
+ apply_update @sub_valid_update lower0 value0 upper0 lower1 value1 upper1.
Defined.
Definition mul : t -> t -> t.
Proof.
refine (t_map2 Word64.mul ZBounds.mul _); t_start;
- admit.
+ apply_update @mul_valid_update lower0 value0 upper0 lower1 value1 upper1.
Defined.
- Definition shl : t -> t -> t.
+ Definition land : t -> t -> t.
Proof.
- refine (t_map2 Word64.shl ZBounds.shl _); t_start;
- admit.
- Defined.
+ refine (t_map2 Word64.land ZBounds.land _); t_start;
+ apply_update @land_valid_update lower0 value0 upper0 lower1 value1 upper1.
+ Qed.
- Definition shr : t -> t -> t.
+ Definition lor : t -> t -> t.
Proof.
- refine (t_map2 Word64.shr ZBounds.shr _); t_start;
- admit.
- Defined.
+ refine (t_map2 Word64.lor ZBounds.lor _); t_start;
+ apply_update @lor_valid_update lower0 value0 upper0 lower1 value1 upper1.
+ Qed.
- Definition land : t -> t -> t.
+ Definition shl : t -> t -> t.
Proof.
- refine (t_map2 Word64.land ZBounds.land _); t_start;
- admit.
+ refine (t_map2 Word64.shl ZBounds.shl _); t_start;
+ apply_update @shl_valid_update lower0 value0 upper0 lower1 value1 upper1.
Defined.
- Definition lor : t -> t -> t.
+ Definition shr : t -> t -> t.
Proof.
- refine (t_map2 Word64.lor ZBounds.lor _); t_start;
- admit.
+ refine (t_map2 Word64.shr ZBounds.shr _); t_start;
+ apply_update @shr_valid_update lower0 value0 upper0 lower1 value1 upper1.
Defined.
Definition neg : t -> t -> t.
diff --git a/src/Util/WordUtil.v b/src/Util/WordUtil.v
index 7a856f1e9..24160d83e 100644
--- a/src/Util/WordUtil.v
+++ b/src/Util/WordUtil.v
@@ -34,6 +34,15 @@ Proof.
auto.
Qed.
+Lemma Z_land_le : forall x y, (0 <= x)%Z -> (Z.land x y <= x)%Z.
+Proof.
+ intros; apply Z.ldiff_le; [assumption|].
+ rewrite Z.ldiff_land, Z.land_comm, Z.land_assoc.
+ rewrite <- Z.land_0_l with (a := y); f_equal.
+ rewrite Z.land_comm, Z.land_lnot_diag.
+ reflexivity.
+Qed.
+
Lemma wordToN_NToWord_idempotent : forall sz n, (n < Npow2 sz)%N ->
wordToN (NToWord sz n) = n.
Proof.
@@ -271,47 +280,379 @@ Proof.
end.
Qed.
-Local Notation bounds_2statement wop Zop
- := (forall {sz} (x y : word sz),
- (0 <= Zop (Z.of_N (wordToN x)) (Z.of_N (wordToN y))
- -> Z.log2 (Zop (Z.of_N (wordToN x)) (Z.of_N (wordToN y))) < Z.of_nat sz
- -> Z.of_N (wordToN (wop x y)) = (Zop (Z.of_N (wordToN x)) (Z.of_N (wordToN y))))%Z).
+Local Notation bounds_2statement wop Zop := (forall {sz} (x y : word sz),
+ (0 <= Zop (Z.of_N (wordToN x)) (Z.of_N (wordToN y))
+ -> (Z.log2 (Zop (Z.of_N (wordToN x)) (Z.of_N (wordToN y))) < Z.of_nat sz)
+ -> (Z.of_N (wordToN (wop x y)) = (Zop (Z.of_N (wordToN x)) (Z.of_N (wordToN y)))))%Z).
+
+Require Import Crypto.Assembly.WordizeUtil.
+Require Import Crypto.Assembly.Bounds.
Lemma wordToN_wplus : bounds_2statement (@wplus _) Z.add.
Proof.
- admit.
-Admitted.
+ intros.
+ rewrite <- wordize_plus; [rewrite N2Z.inj_add; reflexivity|].
+ destruct (N.eq_dec (wordToN x + wordToN y) 0%N) as [e|e];
+ [rewrite e; apply Npow2_gt0|].
+ apply N.neq_0_lt_0 in e.
+ apply N2Z.inj_lt in e.
+ apply N2Z.inj_lt.
+ rewrite N2Z.inj_add in *.
+ rewrite Npow2_N.
+ rewrite N2Z.inj_pow.
+ replace (Z.of_N 2%N) with 2%Z by auto.
+ apply Z.log2_lt_pow2; [auto|].
+ rewrite nat_N_Z.
+ assumption.
+Qed.
+
Hint Rewrite @wordToN_wplus using word_util_arith : push_wordToN.
Hint Rewrite <- @wordToN_wplus using word_util_arith : pull_wordToN.
Lemma wordToN_wminus : bounds_2statement (@wminus _) Z.sub.
Proof.
- admit.
-Admitted.
+ intros sz x y H ?.
+ assert (wordToN y <= wordToN x)%N. {
+ apply N2Z.inj_le.
+ rewrite <- (Z.add_0_l (Z.of_N (wordToN y))).
+ apply Z.le_add_le_sub_r; assumption.
+ }
+
+ rewrite <- N2Z.inj_sub; [|assumption].
+ rewrite <- wordize_minus; [reflexivity|apply N.le_ge; assumption].
+Qed.
+
Hint Rewrite @wordToN_wminus using word_util_arith : push_wordToN.
Hint Rewrite <- @wordToN_wminus using word_util_arith : pull_wordToN.
Lemma wordToN_wmult : bounds_2statement (@wmult _) Z.mul.
Proof.
- admit.
-Admitted.
+ intros.
+ rewrite <- wordize_mult; [rewrite N2Z.inj_mul; reflexivity|].
+ destruct (N.eq_dec (wordToN x * wordToN y) 0%N) as [e|e];
+ [rewrite e; apply Npow2_gt0|].
+ apply N.neq_0_lt_0 in e.
+ apply N2Z.inj_lt in e.
+ apply N2Z.inj_lt.
+ rewrite N2Z.inj_mul in *.
+ rewrite Npow2_N.
+ rewrite N2Z.inj_pow.
+ replace (Z.of_N 2%N) with 2%Z by auto.
+ apply Z.log2_lt_pow2; [auto|].
+ rewrite nat_N_Z.
+ assumption.
+Qed.
+
Hint Rewrite @wordToN_wmult using word_util_arith : push_wordToN.
Hint Rewrite <- @wordToN_wmult using word_util_arith : pull_wordToN.
Lemma wordToN_wand : bounds_2statement (@wand _) Z.land.
Proof.
- admit.
-Admitted.
+ intros.
+ rewrite wordize_and.
+ apply Z.bits_inj_iff'; intros k Hpos; apply Z.le_ge in Hpos.
+ rewrite Z.land_spec.
+ rewrite Z2N.inj_testbit; [|apply Z.ge_le; assumption].
+ rewrite N.land_spec.
+ repeat (rewrite <- Z2N.inj_testbit; [|apply Z.ge_le; assumption]).
+ reflexivity.
+Qed.
Hint Rewrite @wordToN_wand using word_util_arith : push_wordToN.
Hint Rewrite <- @wordToN_wand using word_util_arith : pull_wordToN.
Lemma wordToN_wor : bounds_2statement (@wor _) Z.lor.
Proof.
- admit.
-Admitted.
+ intros.
+ rewrite wordize_or.
+ apply Z.bits_inj_iff'; intros k Hpos; apply Z.le_ge in Hpos.
+ rewrite Z.lor_spec.
+ rewrite Z2N.inj_testbit; [|apply Z.ge_le; assumption].
+ rewrite N.lor_spec.
+ repeat (rewrite <- Z2N.inj_testbit; [|apply Z.ge_le; assumption]).
+ reflexivity.
+Qed.
Hint Rewrite @wordToN_wor using word_util_arith : push_wordToN.
Hint Rewrite <- @wordToN_wor using word_util_arith : pull_wordToN.
+Local Notation bound n lower value upper := (
+ (0 <= lower)%Z
+ /\ (lower <= Z.of_N (@wordToN n value))%Z
+ /\ (Z.of_N (@wordToN n value) <= upper)%Z).
+
+Definition valid_update n lowerF valueF upperF : Prop :=
+ forall lower0 value0 upper0
+ lower1 value1 upper1,
+
+ bound n lower0 value0 upper0
+ -> bound n lower1 value1 upper1
+ -> (0 <= lowerF lower0 upper0 lower1 upper1)%Z
+ -> (Z.log2 (upperF lower0 upper0 lower1 upper1) < Z.of_nat n)%Z
+ -> bound n (lowerF lower0 upper0 lower1 upper1)
+ (valueF value0 value1)
+ (upperF lower0 upper0 lower1 upper1).
+
+Local Ltac add_mono :=
+ etransitivity; [| apply Z.add_le_mono_r; eassumption]; omega.
+
+Lemma add_valid_update: forall n,
+ valid_update n
+ (fun l0 u0 l1 u1 => l0 + l1)%Z
+ (@wplus n)
+ (fun l0 u0 l1 u1 => u0 + u1)%Z.
+Proof.
+ unfold valid_update; intros until upper1; intros B0 B1.
+ destruct B0 as [? B0], B1 as [? B1], B0, B1.
+ repeat split; [add_mono| |]; (
+ rewrite wordToN_wplus; [add_mono|add_mono|];
+ eapply Z.le_lt_trans; [| eassumption];
+ apply Z.log2_le_mono; add_mono).
+Qed.
+
+Local Ltac sub_mono :=
+ etransitivity;
+ [| apply Z.sub_le_mono_r]; eauto;
+ first [ reflexivity
+ | apply Z.sub_le_mono_l; assumption
+ | apply Z.le_add_le_sub_l; etransitivity; [|eassumption];
+ repeat rewrite Z.add_0_r; assumption].
+
+Lemma sub_valid_update: forall n,
+ valid_update n
+ (fun l0 u0 l1 u1 => l0 - u1)%Z
+ (@wminus n)
+ (fun l0 u0 l1 u1 => u0 - l1)%Z.
+Proof.
+ unfold valid_update; intros until upper1; intros B0 B1.
+ destruct B0 as [? B0], B1 as [? B1], B0, B1.
+ repeat split; [sub_mono| |]; (
+ rewrite wordToN_wminus; [sub_mono|omega|];
+ eapply Z.le_lt_trans; [apply Z.log2_le_mono|eassumption]; sub_mono).
+Qed.
+
+Local Ltac mul_mono :=
+ etransitivity; [|apply Z.mul_le_mono_nonneg_r];
+ repeat first
+ [ eassumption
+ | reflexivity
+ | apply Z.mul_le_mono_nonneg_l
+ | rewrite Z.mul_0_l
+ | omega].
+
+Lemma mul_valid_update: forall n,
+ valid_update n
+ (fun l0 u0 l1 u1 => l0 * l1)%Z
+ (@wmult n)
+ (fun l0 u0 l1 u1 => u0 * u1)%Z.
+Proof.
+ unfold valid_update; intros until upper1; intros B0 B1.
+ destruct B0 as [? B0], B1 as [? B1], B0, B1.
+ repeat split; [mul_mono| |]; (
+ rewrite wordToN_wmult; [mul_mono|mul_mono|];
+ eapply Z.le_lt_trans; [| eassumption];
+ apply Z.log2_le_mono; mul_mono).
+Qed.
+
+Local Ltac solve_land_ge0 :=
+ apply Z.land_nonneg; left; etransitivity; [|eassumption]; assumption.
+
+Local Ltac land_mono :=
+ first [assumption | etransitivity; [|eassumption]; assumption].
+
+Lemma land_valid_update: forall n,
+ valid_update n
+ (fun l0 u0 l1 u1 => 0)%Z
+ (@wand n)
+ (fun l0 u0 l1 u1 => Z.min u0 u1)%Z.
+Proof.
+ unfold valid_update; intros until upper1; intros B0 B1.
+ destruct B0 as [? B0], B1 as [? B1], B0, B1.
+ repeat split; [reflexivity| |].
+
+ - rewrite wordToN_wand; [solve_land_ge0|solve_land_ge0|].
+ eapply Z.le_lt_trans; [apply Z.log2_land; land_mono|];
+ eapply Z.le_lt_trans; [| eassumption];
+ repeat match goal with
+ | [|- context[Z.min ?a ?b]] =>
+ destruct (Z.min_dec a b) as [g|g]; rewrite g; clear g
+ end; apply Z.log2_le_mono; try assumption.
+
+ admit. admit.
+
+ - rewrite wordToN_wand; [|solve_land_ge0|].
+ eapply Z.le_lt_trans; [apply Z.log2_land; land_mono|];
+ match goal with
+ | [|- (Z.min ?a ?b < _)%Z] =>
+ destruct (Z.min_dec a b) as [g|g]; rewrite g; clear g
+ end.
+
+ .
+ (*
+[apply N2Z.is_nonneg|];
+ unfold Word64.word64ToZ; repeat rewrite wordToN_NToWord; repeat rewrite Z2N.id;
+ rewrite wordize_and.
+
+ destruct (Z_ge_dec upper1 upper0) as [g|g].
+
+ - rewrite Z.min_r; [|abstract (apply Z.log2_le_mono; omega)].
+ abstract (
+ rewrite (land_intro_ones (wordToN value0));
+ rewrite N.land_assoc;
+ etransitivity; [apply N2Z.inj_le; apply N.lt_le_incl; apply land_lt_Npow2|];
+ rewrite N2Z.inj_pow;
+ apply Z.pow_le_mono; [abstract (split; cbn; [omega|reflexivity])|];
+ unfold getBits; rewrite N2Z.inj_succ;
+ apply -> Z.succ_le_mono;
+ rewrite <- (N2Z.id (wordToN value0)), <- log2_conv;
+ apply Z.log2_le_mono;
+ etransitivity; [eassumption|reflexivity]).
+
+ - rewrite Z.min_l; [|abstract (apply Z.log2_le_mono; omega)].
+ abstract (
+ rewrite (land_intro_ones (wordToN value1));
+ rewrite <- N.land_comm, N.land_assoc;
+ etransitivity; [apply N2Z.inj_le; apply N.lt_le_incl; apply land_lt_Npow2|];
+ rewrite N2Z.inj_pow;
+ apply Z.pow_le_mono; [abstract (split; cbn; [omega|reflexivity])|];
+ unfold getBits; rewrite N2Z.inj_succ;
+ apply -> Z.succ_le_mono;
+ rewrite <- (N2Z.id (wordToN value1)), <- log2_conv;
+ apply Z.log2_le_mono;
+ etransitivity; [eassumption|reflexivity]).
+
+*)
+Admitted.
+
+Lemma lor_valid_update: forall n,
+ valid_update n
+ (fun l0 u0 l1 u1 => Z.max l0 l1)%Z
+ (@wor n)
+ (fun l0 u0 l1 u1 => 2^(Z.max (Z.log2 (u0+1)) (Z.log2 (u1+1))) - 1)%Z.
+Proof.
+(* unfold Word64.word64ToZ in *; repeat rewrite wordToN_NToWord; repeat rewrite Z2N.id;
+ rewrite wordize_or.
+
+ - transitivity (Z.max (Z.of_N (wordToN value1)) (Z.of_N (wordToN value0)));
+ [ abstract (destruct
+ (Z_ge_dec lower1 lower0) as [l|l],
+ (Z_ge_dec (Z.of_N (& value1)%w) (Z.of_N (& value0)%w)) as [v|v];
+ [ rewrite Z.max_l, Z.max_l | rewrite Z.max_l, Z.max_r
+ | rewrite Z.max_r, Z.max_l | rewrite Z.max_r, Z.max_r ];
+
+ try (omega || assumption))
+ | ].
+
+ rewrite <- N2Z.inj_max.
+ apply Z2N.inj_le; [apply N2Z.is_nonneg|apply N2Z.is_nonneg|].
+ repeat rewrite N2Z.id.
+
+ abstract (
+ destruct (N.max_dec (wordToN value1) (wordToN value0)) as [v|v];
+ rewrite v;
+ apply N.ldiff_le, N.bits_inj_iff; intros k;
+ rewrite N.ldiff_spec, N.lor_spec;
+ induction (N.testbit (wordToN value1)), (N.testbit (wordToN value0)); simpl;
+ reflexivity).
+
+ - apply Z.lt_le_incl, Z.log2_lt_cancel.
+ rewrite Z.log2_pow2; [| abstract (
+ destruct (Z.max_dec (Z.log2 upper1) (Z.log2 upper0)) as [g|g];
+ rewrite g; apply Z.le_le_succ_r, Z.log2_nonneg)].
+
+ eapply (Z.le_lt_trans _ (Z.log2 (Z.lor _ _)) _).
+
+ + apply Z.log2_le_mono, Z.eq_le_incl.
+ apply Z.bits_inj_iff'; intros k Hpos.
+ rewrite Z2N.inj_testbit, Z.lor_spec, N.lor_spec; [|assumption].
+ repeat (rewrite <- Z2N.inj_testbit; [|assumption]).
+ reflexivity.
+
+ + abstract (
+ rewrite Z.log2_lor; [|trans'|trans'];
+ destruct
+ (Z_ge_dec (Z.of_N (wordToN value1)) (Z.of_N (wordToN value0))) as [g0|g0],
+ (Z_ge_dec upper1 upper0) as [g1|g1];
+ [ rewrite Z.max_l, Z.max_l
+ | rewrite Z.max_l, Z.max_r
+ | rewrite Z.max_r, Z.max_l
+ | rewrite Z.max_r, Z.max_r];
+ try apply Z.log2_le_mono; try omega;
+ apply Z.le_succ_l;
+ apply -> Z.succ_le_mono;
+ apply Z.log2_le_mono;
+ assumption || (etransitivity; [eassumption|]; omega)).
+*)
+Admitted.
+
+Lemma shr_valid_update: forall n,
+ valid_update n
+ (fun l0 u0 l1 u1 => Z.shiftr l0 u1)%Z
+ (@wordBin N.shiftr n)
+ (fun l0 u0 l1 u1 => Z.shiftr u0 l1)%Z.
+Proof.
+ (*
+ Ltac shr_mono := etransitivity;
+ [apply Z.div_le_compat_l | apply Z.div_le_mono].
+
+ assert (forall x, (0 <= x)%Z -> (0 < 2^x)%Z) as gt0. {
+ intros; rewrite <- (Z2Nat.id x); [|assumption].
+ induction (Z.to_nat x) as [|n]; [cbv; auto|].
+ eapply Z.lt_le_trans; [eassumption|rewrite Nat2Z.inj_succ].
+ apply Z.pow_le_mono_r; [cbv; auto|omega].
+ }
+
+ build_binop Word64.w64shr ZBounds.shr; t_start; abstract (
+ unfold Word64.word64ToZ; repeat rewrite wordToN_NToWord; repeat rewrite Z2N.id;
+ rewrite Z.shiftr_div_pow2 in *;
+ repeat match goal with
+ | [|- _ /\ _ ] => split
+ | [|- (0 <= 2 ^ _)%Z ] => apply Z.pow_nonneg
+ | [|- (0 < 2 ^ ?X)%Z ] => apply gt0
+ | [|- (0 <= _ / _)%Z ] => apply Z.div_le_lower_bound; [|rewrite Z.mul_0_r]
+ | [|- (2 ^ _ <= 2 ^ _)%Z ] => apply Z.pow_le_mono_r
+ | [|- context[(?a >> ?b)%Z]] => rewrite Z.shiftr_div_pow2 in *
+ | [|- (_ < Npow2 _)%N] =>
+ apply N2Z.inj_lt, Z.log2_lt_cancel; simpl;
+ eapply Z.le_lt_trans; [|eassumption]; apply Z.log2_le_mono; rewrite Z2N.id
+
+ | _ => progress shr_mono
+ | _ => progress trans'
+ | _ => progress omega
+ end).
+
+*)
+Admitted.
+
+Lemma shl_valid_update: forall n,
+ valid_update n
+ (fun l0 u0 l1 u1 => Z.shiftl l0 l1)%Z
+ (@wordBin N.shiftl n)
+ (fun l0 u0 l1 u1 => Z.shiftl u0 u1)%Z.
+Proof.
+ (*
+ Ltac shl_mono := etransitivity;
+ [apply Z.mul_le_mono_nonneg_l | apply Z.mul_le_mono_nonneg_r].
+
+ build_binop Word64.w64shl ZBounds.shl; t_start; abstract (
+ unfold Word64.word64ToZ; repeat rewrite wordToN_NToWord; repeat rewrite Z2N.id;
+ rewrite Z.shiftl_mul_pow2 in *;
+ repeat match goal with
+ | [|- (0 <= 2 ^ _)%Z ] => apply Z.pow_nonneg
+ | [|- (0 <= _ * _)%Z ] => apply Z.mul_nonneg_nonneg
+ | [|- (2 ^ _ <= 2 ^ _)%Z ] => apply Z.pow_le_mono_r
+ | [|- context[(?a << ?b)%Z]] => rewrite Z.shiftl_mul_pow2
+ | [|- (_ < Npow2 _)%N] =>
+ apply N2Z.inj_lt, Z.log2_lt_cancel; simpl;
+ eapply Z.le_lt_trans; [|eassumption]; apply Z.log2_le_mono; rewrite Z2N.id
+
+ | _ => progress shl_mono
+ | _ => progress trans'
+ | _ => progress omega
+ end).
+
+*)
+Admitted.
+
+
Axiom wlast : forall sz, word (sz+1) -> bool. Arguments wlast {_} _.
Axiom winit : forall sz, word (sz+1) -> word sz. Arguments winit {_} _.
Axiom combine_winit_wlast : forall {sz} a b (c:word (sz+1)),
diff --git a/src/Util/ZUtil.v b/src/Util/ZUtil.v
index 17e8d62bf..d6ffa4a53 100644
--- a/src/Util/ZUtil.v
+++ b/src/Util/ZUtil.v
@@ -2911,6 +2911,44 @@ for name in names:
Module RemoveEquivModuloInstances (dummy : Nop).
Global Remove Hints equiv_modulo_Reflexive equiv_modulo_Symmetric equiv_modulo_Transitive mul_mod_Proper add_mod_Proper sub_mod_Proper opp_mod_Proper modulo_equiv_modulo_Proper eq_to_ProperProxy : typeclass_instances.
End RemoveEquivModuloInstances.
+
+ Module N2Z.
+ Require Import Coq.NArith.NArith.
+
+ Lemma inj_shiftl: forall x y, Z.of_N (N.shiftl x y) = Z.shiftl (Z.of_N x) (Z.of_N y).
+ Proof.
+ intros.
+ apply Z.bits_inj_iff'; intros k Hpos.
+ rewrite Z2N.inj_testbit; [|assumption].
+ rewrite Z.shiftl_spec; [|assumption].
+
+ assert ((Z.to_N k) >= y \/ (Z.to_N k) < y)%N as g by (
+ unfold N.ge, N.lt; induction (N.compare (Z.to_N k) y); [left|auto|left];
+ intro H; inversion H).
+
+ destruct g as [g|g];
+ [ rewrite N.shiftl_spec_high; [|apply N2Z.inj_le; rewrite Z2N.id|apply N.ge_le]
+ | rewrite N.shiftl_spec_low]; try assumption.
+
+ - rewrite <- N2Z.inj_testbit; f_equal.
+ rewrite N2Z.inj_sub, Z2N.id; [reflexivity|assumption|apply N.ge_le; assumption].
+
+ - apply N2Z.inj_lt in g.
+ rewrite Z2N.id in g; [symmetry|assumption].
+ apply Z.testbit_neg_r; omega.
+ Qed.
+
+ Lemma inj_shiftr: forall x y, Z.of_N (N.shiftr x y) = Z.shiftr (Z.of_N x) (Z.of_N y).
+ Proof.
+ intros.
+ apply Z.bits_inj_iff'; intros k Hpos.
+ rewrite Z2N.inj_testbit; [|assumption].
+ rewrite Z.shiftr_spec, N.shiftr_spec; [|apply N2Z.inj_le; rewrite Z2N.id|]; try assumption.
+ rewrite <- N2Z.inj_testbit; f_equal.
+ rewrite N2Z.inj_add; f_equal.
+ apply Z2N.id; assumption.
+ Qed.
+ End N2Z.
End Z.
Module Export BoundsTactics.