跳到正文
参考文档 / ZLIB × LEAN

inftrees.c.canon.lean

此页源文件快照 · f63653a36bbf25a7 · 对应提交的原文 ↗

本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。

1/-!
2# The canonical construction in the list model
3
4Pure mathematics about the lengths `ls`, migrated from an earlier development: the allocation order, the Kraft
5sums `K`, the canonical code values `cv`, `H = rev (L j) (cv j)` (the table index of the first entry of code `j`),
6the group widths of the sub-tables (`look`, `width`) and the closed form `desc` of the table geometry. The names are
7in the namespace `Zlib.Inftrees.Canon` so that they do not clash with the model used by the main proof.
8-/
9
10/-!
11# Bit reversal and the backwards increment of inflate_table
12
13Pure mathematics. `rev k x` reverses the low `k` bits of `x`; inflate_table
14keeps the current canonical code `x` of length `k` bit-reversed in `huff`
15(DEFLATE sends Huffman codes most-significant bit first, while table indices
16are read least-significant bit first). The C "backwards increment" turns
17`rev k x` into `rev k (x + 1)`.
18-/
19set_option autoImplicit false
20
21namespace Zlib.Inftrees.Canon
22
23/-- Reverse the low `k` bits of `x`. -/
24def rev : Nat → Nat → Nat
25  | 0, _ => 0
26  | k + 1, x => rev k (x / 2) + (x % 2) * 2 ^ k
27
28theorem rev_zero (x : Nat) : rev 0 x = 0 := rfl
29
30theorem rev_succ (k x : Nat) : rev (k + 1) x = rev k (x / 2) + (x % 2) * 2 ^ k := rfl
31
32theorem rev_lt (k x : Nat) : rev k x < 2 ^ k := by
33  induction k generalizing x with
34  | zero => simp [rev]
35  | succ k ih =>
36    rw [rev_succ, Nat.pow_succ]
37    have := ih (x / 2)
38    have : x % 2 ≤ 1 := by omega
39    have : (x % 2) * 2 ^ k ≤ 2 ^ k := by
40      calc (x % 2) * 2 ^ k ≤ 1 * 2 ^ k := Nat.mul_le_mul_right _ this
41        _ = 2 ^ k := Nat.one_mul _
42    omega
43
44theorem rev_split (a b x : Nat) :
45    rev (a + b) x = rev a (x / 2 ^ b) + rev b (x % 2 ^ b) * 2 ^ a := by
46  induction b generalizing x with
47  | zero => simp [rev]
48  | succ b ih =>
49    rw [show a + (b + 1) = (a + b) + 1 by omega, rev_succ, ih, rev_succ]
50    have h1 : x / 2 / 2 ^ b = x / 2 ^ (b + 1) := by
51      rw [Nat.div_div_eq_div_mul, Nat.pow_succ, Nat.mul_comm]
52    have h2 : x % 2 ^ (b + 1) / 2 = x / 2 % 2 ^ b := by
53      rw [Nat.pow_succ, Nat.mul_comm, Nat.mod_mul_right_div_self]
54    have h3 : x % 2 ^ (b + 1) % 2 = x % 2 := by
55      rw [Nat.pow_succ, Nat.mod_mul_left_mod]
56    rw [h1, h2, h3, Nat.pow_add 2 a b, Nat.add_mul, Nat.mul_assoc, Nat.mul_comm (2 ^ b) (2 ^ a)]
57    omega
58
59theorem rev_mod (k x : Nat) : rev k (x % 2 ^ k) = rev k x := by
60  induction k generalizing x with
61  | zero => rfl
62  | succ k ih =>
63    rw [rev_succ, rev_succ]
64    have h2 : x % 2 ^ (k + 1) / 2 = x / 2 % 2 ^ k := by
65      rw [Nat.pow_succ, Nat.mul_comm, Nat.mod_mul_right_div_self]
66    have h3 : x % 2 ^ (k + 1) % 2 = x % 2 := by
67      rw [Nat.pow_succ, Nat.mod_mul_left_mod]
68    rw [h2, h3, ih]
69
70theorem rev_of_zero (k : Nat) : rev k 0 = 0 := by
71  induction k with
72  | zero => rfl
73  | succ k ih => simp [rev_succ, ih]
74
75/-- Appending low zero bits (a code shifted left by `d`) adds high zero bits
76to the reversed value. -/
77theorem rev_shift (k d x : Nat) : rev (k + d) (x * 2 ^ d) = rev k x := by
78  rw [rev_split, Nat.mul_div_cancel _ (Nat.two_pow_pos d), Nat.mul_mod_left, rev_of_zero]
79  simp
80
81theorem rev_two_pow (i : Nat) : rev (i + 1) (2 ^ i) = 1 := by
82  have := rev_split 1 i (2 ^ i)
83  rw [show 1 + i = i + 1 by omega] at this
84  rw [this, Nat.div_self (Nat.two_pow_pos i), Nat.mod_self, rev_of_zero]
85  simp [rev]
86
87/-- Bit `k-1-i` of `rev k x` is bit `i` of `x`. -/
88theorem rev_bit (k i x : Nat) (hi : i < k) :
89    rev k x / 2 ^ (k - 1 - i) % 2 = x / 2 ^ i % 2 := by
90  have hs := rev_split (k - 1 - i) (i + 1) x
91  rw [show k - 1 - i + (i + 1) = k by omega] at hs
92  rw [hs]
93  have hlt := rev_lt (k - 1 - i) (x / 2 ^ (i + 1))
94  rw [Nat.add_mul_div_right _ _ (Nat.two_pow_pos _), Nat.div_eq_of_lt hlt, Nat.zero_add]
95  rw [rev_succ]
96  have hlt2 := rev_lt i (x % 2 ^ (i + 1) / 2)
97  have : (x % 2 ^ (i + 1)) % 2 = x / 2 ^ i % 2 ∨ True := Or.inr trivial
98  -- rev (i+1) y % 2 is the top bit of y
99  have htop : ∀ (j y : Nat), y < 2 ^ (j + 1) → rev (j + 1) y % 2 = y / 2 ^ j := by
100    intro j
101    induction j with
102    | zero => intro y hy; simp [rev] at *; omega
103    | succ j ih =>
104      intro y hy
105      rw [rev_succ, Nat.pow_succ]
106      have hy2 : y / 2 < 2 ^ (j + 1) := by
107        rw [Nat.pow_succ] at hy ⊢; omega
108      have := ih (y / 2) hy2
109      have hpar : (rev (j + 1) (y / 2) + y % 2 * (2 ^ j * 2)) % 2 = rev (j + 1) (y / 2) % 2 := by
110        rw [Nat.add_mod]; simp [← Nat.mul_assoc, Nat.mul_mod_left]
111      rw [hpar, this, Nat.div_div_eq_div_mul, Nat.mul_comm]
112  have hy : x % 2 ^ (i + 1) < 2 ^ (i + 1) := Nat.mod_lt _ (Nat.two_pow_pos _)
113  have ht := htop i (x % 2 ^ (i + 1)) hy
114  rw [← rev_succ, ht]
115  rw [Nat.pow_succ, Nat.mod_mul_right_div_self]
116
117/-- Backwards increment, carry case: if bits `0..i-1` of `x` are ones and bit
118`i` is zero (`i < k`), then `rev k (x+1)` keeps the top `k-1-i` reversed bits
119and sets bit `k-1-i`. -/
120theorem rev_succ_of_trailing (k i x : Nat) (hi : i < k)
121    (hlow : x % 2 ^ i = 2 ^ i - 1) (hbit : x / 2 ^ i % 2 = 0) :
122    rev k (x + 1) = rev k x % 2 ^ (k - 1 - i) + 2 ^ (k - 1 - i) := by
123  have hk : k = (k - 1 - i) + (i + 1) := by omega
124  have hs1 := rev_split (k - 1 - i) (i + 1) x
125  have hs2 := rev_split (k - 1 - i) (i + 1) (x + 1)
126  rw [← hk] at hs1 hs2
127  have hp : 0 < 2 ^ i := Nat.two_pow_pos i
128  have hm : x % 2 ^ (i + 1) = 2 ^ i - 1 := by
129    have := Nat.mod_add_div (x % 2 ^ (i + 1)) (2 ^ i)
130    have e1 : x % 2 ^ (i + 1) % 2 ^ i = x % 2 ^ i := by
131      rw [Nat.pow_succ, Nat.mod_mul_right_mod]
132    have e2 : x % 2 ^ (i + 1) / 2 ^ i = x / 2 ^ i % 2 := by
133      rw [Nat.pow_succ, Nat.mod_mul_right_div_self]
134    rw [e1, e2, hbit, hlow] at this
135    omega
136  have hq : (x + 1) / 2 ^ (i + 1) = x / 2 ^ (i + 1) := by
137    have := Nat.div_add_mod x (2 ^ (i + 1))
138    have hp2 : 2 ^ (i + 1) = 2 * 2 ^ i := by rw [Nat.pow_succ, Nat.mul_comm]
139    have : x + 1 = 2 ^ (i + 1) * (x / 2 ^ (i + 1)) + 2 ^ i := by omega
140    rw [this, Nat.mul_add_div (Nat.two_pow_pos _), Nat.div_eq_of_lt (Nat.pow_lt_pow_right (by decide) (by omega))]
141    simp
142  have hr : (x + 1) % 2 ^ (i + 1) = 2 ^ i := by
143    have := Nat.div_add_mod x (2 ^ (i + 1))
144    have hp2 : 2 ^ (i + 1) = 2 * 2 ^ i := by rw [Nat.pow_succ, Nat.mul_comm]
145    have : x + 1 = 2 ^ (i + 1) * (x / 2 ^ (i + 1)) + 2 ^ i := by omega
146    rw [this, Nat.mul_add_mod, Nat.mod_eq_of_lt (Nat.pow_lt_pow_right (by decide) (by omega))]
147  rw [hs2, hq, hr, rev_two_pow, Nat.one_mul, hs1]
148  have hlt := rev_lt (k - 1 - i) (x / 2 ^ (i + 1))
149  rw [Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt hlt]
150
151/-- Backwards increment, overflow case: all `k` bits ones. -/
152theorem rev_all_ones (k x : Nat) (hlow : x % 2 ^ k = 2 ^ k - 1) (hx : x < 2 ^ k) :
153    x + 1 = 2 ^ k := by
154  rw [Nat.mod_eq_of_lt hx] at hlow
155  have := Nat.two_pow_pos k
156  omega
157
158/-- Extending the low run of ones by one bit. -/
159theorem low_ones_succ (x i : Nat) (hlow : x % 2 ^ i = 2 ^ i - 1) (hbit : x / 2 ^ i % 2 = 1) :
160    x % 2 ^ (i + 1) = 2 ^ (i + 1) - 1 := by
161  have := Nat.mod_add_div (x % 2 ^ (i + 1)) (2 ^ i)
162  have e1 : x % 2 ^ (i + 1) % 2 ^ i = x % 2 ^ i := by
163    rw [Nat.pow_succ, Nat.mod_mul_right_mod]
164  have e2 : x % 2 ^ (i + 1) / 2 ^ i = x / 2 ^ i % 2 := by
165    rw [Nat.pow_succ, Nat.mod_mul_right_div_self]
166  rw [e1, e2, hbit, hlow] at this
167  have hp2 : 2 ^ (i + 1) = 2 * 2 ^ i := by rw [Nat.pow_succ, Nat.mul_comm]
168  have := Nat.two_pow_pos i
169  omega
170
171/-! ## Bitwise helpers -/
172
173theorem and_two_pow (x p : Nat) : x &&& 2 ^ p = if x / 2 ^ p % 2 = 1 then 2 ^ p else 0 := by
174  apply Nat.eq_of_testBit_eq
175  intro j
176  rw [Nat.testBit_and, Nat.testBit_two_pow]
177  split
178  · rename_i hb
179    rw [Nat.testBit_two_pow]
180    by_cases hj : p = j
181    · subst hj; simp [Nat.testBit_eq_decide_div_mod_eq, hb]
182    · simp [hj]
183  · rename_i hb
184    simp only [Nat.zero_testBit]
185    by_cases hj : p = j
186    · subst hj; simp [Nat.testBit_eq_decide_div_mod_eq]; omega
187    · simp [hj]
188
189end Zlib.Inftrees.Canon
190
191/-!
192# Allocation order of the code lengths (counting sort in inflate_table)
193
194Pure mathematics, independent of the C translation. For a length vector
195`ls` (entries `0..15`), `symsOf ls l` lists the symbols of length `l` in
196increasing order and `ord ls` concatenates them for `l = 1..15`. This is the
197order in which inflate_table's counting sort leaves the symbols in `work[]`,
198and the order in which its main loop assigns canonical codes.
199-/
200set_option autoImplicit false
201
202namespace Zlib.Inftrees.Canon
203
204/-- Symbols of length `l`, increasing. -/
205def symsOf (ls : List Nat) (l : Nat) : List Nat :=
206  (List.range ls.length).filter fun s => ls.getD s 0 == l
207
208/-- Number of symbols with nonzero length below `l` (`offs[l]` in the C). -/
209def offL (ls : List Nat) (l : Nat) : Nat :=
210  ((List.range l).map fun l' => if l' = 0 then 0 else ls.count l').sum
211
212/-- Allocation order: lengths 1..15, increasing symbol within a length. -/
213def ord (ls : List Nat) : List Nat :=
214  (List.range 15).flatMap fun i => symsOf ls (i + 1)
215
216/-- Number of coded (nonzero-length) symbols. -/
217def nz (ls : List Nat) : Nat := (ord ls).length
218
219/-- `j`-th symbol in allocation order. -/
220def sy (ls : List Nat) (j : Nat) : Nat := (ord ls).getD j 0
221
222/-- Length of the `j`-th symbol in allocation order. -/
223def L (ls : List Nat) (j : Nat) : Nat := ls.getD (sy ls j) 0
224
225/-! ## Filter/count over ranges -/
226
227theorem countP_range_succ (p : Nat → Bool) (k : Nat) :
228    (List.range (k + 1)).countP p = (List.range k).countP p + (if p k then 1 else 0) := by
229  rw [List.range_succ, List.countP_append]
230  simp [List.countP_cons]
231
232theorem filter_range_getElem? (p : Nat → Bool) (n k : Nat) (hk : k < n) (hp : p k = true) :
233    ((List.range n).filter p)[(List.range k).countP p]? = some k := by
234  induction n with
235  | zero => omega
236  | succ n ih =>
237    rw [List.range_succ, List.filter_append]
238    by_cases hkn : k < n
239    · rw [List.getElem?_append_left]
240      · exact ih hkn
241      · have : (List.range k).countP p < (List.range (k + 1)).countP p := by
242          rw [countP_range_succ]; simp [hp]
243        have h2 : (List.range (k + 1)).countP p ≤ (List.range n).countP p := by
244          apply List.Sublist.countP_le
245          exact (List.range_sublist).mpr (by omega)
246        rw [← List.countP_eq_length_filter]
247        omega
248    · have hk' : k = n := by omega
249      subst hk'
250      rw [List.getElem?_append_right (by simp [List.countP_eq_length_filter])]
251      simp [hp, List.countP_eq_length_filter]
252
253theorem filter_range_length (p : Nat → Bool) (n : Nat) :
254    ((List.range n).filter p).length = (List.range n).countP p :=
255  (List.countP_eq_length_filter).symm
256
257theorem countP_range_getD (ls : List Nat) (l k : Nat) (hk : k ≤ ls.length) :
258    (List.range k).countP (fun s => ls.getD s 0 == l) = (ls.take k).count l := by
259  induction k with
260  | zero => simp
261  | succ k ih =>
262    rw [countP_range_succ, ih (by omega)]
263    rw [List.take_add_one]
264    rw [List.count_append]
265    have hk' : k < ls.length := by omega
266    simp [List.getElem?_eq_getElem hk', List.getD_eq_getElem?_getD, List.count_singleton]
267
268theorem symsOf_length (ls : List Nat) (l : Nat) : (symsOf ls l).length = ls.count l := by
269  unfold symsOf
270  rw [filter_range_length, countP_range_getD ls l _ (Nat.le_refl _), List.take_length]
271
272/-- Position of symbol `k` within `symsOf`. -/
273theorem symsOf_getElem? (ls : List Nat) (l k : Nat) (hk : k < ls.length)
274    (hl : ls.getD k 0 = l) : (symsOf ls l)[(ls.take k).count l]? = some k := by
275  unfold symsOf
276  rw [← countP_range_getD ls l k (by omega)]
277  exact filter_range_getElem? _ _ _ hk (by simp only [beq_iff_eq]; exact hl)
278
279theorem mem_symsOf (ls : List Nat) (l s : Nat) :
280    s ∈ symsOf ls l ↔ s < ls.length ∧ ls.getD s 0 = l := by
281  simp [symsOf]
282
283/-! ## flatMap over a range -/
284
285theorem sum_range_le (g : Nat → Nat) (j m : Nat) (h : j ≤ m) :
286    ((List.range j).map g).sum ≤ ((List.range m).map g).sum := by
287  induction m with
288  | zero => have : j = 0 := by omega
289            subst this; exact Nat.le_refl _
290  | succ m ih =>
291    by_cases hj : j = m + 1
292    · subst hj; exact Nat.le_refl _
293    · have := ih (by omega)
294      rw [List.range_succ, List.map_append, List.sum_append]
295      simp only [List.map_cons, List.map_nil, List.sum_cons, List.sum_nil]
296      omega
297
298theorem flatMap_range_getElem? (f : Nat → List Nat) (m j r : Nat) (hj : j < m)
299    (hr : r < (f j).length) :
300    ((List.range m).flatMap f)[((List.range j).map fun i => (f i).length).sum + r]? =
301      (f j)[r]? := by
302  induction m with
303  | zero => omega
304  | succ m ih =>
305    rw [List.range_succ, List.flatMap_append]
306    by_cases hjm : j < m
307    · rw [List.getElem?_append_left]
308      · exact ih hjm
309      · have hsub : ((List.range j).map fun i => (f i).length).sum + (f j).length ≤
310            ((List.range m).flatMap f).length := by
311          rw [List.length_flatMap]
312          have h1 := sum_range_le (fun i => (f i).length) (j + 1) m (by omega)
313          rw [List.range_succ, List.map_append, List.sum_append] at h1
314          simpa using h1
315        omega
316    · have : j = m := by omega
317      subst this
318      rw [List.getElem?_append_right]
319      · simp [List.length_flatMap]
320      · simp [List.length_flatMap]
321
322end Zlib.Inftrees.Canon
323
324
325/-!
326# Length intervals of the allocation order
327
328Pure mathematics: allocation index `j` has length `l` exactly when
329`offL l ≤ j < offL (l+1)`; lengths are nondecreasing along the order; the
330counting sort places symbol `s` of length `l` at `offL l + #{s' < s : ls[s'] = l}`.
331-/
332set_option autoImplicit false
333
334namespace Zlib.Inftrees.Canon
335
336theorem offL_succ (ls : List Nat) (l : Nat) :
337    offL ls (l + 1) = offL ls l + (if l = 0 then 0 else ls.count l) := by
338  unfold offL
339  rw [List.range_succ, List.map_append, List.sum_append]
340  simp
341
342theorem offL_zero (ls : List Nat) : offL ls 0 = 0 := rfl
343theorem offL_one (ls : List Nat) : offL ls 1 = 0 := by simp [offL_succ, offL_zero]
344
345theorem offL_succ_pos (ls : List Nat) {l : Nat} (hl : 1 ≤ l) :
346    offL ls (l + 1) = offL ls l + ls.count l := by
347  rw [offL_succ]; simp; omega
348
349theorem offL_mono (ls : List Nat) {a b : Nat} (h : a ≤ b) : offL ls a ≤ offL ls b := by
350  induction b with
351  | zero => have : a = 0 := by omega
352            subst this; exact Nat.le_refl _
353  | succ b ih =>
354    by_cases hab : a = b + 1
355    · subst hab; exact Nat.le_refl _
356    · have := ih (by omega); rw [offL_succ]; omega
357
358theorem offL_eq_sum (ls : List Nat) (j : Nat) :
359    offL ls (j + 1) = ((List.range j).map fun i => ls.count (i + 1)).sum := by
360  induction j with
361  | zero => exact offL_one ls
362  | succ j ih =>
363    rw [offL_succ_pos ls (by omega), ih, List.range_succ, List.map_append, List.sum_append]
364    simp
365
366theorem nz_eq (ls : List Nat) : nz ls = offL ls 16 := by
367  unfold nz ord
368  rw [List.length_flatMap, offL_eq_sum]
369  simp [symsOf_length]
370
371theorem ord_getElem? (ls : List Nat) (l r : Nat) (hl1 : 1 ≤ l) (hl : l ≤ 15)
372    (hr : r < ls.count l) : (ord ls)[offL ls l + r]? = (symsOf ls l)[r]? := by
373  unfold ord
374  have hj : l - 1 < 15 := by omega
375  have hlen : r < (symsOf ls (l - 1 + 1)).length := by
376    rw [symsOf_length]; rw [show l - 1 + 1 = l by omega]; exact hr
377  have := flatMap_range_getElem? (fun i => symsOf ls (i + 1)) 15 (l - 1) r hj hlen
378  simp only [symsOf_length] at this
379  rw [← offL_eq_sum, show l - 1 + 1 = l by omega] at this
380  exact this
381
382theorem exists_len (ls : List Nat) (j : Nat) (m : Nat) (hj : j < offL ls (m + 1)) :
383    ∃ l, 1 ≤ l ∧ l ≤ m ∧ offL ls l ≤ j ∧ j < offL ls (l + 1) := by
384  induction m with
385  | zero => rw [offL_one] at hj; omega
386  | succ m ih =>
387    by_cases h : j < offL ls (m + 1)
388    · obtain ⟨l, h1, h2, h3, h4⟩ := ih h
389      exact ⟨l, h1, by omega, h3, h4⟩
390    · exact ⟨m + 1, by omega, by omega, by omega, hj⟩
391
392theorem sy_of_interval (ls : List Nat) {j l : Nat} (hl1 : 1 ≤ l) (hl : l ≤ 15)
393    (h1 : offL ls l ≤ j) (h2 : j < offL ls (l + 1)) :
394    sy ls j < ls.length ∧ ls.getD (sy ls j) 0 = l := by
395  rw [offL_succ_pos ls hl1] at h2
396  have hr : j - offL ls l < ls.count l := by omega
397  have hg := ord_getElem? ls l (j - offL ls l) hl1 hl hr
398  rw [show offL ls l + (j - offL ls l) = j by omega] at hg
399  have hlen : j - offL ls l < (symsOf ls l).length := by rw [symsOf_length]; exact hr
400  have hm : (symsOf ls l)[j - offL ls l] ∈ symsOf ls l := List.getElem_mem hlen
401  rw [List.getElem?_eq_getElem hlen] at hg
402  have hsy : sy ls j = (symsOf ls l)[j - offL ls l] := by
403    unfold sy; rw [List.getD_eq_getElem?_getD, hg]; rfl
404  rw [hsy]
405  exact (mem_symsOf ls l _).mp hm
406
407/-- Lengths are bounded by 15 (the C precondition). -/
408def Bounded (ls : List Nat) : Prop := ∀ l ∈ ls, l ≤ 15
409
410theorem count_eq_zero_of_gt (ls : List Nat) (hb : Bounded ls) (l : Nat) (hl : 15 < l) :
411    ls.count l = 0 := by
412  apply List.count_eq_zero_of_not_mem
413  intro hm; have := hb l hm; omega
414
415theorem L_interval (ls : List Nat) {j : Nat} (hj : j < nz ls) :
416    1 ≤ L ls j ∧ L ls j ≤ 15 ∧ offL ls (L ls j) ≤ j ∧ j < offL ls (L ls j + 1) ∧
417      sy ls j < ls.length := by
418  rw [nz_eq] at hj
419  obtain ⟨l, h1, h2, h3, h4⟩ := exists_len ls j 15 hj
420  obtain ⟨hs, hg⟩ := sy_of_interval ls h1 (by omega) h3 h4
421  have : L ls j = l := hg
422  rw [this]
423  exact ⟨h1, h2, h3, h4, hs⟩
424
425theorem L_eq_of_interval (ls : List Nat) {j l : Nat} (hl1 : 1 ≤ l) (hl : l ≤ 15)
426    (h1 : offL ls l ≤ j) (h2 : j < offL ls (l + 1)) : L ls j = l :=
427  (sy_of_interval ls hl1 hl h1 h2).2
428
429theorem L_mono (ls : List Nat) {j j' : Nat} (hjj : j ≤ j') (hj' : j' < nz ls) :
430    L ls j ≤ L ls j' := by
431  obtain ⟨_, _, a3, _, _⟩ := L_interval ls (show j < nz ls by omega)
432  obtain ⟨_, _, _, b4, _⟩ := L_interval ls hj'
433  refine Classical.byContradiction fun hc => ?_
434  have := offL_mono ls (show L ls j' + 1 ≤ L ls j by omega)
435  omega
436
437/-- Indices of codes with length at most `l` are exactly `[0, offL (l+1))`. -/
438theorem lt_offL_iff (ls : List Nat) {j l : Nat} (hj : j < nz ls) :
439    j < offL ls (l + 1) ↔ L ls j ≤ l := by
440  obtain ⟨_, _, a3, a4, _⟩ := L_interval ls hj
441  constructor
442  · intro h
443    refine Classical.byContradiction fun hc => ?_
444    have := offL_mono ls (show l + 1 ≤ L ls j by omega)
445    omega
446  · intro h
447    have := offL_mono ls (show L ls j + 1 ≤ l + 1 by omega)
448    omega
449
450theorem count_take_lt (ls : List Nat) {s l : Nat} (hs : s < ls.length) (hls : ls.getD s 0 = l) :
451    (ls.take s).count l < ls.count l := by
452  have hsplit := congrArg (fun xs : List Nat => xs.count l) (List.take_append_drop s ls)
453  simp only [List.count_append] at hsplit
454  rw [List.drop_eq_getElem_cons hs] at hsplit
455  have : ls[s] = l := by
456    rw [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem hs] at hls; exact hls
457  simp [this, List.count_cons] at hsplit
458  omega
459
460/-- Counting sort position: symbol `s` of length `l` sits at
461`offL l + #{s' < s : ls[s'] = l}`. -/
462theorem sy_sorted (ls : List Nat) {s l : Nat} (hs : s < ls.length) (hl1 : 1 ≤ l) (hl : l ≤ 15)
463    (hls : ls.getD s 0 = l) : sy ls (offL ls l + (ls.take s).count l) = s := by
464  have hr := count_take_lt ls hs hls
465  unfold sy
466  rw [List.getD_eq_getElem?_getD, ord_getElem? ls l _ hl1 hl hr, symsOf_getElem? ls l s hs hls]
467  rfl
468
469end Zlib.Inftrees.Canon
470
471
472/-!
473# Kraft prefix sums and canonical code values along the allocation order
474
475Pure mathematics. `K ls j` is the left-aligned (15-bit) start of the `j`-th
476canonical code; `cv ls j` its numeric code value; `H ls j` the bit-reversed
477value inflate_table keeps in `huff`. `krAt` is the C's left recurrence.
478-/
479set_option autoImplicit false
480
481namespace Zlib.Inftrees.Canon
482
483def K (ls : List Nat) (j : Nat) : Nat := ((List.range j).map fun i => 2 ^ (15 - L ls i)).sum
484
485def cv (ls : List Nat) (j : Nat) : Nat := K ls j / 2 ^ (15 - L ls j)
486
487def H (ls : List Nat) (j : Nat) : Nat := rev (L ls j) (cv ls j)
488
489/-- `krAt l = Σ_{1 ≤ l' ≤ l} count l' * 2^(l - l')`, the C's
490`left <<= 1; left -= count[len]` recurrence with `left = 2^l - krAt l`. -/
491def krAt (ls : List Nat) : Nat → Nat
492  | 0 => 0
493  | l + 1 => 2 * krAt ls l + ls.count (l + 1)
494
495/-- Remaining codes of length `l` at or after allocation index `a`. -/
496def cntGE (ls : List Nat) (a l : Nat) : Nat := offL ls (l + 1) - max a (offL ls l)
497
498theorem K_succ (ls : List Nat) (j : Nat) : K ls (j + 1) = K ls j + 2 ^ (15 - L ls j) := by
499  unfold K; rw [List.range_succ, List.map_append, List.sum_append]; simp
500
501theorem K_zero (ls : List Nat) : K ls 0 = 0 := rfl
502
503theorem K_mono (ls : List Nat) {j j' : Nat} (h : j ≤ j') : K ls j ≤ K ls j' := by
504  induction j' with
505  | zero => have : j = 0 := by omega
506            subst this; exact Nat.le_refl _
507  | succ j' ih =>
508    by_cases hj : j = j' + 1
509    · subst hj; exact Nat.le_refl _
510    · have := ih (by omega); rw [K_succ]; have := Nat.two_pow_pos (15 - L ls j'); omega
511
512theorem K_strict (ls : List Nat) {j j' : Nat} (h : j < j') : K ls j < K ls j' := by
513  have h1 := K_mono ls (show j + 1 ≤ j' by omega)
514  have h2 := K_succ ls j
515  have := Nat.two_pow_pos (15 - L ls j)
516  omega
517
518/-- Prefix sums are multiples of `2^(15-l)` when all earlier lengths are `≤ l`. -/
519theorem dvd_K (ls : List Nat) (j l : Nat) (h : ∀ i < j, L ls i ≤ l) :
520    2 ^ (15 - l) ∣ K ls j := by
521  induction j with
522  | zero => exact Nat.dvd_zero _
523  | succ j ih =>
524    rw [K_succ]
525    refine Nat.dvd_add (ih fun i hi => h i (by omega)) ?_
526    exact Nat.pow_dvd_pow 2 (by have := h j (by omega); omega)
527
528theorem dvd_K_self (ls : List Nat) {j : Nat} (hj : j < nz ls) :
529    2 ^ (15 - L ls j) ∣ K ls j :=
530  dvd_K ls j _ fun i hi => L_mono ls (by omega) hj
531
532/-- Codes of one length are consecutive multiples. -/
533theorem K_offL_add (ls : List Nat) {l : Nat} (hl1 : 1 ≤ l) (hl : l ≤ 15) (r : Nat)
534    (hr : r ≤ ls.count l) : K ls (offL ls l + r) = K ls (offL ls l) + r * 2 ^ (15 - l) := by
535  induction r with
536  | zero => simp
537  | succ r ih =>
538    rw [← Nat.add_assoc, K_succ, ih (by omega)]
539    have h2 : offL ls l + r < offL ls (l + 1) := by rw [offL_succ_pos ls hl1]; omega
540    rw [L_eq_of_interval ls hl1 hl (by omega) h2, Nat.succ_mul]
541    omega
542
543theorem krAt_K (ls : List Nat) (l : Nat) (hl : l ≤ 15) :
544    krAt ls l * 2 ^ (15 - l) = K ls (offL ls (l + 1)) := by
545  induction l with
546  | zero => simp [krAt, offL_one, K_zero]
547  | succ l ih =>
548    rw [krAt, offL_succ_pos ls (show 1 ≤ l + 1 by omega),
549      K_offL_add ls (by omega) hl _ (Nat.le_refl _), ← ih (by omega)]
550    have hp : 2 ^ (15 - l) = 2 * 2 ^ (15 - (l + 1)) := by
551      rw [show 15 - l = (15 - (l + 1)) + 1 by omega, Nat.pow_succ, Nat.mul_comm]
552    rw [hp, Nat.add_mul, Nat.mul_comm 2 (krAt ls l), Nat.mul_assoc]
553
554/-- Total Kraft sum (in units of 2^-15) of the coded symbols. -/
555theorem krAt15 (ls : List Nat) : krAt ls 15 = K ls (nz ls) := by
556  have := krAt_K ls 15 (by omega)
557  simp at this
558  rw [nz_eq]; exact this
559
560theorem krAt_mono (ls : List Nat) (a b : Nat) (h : a ≤ b) :
561    krAt ls a * 2 ^ (b - a) ≤ krAt ls b := by
562  induction b with
563  | zero => have : a = 0 := by omega
564            subst this; simp
565  | succ b ih =>
566    by_cases hab : a = b + 1
567    · subst hab; simp
568    · have := ih (by omega)
569      rw [krAt, show b + 1 - a = (b - a) + 1 by omega, Nat.pow_succ]
570      rw [← Nat.mul_assoc]
571      omega
572
573/-! ## Canonical values -/
574
575theorem cv_mul (ls : List Nat) {j : Nat} (hj : j < nz ls) :
576    cv ls j * 2 ^ (15 - L ls j) = K ls j := Nat.div_mul_cancel (dvd_K_self ls hj)
577
578theorem cv_succ (ls : List Nat) {j : Nat} (hj : j + 1 < nz ls) :
579    cv ls (j + 1) = (cv ls j + 1) * 2 ^ (L ls (j + 1) - L ls j) := by
580  have hm := L_mono ls (show j ≤ j + 1 by omega) hj
581  have h15 := (L_interval ls hj).2.1
582  show K ls (j + 1) / 2 ^ (15 - L ls (j + 1)) = _
583  rw [K_succ, ← cv_mul ls (show j < nz ls by omega)]
584  have hp : 2 ^ (15 - L ls j) = 2 ^ (L ls (j + 1) - L ls j) * 2 ^ (15 - L ls (j + 1)) := by
585    rw [← Nat.pow_add]; congr 1; omega
586  rw [show cv ls j * 2 ^ (15 - L ls j) + 2 ^ (15 - L ls j) = (cv ls j + 1) * 2 ^ (15 - L ls j)
587    by rw [Nat.succ_mul], hp, ← Nat.mul_assoc, Nat.mul_div_cancel _ (Nat.two_pow_pos _)]
588
589theorem H_succ (ls : List Nat) {j : Nat} (hj : j + 1 < nz ls) :
590    H ls (j + 1) = rev (L ls j) (cv ls j + 1) := by
591  have hm := L_mono ls (show j ≤ j + 1 by omega) hj
592  show rev (L ls (j + 1)) (cv ls (j + 1)) = _
593  rw [cv_succ ls hj]
594  have := rev_shift (L ls j) (L ls (j + 1) - L ls j) (cv ls j + 1)
595  rw [show L ls j + (L ls (j + 1) - L ls j) = L ls (j + 1) by omega] at this
596  exact this
597
598theorem H_zero (ls : List Nat) : H ls 0 = 0 := by
599  unfold H cv; rw [K_zero, Nat.zero_div, rev_of_zero]
600
601/-- A valid (not over-subscribed) code has room for every code value. -/
602theorem cv_succ_le (ls : List Nat) {j : Nat} (hj : j < nz ls)
603    (hk : K ls (j + 1) ≤ 2 ^ 15) : cv ls j + 1 ≤ 2 ^ L ls j := by
604  have h15 := (L_interval ls hj).2.1
605  rw [K_succ, ← cv_mul ls hj] at hk
606  have hp : 2 ^ 15 = 2 ^ L ls j * 2 ^ (15 - L ls j) := by rw [← Nat.pow_add]; congr 1; omega
607  rw [hp, show cv ls j * 2 ^ (15 - L ls j) + 2 ^ (15 - L ls j) =
608    (cv ls j + 1) * 2 ^ (15 - L ls j) by rw [Nat.succ_mul]] at hk
609  exact Nat.le_of_mul_le_mul_right hk (Nat.two_pow_pos _)
610
611theorem H_lt (ls : List Nat) (j : Nat) : H ls j < 2 ^ L ls j := rev_lt _ _
612
613/-! ## Remaining counts -/
614
615theorem cntGE_zero (ls : List Nat) {l : Nat} (hl : 1 ≤ l) : cntGE ls 0 l = ls.count l := by
616  unfold cntGE; rw [offL_succ_pos ls hl]; simp
617
618/-- Decrement of `count[len]` after processing allocation index `j`. -/
619theorem cntGE_succ (ls : List Nat) {j l : Nat} (hj : j < nz ls) (hl : 1 ≤ l) :
620    cntGE ls (j + 1) l = if l = L ls j then cntGE ls j l - 1 else cntGE ls j l := by
621  obtain ⟨a1, a2, a3, a4, _⟩ := L_interval ls hj
622  unfold cntGE
623  split
624  · rename_i he; subst he; omega
625  · rename_i hne
626    rcases Nat.lt_or_gt_of_ne hne with hlt | hgt
627    · have := offL_mono ls (show l + 1 ≤ L ls j by omega); omega
628    · have := offL_mono ls (show L ls j + 1 ≤ l by omega); omega
629
630theorem cntGE_self (ls : List Nat) {j : Nat} (hj : j < nz ls) :
631    cntGE ls j (L ls j) = offL ls (L ls j + 1) - j := by
632  obtain ⟨_, _, a3, _, _⟩ := L_interval ls hj
633  unfold cntGE; congr 1; omega
634
635end Zlib.Inftrees.Canon
636
637
638/-!
639# Root groups, the sub-table lookahead and the table descriptor sequence
640
641Pure mathematics. With root width `root`, the codes longer than `root` fall
642into groups by their first `root` bits, `grp j = K j / 2^(15-root)`. When the
643main loop of inflate_table reaches the first code of a group it computes the
644sub-table width with the `count[]` lookahead (`look`), advances `next` past the
645previous table, and grows `used`. `desc ls root mx i` is the
646(drop, curr, base, used, low) state in force while code `i` is written.
647
648For a complete code (`K (nz) = 2^15`) every code of a group fits its
649sub-table: `L i ≤ root + curr` (`look_covers`).
650-/
651set_option autoImplicit false
652
653namespace Zlib.Inftrees.Canon
654
655def grp (ls : List Nat) (root j : Nat) : Nat := K ls j / 2 ^ (15 - root)
656
657/-- The C lookahead
658```c
659while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break;
660                            curr++; left <<= 1; }
661```
662with `count[l] = cntGE a l` and a fuel bound. -/
663def look (ls : List Nat) (a root mx : Nat) : Nat → Int → Nat → Nat
664  | c, _, 0 => c
665  | c, left, f + 1 =>
666    if c + root < mx then
667      if left - (cntGE ls a (c + root) : Int) ≤ 0 then c
668      else look ls a root mx (c + 1) (2 * (left - (cntGE ls a (c + root) : Int))) f
669    else c
670
671/-- The sub-table width chosen for a group starting at allocation index `a`. -/
672def width (ls : List Nat) (a root mx : Nat) : Nat :=
673  look ls a root mx (L ls a - root) (2 ^ (L ls a - root) : Nat) 16
674
675structure Desc where
676  drop : Nat
677  curr : Nat
678  base : Nat
679  used : Nat
680  low : Nat
681  deriving Repr
682
683/-- A new sub-table starts at code `i+1`. -/
684def startsAt (ls : List Nat) (root i : Nat) : Prop :=
685  root < L ls (i + 1) ∧ (L ls i ≤ root ∨ grp ls root (i + 1) ≠ grp ls root i)
686
687instance (ls : List Nat) (root i : Nat) : Decidable (startsAt ls root i) := by
688  unfold startsAt; infer_instance
689
690/-- Table descriptor in force while code `i` is written. -/
691def desc (ls : List Nat) (root mx : Nat) : Nat → Desc
692  | 0 => ⟨0, root, 0, 2 ^ root, 2 ^ 32 - 1⟩
693  | i + 1 =>
694    let d := desc ls root mx i
695    if startsAt ls root i then
696      ⟨root, width ls (i + 1) root mx, d.base + 2 ^ d.curr,
697        d.used + 2 ^ width ls (i + 1) root mx, rev root (grp ls root (i + 1))⟩
698    else d
699
700/-! ## Hypotheses shared by the lemmas below -/
701
702/-- Accepted complete code with root in `[min, max]`. -/
703structure CompleteCode (ls : List Nat) (root mx : Nat) : Prop where
704  pos : 0 < nz ls
705  complete : K ls (nz ls) = 2 ^ 15
706  root_pos : 1 ≤ root
707  root_le : root ≤ mx
708  mx_eq : mx = L ls (nz ls - 1)
709  min_le : L ls 0 ≤ root
710
711theorem CompleteCode.L_le_mx {ls : List Nat} {root mx : Nat} (hc : CompleteCode ls root mx)
712    {i : Nat} (hi : i < nz ls) : L ls i ≤ mx := by
713  rw [hc.mx_eq]; exact L_mono ls (by omega) (by have := hc.pos; omega)
714
715theorem CompleteCode.mx_le {ls : List Nat} {root mx : Nat} (hc : CompleteCode ls root mx) :
716    mx ≤ 15 := by
717  rw [hc.mx_eq]; exact (L_interval ls (by have := hc.pos; omega)).2.1
718
719theorem CompleteCode.K_lt {ls : List Nat} {root mx : Nat} (hc : CompleteCode ls root mx)
720    {i : Nat} (hi : i < nz ls) : K ls (i + 1) ≤ 2 ^ 15 := by
721  rw [← hc.complete]; exact K_mono ls (by omega)
722
723theorem grp_lt {ls : List Nat} {root mx : Nat} (hc : CompleteCode ls root mx)
724    {i : Nat} (hi : i < nz ls) : grp ls root i < 2 ^ root := by
725  have hk : K ls i < 2 ^ 15 := by
726    have := hc.K_lt hi; have := K_strict ls (show i < i + 1 by omega); omega
727  have hr15 : root ≤ 15 := Nat.le_trans hc.root_le hc.mx_le
728  have hp : 2 ^ 15 = 2 ^ root * 2 ^ (15 - root) := by rw [← Nat.pow_add]; congr 1; omega
729  unfold grp
730  rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _), ← hp]
731  exact hk
732
733theorem grp_mono (ls : List Nat) (root : Nat) {i j : Nat} (h : i ≤ j) :
734    grp ls root i ≤ grp ls root j :=
735  Nat.div_le_div_right (K_mono ls h)
736
737/-! ## Alignment of group starts -/
738
739/-- A long code that starts a group begins on a root-slot boundary. -/
740theorem start_aligned {ls : List Nat} {root mx : Nat} (hc : CompleteCode ls root mx)
741    {i : Nat} (hi : i + 1 < nz ls) (hs : startsAt ls root i) :
742    K ls (i + 1) = grp ls root (i + 1) * 2 ^ (15 - root) := by
743  have hr15 : root ≤ 15 := Nat.le_trans hc.root_le hc.mx_le
744  obtain ⟨hlong, hcase⟩ := hs
745  by_cases hshort : L ls i ≤ root
746  · have hd : 2 ^ (15 - root) ∣ K ls (i + 1) := by
747      apply dvd_K
748      intro j hj
749      exact Nat.le_trans (L_mono ls (show j ≤ i by omega) (by omega)) hshort
750    unfold grp; exact (Nat.div_mul_cancel hd).symm
751  · have hne : grp ls root (i + 1) ≠ grp ls root i := by
752      rcases hcase with h | h
753      · exact absurd h hshort
754      · exact h
755    have hi' : i < nz ls := by omega
756    have hL15 := (L_interval ls hi').2.1
757    -- u = 2^(15 - L i), U = 2^(15 - root) = t * u
758    have hU : 2 ^ (15 - root) = 2 ^ (L ls i - root) * 2 ^ (15 - L ls i) := by
759      rw [← Nat.pow_add]; congr 1; omega
760    have hKi := cv_mul ls hi'
761    have hKs := K_succ ls i
762    have hq_le : grp ls root (i + 1) * 2 ^ (15 - root) ≤ K ls (i + 1) := Nat.div_mul_le_self _ _
763    have hgi : grp ls root i < grp ls root (i + 1) := by
764      have := grp_mono ls root (show i ≤ i + 1 by omega); omega
765    have hlt : K ls i < grp ls root (i + 1) * 2 ^ (15 - root) := by
766      unfold grp at hgi
767      exact (Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)).mp hgi
768    -- divide everything by u
769    generalize hu : 2 ^ (15 - L ls i) = u at hU hKi hKs
770    generalize ht : 2 ^ (L ls i - root) = t at hU
771    generalize hq : grp ls root (i + 1) = q at hq_le hlt ⊢
772    have hupos : 0 < u := by rw [← hu]; exact Nat.two_pow_pos _
773    rw [hU] at hq_le hlt
774    rw [hKs, ← hKi] at hq_le
775    rw [← hKi] at hlt
776    rw [hKs, ← hKi, hU]
777    -- q * (t * u) ≤ cv * u + u and cv * u < q * (t * u)
778    have h1 : q * t ≤ cv ls i + 1 := by
779      have : q * t * u ≤ (cv ls i + 1) * u := by
780        rw [Nat.mul_assoc, Nat.succ_mul]; exact hq_le
781      exact Nat.le_of_mul_le_mul_right this hupos
782    have h2 : cv ls i < q * t := by
783      have : cv ls i * u < q * t * u := by rw [Nat.mul_assoc]; exact hlt
784      exact Nat.lt_of_mul_lt_mul_right this
785    have h3 : q * t = cv ls i + 1 := by omega
786    rw [← Nat.mul_assoc, h3, Nat.succ_mul]
787
788end Zlib.Inftrees.Canon
789
790
791/-!
792# The sub-table lookahead covers its group
793
794Pure mathematics. For a complete code, the width `look` chooses for a group
795starting at allocation index `a` accommodates every code of the group, and
796(for the canonical-table bridge) is attained by some code of the group.
797-/
798set_option autoImplicit false
799
800namespace Zlib.Inftrees.Canon
801
802theorem K_range (ls : List Nat) {l x : Nat} (hl1 : 1 ≤ l) (hl : l ≤ 15)
803    (h1 : offL ls l ≤ x) (h2 : x ≤ offL ls (l + 1)) :
804    K ls x = K ls (offL ls l) + (x - offL ls l) * 2 ^ (15 - l) := by
805  have := K_offL_add ls hl1 hl (x - offL ls l) (by rw [offL_succ_pos ls hl1] at h2; omega)
806  rwa [show offL ls l + (x - offL ls l) = x by omega] at this
807
808/-- Coverage by codes from `a` of length `< root + c`. -/
809def cov (ls : List Nat) (a root c : Nat) : Nat := K ls (max a (offL ls (root + c))) - K ls a
810
811theorem cov_step (ls : List Nat) {a root c : Nat} (ha : a < nz ls)
812    (hc : L ls a ≤ root + c) (h15 : root + c ≤ 15) :
813    cov ls a root (c + 1) = cov ls a root c + cntGE ls a (root + c) * 2 ^ (15 - (root + c)) := by
814  obtain ⟨a1, _, _, a4, _⟩ := L_interval ls ha
815  have hl1 : 1 ≤ root + c := by omega
816  have hmono := offL_mono ls (show L ls a + 1 ≤ root + c + 1 by omega)
817  have hmono2 := offL_mono ls (show root + c ≤ root + c + 1 by omega)
818  have hmax1 : max a (offL ls (root + (c + 1))) = offL ls (root + c + 1) := by
819    rw [show root + (c + 1) = root + c + 1 by omega]; omega
820  have hK1 := K_range ls hl1 h15 (x := offL ls (root + c + 1)) hmono2 (Nat.le_refl _)
821  have hK2 := K_range ls hl1 h15 (x := max a (offL ls (root + c))) (by omega) (by omega)
822  have hKa := K_mono ls (show a ≤ max a (offL ls (root + c)) by omega)
823  unfold cov cntGE
824  rw [hmax1, hK1, hK2]
825  have hsub : offL ls (root + c + 1) - offL ls (root + c) =
826      (offL ls (root + c + 1) - max a (offL ls (root + c))) +
827        (max a (offL ls (root + c)) - offL ls (root + c)) := by omega
828  rw [hsub, Nat.add_mul]
829  rw [hK2] at hKa
830  omega
831
832theorem cov_init (ls : List Nat) {a root : Nat} (ha : a < nz ls) (hr : root ≤ L ls a) :
833    cov ls a root (L ls a - root) = 0 := by
834  obtain ⟨_, _, a3, _, _⟩ := L_interval ls ha
835  unfold cov
836  rw [show root + (L ls a - root) = L ls a by omega, show max a (offL ls (L ls a)) = a by omega]
837  simp
838
839theorem look_spec (ls : List Nat) {a root mx : Nat} (ha : a < nz ls) (hmx : mx ≤ 15) :
840    ∀ (f c : Nat) (left : Int), L ls a ≤ root + c → c + root ≤ mx → mx - root - c ≤ f →
841      left * (2 ^ (15 - root - c) : Nat) = ((2 ^ (15 - root) : Nat) : Int) - (cov ls a root c : Int) →
842      0 < left →
843      c ≤ look ls a root mx c left f ∧ look ls a root mx c left f + root ≤ mx ∧
844      (look ls a root mx c left f + root = mx ∨
845        2 ^ (15 - root) ≤ cov ls a root (look ls a root mx c left f + 1)) ∧
846      (c < look ls a root mx c left f →
847        cov ls a root (look ls a root mx c left f) < 2 ^ (15 - root)) := by
848  intro f
849  induction f with
850  | zero =>
851    intro c left h1 h2 h3 _ _
852    simp only [look]
853    exact ⟨Nat.le_refl _, h2, Or.inl (by omega), fun h => absurd h (Nat.lt_irrefl _)⟩
854  | succ f ih =>
855    intro c left h1 h2 h3 hinv hpos
856    simp only [look]
857    by_cases hlt : c + root < mx
858    · rw [ite_eq_left hlt]
859      have hstep := cov_step ls ha h1 (by omega)
860      have hp : (2 ^ (15 - root - c) : Nat) = 2 ^ (15 - (root + c)) := by congr 1; omega
861      -- new left times 2^(15-root-c)
862      have hinv' : (left - (cntGE ls a (c + root) : Int)) * (2 ^ (15 - root - c) : Nat) =
863          ((2 ^ (15 - root) : Nat) : Int) - (cov ls a root (c + 1) : Int) := by
864        have e1 : ((cov ls a root (c + 1) : Nat) : Int) = (cov ls a root c : Int) +
865            (cntGE ls a (root + c) : Int) * ((2 ^ (15 - (root + c)) : Nat) : Int) := by
866          rw [hstep]; push_cast; rfl
867        rw [Int.sub_mul, hinv, e1, show c + root = root + c by omega, hp]
868        generalize (cntGE ls a (root + c) : Int) * ((2 ^ (15 - (root + c)) : Nat) : Int) = M
869        omega
870      by_cases hle : left - (cntGE ls a (c + root) : Int) ≤ 0
871      · rw [ite_eq_left hle]
872        refine ⟨Nat.le_refl _, by omega, Or.inr ?_, fun h => absurd h (Nat.lt_irrefl _)⟩
873        have hnn : (0 : Int) ≤ (2 ^ (15 - root - c) : Nat) := Int.natCast_nonneg _
874        have := Int.mul_le_mul_of_nonneg_right hle hnn
875        rw [hinv'] at this
876        omega
877      · rw [ite_eq_right hle]
878        have hp2 : (2 ^ (15 - root - c) : Nat) = 2 * 2 ^ (15 - root - (c + 1)) := by
879          rw [show 15 - root - c = (15 - root - (c + 1)) + 1 by omega, Nat.pow_succ, Nat.mul_comm]
880        have hinv2 : 2 * (left - (cntGE ls a (c + root) : Int)) * (2 ^ (15 - root - (c + 1)) : Nat) =
881            ((2 ^ (15 - root) : Nat) : Int) - (cov ls a root (c + 1) : Int) := by
882          rw [← hinv', hp2]; push_cast; rw [Int.mul_comm 2, Int.mul_assoc]
883        obtain ⟨r1, r2, r3, r4⟩ := ih (c + 1) _ (by omega) (by omega) (by omega) hinv2 (by omega)
884        refine ⟨by omega, r2, r3, ?_⟩
885        intro _
886        by_cases hcr : c + 1 < look ls a root mx (c + 1) (2 * (left - (cntGE ls a (c + root) : Int))) f
887        · exact r4 hcr
888        · have heq : look ls a root mx (c + 1) (2 * (left - (cntGE ls a (c + root) : Int))) f = c + 1 := by omega
889          rw [heq]
890          have hpos2 : (0 : Int) < (2 ^ (15 - root - c) : Nat) := by
891            exact Int.natCast_pos.mpr (Nat.two_pow_pos _)
892          have := Int.mul_pos (show (0 : Int) < left - (cntGE ls a (c + root) : Int) by omega) hpos2
893          rw [hinv'] at this
894          omega
895    · rw [ite_eq_right hlt]
896      refine ⟨Nat.le_refl _, h2, Or.inl (by omega), fun h => absurd h (Nat.lt_irrefl _)⟩
897
898/-- Result facts for the width of a group starting at `a` (a long code). -/
899theorem width_spec (ls : List Nat) {a root mx : Nat} (ha : a < nz ls) (hmx : mx ≤ 15)
900    (hlong : root < L ls a) (hLmx : L ls a ≤ mx) :
901    L ls a - root ≤ width ls a root mx ∧ width ls a root mx + root ≤ mx ∧
902      (width ls a root mx + root = mx ∨ 2 ^ (15 - root) ≤ cov ls a root (width ls a root mx + 1)) ∧
903      (L ls a - root < width ls a root mx →
904        cov ls a root (width ls a root mx) < 2 ^ (15 - root)) := by
905  unfold width
906  apply look_spec ls ha hmx 16 _ _ (by omega) (by omega) (by omega) _ (by
907    have := Nat.two_pow_pos (L ls a - root); omega)
908  rw [cov_init ls ha (by omega)]
909  have hp : 2 ^ (L ls a - root) * 2 ^ (15 - root - (L ls a - root)) = 2 ^ (15 - root) := by
910    rw [← Nat.pow_add]; congr 1; omega
911  rw [show ((0 : Nat) : Int) = 0 from rfl, Int.sub_zero]
912  exact_mod_cast hp
913
914/-- Every code of the group fits the chosen sub-table width. -/
915theorem look_covers {ls : List Nat} {root mx : Nat} (hc : CompleteCode ls root mx)
916    {a : Nat} (ha : a + 1 < nz ls) (hs : startsAt ls root a) {i : Nat}
917    (hi1 : a + 1 ≤ i) (hi : i < nz ls) (hg : grp ls root i = grp ls root (a + 1)) :
918    L ls i ≤ root + width ls (a + 1) root mx := by
919  have hmx := hc.mx_le
920  obtain ⟨w1, w2, w3, _⟩ := width_spec ls ha hmx hs.1 (hc.L_le_mx ha)
921  rcases w3 with heq | hcov
922  · have := hc.L_le_mx hi; omega
923  · refine Classical.byContradiction fun hcon => ?_
924    have hal := start_aligned hc ha hs
925    have hge : max (a + 1) (offL ls (root + (width ls (a + 1) root mx + 1))) ≤ i := by
926      have : ¬ i < offL ls (root + width ls (a + 1) root mx + 1) := by
927        rw [lt_offL_iff ls hi]; omega
928      rw [show root + (width ls (a + 1) root mx + 1) = root + width ls (a + 1) root mx + 1 by omega]
929      omega
930    have hKi := K_mono ls hge
931    unfold cov at hcov
932    have hka := K_mono ls (show a + 1 ≤ max (a + 1) (offL ls (root + (width ls (a + 1) root mx + 1)))
933      by omega)
934    -- K i ≥ (grp (a+1) + 1) * 2^(15-root), contradicting grp i = grp (a+1)
935    have hK : (grp ls root (a + 1) + 1) * 2 ^ (15 - root) ≤ K ls i := by
936      rw [Nat.succ_mul, ← hal]; omega
937    have : grp ls root (a + 1) + 1 ≤ grp ls root i := by
938      unfold grp
939      exact (Nat.le_div_iff_mul_le (Nat.two_pow_pos _)).mpr hK
940    omega
941
942end Zlib.Inftrees.Canon
943
944
945/-!
946# Properties of the table descriptor sequence
947
948Pure mathematics: shape of `desc` (root table while codes are short; one
949sub-table per group afterwards), `used = base + 2^curr`, monotonicity, and
950the facts the main loop needs for in-bounds writes. Also the reversed group
951index read from `huff & mask`, and `rev` injectivity.
952-/
953set_option autoImplicit false
954
955namespace Zlib.Inftrees.Canon
956
957theorem rev_one (b : Nat) : rev 1 b = b % 2 := by simp [rev]
958
959theorem rev_rev (k x : Nat) : rev k (rev k x) = x % 2 ^ k := by
960  induction k generalizing x with
961  | zero => simp [rev, Nat.mod_one]
962  | succ k ih =>
963    have hs := rev_split 1 k (rev (k + 1) x)
964    rw [show 1 + k = k + 1 by omega] at hs
965    have hlt := rev_lt k (x / 2)
966    have hb : x % 2 < 2 := Nat.mod_lt _ (by decide)
967    have h1 : (rev k (x / 2) + x % 2 * 2 ^ k) / 2 ^ k = x % 2 := by
968      rw [Nat.add_mul_div_right _ _ (Nat.two_pow_pos k), Nat.div_eq_of_lt hlt]; simp
969    have h2 : (rev k (x / 2) + x % 2 * 2 ^ k) % 2 ^ k = rev k (x / 2) := by
970      rw [Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt hlt]
971    rw [hs, rev_one, show rev (k + 1) x = rev k (x / 2) + x % 2 * 2 ^ k from rev_succ k x,
972      h1, h2, ih, Nat.mod_mod, Nat.pow_one]
973    -- x % 2 + (x / 2 % 2^k) * 2 = x % 2^(k+1)
974    have := Nat.mod_add_div (x % 2 ^ (k + 1)) 2
975    have e1 : x % 2 ^ (k + 1) % 2 = x % 2 := by rw [Nat.pow_succ, Nat.mod_mul_left_mod]
976    have e2 : x % 2 ^ (k + 1) / 2 = x / 2 % 2 ^ k := by
977      rw [Nat.pow_succ, Nat.mul_comm, Nat.mod_mul_right_div_self]
978    rw [e1, e2] at this
979    omega
980
981theorem rev_inj {k x y : Nat} (hx : x < 2 ^ k) (hy : y < 2 ^ k) (h : rev k x = rev k y) :
982    x = y := by
983  have := congrArg (rev k) h
984  rw [rev_rev, rev_rev, Nat.mod_eq_of_lt hx, Nat.mod_eq_of_lt hy] at this
985  exact this
986
987/-- `huff & mask` of a long code is the reversed root prefix (its group). -/
988theorem H_mod_root (ls : List Nat) {root j : Nat} (hj : j < nz ls) (hr : root ≤ L ls j) :
989    H ls j % 2 ^ root = rev root (grp ls root j) := by
990  have h15 := (L_interval ls hj).2.1
991  unfold H
992  have hs := rev_split root (L ls j - root) (cv ls j)
993  rw [show root + (L ls j - root) = L ls j by omega] at hs
994  rw [hs, Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt (rev_lt _ _)]
995  congr 1
996  unfold grp cv
997  rw [Nat.div_div_eq_div_mul, ← Nat.pow_add]
998  congr 2; omega
999
1000/-- `huff >> root` of a long code. -/
1001theorem H_div_root (ls : List Nat) {root j : Nat} (hj : j < nz ls) (hr : root ≤ L ls j) :
1002    H ls j / 2 ^ root = rev (L ls j - root) (cv ls j % 2 ^ (L ls j - root)) := by
1003  unfold H
1004  have hs := rev_split root (L ls j - root) (cv ls j)
1005  rw [show root + (L ls j - root) = L ls j by omega] at hs
1006  rw [hs, Nat.add_mul_div_right _ _ (Nat.two_pow_pos _), Nat.div_eq_of_lt (rev_lt _ _)]
1007  simp
1008
1009theorem desc_used (ls : List Nat) (root mx : Nat) (i : Nat) :
1010    (desc ls root mx i).used = (desc ls root mx i).base + 2 ^ (desc ls root mx i).curr := by
1011  induction i with
1012  | zero => simp [desc]
1013  | succ i ih =>
1014    simp only [desc]
1015    split
1016    · simp only; rw [ih]
1017    · exact ih
1018
1019theorem desc_used_mono (ls : List Nat) (root mx : Nat) {i j : Nat} (h : i ≤ j) :
1020    (desc ls root mx i).used ≤ (desc ls root mx j).used := by
1021  induction j with
1022  | zero => have : i = 0 := by omega
1023            subst this; exact Nat.le_refl _
1024  | succ j ih =>
1025    by_cases hij : i = j + 1
1026    · subst hij; exact Nat.le_refl _
1027    · have := ih (by omega)
1028      simp only [desc]
1029      split
1030      · simp only; have := Nat.two_pow_pos (width ls (j + 1) root mx); omega
1031      · exact this
1032
1033theorem desc_short (ls : List Nat) {root mx i : Nat} (hi : i < nz ls) (hs : L ls i ≤ root) :
1034    desc ls root mx i = desc ls root mx 0 := by
1035  induction i with
1036  | zero => rfl
1037  | succ i ih =>
1038    have hm := L_mono ls (show i ≤ i + 1 by omega) hi
1039    simp only [desc]
1040    rw [ite_eq_right (by intro h; exact absurd h.1 (by omega))]
1041    exact ih (by omega) (by omega)
1042
1043/-- A long code's descriptor is the one set up at the start of its group. -/
1044theorem desc_long {ls : List Nat} {root mx : Nat} (hmin : L ls 0 ≤ root) {i : Nat}
1045    (hi : i < nz ls) (hl : root < L ls i) :
1046    ∃ a, a + 1 ≤ i ∧ startsAt ls root a ∧ grp ls root (a + 1) = grp ls root i ∧
1047      (desc ls root mx i).drop = root ∧ (desc ls root mx i).curr = width ls (a + 1) root mx ∧
1048      (desc ls root mx i).low = rev root (grp ls root i) := by
1049  induction i with
1050  | zero => omega
1051  | succ i ih =>
1052    simp only [desc]
1053    by_cases hs : startsAt ls root i
1054    · rw [ite_eq_left hs]
1055      exact ⟨i, Nat.le_refl _, hs, rfl, rfl, rfl, rfl⟩
1056    · rw [ite_eq_right hs]
1057      have hli : root < L ls i ∧ grp ls root (i + 1) = grp ls root i := by
1058        unfold startsAt at hs
1059        refine Classical.byContradiction fun hc => hs ⟨hl, ?_⟩
1060        by_cases h1 : L ls i ≤ root
1061        · exact Or.inl h1
1062        · exact Or.inr fun he => hc ⟨by omega, he⟩
1063      obtain ⟨a, ha, hsa, hga, hd, hc, hlow⟩ := ih (by omega) hli.1
1064      exact ⟨a, by omega, hsa, by rw [hga, hli.2], hd, hc, by rw [hlow, hli.2]⟩
1065
1066/-- Safety core: every code fits the table it is written into. -/
1067theorem desc_fits {ls : List Nat} {root mx : Nat} (hc : CompleteCode ls root mx) {i : Nat}
1068    (hi : i < nz ls) :
1069    (desc ls root mx i).drop ≤ L ls i ∧
1070      L ls i - (desc ls root mx i).drop ≤ (desc ls root mx i).curr ∧
1071      (desc ls root mx i).curr ≤ 15 ∧ (desc ls root mx i).drop ≤ root := by
1072  have hmx := hc.mx_le
1073  have hr15 : root ≤ 15 := Nat.le_trans hc.root_le hmx
1074  by_cases hs : L ls i ≤ root
1075  · rw [desc_short ls hi hs]; simp [desc]; omega
1076  · obtain ⟨a, ha, hsa, hga, hd, hcur, _⟩ := desc_long (mx := mx) hc.min_le hi (by omega)
1077    have hcov := look_covers hc (show a + 1 < nz ls by omega) hsa (show a + 1 ≤ i from ha) hi hga.symm
1078    have hw := width_spec ls (show a + 1 < nz ls by omega) hmx hsa.1 (hc.L_le_mx (by omega))
1079    rw [hd, hcur]
1080    omega
1081
1082end Zlib.Inftrees.Canon
ZLIB × LEAN

全局目录

当前位置inftrees.c.canon.lean