Require Import BinInt. Require Import Lia. Require Import ZBinary. From bbv Require Import ZLib. From compcert Require Import Integers Coqlib. Require Import Vericertlib. Local Open Scope Z_scope. Module PtrofsExtra. Ltac ptrofs_mod_match m := match goal with | [ H : ?x = 0 |- context[?x] ] => rewrite H | [ _ : _ |- context[_ - 0] ] => rewrite Z.sub_0_r | [ _ : _ |- context[0 + _] ] => rewrite Z.add_0_l | [ _ : _ |- context[_ + 0] ] => rewrite Z.add_0_r | [ _ : _ |- context[0 * _] ] => rewrite Z.mul_0_l | [ _ : _ |- context[_ * 0] ] => rewrite Z.mul_0_r | [ _ : _ |- context[?m mod ?m] ] => rewrite Z_mod_same_full with (a := m) | [ _ : _ |- context[0 mod _] ] => rewrite Z.mod_0_l | [ _ : _ |- context[(_ mod ?m) mod ?m] ] => rewrite Zmod_mod | [ _ : _ |- context[(_ mod Ptrofs.modulus) mod m ] ] => rewrite <- Zmod_div_mod; try (crush; lia || assumption) | [ _ : _ |- context[Ptrofs.modulus mod m] ] => rewrite Zdivide_mod with (a := Ptrofs.modulus); try (lia || assumption) | [ _ : _ |- context[Ptrofs.signed ?a mod Ptrofs.modulus] ] => rewrite Z.mod_small with (a := Ptrofs.signed a) (b := Ptrofs.modulus) | [ _ : _ |- context[(?x - ?y) mod ?m] ] => rewrite Zminus_mod with (a := x) (b := y) (n := m) | [ _ : _ |- context[((?x + ?y) mod ?m) + _] ] => rewrite Zplus_mod with (a := x) (b := y) (n := m) | [ _ : _ |- context[(?x + ?y) mod ?m] ] => rewrite Zplus_mod with (a := x) (b := y) (n := m) | [ _ : _ |- context[(?x * ?y) mod ?m] ] => rewrite Zmult_mod with (a := x) (b := y) (n := m) end. Ltac ptrofs_mod_tac m := repeat (ptrofs_mod_match m); lia. Lemma signed_mod_unsigned_mod : forall x m, 0 < m -> Ptrofs.modulus mod m = 0 -> Ptrofs.signed x mod m = 0 -> Ptrofs.unsigned x mod m = 0. Proof. intros. repeat match goal with | [ _ : _ |- context[if ?x then _ else _] ] => destruct x | [ _ : _ |- context[_ mod Ptrofs.modulus mod m] ] => rewrite <- Zmod_div_mod; try lia; try assumption | [ _ : _ |- context[Ptrofs.unsigned _] ] => rewrite Ptrofs.unsigned_signed end; try crush; ptrofs_mod_tac m. Qed. Lemma of_int_mod : forall x m, Int.unsigned x mod m = 0 -> Ptrofs.unsigned (Ptrofs.of_int x) mod m = 0. Proof. intros. unfold Ptrofs.of_int. rewrite Ptrofs.unsigned_repr; crush; apply Int.unsigned_range_2. Qed. Lemma mul_mod : forall x y m, 0 < m -> (m | Ptrofs.modulus) -> Ptrofs.unsigned x mod m = 0 -> Ptrofs.unsigned y mod m = 0 -> (Ptrofs.signed (Ptrofs.mul x y)) mod m = 0. Proof. intros. unfold Ptrofs.mul. rewrite Ptrofs.signed_repr_eq. repeat match goal with | [ _ : _ |- context[if ?x then _ else _] ] => destruct x | [ _ : _ |- context[_ mod Ptrofs.modulus mod m] ] => rewrite <- Zmod_div_mod; try lia; try assumption end; try(crush; lia); ptrofs_mod_tac m. Qed. Lemma add_mod : forall x y m, 0 < m -> (m | Ptrofs.modulus) -> Ptrofs.unsigned x mod m = 0 -> Ptrofs.unsigned y mod m = 0 -> (Ptrofs.unsigned (Ptrofs.add x y)) mod m = 0. Proof. intros. unfold Ptrofs.add. rewrite Ptrofs.unsigned_repr_eq. repeat match goal with | [ _ : _ |- context[if ?x then _ else _] ] => destruct x | [ _ : _ |- context[_ mod Ptrofs.modulus mod m] ] => rewrite <- Zmod_div_mod; try lia; try assumption end; try (crush; lia); ptrofs_mod_tac m. Qed. Lemma mul_divu : forall x y, 0 < Ptrofs.unsigned x -> Ptrofs.unsigned y mod Ptrofs.unsigned x = 0 -> (Integers.Ptrofs.mul x (Integers.Ptrofs.divu y x)) = y. Proof. intros. assert (x <> Ptrofs.zero). { intro. rewrite H1 in H. replace (Ptrofs.unsigned Ptrofs.zero) with 0 in H by reflexivity. lia. } exploit (Ptrofs.modu_divu_Euclid y x); auto; intros. unfold Ptrofs.modu in H2. rewrite H0 in H2. replace (Ptrofs.repr 0) with Ptrofs.zero in H2 by reflexivity. rewrite Ptrofs.add_zero in H2. rewrite Ptrofs.mul_commut. congruence. Qed. Lemma divu_unsigned : forall x y, 0 < Ptrofs.unsigned y -> Ptrofs.unsigned x <= Ptrofs.max_unsigned -> Ptrofs.unsigned (Ptrofs.divu x y) = Ptrofs.unsigned x / Ptrofs.unsigned y. Proof. intros. unfold Ptrofs.divu. rewrite Ptrofs.unsigned_repr; auto. split. apply Z.div_pos; auto. apply Ptrofs.unsigned_range. apply Z.div_le_upper_bound; auto. eapply Z.le_trans. exact H0. rewrite Z.mul_comm. apply Z.le_mul_diag_r; crush. Qed. Lemma mul_unsigned : forall x y, Ptrofs.mul x y = Ptrofs.repr (Ptrofs.unsigned x * Ptrofs.unsigned y). Proof. intros; unfold Ptrofs.mul. apply Ptrofs.eqm_samerepr. apply Ptrofs.eqm_mult; exists 0; lia. Qed. Lemma pos_signed_unsigned : forall x, 0 <= Ptrofs.signed x -> Ptrofs.signed x = Ptrofs.unsigned x. Proof. intros. rewrite Ptrofs.unsigned_signed. destruct (Ptrofs.lt x Ptrofs.zero) eqn:EQ. unfold Ptrofs.lt in EQ. destruct (zlt (Ptrofs.signed x) (Ptrofs.signed Ptrofs.zero)); try discriminate. replace (Ptrofs.signed (Ptrofs.zero)) with 0 in l by reflexivity. lia. reflexivity. Qed. End PtrofsExtra. Ltac ptrofs := repeat match goal with | [ |- context[Ptrofs.add (Ptrofs.zero) _] ] => setoid_rewrite Ptrofs.add_zero_l | [ H : context[Ptrofs.add (Ptrofs.zero) _] |- _ ] => setoid_rewrite Ptrofs.add_zero_l in H | [ |- context[Ptrofs.repr 0] ] => replace (Ptrofs.repr 0) with Ptrofs.zero by reflexivity | [ H : context[Ptrofs.repr 0] |- _ ] => replace (Ptrofs.repr 0) with Ptrofs.zero in H by reflexivity | [ H: context[Ptrofs.unsigned (Ptrofs.repr (Ptrofs.unsigned _))] |- _ ] => setoid_rewrite Ptrofs.unsigned_repr in H; [>| apply Ptrofs.unsigned_range_2] | [ |- context[Ptrofs.unsigned (Ptrofs.repr (Ptrofs.unsigned _))] ] => rewrite Ptrofs.unsigned_repr; [>| apply Ptrofs.unsigned_range_2] | [ |- context[0 <= Ptrofs.unsigned _] ] => apply Ptrofs.unsigned_range_2 end. Module IntExtra. Import Int. Ltac int_mod_match m := match goal with | [ H : ?x = 0 |- context[?x] ] => rewrite H | [ _ : _ |- context[_ - 0] ] => rewrite Z.sub_0_r | [ _ : _ |- context[0 + _] ] => rewrite Z.add_0_l | [ _ : _ |- context[_ + 0] ] => rewrite Z.add_0_r | [ _ : _ |- context[0 * _] ] => rewrite Z.mul_0_l | [ _ : _ |- context[_ * 0] ] => rewrite Z.mul_0_r | [ _ : _ |- context[?m mod ?m] ] => rewrite Z_mod_same_full with (a := m) | [ _ : _ |- context[0 mod _] ] => rewrite Z.mod_0_l | [ _ : _ |- context[(_ mod ?m) mod ?m] ] => rewrite Zmod_mod | [ _ : _ |- context[(_ mod Int.modulus) mod m ] ] => rewrite <- Zmod_div_mod; try (crush; lia || assumption) | [ _ : _ |- context[Int.modulus mod m] ] => rewrite Zdivide_mod with (a := Int.modulus); try (lia || assumption) | [ _ : _ |- context[Int.signed ?a mod Int.modulus] ] => rewrite Z.mod_small with (a := Int.signed a) (b := Int.modulus) | [ _ : _ |- context[(?x - ?y) mod ?m] ] => rewrite Zminus_mod with (a := x) (b := y) (n := m) | [ _ : _ |- context[((?x + ?y) mod ?m) + _] ] => rewrite Zplus_mod with (a := x) (b := y) (n := m) | [ _ : _ |- context[(?x + ?y) mod ?m] ] => rewrite Zplus_mod with (a := x) (b := y) (n := m) | [ _ : _ |- context[(?x * ?y) mod ?m] ] => rewrite Zmult_mod with (a := x) (b := y) (n := m) end. Ltac int_mod_tac m := repeat (int_mod_match m); lia. Lemma mul_mod1 : forall x y m, 0 < m -> (m | Int.modulus) -> Int.unsigned x mod m = 0 -> (Int.unsigned (Int.mul x y)) mod m = 0. Proof. intros. unfold Int.mul. rewrite Int.unsigned_repr_eq. repeat match goal with | [ _ : _ |- context[if ?x then _ else _] ] => destruct x | [ _ : _ |- context[_ mod Int.modulus mod m] ] => rewrite <- Zmod_div_mod; try lia; try assumption end; try (crush; lia); int_mod_tac m. Qed. Lemma mul_mod2 : forall x y m, 0 < m -> (m | Int.modulus) -> Int.unsigned y mod m = 0 -> (Int.unsigned (Int.mul x y)) mod m = 0. Proof. intros. unfold Int.mul. rewrite Int.unsigned_repr_eq. repeat match goal with | [ _ : _ |- context[if ?x then _ else _] ] => destruct x | [ _ : _ |- context[_ mod Int.modulus mod m] ] => rewrite <- Zmod_div_mod; try lia; try assumption end; try (crush; lia); int_mod_tac m. Qed. Lemma add_mod : forall x y m, 0 < m -> (m | Int.modulus) -> Int.unsigned x mod m = 0 -> Int.unsigned y mod m = 0 -> (Int.unsigned (Int.add x y)) mod m = 0. Proof. intros. unfold Int.add. rewrite Int.unsigned_repr_eq. repeat match goal with | [ _ : _ |- context[if ?x then _ else _] ] => destruct x | [ _ : _ |- context[_ mod Int.modulus mod m] ] => rewrite <- Zmod_div_mod; try lia; try assumption end; try (crush; lia); int_mod_tac m. Qed. Definition ofbytes (a b c d : byte) : int := or (shl (repr (Byte.unsigned a)) (repr (3 * Byte.zwordsize))) (or (shl (repr (Byte.unsigned b)) (repr (2 * Byte.zwordsize))) (or (shl (repr (Byte.unsigned c)) (repr Byte.zwordsize)) (repr (Byte.unsigned d)))). Definition byte1 (n: int) : byte := Byte.repr (unsigned n). Definition byte2 (n: int) : byte := Byte.repr (unsigned (shru n (repr Byte.zwordsize))). Definition byte3 (n: int) : byte := Byte.repr (unsigned (shru n (repr (2 * Byte.zwordsize)))). Definition byte4 (n: int) : byte := Byte.repr (unsigned (shru n (repr (3 * Byte.zwordsize)))). Lemma bits_byte1: forall n i, 0 <= i < Byte.zwordsize -> Byte.testbit (byte1 n) i = testbit n i. Proof. intros. unfold byte1. rewrite Byte.testbit_repr; auto. Qed. Lemma bits_byte2: forall n i, 0 <= i < Byte.zwordsize -> Byte.testbit (byte2 n) i = testbit n (i + Byte.zwordsize). Proof. intros. unfold byte2. rewrite Byte.testbit_repr; auto. assert (zwordsize = 4 * Byte.zwordsize) by reflexivity. fold (testbit (shru n (repr Byte.zwordsize)) i). rewrite bits_shru. change (unsigned (repr Byte.zwordsize)) with Byte.zwordsize. apply zlt_true. omega. omega. Qed. Lemma bits_byte3: forall n i, 0 <= i < Byte.zwordsize -> Byte.testbit (byte3 n) i = testbit n (i + (2 * Byte.zwordsize)). Proof. intros. unfold byte3. rewrite Byte.testbit_repr; auto. assert (zwordsize = 4 * Byte.zwordsize) by reflexivity. fold (testbit (shru n (repr (2 * Byte.zwordsize))) i). rewrite bits_shru. change (unsigned (repr (2 * Byte.zwordsize))) with (2 * Byte.zwordsize). apply zlt_true. omega. omega. Qed. Lemma bits_byte4: forall n i, 0 <= i < Byte.zwordsize -> Byte.testbit (byte4 n) i = testbit n (i + (3 * Byte.zwordsize)). Proof. intros. unfold byte4. rewrite Byte.testbit_repr; auto. assert (zwordsize = 4 * Byte.zwordsize) by reflexivity. fold (testbit (shru n (repr (3 * Byte.zwordsize))) i). rewrite bits_shru. change (unsigned (repr (3 * Byte.zwordsize))) with (3 * Byte.zwordsize). apply zlt_true. omega. omega. Qed. Lemma bits_ofwords: forall b4 b3 b2 b1 i, 0 <= i < zwordsize -> testbit (ofbytes b4 b3 b2 b1) i = if zlt i Byte.zwordsize then Byte.testbit b1 i else (if zlt i (2 * Byte.zwordsize) then Byte.testbit b2 (i - Byte.zwordsize) else (if zlt i (3 * Byte.zwordsize) then Byte.testbit b2 (i - 2 * Byte.zwordsize) else Byte.testbit b2 (i - 3 * Byte.zwordsize))). Proof. intros. unfold ofbytes. repeat (rewrite bits_or; auto). repeat (rewrite bits_shl; auto). change (unsigned (repr Byte.zwordsize)) with Byte.zwordsize. change (unsigned (repr (2 * Byte.zwordsize))) with (2 * Byte.zwordsize). change (unsigned (repr (3 * Byte.zwordsize))) with (3 * Byte.zwordsize). assert (zwordsize = 4 * Byte.zwordsize) by reflexivity. destruct (zlt i Byte.zwordsize). rewrite testbit_repr; auto. Abort. Definition shrx2 (x y : int) : int := if zlt (signed x) 0 then neg (shru (neg x) y) else shru x y. Lemma div_divs_equiv : forall x y, signed x >= 0 -> signed y >= 0 -> divs x y = divu x y. Proof. unfold divs, divu. intros. rewrite signed_eq_unsigned. rewrite signed_eq_unsigned. rewrite Zquot.Zquot_Zdiv_pos. reflexivity. rewrite <- signed_eq_unsigned. apply Z.ge_le; assumption. rewrite <- signed_positive; assumption. rewrite <- signed_eq_unsigned. apply Z.ge_le. assumption. rewrite <- signed_positive. assumption. rewrite <- signed_positive. assumption. rewrite <- signed_positive. assumption. Qed. Lemma neg_divs_distr_l : forall x y, neg (divs x y) = divs (neg x) y. Proof. intros. unfold divs, neg. set (x' := signed x). set (y' := signed y). apply eqm_samerepr. apply eqm_trans with (- (Z.quot x' y')). auto with ints. replace (- (Z.quot x' y')) with (Z.quot (- x') y'). 2: { rewrite Zquot.Zquot_opp_l. auto. } Search signed eqm. rewrite signed_eq_unsigned; auto. auto with ints. Admitted. Lemma neg_inj : forall x y, x = y -> neg x = neg y. Proof. intros. rewrite H. trivial. Qed. Compute (max_signed). Lemma neg_signed' : forall x, signed (neg x) = - signed x. Proof. intros. unfold neg. destruct (Z_le_gt_dec (unsigned x) max_signed). - admit. - rewrite signed_repr. rewrite signed_eq_unsigned. Qed. Lemma neg_signed : forall x : int, signed x < 0 -> signed (neg x) >= 0. Proof. unfold signed. intros. destruct (Z_ge_lt_dec (unsigned x) half_modulus). - rewrite zlt_false in H; try assumption. destruct (Z_ge_lt_dec (unsigned (neg x)) half_modulus). + rewrite zlt_false; try assumption. rewrite neg_not in *. rewrite add_unsigned. rewrite unsigned_repr. Search unsigned not. rewrite unsigned_not. unfold_constants. admit. admit. + rewrite zlt_true; try assumption. pose (unsigned_range (neg x)). apply Z.le_ge. apply a. - rewrite zlt_true in H; try assumption. pose (unsigned_range x). lia. Admitted. Lemma shrx_shrx2_equiv : forall x y, shrx x y = shrx2 x y. Proof. intros. unfold shrx, shrx2, lt. destruct (Z_ge_lt_dec (signed x) 0). - rewrite zlt_false; try assumption. pose (divu_pow2 x (shl one y) y). rewrite <- e. apply div_divs_equiv. assumption. admit (*shl >= 0*). admit (* is_power2 shl *). - rewrite zlt_true; try assumption. rewrite <- neg_involutive at 1. rewrite neg_divs_distr_l. apply neg_inj. pose (divu_pow2 (neg x) (shl one y) y). rewrite <- e. apply div_divs_equiv. apply neg_signed; assumption. admit (*shl >= 0*). admit (* is_power2 shl *). Admitted. End IntExtra.