← Session 27 — ii′-5c/5d: Davenport disc + FE-reflection bounds
thinking (33112 chars)
Committed. Now §4 (A) + §5 (G) — the rest of 5e-ii. Let me write them carefully. I'll append to LiDigammaLeft.lean.
First (A): `norm_digamma_le_of_dist_nat`. I need the digamma recurrence with pole-avoidance hypothesis (not im ≠ 0). Let me write a local `digamma_add_natCast'` with the weaker hypothesis, then (A), then (G).
Let me draft the code carefully, watching all the gotchas banked this session:
- Ascribe Nat.cast_nonneg haves.
- Swapped add_le_add convention.
- Pin nat-sub casts.
- No bare `set` for things I need to compute with; explicit haves.
- h3 : 0 ≤ ... needs explicit positivity ascriptions.
**digamma_add_natCast'**:
```
/-- The digamma recurrence over a natural shift, pole-avoidance form. -/
theorem digamma_add_natCast' {w : ℂ} (hw : ∀ k : ℕ, w ≠ -(k : ℂ)) (n : ℕ) :
Complex.digamma (w + n) = Complex.digamma w + ∑ j ∈ Finset.range n, (w + (j : ℂ))⁻¹ := by
induction n with
| zero => simp
| succ k ih =>
have hne : ∀ m : ℕ, w + (k : ℂ) ≠ -(m : ℂ) := by
intro m h
-- w + ↑k = −↑m ⟹ w = −(↑k+↑m) = −↑(k+m): excluded by hw (k+m)
have h2 : w = -((k : ℂ) + (m : ℂ)) := by
have := h -- w + ↑k = −↑m
-- w = −↑m − ↑k = −(↑k + ↑m)
have h3 := congrArg (· - (k : ℂ)) h -- w = −↑m − ↑k
rwa [add_sub_cancel_right] at h3 -- h3 : w = −↑m − ↑k — wait: (w + ↑k) − ↑k = w: add_sub_cancel_right ✓: h3 : w = -↑m - ↑k
-- need −↑m − ↑k = −(↑k + ↑m): ring
...
```
Hmm: h : w + ↑k = −↑m: so w = −↑m − ↑k = −(↑k + ↑m) — and ↑(k+m) = ↑k + ↑m (Nat.cast_add): hw (k+m) : w ≠ −↑(k+m): apply hw (k+m); convert h2-form: goal w = −↑(k+m): from h: w = −↑m − ↑k = −(↑m + ↑k) = −(↑k + ↑m) = −↑(k+m):
```
intro m h
apply hw (k + m)
-- goal: w = -↑(k+m)
have h3 : w = -(m : ℂ) - (k : ℂ) := by
have h4 := congrArg (· - (k : ℂ)) h
rwa [add_sub_cancel_right] at h4
rw [h3]
push_cast
ring
```
✓ (goal after rw [h3]: −↑m − ↑k = −↑(k+m): push_cast: ↑(k+m) → ↑k+↑m: −↑m − ↑k = −(↑k+↑m): ring ✓).
Then:
```
| succ k ih =>
have hne : ∀ m : ℕ, w + (k : ℂ) ≠ -(m : ℂ) := ...
have h1 := Complex.digamma_apply_add_one (w + (k : ℂ)) hne
rw [show w + ((k + 1 : ℕ) : ℂ) = (w + (k : ℂ)) + 1 by push_cast; ring, h1, ih,
Finset.sum_range_succ]
ring
```
(mirror of LiReflect's digamma_add_natCast which compiled ✓).
**(A) norm_digamma_le_of_dist_nat**:
```
/-- **The near-axis left-plane digamma bound (A)**: for re w ≤ 2 and
dist(w, −ℕ) ≥ c > 0, ‖ψ(w)‖ ≤ (46 + 2/c) + 23·log(2+‖w‖). Recurrence
to re ∈ [3,4] + §3's sum bound + §2/StirlingVert at the landing point. -/
theorem norm_digamma_le_of_dist_nat {c : ℝ} (hc : 0 < c) {w : ℂ}
(hwre : w.re ≤ 2) (hdist : ∀ m : ℕ, c ≤ ‖w + (m : ℂ)‖) :
‖Complex.digamma w‖ ≤ (46 + 2 / c) + 23 * Real.log (2 + ‖w‖) := by
-- pole-avoidance from the dist condition
have hpoles : ∀ k : ℕ, w ≠ -(k : ℂ) := by
intro k h
have h1 := hdist k
rw [h] at h1 -- ‖−↑k + ↑k‖ = 0:
simp at h1 -- ‖0‖ ≥ c contra c > 0: h1 : c ≤ ‖(-↑k : ℂ) + ↑k‖ = ‖0‖ = 0: simp: (−↑k + ↑k) = 0: neg_add_cancel? simp knows: add_neg... hmm (−(↑k) + ↑k) = 0: `neg_add_cancel`? or add_neg... let me: rw [h] at h1; simp at h1 — simp should reduce ‖(−(↑k:ℂ) + ↑k)‖ to 0 via add_neg_cancel? the form: (−↑k : ℂ) + ↑k: `neg_add_cancel`? that's −a + a = 0 ✓ simp lemma? neg_add_cancel is simp? maybe not. Robust: rw [h] at h1; rw [show (-(k:ℂ)) + (k:ℂ) = 0 by ring] at h1; simp at h1 (norm_zero) then linarith [hc, h1]?? h1 : c ≤ 0: linarith [hc, h1] ✓.
-- the shift count
set m := ⌈2 - w.re⌉₊ + 1 with hm_def
have hm_ge : (2 : ℝ) - w.re ≤ (m : ℝ) := by
have h := Nat.le_ceil (2 - w.re)
have h2 : ((⌈2 - w.re⌉₊ : ℕ) : ℝ) ≤ (m : ℝ) := by rw [hm_def]; push_cast; linarith [h]?? hmm: m = ⌈⌉₊ + 1: (↑m : ℝ) = ↑⌈⌉₊ + 1 ≥ (2−re w) + 1 ≥ (2−re w) ✓:
rw [hm_def]
push_cast
linarith [h]
have hm_lt : (m : ℝ) < (2 - w.re) + 2 := by
have h := Nat.ceil_lt_add_one (show (0:ℝ) ≤ 2 - w.re by linarith [hwre]) -- ⌈2−re⌉₊ < (2−re) + 1
have h2 : ((⌈2 - w.re⌉₊ : ℕ) : ℝ) < (2 - w.re) + 1 := by exact_mod_cast h
rw [hm_def]
push_cast
linarith [h2]
set v := w + (m : ℂ) with hv_def
have hvre : 3 ≤ v.re ∧ v.re < 4 := by
have h1 : v.re = w.re + (m : ℝ) := by
rw [hv_def]; simp [Complex.add_re, Complex.natCast_re]
rw [h1]
constructor <;> linarith [hm_ge, hm_lt]
have hvim : v.im = w.im := by
rw [hv_def]; simp [Complex.add_im, Complex.natCast_im]
-- j₀ for the sum bound
set j₀ := ⌈-w.re⌉₊ with hj₀
have hj₀m : j₀ + 1 ≤ m := by
-- j₀ ≤ max(0, −re w + 1): cases
by_cases hre : 0 ≤ -w.re
· have h1 : ((⌈-w.re⌉₊ : ℕ) : ℝ) < -w.re + 1 := by
have h := Nat.ceil_lt_add_one hre
exact_mod_cast h
-- j₀ + 1 ≤ m ⟸ −re w + 2 ≤ m: from hm_ge: m ≥ 2 − re w: hmm need m ≥ −re w + 2: hm_ge gives (m:ℝ) ≥ 2 − w.re: so (m:ℝ) ≥ 2 − re w and j₀ < −re w + 1 ⟹ j₀ + 1 < −re w + 2 ≤ m + 0·...: (j₀:ℝ) + 1 < (−re w + 1) + 1 = 2 − re w ≤ ↑m: so (j₀:ℝ)+1 < ↑m ⟹ j₀+1 ≤ m (nats):
have h2 : (j₀ : ℝ) + 1 < (m : ℝ) := by linarith [h1, hm_ge]
have h3 : j₀ + 1 < m := by -- hmm strict in ℕ from real strict: exact_mod_cast h2 gives (↑(j₀+1):ℝ) < ↑m: j₀+1 < m:
have h4 : ((j₀ + 1 : ℕ) : ℝ) < (m : ℝ) := by
rw [Nat.cast_add_one]
linarith [h2]
exact_mod_cast h4
omega
· push Not at hre -- −re w < 0: j₀ = 0
have h1 : ⌈-w.re⌉₊ = 0 := Nat.ceil_eq_zero.mpr (by linarith [hre])
rw [hj₀, h1] -- goal 0 + 1 ≤ m: m ≥ 1: from hm_def: m = ⌈⌉₊ + 1 ≥ 1 ✓
omega
-- the recurrence
have hshift : Complex.digamma v = Complex.digamma w + ∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹ := by
rw [hv_def]
exact digamma_add_natCast' hpoles m
-- the sum bound
have hsum := digamma_recip_sum_le hc hdist hj₀m -- hmm digamma_recip_sum_le's hm : ⌈−w.re⌉₊ + 1 ≤ m: hj₀m is about j₀ = the set-var: the set j₀ := ⌈−re w⌉₊ makes them the same term ✓ — digamma_recip_sum_le hc hdist (hm := hj₀m)? the {m} implicit: our m ✓ the hypothesis (hm : ⌈-w.re⌉₊ + 1 ≤ m): hj₀m : j₀ + 1 ≤ m with j₀ set-to ⌈−re w⌉₊ — the set makes j₀ a local def equal to it; the expected form ⌈-w.re⌉₊ + 1 ≤ m vs hj₀m's j₀ + 1 ≤ m — defeq via hj₀ — hmm `set` replaces occurrences in goal/context but the NEW application digamma_recip_sum_le hc hdist hj₀m — the argument hj₀m : j₀ + 1 ≤ m must match the expected ⌈-w.re⌉₊ + 1 ≤ m — j₀ is a let-bound local def: isDefEq j₀ =?= ⌈-w.re⌉₊ — `set` introduces j₀ as a local definition with hj₀ : j₀ = ⌈-w.re⌉₊ — the defeq unfolds the local def? `set` introduces an fvar with a let-value — isDefEq CAN unfold it ✓ generally works. If not: rw [hj₀] at hj₀m first.
-- the landing-zone bound
have hLZ : ‖Complex.digamma v‖ ≤ 21 * Real.log (2 + ‖v‖) := by
by_cases him : 1 / 2 ≤ |v.im|
· -- StirlingVert
have hst := StirlingVert.digamma_stirling (by linarith [hvre.1] : (0:ℝ) < v.re) him
-- ‖ψ v‖ ≤ 3/(im v)² + ‖log v‖ + 1/(2‖v‖)
have hvnorm3 : 3 ≤ ‖v‖ := by
have h1 := Complex.abs_re_le_norm v
have h2 : |v.re| = v.re := abs_of_nonneg (by linarith [hvre.1])
rw [h2] at h1
linarith [hvre.1, h1]
calc ‖Complex.digamma v‖
= ‖(Complex.digamma v - Complex.log v + (1/2 : ℂ)/v) + Complex.log v - (1/2 : ℂ)/v‖ := by
congr 1; ring
_ ≤ ‖Complex.digamma v - Complex.log v + (1/2 : ℂ)/v‖ + ‖Complex.log v‖ + ‖(1/2 : ℂ)/v‖ := by
refine (norm_sub_le _ _).trans ?_
exact add_le_add_left (norm_add_le _ _) _ -- swapped convention
_ ≤ 3 / v.im^2 + (Real.log ‖v‖ + Real.pi) + (1/2)/‖v‖ := by
gcongr ... — explicit:
refine add_le_add (add_le_add hst (norm_log_le_of_one_le (by linarith [hvnorm3]))) ?_
rw [norm_div]
have h12 : ‖(1/2 : ℂ)‖ = 1/2 := by ... (the pattern from LiReflect)
rw [h12]
_ ≤ 21 * Real.log (2 + ‖v‖) := by
-- 3/(im v)² ≤ 3/(1/4) = 12; (1/2)/‖v‖ ≤ 1/6; log‖v‖ + π ≤ log(2+‖v‖) + 4: total ≤ log(2+‖v‖) + 16.2 + ... ≤ 21 log(2+‖v‖) ⟸ log(2+‖v‖) ≥ log 5 > 1.6 (‖v‖ ≥ 3): 21·1.6 = 33.6 ≥ 1·log + 16.2 ⟸ log(2+‖v‖)·20 ≥ 16.2 ⟸ 20·1.6 = 32 ≥ 16.2 ✓:
have him2 : v.im^2 ≥ 1/4 := by
calc v.im^2 = |v.im|^2 := by rw [sq_abs]
_ ≥ (1/2)^2 := pow_le_pow_left₀ (abs_nonneg _) him _
_ = 1/4 := by norm_num
have hlogv : Real.log ‖v‖ ≤ Real.log (2 + ‖v‖) := Real.log_le_log (by linarith [hvnorm3]) (by linarith)
have hlog5 : (0 : ℝ) ≤ Real.log (2 + ‖v‖) := Real.log_nonneg (by linarith [hvnorm3])
have hpi : Real.pi ≤ 4 := Real.pi_lt_d2.le.trans (by norm_num)
have h1 : 3 / v.im^2 ≤ 12 := by
rw [div_le_iff₀ (by linarith [him2] : (0:ℝ) < v.im^2)]
nlinarith [him2]
have h2 : (1/2 : ℝ) / ‖v‖ ≤ 1 := by
rw [div_le_one (by linarith [hvnorm3] : (0:ℝ) < ‖v‖)]
linarith [hvnorm3]
nlinarith [h1, h2, hlogv, hpi, hlog5, Real.log_nonneg (show (1:ℝ) ≤ 2 + ‖v‖ by linarith [hvnorm3])]
· -- |im v| < 1/2: the §2 bound
push Not at him
rw [hvim] at him -- |w.im| < 1/2 ≤ 5: §2 needs |im v| ≤ 5: |v.im| < 1/2 ⟹ ≤ 5 ✓ via him: but (B) is stated with |w.im| ≤ 5 for the ARGUMENT v: |v.im| ≤ 5: from him : |v.im| < 1/2: .le.trans:
exact (norm_digamma_le_of_two_le_re (by linarith [hvre.1] : (2:ℝ) ≤ v.re)
(by linarith [him.le] : |v.im| ≤ 5)).trans (by
-- 20 log(2+‖v‖) ≤ 21 log(2+‖v‖): log ≥ 0 (‖v‖ ≥ 3)
have h : (0:ℝ) ≤ Real.log (2 + ‖v‖) := Real.log_nonneg (by linarith [hvre.1, Complex.abs_re_le_norm v] : (1:ℝ) ≤ 2 + ‖v‖)
nlinarith [h])
-- assemble
have hwnorm : ‖w‖ ≥ ... — need: m ≤ 4 + ‖w‖ and ‖v‖ ≤ 2‖w‖ + 4 and the log inequalities:
have hwm : (m : ℝ) ≤ 4 + ‖w‖ := by
have h1 : (m : ℝ) ≤ (2 - w.re) + 2 := hm_lt.le
have h2 : -w.re ≤ ‖w‖ := by
have h3 := Complex.abs_re_le_norm w
rwa [abs_le] at h3?? no: −re w ≤ |re w| ≤ ‖w‖: neg_le_abs (w.re) : −w.re ≤ |w.re| ✓ then trans with abs_re_le_norm:
exact (neg_le_abs w.re).trans (Complex.abs_re_le_norm w)
linarith [h1, h2]
have hvnorm : ‖v‖ ≤ 2 * ‖w‖ + 4 := by
rw [hv_def]
calc ‖w + (m : ℂ)‖ ≤ ‖w‖ + ‖(m : ℂ)‖ := norm_add_le _ _
_ = ‖w‖ + (m : ℝ) := by rw [RCLike.norm_natCast]
_ ≤ 2 * ‖w‖ + 4 := by linarith [hwm]
have hlogv_le : Real.log (2 + ‖v‖) ≤ 2 + Real.log (2 + ‖w‖) := by
-- 2 + ‖v‖ ≤ 6 + 2‖w‖ = 2(3+‖w‖) ≤ 4(2+‖w‖): log ≤ log 4 + log(2+‖w‖) ≤ 2 + log(2+‖w‖)
have h1 : 2 + ‖v‖ ≤ 4 * (2 + ‖w‖) := by linarith [hvnorm]
have h2 : Real.log (2 + ‖v‖) ≤ Real.log (4 * (2 + ‖w‖)) :=
Real.log_le_log (by linarith [hvre.1, ...] : (0:ℝ) < 2 + ‖v‖) h1
have h3 : Real.log (4 * (2 + ‖w‖)) = Real.log 4 + Real.log (2 + ‖w‖) :=
Real.log_mul (by norm_num : (4:ℝ) ≠ 0) (by positivity : (2 + ‖w‖) ≠ 0)
have h4 : Real.log 4 ≤ 2 := by
have h5 := Real.log_two_lt_d9.le -- log 2 < 0.6932
have h6 : Real.log 4 = 2 * Real.log 2 := by
rw [show (4:ℝ) = 2^2 by norm_num, Real.log_pow]; push_cast; ring
linarith [h5, h6]
linarith [h2, h3, h4]
-- the sum bound form: 2/c + 2 + 2 log m ≤ ...: log m ≤ log(4+‖w‖) ≤ 1 + log(2+‖w‖):
have hlogm : Real.log m ≤ 1 + Real.log (2 + ‖w‖) := by
have h1 : (m : ℝ) ≤ 2 * (2 + ‖w‖) := by linarith [hwm]
have h2 : Real.log (m : ℝ) ≤ Real.log (2 * (2 + ‖w‖)) := by
apply Real.log_le_log (by positivity : (0:ℝ) < (m:ℝ)) h1
-- hmm 0 < ↑m: m ≥ 1 ✓: by exact_mod_cast (by omega : 1 ≤ m)?? m = ⌈⌉₊+1 ≥ 1: have hm1 : 1 ≤ m := by omega (from hm_def) — add
have h3 : Real.log (2 * (2 + ‖w‖)) = Real.log 2 + Real.log (2 + ‖w‖) :=
Real.log_mul (by norm_num) (by positivity)
have h4 : Real.log 2 ≤ 1 := Real.log_two_lt_d9.le.trans (by norm_num)
linarith [h2, h3, h4]
-- final assembly
rw [← hshift] -- hmm: goal ‖ψ w‖: hshift : ψ v = ψ w + Σ: ‖ψ w‖ = ‖ψ v − Σ‖ ≤ ‖ψ v‖ + ‖Σ‖:
-- directly: ‖ψ w‖ = ‖ψ v − Σ‖: from hshift: ψ w = ψ v − Σ (by linear_combination hshift):
have hpsi : Complex.digamma w = Complex.digamma v - ∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹ := by
linear_combination hshift
rw [hpsi]
calc ‖Complex.digamma v - ∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹‖
≤ ‖Complex.digamma v‖ + ‖∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹‖ := norm_sub_le _ _
_ ≤ 21 * Real.log (2 + ‖v‖) + (2 / c + 2 + 2 * Real.log m) := add_le_add hLZ (hsum.trans' ...)...
```
wait hsum : ∑ ‖(w+↑j)⁻¹‖ ≤ 2/c + 2 + 2 log m (the SUM of norms) and I need ‖Σ (w+↑j)⁻¹‖ ≤ Σ ‖·‖⁻¹ (norm_sum_le) then hsum: ‖Σ‖ ≤ Σ‖·‖ ≤ 2/c+2+2 log m: `norm_sum_le` : ‖∑ i ∈ s, f i‖ ≤ ∑ i ∈ s, ‖f i‖ ✓ exists. So:
```
_ ≤ 21 * Real.log (2 + ‖v‖) + (2 / c + 2 + 2 * Real.log m) :=
add_le_add hLZ ((norm_sum_le _ _).trans hsum)
_ ≤ (46 + 2/c) + 23 * Real.log (2 + ‖w‖) := by
-- 21(2 + L) + 2/c + 2 + 2(1 + L) = 42 + 21L + 2/c + 2 + 2 + 2L = 46 + 2/c + 23L ✓ with L := log(2+‖w‖):
nlinarith [hlogv_le, hlogm, hc] -- hlogv_le : log(2+‖v‖) ≤ 2 + L; hlogm : log m ≤ 1 + L: 21·log(2+‖v‖) ≤ 21(2+L) (mul by 21: monotone — nlinarith with the product 21·(...) linear ✓); 2 log m ≤ 2(1+L) ✓: total: 21(2+L) + 2/c + 2 + 2(1+L) = 46 + 2/c + 23L ✓ nlinarith closes (linear in the atoms log(2+‖v‖), log m, L, 1/c... 2/c as atom: the target has 2/c as written — the LHS has 2/c too ✓ same atom)
```
The nlinarith: LHS = 21·log(2+‖v‖) + (2/c + 2 + 2·log m): with log(2+‖v‖) ≤ 2 + L and log m ≤ 1 + L: nlinarith multiplies hypotheses by constants? nlinarith can use them linearly: 21·log(2+‖v‖) ≤ 21·(2+L) requires multiplying hlogv_le by 21 — nlinarith/linarith: linarith does that ✓ (constant multiples of hypotheses) — but the RHS target: 46 + 2/c + 23·L — with 2/c written differently? The LHS's (2/c) and the goal's (2 / c) — same ✓. So linarith [hlogv_le, hlogm] should close: 21·logv + 2/c + 2 + 2·logm ≤ 21(2+L) + 2/c + 2 + 2(1+L) = 46 + 2/c + 23L ✓ linear ✓.
Hmm — one concern: `hsum` is about ∑ j ∈ range m, ‖(w + ↑j)‖⁻¹ — wait digamma_recip_sum_le's conclusion: ∑ j ∈ Finset.range m, ‖(w + (j : ℂ))⁻¹‖ ≤ 2/c + 2 + 2·log ↑m ✓ matches.
And the hypothesis alignment: digamma_recip_sum_le {c} (hc) {w} (hdist) {m} (hm : ⌈-w.re⌉₊ + 1 ≤ m) — my call: digamma_recip_sum_le hc hdist (show ⌈-w.re⌉₊ + 1 ≤ m from ...) — the j₀ set-var issue: give the proof directly with the ceil form (not the j₀ alias) — since j₀ is `set`, the term ⌈-w.re⌉₊ displays as j₀ in context but the term I pass must have the literal form... `set j₀ := ⌈-w.re⌉₊ with hj₀` REPLACES occurrences — so writing ⌈-w.re⌉₊ in a new term still elaborates to the same underlying expression; set's fold is only presentational for the GOAL at set-time. The expected type of the (hm :) argument is ⌈-w.re⌉₊ + 1 ≤ m — passing hj₀m : j₀ + 1 ≤ m where j₀ is the set-local-def: isDefEq j₀ ≡ ⌈-w.re⌉₊ — set introduces j₀ as a new free variable with hj₀ : j₀ = ⌈-w.re⌉₊ — NOT a let-value (set uses `fvar` + the equation). So isDefEq does NOT automatically unfold j₀!! I need `rw [hj₀] at hj₀m` to convert hj₀m to the literal form, OR write the have with the literal form. Hmm — actually `set` in Lean4 Mathlib: introduces a local variable j₀ and hj₀ : j₀ = value, and replaces occurrences — the new fvar j₀ is opaque (not defeq to the value). So I DO need rw [hj₀] at hj₀m to get ⌈-w.re⌉₊ + 1 ≤ m for passing. Note: after rw [hj₀] at hj₀m, hj₀m : ⌈-w.re⌉₊ + 1 ≤ m ✓. Fine — handle.
Wait — actually in §3's proof I used `set j₀ := ⌈-w.re⌉₊ with hj₀` and then `recip_norm_le_right hdist hj₀ ...` passing hj₀ : j₀ = ⌈-w.re⌉₊ as the (hj₀ : j₀ = ⌈-w.re⌉₊) argument — matching ✓ (the lemma's hj₀ hypothesis is the equation j₀ = ⌈⌉₊ ✓). And it compiled ✓. OK so the same patterns work.
Now (G). Let me draft it fully:
```
/-! ## 5. The general logDeriv ΓR identity (G) -/
/-- logDeriv of a finite product of linear factors. -/
theorem logDeriv_prod_range_linear {s : ℂ} (hs : s.im ≠ 0) (m : ℕ) :
logDeriv (fun z : ℂ => ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s
= ∑ j ∈ Finset.range m, (1 / 2 : ℂ) / (s / 2 + (j : ℂ)) := by
induction m with
| zero => simp [logDeriv_const] -- ∏ ∅ = 1: logDeriv (fun _ => 1) = 0; ∑ ∅ = 0: simp [logDeriv_const]: logDeriv_const : logDeriv (fun _ => a) = 0 — after simp the goal 0 = 0?? the goal: logDeriv (fun z => ∏ j ∈ range 0, ...) s = ∑ range 0 ...: range_zero, prod_empty, sum_empty: logDeriv (fun z => 1) s = 0: logDeriv_const is about logDeriv (fun _ => a) as a FUNCTION... its statement: logDeriv_const (a) : logDeriv (fun _ => a) = 0 — pointwise free: logDeriv (fun z => 1) s = (logDeriv (fun _ => 1)) s = 0 s = 0 — via congr_fun (logDeriv_const 1) s? simp [logDeriv_const] should handle ✓
| succ k ih =>
have hne : ∀ j : ℕ, (s / 2 + (j : ℂ)) ≠ 0 := by
intro j h
apply hs
have h2 : (s / 2).im = 0 := by
have h3 := congrArg Complex.im (congrArg (· / 2)?...)...
```
hmm — s/2 + ↑j = 0 ⟹ (s/2).im = 0 (since ↑j real): (s/2 + ↑j).im = (s/2).im + 0 = 0 ⟹ (s/2).im = 0 ⟹ s.im/2 = 0 ⟹ s.im = 0 contra hs:
```
have hne : ∀ j : ℕ, (s / 2 + (j : ℂ)) ≠ 0 := by
intro j h
apply hs
have h1 : (s / 2 + (j : ℂ)).im = 0 := by rw [h]; simp
have h2 : (s / 2 + (j : ℂ)).im = s.im / 2 := by
simp [Complex.add_im, Complex.natCast_im, Complex.div_ofNat_im]
rw [h2] at h1
linarith [h1] -- s.im/2 = 0 ⟹ s.im = 0 ✓ linarith: goal s.im = 0: from s.im/2 = 0: linarith closes (linear: s.im = 2·(s.im/2) = 0) ✓
have hprod_ne : (∏ j ∈ Finset.range k, (s / 2 + (j : ℂ))) ≠ 0 :=
Finset.prod_ne_zero_iff.mpr fun j _ => hne j
rw [Finset.prod_range_succ]
rw [logDeriv_mul s (Finset.prod_ne_zero_iff.mpr fun j _ => hne j) (hne k)
(by fun_prop : DifferentiableAt ℂ (fun z : ℂ => ∏ j ∈ Finset.range k, (z / 2 + (j : ℂ))) s)
(by fun_prop : DifferentiableAt ℂ (fun z : ℂ => z / 2 + (k : ℂ)) s)]
rw [ih]
-- logDeriv (fun z => z/2 + ↑k) s = (1/2)/(s/2+↑k):
have hfac : logDeriv (fun z : ℂ => z / 2 + (k : ℂ)) s = (1 / 2 : ℂ) / (s / 2 + (k : ℂ)) := by
have h1 : HasDerivAt (fun z : ℂ => z / 2 + (k : ℂ)) (1 / 2 : ℂ) s := by
have h2 := (hasDerivAt_id' s).div_const (2 : ℂ)
exact h2.add_const (k : ℂ)
rw [logDeriv_apply, h1.deriv]
rw [hfac, Finset.sum_range_succ]
```
Hmm — logDeriv_mul : logDeriv (fun z => f z * g z) x = logDeriv f x + logDeriv g x — after rw [Finset.prod_range_succ] the goal's function is fun z => (∏ j ∈ range k, (z/2+↑j)) * (z/2+↑k) — logDeriv_mul's pattern fun z => f z * g z ✓ matches. Then the goal: logDeriv (∏-part) s + logDeriv (single) s = ∑ range (k+1): rw [ih] (the IH : logDeriv (∏-part) s = ∑ range k): goal ∑ range k + logDeriv single = ∑ range (k+1): rw [hfac, Finset.sum_range_succ]: RHS becomes ∑ range k + (1/2)/(s/2+↑k): both sides: [∑ range k] + (1/2)/(s/2+↑k) = [∑ range k] + (1/2)/(s/2+↑k) ✓ rfl-close by rw ✓.
The fun_prop for the product differentiability: DifferentiableAt ℂ (fun z => ∏ j ∈ range k, (z/2+↑j)) s — fun_prop should handle (div, add, const, prod) ✓.
Then (G) main:
```
/-- **(G) the general logDeriv ΓR identity**: for im s ≠ 0,
logDeriv ΓR s = −(log π)/2 + ½ψ(s/2) — the m-fold shift landing re > 0
(`gamma_mul_prod` + `digamma_add_natCast` + 5d's EventuallyEq machinery). -/
theorem logDeriv_Gammaℝ_eq {s : ℂ} (hs : s.im ≠ 0) :
logDeriv Complex.Gammaℝ s
= -(Real.log Real.pi : ℂ) / 2 + (1 / 2 : ℂ) * Complex.digamma (s / 2) := by
set m := ⌈max 0 (-(s.re / 2))⌉₊ + 1 with hm_def
have hmge : (2 : ℝ) ≤ s.re + 2 * (m : ℝ) := by
have h1 : max 0 (-(s.re / 2)) ≤ (⌈max 0 (-(s.re / 2))⌉₊ : ℝ) := Nat.le_ceil _
have h2 : -(s.re / 2) ≤ max 0 (-(s.re / 2)) := le_max_right _ _
rw [hm_def]
push_cast
linarith [h1, h2]
have hres2 : 0 < (s + 2 * (m : ℂ)).re := by
have h1 : (s + 2 * (m : ℂ)).re = s.re + 2 * (m : ℝ) := by
simp [Complex.add_re, Complex.mul_re, Complex.natCast_re] -- (2*↑m : ℂ).re = 2*↑m: mul_re: 2.re*↑m.re − 2.im*↑m.im: numerals simp ✓
rw [h1]
linarith [hmge]
-- the pointwise identity on U = {im ≠ 0}
have hU : IsOpen {z : ℂ | z.im ≠ 0} := isOpen_ne_fun Complex.continuous_im continuous_const
have hpt : ∀ z : ℂ, z.im ≠ 0 → Complex.Gammaℝ z
= (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))
/ ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ)) := by
intro z hz
-- recurrence side conditions
have hside : ∀ k : ℕ, k < m → z / 2 ≠ -(k : ℂ) := by
intro k _ h
apply hz
have h1 : (z / 2).im = 0 := by
have h2 := congrArg Complex.im h
-- h2 : (z/2).im = (−↑k).im = 0
simpa [Complex.neg_im, Complex.natCast_im] using h2
simp [Complex.div_ofNat_im] at h1 -- (z/2).im = z.im/2: h1 : z.im/2 = 0
linarith [h1]
have hrec := gamma_mul_prod (z / 2) m hside
-- ΓR(z+2m) = π^{−(z+2m)/2} Γ((z+2m)/2) = π^{−z/2}·π^{−m}·Γ(z/2+m)
have hG1 : Complex.Gammaℝ (z + 2 * (m : ℂ))
= (Real.pi : ℂ) ^ (-(z + 2 * (m : ℂ)) / 2) * Complex.Gamma ((z + 2 * (m : ℂ)) / 2) :=
Complex.Gammaℝ_def _
have harg1 : (-(z + 2 * (m : ℂ)) / 2) = -z / 2 - (m : ℂ) := by ring
have harg2 : (z + 2 * (m : ℂ)) / 2 = z / 2 + (m : ℂ) := by ring
-- the cpow split: π^{−z/2 − m} = π^{−z/2} · π^{−m}
have hpi : (Real.pi : ℂ) ^ (-z / 2 - (m : ℂ))
= (Real.pi : ℂ) ^ (-z / 2) * (((Real.pi ^ m : ℝ)) : ℂ)⁻¹ := by
have hlog : Complex.log (Real.pi : ℂ) = (Real.log Real.pi : ℂ) :=
(Complex.ofReal_log Real.pi_nonneg).symm
rw [Complex.cpow_def_of_ne_zero (by exact_mod_cast Real.pi_ne_zero : (Real.pi : ℂ) ≠ 0) _,
Complex.cpow_def_of_ne_zero (by exact_mod_cast Real.pi_ne_zero : (Real.pi : ℂ) ≠ 0) _,
hlog]
have harg : (Real.log Real.pi : ℂ) * (-z / 2 - (m : ℂ))
= (Real.log Real.pi : ℂ) * (-z / 2) + ((-(m : ℝ) * Real.log Real.pi : ℝ) : ℂ) := by
push_cast
ring
rw [harg, Complex.exp_add, ← Complex.ofReal_exp]
-- Real.exp (−m·log π) = (π^m)⁻¹
have hexp : Real.exp (-(m : ℝ) * Real.log Real.pi) = (Real.pi ^ m)⁻¹ := by
have h1 : (-(m : ℝ) * Real.log Real.pi) = Real.log ((Real.pi ^ m)⁻¹) := by
rw [Real.log_inv, Real.log_pow]
ring
rw [h1, Real.exp_log (by positivity)]
rw [hexp]
push_cast
ring -- hmm: ↑(π^m)⁻¹ vs ((↑π)^m)⁻¹: ofReal_pow/inv: push_cast normalizes ↑(π^m) → (↑π)^m: the goal: exp-form LHS already rewritten... let me end with: rw [hexp]; push_cast; ring — the goal at that point: (π:ℂ)^(−z/2) * ↑(Real.exp (−m log π)) = (π:ℂ)^(−z/2) * ↑((π^m)⁻¹): after rw [hexp]: RHS ↑( (π^m)⁻¹ ): push_cast turns it into ((↑π)^m)⁻¹: goal: π^(−z/2) * ((↑π)^m)⁻¹ = π^(−z/2) * ((↑π)^m)⁻¹ ✓ rfl — ring closes or the rw [hexp] + push_cast leaves syntactically equal sides ⟹ ring closes.
-- assemble ΓR(z+2m) = (π^m)⁻¹ · ΓR z · ∏
have hG2 : Complex.Gammaℝ (z + 2 * (m : ℂ))
= (((Real.pi ^ m : ℝ) : ℂ))⁻¹ * Complex.Gammaℝ z * ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ)) := by
rw [hG1, harg1, harg2, hpi, Complex.Gammaℝ_def]
-- ΓR z = π^{−z/2} Γ(z/2): unfold; hrec : Γ(z/2) * ∏ = Γ(z/2 + ↑m): substitute Γ(z/2+m) = Γ(z/2)·∏ via hrec.symm? hrec : Γ(z/2) * ∏ j ∈ range m, (z/2+↑j) = Γ(z/2+↑m): I need Γ(z/2+↑m) = Γ(z/2)·∏: rw [← hrec]:
rw [← hrec]
ring
-- solve for ΓR z: ΓR z = π^m · ΓR(z+2m) / ∏
have hPne : (∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) ≠ 0 := by
apply Finset.prod_ne_zero_iff.mpr
intro j _
intro h
apply hz
have h1 : (z / 2 + (j : ℂ)).im = 0 := by rw [h]; simp
simp [Complex.add_im, Complex.natCast_im, Complex.div_ofNat_im] at h1
linarith [h1]
have hπne : ((Real.pi ^ m : ℝ) : ℂ) ≠ 0 := by
exact_mod_cast pow_ne_zero m Real.pi_ne_zero
rw [eq_div_iff hPne] -- goal: ΓR z * ∏ = π^m * ΓR(z+2m)
rw [hG2]
-- goal: ΓR z * ∏ = π^m * ((π^m)⁻¹ * ΓR z * ∏) = (π^m · (π^m)⁻¹)·(ΓR z · ∏) = ΓR z * ∏:
rw [show (Real.pi : ℂ) ^ (m : ℂ) = ((Real.pi ^ m : ℝ) : ℂ) by
rw [Complex.cpow_natCast]; push_cast; ring] -- hmm (π:ℂ)^(↑m) = ↑(π^m): cpow_natCast: x^(↑n) = x^n: then ↑(π^m) vs (π:ℂ)^m: push_cast: ↑(π^m) → (↑π)^m ✓ then ring? the two sides (↑π)^m and ↑(π^m): push_cast turns ↑(π^m) into (↑π)^m: rfl — hmm the show's LHS is cpow (π:ℂ)^(↑m:ℂ) and RHS ↑(π^m): rw [Complex.cpow_natCast] turns LHS into (π:ℂ)^m: goal (π:ℂ)^m = ↑(π^m): push_cast turns RHS ↑(π^m) into (↑π)^m: rfl — so `by rw [Complex.cpow_natCast]; push_cast` — push_cast closes rfl? if both sides identical after push_cast — push_cast closes rfl goals? no — need exact/rfl: `by rw [Complex.cpow_natCast]; exact_mod_cast rfl`?? — simplest: by rw [Complex.cpow_natCast, ← Complex.ofReal_pow]?? — ↑(π^m) = (↑π)^m via `Complex.ofReal_pow : ↑(x^n) = (↑x)^n` ✓: so: rw [Complex.cpow_natCast, Complex.ofReal_pow] — LHS (π:ℂ)^m, RHS ↑(π^m) → after rw [Complex.ofReal_pow] the RHS becomes (↑π)^m: both sides (π:ℂ)^m ✓ rfl-close ✓. Wait direction: ofReal_pow : (↑(x^n) : ℂ) = (↑x)^n: rw [← Complex.ofReal_pow] turns (↑π)^m into ↑(π^m)... my show's equation: (π:ℂ)^(m:ℂ) = ↑(π^m): rw [Complex.cpow_natCast] : LHS (π:ℂ)^(↑m) → (π:ℂ)^m: goal (π:ℂ)^m = ↑(π^m): rw [← Complex.ofReal_pow]: pattern (↑x)^n: LHS (π:ℂ)^m matches with x := π: → ↑(π^m): goal ↑(π^m) = ↑(π^m) rfl ✓. So the show: by rw [Complex.cpow_natCast, ← Complex.ofReal_pow].
-- now the goal: ΓR z * ∏ = ↑(π^m) * ((↑(π^m))⁻¹ * ΓR z * ∏): ring with the inverse: need ↑(π^m) ≠ 0 to cancel — field_simp [hπne]? or:
field_simp [hπne]
ring
```
Hmm — the field_simp after rw [hG2] and the show-rewrite: goal ΓR z * ∏ = ↑(π^m) * ((↑(π^m))⁻¹ * ΓR z * ∏): field_simp [hπne] clears the ⁻¹: ΓR z * ∏ * ↑(π^m) = ↑(π^m) * (ΓR z * ∏)·... then ring ✓. Or simply: the RHS = ↑(π^m) * (↑(π^m))⁻¹ * ΓR z * ∏ = ΓR z * ∏ by mul_inv_cancel₀ + one_mul: rw [mul_inv_cancel₀ hπne]?? the form: ↑(π^m) * (↑(π^m))⁻¹ * (ΓR z * ∏) — assoc: (↑(π^m) * (↑(π^m))⁻¹) * (ΓR z * ∏): mul_inv_cancel₀ : a * a⁻¹ = 1 for a ≠ 0 ✓: the exact form in the goal: ↑(π^m) * ((↑(π^m))⁻¹ * ΓR z * ∏) — regroup: = (↑(π^m) * (↑(π^m))⁻¹) * (ΓR z * ∏) [ring_nf? no — just: `field_simp [hπne]` then `ring` — iterate at build.
Then:
```
-- the EventuallyEq and the logDeriv computation
have hEv : Complex.Gammaℝ =ᶠ[𝓝 s]
fun z => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))
/ ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ)) := by
filter_upwards [hU.mem_nhds hs] with z hz using hpt z hz
have hG2m : Complex.Gammaℝ (s + 2 * (m : ℂ)) ≠ 0 :=
Complex.Gammaℝ_ne_zero_of_re_pos hres2
have hPne : (∏ j ∈ Finset.range m, (s / 2 + (j : ℂ))) ≠ 0 := ... (as hpt's)
have hdG2m : DifferentiableAt ℂ (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s := by
apply DifferentiableAt.comp
· exact differentiableAt_Gammaℝ (by linarith [hres2] : (0:ℝ) < (s + 2*(m:ℂ)).re)??
```
hmm — Zeta23's `differentiableAt_Gammaℝ (hs : 0 < s.re)` (WeilEF/XiLogDeriv.lean) — namespace? from the earlier grep: `Zeta23/WeilEF/XiLogDeriv.lean:30:lemma differentiableAt_Gammaℝ {s : ℂ} (hs : 0 < s.re)` — namespace inside? probably Zeta23 or plain. With open Zeta23 — accessible as differentiableAt_Gammaℝ (if root Zeta23 namespace) — but my LiReflect has differentiableAt_Gammaℝ_of_im_ne_zero' (mine). For re > 0: use whichever — check the namespace at build: try `Zeta23.differentiableAt_Gammaℝ` — hmm the file XiLogDeriv.lean's namespace: let me just use my own via... my ' variant needs im ≠ 0: (s+2m).im = s.im ≠ 0 ✓: differentiableAt_Gammaℝ_of_im_ne_zero' (by simp [Complex.add_im, ...]; exact hs). Then comp with (z + 2↑m): differentiableAt_id.add_const ✓:
```
have hdG2m : DifferentiableAt ℂ (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s := by
have h1 : (s + 2 * (m : ℂ)).im ≠ 0 := by
have h2 : (s + 2 * (m : ℂ)).im = s.im := by
simp [Complex.add_im, Complex.mul_im, Complex.natCast_im]
rw [h2]; exact hs
exact (differentiableAt_Gammaℝ_of_im_ne_zero' h1).comp s (differentiableAt_id.add_const _)
have hdP : DifferentiableAt ℂ (fun z : ℂ => ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s := by fun_prop
-- the big computation
rw [logDeriv_congr hEv]
have hstep1 : logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))
/ ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s
= logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))) s
- logDeriv (fun z : ℂ => ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s :=
logDeriv_div s (mul_ne_zero (pow_ne_zero _ (by exact_mod_cast Real.pi_ne_zero)) hG2m) hPne
((differentiableAt_const _).mul hdG2m) hdP
have hstep2 : logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))) s
= logDeriv Complex.Gammaℝ (s + 2 * (m : ℂ)) := by
rw [logDeriv_const_mul s _ (pow_ne_zero _ (by exact_mod_cast Real.pi_ne_zero : (Real.pi:ℂ) ≠ 0))]
-- logDeriv (ΓR(·+2m)) s = logDeriv ΓR (s+2m): the comp deriv
have hder : deriv (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s
= deriv Complex.Gammaℝ (s + 2 * (m : ℂ)) := by
have h1 := ((differentiableAt_Gammaℝ_of_im_ne_zero' (by
have h2 : (s + 2 * (m : ℂ)).im = s.im := by
simp [Complex.add_im, Complex.mul_im, Complex.natCast_im]
rw [h2]; exact hs)).hasDerivAt).comp s ((hasDerivAt_id' s).add_const (2 * (m : ℂ)))
have h2 : deriv (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s
= deriv Complex.Gammaℝ (s + 2 * (m : ℂ)) * 1 := h1.deriv
rwa [mul_one] at h2
simp only [logDeriv_apply, hder]
rw [hstep1, hstep2]
-- logDeriv ΓR (s+2m) via logDeriv_Gammaℝ (re > 0)
have hev : logDeriv Complex.Gammaℝ (s + 2 * (m : ℂ))
= -(Real.log Real.pi : ℂ) / 2 + (1 / 2 : ℂ) * Complex.digamma ((s + 2 * (m : ℂ)) / 2) :=
RvM.logDeriv_Gammaℝ hres2
rw [hev]
-- the product logDeriv + the digamma shift + the cancellation
rw [logDeriv_prod_range_linear hs m]
-- (s+2m)/2 = s/2 + m; ψ(s/2 + m) = ψ(s/2) + Σ (s/2+↑j)⁻¹ (digamma_add_natCast, im(s/2) ≠ 0)
have him2 : (s / 2).im ≠ 0 := by
simp [Complex.div_ofNat_im]
exact hs -- hmm: (s/2).im = s.im/2 ≠ 0 from hs: after simp [div_ofNat_im]: goal s.im/2 ≠ 0: div_ne_zero hs two_ne_zero ✓: `simp [Complex.div_ofNat_im]; exact div_ne_zero hs (by norm_num)`? careful — let me: have : (s/2).im = s.im / 2 := by simp [Complex.div_ofNat_im]; rw [this]; exact div_ne_zero hs (by norm_num : (2:ℝ) ≠ 0)
have harg : (s + 2 * (m : ℂ)) / 2 = s / 2 + (m : ℂ) := by ring
rw [harg, digamma_add_natCast him2 m]
-- the per-term form: (1/2)/(s/2+↑j) = (1/2)·(s/2+↑j)⁻¹: and Σ forms match
have hterm : ∀ j : ℕ, (1 / 2 : ℂ) / (s / 2 + (j : ℂ)) = (1 / 2 : ℂ) * (s / 2 + (j : ℂ))⁻¹ := by
intro j
rw [div_eq_mul_inv]
rw [Finset.sum_congr rfl (fun j _ => hterm j)] -- hmm rw with sum_congr result — messy; better:
-- the goal: −(logπ)/2 + ½(ψ(s/2) + Σ (s/2+↑j)⁻¹) − Σ (1/2)/(s/2+↑j) = −(logπ)/2 + ½ψ(s/2)
-- via: Σ (1/2)/(s/2+↑j) = ½ Σ (s/2+↑j)⁻¹: Finset.mul_sum
have hsumform : ∑ j ∈ Finset.range m, (1 / 2 : ℂ) / (s / 2 + (j : ℂ))
= (1 / 2 : ℂ) * ∑ j ∈ Finset.range m, (s / 2 + (j : ℂ))⁻¹ := by
rw [Finset.mul_sum]
apply Finset.sum_congr rfl
intro j _
rw [div_eq_mul_inv]
rw [hsumform]
ring
```
Check the algebra at the end: goal: −(logπ)/2 + ½·(ψ + Σ) − ½·Σ = −(logπ)/2 + ½·ψ — after rw [digamma_add_natCast him2 m]: the term digamma (s/2 + ↑m) becomes ψ(s/2) + Σ: the goal: −(logπ)/2 + ½·(ψ(s/2) + Σ (s/2+↑j)⁻¹) − Σ (1/2)/(s/2+↑j) = −(logπ)/2 + ½ ψ(s/2): rw [hsumform]: the Σ (1/2)/(...) → ½·Σ(...)⁻¹: goal: −(logπ)/2 + ½·(ψ + Σ) − ½·Σ = ...: ring ✓ (treating ψ, Σ as atoms: ½ψ + ½Σ − ½Σ = ½ψ ✓).
One concern: `digamma_add_natCast him2 m` — its statement (LiReflect): digamma (w + ↑n) = digamma w + Σ j ∈ range n, (w + ↑j)⁻¹ with w := s/2: after rw [harg] the term is digamma (s/2 + ↑m) ✓ rw [digamma_add_natCast him2 m] rewrites it to digamma (s/2) + Σ ✓.
Also hpt's form vs the EventuallyEq: the function fun z => (π:ℂ)^(↑m) * ΓR(z+2↑m) / ∏ ... — and hpt gives ΓR z = that ✓ filter_upwards ✓.
The hstep1's logDeriv_div: signature logDeriv_div (x) (hf : f x ≠ 0) (hg : g x ≠ 0) (hdf) (hdg) ✓.
`pow_ne_zero _ (hpi : (π:ℂ) ≠ 0) : (π:ℂ)^? ≠ 0` — the exponent (m:ℂ) is a cpow! pow_ne_zero is for ^ℕ — for the cpow (π:ℂ)^(↑m:ℂ): need cpow-ne-zero: `Complex.cpow_ne_zero`? hmm — for x ≠ 0: x^y ≠ 0 — hmm is that even true for cpow? x^y = exp(y log x) ≠ 0 (exp_ne_zero) for x ≠ 0 ✓: `Complex.cpow_ne_zero (hx : x ≠ 0) (y : ℂ) : x ^ y ≠ 0`? hmm — not sure of the name; maybe `Complex.cpow_ne_zero_iff`? Let me handle: (π:ℂ)^(↑m) = (π:ℂ)^m via cpow_natCast (hmm — is the exponent ↑m : ℂ with m : ℕ — cpow_natCast : x ^ (↑n : ℂ) = x ^ n — so rewrite to (π:ℂ)^m then pow_ne_zero m ✓. To avoid the issue entirely: define the EventuallyEq's constant factor as ((Real.pi ^ m : ℝ) : ℂ) (the real-pow cast) instead of the cpow — from the show-rewrite: (π:ℂ)^(↑m:ℂ) = ↑(π^m) — use ↑(π^m) EVERYWHERE (cleaner: no cpow-ne-zero issues: ↑(π^m) ≠ 0 via cast of pow_ne_zero ✓). Let me use ((Real.pi ^ m : ℝ) : ℂ) as the constant in hpt/hEv/steps.
OK — I have full drafts. Write §4+§5 as the append now. This is long; let me be careful to paste ONLY Lean. I'll write §4 ((A) + digamma_add_natCast') and §5 (G) in one Edit, then compile-iterate.
Build green, audit clean, committed. Now §4 (A) + §5 (G) — the rest of 5e-ii. Appending them (Lean only this time).
tool: Bash
input
{
"command": "tail -3 /d/Python/Quantum/research/lean/NguyenRH1/NguyenRH1/LiDigammaLeft.lean",
"description": "Check file tail before appending"
}
raw content_json (database row)
[{"type":"thinking","thinking":"Committed. Now §4 (A) + §5 (G) — the rest of 5e-ii. Let me write them carefully. I'll append to LiDigammaLeft.lean.\n\nFirst (A): `norm_digamma_le_of_dist_nat`. I need the digamma recurrence with pole-avoidance hypothesis (not im ≠ 0). Let me write a local `digamma_add_natCast'` with the weaker hypothesis, then (A), then (G).\n\nLet me draft the code carefully, watching all the gotchas banked this session:\n- Ascribe Nat.cast_nonneg haves.\n- Swapped add_le_add convention.\n- Pin nat-sub casts.\n- No bare `set` for things I need to compute with; explicit haves.\n- h3 : 0 ≤ ... needs explicit positivity ascriptions.\n\n**digamma_add_natCast'**: \n```\n/-- The digamma recurrence over a natural shift, pole-avoidance form. -/\ntheorem digamma_add_natCast' {w : ℂ} (hw : ∀ k : ℕ, w ≠ -(k : ℂ)) (n : ℕ) :\n Complex.digamma (w + n) = Complex.digamma w + ∑ j ∈ Finset.range n, (w + (j : ℂ))⁻¹ := by\n induction n with\n | zero => simp\n | succ k ih =>\n have hne : ∀ m : ℕ, w + (k : ℂ) ≠ -(m : ℂ) := by\n intro m h\n -- w + ↑k = −↑m ⟹ w = −(↑k+↑m) = −↑(k+m): excluded by hw (k+m)\n have h2 : w = -((k : ℂ) + (m : ℂ)) := by\n have := h -- w + ↑k = −↑m\n -- w = −↑m − ↑k = −(↑k + ↑m)\n have h3 := congrArg (· - (k : ℂ)) h -- w = −↑m − ↑k\n rwa [add_sub_cancel_right] at h3 -- h3 : w = −↑m − ↑k — wait: (w + ↑k) − ↑k = w: add_sub_cancel_right ✓: h3 : w = -↑m - ↑k\n -- need −↑m − ↑k = −(↑k + ↑m): ring\n ... \n```\nHmm: h : w + ↑k = −↑m: so w = −↑m − ↑k = −(↑k + ↑m) — and ↑(k+m) = ↑k + ↑m (Nat.cast_add): hw (k+m) : w ≠ −↑(k+m): apply hw (k+m); convert h2-form: goal w = −↑(k+m): from h: w = −↑m − ↑k = −(↑m + ↑k) = −(↑k + ↑m) = −↑(k+m): \n```\n intro m h\n apply hw (k + m)\n -- goal: w = -↑(k+m)\n have h3 : w = -(m : ℂ) - (k : ℂ) := by\n have h4 := congrArg (· - (k : ℂ)) h\n rwa [add_sub_cancel_right] at h4\n rw [h3]\n push_cast\n ring\n```\n✓ (goal after rw [h3]: −↑m − ↑k = −↑(k+m): push_cast: ↑(k+m) → ↑k+↑m: −↑m − ↑k = −(↑k+↑m): ring ✓).\n\nThen:\n```\n | succ k ih =>\n have hne : ∀ m : ℕ, w + (k : ℂ) ≠ -(m : ℂ) := ...\n have h1 := Complex.digamma_apply_add_one (w + (k : ℂ)) hne\n rw [show w + ((k + 1 : ℕ) : ℂ) = (w + (k : ℂ)) + 1 by push_cast; ring, h1, ih,\n Finset.sum_range_succ]\n ring\n```\n(mirror of LiReflect's digamma_add_natCast which compiled ✓).\n\n**(A) norm_digamma_le_of_dist_nat**:\n```\n/-- **The near-axis left-plane digamma bound (A)**: for re w ≤ 2 and\ndist(w, −ℕ) ≥ c > 0, ‖ψ(w)‖ ≤ (46 + 2/c) + 23·log(2+‖w‖). Recurrence\nto re ∈ [3,4] + §3's sum bound + §2/StirlingVert at the landing point. -/\ntheorem norm_digamma_le_of_dist_nat {c : ℝ} (hc : 0 < c) {w : ℂ}\n (hwre : w.re ≤ 2) (hdist : ∀ m : ℕ, c ≤ ‖w + (m : ℂ)‖) :\n ‖Complex.digamma w‖ ≤ (46 + 2 / c) + 23 * Real.log (2 + ‖w‖) := by\n -- pole-avoidance from the dist condition\n have hpoles : ∀ k : ℕ, w ≠ -(k : ℂ) := by\n intro k h\n have h1 := hdist k\n rw [h] at h1 -- ‖−↑k + ↑k‖ = 0: \n simp at h1 -- ‖0‖ ≥ c contra c > 0: h1 : c ≤ ‖(-↑k : ℂ) + ↑k‖ = ‖0‖ = 0: simp: (−↑k + ↑k) = 0: neg_add_cancel? simp knows: add_neg... hmm (−(↑k) + ↑k) = 0: `neg_add_cancel`? or add_neg... let me: rw [h] at h1; simp at h1 — simp should reduce ‖(−(↑k:ℂ) + ↑k)‖ to 0 via add_neg_cancel? the form: (−↑k : ℂ) + ↑k: `neg_add_cancel`? that's −a + a = 0 ✓ simp lemma? neg_add_cancel is simp? maybe not. Robust: rw [h] at h1; rw [show (-(k:ℂ)) + (k:ℂ) = 0 by ring] at h1; simp at h1 (norm_zero) then linarith [hc, h1]?? h1 : c ≤ 0: linarith [hc, h1] ✓.\n -- the shift count\n set m := ⌈2 - w.re⌉₊ + 1 with hm_def\n have hm_ge : (2 : ℝ) - w.re ≤ (m : ℝ) := by\n have h := Nat.le_ceil (2 - w.re)\n have h2 : ((⌈2 - w.re⌉₊ : ℕ) : ℝ) ≤ (m : ℝ) := by rw [hm_def]; push_cast; linarith [h]?? hmm: m = ⌈⌉₊ + 1: (↑m : ℝ) = ↑⌈⌉₊ + 1 ≥ (2−re w) + 1 ≥ (2−re w) ✓: \n rw [hm_def]\n push_cast\n linarith [h]\n have hm_lt : (m : ℝ) < (2 - w.re) + 2 := by\n have h := Nat.ceil_lt_add_one (show (0:ℝ) ≤ 2 - w.re by linarith [hwre]) -- ⌈2−re⌉₊ < (2−re) + 1\n have h2 : ((⌈2 - w.re⌉₊ : ℕ) : ℝ) < (2 - w.re) + 1 := by exact_mod_cast h\n rw [hm_def]\n push_cast\n linarith [h2]\n set v := w + (m : ℂ) with hv_def\n have hvre : 3 ≤ v.re ∧ v.re < 4 := by\n have h1 : v.re = w.re + (m : ℝ) := by\n rw [hv_def]; simp [Complex.add_re, Complex.natCast_re]\n rw [h1]\n constructor <;> linarith [hm_ge, hm_lt]\n have hvim : v.im = w.im := by\n rw [hv_def]; simp [Complex.add_im, Complex.natCast_im]\n -- j₀ for the sum bound\n set j₀ := ⌈-w.re⌉₊ with hj₀\n have hj₀m : j₀ + 1 ≤ m := by\n -- j₀ ≤ max(0, −re w + 1): cases\n by_cases hre : 0 ≤ -w.re\n · have h1 : ((⌈-w.re⌉₊ : ℕ) : ℝ) < -w.re + 1 := by\n have h := Nat.ceil_lt_add_one hre\n exact_mod_cast h\n -- j₀ + 1 ≤ m ⟸ −re w + 2 ≤ m: from hm_ge: m ≥ 2 − re w: hmm need m ≥ −re w + 2: hm_ge gives (m:ℝ) ≥ 2 − w.re: so (m:ℝ) ≥ 2 − re w and j₀ < −re w + 1 ⟹ j₀ + 1 < −re w + 2 ≤ m + 0·...: (j₀:ℝ) + 1 < (−re w + 1) + 1 = 2 − re w ≤ ↑m: so (j₀:ℝ)+1 < ↑m ⟹ j₀+1 ≤ m (nats): \n have h2 : (j₀ : ℝ) + 1 < (m : ℝ) := by linarith [h1, hm_ge]\n have h3 : j₀ + 1 < m := by -- hmm strict in ℕ from real strict: exact_mod_cast h2 gives (↑(j₀+1):ℝ) < ↑m: j₀+1 < m: \n have h4 : ((j₀ + 1 : ℕ) : ℝ) < (m : ℝ) := by\n rw [Nat.cast_add_one]\n linarith [h2]\n exact_mod_cast h4\n omega\n · push Not at hre -- −re w < 0: j₀ = 0\n have h1 : ⌈-w.re⌉₊ = 0 := Nat.ceil_eq_zero.mpr (by linarith [hre])\n rw [hj₀, h1] -- goal 0 + 1 ≤ m: m ≥ 1: from hm_def: m = ⌈⌉₊ + 1 ≥ 1 ✓\n omega\n -- the recurrence\n have hshift : Complex.digamma v = Complex.digamma w + ∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹ := by\n rw [hv_def]\n exact digamma_add_natCast' hpoles m\n -- the sum bound\n have hsum := digamma_recip_sum_le hc hdist hj₀m -- hmm digamma_recip_sum_le's hm : ⌈−w.re⌉₊ + 1 ≤ m: hj₀m is about j₀ = the set-var: the set j₀ := ⌈−re w⌉₊ makes them the same term ✓ — digamma_recip_sum_le hc hdist (hm := hj₀m)? the {m} implicit: our m ✓ the hypothesis (hm : ⌈-w.re⌉₊ + 1 ≤ m): hj₀m : j₀ + 1 ≤ m with j₀ set-to ⌈−re w⌉₊ — the set makes j₀ a local def equal to it; the expected form ⌈-w.re⌉₊ + 1 ≤ m vs hj₀m's j₀ + 1 ≤ m — defeq via hj₀ — hmm `set` replaces occurrences in goal/context but the NEW application digamma_recip_sum_le hc hdist hj₀m — the argument hj₀m : j₀ + 1 ≤ m must match the expected ⌈-w.re⌉₊ + 1 ≤ m — j₀ is a let-bound local def: isDefEq j₀ =?= ⌈-w.re⌉₊ — `set` introduces j₀ as a local definition with hj₀ : j₀ = ⌈-w.re⌉₊ — the defeq unfolds the local def? `set` introduces an fvar with a let-value — isDefEq CAN unfold it ✓ generally works. If not: rw [hj₀] at hj₀m first.\n -- the landing-zone bound\n have hLZ : ‖Complex.digamma v‖ ≤ 21 * Real.log (2 + ‖v‖) := by\n by_cases him : 1 / 2 ≤ |v.im|\n · -- StirlingVert\n have hst := StirlingVert.digamma_stirling (by linarith [hvre.1] : (0:ℝ) < v.re) him\n -- ‖ψ v‖ ≤ 3/(im v)² + ‖log v‖ + 1/(2‖v‖)\n have hvnorm3 : 3 ≤ ‖v‖ := by\n have h1 := Complex.abs_re_le_norm v\n have h2 : |v.re| = v.re := abs_of_nonneg (by linarith [hvre.1])\n rw [h2] at h1\n linarith [hvre.1, h1]\n calc ‖Complex.digamma v‖\n = ‖(Complex.digamma v - Complex.log v + (1/2 : ℂ)/v) + Complex.log v - (1/2 : ℂ)/v‖ := by\n congr 1; ring\n _ ≤ ‖Complex.digamma v - Complex.log v + (1/2 : ℂ)/v‖ + ‖Complex.log v‖ + ‖(1/2 : ℂ)/v‖ := by\n refine (norm_sub_le _ _).trans ?_\n exact add_le_add_left (norm_add_le _ _) _ -- swapped convention\n _ ≤ 3 / v.im^2 + (Real.log ‖v‖ + Real.pi) + (1/2)/‖v‖ := by\n gcongr ... — explicit:\n refine add_le_add (add_le_add hst (norm_log_le_of_one_le (by linarith [hvnorm3]))) ?_\n rw [norm_div]\n have h12 : ‖(1/2 : ℂ)‖ = 1/2 := by ... (the pattern from LiReflect)\n rw [h12]\n _ ≤ 21 * Real.log (2 + ‖v‖) := by\n -- 3/(im v)² ≤ 3/(1/4) = 12; (1/2)/‖v‖ ≤ 1/6; log‖v‖ + π ≤ log(2+‖v‖) + 4: total ≤ log(2+‖v‖) + 16.2 + ... ≤ 21 log(2+‖v‖) ⟸ log(2+‖v‖) ≥ log 5 > 1.6 (‖v‖ ≥ 3): 21·1.6 = 33.6 ≥ 1·log + 16.2 ⟸ log(2+‖v‖)·20 ≥ 16.2 ⟸ 20·1.6 = 32 ≥ 16.2 ✓:\n have him2 : v.im^2 ≥ 1/4 := by\n calc v.im^2 = |v.im|^2 := by rw [sq_abs]\n _ ≥ (1/2)^2 := pow_le_pow_left₀ (abs_nonneg _) him _\n _ = 1/4 := by norm_num\n have hlogv : Real.log ‖v‖ ≤ Real.log (2 + ‖v‖) := Real.log_le_log (by linarith [hvnorm3]) (by linarith)\n have hlog5 : (0 : ℝ) ≤ Real.log (2 + ‖v‖) := Real.log_nonneg (by linarith [hvnorm3])\n have hpi : Real.pi ≤ 4 := Real.pi_lt_d2.le.trans (by norm_num)\n have h1 : 3 / v.im^2 ≤ 12 := by\n rw [div_le_iff₀ (by linarith [him2] : (0:ℝ) < v.im^2)]\n nlinarith [him2]\n have h2 : (1/2 : ℝ) / ‖v‖ ≤ 1 := by\n rw [div_le_one (by linarith [hvnorm3] : (0:ℝ) < ‖v‖)]\n linarith [hvnorm3]\n nlinarith [h1, h2, hlogv, hpi, hlog5, Real.log_nonneg (show (1:ℝ) ≤ 2 + ‖v‖ by linarith [hvnorm3])]\n · -- |im v| < 1/2: the §2 bound\n push Not at him\n rw [hvim] at him -- |w.im| < 1/2 ≤ 5: §2 needs |im v| ≤ 5: |v.im| < 1/2 ⟹ ≤ 5 ✓ via him: but (B) is stated with |w.im| ≤ 5 for the ARGUMENT v: |v.im| ≤ 5: from him : |v.im| < 1/2: .le.trans: \n exact (norm_digamma_le_of_two_le_re (by linarith [hvre.1] : (2:ℝ) ≤ v.re)\n (by linarith [him.le] : |v.im| ≤ 5)).trans (by\n -- 20 log(2+‖v‖) ≤ 21 log(2+‖v‖): log ≥ 0 (‖v‖ ≥ 3)\n have h : (0:ℝ) ≤ Real.log (2 + ‖v‖) := Real.log_nonneg (by linarith [hvre.1, Complex.abs_re_le_norm v] : (1:ℝ) ≤ 2 + ‖v‖)\n nlinarith [h])\n -- assemble\n have hwnorm : ‖w‖ ≥ ... — need: m ≤ 4 + ‖w‖ and ‖v‖ ≤ 2‖w‖ + 4 and the log inequalities:\n have hwm : (m : ℝ) ≤ 4 + ‖w‖ := by\n have h1 : (m : ℝ) ≤ (2 - w.re) + 2 := hm_lt.le\n have h2 : -w.re ≤ ‖w‖ := by\n have h3 := Complex.abs_re_le_norm w\n rwa [abs_le] at h3?? no: −re w ≤ |re w| ≤ ‖w‖: neg_le_abs (w.re) : −w.re ≤ |w.re| ✓ then trans with abs_re_le_norm:\n exact (neg_le_abs w.re).trans (Complex.abs_re_le_norm w)\n linarith [h1, h2]\n have hvnorm : ‖v‖ ≤ 2 * ‖w‖ + 4 := by\n rw [hv_def]\n calc ‖w + (m : ℂ)‖ ≤ ‖w‖ + ‖(m : ℂ)‖ := norm_add_le _ _\n _ = ‖w‖ + (m : ℝ) := by rw [RCLike.norm_natCast]\n _ ≤ 2 * ‖w‖ + 4 := by linarith [hwm]\n have hlogv_le : Real.log (2 + ‖v‖) ≤ 2 + Real.log (2 + ‖w‖) := by\n -- 2 + ‖v‖ ≤ 6 + 2‖w‖ = 2(3+‖w‖) ≤ 4(2+‖w‖): log ≤ log 4 + log(2+‖w‖) ≤ 2 + log(2+‖w‖)\n have h1 : 2 + ‖v‖ ≤ 4 * (2 + ‖w‖) := by linarith [hvnorm]\n have h2 : Real.log (2 + ‖v‖) ≤ Real.log (4 * (2 + ‖w‖)) :=\n Real.log_le_log (by linarith [hvre.1, ...] : (0:ℝ) < 2 + ‖v‖) h1\n have h3 : Real.log (4 * (2 + ‖w‖)) = Real.log 4 + Real.log (2 + ‖w‖) :=\n Real.log_mul (by norm_num : (4:ℝ) ≠ 0) (by positivity : (2 + ‖w‖) ≠ 0)\n have h4 : Real.log 4 ≤ 2 := by\n have h5 := Real.log_two_lt_d9.le -- log 2 < 0.6932\n have h6 : Real.log 4 = 2 * Real.log 2 := by\n rw [show (4:ℝ) = 2^2 by norm_num, Real.log_pow]; push_cast; ring\n linarith [h5, h6]\n linarith [h2, h3, h4]\n -- the sum bound form: 2/c + 2 + 2 log m ≤ ...: log m ≤ log(4+‖w‖) ≤ 1 + log(2+‖w‖):\n have hlogm : Real.log m ≤ 1 + Real.log (2 + ‖w‖) := by\n have h1 : (m : ℝ) ≤ 2 * (2 + ‖w‖) := by linarith [hwm]\n have h2 : Real.log (m : ℝ) ≤ Real.log (2 * (2 + ‖w‖)) := by\n apply Real.log_le_log (by positivity : (0:ℝ) < (m:ℝ)) h1\n -- hmm 0 < ↑m: m ≥ 1 ✓: by exact_mod_cast (by omega : 1 ≤ m)?? m = ⌈⌉₊+1 ≥ 1: have hm1 : 1 ≤ m := by omega (from hm_def) — add\n have h3 : Real.log (2 * (2 + ‖w‖)) = Real.log 2 + Real.log (2 + ‖w‖) :=\n Real.log_mul (by norm_num) (by positivity)\n have h4 : Real.log 2 ≤ 1 := Real.log_two_lt_d9.le.trans (by norm_num)\n linarith [h2, h3, h4]\n -- final assembly\n rw [← hshift] -- hmm: goal ‖ψ w‖: hshift : ψ v = ψ w + Σ: ‖ψ w‖ = ‖ψ v − Σ‖ ≤ ‖ψ v‖ + ‖Σ‖:\n -- directly: ‖ψ w‖ = ‖ψ v − Σ‖: from hshift: ψ w = ψ v − Σ (by linear_combination hshift):\n have hpsi : Complex.digamma w = Complex.digamma v - ∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹ := by\n linear_combination hshift\n rw [hpsi]\n calc ‖Complex.digamma v - ∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹‖\n ≤ ‖Complex.digamma v‖ + ‖∑ j ∈ Finset.range m, (w + (j : ℂ))⁻¹‖ := norm_sub_le _ _\n _ ≤ 21 * Real.log (2 + ‖v‖) + (2 / c + 2 + 2 * Real.log m) := add_le_add hLZ (hsum.trans' ...)...\n```\nwait hsum : ∑ ‖(w+↑j)⁻¹‖ ≤ 2/c + 2 + 2 log m (the SUM of norms) and I need ‖Σ (w+↑j)⁻¹‖ ≤ Σ ‖·‖⁻¹ (norm_sum_le) then hsum: ‖Σ‖ ≤ Σ‖·‖ ≤ 2/c+2+2 log m: `norm_sum_le` : ‖∑ i ∈ s, f i‖ ≤ ∑ i ∈ s, ‖f i‖ ✓ exists. So:\n```\n _ ≤ 21 * Real.log (2 + ‖v‖) + (2 / c + 2 + 2 * Real.log m) :=\n add_le_add hLZ ((norm_sum_le _ _).trans hsum)\n _ ≤ (46 + 2/c) + 23 * Real.log (2 + ‖w‖) := by\n -- 21(2 + L) + 2/c + 2 + 2(1 + L) = 42 + 21L + 2/c + 2 + 2 + 2L = 46 + 2/c + 23L ✓ with L := log(2+‖w‖):\n nlinarith [hlogv_le, hlogm, hc] -- hlogv_le : log(2+‖v‖) ≤ 2 + L; hlogm : log m ≤ 1 + L: 21·log(2+‖v‖) ≤ 21(2+L) (mul by 21: monotone — nlinarith with the product 21·(...) linear ✓); 2 log m ≤ 2(1+L) ✓: total: 21(2+L) + 2/c + 2 + 2(1+L) = 46 + 2/c + 23L ✓ nlinarith closes (linear in the atoms log(2+‖v‖), log m, L, 1/c... 2/c as atom: the target has 2/c as written — the LHS has 2/c too ✓ same atom)\n```\nThe nlinarith: LHS = 21·log(2+‖v‖) + (2/c + 2 + 2·log m): with log(2+‖v‖) ≤ 2 + L and log m ≤ 1 + L: nlinarith multiplies hypotheses by constants? nlinarith can use them linearly: 21·log(2+‖v‖) ≤ 21·(2+L) requires multiplying hlogv_le by 21 — nlinarith/linarith: linarith does that ✓ (constant multiples of hypotheses) — but the RHS target: 46 + 2/c + 23·L — with 2/c written differently? The LHS's (2/c) and the goal's (2 / c) — same ✓. So linarith [hlogv_le, hlogm] should close: 21·logv + 2/c + 2 + 2·logm ≤ 21(2+L) + 2/c + 2 + 2(1+L) = 46 + 2/c + 23L ✓ linear ✓.\n\nHmm — one concern: `hsum` is about ∑ j ∈ range m, ‖(w + ↑j)‖⁻¹ — wait digamma_recip_sum_le's conclusion: ∑ j ∈ Finset.range m, ‖(w + (j : ℂ))⁻¹‖ ≤ 2/c + 2 + 2·log ↑m ✓ matches.\n\nAnd the hypothesis alignment: digamma_recip_sum_le {c} (hc) {w} (hdist) {m} (hm : ⌈-w.re⌉₊ + 1 ≤ m) — my call: digamma_recip_sum_le hc hdist (show ⌈-w.re⌉₊ + 1 ≤ m from ...) — the j₀ set-var issue: give the proof directly with the ceil form (not the j₀ alias) — since j₀ is `set`, the term ⌈-w.re⌉₊ displays as j₀ in context but the term I pass must have the literal form... `set j₀ := ⌈-w.re⌉₊ with hj₀` REPLACES occurrences — so writing ⌈-w.re⌉₊ in a new term still elaborates to the same underlying expression; set's fold is only presentational for the GOAL at set-time. The expected type of the (hm :) argument is ⌈-w.re⌉₊ + 1 ≤ m — passing hj₀m : j₀ + 1 ≤ m where j₀ is the set-local-def: isDefEq j₀ ≡ ⌈-w.re⌉₊ — set introduces j₀ as a new free variable with hj₀ : j₀ = ⌈-w.re⌉₊ — NOT a let-value (set uses `fvar` + the equation). So isDefEq does NOT automatically unfold j₀!! I need `rw [hj₀] at hj₀m` to convert hj₀m to the literal form, OR write the have with the literal form. Hmm — actually `set` in Lean4 Mathlib: introduces a local variable j₀ and hj₀ : j₀ = value, and replaces occurrences — the new fvar j₀ is opaque (not defeq to the value). So I DO need rw [hj₀] at hj₀m to get ⌈-w.re⌉₊ + 1 ≤ m for passing. Note: after rw [hj₀] at hj₀m, hj₀m : ⌈-w.re⌉₊ + 1 ≤ m ✓. Fine — handle.\n\nWait — actually in §3's proof I used `set j₀ := ⌈-w.re⌉₊ with hj₀` and then `recip_norm_le_right hdist hj₀ ...` passing hj₀ : j₀ = ⌈-w.re⌉₊ as the (hj₀ : j₀ = ⌈-w.re⌉₊) argument — matching ✓ (the lemma's hj₀ hypothesis is the equation j₀ = ⌈⌉₊ ✓). And it compiled ✓. OK so the same patterns work.\n\nNow (G). Let me draft it fully:\n\n```\n/-! ## 5. The general logDeriv ΓR identity (G) -/\n\n/-- logDeriv of a finite product of linear factors. -/\ntheorem logDeriv_prod_range_linear {s : ℂ} (hs : s.im ≠ 0) (m : ℕ) :\n logDeriv (fun z : ℂ => ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s\n = ∑ j ∈ Finset.range m, (1 / 2 : ℂ) / (s / 2 + (j : ℂ)) := by\n induction m with\n | zero => simp [logDeriv_const] -- ∏ ∅ = 1: logDeriv (fun _ => 1) = 0; ∑ ∅ = 0: simp [logDeriv_const]: logDeriv_const : logDeriv (fun _ => a) = 0 — after simp the goal 0 = 0?? the goal: logDeriv (fun z => ∏ j ∈ range 0, ...) s = ∑ range 0 ...: range_zero, prod_empty, sum_empty: logDeriv (fun z => 1) s = 0: logDeriv_const is about logDeriv (fun _ => a) as a FUNCTION... its statement: logDeriv_const (a) : logDeriv (fun _ => a) = 0 — pointwise free: logDeriv (fun z => 1) s = (logDeriv (fun _ => 1)) s = 0 s = 0 — via congr_fun (logDeriv_const 1) s? simp [logDeriv_const] should handle ✓\n | succ k ih =>\n have hne : ∀ j : ℕ, (s / 2 + (j : ℂ)) ≠ 0 := by\n intro j h\n apply hs\n have h2 : (s / 2).im = 0 := by\n have h3 := congrArg Complex.im (congrArg (· / 2)?...)... \n```\nhmm — s/2 + ↑j = 0 ⟹ (s/2).im = 0 (since ↑j real): (s/2 + ↑j).im = (s/2).im + 0 = 0 ⟹ (s/2).im = 0 ⟹ s.im/2 = 0 ⟹ s.im = 0 contra hs:\n```\n have hne : ∀ j : ℕ, (s / 2 + (j : ℂ)) ≠ 0 := by\n intro j h\n apply hs\n have h1 : (s / 2 + (j : ℂ)).im = 0 := by rw [h]; simp\n have h2 : (s / 2 + (j : ℂ)).im = s.im / 2 := by\n simp [Complex.add_im, Complex.natCast_im, Complex.div_ofNat_im]\n rw [h2] at h1\n linarith [h1] -- s.im/2 = 0 ⟹ s.im = 0 ✓ linarith: goal s.im = 0: from s.im/2 = 0: linarith closes (linear: s.im = 2·(s.im/2) = 0) ✓\n have hprod_ne : (∏ j ∈ Finset.range k, (s / 2 + (j : ℂ))) ≠ 0 :=\n Finset.prod_ne_zero_iff.mpr fun j _ => hne j\n rw [Finset.prod_range_succ]\n rw [logDeriv_mul s (Finset.prod_ne_zero_iff.mpr fun j _ => hne j) (hne k)\n (by fun_prop : DifferentiableAt ℂ (fun z : ℂ => ∏ j ∈ Finset.range k, (z / 2 + (j : ℂ))) s)\n (by fun_prop : DifferentiableAt ℂ (fun z : ℂ => z / 2 + (k : ℂ)) s)]\n rw [ih]\n -- logDeriv (fun z => z/2 + ↑k) s = (1/2)/(s/2+↑k):\n have hfac : logDeriv (fun z : ℂ => z / 2 + (k : ℂ)) s = (1 / 2 : ℂ) / (s / 2 + (k : ℂ)) := by\n have h1 : HasDerivAt (fun z : ℂ => z / 2 + (k : ℂ)) (1 / 2 : ℂ) s := by\n have h2 := (hasDerivAt_id' s).div_const (2 : ℂ)\n exact h2.add_const (k : ℂ)\n rw [logDeriv_apply, h1.deriv]\n rw [hfac, Finset.sum_range_succ]\n```\nHmm — logDeriv_mul : logDeriv (fun z => f z * g z) x = logDeriv f x + logDeriv g x — after rw [Finset.prod_range_succ] the goal's function is fun z => (∏ j ∈ range k, (z/2+↑j)) * (z/2+↑k) — logDeriv_mul's pattern fun z => f z * g z ✓ matches. Then the goal: logDeriv (∏-part) s + logDeriv (single) s = ∑ range (k+1): rw [ih] (the IH : logDeriv (∏-part) s = ∑ range k): goal ∑ range k + logDeriv single = ∑ range (k+1): rw [hfac, Finset.sum_range_succ]: RHS becomes ∑ range k + (1/2)/(s/2+↑k): both sides: [∑ range k] + (1/2)/(s/2+↑k) = [∑ range k] + (1/2)/(s/2+↑k) ✓ rfl-close by rw ✓.\n\nThe fun_prop for the product differentiability: DifferentiableAt ℂ (fun z => ∏ j ∈ range k, (z/2+↑j)) s — fun_prop should handle (div, add, const, prod) ✓.\n\nThen (G) main:\n```\n/-- **(G) the general logDeriv ΓR identity**: for im s ≠ 0,\nlogDeriv ΓR s = −(log π)/2 + ½ψ(s/2) — the m-fold shift landing re > 0\n(`gamma_mul_prod` + `digamma_add_natCast` + 5d's EventuallyEq machinery). -/\ntheorem logDeriv_Gammaℝ_eq {s : ℂ} (hs : s.im ≠ 0) :\n logDeriv Complex.Gammaℝ s\n = -(Real.log Real.pi : ℂ) / 2 + (1 / 2 : ℂ) * Complex.digamma (s / 2) := by\n set m := ⌈max 0 (-(s.re / 2))⌉₊ + 1 with hm_def\n have hmge : (2 : ℝ) ≤ s.re + 2 * (m : ℝ) := by\n have h1 : max 0 (-(s.re / 2)) ≤ (⌈max 0 (-(s.re / 2))⌉₊ : ℝ) := Nat.le_ceil _\n have h2 : -(s.re / 2) ≤ max 0 (-(s.re / 2)) := le_max_right _ _\n rw [hm_def]\n push_cast\n linarith [h1, h2]\n have hres2 : 0 < (s + 2 * (m : ℂ)).re := by\n have h1 : (s + 2 * (m : ℂ)).re = s.re + 2 * (m : ℝ) := by\n simp [Complex.add_re, Complex.mul_re, Complex.natCast_re] -- (2*↑m : ℂ).re = 2*↑m: mul_re: 2.re*↑m.re − 2.im*↑m.im: numerals simp ✓\n rw [h1]\n linarith [hmge]\n -- the pointwise identity on U = {im ≠ 0}\n have hU : IsOpen {z : ℂ | z.im ≠ 0} := isOpen_ne_fun Complex.continuous_im continuous_const\n have hpt : ∀ z : ℂ, z.im ≠ 0 → Complex.Gammaℝ z\n = (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))\n / ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ)) := by\n intro z hz\n -- recurrence side conditions\n have hside : ∀ k : ℕ, k < m → z / 2 ≠ -(k : ℂ) := by\n intro k _ h\n apply hz\n have h1 : (z / 2).im = 0 := by\n have h2 := congrArg Complex.im h\n -- h2 : (z/2).im = (−↑k).im = 0\n simpa [Complex.neg_im, Complex.natCast_im] using h2\n simp [Complex.div_ofNat_im] at h1 -- (z/2).im = z.im/2: h1 : z.im/2 = 0\n linarith [h1]\n have hrec := gamma_mul_prod (z / 2) m hside\n -- ΓR(z+2m) = π^{−(z+2m)/2} Γ((z+2m)/2) = π^{−z/2}·π^{−m}·Γ(z/2+m)\n have hG1 : Complex.Gammaℝ (z + 2 * (m : ℂ))\n = (Real.pi : ℂ) ^ (-(z + 2 * (m : ℂ)) / 2) * Complex.Gamma ((z + 2 * (m : ℂ)) / 2) :=\n Complex.Gammaℝ_def _\n have harg1 : (-(z + 2 * (m : ℂ)) / 2) = -z / 2 - (m : ℂ) := by ring\n have harg2 : (z + 2 * (m : ℂ)) / 2 = z / 2 + (m : ℂ) := by ring\n -- the cpow split: π^{−z/2 − m} = π^{−z/2} · π^{−m}\n have hpi : (Real.pi : ℂ) ^ (-z / 2 - (m : ℂ))\n = (Real.pi : ℂ) ^ (-z / 2) * (((Real.pi ^ m : ℝ)) : ℂ)⁻¹ := by\n have hlog : Complex.log (Real.pi : ℂ) = (Real.log Real.pi : ℂ) :=\n (Complex.ofReal_log Real.pi_nonneg).symm\n rw [Complex.cpow_def_of_ne_zero (by exact_mod_cast Real.pi_ne_zero : (Real.pi : ℂ) ≠ 0) _,\n Complex.cpow_def_of_ne_zero (by exact_mod_cast Real.pi_ne_zero : (Real.pi : ℂ) ≠ 0) _,\n hlog]\n have harg : (Real.log Real.pi : ℂ) * (-z / 2 - (m : ℂ))\n = (Real.log Real.pi : ℂ) * (-z / 2) + ((-(m : ℝ) * Real.log Real.pi : ℝ) : ℂ) := by\n push_cast\n ring\n rw [harg, Complex.exp_add, ← Complex.ofReal_exp]\n -- Real.exp (−m·log π) = (π^m)⁻¹\n have hexp : Real.exp (-(m : ℝ) * Real.log Real.pi) = (Real.pi ^ m)⁻¹ := by\n have h1 : (-(m : ℝ) * Real.log Real.pi) = Real.log ((Real.pi ^ m)⁻¹) := by\n rw [Real.log_inv, Real.log_pow]\n ring\n rw [h1, Real.exp_log (by positivity)]\n rw [hexp]\n push_cast\n ring -- hmm: ↑(π^m)⁻¹ vs ((↑π)^m)⁻¹: ofReal_pow/inv: push_cast normalizes ↑(π^m) → (↑π)^m: the goal: exp-form LHS already rewritten... let me end with: rw [hexp]; push_cast; ring — the goal at that point: (π:ℂ)^(−z/2) * ↑(Real.exp (−m log π)) = (π:ℂ)^(−z/2) * ↑((π^m)⁻¹): after rw [hexp]: RHS ↑( (π^m)⁻¹ ): push_cast turns it into ((↑π)^m)⁻¹: goal: π^(−z/2) * ((↑π)^m)⁻¹ = π^(−z/2) * ((↑π)^m)⁻¹ ✓ rfl — ring closes or the rw [hexp] + push_cast leaves syntactically equal sides ⟹ ring closes.\n -- assemble ΓR(z+2m) = (π^m)⁻¹ · ΓR z · ∏\n have hG2 : Complex.Gammaℝ (z + 2 * (m : ℂ))\n = (((Real.pi ^ m : ℝ) : ℂ))⁻¹ * Complex.Gammaℝ z * ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ)) := by\n rw [hG1, harg1, harg2, hpi, Complex.Gammaℝ_def]\n -- ΓR z = π^{−z/2} Γ(z/2): unfold; hrec : Γ(z/2) * ∏ = Γ(z/2 + ↑m): substitute Γ(z/2+m) = Γ(z/2)·∏ via hrec.symm? hrec : Γ(z/2) * ∏ j ∈ range m, (z/2+↑j) = Γ(z/2+↑m): I need Γ(z/2+↑m) = Γ(z/2)·∏: rw [← hrec]:\n rw [← hrec]\n ring\n -- solve for ΓR z: ΓR z = π^m · ΓR(z+2m) / ∏\n have hPne : (∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) ≠ 0 := by\n apply Finset.prod_ne_zero_iff.mpr\n intro j _\n intro h\n apply hz\n have h1 : (z / 2 + (j : ℂ)).im = 0 := by rw [h]; simp\n simp [Complex.add_im, Complex.natCast_im, Complex.div_ofNat_im] at h1\n linarith [h1]\n have hπne : ((Real.pi ^ m : ℝ) : ℂ) ≠ 0 := by\n exact_mod_cast pow_ne_zero m Real.pi_ne_zero\n rw [eq_div_iff hPne] -- goal: ΓR z * ∏ = π^m * ΓR(z+2m)\n rw [hG2]\n -- goal: ΓR z * ∏ = π^m * ((π^m)⁻¹ * ΓR z * ∏) = (π^m · (π^m)⁻¹)·(ΓR z · ∏) = ΓR z * ∏: \n rw [show (Real.pi : ℂ) ^ (m : ℂ) = ((Real.pi ^ m : ℝ) : ℂ) by\n rw [Complex.cpow_natCast]; push_cast; ring] -- hmm (π:ℂ)^(↑m) = ↑(π^m): cpow_natCast: x^(↑n) = x^n: then ↑(π^m) vs (π:ℂ)^m: push_cast: ↑(π^m) → (↑π)^m ✓ then ring? the two sides (↑π)^m and ↑(π^m): push_cast turns ↑(π^m) into (↑π)^m: rfl — hmm the show's LHS is cpow (π:ℂ)^(↑m:ℂ) and RHS ↑(π^m): rw [Complex.cpow_natCast] turns LHS into (π:ℂ)^m: goal (π:ℂ)^m = ↑(π^m): push_cast turns RHS ↑(π^m) into (↑π)^m: rfl — so `by rw [Complex.cpow_natCast]; push_cast` — push_cast closes rfl? if both sides identical after push_cast — push_cast closes rfl goals? no — need exact/rfl: `by rw [Complex.cpow_natCast]; exact_mod_cast rfl`?? — simplest: by rw [Complex.cpow_natCast, ← Complex.ofReal_pow]?? — ↑(π^m) = (↑π)^m via `Complex.ofReal_pow : ↑(x^n) = (↑x)^n` ✓: so: rw [Complex.cpow_natCast, Complex.ofReal_pow] — LHS (π:ℂ)^m, RHS ↑(π^m) → after rw [Complex.ofReal_pow] the RHS becomes (↑π)^m: both sides (π:ℂ)^m ✓ rfl-close ✓. Wait direction: ofReal_pow : (↑(x^n) : ℂ) = (↑x)^n: rw [← Complex.ofReal_pow] turns (↑π)^m into ↑(π^m)... my show's equation: (π:ℂ)^(m:ℂ) = ↑(π^m): rw [Complex.cpow_natCast] : LHS (π:ℂ)^(↑m) → (π:ℂ)^m: goal (π:ℂ)^m = ↑(π^m): rw [← Complex.ofReal_pow]: pattern (↑x)^n: LHS (π:ℂ)^m matches with x := π: → ↑(π^m): goal ↑(π^m) = ↑(π^m) rfl ✓. So the show: by rw [Complex.cpow_natCast, ← Complex.ofReal_pow].\n -- now the goal: ΓR z * ∏ = ↑(π^m) * ((↑(π^m))⁻¹ * ΓR z * ∏): ring with the inverse: need ↑(π^m) ≠ 0 to cancel — field_simp [hπne]? or:\n field_simp [hπne]\n ring\n```\nHmm — the field_simp after rw [hG2] and the show-rewrite: goal ΓR z * ∏ = ↑(π^m) * ((↑(π^m))⁻¹ * ΓR z * ∏): field_simp [hπne] clears the ⁻¹: ΓR z * ∏ * ↑(π^m) = ↑(π^m) * (ΓR z * ∏)·... then ring ✓. Or simply: the RHS = ↑(π^m) * (↑(π^m))⁻¹ * ΓR z * ∏ = ΓR z * ∏ by mul_inv_cancel₀ + one_mul: rw [mul_inv_cancel₀ hπne]?? the form: ↑(π^m) * (↑(π^m))⁻¹ * (ΓR z * ∏) — assoc: (↑(π^m) * (↑(π^m))⁻¹) * (ΓR z * ∏): mul_inv_cancel₀ : a * a⁻¹ = 1 for a ≠ 0 ✓: the exact form in the goal: ↑(π^m) * ((↑(π^m))⁻¹ * ΓR z * ∏) — regroup: = (↑(π^m) * (↑(π^m))⁻¹) * (ΓR z * ∏) [ring_nf? no — just: `field_simp [hπne]` then `ring` — iterate at build.\n\nThen:\n```\n -- the EventuallyEq and the logDeriv computation\n have hEv : Complex.Gammaℝ =ᶠ[𝓝 s]\n fun z => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))\n / ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ)) := by\n filter_upwards [hU.mem_nhds hs] with z hz using hpt z hz\n have hG2m : Complex.Gammaℝ (s + 2 * (m : ℂ)) ≠ 0 :=\n Complex.Gammaℝ_ne_zero_of_re_pos hres2\n have hPne : (∏ j ∈ Finset.range m, (s / 2 + (j : ℂ))) ≠ 0 := ... (as hpt's)\n have hdG2m : DifferentiableAt ℂ (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s := by\n apply DifferentiableAt.comp\n · exact differentiableAt_Gammaℝ (by linarith [hres2] : (0:ℝ) < (s + 2*(m:ℂ)).re)?? \n```\nhmm — Zeta23's `differentiableAt_Gammaℝ (hs : 0 < s.re)` (WeilEF/XiLogDeriv.lean) — namespace? from the earlier grep: `Zeta23/WeilEF/XiLogDeriv.lean:30:lemma differentiableAt_Gammaℝ {s : ℂ} (hs : 0 < s.re)` — namespace inside? probably Zeta23 or plain. With open Zeta23 — accessible as differentiableAt_Gammaℝ (if root Zeta23 namespace) — but my LiReflect has differentiableAt_Gammaℝ_of_im_ne_zero' (mine). For re > 0: use whichever — check the namespace at build: try `Zeta23.differentiableAt_Gammaℝ` — hmm the file XiLogDeriv.lean's namespace: let me just use my own via... my ' variant needs im ≠ 0: (s+2m).im = s.im ≠ 0 ✓: differentiableAt_Gammaℝ_of_im_ne_zero' (by simp [Complex.add_im, ...]; exact hs). Then comp with (z + 2↑m): differentiableAt_id.add_const ✓:\n```\n have hdG2m : DifferentiableAt ℂ (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s := by\n have h1 : (s + 2 * (m : ℂ)).im ≠ 0 := by\n have h2 : (s + 2 * (m : ℂ)).im = s.im := by\n simp [Complex.add_im, Complex.mul_im, Complex.natCast_im]\n rw [h2]; exact hs\n exact (differentiableAt_Gammaℝ_of_im_ne_zero' h1).comp s (differentiableAt_id.add_const _)\n have hdP : DifferentiableAt ℂ (fun z : ℂ => ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s := by fun_prop\n -- the big computation\n rw [logDeriv_congr hEv]\n have hstep1 : logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))\n / ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s\n = logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))) s\n - logDeriv (fun z : ℂ => ∏ j ∈ Finset.range m, (z / 2 + (j : ℂ))) s :=\n logDeriv_div s (mul_ne_zero (pow_ne_zero _ (by exact_mod_cast Real.pi_ne_zero)) hG2m) hPne\n ((differentiableAt_const _).mul hdG2m) hdP\n have hstep2 : logDeriv (fun z : ℂ => (Real.pi : ℂ) ^ (m : ℂ) * Complex.Gammaℝ (z + 2 * (m : ℂ))) s\n = logDeriv Complex.Gammaℝ (s + 2 * (m : ℂ)) := by\n rw [logDeriv_const_mul s _ (pow_ne_zero _ (by exact_mod_cast Real.pi_ne_zero : (Real.pi:ℂ) ≠ 0))]\n -- logDeriv (ΓR(·+2m)) s = logDeriv ΓR (s+2m): the comp deriv\n have hder : deriv (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s\n = deriv Complex.Gammaℝ (s + 2 * (m : ℂ)) := by\n have h1 := ((differentiableAt_Gammaℝ_of_im_ne_zero' (by\n have h2 : (s + 2 * (m : ℂ)).im = s.im := by\n simp [Complex.add_im, Complex.mul_im, Complex.natCast_im]\n rw [h2]; exact hs)).hasDerivAt).comp s ((hasDerivAt_id' s).add_const (2 * (m : ℂ)))\n have h2 : deriv (fun z : ℂ => Complex.Gammaℝ (z + 2 * (m : ℂ))) s\n = deriv Complex.Gammaℝ (s + 2 * (m : ℂ)) * 1 := h1.deriv\n rwa [mul_one] at h2\n simp only [logDeriv_apply, hder]\n rw [hstep1, hstep2]\n -- logDeriv ΓR (s+2m) via logDeriv_Gammaℝ (re > 0)\n have hev : logDeriv Complex.Gammaℝ (s + 2 * (m : ℂ))\n = -(Real.log Real.pi : ℂ) / 2 + (1 / 2 : ℂ) * Complex.digamma ((s + 2 * (m : ℂ)) / 2) :=\n RvM.logDeriv_Gammaℝ hres2\n rw [hev]\n -- the product logDeriv + the digamma shift + the cancellation\n rw [logDeriv_prod_range_linear hs m]\n -- (s+2m)/2 = s/2 + m; ψ(s/2 + m) = ψ(s/2) + Σ (s/2+↑j)⁻¹ (digamma_add_natCast, im(s/2) ≠ 0)\n have him2 : (s / 2).im ≠ 0 := by\n simp [Complex.div_ofNat_im]\n exact hs -- hmm: (s/2).im = s.im/2 ≠ 0 from hs: after simp [div_ofNat_im]: goal s.im/2 ≠ 0: div_ne_zero hs two_ne_zero ✓: `simp [Complex.div_ofNat_im]; exact div_ne_zero hs (by norm_num)`? careful — let me: have : (s/2).im = s.im / 2 := by simp [Complex.div_ofNat_im]; rw [this]; exact div_ne_zero hs (by norm_num : (2:ℝ) ≠ 0)\n have harg : (s + 2 * (m : ℂ)) / 2 = s / 2 + (m : ℂ) := by ring\n rw [harg, digamma_add_natCast him2 m]\n -- the per-term form: (1/2)/(s/2+↑j) = (1/2)·(s/2+↑j)⁻¹: and Σ forms match\n have hterm : ∀ j : ℕ, (1 / 2 : ℂ) / (s / 2 + (j : ℂ)) = (1 / 2 : ℂ) * (s / 2 + (j : ℂ))⁻¹ := by\n intro j\n rw [div_eq_mul_inv]\n rw [Finset.sum_congr rfl (fun j _ => hterm j)] -- hmm rw with sum_congr result — messy; better:\n -- the goal: −(logπ)/2 + ½(ψ(s/2) + Σ (s/2+↑j)⁻¹) − Σ (1/2)/(s/2+↑j) = −(logπ)/2 + ½ψ(s/2)\n -- via: Σ (1/2)/(s/2+↑j) = ½ Σ (s/2+↑j)⁻¹: Finset.mul_sum\n have hsumform : ∑ j ∈ Finset.range m, (1 / 2 : ℂ) / (s / 2 + (j : ℂ))\n = (1 / 2 : ℂ) * ∑ j ∈ Finset.range m, (s / 2 + (j : ℂ))⁻¹ := by\n rw [Finset.mul_sum]\n apply Finset.sum_congr rfl\n intro j _\n rw [div_eq_mul_inv]\n rw [hsumform]\n ring\n```\nCheck the algebra at the end: goal: −(logπ)/2 + ½·(ψ + Σ) − ½·Σ = −(logπ)/2 + ½·ψ — after rw [digamma_add_natCast him2 m]: the term digamma (s/2 + ↑m) becomes ψ(s/2) + Σ: the goal: −(logπ)/2 + ½·(ψ(s/2) + Σ (s/2+↑j)⁻¹) − Σ (1/2)/(s/2+↑j) = −(logπ)/2 + ½ ψ(s/2): rw [hsumform]: the Σ (1/2)/(...) → ½·Σ(...)⁻¹: goal: −(logπ)/2 + ½·(ψ + Σ) − ½·Σ = ...: ring ✓ (treating ψ, Σ as atoms: ½ψ + ½Σ − ½Σ = ½ψ ✓).\n\nOne concern: `digamma_add_natCast him2 m` — its statement (LiReflect): digamma (w + ↑n) = digamma w + Σ j ∈ range n, (w + ↑j)⁻¹ with w := s/2: after rw [harg] the term is digamma (s/2 + ↑m) ✓ rw [digamma_add_natCast him2 m] rewrites it to digamma (s/2) + Σ ✓.\n\nAlso hpt's form vs the EventuallyEq: the function fun z => (π:ℂ)^(↑m) * ΓR(z+2↑m) / ∏ ... — and hpt gives ΓR z = that ✓ filter_upwards ✓.\n\nThe hstep1's logDeriv_div: signature logDeriv_div (x) (hf : f x ≠ 0) (hg : g x ≠ 0) (hdf) (hdg) ✓.\n\n`pow_ne_zero _ (hpi : (π:ℂ) ≠ 0) : (π:ℂ)^? ≠ 0` — the exponent (m:ℂ) is a cpow! pow_ne_zero is for ^ℕ — for the cpow (π:ℂ)^(↑m:ℂ): need cpow-ne-zero: `Complex.cpow_ne_zero`? hmm — for x ≠ 0: x^y ≠ 0 — hmm is that even true for cpow? x^y = exp(y log x) ≠ 0 (exp_ne_zero) for x ≠ 0 ✓: `Complex.cpow_ne_zero (hx : x ≠ 0) (y : ℂ) : x ^ y ≠ 0`? hmm — not sure of the name; maybe `Complex.cpow_ne_zero_iff`? Let me handle: (π:ℂ)^(↑m) = (π:ℂ)^m via cpow_natCast (hmm — is the exponent ↑m : ℂ with m : ℕ — cpow_natCast : x ^ (↑n : ℂ) = x ^ n — so rewrite to (π:ℂ)^m then pow_ne_zero m ✓. To avoid the issue entirely: define the EventuallyEq's constant factor as ((Real.pi ^ m : ℝ) : ℂ) (the real-pow cast) instead of the cpow — from the show-rewrite: (π:ℂ)^(↑m:ℂ) = ↑(π^m) — use ↑(π^m) EVERYWHERE (cleaner: no cpow-ne-zero issues: ↑(π^m) ≠ 0 via cast of pow_ne_zero ✓). Let me use ((Real.pi ^ m : ℝ) : ℂ) as the constant in hpt/hEv/steps.\n\nOK — I have full drafts. Write §4+§5 as the append now. This is long; let me be careful to paste ONLY Lean. I'll write §4 ((A) + digamma_add_natCast') and §5 (G) in one Edit, then compile-iterate.","signature":""},{"type":"text","text":"Build green, audit clean, committed. Now §4 (A) + §5 (G) — the rest of 5e-ii. Appending them (Lean only this time)."},{"type":"tool_use","id":"Bash_438","name":"Bash","input":{"command":"tail -3 /d/Python/Quantum/research/lean/NguyenRH1/NguyenRH1/LiDigammaLeft.lean","description":"Check file tail before appending"},"extra_content":null}]