REFERENCE / ZLIB × LEAN
adler32.c.public-any.lean
Source snapshot ·
8b8f46306eba7039 · Source at the matching commit ↗Lean source with line numbers. Follow a line number to locate a statement, or an import to read its dependency.
1import ZlibF.Proof.«adler32.c.public-block»
2
3/-! Adler execution over every represented byte reference. -/
4namespace Zlib.Adler32.Proofs
5open C Zlib.Adler32 Zlib.Adler32.Spec Zlib.Adler32.Proofs
6
7
8variable {h : Heap} {ref : BRef} {bytes : Array UInt8}
9
10theorem do1_ok_any (hb : Space.get h ref = some bytes) (s : Locals) (p i : Nat)
11 (hbuf : s.buf = .ref ref p) (hlt : p + i < bytes.size) :
12 OkOn h (do1 s i) (upd s bytes[p + i]!) := by
13 obtain ⟨a, s2, buf, len, n⟩ := s
14 simp only at hbuf
15 subst hbuf
16 unfold do1
17 refine OkOn.bind (Ptr.index_ok hb hlt) ?_
18 rw [getElem_eq_bang bytes _ hlt]
19 exact OkOn.pure _ _
20
21theorem upd_buf_any (t : Locals) (b : UInt8) : (upd t b).buf = t.buf := rfl
22
23theorem do16_ok_any (hb : Space.get h ref = some bytes) (s : Locals) (p : Nat)
24 (hbuf : s.buf = .ref ref p) (hlt : p + 16 ≤ bytes.size) :
25 OkOn h (do16 s) (updL s (seg bytes p 16)) := by
26 have st : ∀ (t : Locals) (i : Nat), t.buf = .ref ref p → i < 16 →
27 OkOn h (do1 t i) (upd t bytes[p + i]!) :=
28 fun t i ht hi => do1_ok_any (ref := ref) hb t p i ht (by omega)
29 unfold do16
30 refine OkOn.bind (st _ 0 hbuf (by omega)) ?_
31 refine OkOn.bind (st _ 1 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
32 refine OkOn.bind (st _ 2 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
33 refine OkOn.bind (st _ 3 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
34 refine OkOn.bind (st _ 4 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
35 refine OkOn.bind (st _ 5 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
36 refine OkOn.bind (st _ 6 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
37 refine OkOn.bind (st _ 7 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
38 refine OkOn.bind (st _ 8 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
39 refine OkOn.bind (st _ 9 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
40 refine OkOn.bind (st _ 10 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
41 refine OkOn.bind (st _ 11 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
42 refine OkOn.bind (st _ 12 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
43 refine OkOn.bind (st _ 13 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
44 refine OkOn.bind (st _ 14 (by simp only [upd_buf_any]; exact hbuf) (by omega)) ?_
45 have e : updL s (seg bytes p 16) = upd (upd (upd (upd (upd (upd (upd (upd (upd (upd (upd
46 (upd (upd (upd (upd (upd s bytes[p + 0]!) bytes[p + 1]!) bytes[p + 2]!) bytes[p + 3]!)
47 bytes[p + 4]!) bytes[p + 5]!) bytes[p + 6]!) bytes[p + 7]!) bytes[p + 8]!) bytes[p + 9]!)
48 bytes[p + 10]!) bytes[p + 11]!) bytes[p + 12]!) bytes[p + 13]!) bytes[p + 14]!) bytes[p + 15]! := rfl
49 rw [e]
50 exact st _ 15 (by simp only [upd_buf_any]; exact hbuf) (by omega)
51
52theorem stepByte_ok_any (hb : Space.get h ref = some bytes) (s : Locals) (p : Nat)
53 (hbuf : s.buf = .ref ref p) (hlt : p < bytes.size) :
54 OkOn h (stepByte s) { upd s bytes[p]! with buf := .ref ref (p + 1) } := by
55 obtain ⟨a, s2, buf, len, n⟩ := s
56 simp only at hbuf
57 subst hbuf
58 unfold stepByte
59 refine OkOn.bind (Ptr.load_ok hb hlt) ?_
60 refine OkOn.bind (Ptr.add_ok hb (by omega) (by omega)) ?_
61 rw [getElem_eq_bang bytes _ hlt]
62 have : ((p : Int) + 1).toNat = p + 1 := by omega
63 rw [this]
64 exact OkOn.pure _ _
65
66theorem bufAdd16_ok_any (hb : Space.get h ref = some bytes) (s : Locals) (p : Nat)
67 (hbuf : s.buf = .ref ref p) (hlt : p + 16 ≤ bytes.size) :
68 OkOn h (do pure { s with buf := ← s.buf.add 16 }) { s with buf := .ref ref (p + 16) } := by
69 rw [hbuf]
70 refine OkOn.bind (Ptr.add_ok hb (by omega) (by omega)) ?_
71 have : ((p : Int) + 16).toNat = p + 16 := by omega
72 rw [this]
73 exact OkOn.pure _ _
74
75theorem byteLoop_ok_any (hb : Space.get h ref = some bytes) (s : Locals) (p : Nat)
76 (hbuf : s.buf = .ref ref p) (hfit : p + s.len.toNat ≤ bytes.size) :
77 ∃ s', OkOn h (cwhile lenPostDec stepByte s) s' ∧
78 s'.buf = .ref ref (p + s.len.toNat) ∧ AccFrom s s' (seg bytes p s.len.toNat) := by
79 have hk := fuel_gt s.len
80 generalize hkdef : s.len.toNat = k at hfit hk ⊢
81 let P : Nat → Locals → Prop := fun j t => ∃ i, i + j = k ∧ t.buf = .ref ref (p + i) ∧
82 t.len.toNat = j ∧ AccFrom s t (seg bytes p i)
83 let Q : Locals → Prop := fun t => t.buf = .ref ref (p + k) ∧ AccFrom s t (seg bytes p k)
84 refine cwhile_ok (h := h) P Q ?_ ?_ (k := k) ⟨0, by omega, by simpa using hbuf, hkdef, AccFrom.refl s⟩ hk
85 · intro j t ⟨i, hi, htb, htl, hacc⟩
86 have hne : (t.len != 0) = true := by
87 simp only [bne_iff_ne, ne_eq]; intro h0; rw [h0] at htl; simp at htl
88 refine ⟨{ t with len := t.len - 1 }, { upd { t with len := t.len - 1 } bytes[p + i]! with
89 buf := .ref ref (p + i + 1) }, ?_, stepByte_ok_any (ref := ref) hb _ (p + i) htb (by omega), ?_⟩
90 · show OkOn h (pure (t.len != 0, { t with len := t.len - 1 })) _
91 rw [hne]; exact OkOn.pure _ _
92 · refine ⟨i + 1, by omega, by simp [Nat.add_assoc], ?_, ?_⟩
93 · simp only [Zlib.Adler32.Proofs.upd]
94 rw [UInt64.toNat_sub_of_le _ _ (by rw [UInt64.le_iff_toNat_le]; simp; omega)]
95 simp; omega
96 · rw [seg_add, seg_one]
97 exact (hacc.congr rfl rfl).upd _
98 · intro t ⟨i, hi, htb, htl, hacc⟩
99 have he : (t.len != 0) = false := by
100 simp only [bne_eq_false_iff_eq]; exact UInt64.toNat_inj.mp (by simp [htl])
101 refine ⟨{ t with len := t.len - 1 }, ?_, ?_, ?_⟩
102 · show OkOn h (pure (t.len != 0, { t with len := t.len - 1 })) _
103 rw [he]; exact OkOn.pure _ _
104 · simpa [show i = k by omega] using htb
105 · exact (show i = k by omega) ▸ hacc.congr rfl rfl
106
107/-- `while (len >= 16) { len -= 16; DO16(buf); buf += 16; }` -/
108theorem chunkLoop_ok_any (hb : Space.get h ref = some bytes) (s : Locals) (p : Nat)
109 (hbuf : s.buf = .ref ref p) (hfit : p + s.len.toNat ≤ bytes.size) :
110 ∃ s', OkOn h (cwhile (fun s => pure (decide (s.len ≥ 16), s))
111 (fun s => do
112 let s ← do16 { adler := s.adler, sum2 := s.sum2, buf := s.buf, len := s.len - 16, n := s.n }
113 let __do_lift ← s.buf.add 16
114 pure { adler := s.adler, sum2 := s.sum2, buf := __do_lift, len := s.len, n := s.n }) s) s' ∧
115 s'.buf = .ref ref (p + 16 * (s.len.toNat / 16)) ∧ s'.len.toNat = s.len.toNat % 16 ∧
116 s'.n = s.n ∧ AccFrom s s' (seg bytes p (16 * (s.len.toNat / 16))) := by
117 have hk := fuel_gt s.len
118 generalize hrdef : s.len.toNat = r at hfit hk ⊢
119 let P : Nat → Locals → Prop := fun j t => ∃ i, i + j = r / 16 ∧
120 t.buf = .ref ref (p + 16 * i) ∧
121 t.len.toNat = r - 16 * i ∧ t.n = s.n ∧ AccFrom s t (seg bytes p (16 * i))
122 let Q : Locals → Prop := fun t => t.buf = .ref ref (p + 16 * (r / 16)) ∧
123 t.len.toNat = r % 16 ∧ t.n = s.n ∧ AccFrom s t (seg bytes p (16 * (r / 16)))
124 refine cwhile_ok (h := h) P Q ?_ ?_ (k := r / 16)
125 ⟨0, by omega, by simpa using hbuf, by simp [hrdef], rfl, AccFrom.refl s⟩ (by omega)
126 · intro j t ⟨i, hi, htb, htl, htn, hacc⟩
127 have hge : decide (t.len ≥ 16) = true := by
128 simp only [decide_eq_true_eq, ge_iff_le, UInt64.le_iff_toNat_le]; simp; omega
129 let t1 : Locals := { adler := t.adler, sum2 := t.sum2, buf := t.buf, len := t.len - 16, n := t.n }
130 have ht1 : t1.buf = .ref ref (p + 16 * i) := htb
131 refine ⟨t, { updL t1 (seg bytes (p + 16 * i) 16) with
132 buf := .ref ref (p + 16 * i + 16) }, ?_, ?_, ?_⟩
133 · show OkOn h (pure (decide (t.len ≥ 16), t)) _
134 rw [hge]; exact OkOn.pure _ _
135 · refine OkOn.bind (do16_ok_any (ref := ref) hb t1 (p + 16 * i) ht1 (by omega)) ?_
136 exact bufAdd16_ok_any (ref := ref) hb _ (p + 16 * i) ht1 (by omega)
137 · refine ⟨i + 1, by omega, by simp [Nat.mul_add, Nat.add_assoc], ?_, htn, ?_⟩
138 · show (t.len - 16).toNat = r - 16 * (i + 1)
139 rw [UInt64.toNat_sub_of_le _ _ (by rw [UInt64.le_iff_toNat_le]; simp; omega)]
140 simp; omega
141 · rw [show 16 * (i + 1) = 16 * i + 16 by omega, seg_add]
142 exact ((hacc.congr rfl rfl : AccFrom s t1 _).updL _).congr rfl rfl
143 · intro t ⟨i, hi, htb, htl, htn, hacc⟩
144 have hlt : decide (t.len ≥ 16) = false := by
145 simp only [decide_eq_false_iff_not, ge_iff_le, UInt64.le_iff_toNat_le]; simp; omega
146 refine ⟨t, ?_, ?_, ?_, htn, ?_⟩
147 · show OkOn h (pure (decide (t.len ≥ 16), t)) _
148 rw [hlt]; exact OkOn.pure _ _
149 · simpa [show i = r / 16 by omega] using htb
150 · rw [htl]; omega
151 · exact (show i = r / 16 by omega) ▸ hacc
152
153theorem nmaxBlock_ok_any (hb : Space.get h ref = some bytes) (t : Locals) (p : Nat)
154 (hbuf : t.buf = .ref ref p) (hfit : p + 5552 ≤ bytes.size) (ht : t.n = 347) :
155 ∃ u, OkOn h (cdoWhile
156 (fun s => do
157 let s ← do16 s
158 let __do_lift ← s.buf.add 16
159 pure { adler := s.adler, sum2 := s.sum2, buf := __do_lift, len := s.len, n := s.n })
160 (fun s => pure (s.n - 1 != 0, { adler := s.adler, sum2 := s.sum2, buf := s.buf, len := s.len, n := s.n - 1 }))
161 t) u ∧
162 u.buf = .ref ref (p + 5552) ∧ u.len = t.len ∧ AccFrom t u (seg bytes p 5552) := by
163 let P : Nat → Locals → Prop := fun m u => ∃ i, i + m = 346 ∧ u.n.toNat = m + 1 ∧
164 u.buf = .ref ref (p + 16 * i) ∧ u.len = t.len ∧ AccFrom t u (seg bytes p (16 * i))
165 let Q : Locals → Prop := fun u => u.buf = .ref ref (p + 5552) ∧ u.len = t.len ∧
166 AccFrom t u (seg bytes p 5552)
167 refine cdoWhile_ok (h := h) P Q ?_ ?_ (k := 346)
168 ⟨0, rfl, by rw [ht]; rfl, by simpa using hbuf, rfl, AccFrom.refl t⟩ (by simp [fuel])
169 · intro m u ⟨i, hi, hn, hub, hul, hacc⟩
170 let u1 : Locals := { updL u (seg bytes (p + 16 * i) 16) with buf := .ref ref (p + 16 * i + 16) }
171 have hne : (u1.n - 1 != 0) = true := by
172 have : u1.n = u.n := rfl
173 simp only [bne_iff_ne, ne_eq, this]
174 intro h0
175 have := congrArg UInt32.toNat h0
176 rw [UInt32.toNat_sub_of_le _ _ (by rw [UInt32.le_iff_toNat_le]; simp; omega)] at this
177 simp at this; omega
178 refine ⟨u1, { u1 with n := u1.n - 1 }, ?_, ?_, ?_⟩
179 · refine OkOn.bind (do16_ok_any (ref := ref) hb u (p + 16 * i) hub (by omega)) ?_
180 exact bufAdd16_ok_any (ref := ref) hb _ (p + 16 * i) hub (by omega)
181 · show OkOn h (pure (u1.n - 1 != 0, { u1 with n := u1.n - 1 })) _
182 rw [hne]; exact OkOn.pure _ _
183 · refine ⟨i + 1, by omega, ?_, ?_, hul, ?_⟩
184 · show (u.n - 1).toNat = m + 1
185 rw [UInt32.toNat_sub_of_le _ _ (by rw [UInt32.le_iff_toNat_le]; simp; omega)]
186 simp; omega
187 · show Ptr.ref ref (p + 16 * i + 16) = _
188 rw [show p + 16 * i + 16 = p + 16 * (i + 1) by omega]
189 · rw [show 16 * (i + 1) = 16 * i + 16 by omega, seg_add]
190 exact (hacc.updL _).congr rfl rfl
191 · intro u ⟨i, hi, hn, hub, hul, hacc⟩
192 let u1 : Locals := { updL u (seg bytes (p + 16 * i) 16) with buf := .ref ref (p + 16 * i + 16) }
193 have he : (u1.n - 1 != 0) = false := by
194 have : u1.n = u.n := rfl
195 simp only [bne_eq_false_iff_eq, this]
196 apply UInt32.toNat_inj.mp
197 rw [UInt32.toNat_sub_of_le _ _ (by rw [UInt32.le_iff_toNat_le]; simp; omega)]
198 simp; omega
199 refine ⟨u1, { u1 with n := u1.n - 1 }, ?_, ?_, ?_⟩
200 · refine OkOn.bind (do16_ok_any (ref := ref) hb u (p + 16 * i) hub (by omega)) ?_
201 exact bufAdd16_ok_any (ref := ref) hb _ (p + 16 * i) hub (by omega)
202 · show OkOn h (pure (u1.n - 1 != 0, { u1 with n := u1.n - 1 })) _
203 rw [he]; exact OkOn.pure _ _
204 · refine ⟨by simp [u1]; omega, hul, ?_⟩
205 have hi' : i = 346 := by omega
206 subst hi'
207 rw [show 5552 = 16 * 346 + 16 by rfl, seg_add]
208 exact (hacc.updL _).congr rfl rfl
209
210
211theorem adler32_z_long_any (hb : Space.get h ref = some bytes) (a : UInt64) (off L : Nat)
212 (hfit : off + L ≤ bytes.size) (hL : L < 2 ^ 64) (h16 : 16 ≤ L) :
213 ∃ r, OkOn h (adler32_z a (.ref ref off) L.toUInt64) r ∧
214 r.toNat = Spec.adler32 a.toNat (seg bytes off L) := by
215 have hLn : L.toUInt64.toNat = L := by simp; omega
216 have hne1 : (L.toUInt64 == 1) = false := by
217 simp only [beq_eq_false_iff_ne, ne_eq]; intro e; have := congrArg UInt64.toNat e; simp at this; omega
218 have hnull : (Ptr.ref ref off == (Ptr.null : BPtr)) = false := by simp
219 have hn16 : ¬ (L.toUInt64 < 16) := by rw [UInt64.lt_iff_toNat_lt, hLn]; simp; omega
220 unfold adler32_z
221 rw [ite_eq_right_of_eq_false _ _ (by simp [hne1]), ite_eq_right_of_eq_false _ _ (by simp [hnull]),
222 ite_eq_right_of_eq_false _ _ (by simp [hn16])]
223 let lo := (a &&& 65535).toNat % 65521
224 let hi := (a >>> 16 &&& 65535).toNat % 65521
225 let q := L / 5552
226 let r := L % 5552
227 let s0 : Locals := { adler := a &&& 65535, sum2 := a >>> 16 &&& 65535, buf := .ref ref off, len := L.toUInt64, n := 0 }
228 let P : Nat → Locals → Prop := fun k t => ∃ i, i + k = q ∧ t.buf = .ref ref (off + 5552 * i) ∧
229 t.len.toNat = L - 5552 * i ∧
230 Rel 0 t.adler t.sum2 (sums lo hi (seg bytes off (5552 * i))).1 (sums lo hi (seg bytes off (5552 * i))).2 ∧
231 (1 ≤ i → t.adler.toNat < 65521 ∧ t.sum2.toNat < 65521)
232 let Q : Locals → Prop := fun t => t.buf = .ref ref (off + 5552 * q) ∧ t.len.toNat = r ∧
233 Rel 0 t.adler t.sum2 (sums lo hi (seg bytes off (5552 * q))).1 (sums lo hi (seg bytes off (5552 * q))).2 ∧
234 (1 ≤ q → t.adler.toNat < 65521 ∧ t.sum2.toNat < 65521)
235 have hinit : P q s0 := ⟨0, by omega, by simp [s0], by simp [s0, hLn], rel_init a, by omega⟩
236 refine OkOn.bind_ex (cwhile_ok (h := h) P Q ?_ ?_ hinit (by simp [fuel]; omega)) ?_
237 · -- one NMAX block
238 rintro k t ⟨i, hi_, htb, htl, hrel, -⟩
239 have hge : decide (t.len ≥ NMAX) = true := by
240 simp only [decide_eq_true_eq, ge_iff_le, UInt64.le_iff_toNat_le, htl]; simp [NMAX]; omega
241 let t0 : Locals := { adler := t.adler, sum2 := t.sum2, buf := t.buf, len := t.len - NMAX, n := (NMAX / 16).toUInt32 }
242 obtain ⟨u, hu, hub, hul, hacc⟩ := nmaxBlock_ok_any (ref := ref) hb t0 (off + 5552 * i) htb (by omega) nmax_div
243 refine ⟨t, { adler := u.adler % BASE, sum2 := u.sum2 % BASE, buf := u.buf, len := u.len, n := u.n }, ?_, ?_, ?_⟩
244 · show OkOn h (pure (decide (t.len ≥ NMAX), t)) _
245 rw [hge]; exact OkOn.pure _ _
246 · exact OkOn.bind hu (OkOn.pure _ _)
247 · have hacc' := acc_list (seg bytes (off + 5552 * i) 5552) 0 t0.adler t0.sum2 _ _ hrel (by simp [seg_length])
248 rw [seg_length] at hacc'
249 have hmod := rel_mod _ _ _ _ _ hacc'
250 refine ⟨i + 1, by omega, ?_, ?_, ?_, ?_⟩
251 · rw [hub, show off + 5552 * i + 5552 = off + 5552 * (i + 1) by omega]
252 · show u.len.toNat = _
253 rw [hul]; show (t.len - NMAX).toNat = _
254 rw [UInt64.toNat_sub_of_le _ _ (by rw [UInt64.le_iff_toNat_le, htl]; simp [NMAX]; omega), htl]
255 simp [NMAX]; omega
256 · rw [show 5552 * (i + 1) = 5552 * i + 5552 by omega, seg_add, sums_append]
257 obtain ⟨ha, hs⟩ := hacc
258 simp only [updL] at ha hs
259 show Rel 0 (u.adler % 65521) (u.sum2 % 65521) _ _
260 rw [ha, hs]
261 exact hmod
262 · intro _
263 simp only [UInt64.toNat_mod, BASE]
264 exact ⟨Nat.mod_lt _ (by decide), Nat.mod_lt _ (by decide)⟩
265 · -- loop exit
266 rintro t ⟨i, hi_, htb, htl, hrel, hred⟩
267 have hlt : decide (t.len ≥ NMAX) = false := by
268 simp only [decide_eq_false_iff_not, ge_iff_le, UInt64.le_iff_toNat_le, htl]; simp [NMAX]; omega
269 refine ⟨t, ?_, ?_⟩
270 · show OkOn h (pure (decide (t.len ≥ NMAX), t)) _
271 rw [hlt]; exact OkOn.pure _ _
272 · have : i = q := by omega
273 subst this
274 exact ⟨htb, by rw [htl]; omega, hrel, hred⟩
275 · -- remainder
276 rintro t ⟨htb, htl, hrel, hred⟩
277 by_cases hr0 : r = 0
278 · have hz : (t.len != 0) = false := by
279 simp only [bne_eq_false_iff_eq]; exact UInt64.toNat_inj.mp (by simp [htl, hr0])
280 rw [hz]
281 simp only [Bool.false_eq_true, ite_false]
282 have hq : 1 ≤ q := by omega
283 obtain ⟨ha, hs⟩ := hred hq
284 obtain ⟨ea, es⟩ := rel_exact hrel ha hs
285 refine ⟨_, OkOn.bind (OkOn.pure _ _) (OkOn.pure _ _), ?_⟩
286 have hseg : seg bytes off L = seg bytes off (5552 * q) := by
287 rw [show 5552 * q = L by omega]
288 rw [hseg]
289 exact result_value a t.adler t.sum2 _ ea es
290 · have hnz : (t.len != 0) = true := by
291 simp only [bne_iff_ne, ne_eq]; intro e; have := congrArg UInt64.toNat e; simp [htl] at this; omega
292 rw [hnz]
293 simp only [ite_true]
294 obtain ⟨c, hc, hcb, hcl, -, hcacc⟩ := chunkLoop_ok_any (ref := ref) hb t (off + 5552 * q) htb (by rw [htl]; omega)
295 rw [htl] at hcb hcl hcacc
296 obtain ⟨d, hd, hdb, hdacc⟩ := byteLoop_ok_any (ref := ref) hb c _ hcb (by rw [hcl]; omega)
297 rw [hcl] at hdb hdacc
298 have hall := hcacc.trans hdacc
299 have hlen : (seg bytes (off + 5552 * q) (16 * (r / 16)) ++ seg bytes (off + 5552 * q + 16 * (r / 16)) (r % 16)).length = r := by
300 simp [seg_length]; omega
301 have hrel' := acc_list _ 0 t.adler t.sum2 _ _ hrel (by rw [hlen]; omega)
302 rw [hlen] at hrel'
303 obtain ⟨hda, hds⟩ := hall
304 simp only [updL] at hda hds
305 refine ⟨_, OkOn.bind hc (OkOn.bind hd (OkOn.bind (OkOn.pure _ _) (OkOn.pure _ _))), ?_⟩
306 have hseg : seg bytes off L = seg bytes off (5552 * q) ++
307 (seg bytes (off + 5552 * q) (16 * (r / 16)) ++ seg bytes (off + 5552 * q + 16 * (r / 16)) (r % 16)) := by
308 rw [← seg_add, ← seg_add]; congr 1; omega
309 rw [hseg]
310 apply result_value
311 · rw [sums_append, show (d.adler % BASE).toNat = d.adler.toNat % 65521 by simp [BASE], hda]
312 exact hrel'.1
313 · rw [sums_append, show (d.sum2 % BASE).toNat = d.sum2.toNat % 65521 by simp [BASE], hds]
314 exact hrel'.2.1
315
316
317theorem adler32_z_short_any (hb : Space.get h ref = some bytes) (a : UInt64) (off L : Nat)
318 (hfit : off + L ≤ bytes.size) (h16 : L < 16) (h1 : L ≠ 1) :
319 ∃ r, OkOn h (adler32_z a (.ref ref off) L.toUInt64) r ∧
320 r.toNat = Spec.adler32 a.toNat (seg bytes off L) := by
321 have hLn : L.toUInt64.toNat = L := by simp; omega
322 have hne1 : (L.toUInt64 == 1) = false := by
323 simp only [beq_eq_false_iff_ne, ne_eq]; intro e; have := congrArg UInt64.toNat e; simp at this; omega
324 have hnull : (Ptr.ref ref off == (Ptr.null : BPtr)) = false := by simp
325 have hy16 : L.toUInt64 < 16 := by rw [UInt64.lt_iff_toNat_lt, hLn]; simp; omega
326 unfold adler32_z
327 rw [ite_eq_right_of_eq_false _ _ (by simp [hne1]), ite_eq_right_of_eq_false _ _ (by simp [hnull]),
328 ite_eq_left hy16]
329 let s0 : Locals := { adler := a &&& 65535, sum2 := a >>> 16 &&& 65535, buf := .ref ref off, len := L.toUInt64, n := 0 }
330 obtain ⟨d, hd, -, hacc⟩ := byteLoop_ok_any (ref := ref) hb s0 off rfl (by simp [s0, hLn]; omega)
331 have hrel := acc_list (seg bytes off s0.len.toNat) 0 s0.adler s0.sum2 _ _ (rel_init a)
332 (by simp [seg_length, s0, hLn]; omega)
333 obtain ⟨hda, hds⟩ := hacc
334 simp only [updL] at hda hds
335 rw [← hda, ← hds] at hrel
336 obtain ⟨r1, r2, rb1, -⟩ := hrel
337 simp only [seg_length, s0, hLn] at r1 r2 rb1
338 refine OkOn.bind_ex (R := fun x => x = d) ⟨d, hd, rfl⟩ ?_
339 intro x hx
340 rw [hx]
341 dsimp only
342 have hres := result_value a (if d.adler ≥ BASE then d.adler - BASE else d.adler) (d.sum2 % BASE)
343 (seg bytes off L) ?_ ?_
344 · split
345 · next hge => exact ⟨_, OkOn.pure _ _, by simpa [hge] using hres⟩
346 · next hlt => exact ⟨_, OkOn.pure _ _, by simpa [hlt] using hres⟩
347 · split
348 · next hge =>
349 rw [ge_iff_le, UInt64.le_iff_toNat_le, base_toNat] at hge
350 rw [sub_small _ _ (by rw [base_toNat]; omega), base_toNat, ← r1]; omega
351 · next hlt =>
352 rw [ge_iff_le, UInt64.le_iff_toNat_le, base_toNat] at hlt
353 rw [← r1]; omega
354 · rw [UInt64.toNat_mod, base_toNat, r2]
355
356
357theorem adler32_z_short_format_any (hb : Space.get h ref = some bytes) (a : UInt64) (off L : Nat)
358 (hfit : off + L ≤ bytes.size) (h16 : L < 16) (h1 : L ≠ 1) :
359 C.run (adler32_z a (.ref ref off) L.toUInt64) h =
360 .ok ((ZlibF.Spec.adler32Update (canonicalStart a) (seg bytes off L)).toUInt64, h) := by
361 obtain ⟨r, hr, hv⟩ := adler32_z_short_any hb a off L hfit h16 h1
362 change C.run (adler32_z a (.ref ref off) L.toUInt64) h = .ok (r, h) at hr
363 rw [hr]
364 congr 2
365 apply UInt64.toNat_inj.mp
366 rw [UInt32.toNat_toUInt64, adler_format_seed, UInt32.toNat_ofNat', hv]
367 have hs := sums_lt (a.toNat % 65536 % 65521) (a.toNat / 65536 % 65536 % 65521)
368 (seg bytes off L) (Nat.mod_lt _ (by decide)) (Nat.mod_lt _ (by decide))
369 change (sums _ _ _).1 < 65521 ∧ (sums _ _ _).2 < 65521 at hs
370 have he : Zlib.Adler32.Spec.adler32 a.toNat (seg bytes off L) < 2 ^ 32 := by
371 unfold Zlib.Adler32.Spec.adler32
372 simp only [Zlib.Adler32.Spec.BASE]
373 omega
374 exact (Nat.mod_eq_of_lt he).symm
375
376
377theorem adler32_z_any_format (hb : Space.get h ref = some bytes) (a : UInt64) (off L : Nat)
378 (hfit : off + L ≤ bytes.size) (hL : L < 2 ^ 64) (h1 : L ≠ 1) :
379 C.run (adler32_z a (.ref ref off) L.toUInt64) h =
380 .ok ((ZlibF.Spec.adler32Update (canonicalStart a) (seg bytes off L)).toUInt64, h) := by
381 by_cases h16 : L < 16
382 · exact adler32_z_short_format_any hb a off L hfit h16 h1
383 · obtain ⟨r, hr, hv⟩ := adler32_z_long_any hb a off L hfit hL (by omega)
384 change C.run (adler32_z a (.ref ref off) L.toUInt64) h = .ok (r, h) at hr
385 rw [hr]
386 congr 2
387 apply UInt64.toNat_inj.mp
388 rw [UInt32.toNat_toUInt64, adler_format_seed, UInt32.toNat_ofNat', hv]
389 have hs := sums_lt (a.toNat % 65536 % 65521) (a.toNat / 65536 % 65536 % 65521)
390 (seg bytes off L) (Nat.mod_lt _ (by decide)) (Nat.mod_lt _ (by decide))
391 change (sums _ _ _).1 < 65521 ∧ (sums _ _ _).2 < 65521 at hs
392 have he : Zlib.Adler32.Spec.adler32 a.toNat (seg bytes off L) < 2 ^ 32 := by
393 unfold Zlib.Adler32.Spec.adler32
394 simp only [Zlib.Adler32.Spec.BASE]
395 omega
396 exact (Nat.mod_eq_of_lt he).symm
397
398/-- `uLong adler32(uLong adler, const Bytef *buf, uInt len)`: the
39932-bit entry preserves the full general-reference format result. -/
400theorem adler32_any_format (hb : Space.get h ref = some bytes) (a : UInt64)
401 (off : Nat) (len : UInt32) (hfit : off + len.toNat ≤ bytes.size)
402 (h1 : len.toNat ≠ 1) :
403 C.run (Zlib.Adler32.adler32 a (.ref ref off) len) h =
404 .ok ((ZlibF.Spec.adler32Update (canonicalStart a) (seg bytes off len.toNat)).toUInt64, h) := by
405 simpa [Zlib.Adler32.adler32, UInt32.toNat_toUInt64, UInt64.ofNat_toNat] using
406 (adler32_z_any_format hb a off len.toNat hfit (by have := len.toNat_lt; omega) h1)
407
408#print axioms adler32_z_any_format
409#print axioms adler32_any_format
410end Zlib.Adler32.Proofs