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

inffast.c.pass.lean

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

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

1import ZlibF.Proof.«inffast.c.dist»
2
3namespace Zlib.Inffast.Proofs
4open C Zlib.Inffast Zlib.Inffast.Spec ZlibF.Spec
5
6variable {e : Env} {c : Ctx}
7
8set_option maxHeartbeats 1000000 in
9/-- One pass of the block at `dodist:`. Either it follows a link (`againD`), or it ends the distance block. -/
10theorem dodist_pass (hc : CtxOK e c) (A : Array UInt8) (msg : BPtr) (m : UInt32) (l : L) (i o d k : Nat)
11    (hls : LS e l i o) (hA : e.o0 + e.sm0.avail_out.toNat ≤ A.size) (ho : o + 258 ≤ e.o0 + e.sm0.avail_out.toNat)
12    (hAb : A.size < 2 ^ 63) (hbroke : l.broke = false) (hlen : 3 ≤ l.len.toNat ∧ l.len.toNat ≤ 258)
13    (hhere : l.here = .ref e.rd k) (hk : k < e.DCA.size)
14    (hEb : (e.DCA.getD k default).bits.toNat ≤ l.bits.toNat)
15    (hEd : (e.DCA.getD k default).bits.toNat + d ≤ 15)
16    (hcl : DistClass e (e.DCA.getD k default))
17    (hpull : i + 2 ≤ e.i0 + e.sm0.avail_in.toNat ∨ (i + 1 ≤ e.i0 + e.sm0.avail_in.toNat ∧ 20 ≤ l.bits.toNat + d)) :
18    Wp (dodist c l) (e.heap A msg m) (fun l' h' =>
19      (l'.againD = true ∧ l'.broke = false ∧ h' = e.heap A msg m ∧
20        ((e.DCA.getD k default).op &&& 16 = 0 ∧ (e.DCA.getD k default).op &&& 64 = 0) ∧
21        ∃ j, j < 2 ^ (e.DCA.getD k default).op.toNat ∧
22          j = (l.hold.toNat / 2 ^ (e.DCA.getD k default).bits.toNat) % 2 ^ (e.DCA.getD k default).op.toNat ∧
23          l'.here = .ref e.rd (e.od + (e.DCA.getD k default).val.toNat + j) ∧ LS e l' i o ∧
24          Sg e l'.hold.toNat l'.bits.toNat i = (Sg e l.hold.toNat l.bits.toNat i).drop (e.DCA.getD k default).bits.toNat ∧
25          l'.bits.toNat = l.bits.toNat - (e.DCA.getD k default).bits.toNat ∧
26          l'.len = l.len ∧ l'.out = l.out ∧ l'.dist = l.dist ∧ l'.againL = l.againL) ∨
27      DistEnd e A msg m ((Sg e l.hold.toNat l.bits.toNat i).drop (e.DCA.getD k default).bits.toNat) i o l.len.toNat
28        (e.DCA.getD k default) l' h') := by
29  have hkE : e.DCA[k]'hk = e.DCA.getD k default := by simp [Array.getD_eq_getD_getElem?, hk]
30  have hld : OkOn (e.heap A msg m) (Ptr.load l.here) (e.DCA.getD k default) := by
31    rw [hhere, ← hkE]; exact Ptr.load_ok (e.heap_cget_DCA A msg m) hk
32  have hEb64 : (((e.DCA.getD k default).bits.toUInt32).toUInt64).toNat = (e.DCA.getD k default).bits.toNat := by
33    simp [toNat32]
34  have hEbn : ((e.DCA.getD k default).bits.toUInt32).toNat = (e.DCA.getD k default).bits.toNat := toNat32 _
35  have hls1 : LS e (dropL l (e.DCA.getD k default).bits.toUInt32) i o :=
36    hls.dropL _ (by omega) (by omega)
37  have hEb64 : (((e.DCA.getD k default).bits.toUInt32).toUInt64).toNat = (e.DCA.getD k default).bits.toNat := by
38    simp [toNat32]
39  have hEbn : ((e.DCA.getD k default).bits.toUInt32).toNat = (e.DCA.getD k default).bits.toNat := toNat32 _
40  have hls1 : LS e (dropL l (e.DCA.getD k default).bits.toUInt32) i o :=
41    hls.dropL _ (by omega) (by omega)
42  have hsg1 := Sg_dropL (e := e) l (e.DCA.getD k default).bits.toUInt32 i (by omega) (by omega)
43  have hlow64 : ∀ x : UInt32, x.toNat < 32 → (l.hold >>> (e.DCA.getD k default).bits.toUInt32.toUInt64).toNat = l.hold.toNat / 2 ^ (e.DCA.getD k default).bits.toNat := by
44    intro x _; rw [u64_shr (by omega), hEbn]
45  unfold dodist
46  dsimp only
47  refine Wp.bindO hld ?_
48  refine Wp.bindO (shr64_ok (x := l.hold) (by omega)) ?_
49  refine Wp.bindO hld ?_
50  generalize e.DCA.getD k default = E at *
51  have hsg1' : Sg e (l.hold >>> E.bits.toUInt32.toUInt64).toNat (l.bits - E.bits.toUInt32).toNat i =
52      (Sg e l.hold.toNat l.bits.toNat i).drop E.bits.toNat := by
53    have := hsg1; rw [hEbn] at this; exact this
54  by_cases hb16 : (E.op.toUInt32 &&& 16 != 0) = true
55  · simp only [hb16, ite_true]
56    have hb16' : E.op &&& 16 ≠ 0 := by
57      rw [mask16] at hb16; simpa using hb16
58    have hbase : E.op &&& 16 ≠ 0 ∧ ((E.op &&& 15).toNat ≤ 13) ∧ 1 ≤ E.val.toNat := by
59      rcases hcl with h | h | h
60      · exact h
61      · exact absurd h.1 hb16'
62      · exact absurd h.1 hb16'
63    refine Wp.bindO hld ?_
64    have hv : E.val.toUInt32.toNat = E.val.toNat := by simp
65    have hv2 := UInt16.toNat_lt E.val
66    have hbn := dropL_bits l E.bits.toUInt32 (by omega)
67    have key := (dodistBase_wp hc A msg m
68      { in_ := l.in_, out := l.out, hold := l.hold >>> E.bits.toUInt32.toUInt64, bits := l.bits - E.bits.toUInt32,
69        here := l.here, op := E.op.toUInt32 &&& 15, len := l.len, dist := E.val.toUInt32, from_ := l.from_,
70        broke := l.broke, againL := l.againL, againD := false } i o (LS.congr hls1 rfl rfl rfl rfl) hA ho hAb
71      (by rw [mask15]; exact hbase.2.1) (by rw [hv]; exact hbase.2.2) (by rw [hv]; omega) hlen hbroke
72      (by rcases hpull with h | h
73          · exact Or.inl h
74          · refine Or.inr ⟨h.1, ?_⟩
75            show 5 ≤ (l.bits - E.bits.toUInt32).toNat
76            have hbn' : (l.bits - E.bits.toUInt32).toNat = l.bits.toNat - E.bits.toNat := by
77              rw [u32_toNat_sub (by omega), hEbn]
78            omega))
79    unfold dodistBase distCont at key
80    dsimp only at key
81    refine Wp.mono key ?_
82    intro l' h' hq
83    obtain ⟨i', xv, rest, hi1, hi2, hr, hagD, hres⟩ := hq
84    refine Or.inr ⟨fun hl => hb16' hl.1, hagD, ?_⟩
85    rcases hres with ⟨hb, hls', hsg, hh⟩ | ⟨hb, hls', p, hh⟩
86    · refine Or.inl ⟨i', xv, rest, hi1, hi2, ?_, hb, hls', hsg, ?_⟩
87      · have : (E.op.toUInt32 &&& 15).toNat = (E.op &&& 15).toNat := mask15 _
88        rw [this] at hr
89        rw [hsg1'] at hr
90        exact hr
91      · rw [hh]; simp only [hv]
92    · exact Or.inr ⟨i', p, hi1, hi2, hb, hls', hh⟩
93  · -- not a base: a link or an invalid code
94    have hb16' : E.op &&& 16 = 0 := by
95      rw [mask16] at hb16; simpa using hb16
96    by_cases hb64 : (E.op.toUInt32 &&& 64 == 0) = true
97    · simp only [hb16, hb64, ite_true, ite_false, Bool.false_eq_true]
98      have hb64' : E.op &&& 64 = 0 := by
99        rw [mask64] at hb64; simpa using hb64
100      have hlink : 1 ≤ E.op.toNat ∧ E.op.toNat ≤ 15 ∧ e.od + E.val.toNat + 2 ^ E.op.toNat ≤ e.DCA.size := by
101        rcases hcl with h | h | h
102        · exact absurd hb16' h.1
103        · exact ⟨h.2.2.1, h.2.2.2.1, h.2.2.2.2⟩
104        · exact absurd hb64' h.2
105      refine Wp.bindO hld ?_
106      have hdc : c.dcode = .ref e.rd e.od := by rw [hc.dcode]; exact e.hdc
107      have hop32 : E.op.toUInt32.toNat < 32 := by rw [toNat32]; omega
108      refine Wp.bindO (x := Ptr.ref e.rd (e.od + E.val.toNat)) ?_ ?_
109      · rw [hdc]
110        exact Ptr.add_nat_ok (e.heap_cget_DCA A msg m) (Nat.le_trans (Nat.le_add_right _ _) hlink.2.2)
111      refine Wp.bindO (shl32_ok hop32) ?_
112      have hlow := hold_low64 (x := l.hold >>> E.bits.toUInt32.toUInt64) (k := E.op.toUInt32) hop32
113      have hjlt : (l.hold >>> E.bits.toUInt32.toUInt64).toNat % 2 ^ E.op.toUInt32.toNat < 2 ^ E.op.toNat := by
114        rw [toNat32]; exact Nat.mod_lt _ (Nat.pow_pos (by omega))
115      generalize hjd : (l.hold >>> E.bits.toUInt32.toUInt64).toNat % 2 ^ E.op.toUInt32.toNat = j at hlow hjlt
116      refine Wp.bindO (x := Ptr.ref e.rd (e.od + E.val.toNat + j)) ?_ ?_
117      · rw [hlow]
118        exact Ptr.add_nat_ok (h := e.heap A msg m) (r := e.rd) (a := e.DCA) (off := e.od + E.val.toNat)
119          (n := j) (e.heap_cget_DCA A msg m) (by have := hlink.2.2; omega)
120      refine Wp.pure' (Or.inl ⟨rfl, hbroke, rfl, ⟨hb16', hb64'⟩, j, hjlt, by rw [← hjd, u64_shr (by omega), hEbn, toNat32],  rfl, LS.congr hls1 rfl rfl rfl rfl, hsg1',
121        (by show (l.bits - E.bits.toUInt32).toNat = _; rw [u32_toNat_sub (by omega), hEbn]), rfl, rfl, rfl, rfl⟩)
122    · simp only [hb16, hb64, ite_false, Bool.false_eq_true]
123      obtain ⟨ip, hip⟩ := badData_run hc A msg m "invalid distance code" (by decide +kernel)
124      refine Wp.bindE hip (Wp.pure' (Or.inr ⟨fun hl => (by rw [mask64] at hb64; simpa using hb64 : E.op &&& 64 ≠ 0) hl.2, rfl, Or.inr ⟨i, Ptr.ref (BRef.str ip) 0, Nat.le_refl _, by omega, rfl,
125        LS.congr hls1 rfl rfl rfl rfl, rfl⟩⟩))
126
127end Zlib.Inffast.Proofs
ZLIB × LEAN

全局目录

当前位置inffast.c.pass.lean