Skip to content
REFERENCE / ZLIB × LEAN

deflate.c.engine.lmmain.lean

Source snapshot · f3ed714f39390511 · 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.«deflate.c.engine.lmbody»
2
3/-!
4# deflate.c, engine: `longest_match`
5
6`longest_match_ok`: under the environment `LMEnv` (window block, `prev` block, position facts and the chain facts that
7the hash invariant H gives), the function does not fault, only `match_start` changes, and it returns
8`min(best_len, lookahead)` where `prev_length <= best_len <= 258` and either `best_len = prev_length` with `match_start`
9unchanged, or `match_start` names a match: it lies before `strstart`, within `MAX_DIST`, and the window bytes at
10`match_start` and at `strstart` agree on the first `best_len` bytes (so on the returned length).
11-/
12
13namespace Zlib.Deflate.Engine.Proofs
14open C Zlib.Deflate
15
16/-- The condition of the `longest_match` loop, as in the translation. -/
17def lmCond (prev : WPtr) (wmask limit : UInt32) : LMState → M (Bool × LMState) := fun st => do
18  if st.brk then return (false, st)
19  let cm : UInt32 := (← Ptr.index prev (st.cur_match &&& wmask).toNat).toUInt32
20  let st := { st with cur_match := cm }
21  if cm > limit then
22    let cl := st.chain_length - 1
23    return (cl != 0, { st with chain_length := cl })
24  return (false, st)
25
26theorem longest_match_unfold (s : DeflateStatePtr) (cur_match : UInt32) : longest_match s cur_match = (do
27  let d ← ldDeflateState s
28  let mut chain_length : UInt32 := d.max_chain_length
29  let scan ← padd d.window d.strstart.toNat
30  let best_len : Int32 := d.prev_length.toInt32
31  let mut nice_match : Int32 := d.nice_match
32  let maxd : UInt32 := d.w_size - MIN_LOOKAHEAD_u
33  let limit : UInt32 := if d.strstart > maxd then d.strstart - maxd else 0
34  let prev := d.prev
35  let wmask := d.w_mask
36  let _strend ← padd (← padd d.window d.strstart.toNat) MAX_MATCH_u.toNat
37  let scan_end1 ← index8 scan (← isub best_len 1).toInt
38  let scan_end ← index8 scan best_len.toInt
39  if d.prev_length ≥ d.good_match then chain_length := chain_length >>> 2
40  if nice_match.toUInt32 > d.lookahead then nice_match := d.lookahead.toInt32
41  let st ← cdoWhile (lm_body s) (lmCond prev wmask limit)
42    { cur_match, chain_length, best_len, nice_match, scan, scan_end1, scan_end, brk := false }
43  let lookahead ← rd s (·.lookahead)
44  if st.best_len.toUInt32 ≤ lookahead then return st.best_len.toUInt32
45  return lookahead) := rfl
46
47/-- The state after the condition read `v = prev[cur_match & wmask]` and set the counter to `cl`. -/
48def lmStep (st1 : LMState) (v : UInt16) (cl : UInt32) : LMState := { st1 with cur_match := v.toUInt32, chain_length := cl }
49
50/-- What the loop guarantees at its end (or at `break`). -/
51def LMOut (h0 : Heap) (sr : Nat) (d : DeflateState) (wa : Array UInt8) (st : LMState) (h : Heap) : Prop :=
52  ∃ (ms : UInt32) (b : Nat), h = hAt h0 sr d ms ∧ st.best_len.toInt = (b : Int) ∧ d.prev_length.toNat ≤ b ∧ b ≤ 258 ∧
53    ((b = d.prev_length.toNat ∧ ms = d.match_start) ∨
54     (d.prev_length.toNat < b ∧ GoodMatch wa d.strstart.toNat d.w_size.toNat ms.toNat b))
55
56theorem LMInv.out {h0 : Heap} {sr wb pb : Nat} {d : DeflateState} {wa : Array UInt8} {pa : Array UInt16} {c : UInt32}
57    {st : LMState} {h : Heap} (hI : LMInv h0 sr d wb pb wa pa c st h) : LMOut h0 sr d wa st h := by
58  obtain ⟨ms, b, hh, _, hb, hpl, hb258, _, _, hgood⟩ := hI
59  exact ⟨ms, b, hh, hb, hpl, hb258, hgood⟩
60
61theorem u32_toInt32_toInt (x : UInt32) (hx : x.toNat < 2 ^ 31) : x.toInt32.toInt = (x.toNat : Int) := by
62  have h1 : x.toInt32.toInt = x.toBitVec.toInt := rfl
63  rw [BitVec.toInt_eq_toNat_cond] at h1
64  have : x.toBitVec.toNat = x.toNat := rfl
65  rw [this] at h1
66  split at h1 <;> omega
67
68theorem i32_toUInt32_toNat (x : Int32) (b : Nat) (hx : x.toInt = (b : Int)) (hb : b < 2 ^ 31) : x.toUInt32.toNat = b := by
69  have h1 : x.toInt = x.toBitVec.toInt := rfl
70  rw [BitVec.toInt_eq_toNat_cond] at h1
71  have : x.toUInt32.toNat = x.toBitVec.toNat := rfl
72  rw [this]
73  split at h1 <;> omega
74
75/-- **The loop.** From a state with the invariant and `brk = false`, the loop does not fault and ends in a state
76that satisfies `LMOut`. The measure is `cur_match`, which falls at every step because `prev[p & wmask] < p` (H). -/
77theorem lm_loop_ok {h0 : Heap} {sr wb pb : Nat} {d : DeflateState} {wa : Array UInt8} {pa : Array UInt16} {c : UInt32}
78    (E : LMEnv h0 sr d wb pb wa pa c) (limit : UInt32) (hlimit : limit.toNat = lmLimit d.strstart.toNat (d.w_size.toNat - 262))
79    (st : LMState) (h : Heap) (hbrk : st.brk = false) (hI : LMInv h0 sr d wb pb wa pa c st h) :
80    ∃ st' h', cdoWhile (lm_body (some (.tab sr))) (lmCond d.prev d.w_mask limit) st h = .ok (st', h') ∧
81      LMOut h0 sr d wa st' h' := by
82  have key := cdoWhile_measure (σ := LMState) (body := lm_body (some (.tab sr))) (cond := lmCond d.prev d.w_mask limit)
83    (fun st h => st.brk = false ∧ LMInv h0 sr d wb pb wa pa c st h) (fun st => st.cur_match.toNat)
84    (fun st h => LMOut h0 sr d wa st h) ?_ (s := st) (h := h) ⟨hbrk, hI⟩
85    (by unfold fuel; have := st.cur_match.toNat_lt; omega)
86  · exact key
87  · intro st h hIn
88    obtain ⟨hbrk, hI⟩ := hIn
89    obtain ⟨st1, h1, hrun, hI1, hcur, hcl, hnm⟩ := lm_body_ok E st hbrk hI
90    have hout := hI1.out
91    by_cases hb1 : st1.brk = true
92    · exact ⟨st1, h1, false, st1, h1, hrun, by simp [lmCond, hb1], fun _ => hout, by simp⟩
93    have hb1' : st1.brk = false := by simpa using hb1
94    obtain ⟨k, hk, hk9, hk15⟩ := E.wsb
95    have hws9 : 512 ≤ d.w_size.toNat := by
96      rw [hk]; calc 512 = 2 ^ 9 := by decide
97        _ ≤ 2 ^ k := Nat.pow_le_pow_right (by decide) hk9
98    have hI1' := hI1
99    obtain ⟨ms1, b1, hh1, hscan1, hb, hpl, hb258, hse', hch1, hgood1⟩ := hI1'
100    obtain ⟨hcm1, hcmlt, hcmprev, _⟩ := E.chain _ hch1
101    have hwm : d.w_mask.toNat = d.w_size.toNat - 1 := by
102      rw [E.wmask, UInt32.toNat_sub_of_le _ _ (by rw [UInt32.le_iff_toNat_le]; simp; omega)]
103      simp
104    have hidx : (st1.cur_match &&& d.w_mask).toNat = st1.cur_match.toNat &&& (d.w_size.toNat - 1) := by
105      rw [UInt32.toNat_and, hwm]
106    have hidx_lt : st1.cur_match.toNat &&& (d.w_size.toNat - 1) < d.w_size.toNat :=
107      and_wm_lt (by rw [hk]) _
108    have hpw : h1.words pb = some pa := by rw [hh1]; exact E.pwords
109    have hidx_arr : st1.cur_match.toNat &&& (d.w_size.toNat - 1) < pa.size := by have := E.psize; omega
110    have hrd : Ptr.index d.prev (↑(st1.cur_match &&& d.w_mask).toNat) h1 =
111        .ok (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1)), h1) := by
112      rw [E.prevp, hidx]
113      have := Ptr.index_ok (h := h1) (r := WRef.blk pb) (a := pa) (off := 0)
114        (i := st1.cur_match.toNat &&& (d.w_size.toNat - 1)) (by simpa using hpw) (by omega)
115      unfold OkOn at this
116      simp only [Nat.zero_add] at this
117      rw [this, wfn_getElem _ _ hidx_arr]
118    by_cases big : limit.toNat < (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1))).toNat
119    · have hgt : limit < (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1))).toUInt32 := by
120        rw [UInt32.lt_iff_toNat_lt]; simpa using big
121      have hch2 : Chain (wfn pa) (d.w_size.toNat - 1) (lmLimit d.strstart.toNat (d.w_size.toNat - 262)) c.toNat
122          (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1))).toNat :=
123        Chain.step hch1 rfl (by rw [← hlimit]; exact big)
124      by_cases hcl0 : (st1.chain_length - 1 != 0) = true
125      · refine ⟨st1, h1, true, lmStep st1 (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1))) (st1.chain_length - 1), h1, hrun, ?_, by simp, ?_⟩
126        · simp only [lmCond, bind_app, pure_app, M_ite_app, hb1', Bool.false_eq_true, ↓reduceIte, hrd, GT.gt, hgt, hcl0, lmStep]
127        · intro _
128          refine ⟨⟨hb1', ms1, b1, hh1, hscan1, hb, hpl, hb258, hse', ?_, hgood1⟩, ?_⟩
129          · simpa [lmStep] using hch2
130          · simp only [lmStep, hcur] at hcmprev ⊢
131            simpa using hcmprev
132      · have hcl0' : (st1.chain_length - 1 != 0) = false := by simpa using hcl0
133        refine ⟨st1, h1, false, lmStep st1 (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1))) (st1.chain_length - 1), h1, hrun, ?_, fun _ => hout, by simp⟩
134        simp only [lmCond, bind_app, pure_app, M_ite_app, hb1', Bool.false_eq_true, ↓reduceIte, hrd, GT.gt, hgt, hcl0', lmStep]
135    · have hng : ¬ limit < (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1))).toUInt32 := by
136        rw [UInt32.lt_iff_toNat_lt]; simpa using big
137      refine ⟨st1, h1, false, lmStep st1 (wfn pa (st1.cur_match.toNat &&& (d.w_size.toNat - 1))) st1.chain_length, h1, hrun, ?_, fun _ => hout, by simp⟩
138      simp only [lmCond, bind_app, pure_app, M_ite_app, hb1', Bool.false_eq_true, ↓reduceIte, hrd, GT.gt, hng, lmStep]
139
140theorem hAt_self (h0 : Heap) (sr : Nat) (d : DeflateState) (hd : h0.dstates sr = some d) :
141    hAt h0 sr d d.match_start = h0 := by
142  simp [hAt, upd_self _ _ _ hd]
143
144/-- The initial state of the loop satisfies the invariant, whatever `chain_length` and `nice_match` are. -/
145theorem lm_init_inv {h0 : Heap} {sr wb pb : Nat} {d : DeflateState} {wa : Array UInt8} {pa : Array UInt16} {c : UInt32}
146    (E : LMEnv h0 sr d wb pb wa pa c) (cl : UInt32) (nm : Int32) :
147    LMInv h0 sr d wb pb wa pa c
148      { cur_match := c, chain_length := cl, best_len := d.prev_length.toInt32, nice_match := nm,
149        scan := Ptr.ref (BRef.blk wb) d.strstart.toNat,
150        scan_end1 := bfn wa (d.strstart.toNat + d.prev_length.toNat - 1),
151        scan_end := bfn wa (d.strstart.toNat + d.prev_length.toNat), brk := false } h0 := by
152  have h31 : d.prev_length.toNat < 2 ^ 31 := by have := E.plle; omega
153  refine ⟨d.match_start, d.prev_length.toNat, (hAt_self h0 sr d E.hd).symm, rfl, u32_toInt32_toInt _ h31, Nat.le_refl _,
154    E.plle, fun _ => ⟨rfl, rfl⟩, ?_, Or.inl ⟨rfl, rfl⟩⟩
155  exact Chain.start
156
157theorem lm_loop_total {h0 : Heap} {sr wb pb : Nat} {d : DeflateState} {wa : Array UInt8} {pa : Array UInt16} {c : UInt32}
158    (E : LMEnv h0 sr d wb pb wa pa c) (limit : UInt32) (hlimit : limit.toNat = lmLimit d.strstart.toNat (d.w_size.toNat - 262))
159    (st : LMState) (h : Heap) (hbrk : st.brk = false) (hI : LMInv h0 sr d wb pb wa pa c st h)
160    (res : Except Fault (LMState × Heap)) (hres : cdoWhile (lm_body (some (.tab sr))) (lmCond d.prev d.w_mask limit) st h = res) :
161    ∃ st' h', res = .ok (st', h') ∧ LMOut h0 sr d wa st' h' := by
162  obtain ⟨st', h', hr, ho⟩ := lm_loop_ok E limit hlimit st h hbrk hI
163  exact ⟨st', h', hres.symm.trans hr, ho⟩
164
165
166/-- The part of `longest_match` after the two tests on `prev_length` and `lookahead`: the loop and the final `min`. -/
167def lmRest (sr : Nat) (L : UInt32) (d : DeflateState) (c : UInt32) (wb : Nat) (wa : Array UInt8) (cl : UInt32) (nm : Int32) :
168    M UInt32 := do
169  let st ← cdoWhile (lm_body (some (.tab sr))) (lmCond d.prev d.w_mask L)
170      { cur_match := c, chain_length := cl, best_len := d.prev_length.toInt32, nice_match := nm,
171        scan := Ptr.ref (BRef.blk wb) d.strstart.toNat,
172        scan_end1 := bfn wa (d.strstart.toNat + d.prev_length.toNat - 1),
173        scan_end := bfn wa (d.strstart.toNat + d.prev_length.toNat), brk := false }
174  let lookahead ← rd (some (.tab sr)) (fun x => x.lookahead)
175  if st.best_len.toUInt32 ≤ lookahead then return st.best_len.toUInt32
176  return lookahead
177
178theorem lmRest_ok {h0 : Heap} {sr wb pb : Nat} {d : DeflateState} {wa : Array UInt8} {pa : Array UInt16} {c : UInt32}
179    (E : LMEnv h0 sr d wb pb wa pa c) (L : UInt32)
180    (hlimit : L.toNat = lmLimit d.strstart.toNat (d.w_size.toNat - 262)) (cl : UInt32) (nm : Int32) :
181    ∃ (r : UInt32) (h' : Heap) (ms : UInt32) (best : Nat),
182      lmRest sr L d c wb wa cl nm h0 = .ok (r, h') ∧
183      r = UInt32.ofNat (lmResult best d.lookahead.toNat) ∧ h' = hAt h0 sr d ms ∧
184      d.prev_length.toNat ≤ best ∧ best ≤ 258 ∧
185      ((best = d.prev_length.toNat ∧ ms = d.match_start) ∨
186       (d.prev_length.toNat < best ∧ GoodMatch wa d.strstart.toNat d.w_size.toNat ms.toNat best)) := by
187  obtain ⟨st', h', hrun, ms, b, hh, hb, hpl, hb258, hgood⟩ :=
188    lm_loop_ok E L hlimit _ h0 rfl (lm_init_inv E cl nm)
189  subst hh
190  have hdd : (hAt h0 sr d ms).dstates sr = some { d with match_start := ms } := by simp [hAt]
191  have hrd : rd (some (.tab sr)) (fun x => x.lookahead) (hAt h0 sr d ms) = .ok (d.lookahead, hAt h0 sr d ms) := by
192    simp [rd, ldDeflateState_tab hdd]
193  have hbn : st'.best_len.toUInt32.toNat = b := i32_toUInt32_toNat _ b hb (by omega)
194  have hbu : st'.best_len.toUInt32 = UInt32.ofNat b := by
195    apply UInt32.toNat_inj.mp; rw [hbn]; simp; omega
196  by_cases hle : b ≤ d.lookahead.toNat
197  · have hle' : st'.best_len.toUInt32 ≤ d.lookahead := by
198      rw [UInt32.le_iff_toNat_le, hbn]; exact hle
199    refine ⟨st'.best_len.toUInt32, hAt h0 sr d ms, ms, b, ?_, ?_, rfl, hpl, hb258, hgood⟩
200    · simp only [lmRest, bind_app, pure_app, M_ite_app, hrun, hrd, hle', ite_true]
201    · rw [hbu]; unfold lmResult; rw [ite_eq_left hle]
202  · have hle' : ¬ st'.best_len.toUInt32 ≤ d.lookahead := by
203      rw [UInt32.le_iff_toNat_le, hbn]; exact hle
204    refine ⟨d.lookahead, hAt h0 sr d ms, ms, b, ?_, ?_, rfl, hpl, hb258, hgood⟩
205    · simp only [lmRest, bind_app, pure_app, M_ite_app, hrun, hrd, hle', ite_false]
206    · unfold lmResult; rw [ite_eq_right hle]; simp
207
208/-- **longest_match, safety and specification.** Under `LMEnv` the call does not fault and only `match_start` changes
209(the result heap is `hAt h0 sr d ms`). It returns `min(best, lookahead)` for some `best` with
210`prev_length <= best <= 258`; either `best = prev_length` and `match_start` is unchanged, or `match_start` names a good
211match of length `best`: before `strstart`, within `MAX_DIST`, and the window bytes agree on the first `best` bytes. -/
212theorem longest_match_ok {h0 : Heap} {sr wb pb : Nat} {d : DeflateState} {wa : Array UInt8} {pa : Array UInt16} {c : UInt32}
213    (E : LMEnv h0 sr d wb pb wa pa c) :
214    ∃ (r : UInt32) (h' : Heap) (ms : UInt32) (best : Nat),
215      longest_match (some (.tab sr)) c h0 = .ok (r, h') ∧
216      r = UInt32.ofNat (lmResult best d.lookahead.toNat) ∧ h' = hAt h0 sr d ms ∧
217      d.prev_length.toNat ≤ best ∧ best ≤ 258 ∧
218      ((best = d.prev_length.toNat ∧ ms = d.match_start) ∨
219       (d.prev_length.toNat < best ∧ GoodMatch wa d.strstart.toNat d.w_size.toNat ms.toNat best)) := by
220  obtain ⟨k, hk, hk9, hk15⟩ := E.wsb
221  have hws9 : 512 ≤ d.w_size.toNat := by
222    rw [hk]; calc 512 = 2 ^ 9 := by decide
223      _ ≤ 2 ^ k := Nat.pow_le_pow_right (by decide) hk9
224  have hws15 : d.w_size.toNat ≤ 32768 := by
225    rw [hk]; calc 2 ^ k ≤ 2 ^ 15 := Nat.pow_le_pow_right (by decide) hk15
226      _ = 32768 := by decide
227  have hroom := E.room
228  have hasz := E.asize
229  have hss : d.strstart.toNat + 258 < wa.size := by omega
230  have hss2 : 2 ≤ d.strstart.toNat := by have := E.c1; have := E.clt; omega
231  have hmm : MAX_MATCH_u.toNat = 258 := rfl
232  have h1i : (1 : Int32).toInt = 1 := by decide
233  have hpl := E.plle
234  have e_ld0 : ldDeflateState (some (.tab sr)) h0 = .ok (d, h0) := ldDeflateState_tab E.hd
235  have hbytes : h0.bytes wb = some wa := E.wbytes
236  have f14 : padd (Ptr.ref (BRef.blk wb) 0) d.strstart.toNat h0 = .ok (Ptr.ref (BRef.blk wb) d.strstart.toNat, h0) := by
237    simpa using padd_ok' (h := h0) (r := BRef.blk wb) (a := wa) (off := 0) (n := d.strstart.toNat)
238      (by simpa using hbytes) (by omega)
239  have f15 : padd (Ptr.ref (BRef.blk wb) d.strstart.toNat) 258 h0 =
240      .ok (Ptr.ref (BRef.blk wb) (d.strstart.toNat + 258), h0) := padd_ok' (by simpa using hbytes) (by omega)
241  have i0 : d.prev_length.toInt32.toInt = (d.prev_length.toNat : Int) := u32_toInt32_toInt _ (by omega)
242  have i4 : isub d.prev_length.toInt32 1 h0 = .ok (Int32.ofInt ((d.prev_length.toNat : Int) - 1), h0) := by
243    rw [isub_ok _ 1 (by rw [i0, h1i]; omega), i0, h1i]
244  have i5' : (Int32.ofInt ((d.prev_length.toNat : Int) - 1)).toInt = (d.prev_length.toNat : Int) - 1 :=
245    Int32.toInt_ofInt_of_le (by omega) (by omega)
246  have i5 : index8 (Ptr.ref (BRef.blk wb) d.strstart.toNat) ((d.prev_length.toNat : Int) - 1) h0 =
247      .ok (bfn wa (d.strstart.toNat + d.prev_length.toNat - 1), h0) := index8_bfn hbytes (by omega) (by omega)
248  have i6 : index8 (Ptr.ref (BRef.blk wb) d.strstart.toNat) (d.prev_length.toNat : Int) h0 =
249      .ok (bfn wa (d.strstart.toNat + d.prev_length.toNat), h0) := index8_bfn hbytes (by omega) (by omega)
250  have hmin : MIN_LOOKAHEAD_u.toNat = 262 := rfl
251  have hsub : (d.w_size - MIN_LOOKAHEAD_u).toNat = d.w_size.toNat - 262 := by
252    rw [UInt32.toNat_sub_of_le _ _ (by rw [UInt32.le_iff_toNat_le, hmin]; omega), hmin]
253  obtain ⟨L, hL⟩ : ∃ L : UInt32, L = (if d.strstart > d.w_size - MIN_LOOKAHEAD_u then d.strstart - (d.w_size - MIN_LOOKAHEAD_u) else 0) :=
254    ⟨_, rfl⟩
255  have hlimit : L.toNat = lmLimit d.strstart.toNat (d.w_size.toNat - 262) := by
256    rw [hL]; unfold lmLimit
257    by_cases hg : d.strstart > d.w_size - MIN_LOOKAHEAD_u
258    · have hg' : d.strstart.toNat > d.w_size.toNat - 262 := by
259        rw [GT.gt, UInt32.lt_iff_toNat_lt, hsub] at hg; exact hg
260      rw [ite_eq_left hg, ite_eq_left hg', UInt32.toNat_sub_of_le _ _ (by rw [UInt32.le_iff_toNat_le]; rw [GT.gt, UInt32.lt_iff_toNat_lt] at hg; omega), hsub]
261    · have hg' : ¬ d.strstart.toNat > d.w_size.toNat - 262 := by
262        intro hh; apply hg; rw [GT.gt, UInt32.lt_iff_toNat_lt, hsub]; exact hh
263      rw [ite_eq_right hg, ite_eq_right hg']; rfl
264  have hLsame : (if d.strstart > d.w_size - MIN_LOOKAHEAD_u then d.strstart - (d.w_size - MIN_LOOKAHEAD_u) else 0) = L := hL.symm
265  have key : ∀ (cl : UInt32) (nm : Int32), ∃ (r : UInt32) (h' : Heap) (ms : UInt32) (best : Nat),
266      lmRest sr L d c wb wa cl nm h0 = .ok (r, h') ∧
267      r = UInt32.ofNat (lmResult best d.lookahead.toNat) ∧ h' = hAt h0 sr d ms ∧
268      d.prev_length.toNat ≤ best ∧ best ≤ 258 ∧
269      ((best = d.prev_length.toNat ∧ ms = d.match_start) ∨
270       (d.prev_length.toNat < best ∧ GoodMatch wa d.strstart.toNat d.w_size.toNat ms.toNat best)) :=
271    fun cl nm => lmRest_ok E L hlimit cl nm
272  rw [longest_match_unfold]
273  simp only [bind_app, pure_app, M_ite_app, e_ld0, E.win, f14, f15, i0, i4, i5', i5, i6, hmm, hLsame]
274  by_cases hg : d.prev_length ≥ d.good_match <;> by_cases hn : d.nice_match.toUInt32 > d.lookahead
275  · obtain ⟨r, h', ms, best, hr, hrest⟩ := key (d.max_chain_length >>> 2) d.lookahead.toInt32
276    refine ⟨r, h', ms, best, ?_, hrest⟩
277    simp only [hg, hn, ite_true]; simp only [lmRest, bind_app, pure_app, M_ite_app] at hr; exact hr
278  · obtain ⟨r, h', ms, best, hr, hrest⟩ := key (d.max_chain_length >>> 2) d.nice_match
279    refine ⟨r, h', ms, best, ?_, hrest⟩
280    simp only [hg, hn, ite_true, ite_false]; simp only [lmRest, bind_app, pure_app, M_ite_app] at hr; exact hr
281  · obtain ⟨r, h', ms, best, hr, hrest⟩ := key d.max_chain_length d.lookahead.toInt32
282    refine ⟨r, h', ms, best, ?_, hrest⟩
283    simp only [hg, hn, ite_true, ite_false]; simp only [lmRest, bind_app, pure_app, M_ite_app] at hr; exact hr
284  · obtain ⟨r, h', ms, best, hr, hrest⟩ := key d.max_chain_length d.nice_match
285    refine ⟨r, h', ms, best, ?_, hrest⟩
286    simp only [hg, hn, ite_true, ite_false]; simp only [lmRest, bind_app, pure_app, M_ite_app] at hr; exact hr
287
288end Zlib.Deflate.Engine.Proofs
ZLIB × LEAN

Global contents

READING NOWdeflate.c.engine.lmmain.lean