Skip to content
REFERENCE / ZLIB × LEAN

trees.c.build.frame.lean

Source snapshot · 71a27024ff154c7d · 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.build.format»
2
3/-! # trees.c: caller state retained by complete tree construction -/
4
5namespace Zlib.Trees.Proofs
6open C Zlib.Trees
7
8/-- The complete record footprint of tree construction. Only the selected
9tree, selected descriptor maximum, work arrays, heap controls and costs may
10change. The replacement arrays have the original sizes. -/
11def BTBuildFrame (tk dk : TK) (d e : DeflateState) : Prop :=
12  ∃ (T : Array CtData) (H : Array Int32) (D : Array UInt8) (B : Array UInt16)
13    (hl hm mc : Int32) (O S : UInt64),
14    e = { tk.setArr (dk.setDesc d { dk.getDesc d with max_code := mc }) T with
15      heap := H, depth := D, bl_count := B, heap_len := hl, heap_max := hm,
16      opt_len := O, static_len := S } ∧
17    T.size = (tk.arr d).size ∧ H.size = d.heap.size ∧
18    D.size = d.depth.size ∧ B.size = d.bl_count.size
19
20theorem BTBuildFrame.refl (tk dk : TK) (d : DeflateState) : BTBuildFrame tk dk d d := by
21  refine ⟨tk.arr d, d.heap, d.depth, d.bl_count, d.heap_len, d.heap_max,
22    (dk.getDesc d).max_code, d.opt_len, d.static_len, ?_, rfl, rfl, rfl, rfl⟩
23  cases tk <;> cases dk <;> simp only [TK.setArr, TK.setDesc, TK.getDesc, TK.arr] <;> rfl
24
25theorem BTBuildFrame.trans {tk dk : TK} {a b c : DeflateState}
26    (hab : BTBuildFrame tk dk a b) (hbc : BTBuildFrame tk dk b c) :
27    BTBuildFrame tk dk a c := by
28  obtain ⟨T, H, D, B, hl, hm, mc, O, S, rfl, hT, hH, hD, hB⟩ := hab
29  obtain ⟨T', H', D', B', hl', hm', mc', O', S', rfl, hT', hH', hD', hB'⟩ := hbc
30  refine ⟨T', H', D', B', hl', hm', mc', O', S', ?_, ?_, ?_, ?_, ?_⟩
31  · cases tk <;> cases dk <;> simp only [TK.setArr, TK.setDesc, TK.getDesc] <;> rfl
32  · have hT'' : T'.size = T.size := by
33      cases tk <;> cases dk <;> exact hT'
34    exact hT''.trans hT
35  · exact hH'.trans hH
36  · exact hD'.trans hD
37  · exact hB'.trans hB
38
39/-- The forest's checked exact write frame is contained in the complete
40construction footprint. -/
41theorem BTForestFrame.build_frame {tk : TK} {d e : DeflateState}
42    (hi : BTForestFrame tk d e) (dk : TK) : BTBuildFrame tk dk d e := by
43  obtain ⟨T, H, D, hl, hm, rfl, hT, hH, hD⟩ := hi
44  refine ⟨T, H, D, d.bl_count, hl, hm, (dk.getDesc d).max_code,
45    d.opt_len, d.static_len, ?_, hT, hH, hD, rfl⟩
46  cases tk <;> cases dk <;> simp only [TK.setArr, TK.setDesc, TK.getDesc, btScanState] <;> rfl
47
48/-- Repair never changes the heap's allocated length. -/
49theorem BTForceTrace.heap_size {tk : TK} {sl : Option (Nat → UInt16)}
50    {k : Nat} {mc0 mc : Int32} {d e : DeflateState} (hi : BTForceTrace tk sl k mc0 d mc e) :
51    e.heap.size = d.heap.size := by
52  induction hi with
53  | nil => rfl
54  | snoc node hl before hn hnT hm hhl ih =>
55    simpa only [btForceState_heap, Array.size_set!] using ih
56
57/-- The actual reset, scan, repair, maximum store and heapify retain all
58caller fields outside the complete construction footprint. -/
59theorem ws_btSortedStart_frame {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
60    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc} {sl : Option (Nat → UInt16)}
61    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
62    (hsd : StaticTreeDescRef.get h0 sref = some sd)
63    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
64    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
65    (hT : sd.elems.toInt ≤ (tk.arr d).size) (hD : sd.elems.toInt ≤ d.depth.size)
66    (hH : d.heap.size = 573) (hs : BTStatic h0 id sd.static_tree sd.elems.toInt.toNat sl) :
67    WS h0 id (btSortedStart (Sp id) (some (dk.descRef id))) d
68      (fun _ e => BTBuildFrame tk dk d e) := by
69  unfold btSortedStart
70  refine WS.bind' (ws_btLeavesStart hdd hsd hstat htree he3 he286 hT hD hH hs)
71    fun a mid ⟨ht, hst, he, hleaf, scan, scanMc, k, hscan, hlen, hk, hkexact, htrace⟩ => ?_
72  rcases a with ⟨tree, stree, elems, mc⟩
73  dsimp only at ht hst he hleaf htrace ⊢
74  subst tree; subst stree; subst elems
75  have hsz := htrace.merge_sizes
76  have hheap := htrace.heap_size
77  have hB := htrace.bl_count
78  obtain ⟨Ts, Hs, Ds, hls, hscanEq, hsT, hsH, hsD, rest⟩ := hscan
79  obtain ⟨T, H, D, hl, O, S, hmid⟩ := htrace.frame
80  refine WS.bind' (ws_btOrder_leaf tk dk mid sd.elems.toInt.toNat mc hleaf)
81    fun _ e ⟨hleaf', H', he, hsH', hf, hp, ho, hdesc', hmin⟩ => ?_
82  refine WS.pure' ?_
83  refine ⟨T, H', D, d.bl_count, hl, HEAP_SIZE, mc, O, S, ?_, ?_, ?_, ?_, rfl⟩
84  · rw [he, hmid, hscanEq]
85    cases tk <;> cases dk <;> simp only [TK.setArr, TK.setDesc, TK.getDesc, btScanState] <;> rfl
86  · rw [hmid] at hsz
87    have hszt : T.size = (tk.arr scan).size := by
88      cases tk <;> exact hsz.1
89    rw [hscanEq, btScanState_tree] at hszt
90    have hsT' : Ts.size = (tk.arr d).size := by
91      cases tk <;> exact hsT
92    exact hszt.trans hsT'
93  · rw [hsH', hheap, hscanEq]
94    exact hsH
95  · rw [hmid, hscanEq] at hsz
96    exact hsz.2.trans hsD
97
98/-- The actual complete heap-building prefix keeps the caller frame.
99Its forest premises come from the actual sorted-leaf prefix. -/
100theorem ws_btHeap_frame {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
101    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc} {sl : Option (Nat → UInt16)}
102    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
103    (hsd : StaticTreeDescRef.get h0 sref = some sd)
104    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
105    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
106    (hT : 2 * sd.elems.toInt.toNat - 1 ≤ (tk.arr d).size)
107    (hD : 2 * sd.elems.toInt.toNat - 1 ≤ d.depth.size)
108    (hH : d.heap.size = 573) (hs : BTStatic h0 id sd.static_tree sd.elems.toInt.toNat sl) :
109    WS h0 id (btHeap (Sp id) (some (dk.descRef id))) d
110      (fun _ e => BTBuildFrame tk dk d e) := by
111  have hT0 : sd.elems.toInt ≤ (tk.arr d).size := by omega
112  have hD0 : sd.elems.toInt ≤ d.depth.size := by omega
113  unfold btHeap btMergedStart
114  simp only [M_bind_assoc, M_pure_bind]
115  refine WS.bind' (merge_ws_and (merge_ws_and
116    (ws_btSortedStart hdd hsd hstat htree he3 he286 hT0 hD0 hH hs)
117    (ws_btSortedStart_sizes hdd hsd hstat htree he3 he286 hT0 hD0 hH hs))
118    (ws_btSortedStart_frame hdd hsd hstat htree he3 he286 hT0 hD0 hH hs))
119    fun a prepared ⟨⟨⟨ht, hst, he, hleaf, h2, hm, hdesc, ho, hmin⟩, hTs, hDs⟩, hframe⟩ => ?_
120  rcases a with ⟨tree, stree, elems, mc⟩
121  dsimp only at ht hst he hleaf hdesc ⊢
122  subst tree; subst stree; subst elems
123  have hcnt := hleaf.count
124  have hKN := Math.scanCount_le (btFreq tk prepared) sd.elems.toInt.toNat
125  have hI := BTForest.of_leaf hleaf h2 hm (node := sd.elems) (by omega)
126    (by rw [hTs]; omega) (by rw [hDs]; omega) ho
127  refine WS.bind' (ws_btMergeLoop_forest hI) fun next merged ⟨hforest, hmerge, hlen⟩ => ?_
128  refine WS.bind' (ws_btSaveRoot_forest hforest hmerge) fun _ e hbuilt => ?_
129  exact WS.pure' (hframe.trans (hbuilt.frame.build_frame dk))
130
131/-- Length generation has the complete caller footprint. -/
132theorem GBDone.build_frame {tk : TK} {d e : DeflateState} {hm J maxc L : Nat}
133    {xb : Nat → Nat} {slOpt : Option (Nat → Nat)}
134    (hi : GBDone tk d hm J maxc L xb slOpt e) (hB : d.bl_count.size = 16) (dk : TK) :
135    BTBuildFrame tk dk d e := by
136  obtain ⟨T, B, O, S, rfl, hT, hBs, rest⟩ := hi
137  refine ⟨T, d.heap, d.depth, B, d.heap_len, d.heap_max, (dk.getDesc d).max_code,
138    O, S, ?_, hT, rfl, rfl, hBs.trans hB.symm⟩
139  cases tk <;> cases dk <;> simp only [mkP1, TK.setArr, TK.setDesc, TK.getDesc] <;> rfl
140
141/-- Canonical code stores keep the complete caller footprint. -/
142theorem BTBuildFrame.codes (tk dk : TK) (d : DeflateState) (T : Array CtData)
143    (hT : T.size = (tk.arr d).size) : BTBuildFrame tk dk d (tk.setArr d T) := by
144  refine ⟨T, d.heap, d.depth, d.bl_count, d.heap_len, d.heap_max, (dk.getDesc d).max_code,
145    d.opt_len, d.static_len, ?_, hT, rfl, rfl, rfl⟩
146  cases tk <;> cases dk <;> simp only [TK.setArr, TK.setDesc, TK.getDesc] <;> rfl
147
148/-- Complete actual build_tree retains all caller state outside its exact
149record footprint. No postcondition of a callee is assumed. -/
150theorem ws_build_tree_frame {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
151    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc}
152    {xb : Nat → Nat} {slOpt : Option (Nat → Nat)}
153    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
154    (hsd : StaticTreeDescRef.get h0 sref = some sd)
155    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
156    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
157    (hT : 2 * sd.elems.toInt.toNat - 1 ≤ (tk.arr d).size) (hTbig : (tk.arr d).size ≤ 600)
158    (hD : 2 * sd.elems.toInt.toNat - 1 ≤ d.depth.size)
159    (hH : d.heap.size = 573) (hB : d.bl_count.size = 16)
160    (hs : BTBuildStatic h0 id sd xb slOpt) :
161    WS h0 id (build_tree (Sp id) (some (dk.descRef id))) d
162      (fun _ e => BTBuildFrame tk dk d e) := by
163  obtain ⟨sl, hsRepair⟩ := hs.repair
164  rw [build_tree_eq_heap_codes]
165  refine WS.bind' (merge_ws_and
166    (ws_btHeap_built hdd hsd hstat htree he3 he286 hT hTbig hD hH hB hsRepair)
167    (ws_btHeap_frame hdd hsd hstat htree he3 he286 hT hD hH hsRepair))
168    fun a built ⟨⟨ht, prepared, K, hbuilt, hdesc, hBs, hTs⟩, hframe⟩ => ?_
169  rcases a with ⟨tree, mc⟩
170  dsimp only at ht hbuilt hdesc ⊢
171  subst tree
172  have hctx := hbuilt.bitlen_ctx hs rfl hBs hTs
173  have hcodes := ws_btCodes (h0 := h0) (id := id) (tk := tk) (d := built)
174    (r := dk.descRef id) (sref := sref) (dd := { dd with max_code := mc }) (sd := sd)
175    (hm := 574 - 2 * K) (J := K - 1) (elems := sd.elems.toInt.toNat) (maxc := mc.toInt.toNat)
176    (L := sd.max_length.toInt.toNat) (baseN := sd.extra_base.toInt.toNat) (xb := xb) (slOpt := slOpt)
177    hdesc hsd hstat htree hctx hbuilt.heap_max hs.length_capacity (by omega) hbuilt.unused
178  refine WS.mono hcodes ?_
179  intro _ e ⟨mid, hdone, T, he, hT, hstores⟩
180  subst e
181  exact hframe.trans ((hdone.build_frame hBs dk).trans (BTBuildFrame.codes tk dk mid T hT))
182
183/-- The construction footprint preserves every array size in WellFormed. -/
184theorem BTBuildFrame.wellFormed {tk dk : TK} {d e : DeflateState}
185    (hi : BTBuildFrame tk dk d e) (hw : d.WellFormed) : e.WellFormed := by
186  obtain ⟨T, H, D, B, hl, hm, mc, O, S, rfl, hT, hH, hD, hB⟩ := hi
187  obtain ⟨hLT, hDT, hBT, hBC, hHeap, hDepth⟩ := hw
188  cases tk <;> cases dk <;>
189    simp only [TK.setArr, TK.setDesc, DeflateState.WellFormed] <;>
190    simp_all only [TK.arr, and_self]
191
192/-- Tree construction retains the live output buffer, descriptor pointers,
193symbol count and bit-buffer invariant. -/
194theorem BTBuildFrame.treesInvAt {tk dk : TK} {h : Heap} {id b : Nat}
195    {d e : DeflateState} {buf : Array UInt8} (hi : BTBuildFrame tk dk d e)
196    (hI : Out.TreesInvAt h id d b buf) : Out.TreesInvAt (setD h id e) id e b buf := by
197  have hw := hi.wellFormed hI.base.wf
198  obtain ⟨T, H, D, B, hl, hm, mc, O, S, rfl, rest⟩ := hi
199  cases tk <;> cases dk <;>
200    exact ⟨⟨by simp [setD], hw, hI.base.static, hI.base.pbuf, hI.base.bytes, hI.base.rw,
201      hI.base.size, hI.base.psize, hI.base.sym, hI.base.lit_lo, hI.base.lit_hi,
202      hI.base.sym_end, hI.base.pending_le⟩,
203      ⟨hI.run.ldyn, hI.run.lstat, hI.run.ddyn, hI.run.dstat, hI.run.bldyn, hI.run.blstat,
204        hI.run.bi_lo, hI.run.bi_hi, hI.run.bi_buf, hI.run.sym_next_le, hI.run.sym_next_mod⟩⟩
205
206/-- Building codes changes no pending output bits. -/
207theorem BTBuildFrame.outBits {tk dk : TK} {d e : DeflateState}
208    (hi : BTBuildFrame tk dk d e) (buf : Array UInt8) : Out.outBits buf e = Out.outBits buf d := by
209  obtain ⟨T, H, D, B, hl, hm, mc, O, S, rfl, rest⟩ := hi
210  cases tk <;> cases dk <;> rfl
211
212/-- Building a different alphabet retains this tree exactly, including all
213code words and lengths needed for subsequent emission. -/
214theorem BTBuildFrame.other_tree {tk dk : TK} {d e : DeflateState}
215    (hi : BTBuildFrame tk dk d e) (other : TK) (hne : other ≠ tk) :
216    other.arr e = other.arr d := by
217  obtain ⟨T, H, D, B, hl, hm, mc, O, S, rfl, rest⟩ := hi
218  cases tk <;> cases other <;> cases dk <;> first | exact False.elim (hne rfl) | rfl
219
220/-- The installed descriptors and existing initialization representation
221supply every premise of the complete caller-frame proof. -/
222theorem ws_build_tree_frame_initialized {h0 : Heap} {id : Nat} {d : DeflateState}
223    (tk : TK) (hwf : d.WellFormed) (hs : Out.TreesStatic h0.static) (hr : Out.TreesRun0 id d) :
224    WS h0 id (build_tree (Sp id) (some (tk.descRef id))) d
225      (fun _ e => BTBuildFrame tk tk d e) := by
226  obtain ⟨hLT, hDT, hBT, hBC, hH, hD⟩ := hwf
227  have he3 : 3 ≤ tk.buildDesc.elems.toInt := by cases tk <;> decide +kernel
228  have he286 : tk.buildDesc.elems.toInt ≤ 286 := by cases tk <;> decide +kernel
229  have hT : 2 * tk.buildDesc.elems.toInt.toNat - 1 ≤ (tk.arr d).size := by
230    cases tk
231    · change 571 ≤ d.dyn_ltree.size; omega
232    · change 59 ≤ d.dyn_dtree.size; omega
233    · change 37 ≤ d.bl_tree.size; omega
234  have hTbig : (tk.arr d).size ≤ 600 := by
235    cases tk
236    · change d.dyn_ltree.size ≤ 600; omega
237    · change d.dyn_dtree.size ≤ 600; omega
238    · change d.bl_tree.size ≤ 600; omega
239  have hDepth : 2 * tk.buildDesc.elems.toInt.toNat - 1 ≤ d.depth.size := by
240    cases tk
241    · change 571 ≤ d.depth.size; omega
242    · change 59 ≤ d.depth.size; omega
243    · change 37 ≤ d.depth.size; omega
244  have hstat : (tk.getDesc d).stat_desc = some tk.buildStaticRef := by
245    cases tk
246    · exact hr.lstat
247    · exact hr.dstat
248    · exact hr.blstat
249  have htree : (tk.getDesc d).dyn_tree = .ref (tk.ref id) 0 := by
250    cases tk
251    · exact hr.ldyn
252    · exact hr.ddyn
253    · exact hr.bldyn
254  exact ws_build_tree_frame (bt_desc_get tk h0 id d) (trees_build_desc_get hs tk) hstat htree
255    he3 he286 hT hTbig hDepth hH hBC (trees_build_static hs tk)
256
257/-- Complete tree construction preserves the actual caller's live output
258invariant and pending bits, without assuming either fact after the call. -/
259theorem build_tree_preserves {h : Heap} {id b : Nat} {d : DeflateState} {buf : Array UInt8}
260    (hI : Out.TreesInvAt h id d b buf) (tk : TK) :
261    ∃ e : DeflateState, build_tree (Sp id) (some (tk.descRef id)) h = .ok ((), setD h id e) ∧
262      BTBuildFrame tk tk d e ∧ Out.TreesInvAt (setD h id e) id e b buf ∧
263      Out.outBits buf e = Out.outBits buf d := by
264  obtain ⟨a, e, he, hframe⟩ := ws_build_tree_frame_initialized (h0 := h) tk
265    hI.base.wf hI.base.static hI.run.to0
266  have ha : a = () := Subsingleton.elim _ _
267  subst a
268  rw [setD_self hI.base.dstate] at he
269  exact ⟨e, he, hframe, hframe.treesInvAt hI, hframe.outBits buf⟩
270
271/-- Building the actual tree and then sending one originally used symbol
272runs on one caller heap. The appended output decodes to that symbol under
273the independently specified decoder, with every following suffix retained.
274The fifteen-bit room premise is an internal caller obligation. It still
275needs to be derived from block output and overlay bounds. This is a symbol
276result, not a complete block or public deflate theorem. -/
277theorem build_tree_send_decodable {h : Heap} {id b : Nat} {d : DeflateState} {buf : Array UInt8}
278    (hI : Out.TreesInvAt h id d b buf) (tk : TK) (v : Nat)
279    (hv : v < tk.buildDesc.elems.toInt.toNat) (hfreq : btFreq tk d v ≠ 0)
280    (hroom : 8 * d.pending.toNat + d.bi_valid.toInt.toNat + 15 ≤ 8 * buf.size) :
281    ∃ (built e : DeflateState) (buf' : Array UInt8) (maxc : Nat),
282      build_tree (Sp id) (some (tk.descRef id)) h = .ok ((), setD h id built) ∧
283      (do build_tree (Sp id) (some (tk.descRef id))
284          send_code (Sp id) (v : Int) (.ref (tk.ref id) 0)) h =
285        .ok ((), Out.setD (Out.setB h b buf') id e) ∧
286      Out.TreesInvAt (Out.setD (Out.setB h b buf') id e) id e b buf' ∧
287      BTBuildFrame tk tk d built ∧ Out.BitsDiff built e ∧
288      (tk.getDesc built).max_code.toInt = maxc ∧
289      maxc < tk.buildDesc.elems.toInt.toNat ∧
290      Out.outBits buf' e = Out.outBits buf d ++
291        Out.natBits (tk.arr built)[v]!.fc.toNat (tk.arr built)[v]!.dl.toNat ∧
292      ∀ suffix : List Bool,
293        ZlibF.Spec.decodeSym
294          (Zlib.Inftrees.Proofs.lensOf (fun n => (tk.arr built)[n]!.dl.toNat) (maxc + 1))
295          (Out.natBits (tk.arr built)[v]!.fc.toNat (tk.arr built)[v]!.dl.toNat ++ suffix) =
296            some (v, suffix) := by
297  obtain ⟨a, built, hbuild, hframe, husable, maxc, hmax, hdesc, haccept, hdecode⟩ :=
298    merge_ws_and (ws_build_tree_frame_initialized (h0 := h) tk hI.base.wf hI.base.static hI.run.to0)
299      (merge_ws_and (ws_build_tree_usable_initialized (h0 := h) tk hI.base.wf hI.base.static hI.run.to0)
300        (ws_build_tree_decodable_initialized (h0 := h) tk hI.base.wf hI.base.static hI.run.to0))
301  have ha : a = () := Subsingleton.elim _ _
302  subst a
303  rw [setD_self hI.base.dstate] at hbuild
304  have hIbuilt := hframe.treesInvAt hI
305  have hbits := hframe.outBits buf
306  have hcount := congrArg List.length hbits
307  simp only [Out.outBits_length] at hcount
308  have hused := husable v hv hfreq
309  have hL : tk.buildDesc.max_length.toInt.toNat ≤ 15 := by cases tk <;> decide +kernel
310  have hsize : tk.buildDesc.elems.toInt.toNat ≤ (tk.arr built).size := by
311    obtain ⟨hLT, hDT, hBT, hBC, hH, hD⟩ := hIbuilt.base.wf
312    cases tk
313    · change 286 ≤ built.dyn_ltree.size; omega
314    · change 30 ≤ built.dyn_dtree.size; omega
315    · change 19 ≤ built.bl_tree.size; omega
316  have hg := tk_get (h0 := h) (id := id) (d := built) tk
317  have hdl : getDl (.ref (tk.ref id) 0) (v : Int) (setD h id built) =
318      .ok ((tk.arr built)[v]!.dl, setD h id built) := by
319    simpa only [getElem!_pos, show v < (tk.arr built).size by omega] using
320      Out.getDl_gen hg (show v < (tk.arr built).size by omega)
321  have hfc : getFc (.ref (tk.ref id) 0) (v : Int) (setD h id built) =
322      .ok ((tk.arr built)[v]!.fc, setD h id built) := by
323    simpa only [getElem!_pos, show v < (tk.arr built).size by omega] using
324      Out.getFc_gen hg (show v < (tk.arr built).size by omega)
325  obtain ⟨buf', e, hsend, hIe, hout, hsize', houtside, hlow, hupp, hdiff⟩ :=
326    Out.send_code_emit hIbuilt (v : Int) (.ref (tk.ref id) 0) _ _ hdl hfc
327      (by omega) hused.2.2.2 (by omega)
328  have hheap : Out.setD (Out.setB (setD h id built) b buf') id e =
329      Out.setD (Out.setB h b buf') id e := by
330    change Out.setD (Out.setB (Out.setD h id built) b buf') id e = _
331    rw [Out.setB_setD, Out.setD_setD]
332  rw [hheap] at hsend hIe
333  have hsend' : send_code (Sp id) (v : Int) (.ref (tk.ref id) 0) (setD h id built) =
334      .ok ((), Out.setD (Out.setB h b buf') id e) := by
335    exact hsend
336  have hIe' : Out.TreesInvAt (Out.setD (Out.setB h b buf') id e) id e b buf' := by
337    exact hIe
338  refine ⟨built, e, buf', maxc, hbuild, ?_, hIe', hframe, hdiff, hdesc, hmax, ?_, hdecode v hv hfreq⟩
339  · rw [bind_app, hbuild]
340    exact hsend'
341  · rw [hout, hbits]
342
343end Zlib.Trees.Proofs
ZLIB × LEAN

Global contents

READING NOWtrees.c.build.frame.lean