REFERENCE / ZLIB × LEAN
trees.c.bits.lean
Source snapshot ·
bd790cbe535672af · 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.«trees.c.inv»
2
3/-!
4# trees.c: the bit writers (`put_byte`, `put_short`, `send_bits`, `bi_reverse`, `bi_flush`, `bi_windup`)
5-/
6
7namespace Zlib.Trees.Proofs.Out
8open C Zlib.Trees
9
10theorem put_byte_run {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
11 (hb : TreesBase h id d b buf) (hroom : d.pending.toNat < buf.size) (c : UInt8) :
12 put_byte (some (.tab id)) c h =
13 .ok ((), setD (setB h b (buf.set! d.pending.toNat c)) id { d with pending := d.pending + 1 }) := by
14 have hg : Space.get h (BRef.blk b) = some buf := hb.bytes
15 have e1 := Ptr.add_nat_ok (off := 0) (n := d.pending.toNat) hg (by omega)
16 have e2 := Ptr.store_ok (v := c) (off := 0 + d.pending.toNat) hg hb.rw (by omega)
17 unfold OkOn at e1
18 unfold put_byte
19 rw [bind_app, rd_run hb.dstate]
20 simp only [hb.pbuf]
21 rw [bind_app, e1]
22 simp only []
23 rw [bind_app]
24 unfold store8
25 rw [e2]
26 simp only []
27 have hd : (Space.put h (BRef.blk b) (buf.set! (0 + d.pending.toNat) c)).dstates id = some d := hb.dstate
28 rw [md_run hd]
29 simp [setD, Space.put, setB]
30 rw [hb.pbuf]
31
32
33@[simp] theorem setB_setB (h : Heap) (b : Nat) (a a' : Array UInt8) : setB (setB h b a) b a' = setB h b a' := by
34 simp [setB, upd_upd]
35
36theorem TreesBase.step {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
37 (hb : TreesBase h id d b buf) (buf' : Array UInt8) (hsz : buf'.size = buf.size) (d' : DeflateState)
38 (hw : d'.WellFormed) (h1 : d'.pending_buf = d.pending_buf) (h2 : d'.pending_buf_size = d.pending_buf_size)
39 (h3 : d'.sym_buf = d.sym_buf) (h4 : d'.lit_bufsize = d.lit_bufsize) (h5 : d'.sym_end = d.sym_end)
40 (h6 : d'.pending.toNat ≤ d'.pending_buf_size.toNat) :
41 TreesBase (setD (setB h b buf') id d') id d' b buf' where
42 dstate := by simp
43 wf := hw
44 static := by simpa using hb.static
45 pbuf := by rw [h1]; exact hb.pbuf
46 bytes := by simp
47 rw := by simpa using hb.rw
48 size := by rw [hsz, h4]; exact hb.size
49 psize := by rw [hsz, h2]; exact hb.psize
50 sym := by rw [h3, h4]; exact hb.sym
51 lit_lo := by rw [h4]; exact hb.lit_lo
52 lit_hi := by rw [h4]; exact hb.lit_hi
53 sym_end := by rw [h5, h4]; exact hb.sym_end
54 pending_le := h6
55
56theorem toNat_add_one_u64 {x : UInt64} (hx : x.toNat < 2 ^ 20) : (x + 1).toNat = x.toNat + 1 := by
57 rw [UInt64.toNat_add]; simp; omega
58
59theorem toNat_add_two_u64 {x : UInt64} (hx : x.toNat < 2 ^ 20) : (x + 2).toNat = x.toNat + 2 := by
60 rw [UInt64.toNat_add]; simp; omega
61
62theorem TreesBase.pending_small {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
63 (hb : TreesBase h id d b buf) : d.pending.toNat < 2 ^ 20 := by
64 have := hb.pending_le; have := hb.psize; have := hb.size; have := hb.lit_hi; omega
65
66theorem put_short_run {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
67 (hb : TreesBase h id d b buf) (hroom : d.pending.toNat + 2 ≤ buf.size) (w : UInt16) :
68 put_short (some (.tab id)) w h =
69 .ok ((), setD (setB h b ((buf.set! d.pending.toNat (w &&& 0xff).toUInt8).set! (d.pending.toNat + 1)
70 (w >>> 8).toUInt8)) id { d with pending := d.pending + 2 }) := by
71 have hp := hb.pending_small
72 have hp1 := toNat_add_one_u64 hp
73 have hs1 := hb.size
74 have hs2 := hb.lit_hi
75 unfold put_short
76 rw [bind_app, put_byte_run hb (by omega)]
77 simp only []
78 have hb1 := hb.step (buf.set! d.pending.toNat (w &&& 0xff).toUInt8) (by simp) { d with pending := d.pending + 1 }
79 hb.wf rfl rfl rfl rfl rfl (by simp only []; rw [hp1]; have := hb.psize; omega)
80 rw [put_byte_run hb1 (by simp only []; rw [hp1]; simp; omega)]
81 simp only [setD_setB, setD_setD, setB_setB]
82 have e2 : d.pending + 1 + 1 = d.pending + 2 := by
83 apply UInt64.toNat_inj.mp
84 rw [toNat_add_one_u64 (by rw [hp1]; omega), hp1, toNat_add_two_u64 hp]
85 simp only [e2, hp1]
86
87
88theorem Buf_size_toInt : Buf_size.toInt = 16 := by decide
89
90/-- `(ush)value` as a natural number. -/
91def v16 (value : Int32) : Nat := (i2us value).toNat
92
93theorem v16_lt (value : Int32) : v16 value < 65536 := by
94 unfold v16; exact UInt16.toNat_lt _
95
96theorem shlUs_eq (value c : Int32) (h0 : 0 ≤ c.toInt) (h1 : c.toInt ≤ 31)
97 (h2 : v16 value * 2 ^ c.toInt.toNat < 2147483648) : shlUs value c = pure (v16 value * 2 ^ c.toInt.toNat) := by
98 funext h
99 have : ¬ (c.toInt < 0 ∨ 31 < c.toInt) := by omega
100 have h3 : ¬ ((i2us value).toNat * 2 ^ c.toInt.toNat ≥ 2147483648) := by unfold v16 at h2; omega
101 simp only [shlUs, this, h3, ite_false]
102 rfl
103
104theorem shrUs_eq (value c : Int32) (h0 : 0 ≤ c.toInt) (h1 : c.toInt ≤ 31) :
105 shrUs value c = pure (UInt16.ofNat (v16 value >>> c.toInt.toNat)) := by
106 funext h
107 have : ¬ (c.toInt < 0 ∨ 31 < c.toInt) := by omega
108 simp only [shrUs, this, ite_false]
109 rfl
110
111theorem i32_lt_iff {a b : Int32} : a < b ↔ a.toInt < b.toInt := Int32.lt_iff_toInt_lt
112
113
114theorem pow_mul_lt (v n m : Nat) (hv : v < 2 ^ n) : v * 2 ^ m < 2 ^ (n + m) := by
115 rw [Nat.pow_add]; exact Nat.mul_lt_mul_of_pos_right hv (Nat.pow_pos (by omega))
116
117theorem send_bits_B {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
118 (hb : TreesBase h id d b buf) (hr : TreesRun id d) (value len : Int32)
119 (hl0 : 0 ≤ len.toInt) (hl1 : len.toInt ≤ 15) (hv : v16 value < 2 ^ len.toInt.toNat)
120 (hcase : d.bi_valid.toInt + len.toInt ≤ 16) :
121 send_bits (some (.tab id)) value len h =
122 .ok ((), setD h id { d with
123 bi_buf := UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat),
124 bi_valid := Int32.ofInt (d.bi_valid.toInt + len.toInt) }) := by
125 have hbl := hr.bi_lo
126 have hbh := hr.bi_hi
127 have hlt := pow_mul_lt _ _ d.bi_valid.toInt.toNat hv
128 have hpow : 2 ^ (len.toInt.toNat + d.bi_valid.toInt.toNat) ≤ 2 ^ 16 :=
129 Nat.pow_le_pow_right (by omega) (by omega)
130 have hsh := shlUs_eq value d.bi_valid hr.bi_lo (by have := hr.bi_hi; omega) (by omega)
131 have hsub := isub_eq (a := Buf_size) (b := len) (by rw [Buf_size_toInt]; omega) (by rw [Buf_size_toInt]; omega)
132 have hnc : ¬ (d.bi_valid > Int32.ofInt (Buf_size.toInt - len.toInt)) := by
133 rw [gt_iff_lt, i32_lt_iff, i32_ofInt_toInt (by rw [Buf_size_toInt]; omega) (by rw [Buf_size_toInt]; omega),
134 Buf_size_toInt]
135 omega
136 unfold send_bits
137 rw [bind_app, rd_run hb.dstate]
138 simp only []
139 rw [bind_app, hsub]
140 simp only [pure_app, hnc, ite_false]
141 rw [bind_app, hsh]
142 simp only [pure_app]
143 rw [bind_app, md_run hb.dstate]
144 simp only []
145 have hd1 : (setD h id { d with bi_buf := UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat) }).dstates id
146 = some _ := setD_dstates_same _ _ _
147 rw [bind_app, rd_run hd1]
148 simp only []
149 have hadd := iadd_eq (a := d.bi_valid) (b := len) (by omega) (by omega)
150 rw [bind_app, hadd]
151 simp only [pure_app]
152 rw [md_run hd1]
153 simp
154
155
156theorem TreesBase.stepD {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
157 (hb : TreesBase h id d b buf) (d' : DeflateState)
158 (hw : d'.WellFormed) (h1 : d'.pending_buf = d.pending_buf) (h2 : d'.pending_buf_size = d.pending_buf_size)
159 (h3 : d'.sym_buf = d.sym_buf) (h4 : d'.lit_bufsize = d.lit_bufsize) (h5 : d'.sym_end = d.sym_end)
160 (h6 : d'.pending.toNat ≤ d'.pending_buf_size.toNat) :
161 TreesBase (setD h id d') id d' b buf where
162 dstate := by simp
163 wf := hw
164 static := by simpa using hb.static
165 pbuf := by rw [h1]; exact hb.pbuf
166 bytes := by simpa using hb.bytes
167 rw := by simpa using hb.rw
168 size := by rw [h4]; exact hb.size
169 psize := by rw [h2]; exact hb.psize
170 sym := by rw [h3, h4]; exact hb.sym
171 lit_lo := by rw [h4]; exact hb.lit_lo
172 lit_hi := by rw [h4]; exact hb.lit_hi
173 sym_end := by rw [h5, h4]; exact hb.sym_end
174 pending_le := h6
175
176theorem send_bits_A {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
177 (hb : TreesBase h id d b buf) (hr : TreesRun id d) (value len : Int32)
178 (hl0 : 0 ≤ len.toInt) (hl1 : len.toInt ≤ 15) (hv : v16 value < 2 ^ len.toInt.toNat)
179 (hcase : 16 < d.bi_valid.toInt + len.toInt) (hroom : d.pending.toNat + 2 ≤ buf.size) :
180 send_bits (some (.tab id)) value len h =
181 .ok ((), setD (setB h b ((buf.set! d.pending.toNat
182 (UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat) &&& 0xff).toUInt8).set!
183 (d.pending.toNat + 1) (UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat) >>> 8).toUInt8))
184 id { d with
185 pending := d.pending + 2,
186 bi_buf := UInt16.ofNat (v16 value >>> (16 - d.bi_valid.toInt).toNat),
187 bi_valid := Int32.ofInt (d.bi_valid.toInt + len.toInt - 16) }) := by
188 have hbl := hr.bi_lo
189 have hbh := hr.bi_hi
190 have hlt := pow_mul_lt _ _ d.bi_valid.toInt.toNat hv
191 have hpow : 2 ^ (len.toInt.toNat + d.bi_valid.toInt.toNat) ≤ 2 ^ 31 :=
192 Nat.pow_le_pow_right (by omega) (by omega)
193 have hsh := shlUs_eq value d.bi_valid hr.bi_lo (by omega) (by omega)
194 have hsub := isub_eq (a := Buf_size) (b := len) (by rw [Buf_size_toInt]; omega) (by rw [Buf_size_toInt]; omega)
195 have hc : d.bi_valid > Int32.ofInt (Buf_size.toInt - len.toInt) := by
196 rw [gt_iff_lt, i32_lt_iff, i32_ofInt_toInt (by rw [Buf_size_toInt]; omega) (by rw [Buf_size_toInt]; omega),
197 Buf_size_toInt]
198 omega
199 have hb1 : TreesBase (setD h id { d with bi_buf := (UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat)) }) id { d with bi_buf := (UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat)) } b buf := hb.stepD _ hb.wf rfl rfl rfl rfl rfl hb.pending_le
200 have hd1 : (setD h id { d with bi_buf := (UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat)) }).dstates id = some { d with bi_buf := (UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat)) } := setD_dstates_same _ _ _
201 have hsr : isub Buf_size d.bi_valid = pure (Int32.ofInt (16 - d.bi_valid.toInt)) :=
202 isub_eq (by rw [Buf_size_toInt]; omega) (by rw [Buf_size_toInt]; omega) |>.trans (by rw [Buf_size_toInt])
203 have hrr := shrUs_eq value (Int32.ofInt (16 - d.bi_valid.toInt)) (by rw [i32_ofInt_toInt (by omega) (by omega)]; omega)
204 (by rw [i32_ofInt_toInt (by omega) (by omega)]; omega)
205 rw [i32_ofInt_toInt (by omega) (by omega)] at hrr
206 have hsl : isub len Buf_size = pure (Int32.ofInt (len.toInt - 16)) :=
207 isub_eq (by rw [Buf_size_toInt]; omega) (by rw [Buf_size_toInt]; omega) |>.trans (by rw [Buf_size_toInt])
208 unfold send_bits
209 rw [bind_app, rd_run hb.dstate]
210 simp only []
211 rw [bind_app, hsub]
212 simp only [pure_app, hc, ite_true]
213 rw [bind_app, hsh]
214 simp only [pure_app]
215 rw [bind_app, md_run hb.dstate]
216 simp only []
217 -- put_short s (← rd s).bi_buf
218 rw [bind_app, rd_run hd1]
219 simp only []
220 rw [bind_app, put_short_run hb1 (by simpa using hroom)]
221 simp only [setD_setB, setD_setD]
222 have hadd : iadd d.bi_valid (Int32.ofInt (len.toInt - 16)) =
223 pure (Int32.ofInt (d.bi_valid.toInt + len.toInt - 16)) := by
224 rw [iadd_eq (by rw [i32_ofInt_toInt (by omega) (by omega)]; omega)
225 (by rw [i32_ofInt_toInt (by omega) (by omega)]; omega), i32_ofInt_toInt (by omega) (by omega)]
226 simp only [Int.add_sub_assoc]
227 simp (disch := simp [hb.dstate]) only [bind_app, rd_run', md_run', hsr, hrr, hsl, hadd, pure_app, rdD_setD_same,
228 rdD_setB, setD_setD, setD_setB]
229 done
230
231
232theorem setB_self {h : Heap} {b : Nat} {buf : Array UInt8} (e : h.bytes b = some buf) : setB h b buf = h := by
233 have := upd_self h.bytes b buf e
234 cases h; simp only [setB] at *; simp_all
235
236theorem natBits_or_shift (old w n m : Nat) (ho : old < 2 ^ n) :
237 natBits (old ||| w * 2 ^ n) (n + m) = natBits old n ++ natBits w m := by
238 have hor : old ||| w * 2 ^ n = old + w * 2 ^ n := by
239 rw [Nat.or_comm, ← Nat.shiftLeft_eq, ← Nat.shiftLeft_add_eq_or_of_lt ho, Nat.add_comm]
240 rw [hor, natBits_add]
241 congr 1
242 · apply natBits_congr
243 rw [Nat.add_mul_mod_self_right]
244 · rw [Nat.shiftRight_eq_div_pow, Nat.add_mul_div_right _ _ (Nat.pow_pos (by omega)),
245 Nat.div_eq_of_lt ho, Nat.zero_add]
246
247theorem natBits_shr_lt (v n k : Nat) (hv : v < 2 ^ n) (hk : k ≤ n) : v >>> k < 2 ^ (n - k) := by
248 rw [Nat.shiftRight_eq_div_pow, Nat.div_lt_iff_lt_mul (Nat.pow_pos (by omega)), ← Nat.pow_add]
249 have : n - k + k = n := by omega
250 rw [this]; exact hv
251
252theorem toNat_lo (bb : UInt16) : ((bb &&& 0xff).toUInt8).toNat = bb.toNat % 256 := by
253 simp only [UInt16.toNat_toUInt8, UInt16.toNat_and]
254 rw [show (0xff : UInt16).toNat = 2 ^ 8 - 1 from rfl, Nat.and_two_pow_sub_one_eq_mod]; omega
255
256theorem natBits_word (W : UInt16) :
257 natBits (((W &&& 0xff).toUInt8).toNat) 8 ++ natBits (((W >>> 8).toUInt8).toNat) 8 = natBits W.toNat 16 := by
258 rw [show (16 : Nat) = 8 + 8 from rfl, natBits_add]
259 congr 1
260 · apply natBits_congr
261 rw [toNat_lo]; show W.toNat % 256 % 2 ^ 8 = W.toNat % 2 ^ 8; simp
262 · apply natBits_congr
263 simp [UInt16.toNat_toUInt8, UInt16.toNat_shiftRight]
264
265
266theorem u16_toNat_ofNat_mod (x : Nat) : (UInt16.ofNat x).toNat = x % 65536 := by
267 first | exact UInt16.toNat_ofNat x | simp | (simp [UInt16.toNat, UInt16.ofNat, BitVec.toNat_ofNat])
268
269theorem u16_toNat_ofNat_lt {x : Nat} (hx : x < 65536) : (UInt16.ofNat x).toNat = x := by
270 first | exact UInt16.toNat_ofNat_of_lt' hx | exact UInt16.toNat_ofNat_of_lt hx | (simp [UInt16.toNat_ofNat]; omega) | (simp; omega)
271
272theorem send_bits_spec_B {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
273 (hI : TreesInvAt h id d b buf) (value len : Int32)
274 (hl0 : 0 ≤ len.toInt) (hl1 : len.toInt ≤ 15) (hv : v16 value < 2 ^ len.toInt.toNat)
275 (hcase : d.bi_valid.toInt + len.toInt ≤ 16) :
276 ∃ d', send_bits (some (.tab id)) value len h = .ok ((), setD h id d') ∧
277 TreesInvAt (setD h id d') id d' b buf ∧
278 outBits buf d' = outBits buf d ++ natBits (v16 value) len.toInt.toNat ∧
279 d'.pending = d.pending ∧ (∃ a v, d' = { d with bi_buf := a, bi_valid := v }) := by
280 obtain ⟨hb, hr⟩ := hI
281 have hbl := hr.bi_lo
282 have hbh := hr.bi_hi
283 have hbb := hr.bi_buf
284 have hlt := pow_mul_lt _ _ d.bi_valid.toInt.toNat hv
285 have hpow : 2 ^ (len.toInt.toNat + d.bi_valid.toInt.toNat) ≤ 2 ^ 16 :=
286 Nat.pow_le_pow_right (by omega) (by omega)
287 have hor : d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat < 2 ^ (d.bi_valid.toInt.toNat + len.toInt.toNat) := by
288 apply Nat.or_lt_two_pow
289 · exact Nat.lt_of_lt_of_le hbb (Nat.pow_le_pow_right (by omega) (by omega))
290 · rw [Nat.add_comm]; exact hlt
291 have hx : d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat < 65536 := by
292 have : 2 ^ (d.bi_valid.toInt.toNat + len.toInt.toNat) ≤ 2 ^ 16 := by rw [Nat.add_comm]; exact hpow
293 omega
294 have hnv : (Int32.ofInt (d.bi_valid.toInt + len.toInt)).toInt = d.bi_valid.toInt + len.toInt :=
295 i32_ofInt_toInt (by omega) (by omega)
296 refine ⟨_, send_bits_B hb hr value len hl0 hl1 hv hcase, ?_, ?_, rfl, _, _, rfl⟩
297 · refine ⟨hb.stepD _ hb.wf rfl rfl rfl rfl rfl hb.pending_le, ?_⟩
298 refine ⟨hr.ldyn, hr.lstat, hr.ddyn, hr.dstat, hr.bldyn, hr.blstat, ?_, ?_, ?_, hr.sym_next_le, hr.sym_next_mod⟩
299 · show 0 ≤ (Int32.ofInt _).toInt; rw [hnv]; omega
300 · show (Int32.ofInt _).toInt ≤ 16; rw [hnv]; omega
301 · show (UInt16.ofNat _).toNat < 2 ^ (Int32.ofInt _).toInt.toNat
302 rw [hnv, u16_toNat_ofNat_lt hx]
303 have : (d.bi_valid.toInt + len.toInt).toNat = d.bi_valid.toInt.toNat + len.toInt.toNat := by omega
304 rw [this]; exact hor
305 · unfold outBits
306 show bytesBits buf d.pending.toNat ++ natBits (UInt16.ofNat _).toNat (Int32.ofInt _).toInt.toNat = _
307 rw [hnv, u16_toNat_ofNat_lt hx]
308 have : (d.bi_valid.toInt + len.toInt).toNat = d.bi_valid.toInt.toNat + len.toInt.toNat := by omega
309 rw [this, natBits_or_shift _ _ _ _ hbb, List.append_assoc]
310
311
312theorem getD_set_u8 (a : Array UInt8) (i j : Nat) (v : UInt8) :
313 (a.set! i v).getD j 0 = if i = j ∧ i < a.size then v else a.getD j 0 := by
314 rw [Array.set!_eq_setIfInBounds, Array.getD_eq_getD_getElem?, Array.getD_eq_getD_getElem?,
315 Array.getElem?_setIfInBounds]
316 by_cases h1 : i = j
317 · subst h1; by_cases h2 : i < a.size <;> simp [h2]
318 · simp [h1]
319
320/-- Two bytes appended at `p`: the bits of the pending bytes grow by those of the two bytes. -/
321theorem bytesBits_two {buf : Array UInt8} {p : Nat} (v0 v1 : UInt8) (hp : p + 2 ≤ buf.size) :
322 bytesBits ((buf.set! p v0).set! (p + 1) v1) (p + 2) = bytesBits buf p ++ natBits v0.toNat 8 ++ natBits v1.toNat 8 := by
323 have e1 : ((buf.set! p v0).set! (p + 1) v1).getD (p + 1) 0 = v1 := by
324 rw [getD_set_u8]; simp; omega
325 have e0 : ((buf.set! p v0).set! (p + 1) v1).getD p 0 = v0 := by
326 rw [getD_set_u8, getD_set_u8]; simp
327 intro h; omega
328 rw [show p + 2 = (p + 1) + 1 from rfl, bytesBits_succ, bytesBits_succ, bytesBits_set _ (by omega),
329 bytesBits_set _ (by omega), e1, e0]
330
331
332theorem send_bits_spec_A {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
333 (hI : TreesInvAt h id d b buf) (value len : Int32)
334 (hl0 : 0 ≤ len.toInt) (hl1 : len.toInt ≤ 15) (hv : v16 value < 2 ^ len.toInt.toNat)
335 (hcase : 16 < d.bi_valid.toInt + len.toInt) (hroom : d.pending.toNat + 2 ≤ buf.size) :
336 ∃ buf' d', send_bits (some (.tab id)) value len h = .ok ((), setD (setB h b buf') id d') ∧
337 TreesInvAt (setD (setB h b buf') id d') id d' b buf' ∧
338 outBits buf' d' = outBits buf d ++ natBits (v16 value) len.toInt.toNat ∧
339 buf'.size = buf.size ∧
340 (∀ i, (i < d.pending.toNat ∨ d.pending.toNat + 2 ≤ i) → buf'.getD i 0 = buf.getD i 0) ∧
341 d'.pending = d.pending + 2 ∧ (∃ a v, d' = { d with pending := d.pending + 2, bi_buf := a, bi_valid := v }) := by
342 obtain ⟨hb, hr⟩ := hI
343 have hbl := hr.bi_lo
344 have hbh := hr.bi_hi
345 have hbb := hr.bi_buf
346 have hp := hb.pending_small
347 have hp2 := toNat_add_two_u64 hp
348 have hs1 := hb.size
349 have hs2 := hb.lit_hi
350 have hpsz := hb.psize
351 have hvl := v16_lt value
352 obtain ⟨W, hW⟩ : ∃ W, W = UInt16.ofNat (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat) := ⟨_, rfl⟩
353 have hA := send_bits_A hb hr value len hl0 hl1 hv hcase hroom
354 rw [← hW] at hA
355 have hnv : (Int32.ofInt (d.bi_valid.toInt + len.toInt - 16)).toInt = d.bi_valid.toInt + len.toInt - 16 :=
356 i32_ofInt_toInt (by omega) (by omega)
357 have hshr : v16 value >>> (16 - d.bi_valid.toInt).toNat < 2 ^ (d.bi_valid.toInt + len.toInt - 16).toNat := by
358 have := natBits_shr_lt (v16 value) len.toInt.toNat (16 - d.bi_valid.toInt).toNat hv (by omega)
359 have e : len.toInt.toNat - (16 - d.bi_valid.toInt).toNat = (d.bi_valid.toInt + len.toInt - 16).toNat := by omega
360 rwa [e] at this
361 have hsr : v16 value >>> (16 - d.bi_valid.toInt).toNat ≤ v16 value := by
362 rw [Nat.shiftRight_eq_div_pow]; exact Nat.div_le_self _ _
363 have hbuf2 : ((buf.set! d.pending.toNat (W &&& 0xff).toUInt8).set! (d.pending.toNat + 1) (W >>> 8).toUInt8).size
364 = buf.size := by simp
365 refine ⟨_, _, hA, ?_, ?_, hbuf2, ?_, ?_, _, _, rfl⟩
366 · refine ⟨hb.step _ hbuf2 _ hb.wf rfl rfl rfl rfl rfl (by simp only []; rw [hp2]; omega), ?_⟩
367 refine ⟨hr.ldyn, hr.lstat, hr.ddyn, hr.dstat, hr.bldyn, hr.blstat, ?_, ?_, ?_, hr.sym_next_le, hr.sym_next_mod⟩
368 · show 0 ≤ (Int32.ofInt _).toInt; rw [hnv]; omega
369 · show (Int32.ofInt _).toInt ≤ 16; rw [hnv]; omega
370 · show (UInt16.ofNat _).toNat < 2 ^ (Int32.ofInt _).toInt.toNat
371 rw [hnv, u16_toNat_ofNat_lt (by omega)]
372 exact hshr
373 · unfold outBits
374 show bytesBits _ (d.pending + 2).toNat ++ natBits (UInt16.ofNat _).toNat (Int32.ofInt _).toInt.toNat = _
375 rw [hp2, bytesBits_two _ _ (by omega), hnv, u16_toNat_ofNat_lt (by omega)]
376 have hw16 : natBits (((W &&& 0xff).toUInt8).toNat) 8 ++ natBits (((W >>> 8).toUInt8).toNat) 8
377 = natBits d.bi_buf.toNat d.bi_valid.toInt.toNat ++ natBits (v16 value) (16 - d.bi_valid.toInt).toNat := by
378 rw [natBits_word]
379 have : natBits W.toNat 16
380 = natBits (d.bi_buf.toNat ||| v16 value * 2 ^ d.bi_valid.toInt.toNat) 16 := by
381 apply natBits_congr
382 rw [hW, u16_toNat_ofNat_mod]; simp
383 rw [this, show (16 : Nat) = d.bi_valid.toInt.toNat + (16 - d.bi_valid.toInt).toNat by omega,
384 natBits_or_shift _ _ _ _ hbb]
385 have hsplit : natBits (v16 value) len.toInt.toNat =
386 natBits (v16 value) (16 - d.bi_valid.toInt).toNat ++
387 natBits (v16 value >>> (16 - d.bi_valid.toInt).toNat) (d.bi_valid.toInt + len.toInt - 16).toNat := by
388 rw [← natBits_add]; congr 1; omega
389 rw [hsplit]
390 have := congrArg (· ++ natBits (v16 value >>> (16 - d.bi_valid.toInt).toNat)
391 (d.bi_valid.toInt + len.toInt - 16).toNat) hw16
392 simp only [List.append_assoc] at this ⊢
393 rw [this]
394 · intro i hi
395 have h1 : ¬ (d.pending.toNat + 1 = i) := by omega
396 have h2 : ¬ (d.pending.toNat = i) := by omega
397 rw [getD_set_u8, getD_set_u8]
398 simp [h1, h2]
399 · rfl
400
401
402/-- **`send_bits`, safety and specification.** `send_bits(s, value, length)` appends the `length` low bits of `value`
403(least significant first) to the output bit stream `outBits`: the bits of the pending bytes followed by those of
404`bi_buf`. Preconditions: `TreesInvAt` (so `bi_valid <= 16`, no stray bits in `bi_buf`); `0 <= length <= 15` (every
405caller in `trees.c` sends at most 15 bits: codes have length at most 15, extra bits at most 13);
406`(ush)value < 2^length` (the value has no bits above its length: true for the codes of `gen_codes`, for the extra
407bits, and for the block header); and room: the bits already written plus `length` fit in `pending_buf`
408(`8 * pending + bi_valid + length <= 8 * pending_buf_size`; `deflate.c` establishes this by the overlay lemma F9).
409Afterwards: no fault, `TreesInvAt` again for the same byte block `b`, the stream grew by exactly the bits, at most
410two bytes were written at `pending_buf[pending]` and the bytes outside `[pending, pending')` are unchanged. -/
411theorem send_bits_spec {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
412 (hI : TreesInvAt h id d b buf) (value len : Int32)
413 (hl0 : 0 ≤ len.toInt) (hl1 : len.toInt ≤ 15) (hv : v16 value < 2 ^ len.toInt.toNat)
414 (hroom : 8 * d.pending.toNat + d.bi_valid.toInt.toNat + len.toInt.toNat ≤ 8 * buf.size) :
415 ∃ buf' d', send_bits (some (.tab id)) value len h = .ok ((), setD (setB h b buf') id d') ∧
416 TreesInvAt (setD (setB h b buf') id d') id d' b buf' ∧
417 outBits buf' d' = outBits buf d ++ natBits (v16 value) len.toInt.toNat ∧
418 buf'.size = buf.size ∧
419 (∀ i, (i < d.pending.toNat ∨ d'.pending.toNat ≤ i) → buf'.getD i 0 = buf.getD i 0) ∧
420 d.pending.toNat ≤ d'.pending.toNat ∧ d'.pending.toNat ≤ d.pending.toNat + 2 ∧
421 (∃ p a v, d' = { d with pending := p, bi_buf := a, bi_valid := v }) := by
422 have hbl := hI.run.bi_lo
423 have hbh := hI.run.bi_hi
424 by_cases hcase : d.bi_valid.toInt + len.toInt ≤ 16
425 · obtain ⟨d', e, hinv, hbits, hpend, a, v, hd'⟩ := send_bits_spec_B hI value len hl0 hl1 hv hcase
426 refine ⟨buf, d', ?_, ?_, hbits, rfl, fun _ _ => rfl, by rw [hpend]; exact Nat.le_refl _,
427 by rw [hpend]; omega, ?_⟩
428 · rw [setB_self hI.base.bytes]; exact e
429 · rw [setB_self hI.base.bytes]; exact hinv
430 · exact ⟨d.pending, a, v, by rw [hd']⟩
431 · have hcase' : 16 < d.bi_valid.toInt + len.toInt := by omega
432 have hpe := hI.base.pending_small
433 obtain ⟨buf', d', e, hinv, hbits, hsz, hfr, hpend, a, v, hd'⟩ :=
434 send_bits_spec_A hI value len hl0 hl1 hv hcase' (by omega)
435 have hp2 := toNat_add_two_u64 hpe
436 refine ⟨buf', d', e, hinv, hbits, hsz, ?_, by rw [hpend, hp2]; omega, by rw [hpend, hp2]; omega,
437 ⟨_, a, v, hd'⟩⟩
438 intro i hi
439 apply hfr
440 rw [hpend, hp2] at hi
441 omega
442
443
444theorem i32_beq_toInt (a b : Int32) : (a == b) = decide (a.toInt = b.toInt) := by
445 by_cases h : a = b
446 · subst h; simp
447 · have : a.toInt ≠ b.toInt := fun e => h (Int32.toInt_inj.mp e)
448 simp [h, this]
449
450theorem i32_le_toInt {a b : Int32} : a ≤ b ↔ a.toInt ≤ b.toInt := Int32.le_iff_toInt_le
451
452theorem i32_16 : (16 : Int32).toInt = 16 := by decide
453theorem i32_8 : (8 : Int32).toInt = 8 := by decide
454theorem i32_0 : (0 : Int32).toInt = 0 := by decide
455
456theorem u16_shr8_toNat (w : UInt16) : (w >>> 8).toNat = w.toNat / 256 := by
457 simp [Nat.shiftRight_eq_div_pow]
458
459theorem bi_flush_16 {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
460 (hb : TreesBase h id d b buf) (hv : d.bi_valid.toInt = 16) (hroom : d.pending.toNat + 2 ≤ buf.size) :
461 bi_flush (some (.tab id)) h =
462 .ok ((), setD (setB h b ((buf.set! d.pending.toNat (d.bi_buf &&& 0xff).toUInt8).set! (d.pending.toNat + 1)
463 (d.bi_buf >>> 8).toUInt8)) id { d with pending := d.pending + 2, bi_buf := 0, bi_valid := 0 }) := by
464 have hc : (d.bi_valid == 16) = true := by rw [i32_beq_toInt, i32_16]; simp [hv]
465 unfold bi_flush
466 rw [bind_app, rd_run hb.dstate]
467 simp only [hc, ite_true]
468 rw [bind_app, rd_run hb.dstate]
469 simp only []
470 rw [bind_app, put_short_run hb hroom]
471 simp (disch := simp [hb.dstate]) only [setD_setB, setD_setD, bind_app, rd_run', md_run', rdD_setD_same, rdD_setB,
472 setD_setB]
473
474
475theorem bi_flush_mid {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
476 (hb : TreesBase h id d b buf) (hv8 : 8 ≤ d.bi_valid.toInt) (hv16 : d.bi_valid.toInt < 16)
477 (hroom : d.pending.toNat + 1 ≤ buf.size) :
478 bi_flush (some (.tab id)) h =
479 .ok ((), setD (setB h b (buf.set! d.pending.toNat d.bi_buf.toUInt8)) id
480 { d with pending := d.pending + 1, bi_buf := d.bi_buf >>> 8,
481 bi_valid := Int32.ofInt (d.bi_valid.toInt - 8) }) := by
482 have hc : (d.bi_valid == 16) = false := by rw [i32_beq_toInt, i32_16]; simp; omega
483 have hge : d.bi_valid ≥ 8 := by
484 show 8 ≤ d.bi_valid
485 rw [i32_le_toInt, i32_8]; exact hv8
486 have hsub : isub d.bi_valid 8 = pure (Int32.ofInt (d.bi_valid.toInt - 8)) :=
487 (isub_eq (a := d.bi_valid) (b := 8) (by rw [i32_8]; omega) (by rw [i32_8]; omega)).trans (by rw [i32_8])
488 have hp := hb.pending_small
489 have hs1 := hb.size
490 have hs2 := hb.lit_hi
491 have hp1 := toNat_add_one_u64 hp
492 unfold bi_flush
493 rw [bind_app, rd_run hb.dstate]
494 simp only [hc, hge, ite_true, ite_false, Bool.false_eq_true]
495 rw [bind_app, rd_run hb.dstate]
496 simp only []
497 rw [bind_app, put_byte_run hb hroom]
498 simp (disch := simp [hb.dstate]) only [setD_setB, setD_setD, bind_app, rd_run', md_run', rdD_setD_same, rdD_setB,
499 hsub, pure_app]
500
501theorem bi_flush_low {h : Heap} {id : Nat} {d : DeflateState} (hd : h.dstates id = some d)
502 (hv8 : d.bi_valid.toInt < 8) : bi_flush (some (.tab id)) h = .ok ((), h) := by
503 have hc : (d.bi_valid == 16) = false := by rw [i32_beq_toInt, i32_16]; simp; omega
504 have hge : ¬ d.bi_valid ≥ 8 := by
505 show ¬ 8 ≤ d.bi_valid
506 rw [i32_le_toInt, i32_8]; omega
507 unfold bi_flush
508 rw [bind_app, rd_run hd]
509 simp only [hc, hge, ite_true, ite_false, Bool.false_eq_true]
510 rfl
511
512
513theorem setD_self {h : Heap} {id : Nat} {d : DeflateState} (e : h.dstates id = some d) : setD h id d = h := by
514 have := upd_self h.dstates id d e
515 cases h; simp only [setD] at *; simp_all
516
517theorem bytesBits_one {buf : Array UInt8} {p : Nat} (v : UInt8) (hp : p < buf.size) :
518 bytesBits (buf.set! p v) (p + 1) = bytesBits buf p ++ natBits v.toNat 8 := by
519 rw [bytesBits_succ, bytesBits_set _ (Nat.le_refl _)]
520 rw [show (buf.set! p v).getD p 0 = v by rw [getD_set_u8]; simp; omega]
521
522theorem natBits_byte (w : UInt16) : natBits (w.toUInt8).toNat 8 = natBits w.toNat 8 := by
523 apply natBits_congr
524 rw [UInt16.toNat_toUInt8]; simp
525
526theorem TreesRun.with_bi {id : Nat} {d : DeflateState} (hr : TreesRun id d) (d' : DeflateState)
527 (h1 : d'.l_desc = d.l_desc) (h2 : d'.d_desc = d.d_desc) (h3 : d'.bl_desc = d.bl_desc)
528 (h4 : 0 ≤ d'.bi_valid.toInt) (h5 : d'.bi_valid.toInt ≤ 16)
529 (h6 : d'.bi_buf.toNat < 2 ^ d'.bi_valid.toInt.toNat) (h7 : d'.sym_next = d.sym_next)
530 (h8 : d'.sym_end = d.sym_end) : TreesRun id d' where
531 ldyn := by rw [h1]; exact hr.ldyn
532 lstat := by rw [h1]; exact hr.lstat
533 ddyn := by rw [h2]; exact hr.ddyn
534 dstat := by rw [h2]; exact hr.dstat
535 bldyn := by rw [h3]; exact hr.bldyn
536 blstat := by rw [h3]; exact hr.blstat
537 bi_lo := h4
538 bi_hi := h5
539 bi_buf := h6
540 sym_next_le := by rw [h7, h8]; exact hr.sym_next_le
541 sym_next_mod := by rw [h7]; exact hr.sym_next_mod
542
543/-- **`bi_flush`, safety and specification.** Writes the complete bytes of `bi_buf` to the pending output: the
544output bit stream `outBits` is unchanged and `bi_valid < 8` afterwards. Precondition: `TreesInvAt` and the bits
545already written fit in `pending_buf` (`8 * pending + bi_valid <= 8 * pending_buf_size`, from the overlay
546lemma F9; `bi_valid = 16` needs 2 bytes, `bi_valid >= 8` needs 1). Called by `_tr_flush_bits` (from
547`flush_pending`) and `_tr_align`. -/
548theorem bi_flush_spec {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
549 (hI : TreesInvAt h id d b buf)
550 (hroom : 8 * d.pending.toNat + d.bi_valid.toInt.toNat ≤ 8 * buf.size) :
551 ∃ buf' d', bi_flush (some (.tab id)) h = .ok ((), setD (setB h b buf') id d') ∧
552 TreesInvAt (setD (setB h b buf') id d') id d' b buf' ∧
553 outBits buf' d' = outBits buf d ∧ d'.bi_valid.toInt < 8 ∧
554 buf'.size = buf.size ∧
555 (∀ i, (i < d.pending.toNat ∨ d'.pending.toNat ≤ i) → buf'.getD i 0 = buf.getD i 0) ∧
556 d.pending.toNat ≤ d'.pending.toNat ∧ d'.pending.toNat ≤ d.pending.toNat + 2 ∧
557 (∃ p a v, d' = { d with pending := p, bi_buf := a, bi_valid := v }) := by
558 obtain ⟨hb, hr⟩ := hI
559 have hbl := hr.bi_lo
560 have hbh := hr.bi_hi
561 have hbb := hr.bi_buf
562 have hp := hb.pending_small
563 have hs1 := hb.size
564 have hs2 := hb.lit_hi
565 have hp1 := toNat_add_one_u64 hp
566 have hpsz := hb.psize
567 by_cases h16 : d.bi_valid.toInt = 16
568 · have hroom2 : d.pending.toNat + 2 ≤ buf.size := by
569 have : d.bi_valid.toInt.toNat = 16 := by omega
570 omega
571 have hp2 := toNat_add_two_u64 hp
572 have hbuf2 : ((buf.set! d.pending.toNat (d.bi_buf &&& 0xff).toUInt8).set! (d.pending.toNat + 1)
573 (d.bi_buf >>> 8).toUInt8).size = buf.size := by simp
574 refine ⟨_, _, bi_flush_16 hb h16 hroom2, ?_, ?_, ?_, hbuf2, ?_, ?_, ?_, ⟨_, _, _, rfl⟩⟩
575 · refine ⟨hb.step _ hbuf2 _ hb.wf rfl rfl rfl rfl rfl (by simp only []; rw [hp2]; omega), ?_⟩
576 refine hr.with_bi _ rfl rfl rfl ?_ ?_ ?_ rfl rfl
577 · show 0 ≤ (0 : Int32).toInt; rw [i32_0]; omega
578 · show (0 : Int32).toInt ≤ 16; rw [i32_0]; omega
579 · show (0 : UInt16).toNat < 2 ^ (0 : Int32).toInt.toNat; rw [i32_0]; simp
580 · unfold outBits
581 show bytesBits _ (d.pending + 2).toNat ++ natBits (0 : UInt16).toNat (0 : Int32).toInt.toNat = _
582 rw [hp2, bytesBits_two _ _ (by omega), i32_0, List.append_assoc (bytesBits _ _), natBits_word, h16]
583 simp [natBits]
584 · show (0 : Int32).toInt < 8; rw [i32_0]; omega
585 · intro i hi
586 have h1 : ¬ (d.pending.toNat + 1 = i) := by simp only [] at hi; rw [hp2] at hi; omega
587 have h2 : ¬ (d.pending.toNat = i) := by simp only [] at hi; rw [hp2] at hi; omega
588 rw [getD_set_u8, getD_set_u8]
589 simp [h1, h2]
590 · show d.pending.toNat ≤ (d.pending + 2).toNat; rw [hp2]; omega
591 · show (d.pending + 2).toNat ≤ _; rw [hp2]; exact Nat.le_refl _
592 · by_cases h8 : 8 ≤ d.bi_valid.toInt
593 · have hlt16 : d.bi_valid.toInt < 16 := by omega
594 have hroom1 : d.pending.toNat + 1 ≤ buf.size := by
595 have : 8 ≤ d.bi_valid.toInt.toNat := by omega
596 omega
597 have hbuf1 : (buf.set! d.pending.toNat d.bi_buf.toUInt8).size = buf.size := by simp
598 have hnv : (Int32.ofInt (d.bi_valid.toInt - 8)).toInt = d.bi_valid.toInt - 8 :=
599 i32_ofInt_toInt (by omega) (by omega)
600 refine ⟨_, _, bi_flush_mid hb h8 hlt16 hroom1, ?_, ?_, ?_, hbuf1, ?_, ?_, ?_, ⟨_, _, _, rfl⟩⟩
601 · refine ⟨hb.step _ hbuf1 _ hb.wf rfl rfl rfl rfl rfl (by simp only []; rw [hp1]; omega), ?_⟩
602 refine hr.with_bi _ rfl rfl rfl ?_ ?_ ?_ rfl rfl
603 · show 0 ≤ (Int32.ofInt _).toInt; rw [hnv]; omega
604 · show (Int32.ofInt _).toInt ≤ 16; rw [hnv]; omega
605 · show (d.bi_buf >>> 8).toNat < 2 ^ (Int32.ofInt _).toInt.toNat
606 rw [hnv, u16_shr8_toNat]
607 have := natBits_shr_lt d.bi_buf.toNat d.bi_valid.toInt.toNat 8 hbb (by omega)
608 rw [Nat.shiftRight_eq_div_pow] at this
609 have e : (d.bi_valid.toInt - 8).toNat = d.bi_valid.toInt.toNat - 8 := by omega
610 rw [e]; simpa using this
611 · unfold outBits
612 show bytesBits _ (d.pending + 1).toNat ++ natBits (d.bi_buf >>> 8).toNat (Int32.ofInt _).toInt.toNat = _
613 rw [hp1, bytesBits_one _ (by omega), hnv, natBits_byte, u16_shr8_toNat, List.append_assoc]
614 congr 1
615 have e : d.bi_valid.toInt.toNat = 8 + (d.bi_valid.toInt - 8).toNat := by omega
616 conv => rhs; rw [e, natBits_add]
617 rw [Nat.shiftRight_eq_div_pow]
618 · show (Int32.ofInt _).toInt < 8; rw [hnv]; omega
619 · intro i hi
620 have h2 : ¬ (d.pending.toNat = i) := by simp only [] at hi; rw [hp1] at hi; omega
621 rw [getD_set_u8]
622 simp [h2]
623 · show d.pending.toNat ≤ (d.pending + 1).toNat; rw [hp1]; omega
624 · show (d.pending + 1).toNat ≤ _; rw [hp1]; omega
625 · have hlt8 : d.bi_valid.toInt < 8 := by omega
626 refine ⟨buf, d, ?_, ?_, rfl, hlt8, rfl, fun _ _ => rfl, Nat.le_refl _, by omega, ⟨_, _, _, rfl⟩⟩
627 · rw [setB_self hb.bytes, setD_self hb.dstate]; exact bi_flush_low hb.dstate hlt8
628 · rw [setB_self hb.bytes, setD_self hb.dstate]; exact ⟨hb, hr⟩
629
630
631/-- The last part of `bi_windup`: `bi_used = ((bi_valid - 1) & 7) + 1`, then clear the bit buffer. -/
632def windupTail (s : DeflateStatePtr) : M Unit := do
633 let t ← isub (← rd s).bi_valid 1
634 let u ← iadd (t &&& 7) 1
635 md s fun d => { d with bi_used := u }
636 md s fun d => { d with bi_buf := 0 }
637 md s fun d => { d with bi_valid := 0 }
638
639/-- `bi_used` as `bi_windup` computes it, for `0 <= bi_valid <= 16`. -/
640def usedOf (bv : Int) : Int := if bv = 0 then 8 else (bv - 1) % 8 + 1
641
642theorem usedOf_key : ∀ k : Fin 17, ((Int32.ofInt ((k : Int) - 1)) &&& 7).toInt + 1 = usedOf (k : Int) := by decide
643
644theorem i32_1 : (1 : Int32).toInt = 1 := by decide
645
646theorem windupTail_run {h : Heap} {id : Nat} {d : DeflateState} (hd : h.dstates id = some d)
647 (hl : 0 ≤ d.bi_valid.toInt) (hh : d.bi_valid.toInt ≤ 16) :
648 windupTail (some (.tab id)) h =
649 .ok ((), setD h id { d with bi_used := Int32.ofInt (usedOf d.bi_valid.toInt), bi_buf := 0, bi_valid := 0 }) := by
650 have hne : h.dstates id ≠ none := by simp [hd]
651 have hsub : isub d.bi_valid 1 = pure (Int32.ofInt (d.bi_valid.toInt - 1)) :=
652 (isub_eq (a := d.bi_valid) (b := 1) (by rw [i32_1]; omega) (by rw [i32_1]; omega)).trans (by rw [i32_1])
653 obtain ⟨n, hn⟩ : ∃ n : Nat, (n : Int) = d.bi_valid.toInt := ⟨d.bi_valid.toInt.toNat, Int.toNat_of_nonneg hl⟩
654 have hkey := usedOf_key ⟨n, by omega⟩
655 simp only [] at hkey
656 rw [hn] at hkey
657 have h1 : usedOf d.bi_valid.toInt ≤ 8 := by unfold usedOf; split <;> omega
658 have h2 : 1 ≤ usedOf d.bi_valid.toInt := by unfold usedOf; split <;> omega
659 have hadd : iadd (Int32.ofInt (d.bi_valid.toInt - 1) &&& 7) 1 = pure (Int32.ofInt (usedOf d.bi_valid.toInt)) := by
660 rw [iadd_eq (a := Int32.ofInt (d.bi_valid.toInt - 1) &&& 7) (b := 1) (by rw [i32_1]; omega)
661 (by rw [i32_1]; omega), i32_1, hkey]
662 have hrd : rdD h id = d := by simp [rdD, hd]
663 unfold windupTail
664 simp (disch := simp [hd]) only [bind_app, rd_run', md_run', rdD_setD_same, hrd, hsub, hadd, pure_app, setD_setD]
665 done
666
667
668theorem i32_gt_toInt {a b : Int32} : a > b ↔ a.toInt > b.toInt := by
669 rw [gt_iff_lt, Int32.lt_iff_toInt_lt]
670
671theorem bi_windup_big {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
672 (hb : TreesBase h id d b buf) (hl : 0 ≤ d.bi_valid.toInt) (hh : d.bi_valid.toInt ≤ 16)
673 (h8 : 8 < d.bi_valid.toInt) (hroom : d.pending.toNat + 2 ≤ buf.size) :
674 bi_windup (some (.tab id)) h =
675 .ok ((), setD (setB h b ((buf.set! d.pending.toNat (d.bi_buf &&& 0xff).toUInt8).set! (d.pending.toNat + 1)
676 (d.bi_buf >>> 8).toUInt8)) id
677 { d with pending := d.pending + 2, bi_used := Int32.ofInt (usedOf d.bi_valid.toInt), bi_buf := 0,
678 bi_valid := 0 }) := by
679 have hc : d.bi_valid > 8 := by rw [i32_gt_toInt, i32_8]; exact h8
680 unfold bi_windup
681 rw [bind_app, rd_run hb.dstate]
682 simp only [hc, ite_true]
683 rw [bind_app, rd_run hb.dstate]
684 simp only []
685 rw [bind_app, put_short_run hb hroom]
686 simp only []
687 have hd' : (setD (setB h b ((buf.set! d.pending.toNat (d.bi_buf &&& 0xff).toUInt8).set! (d.pending.toNat + 1)
688 (d.bi_buf >>> 8).toUInt8)) id { d with pending := d.pending + 2 }).dstates id
689 = some { d with pending := d.pending + 2 } := by simp
690 exact (windupTail_run hd' hl hh).trans (by simp only [setD_setD])
691
692theorem bi_windup_small {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
693 (hb : TreesBase h id d b buf) (hl : 0 ≤ d.bi_valid.toInt) (hh : d.bi_valid.toInt ≤ 16)
694 (h8 : d.bi_valid.toInt ≤ 8) (h0 : 0 < d.bi_valid.toInt) (hroom : d.pending.toNat + 1 ≤ buf.size) :
695 bi_windup (some (.tab id)) h =
696 .ok ((), setD (setB h b (buf.set! d.pending.toNat d.bi_buf.toUInt8)) id
697 { d with pending := d.pending + 1, bi_used := Int32.ofInt (usedOf d.bi_valid.toInt), bi_buf := 0,
698 bi_valid := 0 }) := by
699 have hc : ¬ d.bi_valid > 8 := by rw [i32_gt_toInt, i32_8]; omega
700 have hc2 : d.bi_valid > 0 := by rw [i32_gt_toInt, i32_0]; exact h0
701 unfold bi_windup
702 rw [bind_app, rd_run hb.dstate]
703 simp only [hc, hc2, ite_true, ite_false]
704 rw [bind_app, rd_run hb.dstate]
705 simp only []
706 rw [bind_app, put_byte_run hb hroom]
707 simp only []
708 have hd' : (setD (setB h b (buf.set! d.pending.toNat d.bi_buf.toUInt8)) id { d with pending := d.pending + 1 }).dstates id
709 = some { d with pending := d.pending + 1 } := by simp
710 exact (windupTail_run hd' hl hh).trans (by simp only [setD_setD])
711
712theorem bi_windup_zero {h : Heap} {id : Nat} {d : DeflateState} (hd : h.dstates id = some d)
713 (hl : d.bi_valid.toInt = 0) :
714 bi_windup (some (.tab id)) h =
715 .ok ((), setD h id { d with bi_used := Int32.ofInt (usedOf d.bi_valid.toInt), bi_buf := 0, bi_valid := 0 }) := by
716 have hc : ¬ d.bi_valid > 8 := by rw [i32_gt_toInt, i32_8]; omega
717 have hc2 : ¬ d.bi_valid > 0 := by rw [i32_gt_toInt, i32_0]; omega
718 unfold bi_windup
719 rw [bind_app, rd_run hd]
720 simp only [hc, hc2, ite_false]
721 exact windupTail_run hd (by omega) (by omega)
722
723
724theorem natBits_pad (w bv k : Nat) (hw : w < 2 ^ bv) : natBits w (bv + k) = natBits w bv ++ List.replicate k false := by
725 rw [natBits_add, Nat.shiftRight_eq_div_pow, Nat.div_eq_of_lt hw, natBits_zero]
726
727/-- **`bi_windup`, safety and specification.** Flushes the bit buffer to a byte boundary: the output bit stream
728gets `(8 - bi_valid % 8) % 8` zero bits appended (the padding), `bi_buf = bi_valid = 0` and
729`bi_used = ((bi_valid - 1) & 7) + 1` (`usedOf`). Precondition: `TreesInvAt` and room for the pending bits
730(`8 * pending + bi_valid <= 8 * pending_buf_size`, F9). Called by `_tr_stored_block` and `_tr_flush_block`. -/
731theorem bi_windup_spec {h : Heap} {id : Nat} {d : DeflateState} {b : Nat} {buf : Array UInt8}
732 (hI : TreesInvAt h id d b buf)
733 (hroom : 8 * d.pending.toNat + d.bi_valid.toInt.toNat ≤ 8 * buf.size) :
734 ∃ buf' d', bi_windup (some (.tab id)) h = .ok ((), setD (setB h b buf') id d') ∧
735 TreesInvAt (setD (setB h b buf') id d') id d' b buf' ∧
736 outBits buf' d' = outBits buf d ++ List.replicate ((8 - d.bi_valid.toInt.toNat % 8) % 8) false ∧
737 d'.bi_valid.toInt = 0 ∧ d'.bi_buf = 0 ∧ d'.bi_used.toInt = usedOf d.bi_valid.toInt ∧
738 buf'.size = buf.size ∧
739 (∀ i, (i < d.pending.toNat ∨ d'.pending.toNat ≤ i) → buf'.getD i 0 = buf.getD i 0) ∧
740 d.pending.toNat ≤ d'.pending.toNat ∧ d'.pending.toNat ≤ d.pending.toNat + 2 ∧
741 (∃ p u, d' = { d with pending := p, bi_used := u, bi_buf := 0, bi_valid := 0 }) := by
742 obtain ⟨hb, hr⟩ := hI
743 have hbl := hr.bi_lo
744 have hbh := hr.bi_hi
745 have hbb := hr.bi_buf
746 have hp := hb.pending_small
747 have hs1 := hb.size
748 have hs2 := hb.lit_hi
749 have hp1 := toNat_add_one_u64 hp
750 have hpsz := hb.psize
751 have hu : (Int32.ofInt (usedOf d.bi_valid.toInt)).toInt = usedOf d.bi_valid.toInt := by
752 have h1 : usedOf d.bi_valid.toInt ≤ 8 := by unfold usedOf; split <;> omega
753 have h2 : 1 ≤ usedOf d.bi_valid.toInt := by unfold usedOf; split <;> omega
754 exact i32_ofInt_toInt (by omega) (by omega)
755 have hrun : ∀ (d' : DeflateState), d'.l_desc = d.l_desc → d'.d_desc = d.d_desc → d'.bl_desc = d.bl_desc →
756 d'.bi_valid = 0 → d'.bi_buf = 0 → d'.sym_next = d.sym_next → d'.sym_end = d.sym_end → TreesRun id d' := by
757 intro d' h1 h2 h3 h4 h5 h7 h8
758 refine hr.with_bi d' h1 h2 h3 ?_ ?_ ?_ h7 h8
759 · rw [h4, i32_0]; omega
760 · rw [h4, i32_0]; omega
761 · rw [h4, h5, i32_0]; simp
762 by_cases h8 : 8 < d.bi_valid.toInt
763 · have hroom2 : d.pending.toNat + 2 ≤ buf.size := by
764 have : 8 < d.bi_valid.toInt.toNat := by omega
765 omega
766 have hp2 := toNat_add_two_u64 hp
767 have hbuf2 : ((buf.set! d.pending.toNat (d.bi_buf &&& 0xff).toUInt8).set! (d.pending.toNat + 1)
768 (d.bi_buf >>> 8).toUInt8).size = buf.size := by simp
769 refine ⟨_, _, bi_windup_big hb hbl hbh h8 hroom2, ?_, ?_, ?_, ?_, ?_, hbuf2, ?_, ?_, ?_, ⟨_, _, rfl⟩⟩
770 · exact ⟨hb.step _ hbuf2 _ hb.wf rfl rfl rfl rfl rfl (by simp only []; rw [hp2]; omega), hrun _ rfl rfl rfl rfl rfl rfl rfl⟩
771 · unfold outBits
772 show bytesBits _ (d.pending + 2).toNat ++ natBits (0 : UInt16).toNat (0 : Int32).toInt.toNat = _
773 rw [hp2, bytesBits_two _ _ (by omega), i32_0, List.append_assoc (bytesBits _ _), natBits_word]
774 have e : (16 : Nat) = d.bi_valid.toInt.toNat + (16 - d.bi_valid.toInt.toNat) := by omega
775 rw [e, natBits_pad _ _ _ hbb]
776 have e2 : 16 - d.bi_valid.toInt.toNat = (8 - d.bi_valid.toInt.toNat % 8) % 8 := by omega
777 rw [e2]; simp [natBits]
778 · exact i32_0
779 · rfl
780 · show Int32.toInt (Int32.ofInt _) = _; exact hu
781 · intro i hi
782 have h1 : ¬ (d.pending.toNat + 1 = i) := by simp only [] at hi; rw [hp2] at hi; omega
783 have h2 : ¬ (d.pending.toNat = i) := by simp only [] at hi; rw [hp2] at hi; omega
784 rw [getD_set_u8, getD_set_u8]
785 simp [h1, h2]
786 · show d.pending.toNat ≤ (d.pending + 2).toNat; rw [hp2]; omega
787 · show (d.pending + 2).toNat ≤ _; rw [hp2]; omega
788 · by_cases h0 : 0 < d.bi_valid.toInt
789 · have hroom1 : d.pending.toNat + 1 ≤ buf.size := by
790 have : 0 < d.bi_valid.toInt.toNat := by omega
791 omega
792 have hbuf1 : (buf.set! d.pending.toNat d.bi_buf.toUInt8).size = buf.size := by simp
793 refine ⟨_, _, bi_windup_small hb hbl hbh (by omega) h0 hroom1, ?_, ?_, ?_, ?_, ?_, hbuf1, ?_, ?_, ?_, ⟨_, _, rfl⟩⟩
794 · exact ⟨hb.step _ hbuf1 _ hb.wf rfl rfl rfl rfl rfl (by simp only []; rw [hp1]; omega), hrun _ rfl rfl rfl rfl rfl rfl rfl⟩
795 · unfold outBits
796 show bytesBits _ (d.pending + 1).toNat ++ natBits (0 : UInt16).toNat (0 : Int32).toInt.toNat = _
797 rw [hp1, bytesBits_one _ (by omega), i32_0, natBits_byte]
798 have hpad := natBits_pad d.bi_buf.toNat d.bi_valid.toInt.toNat (8 - d.bi_valid.toInt.toNat) hbb
799 rw [show d.bi_valid.toInt.toNat + (8 - d.bi_valid.toInt.toNat) = 8 by omega] at hpad
800 have e2 : 8 - d.bi_valid.toInt.toNat = (8 - d.bi_valid.toInt.toNat % 8) % 8 := by omega
801 rw [hpad, e2]; simp [natBits]
802 · exact i32_0
803 · rfl
804 · show Int32.toInt (Int32.ofInt _) = _; exact hu
805 · intro i hi
806 have h2 : ¬ (d.pending.toNat = i) := by simp only [] at hi; rw [hp1] at hi; omega
807 rw [getD_set_u8]
808 simp [h2]
809 · show d.pending.toNat ≤ (d.pending + 1).toNat; rw [hp1]; omega
810 · show (d.pending + 1).toNat ≤ _; rw [hp1]; omega
811 · have hz : d.bi_valid.toInt = 0 := by omega
812 refine ⟨buf, { d with bi_used := Int32.ofInt (usedOf d.bi_valid.toInt), bi_buf := 0, bi_valid := 0 }, ?_, ?_, ?_, i32_0, rfl, ?_, rfl, fun _ _ => rfl, Nat.le_refl _, (by show d.pending.toNat ≤ d.pending.toNat + 2; omega), ⟨_, _, rfl⟩⟩
813 · rw [setB_self hb.bytes]; exact bi_windup_zero hb.dstate hz
814 · rw [setB_self hb.bytes]
815 exact ⟨hb.stepD _ hb.wf rfl rfl rfl rfl rfl hb.pending_le, hrun _ rfl rfl rfl rfl rfl rfl rfl⟩
816 · unfold outBits
817 show bytesBits buf d.pending.toNat ++ natBits (0 : UInt16).toNat (0 : Int32).toInt.toNat = _
818 rw [i32_0, hz]; simp [natBits]
819 · show Int32.toInt (Int32.ofInt _) = _; exact hu
820
821end Zlib.Trees.Proofs.Out