Skip to content

Commit 8dda386

Browse files
committed
wrap Zmod in Word.Naive
1 parent 6f26796 commit 8dda386

File tree

1 file changed

+81
-57
lines changed

1 file changed

+81
-57
lines changed

src/coqutil/Word/Naive.v

Lines changed: 81 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
1-
Require Import Coq.ZArith.BinIntDef Coq.ZArith.BinInt coqutil.Z.Lia.
1+
From Coq Require Import BinInt Zmod Bits.
22
Require Import coqutil.Tactics.destr.
33
Require Import coqutil.sanity coqutil.Word.Interface. Import word.
44
Local Open Scope Z_scope.
55

6-
(* TODO: move me? *)
7-
Definition minimize_eq_proof{A: Type}(eq_dec: forall (x y: A), {x = y} + {x <> y}){x y: A} (pf: x = y): x = y :=
8-
match eq_dec x y with
9-
| left p => p
10-
| right n => match n pf: False with end
11-
end.
12-
136
Section WithWidth. Local Set Default Proof Using "All".
147
Context {width : Z}.
8+
Definition rep : Set := bits width.
9+
Definition unsigned (w : rep) := Zmod.unsigned w.
10+
11+
Definition wrap (z:Z) : rep := bits.of_Z width z.
12+
Definition signed (w : rep) := Zmod.signed w.
13+
1514
Let wrap_value z := z mod (2^width).
1615
Let swrap_value z := wrap_value (z + 2 ^ (width - 1)) - 2 ^ (width - 1).
17-
Record rep : Set := mk { unsigned : Z ; _unsigned_in_range : wrap_value unsigned = unsigned }.
18-
19-
Definition wrap (z:Z) : rep :=
20-
mk (wrap_value z) (minimize_eq_proof Z.eq_dec (Zdiv.Zmod_mod z _)).
21-
Definition signed w := swrap_value (unsigned w).
2216

2317
Record special_cases : Set := {
24-
div_by_zero: Z -> Z;
25-
mod_by_zero: Z -> Z;
2618
adjust_too_big_shift_amount: Z -> Z;
2719
}.
2820

@@ -50,81 +42,113 @@ Section WithWidth. Local Set Default Proof Using "All".
5042
word.signed := signed;
5143
of_Z := wrap;
5244

53-
add x y := wrap (Z.add (unsigned x) (unsigned y));
54-
sub x y := wrap (Z.sub (unsigned x) (unsigned y));
55-
opp x := wrap (Z.opp (unsigned x));
45+
add := Zmod.add;
46+
sub := Zmod.sub;
47+
opp := Zmod.opp;
5648

57-
or x y := wrap (Z.lor (unsigned x) (unsigned y));
58-
and x y := wrap (Z.land (unsigned x) (unsigned y));
59-
xor x y := wrap (Z.lxor (unsigned x) (unsigned y));
60-
not x := wrap (Z.lnot (unsigned x));
61-
ndn x y := wrap (Z.ldiff (unsigned x) (unsigned y));
49+
or := Zmod.or;
50+
and := Zmod.and;
51+
xor := Zmod.xor;
52+
not := Zmod.not;
53+
ndn := Zmod.ndn;
6254

63-
mul x y := wrap (Z.mul (unsigned x) (unsigned y));
55+
mul := Zmod.mul;
6456
mulhss x y := wrap (Z.mul (signed x) (signed y) / 2^width);
6557
mulhsu x y := wrap (Z.mul (signed x) (unsigned y) / 2^width);
6658
mulhuu x y := wrap (Z.mul (unsigned x) (unsigned y) / 2^width);
6759

