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

inffast.c.copy.lean

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

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

1import ZlibF.Proof.«inffast.c.step1»
2
3namespace Zlib.Inffast.Proofs
4open C Zlib.Inffast Zlib.Inffast.Spec
5
6/-! ### Copying bytes: the pure array functions -/
7
8/-- `k` bytes copied from the fixed array `S` (offset `fo`) into `A` (offset `oo`), one at a time. -/
9def blitN (S : Array UInt8) : Nat → Nat → Nat → Array UInt8 → Array UInt8
10  | 0, _, _, A => A
11  | k + 1, fo, oo, A => blitN S k (fo + 1) (oo + 1) (A.set! oo (S.getD fo 0))
12
13/-- `k` bytes copied inside `A` from offset `fo` to offset `oo`, one at a time (the source may be written meanwhile). -/
14def cpyN : Nat → Nat → Nat → Array UInt8 → Array UInt8
15  | 0, _, _, A => A
16  | k + 1, fo, oo, A => cpyN k (fo + 1) (oo + 1) (A.set! oo (A.getD fo 0))
17
18theorem blitN_size (S : Array UInt8) : ∀ k fo oo A, (blitN S k fo oo A).size = A.size
19  | 0, _, _, _ => rfl
20  | k + 1, fo, oo, A => by simp [blitN, blitN_size S k]
21
22theorem cpyN_size : ∀ k fo oo (A : Array UInt8), (cpyN k fo oo A).size = A.size
23  | 0, _, _, _ => rfl
24  | k + 1, fo, oo, A => by simp [cpyN, cpyN_size k]
25
26theorem blitN_add (S : Array UInt8) : ∀ k1 k2 fo oo A,
27    blitN S (k1 + k2) fo oo A = blitN S k2 (fo + k1) (oo + k1) (blitN S k1 fo oo A)
28  | 0, k2, fo, oo, A => by simp [blitN]
29  | k1 + 1, k2, fo, oo, A => by
30    have := blitN_add S k1 k2 (fo + 1) (oo + 1) (A.set! oo (S.getD fo 0))
31    rw [show k1 + 1 + k2 = (k1 + k2) + 1 by omega]
32    simp only [blitN]
33    rw [this]
34    simp [Nat.add_assoc, Nat.add_comm 1 k1]
35
36theorem cpyN_add : ∀ k1 k2 fo oo (A : Array UInt8),
37    cpyN (k1 + k2) fo oo A = cpyN k2 (fo + k1) (oo + k1) (cpyN k1 fo oo A)
38  | 0, k2, fo, oo, A => by simp [cpyN]
39  | k1 + 1, k2, fo, oo, A => by
40    have := cpyN_add k1 k2 (fo + 1) (oo + 1) (A.set! oo (A.getD fo 0))
41    rw [show k1 + 1 + k2 = (k1 + k2) + 1 by omega]
42    simp only [cpyN]
43    rw [this]
44    simp [Nat.add_assoc, Nat.add_comm 1 k1]
45
46variable (e : Env)
47
48/-- Writing the output block of `e.heap A` gives `e.heap A'`. -/
49theorem Env.heap_put (A A' : Array UInt8) (msg m) :
50    Space.put (e.heap A msg m) (BRef.blk e.ob) A' = e.heap A' msg m := by
51  rw [BRef.put_blk]
52  unfold Env.heap
53  rw [put_bytes_comm]
54  simp only [put_bytes, upd_upd]
55
56/-- `*out++ = *from++;` on the heap `e.heap A msg m`, the source block `fb` holding `S`. -/
57theorem copy1_run (A S : Array UInt8) (msg : BPtr) (m : UInt32) (l : L) (fb fo oo : Nat)
58    (hf : l.from_ = .ref (BRef.blk fb) fo) (ho : l.out = .ref (BRef.blk e.ob) oo)
59    (hSg : (e.heap A msg m).bytes fb = some S) (hfo : fo < S.size) (hoo : oo < A.size) :
60    copy1 l (e.heap A msg m) = .ok ({ l with from_ := .ref (BRef.blk fb) (fo + 1), out := .ref (BRef.blk e.ob) (oo + 1) },
61      e.heap (A.set! oo (S.getD fo 0)) msg m) := by
62  have hAg : Space.get (e.heap A msg m) (BRef.blk e.ob) = some A := e.heap_bytes_ob A msg m
63  have hSg' : Space.get (e.heap A msg m) (BRef.blk fb) = some S := hSg
64  have hSd : S.getD fo 0 = S[fo] := by simp [Array.getD_eq_getD_getElem?, hfo]
65  have hst : store8 (Ptr.ref (BRef.blk e.ob) oo) S[fo] (e.heap A msg m) =
66      .ok ((), e.heap (A.set! oo S[fo]) msg m) := by
67    rw [← e.heap_put A (A.set! oo S[fo]) msg m]
68    exact Ptr.store_ok hAg (e.heap_ro_ob A msg m) hoo
69  have hsz : (A.set! oo S[fo]).size = A.size := by simp
70  have hAg2 : Space.get (e.heap (A.set! oo S[fo]) msg m) (BRef.blk e.ob) = some (A.set! oo S[fo]) :=
71    e.heap_bytes_ob _ msg m
72  have hadd := Ptr.add_nat_ok (h := e.heap A msg m) (r := BRef.blk fb) (a := S) (off := fo) (n := 1) hSg' (by omega)
73  have hadd2 := Ptr.add_nat_ok (h := e.heap (A.set! oo S[fo]) msg m) (r := BRef.blk e.ob) (a := A.set! oo S[fo])
74    (off := oo) (n := 1) hAg2 (by omega)
75  unfold copy1
76  rw [hf, ho, bind_ok (Ptr.load_ok hSg' hfo), bind_ok (by exact hadd), bind_ok hst,
77    bind_ok (by exact hadd2), hSd]
78  rfl
79
80
81theorem u32_sub_one_toNat {x : UInt32} (h : 1 ≤ x.toNat) : (x - 1).toNat = x.toNat - 1 :=
82  u32_toNat_sub (by simpa using h)
83
84theorem u32_sub_one_ne {x : UInt32} (h : 2 ≤ x.toNat) : ((x - 1) != 0) = true := by
85  have := u32_sub_one_toNat (x := x) (by omega)
86  simp only [bne_iff_ne, ne_eq]
87  intro h0
88  rw [h0] at this
89  simp at this
90  omega
91
92theorem u32_sub_one_eq {x : UInt32} (h : x.toNat = 1) : ((x - 1) != 0) = false := by
93  have := u32_sub_one_toNat (x := x) (by omega)
94  have h0 : x - 1 = 0 := by
95    apply UInt32.toNat_inj.mp
96    simp [this, h]
97  simp [h0]
98
99/-- `do { *out++ = *from++; } while (--op);` copying from a block `fb` other than the output block. -/
100theorem copyOp_win_go (A S : Array UInt8) (msg : BPtr) (m : UInt32) (fb : Nat) (hfb : fb ≠ e.ob)
101    (hSg : e.h0.bytes fb = some S) :
102    ∀ n (l : L) (fo oo : Nat) (A : Array UInt8) (fu : Nat), l.op.toNat = n + 1 → n ≤ fu →
103      l.from_ = .ref (BRef.blk fb) fo → l.out = .ref (BRef.blk e.ob) oo → fo + n + 1 ≤ S.size → oo + n + 1 ≤ A.size →
104      cdoWhile.go copy1 (fun l => let op := l.op - 1; pure (op != 0, { l with op })) (fu + 1) l (e.heap A msg m) =
105        .ok ({ l with from_ := .ref (BRef.blk fb) (fo + n + 1), out := .ref (BRef.blk e.ob) (oo + n + 1), op := 0 },
106          e.heap (blitN S (n + 1) fo oo A) msg m) := by
107  intro n
108  induction n with
109  | zero =>
110    intro l fo oo A fu hop _ hf ho hfo hoo
111    have hS : (e.heap A msg m).bytes fb = some S := by rw [e.heap_bytes_ne A msg m hfb]; exact hSg
112    simp only [cdoWhile.go, bind_app]
113    rw [copy1_run e A S msg m l fb fo oo hf ho hS (by omega) (by omega)]
114    simp only [pure_app]
115    have h1 : (l.op - 1 != 0) = false := u32_sub_one_eq (by omega)
116    have h0 : l.op - 1 = 0 := by
117      apply UInt32.toNat_inj.mp
118      simp [u32_sub_one_toNat (x := l.op) (by omega), hop]
119    simp [h1, h0, blitN]
120  | succ n ih =>
121    intro l fo oo A fu hop hfu hf ho hfo hoo
122    obtain ⟨fu, rfl⟩ : ∃ fu', fu = fu' + 1 := ⟨fu - 1, by omega⟩
123    have hS : (e.heap A msg m).bytes fb = some S := by rw [e.heap_bytes_ne A msg m hfb]; exact hSg
124    rw [cdoWhile.go]
125    simp only [bind_app]
126    rw [copy1_run e A S msg m l fb fo oo hf ho hS (by omega) (by omega)]
127    simp only [pure_app]
128    have h1 : (l.op - 1 != 0) = true := u32_sub_one_ne (by omega)
129    simp only [h1, ite_true]
130    have hop1 : (l.op - 1).toNat = n + 1 := by rw [u32_sub_one_toNat (by omega)]; omega
131    rw [ih { l with from_ := Ptr.ref (BRef.blk fb) (fo + 1), out := Ptr.ref (BRef.blk e.ob) (oo + 1), op := l.op - 1 }
132      (fo + 1) (oo + 1) (A.set! oo (S.getD fo 0)) fu hop1 (by omega) rfl rfl (by omega) (by simp; omega)]
133    have h0 : (0 : Nat) = 0 := rfl
134    simp [blitN, Nat.add_assoc, Nat.add_comm 1 n]
135
136theorem fuel_pred : fuel - 1 + 1 = fuel := by unfold fuel; omega
137
138/-- `do { *out++ = *from++; } while (--op);` with `op = n ≥ 1`, from a block other than the output block. -/
139theorem copyOp_win (S : Array UInt8) (msg : BPtr) (m : UInt32) (fb : Nat) (hfb : fb ≠ e.ob)
140    (hSg : e.h0.bytes fb = some S) (A : Array UInt8) (l : L) (n fo oo : Nat) (hop : l.op.toNat = n) (hn : 1 ≤ n)
141    (hf : l.from_ = .ref (BRef.blk fb) fo) (ho : l.out = .ref (BRef.blk e.ob) oo)
142    (hfo : fo + n ≤ S.size) (hoo : oo + n ≤ A.size) :
143    copyOp l (e.heap A msg m) = .ok ({ l with from_ := .ref (BRef.blk fb) (fo + n), out := .ref (BRef.blk e.ob) (oo + n), op := 0 },
144      e.heap (blitN S n fo oo A) msg m) := by
145  obtain ⟨n, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩
146  have hlt := UInt32.toNat_lt l.op
147  have key := copyOp_win_go e A S msg m fb hfb hSg n l fo oo A (fuel - 1) (by omega) (by unfold fuel; omega) hf ho
148    (by omega) (by omega)
149  rw [fuel_pred] at key
150  unfold copyOp cdoWhile
151  rw [key]
152  simp [Nat.add_assoc]
153
154/-- The same, copying inside the output block. -/
155theorem copyOp_out_go : ∀ n (l : L) (fo oo : Nat) (A : Array UInt8) (msg : BPtr) (m : UInt32) (fu : Nat),
156    l.op.toNat = n + 1 → n ≤ fu →
157    l.from_ = .ref (BRef.blk e.ob) fo → l.out = .ref (BRef.blk e.ob) oo → fo + n + 1 ≤ A.size → oo + n + 1 ≤ A.size →
158    cdoWhile.go copy1 (fun l => let op := l.op - 1; pure (op != 0, { l with op })) (fu + 1) l (e.heap A msg m) =
159      .ok ({ l with from_ := .ref (BRef.blk e.ob) (fo + n + 1), out := .ref (BRef.blk e.ob) (oo + n + 1), op := 0 },
160        e.heap (cpyN (n + 1) fo oo A) msg m) := by
161  intro n
162  induction n with
163  | zero =>
164    intro l fo oo A msg m fu hop _ hf ho hfo hoo
165    have hS : (e.heap A msg m).bytes e.ob = some A := e.heap_bytes_ob A msg m
166    simp only [cdoWhile.go, bind_app]
167    rw [copy1_run e A A msg m l e.ob fo oo hf ho hS (by omega) (by omega)]
168    simp only [pure_app]
169    have h1 : (l.op - 1 != 0) = false := u32_sub_one_eq (by omega)
170    have h0 : l.op - 1 = 0 := by
171      apply UInt32.toNat_inj.mp
172      simp [u32_sub_one_toNat (x := l.op) (by omega), hop]
173    simp [h0, cpyN]
174  | succ n ih =>
175    intro l fo oo A msg m fu hop hfu hf ho hfo hoo
176    obtain ⟨fu, rfl⟩ : ∃ fu', fu = fu' + 1 := ⟨fu - 1, by omega⟩
177    have hS : (e.heap A msg m).bytes e.ob = some A := e.heap_bytes_ob A msg m
178    rw [cdoWhile.go]
179    simp only [bind_app]
180    rw [copy1_run e A A msg m l e.ob fo oo hf ho hS (by omega) (by omega)]
181    simp only [pure_app]
182    have h1 : (l.op - 1 != 0) = true := u32_sub_one_ne (by omega)
183    simp only [h1, ite_true]
184    have hop1 : (l.op - 1).toNat = n + 1 := by rw [u32_sub_one_toNat (by omega)]; omega
185    rw [ih { l with from_ := Ptr.ref (BRef.blk e.ob) (fo + 1), out := Ptr.ref (BRef.blk e.ob) (oo + 1), op := l.op - 1 }
186      (fo + 1) (oo + 1) (A.set! oo (A.getD fo 0)) msg m fu hop1 (by omega) rfl rfl (by simp; omega) (by simp; omega)]
187    simp [cpyN, Nat.add_assoc, Nat.add_comm 1 n]
188
189theorem copyOp_out (A : Array UInt8) (msg : BPtr) (m : UInt32) (l : L) (n fo oo : Nat) (hop : l.op.toNat = n)
190    (hn : 1 ≤ n) (hf : l.from_ = .ref (BRef.blk e.ob) fo) (ho : l.out = .ref (BRef.blk e.ob) oo)
191    (hfo : fo + n ≤ A.size) (hoo : oo + n ≤ A.size) :
192    copyOp l (e.heap A msg m) = .ok ({ l with from_ := .ref (BRef.blk e.ob) (fo + n), out := .ref (BRef.blk e.ob) (oo + n), op := 0 },
193      e.heap (cpyN n fo oo A) msg m) := by
194  obtain ⟨n, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩
195  have hlt := UInt32.toNat_lt l.op
196  have key := copyOp_out_go e n l fo oo A msg m (fuel - 1) (by omega) (by unfold fuel; omega) hf ho (by omega) (by omega)
197  rw [fuel_pred] at key
198  unfold copyOp cdoWhile
199  rw [key]
200  simp [Nat.add_assoc]
201
202
203/-! ### The tail of a match copy, for either source -/
204
205/-- `k` bytes copied from `sel A` (offset `fo`) into `A` (offset `oo`), one at a time; `sel` is the identity when the
206source is the output block (it changes as the copy goes) and a constant when it is the window. -/
207def cpyG (sel : Array UInt8 → Array UInt8) : Nat → Nat → Nat → Array UInt8 → Array UInt8
208  | 0, _, _, A => A
209  | k + 1, fo, oo, A => cpyG sel k (fo + 1) (oo + 1) (A.set! oo ((sel A).getD fo 0))
210
211theorem cpyG_size (sel : Array UInt8 → Array UInt8) : ∀ k fo oo (A : Array UInt8), (cpyG sel k fo oo A).size = A.size
212  | 0, _, _, _ => rfl
213  | k + 1, fo, oo, A => by simp [cpyG, cpyG_size sel k]
214
215theorem cpyG_add (sel : Array UInt8 → Array UInt8) : ∀ k1 k2 fo oo (A : Array UInt8),
216    cpyG sel (k1 + k2) fo oo A = cpyG sel k2 (fo + k1) (oo + k1) (cpyG sel k1 fo oo A)
217  | 0, k2, fo, oo, A => by simp [cpyG]
218  | k1 + 1, k2, fo, oo, A => by
219    have := cpyG_add sel k1 k2 (fo + 1) (oo + 1) (A.set! oo ((sel A).getD fo 0))
220    rw [show k1 + 1 + k2 = (k1 + k2) + 1 by omega]
221    simp only [cpyG]
222    rw [this]
223    simp [Nat.add_assoc, Nat.add_comm 1 k1]
224
225theorem cpyG_id : ∀ k fo oo (A : Array UInt8), cpyG id k fo oo A = cpyN k fo oo A
226  | 0, _, _, _ => rfl
227  | k + 1, fo, oo, A => by simp [cpyG, cpyN, cpyG_id k]
228
229theorem cpyG_const (S : Array UInt8) : ∀ k fo oo (A : Array UInt8), cpyG (fun _ => S) k fo oo A = blitN S k fo oo A
230  | 0, _, _, _ => rfl
231  | k + 1, fo, oo, A => by simp [cpyG, blitN, cpyG_const S k]
232
233/-- The source block `fb` holds `sel A` while the output block holds `A`. -/
234structure Src (fb : Nat) (sel : Array UInt8 → Array UInt8) : Prop where
235  get : ∀ A msg m, (e.heap A msg m).bytes fb = some (sel A)
236  size : ∀ (A : Array UInt8) i x, (sel (A.set! i x)).size = (sel A).size
237
238theorem Src.out : Src e e.ob id :=
239  ⟨fun A msg m => e.heap_bytes_ob A msg m, fun A i x => by simp⟩
240
241theorem Src.win (fb : Nat) (S : Array UInt8) (hfb : fb ≠ e.ob) (hS : e.h0.bytes fb = some S) :
242    Src e fb (fun _ => S) :=
243  ⟨fun A msg m => by rw [e.heap_bytes_ne A msg m hfb]; exact hS, fun _ _ _ => rfl⟩
244
245variable {e}
246
247theorem copy1_src {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) (A : Array UInt8) (msg : BPtr)
248    (m : UInt32) (l : L) (fo oo : Nat) (hf : l.from_ = .ref (BRef.blk fb) fo) (ho : l.out = .ref (BRef.blk e.ob) oo)
249    (hfo : fo < (sel A).size) (hoo : oo < A.size) :
250    copy1 l (e.heap A msg m) = .ok ({ l with from_ := .ref (BRef.blk fb) (fo + 1), out := .ref (BRef.blk e.ob) (oo + 1) },
251      e.heap (A.set! oo ((sel A).getD fo 0)) msg m) :=
252  copy1_run e A (sel A) msg m l fb fo oo hf ho (hs.get A msg m) hfo hoo
253
254/-- `if (len) { *out++ = *from++; if (len > 1) *out++ = *from++; }` -/
255def tailIf (l : L) : M L := do
256  let mut l := l
257  if l.len != 0 then
258    l ← copy1 l
259    if l.len > 1 then l ← copy1 l
260  pure l
261
262/-- The condition `len > 2`. -/
263def cond3 (l : L) : M (Bool × L) := pure (l.len > 2, l)
264
265/-- The body `*out++ = *from++;` three times and `len -= 3;`. -/
266def body3 (l : L) : M L := do
267  let l ← copy1 l
268  let l ← copy1 l
269  let l ← copy1 l
270  pure { l with len := l.len - 3 }
271
272/-- Three copies in a row (the body of the unrolled loop, without `len -= 3`). -/
273theorem copy3_src {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) (A : Array UInt8) (msg : BPtr)
274    (m : UInt32) (l : L) (fo oo : Nat) (hf : l.from_ = .ref (BRef.blk fb) fo) (ho : l.out = .ref (BRef.blk e.ob) oo)
275    (hfo : fo + 3 ≤ (sel A).size) (hoo : oo + 3 ≤ A.size) :
276    body3 l (e.heap A msg m) =
277      .ok ({ l with from_ := .ref (BRef.blk fb) (fo + 3), out := .ref (BRef.blk e.ob) (oo + 3), len := l.len - 3 },
278        e.heap (cpyG sel 3 fo oo A) msg m) := by
279  have hsz : ∀ (B : Array UInt8) i x, (sel (B.set! i x)).size = (sel B).size := hs.size
280  unfold body3
281  rw [bind_ok (copy1_src hs A msg m l fo oo hf ho (by omega) (by omega))]
282  rw [bind_ok (copy1_src hs (A.set! oo ((sel A).getD fo 0)) msg m _ (fo + 1) (oo + 1) rfl rfl
283    (by rw [hsz]; omega) (by simp; omega))]
284  rw [bind_ok (copy1_src hs (A.set! oo ((sel A).getD fo 0) |>.set! (oo + 1) ((sel (A.set! oo ((sel A).getD fo 0))).getD (fo + 1) 0))
285    msg m _ (fo + 2) (oo + 2) rfl rfl (by rw [hsz, hsz]; omega) (by simp; omega))]
286  simp only [pure_app, cpyG]
287
288
289/-- `while (len > 2) { three copies; len -= 3; }` followed by `tailIf`. -/
290def tailW (l : L) : M L := do
291  let l ← cwhile cond3 body3 l
292  tailIf l
293
294/-- `do { three copies; len -= 3; } while (len > 2);` followed by `tailIf`. -/
295def tailD (l : L) : M L := do
296  let l ← cdoWhile body3 cond3 l
297  tailIf l
298
299theorem tailIf_run {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) (A : Array UInt8) (msg : BPtr)
300    (m : UInt32) (l : L) (r fo oo : Nat) (hr : l.len.toNat = r) (hr2 : r < 3)
301    (hf : l.from_ = .ref (BRef.blk fb) fo) (ho : l.out = .ref (BRef.blk e.ob) oo)
302    (hfo : fo + r ≤ (sel A).size) (hoo : oo + r ≤ A.size) :
303    tailIf l (e.heap A msg m) = .ok ({ l with from_ := .ref (BRef.blk fb) (fo + r), out := .ref (BRef.blk e.ob) (oo + r) },
304      e.heap (cpyG sel r fo oo A) msg m) := by
305  have hsz : ∀ (B : Array UInt8) i x, (sel (B.set! i x)).size = (sel B).size := hs.size
306  unfold tailIf
307  by_cases h0 : r = 0
308  · subst h0
309    have hl : l.len = 0 := by apply UInt32.toNat_inj.mp; simpa using hr
310    simp only [hl, bne_self_eq_false, Bool.false_eq_true, ite_false, pure_app, cpyG, Nat.add_zero]
311    rcases l with ⟨i1, o1, h1, b1, he1, op1, ln1, d1, f1, br1, al1, ad1⟩
312    simp only at hf ho hl ⊢
313    subst hf ho hl
314    rfl
315  · have hne : (l.len != 0) = true := by
316      simp only [bne_iff_ne, ne_eq]
317      intro h; rw [h] at hr; simp at hr; omega
318    simp only [hne, ite_true]
319    rw [bind_ok (copy1_src hs A msg m l fo oo hf ho (by omega) (by omega))]
320    dsimp only
321    by_cases h1 : r = 1
322    · subst h1
323      have hgt : ¬ (l.len > 1) := by
324        intro h; have := (UInt32.lt_iff_toNat_lt.mp h); simp at this; omega
325      simp only [hgt, ite_false, pure_app, cpyG]
326    · have h2 : r = 2 := by omega
327      subst h2
328      have hgt : (l.len > 1) := by
329        apply UInt32.lt_iff_toNat_lt.mpr; simp; omega
330      simp only [hgt, ite_true]
331      rw [bind_ok (copy1_src hs (A.set! oo ((sel A).getD fo 0)) msg m _ (fo + 1) (oo + 1) rfl rfl
332        (by rw [hsz]; omega) (by simp; omega))]
333      simp only [pure_app, cpyG]
334
335
336theorem len_gt2_iff (x : UInt32) : decide (x > 2) = decide (2 < x.toNat) := by
337  by_cases h : x > 2
338  · have := UInt32.lt_iff_toNat_lt.mp h; simp at this; simp [h]; omega
339  · have : ¬ (2 < x.toNat) := fun h2 => h (UInt32.lt_iff_toNat_lt.mpr (by simpa using h2))
340    simp [h, this]
341
342theorem len_sub3 {x : UInt32} (h : 3 ≤ x.toNat) : (x - 3).toNat = x.toNat - 3 :=
343  u32_toNat_sub (by simpa using h)
344
345theorem Src.sel_cpyG {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) :
346    ∀ k fo oo (A : Array UInt8), (sel (cpyG sel k fo oo A)).size = (sel A).size
347  | 0, _, _, _ => rfl
348  | k + 1, fo, oo, A => by
349    simp only [cpyG]
350    rw [Src.sel_cpyG hs k, hs.size]
351
352theorem cond3_true {l : L} (h : 3 ≤ l.len.toNat) (hp : Heap) : cond3 l hp = .ok ((true, l), hp) := by
353  have hd : decide (l.len > 2) = true := by rw [len_gt2_iff]; simp; omega
354  simp [cond3, hd]
355
356theorem cond3_false {l : L} (h : l.len.toNat ≤ 2) (hp : Heap) : cond3 l hp = .ok ((false, l), hp) := by
357  have hd : decide (l.len > 2) = false := by rw [len_gt2_iff]; simp; omega
358  simp [cond3, hd]
359
360theorem whileTail_go {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) (msg : BPtr) (m : UInt32) :
361    ∀ q (l : L) fo oo (A : Array UInt8) fu r, r < 3 → l.len.toNat = 3 * q + r → q ≤ fu →
362      l.from_ = .ref (BRef.blk fb) fo → l.out = .ref (BRef.blk e.ob) oo →
363      fo + 3 * q ≤ (sel A).size → oo + 3 * q ≤ A.size →
364      cwhile.go cond3 body3 (fu + 1) l (e.heap A msg m) =
365        .ok ({ l with from_ := .ref (BRef.blk fb) (fo + 3 * q), out := .ref (BRef.blk e.ob) (oo + 3 * q),
366                      len := UInt32.ofNat r }, e.heap (cpyG sel (3 * q) fo oo A) msg m) := by
367  intro q
368  induction q with
369  | zero =>
370    intro l fo oo A fu r hr hl _ hf ho _ _
371    rw [cwhile.go, bind_ok (cond3_false (by omega) _)]
372    simp only [Bool.false_eq_true, ite_false, pure_app, cpyG, Nat.mul_zero, Nat.add_zero]
373    have hlen : l.len = UInt32.ofNat r := by
374      apply UInt32.toNat_inj.mp; simp [UInt32.toNat_ofNat, Nat.mod_eq_of_lt (show r < 2 ^ 32 by omega)]; omega
375    rcases l with ⟨i1, o1, h1, b1, he1, op1, ln1, d1, f1, br1, al1, ad1⟩
376    simp only at hf ho hlen ⊢
377    subst hf ho hlen
378    rfl
379  | succ q ih =>
380    intro l fo oo A fu r hr hl hfu hf ho hfo hoo
381    obtain ⟨fu, rfl⟩ : ∃ fu', fu = fu' + 1 := ⟨fu - 1, by omega⟩
382    rw [cwhile.go, bind_ok (cond3_true (by omega) _)]
383    simp only [ite_true]
384    rw [bind_ok (copy3_src hs A msg m l fo oo hf ho (by omega) (by omega))]
385    have hl3 : (l.len - 3).toNat = 3 * q + r := by rw [len_sub3 (by omega)]; omega
386    rw [ih { l with from_ := Ptr.ref (BRef.blk fb) (fo + 3), out := Ptr.ref (BRef.blk e.ob) (oo + 3), len := l.len - 3 }
387      (fo + 3) (oo + 3) (cpyG sel 3 fo oo A) fu r hr hl3 (by omega) rfl rfl
388      (by rw [hs.sel_cpyG]; omega) (by rw [cpyG_size]; omega)]
389    have e1 : fo + 3 + 3 * q = fo + 3 * (q + 1) := by omega
390    have e2 : oo + 3 + 3 * q = oo + 3 * (q + 1) := by omega
391    have e3 : cpyG sel (3 * q) (fo + 3) (oo + 3) (cpyG sel 3 fo oo A) = cpyG sel (3 * (q + 1)) fo oo A := by
392      rw [show 3 * (q + 1) = 3 + 3 * q by omega, cpyG_add]
393    rw [e1, e2, e3]
394
395
396theorem tailW_run {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) (A : Array UInt8) (msg : BPtr)
397    (m : UInt32) (l : L) (n fo oo : Nat) (hn : l.len.toNat = n) (hf : l.from_ = .ref (BRef.blk fb) fo)
398    (ho : l.out = .ref (BRef.blk e.ob) oo) (hfo : fo + n ≤ (sel A).size) (hoo : oo + n ≤ A.size) :
399    tailW l (e.heap A msg m) = .ok ({ l with from_ := .ref (BRef.blk fb) (fo + n), out := .ref (BRef.blk e.ob) (oo + n), len := UInt32.ofNat (n % 3) }, e.heap (cpyG sel n fo oo A) msg m) := by
400  have hlt := UInt32.toNat_lt l.len
401  have key := whileTail_go hs msg m (n / 3) l fo oo A (fuel - 1) (n % 3) (by omega) (by omega) (by unfold fuel; omega)
402    hf ho (by omega) (by omega)
403  rw [fuel_pred] at key
404  unfold tailW cwhile
405  rw [bind_ok key]
406  have hr : (UInt32.ofNat (n % 3)).toNat = n % 3 := by simp [UInt32.toNat_ofNat]; omega
407  have hn3 : n = 3 * (n / 3) + n % 3 := by omega
408  rw [tailIf_run hs (cpyG sel (3 * (n / 3)) fo oo A) msg m _ (n % 3) (fo + 3 * (n / 3)) (oo + 3 * (n / 3)) hr
409    (by omega) rfl rfl (by rw [hs.sel_cpyG]; omega) (by rw [cpyG_size]; omega)]
410  have e1 : fo + 3 * (n / 3) + n % 3 = fo + n := by omega
411  have e2 : oo + 3 * (n / 3) + n % 3 = oo + n := by omega
412  have e3 : cpyG sel (n % 3) (fo + 3 * (n / 3)) (oo + 3 * (n / 3)) (cpyG sel (3 * (n / 3)) fo oo A) = cpyG sel n fo oo A := by
413    conv => rhs; rw [hn3, cpyG_add]
414  rw [e1, e2, e3]
415
416theorem doTail_go {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) (msg : BPtr) (m : UInt32) :
417    ∀ q (l : L) fo oo (A : Array UInt8) fu r, r < 3 → l.len.toNat = 3 * (q + 1) + r → q ≤ fu →
418      l.from_ = .ref (BRef.blk fb) fo → l.out = .ref (BRef.blk e.ob) oo →
419      fo + 3 * (q + 1) ≤ (sel A).size → oo + 3 * (q + 1) ≤ A.size →
420      cdoWhile.go body3 cond3 (fu + 1) l (e.heap A msg m) =
421        .ok ({ l with from_ := .ref (BRef.blk fb) (fo + 3 * (q + 1)), out := .ref (BRef.blk e.ob) (oo + 3 * (q + 1)), len := UInt32.ofNat r }, e.heap (cpyG sel (3 * (q + 1)) fo oo A) msg m) := by
422  intro q
423  induction q with
424  | zero =>
425    intro l fo oo A fu r hr hl _ hf ho hfo hoo
426    rw [cdoWhile.go, bind_ok (copy3_src hs A msg m l fo oo hf ho (by omega) (by omega))]
427    have hl3 : (l.len - 3).toNat = r := by rw [len_sub3 (by omega)]; omega
428    rw [bind_ok (cond3_false (l := { l with from_ := Ptr.ref (BRef.blk fb) (fo + 3), out := Ptr.ref (BRef.blk e.ob) (oo + 3), len := l.len - 3 }) (by simp; omega) _)]
429    simp only [Bool.false_eq_true, ite_false, pure_app, cpyG]
430    have hlen : l.len - 3 = UInt32.ofNat r := by
431      apply UInt32.toNat_inj.mp; simp [UInt32.toNat_ofNat, Nat.mod_eq_of_lt (show r < 2 ^ 32 by omega)]; omega
432    simp [hlen]
433  | succ q ih =>
434    intro l fo oo A fu r hr hl hfu hf ho hfo hoo
435    obtain ⟨fu, rfl⟩ : ∃ fu', fu = fu' + 1 := ⟨fu - 1, by omega⟩
436    rw [cdoWhile.go, bind_ok (copy3_src hs A msg m l fo oo hf ho (by omega) (by omega))]
437    have hl3 : (l.len - 3).toNat = 3 * (q + 1) + r := by rw [len_sub3 (by omega)]; omega
438    rw [bind_ok (cond3_true (l := { l with from_ := Ptr.ref (BRef.blk fb) (fo + 3), out := Ptr.ref (BRef.blk e.ob) (oo + 3), len := l.len - 3 }) (by simp; omega) _)]
439    simp only [ite_true]
440    rw [ih { l with from_ := Ptr.ref (BRef.blk fb) (fo + 3), out := Ptr.ref (BRef.blk e.ob) (oo + 3), len := l.len - 3 }
441      (fo + 3) (oo + 3) (cpyG sel 3 fo oo A) fu r hr hl3 (by omega) rfl rfl
442      (by rw [hs.sel_cpyG]; omega) (by rw [cpyG_size]; omega)]
443    have e1 : fo + 3 + 3 * (q + 1) = fo + 3 * (q + 1 + 1) := by omega
444    have e2 : oo + 3 + 3 * (q + 1) = oo + 3 * (q + 1 + 1) := by omega
445    have e3 : cpyG sel (3 * (q + 1)) (fo + 3) (oo + 3) (cpyG sel 3 fo oo A) = cpyG sel (3 * (q + 1 + 1)) fo oo A := by
446      rw [show 3 * (q + 1 + 1) = 3 + 3 * (q + 1) by omega, cpyG_add]
447    rw [e1, e2, e3]
448
449theorem tailD_run {fb : Nat} {sel : Array UInt8 → Array UInt8} (hs : Src e fb sel) (A : Array UInt8) (msg : BPtr)
450    (m : UInt32) (l : L) (n fo oo : Nat) (hn : l.len.toNat = n) (h3 : 3 ≤ n) (hf : l.from_ = .ref (BRef.blk fb) fo)
451    (ho : l.out = .ref (BRef.blk e.ob) oo) (hfo : fo + n ≤ (sel A).size) (hoo : oo + n ≤ A.size) :
452    tailD l (e.heap A msg m) = .ok ({ l with from_ := .ref (BRef.blk fb) (fo + n), out := .ref (BRef.blk e.ob) (oo + n), len := UInt32.ofNat (n % 3) }, e.heap (cpyG sel n fo oo A) msg m) := by
453  have hlt := UInt32.toNat_lt l.len
454  obtain ⟨q, hq⟩ : ∃ q, n / 3 = q + 1 := ⟨n / 3 - 1, by omega⟩
455  have key := doTail_go hs msg m q l fo oo A (fuel - 1) (n % 3) (by omega) (by omega) (by unfold fuel; omega)
456    hf ho (by omega) (by omega)
457  rw [fuel_pred] at key
458  unfold tailD cdoWhile
459  rw [bind_ok key]
460  have hr : (UInt32.ofNat (n % 3)).toNat = n % 3 := by simp [UInt32.toNat_ofNat]; omega
461  have hn3 : n = 3 * (q + 1) + n % 3 := by omega
462  rw [tailIf_run hs (cpyG sel (3 * (q + 1)) fo oo A) msg m _ (n % 3) (fo + 3 * (q + 1)) (oo + 3 * (q + 1)) hr
463    (by omega) rfl rfl (by rw [hs.sel_cpyG]; omega) (by rw [cpyG_size]; omega)]
464  have e1 : fo + 3 * (q + 1) + n % 3 = fo + n := by omega
465  have e2 : oo + 3 * (q + 1) + n % 3 = oo + n := by omega
466  have e3 : cpyG sel (n % 3) (fo + 3 * (q + 1)) (oo + 3 * (q + 1)) (cpyG sel (3 * (q + 1)) fo oo A) = cpyG sel n fo oo A := by
467    conv => rhs; rw [hn3, cpyG_add]
468  rw [e1, e2, e3]
469
470end Zlib.Inffast.Proofs
ZLIB × LEAN

全局目录

当前位置inffast.c.copy.lean