Skip to content
REFERENCE / ZLIB × LEAN

trees.c.build.lengths.lean

Source snapshot · bb09ada5fe855ed3 · 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.frame»
2
3/-! # trees.c: lengths of the entire alphabet after actual construction -/
4
5namespace Zlib.Trees.Proofs
6open C Zlib.Trees
7
8/-- Every leaf above the actual prepared maximum is unused and remains
9zero-length throughout merging. This also covers leaves outside 0..max_code. -/
10theorem BTForest.above_max_zero {tk : TK} {N K j : Nat} {mc node : Int32}
11    {d0 d : DeflateState} (hi : BTForest tk N K j mc d0 node d)
12    (v : Nat) (hv : v < N) (hmax : mc.toInt.toNat < v) : (tk.arr d)[v]!.dl = 0 := by
13  apply hi.unused v hv
14  have hm := hi.initial.maxCode
15  rcases Math.scanMax_spec (btFreq tk d0) N with ⟨he, hz⟩ | ⟨u, he, hu, hf, hz⟩
16  · exact hz v hv
17  · exact hz v (by omega) hv
18
19/-- Complete actual heap building retains zero lengths above its maximum.
20The property comes from the actual forest and the root store's exact frame. -/
21theorem ws_btHeap_upper_zero {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
22    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc} {sl : Option (Nat → UInt16)}
23    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
24    (hsd : StaticTreeDescRef.get h0 sref = some sd)
25    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
26    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
27    (hT : 2 * sd.elems.toInt.toNat - 1 ≤ (tk.arr d).size)
28    (hD : 2 * sd.elems.toInt.toNat - 1 ≤ d.depth.size)
29    (hH : d.heap.size = 573) (hs : BTStatic h0 id sd.static_tree sd.elems.toInt.toNat sl) :
30    WS h0 id (btHeap (Sp id) (some (dk.descRef id))) d (fun a e =>
31      ∀ v < sd.elems.toInt.toNat, a.2.toInt.toNat < v → (tk.arr e)[v]!.dl = 0) := by
32  have hT0 : sd.elems.toInt ≤ (tk.arr d).size := by omega
33  have hD0 : sd.elems.toInt ≤ d.depth.size := by omega
34  unfold btHeap btMergedStart
35  simp only [M_bind_assoc, M_pure_bind]
36  refine WS.bind' (merge_ws_and
37    (ws_btSortedStart hdd hsd hstat htree he3 he286 hT0 hD0 hH hs)
38    (ws_btSortedStart_sizes hdd hsd hstat htree he3 he286 hT0 hD0 hH hs))
39    fun a prepared ⟨⟨ht, hst, he, hleaf, h2, hm, hdesc, ho, hmin⟩, hTs, hDs⟩ => ?_
40  rcases a with ⟨tree, stree, elems, mc⟩
41  dsimp only at ht hst he hleaf hdesc ⊢
42  subst tree; subst stree; subst elems
43  have hcnt := hleaf.count
44  have hKN := Math.scanCount_le (btFreq tk prepared) sd.elems.toInt.toNat
45  have hI := BTForest.of_leaf hleaf h2 hm (node := sd.elems) (by omega)
46    (by rw [hTs]; omega) (by rw [hDs]; omega) ho
47  refine WS.bind' (ws_btMergeLoop_forest hI) fun next merged ⟨hforest, hframe, hlen⟩ => ?_
48  have hK2 := hforest.queue.k2
49  have hKN := hforest.queue.kN
50  have hN286 := hforest.queue.n286
51  have hsize := hforest.queue.heap
52  have hmax := hforest.queue.max
53  have hj := hforest.queue.stage
54  refine WS.bind' (ws_btSaveRoot merged (by omega) (by omega) (by omega) (by omega))
55    fun _ e ⟨hm, hhm, he, hsz, hroot, htail⟩ => ?_
56  refine WS.pure' ?_
57  intro v hv hmaxv
58  have hz := hforest.above_max_zero v hv hmaxv
59  rw [he]
60  cases tk <;> exact hz
61
62/-- Complete actual construction bounds every alphabet length, including
63zero-frequency symbols above max_code. Those omitted symbols are exactly
64zero, so subsequent header writes never read an unconstrained old length. -/
65theorem ws_build_tree_all_lengths {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
66    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc}
67    {xb : Nat → Nat} {slOpt : Option (Nat → Nat)}
68    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
69    (hsd : StaticTreeDescRef.get h0 sref = some sd)
70    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
71    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
72    (hT : 2 * sd.elems.toInt.toNat - 1 ≤ (tk.arr d).size) (hTbig : (tk.arr d).size ≤ 600)
73    (hD : 2 * sd.elems.toInt.toNat - 1 ≤ d.depth.size)
74    (hH : d.heap.size = 573) (hB : d.bl_count.size = 16)
75    (hs : BTBuildStatic h0 id sd xb slOpt) :
76    WS h0 id (build_tree (Sp id) (some (dk.descRef id))) d (fun _ e =>
77      (∀ v < sd.elems.toInt.toNat, (tk.arr e)[v]!.dl.toNat ≤ sd.max_length.toInt.toNat) ∧
78      ∀ v < sd.elems.toInt.toNat, (dk.getDesc e).max_code.toInt.toNat < v → (tk.arr e)[v]!.dl = 0) := by
79  obtain ⟨sl, hsRepair⟩ := hs.repair
80  rw [build_tree_eq_heap_codes]
81  refine WS.bind' (merge_ws_and
82    (ws_btHeap_built hdd hsd hstat htree he3 he286 hT hTbig hD hH hB hsRepair)
83    (ws_btHeap_upper_zero hdd hsd hstat htree he3 he286 hT hD hH hsRepair))
84    fun a built ⟨⟨ht, prepared, K, hbuilt, hdesc, hBs, hTs⟩, habove⟩ => ?_
85  rcases a with ⟨tree, mc⟩
86  dsimp only at ht hbuilt hdesc habove ⊢
87  subst tree
88  have hctx := hbuilt.bitlen_ctx hs rfl hBs hTs
89  have hcodes := ws_btCodes (h0 := h0) (id := id) (tk := tk) (d := built)
90    (r := dk.descRef id) (sref := sref) (dd := { dd with max_code := mc }) (sd := sd)
91    (hm := 574 - 2 * K) (J := K - 1) (elems := sd.elems.toInt.toNat) (maxc := mc.toInt.toNat)
92    (L := sd.max_length.toInt.toNat) (baseN := sd.extra_base.toInt.toNat) (xb := xb) (slOpt := slOpt)
93    hdesc hsd hstat htree hctx hbuilt.heap_max hs.length_capacity (by omega) hbuilt.unused
94  refine WS.mono hcodes ?_
95  intro _ e ⟨mid, hdone, T, he, hT, hstores⟩
96  have hlens := code_stores_lengths he hT hstores
97  have hlow := (hdone.symbolic_lengths hbuilt.shape hbuilt.unused).1
98  have hupper : ∀ v < sd.elems.toInt.toNat, mc.toInt.toNat < v → (tk.arr mid)[v]!.dl = 0 := by
99    intro v hv hmv
100    have hnone : ∀ q, 574 - 2 * K ≤ q → q < 573 → Hn built q ≠ v := by
101      intro q hq1 hq2 hqv
102      have hk := hbuilt.shape.kind q hq1 hq2
103      omega
104    obtain ⟨Tf, Bf, O, S, hemid, hTf, hBf, hfreq, hout, rest⟩ := hdone
105    rw [hemid, tk_arr_mkP1, hout v hnone, habove v hv hmv]
106  have hmaxBuilt : (dk.getDesc built).max_code = mc := by
107    have hg := bt_desc_get dk h0 id built
108    rw [hg] at hdesc
109    exact congrArg TreeDesc.max_code (Option.some.inj hdesc)
110  have hmaxE : (dk.getDesc e).max_code = mc := by
111    rw [he]
112    have hdescmid := hdone.descriptor dk
113    cases tk <;> cases dk <;> exact (congrArg TreeDesc.max_code hdescmid).trans hmaxBuilt
114  constructor
115  · intro v hv
116    rw [hlens]
117    by_cases hvm : v ≤ mc.toInt.toNat
118    · exact hlow v hvm
119    · rw [hupper v hv (by omega)]
120      change 0 ≤ sd.max_length.toInt.toNat
121      omega
122  · intro v hv hmv
123    rw [hmaxE] at hmv
124    rw [hlens]
125    exact hupper v hv hmv
126
127/-- Every installed alphabet's full length bound follows from the existing
128initialization representation and actual constructor execution. -/
129theorem ws_build_tree_all_lengths_initialized {h0 : Heap} {id : Nat} {d : DeflateState}
130    (tk : TK) (hwf : d.WellFormed) (hs : Out.TreesStatic h0.static) (hr : Out.TreesRun0 id d) :
131    WS h0 id (build_tree (Sp id) (some (tk.descRef id))) d (fun _ e =>
132      (∀ v < tk.buildDesc.elems.toInt.toNat, (tk.arr e)[v]!.dl.toNat ≤ tk.buildDesc.max_length.toInt.toNat) ∧
133      ∀ v < tk.buildDesc.elems.toInt.toNat, (tk.getDesc e).max_code.toInt.toNat < v → (tk.arr e)[v]!.dl = 0) := by
134  obtain ⟨hLT, hDT, hBT, hBC, hH, hD⟩ := hwf
135  have he3 : 3 ≤ tk.buildDesc.elems.toInt := by cases tk <;> decide +kernel
136  have he286 : tk.buildDesc.elems.toInt ≤ 286 := by cases tk <;> decide +kernel
137  have hT : 2 * tk.buildDesc.elems.toInt.toNat - 1 ≤ (tk.arr d).size := by
138    cases tk
139    · change 571 ≤ d.dyn_ltree.size; omega
140    · change 59 ≤ d.dyn_dtree.size; omega
141    · change 37 ≤ d.bl_tree.size; omega
142  have hTbig : (tk.arr d).size ≤ 600 := by
143    cases tk
144    · change d.dyn_ltree.size ≤ 600; omega
145    · change d.dyn_dtree.size ≤ 600; omega
146    · change d.bl_tree.size ≤ 600; omega
147  have hDepth : 2 * tk.buildDesc.elems.toInt.toNat - 1 ≤ d.depth.size := by
148    cases tk
149    · change 571 ≤ d.depth.size; omega
150    · change 59 ≤ d.depth.size; omega
151    · change 37 ≤ d.depth.size; omega
152  have hstat : (tk.getDesc d).stat_desc = some tk.buildStaticRef := by
153    cases tk
154    · exact hr.lstat
155    · exact hr.dstat
156    · exact hr.blstat
157  have htree : (tk.getDesc d).dyn_tree = .ref (tk.ref id) 0 := by
158    cases tk
159    · exact hr.ldyn
160    · exact hr.ddyn
161    · exact hr.bldyn
162  exact ws_build_tree_all_lengths (bt_desc_get tk h0 id d) (trees_build_desc_get hs tk) hstat htree
163    he3 he286 hT hTbig hDepth hH hBC (trees_build_static hs tk)
164
165end Zlib.Trees.Proofs
ZLIB × LEAN

Global contents

READING NOWtrees.c.build.lengths.lean