68-
divu x y := wrap (if Z.eqb (unsigned y) 0 then sp.(div_by_zero) (unsigned x)
69-
else Z.div (unsigned x) (unsigned y));
70-
divs x y := wrap (if Z.eqb (signed y) 0 then sp.(div_by_zero) (signed x)
71-
else Z.quot (signed x) (signed y));
72-
modu x y := wrap (if Z.eqb (unsigned y) 0 then sp.(mod_by_zero) (unsigned x)
73-
else Z.modulo (unsigned x) (unsigned y));
74-
mods x y := wrap (if Z.eqb (signed y) 0 then sp.(mod_by_zero) (signed x)
75-
else Z.rem (signed x) (signed y));
60+
divu := Zmod.udiv;
61+
divs := Zmod.squot;
62+
modu := Zmod.umod;
63+
mods := Zmod.srem;
7664

77-
slu x y := wrap (Z.shiftl (unsigned x) (adjust_shift_amount (unsigned y)));
78-
sru x y := wrap (Z.shiftr (unsigned x) (adjust_shift_amount (unsigned y)));
79-
srs x y := wrap (Z.shiftr (signed x) (adjust_shift_amount (unsigned y)));
65+
slu x y := Zmod.slu x (adjust_shift_amount (unsigned y));
66+
sru x y := Zmod.sru x (adjust_shift_amount (unsigned y));
67+
srs x y := Zmod.srs x (adjust_shift_amount (unsigned y));
8068

81-
eqb x y := Z.eqb (unsigned x) (unsigned y);
69+
eqb := Zmod.eqb;
8270
ltu x y := Z.ltb (unsigned x) (unsigned y);
8371
lts x y := Z.ltb (signed x) (signed y);
8472

8573
sextend oldwidth z := wrap ((unsigned z + 2^(oldwidth-1)) mod 2^oldwidth - 2^(oldwidth-1));
8674
|}.
8775

8876
Lemma eq_unsigned {x y : rep} : unsigned x = unsigned y -> x = y.
89-
Proof.
90-
cbv [value]; destruct x as [x px], y as [y py]; cbn.
91-
intro; subst y.
92-
apply f_equal, Eqdep_dec.UIP_dec. eapply Z.eq_dec.
93-
Qed.
77+
Proof. apply Zmod.unsigned_inj. Qed.
9478

9579
Lemma of_Z_unsigned x : wrap (unsigned x) = x.
96-
Proof. eapply eq_unsigned; destruct x; cbn; assumption. Qed.
80+
Proof. apply Zmod.of_Z_to_Z. Qed.
81+
82+
(* Candidate for stdlib inclusion: *)
83+
Lemma smod_swrap z : ZModOffset.Z.smodulo z (2 ^ width) = @swrap width gen_word z.
84+
Proof.
85+
cbv [swrap gen_word].
86+
cbv [ZModOffset.Z.smodulo ZModOffset.Z.omodulo].
87+
rewrite Z.add_opp_r, Z.sub_opp_r.
88+
case (Z.eqb_spec width 0) as [->|]; trivial.
89+
case (Z.eqb_spec width 1) as [->|]; trivial.
90+
case (Z.ltb_spec width 0) as []. { rewrite !Z.pow_neg_r by lia; trivial. }
91+
rewrite Z.pow_sub_r by try lia; change (2^1) with 2.
92+
rewrite Z.quot_div_nonneg by lia; trivial.
93+
Qed.
9794

9895
Lemma signed_of_Z z : signed (wrap z) = wrap_value (z + 2 ^ (width - 1)) - 2 ^ (width - 1).
9996
Proof.
97+
cbv [signed wrap]; rewrite Zmod.signed_of_Z.
10098
cbv [unsigned signed wrap wrap_value swrap_value].
101-
rewrite Zdiv.Zplus_mod_idemp_l; auto.
99+
apply smod_swrap.
102100
Qed.
103101

104102
Context (width_nonneg : Z.lt 0 width).
105103

106104
Global Instance gen_ok : word.ok gen_word.
107105
Proof.
108-
split; intros;
109-
repeat match goal with
110-
| a: @word.rep _ _ |- _ => destruct a
111-
end;
112-
cbn in *;
113-
unfold adjust_shift_amount in *;
114-
repeat match goal with
115-
| |- context[if ?b then _ else _] => destr b
116-
end;
117-
eauto using of_Z_unsigned, signed_of_Z;
118-
try (exfalso; blia).
119-
apply eq_unsigned; assumption.
106+
split; trivial;
107+
cbv [gen_word adjust_shift_amount signed unsigned wrap]; intros.
108+
{ apply Zmod.unsigned_of_Z. }
109+
{ rewrite <-smod_swrap. apply Zmod.signed_of_Z. }
110+
{ apply Zmod.of_Z_to_Z. }
111+
{ apply Zmod.unsigned_add. }
112+
{ apply Zmod.unsigned_sub. }
113+
{ apply Zmod.unsigned_opp. }
114+
{ apply Zmod.unsigned_of_Z. }
115+
{ apply Zmod.unsigned_of_Z. }
116+
{ apply Zmod.unsigned_of_Z. }
117+
{ apply Zmod.unsigned_of_Z. }
118+
{ apply Zmod.unsigned_of_Z. }
119+
{ apply Zmod.unsigned_mul. }
120+
{ cbv [word.signed mulhss]. rewrite Zmod.signed_of_Z, smod_swrap; trivial. }
121+
{ cbv [word.signed mulhsu]. rewrite Zmod.signed_of_Z, smod_swrap; trivial. }
122+
{ cbv [word.unsigned mulhuu]. apply Zmod.unsigned_of_Z. }
123+
{ cbv [word.unsigned divu]. rewrite Zmod.unsigned_udiv; trivial. }
124+
{ cbv [word.signed divs]. rewrite Zmod.signed_squot, <-smod_swrap.
125+
case Z.eqb_spec; [contradiction|]; trivial. }
126+
{ cbv [word.unsigned modu] in *. rewrite Zmod.unsigned_umod; trivial.
127+
symmetry; apply Z.mod_small.
128+
pose proof Zmod.unsigned_pos_bound x ltac:(lia).
129+
pose proof Zmod.unsigned_pos_bound y ltac:(lia).
130+
pose proof (Z.mod_pos_bound (Zmod.unsigned x) (Zmod.unsigned y)).
131+
lia. }
132+
{ cbv [word.signed mods]. rewrite Zmod.signed_srem, <-smod_swrap; trivial. }
133+
{ cbv [word.unsigned slu] in *; case Z.ltb_spec; intros; [|lia].
134+
apply Zmod.unsigned_slu. }
135+
{ cbv [word.unsigned sru] in *; case Z.ltb_spec; intros; [|lia].
136+
pose proof Zmod.unsigned_pos_bound x ltac:(lia).
137+
pose proof Zmod.unsigned_pos_bound y ltac:(lia).
138+
rewrite Zmod.unsigned_sru, Z.mod_small;
139+
rewrite ?Z.shiftr_div_pow2; try (Z.to_euclidean_division_equations; nia). }
140+
{ cbv [word.unsigned word.signed srs] in *; case Z.ltb_spec; intros; [|lia].
141+
pose proof Zmod.signed_pos_bound x ltac:(lia).
142+
pose proof Zmod.unsigned_pos_bound y ltac:(lia).
143+
rewrite Zmod.signed_srs, <-smod_swrap, Z.smod_even_small;
144+
rewrite ?Z.shiftr_div_pow2; try (Z.to_euclidean_division_equations; nia).
145+
rewrite <-(Z.succ_pred width), Z.pow_succ_r, Z.mul_comm, Z.rem_mul; lia. }
120146
Qed.
121147
End WithWidth.
122148
Arguments gen_word : clear implicits.
123149
Arguments gen_ok : clear implicits.
124150

125151
Definition default_special_case_handlers width := {|
126-
div_by_zero x := -1;
127-
mod_by_zero x := x;
128152
adjust_too_big_shift_amount n := n mod 2 ^ Z.log2 width;
129153
|}.
130154

0 commit comments

Comments
 (0)