number_theory.zeta_function
⟷
Mathlib.NumberTheory.ZetaFunction
The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(last sync)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -873,8 +873,8 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [riemannZeta_one_sub]
rotate_left
· intro n
- rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), ← Int.cast_neg_natCast, ← Int.cast_ofNat,
- Ne.def, Int.cast_inj]
+ rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), ← Int.cast_neg_natCast, ←
+ Int.cast_natCast, Ne.def, Int.cast_inj]
apply ne_of_gt
refine' lt_of_le_of_lt (by norm_num : (-n : ℤ) ≤ 0) (by positivity)
· rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), Ne.def, Nat.cast_eq_one]; norm_num
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
-/
import Analysis.SpecialFunctions.Gamma.Beta
-import NumberTheory.ModularForms.JacobiTheta.Basic
+import NumberTheory.ModularForms.JacobiTheta.OneVariable
import NumberTheory.ZetaValues
#align_import number_theory.zeta_function from "leanprover-community/mathlib"@"d0b1936853671209a866fa35b9e54949c81116e2"
@@ -146,8 +146,8 @@ the Dirichlet series for `re s > 1`.) -/
theorem zetaKernel₁_eq_jacobiTheta {t : ℝ} (ht : 0 < t) :
zetaKernel₁ t = (jacobiTheta (t * I) - 1) / 2 :=
by
- rw [jacobiTheta_eq_tsum_nat ((mul_I_im t).symm ▸ ht : 0 < (↑t * I).im), add_comm, add_sub_cancel,
- mul_div_cancel_left _ (two_ne_zero' ℂ), zetaKernel₁]
+ rw [jacobiTheta_eq_tsum_nat ((mul_I_im t).symm ▸ ht : 0 < (↑t * I).im), add_comm,
+ add_sub_cancel_right, mul_div_cancel_left₀ _ (two_ne_zero' ℂ), zetaKernel₁]
congr 1 with n : 1
push_cast
rw [(by ring : ↑π * I * (n + 1) ^ 2 * (t * I) = I ^ 2 * π * t * (n + 1) ^ 2), I_sq, neg_one_mul]
@@ -288,7 +288,7 @@ theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => ex
exact of_real_ne_zero.mpr ((sqrt_ne_zero <| le_of_lt hx).mpr (ne_of_gt hx))
· refine' eventually_of_mem self_mem_nhdsWithin fun x hx => _
dsimp only
- rw [Function.comp_apply, mul_one_div, one_div ↑(sqrt _), ← of_real_inv, IsROrC.norm_ofReal,
+ rw [Function.comp_apply, mul_one_div, one_div ↑(sqrt _), ← of_real_inv, RCLike.norm_ofReal,
abs_inv, abs_of_nonneg (sqrt_nonneg _), ← div_eq_mul_inv]
#align is_O_zero_zeta_kernel₂ isBigO_zero_zetaKernel₂
-/
@@ -331,7 +331,7 @@ theorem isBigO_zero_zetaKernel₁ : IsBigO (𝓝[>] 0) zetaKernel₁ fun t => t
((is_O_refl _ _).congr' (eventually_eq.refl _ _)
(eventually_eq_of_mem self_mem_nhdsWithin fun x hx => _)).const_mul_left
_
- rw [IsROrC.norm_ofReal, abs_of_nonneg (sqrt_nonneg _)]
+ rw [RCLike.norm_ofReal, abs_of_nonneg (sqrt_nonneg _)]
simp_rw [sqrt_eq_rpow, rpow_neg (le_of_lt hx), one_div]
· refine' is_O_iff.mpr ⟨‖(1 / 2 : ℂ)‖, _⟩
refine' eventually_of_mem (Ioc_mem_nhdsWithin_Ioi <| left_mem_Ico.mpr zero_lt_one) fun t ht => _
@@ -417,7 +417,7 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
tendsto (fun z => riemannCompletedZeta z * (z / 2) / (z / 2 * Gamma (z / 2))) (𝓝[≠] 0)
(𝓝 <| -1 / 2)
· refine' tendsto.congr' (eventually_eq_of_mem self_mem_nhdsWithin fun z hz => _) h3
- rw [← div_div, mul_div_cancel _ (div_ne_zero hz two_ne_zero)]
+ rw [← div_div, mul_div_cancel_right₀ _ (div_ne_zero hz two_ne_zero)]
have h4 : tendsto (fun z : ℂ => z / 2 * Gamma (z / 2)) (𝓝[≠] 0) (𝓝 1) :=
by
refine' tendsto_self_mul_Gamma_nhds_zero.comp _
@@ -529,7 +529,7 @@ theorem hasMellin_one_div_sqrt_sub_one_div_two_Ioc {s : ℂ} (hs : 1 / 2 < s.re)
by ext1 t; simp_rw [div_eq_inv_mul, indicator_mul_right]]
simp_rw [HasMellin, mellin_div_const, step1.2, sub_div, div_div]
refine' ⟨step1.1.div_const _, _⟩
- rw [mul_comm, sub_mul, div_mul_cancel _ (two_ne_zero' ℂ), mul_comm s 2]
+ rw [mul_comm, sub_mul, div_mul_cancel₀ _ (two_ne_zero' ℂ), mul_comm s 2]
#align has_mellin_one_div_sqrt_sub_one_div_two_Ioc hasMellin_one_div_sqrt_sub_one_div_two_Ioc
-/
@@ -557,7 +557,7 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
sub_sub, ← add_sub]
conv_rhs => rw [← add_zero (mellin zetaKernel₁ <| s / 2)]
congr 1
- rw [mul_div_cancel' _ (two_ne_zero' ℂ)]
+ rw [mul_div_cancel₀ _ (two_ne_zero' ℂ)]
abel
#align completed_zeta_eq_mellin_of_one_lt_re completed_zeta_eq_mellin_of_one_lt_re
-/
@@ -655,7 +655,7 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
riemannCompletedZeta s = π ^ (-s / 2) * Gamma (s / 2) * ∑' n : ℕ, 1 / (n + 1) ^ s :=
by
rw [completed_zeta_eq_mellin_of_one_lt_re hs, mellin_zetaKernel₁_eq_tsum, neg_div,
- mul_div_cancel' _ (two_ne_zero' ℂ)]
+ mul_div_cancel₀ _ (two_ne_zero' ℂ)]
rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
rwa [of_real_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
#align completed_zeta_eq_tsum_of_one_lt_re completed_zeta_eq_tsum_of_one_lt_re
@@ -670,7 +670,7 @@ theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) :
by
have : s ≠ 0 := by contrapose! hs; rw [hs, zero_re]; exact zero_le_one
rw [riemannZeta, Function.update_noteq this, completed_zeta_eq_tsum_of_one_lt_re hs, ← mul_assoc,
- neg_div, cpow_neg, mul_inv_cancel_left₀, mul_div_cancel_left]
+ neg_div, cpow_neg, mul_inv_cancel_left₀, mul_div_cancel_left₀]
· apply Gamma_ne_zero_of_re_pos
rw [← of_real_one, ← of_real_bit0, div_eq_mul_inv, ← of_real_inv, mul_comm, of_real_mul_re]
exact mul_pos (inv_pos_of_pos two_pos) (zero_lt_one.trans hs)
@@ -805,9 +805,9 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
exact ⟨m * 2, by rw [hm]⟩
have h_Ga_eq : Gamma s = Gamma (s / 2) * Gamma ((s + 1) / 2) * 2 ^ (s - 1) / sqrt π := by
- rw [add_div, Complex.Gamma_mul_Gamma_add_half, mul_div_cancel' _ (two_ne_zero' ℂ),
+ rw [add_div, Complex.Gamma_mul_Gamma_add_half, mul_div_cancel₀ _ (two_ne_zero' ℂ),
(by ring : 1 - s = -(s - 1)), cpow_neg, ← div_eq_mul_inv, eq_div_iff h_sqrt,
- div_mul_eq_mul_div₀, div_mul_cancel _ h_pow]
+ div_mul_eq_mul_div₀, div_mul_cancel₀ _ h_pow]
have h_Ga_ne3 : Gamma ((s + 1) / 2) ≠ 0 :=
by
have h_Ga_aux : Gamma s ≠ 0 := Complex.Gamma_ne_zero hs
@@ -822,7 +822,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
-- `function.update_noteq` to change the goal; the original goal is genuinely false for s = 1.
obtain ⟨n, rfl⟩ := hs_pos_odd
have : (1 - (1 + 2 * (n : ℂ))) / 2 = -↑n := by
- rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left _ (two_ne_zero' ℂ)]
+ rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left₀ _ (two_ne_zero' ℂ)]
rw [this, Complex.Gamma_neg_nat_eq_zero, div_zero]
have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast; field_simp; ring
rw [this, Complex.sin_int_mul_pi, MulZeroClass.mul_zero, MulZeroClass.zero_mul]
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -226,7 +226,7 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) : zetaKernel₂ (1 / t) = s
· exact aux h
· simp only [div_self, Ne.def, one_ne_zero, not_false_iff, sqrt_one, of_real_one, one_mul]
· have := aux (show 1 < 1 / t by rwa [lt_one_div (zero_lt_one' ℝ) ht, div_one])
- rw [one_div_one_div] at this
+ rw [one_div_one_div] at this
rw [this, ← mul_assoc, ← of_real_mul, ← sqrt_mul ht.le, mul_one_div_cancel ht.ne', sqrt_one,
of_real_one, one_mul]
#align zeta_kernel₂_one_div zetaKernel₂_one_div
@@ -245,7 +245,7 @@ show holomorphy of their Mellin transforms (for `1 / 2 < re s` for `zeta_kernel
theorem isBigO_atTop_zetaKernel₁ : IsBigO atTop zetaKernel₁ fun t => exp (-π * t) :=
by
have h := isBigO_at_im_infty_jacobiTheta_sub_one.const_mul_left (1 / 2)
- simp_rw [mul_comm (1 / 2 : ℂ) _, mul_one_div] at h
+ simp_rw [mul_comm (1 / 2 : ℂ) _, mul_one_div] at h
have h' : tendsto (fun t : ℝ => ↑t * I) at_top (comap im at_top) :=
by
rw [tendsto_comap_iff]
@@ -276,7 +276,7 @@ theorem isBigO_atTop_zetaKernel₂ : IsBigO atTop zetaKernel₂ fun t => exp (-
theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => exp (-π / t) / sqrt t :=
by
have h1 := isBigO_atTop_zetaKernel₂.comp_tendsto tendsto_inv_zero_atTop
- simp_rw [← one_div] at h1
+ simp_rw [← one_div] at h1
have h2 : zetaKernel₂ ∘ Div.div 1 =ᶠ[𝓝[>] 0] fun t => sqrt t * zetaKernel₂ t :=
eventually_of_mem self_mem_nhdsWithin fun t ht => by simp_rw [← zetaKernel₂_one_div ht]
have h3 := h1.congr' h2 (eventually_eq.refl _ _)
@@ -428,7 +428,7 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
suffices tendsto (fun z => riemannCompletedZeta z * z / 2) (𝓝[≠] 0) (𝓝 (-1 / 2 : ℂ))
by
have := this.div h4 one_ne_zero
- simp_rw [div_one, mul_div_assoc] at this
+ simp_rw [div_one, mul_div_assoc] at this
exact this
refine' tendsto.div _ tendsto_const_nhds two_ne_zero
simp_rw [riemannCompletedZeta, add_mul, sub_mul]
@@ -762,7 +762,7 @@ theorem riemannCompletedZeta₀_one_sub (s : ℂ) :
by
have := mellin_comp_rpow zetaKernel₂ (s / 2 - 1 / 2) neg_one_lt_zero.ne
simp_rw [rpow_neg_one, ← one_div, abs_neg, abs_one, div_one, one_smul, of_real_neg, of_real_one,
- div_neg, div_one, neg_sub] at this
+ div_neg, div_one, neg_sub] at this
conv_lhs => rw [riemannCompletedZeta₀, sub_div, ← this]
refine' set_integral_congr measurableSet_Ioi fun t ht => _
simp_rw [zetaKernel₂_one_div ht, smul_eq_mul, ← mul_assoc, sqrt_eq_rpow,
@@ -802,7 +802,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
rw [Ne.def, Complex.Gamma_eq_zero_iff]
contrapose! hs
obtain ⟨m, hm⟩ := hs
- rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
+ rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
exact ⟨m * 2, by rw [hm]⟩
have h_Ga_eq : Gamma s = Gamma (s / 2) * Gamma ((s + 1) / 2) * 2 ^ (s - 1) / sqrt π := by
rw [add_div, Complex.Gamma_mul_Gamma_add_half, mul_div_cancel' _ (two_ne_zero' ℂ),
@@ -832,14 +832,14 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
contrapose! hs_pos_odd
obtain ⟨m, hm⟩ := hs_pos_odd
rw [div_eq_iff (two_ne_zero' ℂ), sub_eq_iff_eq_add, neg_mul, ← sub_eq_neg_add,
- eq_sub_iff_add_eq] at hm
+ eq_sub_iff_add_eq] at hm
exact ⟨m, by rw [← hm, mul_comm]⟩
-- At last the main proof
rw [show sin (↑π * (1 - s) / 2) = π * (Gamma ((1 - s) / 2) * Gamma (s / 2 + 1 / 2))⁻¹
by
have := congr_arg Inv.inv (Complex.Gamma_mul_Gamma_one_sub ((1 - s) / 2)).symm
rwa [(by ring : 1 - (1 - s) / 2 = s / 2 + 1 / 2), inv_div,
- div_eq_iff (of_real_ne_zero.mpr pi_pos.ne'), mul_comm _ ↑π, mul_div_assoc'] at this ]
+ div_eq_iff (of_real_ne_zero.mpr pi_pos.ne'), mul_comm _ ↑π, mul_div_assoc'] at this]
rw [(by rw [← neg_sub] : (2 : ℂ) ^ (1 - s) = 2 ^ (-(s - 1))), cpow_neg, h_Ga_eq]
suffices (π : ℂ) ^ ((1 - s) / 2) = π ^ (-s) * sqrt π * π ^ (s / 2) by rw [this]; field_simp;
ring_nf; rw [← of_real_pow, sq_sqrt pi_pos.le]; ring
@@ -891,8 +891,8 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
-- substitute in what we know about zeta values at positive integers
have step1 := congr_arg (coe : ℝ → ℂ) (hasSum_zeta_nat (by norm_num : m + 1 ≠ 0)).tsum_eq
have step2 := zeta_nat_eq_tsum_of_gt_one (by rw [mul_add]; norm_num : 1 < 2 * (m + 1))
- simp_rw [of_real_tsum, of_real_div, of_real_one, of_real_pow, of_real_nat_cast] at step1
- rw [step1, (by norm_cast : (↑(2 * (m + 1)) : ℂ) = 2 * ↑m + 2)] at step2
+ simp_rw [of_real_tsum, of_real_div, of_real_one, of_real_pow, of_real_nat_cast] at step1
+ rw [step1, (by norm_cast : (↑(2 * (m + 1)) : ℂ) = 2 * ↑m + 2)] at step2
rw [step2, mul_div]
-- now the rest is just a lengthy but elementary rearrangement
rw [show ((2 * (m + 1))! : ℂ) = Gamma (2 * m + 2) * (↑(2 * m + 1) + 1)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -134,7 +134,7 @@ theorem summable_exp_neg_pi_mul_nat_sq {t : ℝ} (ht : 0 < t) :
convert summable_norm_iff.mpr (hasSum_nat_jacobiTheta this).Summable
ext1 n
rw [Complex.norm_eq_abs, Complex.abs_exp]
- rw [show ↑π * I * (↑n + 1) ^ 2 * (↑t * I) = ↑(π * t * (n + 1) ^ 2) * I ^ 2 by push_cast ; ring]
+ rw [show ↑π * I * (↑n + 1) ^ 2 * (↑t * I) = ↑(π * t * (n + 1) ^ 2) * I ^ 2 by push_cast; ring]
rw [I_sq, mul_neg_one, ← of_real_neg, of_real_re, neg_mul, neg_mul]
#align summable_exp_neg_pi_mul_nat_sq summable_exp_neg_pi_mul_nat_sq
-/
@@ -297,9 +297,9 @@ theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => ex
/-- Weaker but more usable bound for `zeta_kernel₂` for `t → 0`. -/
theorem isBigO_zero_zetaKernel₂_rpow (a : ℝ) : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => t ^ a :=
by
- have aux1 : is_O at_top (fun t => exp (-π * t)) fun t => t ^ (-a - 1 / 2) :=
+ have aux1 : is_O at_top (fun t => NormedSpace.exp (-π * t)) fun t => t ^ (-a - 1 / 2) :=
(isLittleO_exp_neg_mul_rpow_atTop pi_pos _).IsBigO
- have aux2 : is_O at_top (fun t => exp (-π * t) * sqrt t) fun t => t ^ (-a) :=
+ have aux2 : is_O at_top (fun t => NormedSpace.exp (-π * t) * sqrt t) fun t => t ^ (-a) :=
by
refine' (aux1.mul (is_O_refl sqrt _)).congr' (eventually_eq.refl _ _) _
refine' (eventually_gt_at_top 0).mp (eventually_of_forall fun t ht => _)
@@ -476,7 +476,7 @@ theorem riemannZeta_neg_two_mul_nat_add_one (n : ℕ) : riemannZeta (-2 * (n + 1
have : (-2 : ℂ) * (n + 1) ≠ 0 :=
mul_ne_zero (neg_ne_zero.mpr two_ne_zero) (Nat.cast_add_one_ne_zero n)
rw [riemannZeta, Function.update_noteq this,
- show -2 * ((n : ℂ) + 1) / 2 = -↑(n + 1) by push_cast ; ring, Complex.Gamma_neg_nat_eq_zero,
+ show -2 * ((n : ℂ) + 1) / 2 = -↑(n + 1) by push_cast; ring, Complex.Gamma_neg_nat_eq_zero,
div_zero]
#align riemann_zeta_neg_two_mul_nat_add_one riemannZeta_neg_two_mul_nat_add_one
-/
@@ -551,7 +551,7 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
by
have : 1 / 2 < (s / 2).re :=
by
- rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast ; rw [mul_comm]; rfl]
+ rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
rwa [of_real_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
rw [riemannCompletedZeta, riemannCompletedZeta₀, mellin_zetaKernel₂_eq_of_lt_re this, sub_add,
sub_sub, ← add_sub]
@@ -598,8 +598,8 @@ theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ)
theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
mellin zetaKernel₁ s = π ^ (-s) * Gamma s * ∑' n : ℕ, 1 / (n + 1) ^ (2 * s) :=
by
- let bd : ℕ → ℝ → ℝ := fun n t => t ^ (s.re - 1) * exp (-π * t * (n + 1) ^ 2)
- let f : ℕ → ℝ → ℂ := fun n t => t ^ (s - 1) * exp (-π * t * (n + 1) ^ 2)
+ let bd : ℕ → ℝ → ℝ := fun n t => t ^ (s.re - 1) * NormedSpace.exp (-π * t * (n + 1) ^ 2)
+ let f : ℕ → ℝ → ℂ := fun n t => t ^ (s - 1) * NormedSpace.exp (-π * t * (n + 1) ^ 2)
have hm : MeasurableSet (Ioi (0 : ℝ)) := measurableSet_Ioi
have h_norm : ∀ (n : ℕ) {t : ℝ} (ht : 0 < t), ‖f n t‖ = bd n t :=
by
@@ -656,7 +656,7 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
by
rw [completed_zeta_eq_mellin_of_one_lt_re hs, mellin_zetaKernel₁_eq_tsum, neg_div,
mul_div_cancel' _ (two_ne_zero' ℂ)]
- rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast ; rw [mul_comm]; rfl]
+ rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
rwa [of_real_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
#align completed_zeta_eq_tsum_of_one_lt_re completed_zeta_eq_tsum_of_one_lt_re
-/
@@ -824,7 +824,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
have : (1 - (1 + 2 * (n : ℂ))) / 2 = -↑n := by
rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left _ (two_ne_zero' ℂ)]
rw [this, Complex.Gamma_neg_nat_eq_zero, div_zero]
- have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast ; field_simp; ring
+ have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast; field_simp; ring
rw [this, Complex.sin_int_mul_pi, MulZeroClass.mul_zero, MulZeroClass.zero_mul]
have h_Ga_ne4 : Gamma ((1 - s) / 2) ≠ 0 :=
by
@@ -869,7 +869,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
zero_div]
· -- k = 2 * m + 1 : the interesting case
rw [Odd.neg_one_pow ⟨m, rfl⟩]
- rw [show -(↑(2 * m + 1) : ℂ) = 1 - (2 * m + 2) by push_cast ; ring]
+ rw [show -(↑(2 * m + 1) : ℂ) = 1 - (2 * m + 2) by push_cast; ring]
rw [riemannZeta_one_sub]
rotate_left
· intro n
@@ -885,9 +885,9 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [Complex.sin_pi_div_two_sub, Complex.cos_add_pi, neg_inj]
rcases Nat.even_or_odd' m with ⟨t, rfl | rfl⟩
· rw [pow_mul, neg_one_sq, one_pow]
- convert Complex.cos_nat_mul_two_pi t using 2; push_cast ; ring
+ convert Complex.cos_nat_mul_two_pi t using 2; push_cast; ring
· rw [pow_add, pow_one, pow_mul, neg_one_sq, one_pow, one_mul]
- convert Complex.cos_nat_mul_two_pi_add_pi t using 2; push_cast ; ring]
+ convert Complex.cos_nat_mul_two_pi_add_pi t using 2; push_cast; ring]
-- substitute in what we know about zeta values at positive integers
have step1 := congr_arg (coe : ℝ → ℂ) (hasSum_zeta_nat (by norm_num : m + 1 ≠ 0)).tsum_eq
have step2 := zeta_nat_eq_tsum_of_gt_one (by rw [mul_add]; norm_num : 1 < 2 * (m + 1))
@@ -897,10 +897,10 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
-- now the rest is just a lengthy but elementary rearrangement
rw [show ((2 * (m + 1))! : ℂ) = Gamma (2 * m + 2) * (↑(2 * m + 1) + 1)
by
- rw [(by push_cast ; ring : (2 * m + 2 : ℂ) = ↑(2 * m + 1) + 1),
+ rw [(by push_cast; ring : (2 * m + 2 : ℂ) = ↑(2 * m + 1) + 1),
Complex.Gamma_nat_eq_factorial, (by ring : 2 * (m + 1) = 2 * m + 1 + 1),
Nat.factorial_succ, Nat.cast_mul, mul_comm]
- push_cast ]
+ push_cast]
rw [← div_div, neg_one_mul]
congr 1
rw [div_eq_iff (Gamma_ne_zero_of_re_pos _)]
@@ -920,7 +920,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
congr 1
rw [Nat.add_sub_assoc one_le_two, Nat.cast_add, Nat.cast_mul, Nat.cast_two,
(by norm_num : 2 - 1 = 1)]
- push_cast ; ring]
+ push_cast; ring]
rw [show (π : ℂ) ^ (-(2 * (m : ℂ) + 2)) = (↑(π ^ (2 * m + 2)))⁻¹ by
rw [of_real_pow, ← cpow_nat_cast, ← cpow_neg, Nat.cast_add, Nat.cast_mul, Nat.cast_two]]
rw [(by intros; ring : ∀ a b c d e : ℂ, a * b * c * d * e = a * d * (b * e) * c)]
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,9 +3,9 @@ Copyright (c) 2023 David Loeffler. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
-/
-import Mathbin.Analysis.SpecialFunctions.Gamma.Beta
-import Mathbin.NumberTheory.ModularForms.JacobiTheta.Basic
-import Mathbin.NumberTheory.ZetaValues
+import Analysis.SpecialFunctions.Gamma.Beta
+import NumberTheory.ModularForms.JacobiTheta.Basic
+import NumberTheory.ZetaValues
#align_import number_theory.zeta_function from "leanprover-community/mathlib"@"d0b1936853671209a866fa35b9e54949c81116e2"
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -624,7 +624,7 @@ theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
by
intro t ht
have :=
- (has_sum_of_real.mpr (summable_exp_neg_pi_mul_nat_sq ht).HasSum).mul_left ((t : ℂ) ^ (s - 1))
+ (has_sum_of_real.mpr (summable_exp_neg_pi_mul_nat_sq ht).HasSum).hMul_left ((t : ℂ) ^ (s - 1))
simpa only [of_real_mul, ← mul_assoc, of_real_bit0, of_real_one, mul_comm _ (2 : ℂ),
of_real_sub, of_real_one, of_real_tsum] using this
have h_sum' :
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,16 +2,13 @@
Copyright (c) 2023 David Loeffler. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
-
-! This file was ported from Lean 3 source module number_theory.zeta_function
-! leanprover-community/mathlib commit d0b1936853671209a866fa35b9e54949c81116e2
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.Analysis.SpecialFunctions.Gamma.Beta
import Mathbin.NumberTheory.ModularForms.JacobiTheta.Basic
import Mathbin.NumberTheory.ZetaValues
+#align_import number_theory.zeta_function from "leanprover-community/mathlib"@"d0b1936853671209a866fa35b9e54949c81116e2"
+
/-!
# Definition of the Riemann zeta function
mathlib commit https://github.com/leanprover-community/mathlib/commit/728ef9dbb281241906f25cbeb30f90d83e0bb451
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
! This file was ported from Lean 3 source module number_theory.zeta_function
-! leanprover-community/mathlib commit 57f9349f2fe19d2de7207e99b0341808d977cdcf
+! leanprover-community/mathlib commit d0b1936853671209a866fa35b9e54949c81116e2
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -15,6 +15,9 @@ import Mathbin.NumberTheory.ZetaValues
/-!
# Definition of the Riemann zeta function
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
## Main definitions:
* `riemann_zeta`: the Riemann zeta function `ζ : ℂ → ℂ`.
mathlib commit https://github.com/leanprover-community/mathlib/commit/8b981918a93bc45a8600de608cde7944a80d92b9
@@ -72,33 +72,44 @@ noncomputable section
-/
+#print zetaKernel₁ /-
/-- Function whose Mellin transform is `π ^ (-s) * Γ(s) * zeta (2 * s)`, for `1 / 2 < Re s`. -/
def zetaKernel₁ (t : ℝ) : ℂ :=
∑' n : ℕ, rexp (-π * t * (n + 1) ^ 2)
#align zeta_kernel₁ zetaKernel₁
+-/
+#print zetaKernel₂ /-
/-- Modified zeta kernel, whose Mellin transform is entire. --/
def zetaKernel₂ : ℝ → ℂ :=
zetaKernel₁ + indicator (Ioc 0 1) fun t => (1 - 1 / sqrt t) / 2
#align zeta_kernel₂ zetaKernel₂
+-/
+#print riemannCompletedZeta₀ /-
/-- The completed Riemann zeta function with its poles removed, `Λ(s) + 1 / s - 1 / (s - 1)`. -/
def riemannCompletedZeta₀ (s : ℂ) : ℂ :=
mellin zetaKernel₂ (s / 2)
#align riemann_completed_zeta₀ riemannCompletedZeta₀
+-/
+#print riemannCompletedZeta /-
/-- The completed Riemann zeta function, `Λ(s)`, which satisfies
`Λ(s) = π ^ (-s / 2) Γ(s / 2) ζ(s)` (up to a minor correction at `s = 0`). -/
def riemannCompletedZeta (s : ℂ) : ℂ :=
riemannCompletedZeta₀ s - 1 / s + 1 / (s - 1)
#align riemann_completed_zeta riemannCompletedZeta
+-/
+#print riemannZeta /-
/-- The Riemann zeta function `ζ(s)`. We set this to be irreducible to hide messy implementation
details. -/
irreducible_def riemannZeta :=
Function.update (fun s : ℂ => ↑π ^ (s / 2) * riemannCompletedZeta s / Gamma (s / 2)) 0 (-1 / 2)
#align riemann_zeta riemannZeta
+-/
+#print riemannZeta_zero /-
/- Note the next lemma is true by definition; what's hard is to show that with this definition, `ζ`
is continuous (and indeed analytic) at 0, see `differentiable_riemann_zeta` below. -/
/-- We have `ζ(0) = -1 / 2`. -/
@@ -107,12 +118,14 @@ theorem riemannZeta_zero : riemannZeta 0 = -1 / 2 :=
unfold riemannZeta
exact Function.update_same _ _ _
#align riemann_zeta_zero riemannZeta_zero
+-/
/-!
## First properties of the zeta kernels
-/
+#print summable_exp_neg_pi_mul_nat_sq /-
/-- The sum defining `zeta_kernel₁` is convergent. -/
theorem summable_exp_neg_pi_mul_nat_sq {t : ℝ} (ht : 0 < t) :
Summable fun n : ℕ => rexp (-π * t * (n + 1) ^ 2) :=
@@ -124,7 +137,9 @@ theorem summable_exp_neg_pi_mul_nat_sq {t : ℝ} (ht : 0 < t) :
rw [show ↑π * I * (↑n + 1) ^ 2 * (↑t * I) = ↑(π * t * (n + 1) ^ 2) * I ^ 2 by push_cast ; ring]
rw [I_sq, mul_neg_one, ← of_real_neg, of_real_re, neg_mul, neg_mul]
#align summable_exp_neg_pi_mul_nat_sq summable_exp_neg_pi_mul_nat_sq
+-/
+#print zetaKernel₁_eq_jacobiTheta /-
/-- Relate `zeta_kernel₁` to the Jacobi theta function on `ℍ`. (We don't use this as the definition
of `zeta_kernel₁`, since the sum over `ℕ` rather than `ℤ` is more convenient for relating zeta to
the Dirichlet series for `re s > 1`.) -/
@@ -137,7 +152,9 @@ theorem zetaKernel₁_eq_jacobiTheta {t : ℝ} (ht : 0 < t) :
push_cast
rw [(by ring : ↑π * I * (n + 1) ^ 2 * (t * I) = I ^ 2 * π * t * (n + 1) ^ 2), I_sq, neg_one_mul]
#align zeta_kernel₁_eq_jacobi_theta zetaKernel₁_eq_jacobiTheta
+-/
+#print continuousAt_zetaKernel₁ /-
/-- Continuity of `zeta_kernel₁`. -/
theorem continuousAt_zetaKernel₁ {t : ℝ} (ht : 0 < t) : ContinuousAt zetaKernel₁ t :=
by
@@ -150,13 +167,17 @@ theorem continuousAt_zetaKernel₁ {t : ℝ} (ht : 0 < t) : ContinuousAt zetaKer
refine' this.congr (eventually_of_mem (Ioi_mem_nhds ht) fun u hu => _)
rw [zetaKernel₁_eq_jacobiTheta hu]
#align continuous_at_zeta_kernel₁ continuousAt_zetaKernel₁
+-/
+#print locally_integrable_zetaKernel₁ /-
/-- Local integrability of `zeta_kernel₁`. -/
theorem locally_integrable_zetaKernel₁ : LocallyIntegrableOn zetaKernel₁ (Ioi 0) :=
(ContinuousAt.continuousOn fun t ht => continuousAt_zetaKernel₁ ht).LocallyIntegrableOn
measurableSet_Ioi
#align locally_integrable_zeta_kernel₁ locally_integrable_zetaKernel₁
+-/
+#print locally_integrable_zetaKernel₂ /-
/-- Local integrability of `zeta_kernel₂`. -/
theorem locally_integrable_zetaKernel₂ : LocallyIntegrableOn zetaKernel₂ (Ioi 0) :=
by
@@ -176,7 +197,9 @@ theorem locally_integrable_zetaKernel₂ : LocallyIntegrableOn zetaKernel₂ (Io
· exact (continuous_of_real.comp continuous_sqrt).ContinuousOn
exact of_real_ne_zero.mpr (sqrt_ne_zero'.mpr hx)
#align locally_integrable_zeta_kernel₂ locally_integrable_zetaKernel₂
+-/
+#print zetaKernel₂_one_div /-
/-- Functional equation for `zeta_kernel₂`. -/
theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) : zetaKernel₂ (1 / t) = sqrt t * zetaKernel₂ t :=
by
@@ -207,6 +230,7 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) : zetaKernel₂ (1 / t) = s
rw [this, ← mul_assoc, ← of_real_mul, ← sqrt_mul ht.le, mul_one_div_cancel ht.ne', sqrt_one,
of_real_one, one_mul]
#align zeta_kernel₂_one_div zetaKernel₂_one_div
+-/
/-!
## Bounds for zeta kernels
@@ -216,6 +240,7 @@ show holomorphy of their Mellin transforms (for `1 / 2 < re s` for `zeta_kernel
`zeta_kernel₂`). -/
+#print isBigO_atTop_zetaKernel₁ /-
/-- Bound for `zeta_kernel₁` for large `t`. -/
theorem isBigO_atTop_zetaKernel₁ : IsBigO atTop zetaKernel₁ fun t => exp (-π * t) :=
by
@@ -233,7 +258,9 @@ theorem isBigO_atTop_zetaKernel₁ : IsBigO atTop zetaKernel₁ fun t => exp (-
· rw [Function.comp_apply, ← zetaKernel₁_eq_jacobiTheta ht]
· rw [Function.comp_apply, mul_I_im, of_real_re]
#align is_O_at_top_zeta_kernel₁ isBigO_atTop_zetaKernel₁
+-/
+#print isBigO_atTop_zetaKernel₂ /-
/-- Bound for `zeta_kernel₂` for large `t`. -/
theorem isBigO_atTop_zetaKernel₂ : IsBigO atTop zetaKernel₂ fun t => exp (-π * t) :=
by
@@ -242,7 +269,9 @@ theorem isBigO_atTop_zetaKernel₂ : IsBigO atTop zetaKernel₂ fun t => exp (-
isBigO_atTop_zetaKernel₁
rw [zetaKernel₂, Pi.add_apply, indicator_of_not_mem (not_mem_Ioc_of_gt ht), add_zero]
#align is_O_at_top_zeta_kernel₂ isBigO_atTop_zetaKernel₂
+-/
+#print isBigO_zero_zetaKernel₂ /-
/-- Precise but awkward-to-use bound for `zeta_kernel₂` for `t → 0`. -/
theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => exp (-π / t) / sqrt t :=
by
@@ -262,7 +291,9 @@ theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => ex
rw [Function.comp_apply, mul_one_div, one_div ↑(sqrt _), ← of_real_inv, IsROrC.norm_ofReal,
abs_inv, abs_of_nonneg (sqrt_nonneg _), ← div_eq_mul_inv]
#align is_O_zero_zeta_kernel₂ isBigO_zero_zetaKernel₂
+-/
+#print isBigO_zero_zetaKernel₂_rpow /-
/-- Weaker but more usable bound for `zeta_kernel₂` for `t → 0`. -/
theorem isBigO_zero_zetaKernel₂_rpow (a : ℝ) : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => t ^ a :=
by
@@ -279,7 +310,9 @@ theorem isBigO_zero_zetaKernel₂_rpow (a : ℝ) : IsBigO (𝓝[>] 0) zetaKernel
· refine' eventually_of_mem self_mem_nhdsWithin fun x hx => _
simp_rw [Function.comp_apply, inv_rpow (le_of_lt hx), rpow_neg (le_of_lt hx), inv_inv]
#align is_O_zero_zeta_kernel₂_rpow isBigO_zero_zetaKernel₂_rpow
+-/
+#print isBigO_zero_zetaKernel₁ /-
/-- Bound for `zeta_kernel₁` for `t → 0`. -/
theorem isBigO_zero_zetaKernel₁ : IsBigO (𝓝[>] 0) zetaKernel₁ fun t => t ^ (-(1 / 2) : ℝ) :=
by
@@ -306,30 +339,38 @@ theorem isBigO_zero_zetaKernel₁ : IsBigO (𝓝[>] 0) zetaKernel₁ fun t => t
rw [norm_of_nonneg (rpow_nonneg_of_nonneg ht.1.le _), rpow_neg ht.1.le]
exact one_le_inv (rpow_pos_of_pos ht.1 _) (rpow_le_one ht.1.le ht.2 one_half_pos.le)
#align is_O_zero_zeta_kernel₁ isBigO_zero_zetaKernel₁
+-/
/-!
## Differentiability of the completed zeta function
-/
+#print differentiableAt_mellin_zetaKernel₁ /-
/-- The Mellin transform of the first zeta kernel is holomorphic for `1 / 2 < re s`. -/
theorem differentiableAt_mellin_zetaKernel₁ {s : ℂ} (hs : 1 / 2 < s.re) :
DifferentiableAt ℂ (mellin zetaKernel₁) s :=
mellin_differentiableAt_of_isBigO_rpow_exp pi_pos locally_integrable_zetaKernel₁
isBigO_atTop_zetaKernel₁ isBigO_zero_zetaKernel₁ hs
#align differentiable_at_mellin_zeta_kernel₁ differentiableAt_mellin_zetaKernel₁
+-/
+#print differentiable_mellin_zetaKernel₂ /-
/-- The Mellin transform of the second zeta kernel is entire. -/
theorem differentiable_mellin_zetaKernel₂ : Differentiable ℂ (mellin zetaKernel₂) := fun s =>
mellin_differentiableAt_of_isBigO_rpow_exp pi_pos locally_integrable_zetaKernel₂
isBigO_atTop_zetaKernel₂ (isBigO_zero_zetaKernel₂_rpow _) ((sub_lt_self_iff _).mpr zero_lt_one)
#align differentiable_mellin_zeta_kernel₂ differentiable_mellin_zetaKernel₂
+-/
+#print differentiable_completed_zeta₀ /-
/-- The modified completed Riemann zeta function `Λ(s) + 1 / s - 1 / (s - 1)` is entire. -/
theorem differentiable_completed_zeta₀ : Differentiable ℂ riemannCompletedZeta₀ :=
differentiable_mellin_zetaKernel₂.comp (Differentiable.div_const differentiable_id 2)
#align differentiable_completed_zeta₀ differentiable_completed_zeta₀
+-/
+#print differentiableAt_completed_zeta /-
/-- The completed Riemann zeta function `Λ(s)` is differentiable away from `s = 0` and `s = 1`
(where it has simple poles). -/
theorem differentiableAt_completed_zeta {s : ℂ} (hs : s ≠ 0) (hs' : s ≠ 1) :
@@ -340,7 +381,9 @@ theorem differentiableAt_completed_zeta {s : ℂ} (hs : s ≠ 0) (hs' : s ≠ 1)
· refine' (differentiable_const _).DifferentiableAt.div _ (sub_ne_zero.mpr hs')
exact differentiable_at_id.sub (differentiableAt_const _)
#align differentiable_at_completed_zeta differentiableAt_completed_zeta
+-/
+#print differentiableAt_riemannZeta /-
/-- The Riemann zeta function is differentiable away from `s = 1`. -/
theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableAt ℂ riemannZeta s :=
by
@@ -424,7 +467,9 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
· exact tendsto.congr (fun x => by rw [← one_div, one_div_one_div]) nhdsWithin_le_nhds
· exact eventually_of_mem self_mem_nhdsWithin fun x hx hx' => (hx <| inv_eq_zero.mp hx').elim
#align differentiable_at_riemann_zeta differentiableAt_riemannZeta
+-/
+#print riemannZeta_neg_two_mul_nat_add_one /-
/-- The trivial zeroes of the zeta function. -/
theorem riemannZeta_neg_two_mul_nat_add_one (n : ℕ) : riemannZeta (-2 * (n + 1)) = 0 :=
by
@@ -434,18 +479,22 @@ theorem riemannZeta_neg_two_mul_nat_add_one (n : ℕ) : riemannZeta (-2 * (n + 1
show -2 * ((n : ℂ) + 1) / 2 = -↑(n + 1) by push_cast ; ring, Complex.Gamma_neg_nat_eq_zero,
div_zero]
#align riemann_zeta_neg_two_mul_nat_add_one riemannZeta_neg_two_mul_nat_add_one
+-/
+#print RiemannHypothesis /-
/-- A formal statement of the Riemann hypothesis – constructing a term of this type is worth a
million dollars. -/
def RiemannHypothesis : Prop :=
∀ (s : ℂ) (hs : riemannCompletedZeta s = 0) (hs' : ¬∃ n : ℕ, s = -2 * (n + 1)), s.re = 1 / 2
#align riemann_hypothesis RiemannHypothesis
+-/
/-!
## Relating the Mellin transforms of the two zeta kernels
-/
+#print hasMellin_one_div_sqrt_Ioc /-
theorem hasMellin_one_div_sqrt_Ioc {s : ℂ} (hs : 1 / 2 < re s) :
HasMellin (indicator (Ioc 0 1) (fun t => 1 / ↑(sqrt t) : ℝ → ℂ)) s (1 / (s - 1 / 2)) :=
by
@@ -458,7 +507,9 @@ theorem hasMellin_one_div_sqrt_Ioc {s : ℂ} (hs : 1 / 2 < re s) :
convert hasMellin_cpow_Ioc (-1 / 2) _
rwa [(by push_cast : (-1 / 2 : ℂ) = (-1 / 2 : ℝ)), of_real_re, neg_div, ← sub_eq_add_neg, sub_pos]
#align has_mellin_one_div_sqrt_Ioc hasMellin_one_div_sqrt_Ioc
+-/
+#print hasMellin_one_div_sqrt_sub_one_div_two_Ioc /-
/-- Evaluate the Mellin transform of the "fudge factor" in `zeta_kernel₂` -/
theorem hasMellin_one_div_sqrt_sub_one_div_two_Ioc {s : ℂ} (hs : 1 / 2 < s.re) :
HasMellin ((Ioc 0 1).indicator fun t => (1 - 1 / (sqrt t : ℂ)) / 2) s
@@ -480,7 +531,9 @@ theorem hasMellin_one_div_sqrt_sub_one_div_two_Ioc {s : ℂ} (hs : 1 / 2 < s.re)
refine' ⟨step1.1.div_const _, _⟩
rw [mul_comm, sub_mul, div_mul_cancel _ (two_ne_zero' ℂ), mul_comm s 2]
#align has_mellin_one_div_sqrt_sub_one_div_two_Ioc hasMellin_one_div_sqrt_sub_one_div_two_Ioc
+-/
+#print mellin_zetaKernel₂_eq_of_lt_re /-
theorem mellin_zetaKernel₂_eq_of_lt_re {s : ℂ} (hs : 1 / 2 < s.re) :
mellin zetaKernel₂ s = mellin zetaKernel₁ s + 1 / (2 * s) - 1 / (2 * s - 1) :=
by
@@ -490,7 +543,9 @@ theorem mellin_zetaKernel₂_eq_of_lt_re {s : ℂ} (hs : 1 / 2 < s.re) :
have h' := hasMellin_one_div_sqrt_sub_one_div_two_Ioc hs
simp_rw [zetaKernel₂, Pi.add_def, add_sub_assoc, (hasMellin_add h h'.1).2, h'.2]
#align mellin_zeta_kernel₂_eq_of_lt_re mellin_zetaKernel₂_eq_of_lt_re
+-/
+#print completed_zeta_eq_mellin_of_one_lt_re /-
theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
riemannCompletedZeta s = mellin zetaKernel₁ (s / 2) :=
by
@@ -505,12 +560,14 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
rw [mul_div_cancel' _ (two_ne_zero' ℂ)]
abel
#align completed_zeta_eq_mellin_of_one_lt_re completed_zeta_eq_mellin_of_one_lt_re
+-/
/-!
## Relating the first zeta kernel to the Dirichlet series
-/
+#print integral_cpow_mul_exp_neg_pi_mul_sq /-
/-- Auxiliary lemma for `mellin_zeta_kernel₁_eq_tsum`, computing the Mellin transform of an
individual term in the series. -/
theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ) :
@@ -535,7 +592,9 @@ theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ)
conv_rhs => rw [← Nat.cast_two, rpow_nat_cast]
ring
#align integral_cpow_mul_exp_neg_pi_mul_sq integral_cpow_mul_exp_neg_pi_mul_sq
+-/
+#print mellin_zetaKernel₁_eq_tsum /-
theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
mellin zetaKernel₁ s = π ^ (-s) * Gamma s * ∑' n : ℕ, 1 / (n + 1) ^ (2 * s) :=
by
@@ -589,7 +648,9 @@ theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
simpa only [integral_cpow_mul_exp_neg_pi_mul_sq (one_half_pos.trans hs), tsum_mul_left] using
(has_sum_integral_of_dominated_convergence bd hf_meas h_le h_sum h_int h_sum').tsum_eq.symm
#align mellin_zeta_kernel₁_eq_tsum mellin_zetaKernel₁_eq_tsum
+-/
+#print completed_zeta_eq_tsum_of_one_lt_re /-
theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
riemannCompletedZeta s = π ^ (-s / 2) * Gamma (s / 2) * ∑' n : ℕ, 1 / (n + 1) ^ s :=
by
@@ -598,7 +659,9 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast ; rw [mul_comm]; rfl]
rwa [of_real_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
#align completed_zeta_eq_tsum_of_one_lt_re completed_zeta_eq_tsum_of_one_lt_re
+-/
+#print zeta_eq_tsum_one_div_nat_add_one_cpow /-
/-- The Riemann zeta function agrees with the naive Dirichlet-series definition when the latter
converges. (Note that this is false without the assumption: when `re s ≤ 1` the sum is divergent,
and we use a different definition to obtain the analytic continuation to all `s`.) -/
@@ -614,7 +677,9 @@ theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) :
· rw [Ne.def, cpow_eq_zero_iff, not_and_or, ← Ne.def, of_real_ne_zero]
exact Or.inl pi_pos.ne'
#align zeta_eq_tsum_one_div_nat_add_one_cpow zeta_eq_tsum_one_div_nat_add_one_cpow
+-/
+#print zeta_eq_tsum_one_div_nat_cpow /-
/-- Alternate formulation of `zeta_eq_tsum_one_div_nat_add_one_cpow` without the `+ 1`, using the
fact that for `s ≠ 0` we define `0 ^ s = 0`. -/
theorem zeta_eq_tsum_one_div_nat_cpow {s : ℂ} (hs : 1 < re s) :
@@ -631,7 +696,9 @@ theorem zeta_eq_tsum_one_div_nat_cpow {s : ℂ} (hs : 1 < re s) :
summable_one_div_nat_rpow]
assumption
#align zeta_eq_tsum_one_div_nat_cpow zeta_eq_tsum_one_div_nat_cpow
+-/
+#print zeta_nat_eq_tsum_of_gt_one /-
/-- Special case of `zeta_eq_tsum_one_div_nat_cpow` when the argument is in `ℕ`, so the power
function can be expressed using naïve `pow` rather than `cpow`. -/
theorem zeta_nat_eq_tsum_of_gt_one {k : ℕ} (hk : 1 < k) : riemannZeta k = ∑' n : ℕ, 1 / n ^ k := by
@@ -639,7 +706,9 @@ theorem zeta_nat_eq_tsum_of_gt_one {k : ℕ} (hk : 1 < k) : riemannZeta k = ∑'
(by rwa [← of_real_nat_cast, of_real_re, ← Nat.cast_one, Nat.cast_lt] : 1 < re k),
cpow_nat_cast]
#align zeta_nat_eq_tsum_of_gt_one zeta_nat_eq_tsum_of_gt_one
+-/
+#print riemannZeta_two_mul_nat /-
/-- Explicit formula for `ζ (2 * k)`, for `k ∈ ℕ` with `k ≠ 0`: we have
`ζ (2 * k) = (-1) ^ (k + 1) * 2 ^ (2 * k - 1) * π ^ (2 * k) * bernoulli (2 * k) / (2 * k)!`.
Compare `has_sum_zeta_nat` for a version formulated explicitly as a sum, and
@@ -657,7 +726,9 @@ theorem riemannZeta_two_mul_nat {k : ℕ} (hk : k ≠ 0) :
rwa [mul_le_mul_left (zero_lt_two' ℕ), Nat.one_le_iff_ne_zero]
· push_cast
#align riemann_zeta_two_mul_nat riemannZeta_two_mul_nat
+-/
+#print riemannZeta_two /-
theorem riemannZeta_two : riemannZeta 2 = π ^ 2 / 6 :=
by
convert congr_arg coe has_sum_zeta_two.tsum_eq
@@ -665,7 +736,9 @@ theorem riemannZeta_two : riemannZeta 2 = π ^ 2 / 6 :=
push_cast
· push_cast
#align riemann_zeta_two riemannZeta_two
+-/
+#print riemannZeta_four /-
theorem riemannZeta_four : riemannZeta 4 = π ^ 4 / 90 :=
by
convert congr_arg coe has_sum_zeta_four.tsum_eq
@@ -674,12 +747,14 @@ theorem riemannZeta_four : riemannZeta 4 = π ^ 4 / 90 :=
push_cast
· push_cast
#align riemann_zeta_four riemannZeta_four
+-/
/-!
## Functional equation
-/
+#print riemannCompletedZeta₀_one_sub /-
/-- Riemann zeta functional equation, formulated for `Λ₀`: for any complex `s` we have
`Λ₀(1 - s) = Λ₀ s`. -/
theorem riemannCompletedZeta₀_one_sub (s : ℂ) :
@@ -696,7 +771,9 @@ theorem riemannCompletedZeta₀_one_sub (s : ℂ) :
push_cast
ring
#align riemann_completed_zeta₀_one_sub riemannCompletedZeta₀_one_sub
+-/
+#print riemannCompletedZeta_one_sub /-
/-- Riemann zeta functional equation, formulated for `Λ`: for any complex `s` we have
`Λ (1 - s) = Λ s`. -/
theorem riemannCompletedZeta_one_sub (s : ℂ) :
@@ -704,7 +781,9 @@ theorem riemannCompletedZeta_one_sub (s : ℂ) :
simp_rw [riemannCompletedZeta, riemannCompletedZeta₀_one_sub, sub_add, (by abel : 1 - s - 1 = -s),
(by abel : 1 - s = -(s - 1)), div_neg, neg_sub_neg]
#align riemann_completed_zeta_one_sub riemannCompletedZeta_one_sub
+-/
+#print riemannZeta_one_sub /-
/-- Riemann zeta functional equation, formulated for `ζ`: if `1 - s ∉ ℕ`, then we have
`ζ (1 - s) = 2 ^ (1 - s) * π ^ (-s) * Γ s * sin (π * (1 - s) / 2) * ζ s`. -/
theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠ 1) :
@@ -770,7 +849,9 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
field_simp
ring
#align riemann_zeta_one_sub riemannZeta_one_sub
+-/
+#print riemannZeta_neg_nat_eq_bernoulli /-
theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
riemannZeta (-k) = (-1) ^ k * bernoulli (k + 1) / (k + 1) :=
by
@@ -846,4 +927,5 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [inv_mul_cancel (of_real_ne_zero.mpr <| pow_ne_zero _ pi_pos.ne'),
inv_mul_cancel (of_real_ne_zero.mpr <| pow_ne_zero _ two_ne_zero), one_mul, one_mul]
#align riemann_zeta_neg_nat_eq_bernoulli riemannZeta_neg_nat_eq_bernoulli
+-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/8b981918a93bc45a8600de608cde7944a80d92b9
@@ -192,7 +192,7 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) : zetaKernel₂ (1 / t) = s
one_div_one_div, mul_sub, mul_one]
congr 2
let τ : UpperHalfPlane := ⟨u * I, (mul_I_im u).symm ▸ zero_lt_one.trans hu⟩
- convert jacobiTheta_s_smul τ using 2
+ convert jacobiTheta_S_smul τ using 2
·
rw [UpperHalfPlane.modular_S_smul, UpperHalfPlane.coe_mk, Subtype.coe_mk, ← neg_inv, mul_inv,
inv_I, mul_neg, neg_neg, one_div, of_real_inv]
mathlib commit https://github.com/leanprover-community/mathlib/commit/8b981918a93bc45a8600de608cde7944a80d92b9
@@ -194,7 +194,7 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) : zetaKernel₂ (1 / t) = s
let τ : UpperHalfPlane := ⟨u * I, (mul_I_im u).symm ▸ zero_lt_one.trans hu⟩
convert jacobiTheta_s_smul τ using 2
·
- rw [UpperHalfPlane.modular_s_smul, UpperHalfPlane.coe_mk, Subtype.coe_mk, ← neg_inv, mul_inv,
+ rw [UpperHalfPlane.modular_S_smul, UpperHalfPlane.coe_mk, Subtype.coe_mk, ← neg_inv, mul_inv,
inv_I, mul_neg, neg_neg, one_div, of_real_inv]
· rw [Subtype.coe_mk, mul_comm, mul_assoc, mul_neg, I_mul_I, neg_neg, mul_one, sqrt_eq_rpow,
of_real_cpow (zero_lt_one.trans hu).le]
mathlib commit https://github.com/leanprover-community/mathlib/commit/8b981918a93bc45a8600de608cde7944a80d92b9
@@ -720,18 +720,18 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
exact Or.inl two_ne_zero
have h_Ga_ne1 : Gamma (s / 2) ≠ 0 :=
by
- rw [Ne.def, Complex.gamma_eq_zero_iff]
+ rw [Ne.def, Complex.Gamma_eq_zero_iff]
contrapose! hs
obtain ⟨m, hm⟩ := hs
rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
exact ⟨m * 2, by rw [hm]⟩
have h_Ga_eq : Gamma s = Gamma (s / 2) * Gamma ((s + 1) / 2) * 2 ^ (s - 1) / sqrt π := by
- rw [add_div, Complex.gamma_mul_gamma_add_half, mul_div_cancel' _ (two_ne_zero' ℂ),
+ rw [add_div, Complex.Gamma_mul_Gamma_add_half, mul_div_cancel' _ (two_ne_zero' ℂ),
(by ring : 1 - s = -(s - 1)), cpow_neg, ← div_eq_mul_inv, eq_div_iff h_sqrt,
div_mul_eq_mul_div₀, div_mul_cancel _ h_pow]
have h_Ga_ne3 : Gamma ((s + 1) / 2) ≠ 0 :=
by
- have h_Ga_aux : Gamma s ≠ 0 := Complex.gamma_ne_zero hs
+ have h_Ga_aux : Gamma s ≠ 0 := Complex.Gamma_ne_zero hs
contrapose! h_Ga_aux
rw [h_Ga_eq, h_Ga_aux, MulZeroClass.mul_zero, MulZeroClass.zero_mul, zero_div]
rw [riemannZeta, Function.update_noteq (by rwa [sub_ne_zero, ne_comm] : 1 - s ≠ 0),
@@ -749,7 +749,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
rw [this, Complex.sin_int_mul_pi, MulZeroClass.mul_zero, MulZeroClass.zero_mul]
have h_Ga_ne4 : Gamma ((1 - s) / 2) ≠ 0 :=
by
- rw [Ne.def, Complex.gamma_eq_zero_iff]
+ rw [Ne.def, Complex.Gamma_eq_zero_iff]
contrapose! hs_pos_odd
obtain ⟨m, hm⟩ := hs_pos_odd
rw [div_eq_iff (two_ne_zero' ℂ), sub_eq_iff_eq_add, neg_mul, ← sub_eq_neg_add,
@@ -758,7 +758,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
-- At last the main proof
rw [show sin (↑π * (1 - s) / 2) = π * (Gamma ((1 - s) / 2) * Gamma (s / 2 + 1 / 2))⁻¹
by
- have := congr_arg Inv.inv (Complex.gamma_mul_gamma_one_sub ((1 - s) / 2)).symm
+ have := congr_arg Inv.inv (Complex.Gamma_mul_Gamma_one_sub ((1 - s) / 2)).symm
rwa [(by ring : 1 - (1 - s) / 2 = s / 2 + 1 / 2), inv_div,
div_eq_iff (of_real_ne_zero.mpr pi_pos.ne'), mul_comm _ ↑π, mul_div_assoc'] at this ]
rw [(by rw [← neg_sub] : (2 : ℂ) ^ (1 - s) = 2 ^ (-(s - 1))), cpow_neg, h_Ga_eq]
mathlib commit https://github.com/leanprover-community/mathlib/commit/93f880918cb51905fd51b76add8273cbc27718ab
@@ -4,12 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
! This file was ported from Lean 3 source module number_theory.zeta_function
-! leanprover-community/mathlib commit 81843c08659063f91486be95a617b5e9ec93c9da
+! leanprover-community/mathlib commit 57f9349f2fe19d2de7207e99b0341808d977cdcf
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Analysis.SpecialFunctions.Gamma.Beta
-import Mathbin.NumberTheory.ModularForms.JacobiTheta
+import Mathbin.NumberTheory.ModularForms.JacobiTheta.Basic
import Mathbin.NumberTheory.ZetaValues
/-!
mathlib commit https://github.com/leanprover-community/mathlib/commit/2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
@@ -96,7 +96,7 @@ def riemannCompletedZeta (s : ℂ) : ℂ :=
/-- The Riemann zeta function `ζ(s)`. We set this to be irreducible to hide messy implementation
details. -/
irreducible_def riemannZeta :=
- Function.update (fun s : ℂ => ↑π ^ (s / 2) * riemannCompletedZeta s / gamma (s / 2)) 0 (-1 / 2)
+ Function.update (fun s : ℂ => ↑π ^ (s / 2) * riemannCompletedZeta s / Gamma (s / 2)) 0 (-1 / 2)
#align riemann_zeta riemannZeta
/- Note the next lemma is true by definition; what's hard is to show that with this definition, `ζ`
@@ -417,7 +417,7 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
(fun t ht => (c1 t ht.2 ht.1).DifferentiableWithinAt) _)
0 hs').DifferentiableAt
S_nhds
- simp only [zero_div, div_zero, Complex.gamma_zero, MulZeroClass.mul_zero, cpow_zero, sub_zero]
+ simp only [zero_div, div_zero, Complex.Gamma_zero, MulZeroClass.mul_zero, cpow_zero, sub_zero]
-- Remains to show completed zeta is `o (s ^ (-1))` near 0.
refine' (is_O_const_of_tendsto c2 <| one_ne_zero' ℂ).trans_isLittleO _
rw [is_o_iff_tendsto']
@@ -431,7 +431,7 @@ theorem riemannZeta_neg_two_mul_nat_add_one (n : ℕ) : riemannZeta (-2 * (n + 1
have : (-2 : ℂ) * (n + 1) ≠ 0 :=
mul_ne_zero (neg_ne_zero.mpr two_ne_zero) (Nat.cast_add_one_ne_zero n)
rw [riemannZeta, Function.update_noteq this,
- show -2 * ((n : ℂ) + 1) / 2 = -↑(n + 1) by push_cast ; ring, Complex.gamma_neg_nat_eq_zero,
+ show -2 * ((n : ℂ) + 1) / 2 = -↑(n + 1) by push_cast ; ring, Complex.Gamma_neg_nat_eq_zero,
div_zero]
#align riemann_zeta_neg_two_mul_nat_add_one riemannZeta_neg_two_mul_nat_add_one
@@ -515,9 +515,9 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
individual term in the series. -/
theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ) :
∫ t : ℝ in Ioi 0, (t : ℂ) ^ (s - 1) * rexp (-π * t * (n + 1) ^ 2) =
- ↑π ^ (-s) * Complex.gamma s * (1 / (n + 1) ^ (2 * s)) :=
+ ↑π ^ (-s) * Complex.Gamma s * (1 / (n + 1) ^ (2 * s)) :=
by
- rw [Complex.gamma_eq_integral hs, Gamma_integral_eq_mellin]
+ rw [Complex.Gamma_eq_integral hs, Gamma_integral_eq_mellin]
conv_rhs =>
congr
rw [← smul_eq_mul, ← mellin_comp_mul_left _ _ pi_pos]
@@ -537,7 +537,7 @@ theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ)
#align integral_cpow_mul_exp_neg_pi_mul_sq integral_cpow_mul_exp_neg_pi_mul_sq
theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
- mellin zetaKernel₁ s = π ^ (-s) * gamma s * ∑' n : ℕ, 1 / (n + 1) ^ (2 * s) :=
+ mellin zetaKernel₁ s = π ^ (-s) * Gamma s * ∑' n : ℕ, 1 / (n + 1) ^ (2 * s) :=
by
let bd : ℕ → ℝ → ℝ := fun n t => t ^ (s.re - 1) * exp (-π * t * (n + 1) ^ 2)
let f : ℕ → ℝ → ℂ := fun n t => t ^ (s - 1) * exp (-π * t * (n + 1) ^ 2)
@@ -591,7 +591,7 @@ theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
#align mellin_zeta_kernel₁_eq_tsum mellin_zetaKernel₁_eq_tsum
theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
- riemannCompletedZeta s = π ^ (-s / 2) * gamma (s / 2) * ∑' n : ℕ, 1 / (n + 1) ^ s :=
+ riemannCompletedZeta s = π ^ (-s / 2) * Gamma (s / 2) * ∑' n : ℕ, 1 / (n + 1) ^ s :=
by
rw [completed_zeta_eq_mellin_of_one_lt_re hs, mellin_zetaKernel₁_eq_tsum, neg_div,
mul_div_cancel' _ (two_ne_zero' ℂ)]
@@ -709,7 +709,7 @@ theorem riemannCompletedZeta_one_sub (s : ℂ) :
`ζ (1 - s) = 2 ^ (1 - s) * π ^ (-s) * Γ s * sin (π * (1 - s) / 2) * ζ s`. -/
theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠ 1) :
riemannZeta (1 - s) =
- 2 ^ (1 - s) * π ^ (-s) * gamma s * sin (π * (1 - s) / 2) * riemannZeta s :=
+ 2 ^ (1 - s) * π ^ (-s) * Gamma s * sin (π * (1 - s) / 2) * riemannZeta s :=
by
-- Deducing this from the previous formulations is quite involved. The proof uses two
-- nontrivial facts (the doubling formula and reflection formula for Gamma) and a lot of careful
@@ -744,7 +744,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
obtain ⟨n, rfl⟩ := hs_pos_odd
have : (1 - (1 + 2 * (n : ℂ))) / 2 = -↑n := by
rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left _ (two_ne_zero' ℂ)]
- rw [this, Complex.gamma_neg_nat_eq_zero, div_zero]
+ rw [this, Complex.Gamma_neg_nat_eq_zero, div_zero]
have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast ; field_simp; ring
rw [this, Complex.sin_int_mul_pi, MulZeroClass.mul_zero, MulZeroClass.zero_mul]
have h_Ga_ne4 : Gamma ((1 - s) / 2) ≠ 0 :=
@@ -817,7 +817,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [show ((2 * (m + 1))! : ℂ) = Gamma (2 * m + 2) * (↑(2 * m + 1) + 1)
by
rw [(by push_cast ; ring : (2 * m + 2 : ℂ) = ↑(2 * m + 1) + 1),
- Complex.gamma_nat_eq_factorial, (by ring : 2 * (m + 1) = 2 * m + 1 + 1),
+ Complex.Gamma_nat_eq_factorial, (by ring : 2 * (m + 1) = 2 * m + 1 + 1),
Nat.factorial_succ, Nat.cast_mul, mul_comm]
push_cast ]
rw [← div_div, neg_one_mul]
mathlib commit https://github.com/leanprover-community/mathlib/commit/a3e83f0fa4391c8740f7d773a7a9b74e311ae2a3
@@ -514,7 +514,7 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
/-- Auxiliary lemma for `mellin_zeta_kernel₁_eq_tsum`, computing the Mellin transform of an
individual term in the series. -/
theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ) :
- (∫ t : ℝ in Ioi 0, (t : ℂ) ^ (s - 1) * rexp (-π * t * (n + 1) ^ 2)) =
+ ∫ t : ℝ in Ioi 0, (t : ℂ) ^ (s - 1) * rexp (-π * t * (n + 1) ^ 2) =
↑π ^ (-s) * Complex.gamma s * (1 / (n + 1) ^ (2 * s)) :=
by
rw [Complex.gamma_eq_integral hs, Gamma_integral_eq_mellin]
mathlib commit https://github.com/leanprover-community/mathlib/commit/31c24aa72e7b3e5ed97a8412470e904f82b81004
@@ -4,12 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
! This file was ported from Lean 3 source module number_theory.zeta_function
-! leanprover-community/mathlib commit cca40788df1b8755d5baf17ab2f27dacc2e17acb
+! leanprover-community/mathlib commit 81843c08659063f91486be95a617b5e9ec93c9da
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Analysis.SpecialFunctions.Gamma.Beta
import Mathbin.NumberTheory.ModularForms.JacobiTheta
+import Mathbin.NumberTheory.ZetaValues
/-!
# Definition of the Riemann zeta function
@@ -34,6 +35,12 @@ I haven't checked exactly what they are).
* `differentiable_at_riemann_zeta` : the function `ζ(s)` is differentiable away from `s = 1`.
* `zeta_eq_tsum_of_one_lt_re` : for `1 < re s`, we have
`ζ(s) = ∑' (n : ℕ), 1 / (n + 1) ^ s`.
+* `riemann_completed_zeta₀_one_sub`, `riemann_completed_zeta_one_sub`, and `riemann_zeta_one_sub` :
+ functional equation relating values at `s` and `1 - s`
+* `riemann_zeta_neg_nat_eq_bernoulli` : for any `k ∈ ℕ` we have the formula
+ `riemann_zeta (-k) = (-1) ^ k * bernoulli (k + 1) / (k + 1)`
+* `riemann_zeta_two_mul_nat`: formula for `ζ(2 * k)` for `k ∈ ℕ, k ≠ 0` in terms of Bernoulli
+ numbers
## Outline of proofs:
@@ -43,6 +50,12 @@ completed zeta function. The second is obtained by subtracting a linear combinat
the interval `Ioc 0 1` to give a function with exponential decay at both `0` and `∞`. We then define
`riemann_completed_zeta₀` as the Mellin transform of the second zeta kernel, and define
`riemann_completed_zeta` and `riemann_zeta` from this.
+
+Since `zeta_kernel₂` has rapid decay and satisfies a functional equation relating its values at `t`
+and `1 / t`, we deduce the analyticity of `riemann_completed_zeta₀` and the functional equation
+relating its values at `s` and `1 - s`. On the other hand, since `zeta_kernel₁` can be expanded in
+powers of `exp (-π * t)` and the Mellin transform integrated term-by-term, we obtain the relation
+to the naive Dirichlet series `∑' (n : ℕ), 1 / (n + 1) ^ s`.
-/
@@ -50,7 +63,7 @@ open MeasureTheory Set Filter Asymptotics TopologicalSpace Real Asymptotics
open Complex hiding exp norm_eq_abs abs_of_nonneg abs_two continuous_exp
-open scoped Topology Real
+open scoped Topology Real Nat
noncomputable section
@@ -589,7 +602,7 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
/-- The Riemann zeta function agrees with the naive Dirichlet-series definition when the latter
converges. (Note that this is false without the assumption: when `re s ≤ 1` the sum is divergent,
and we use a different definition to obtain the analytic continuation to all `s`.) -/
-theorem zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
+theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) :
riemannZeta s = ∑' n : ℕ, 1 / (n + 1) ^ s :=
by
have : s ≠ 0 := by contrapose! hs; rw [hs, zero_re]; exact zero_le_one
@@ -600,5 +613,237 @@ theorem zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
exact mul_pos (inv_pos_of_pos two_pos) (zero_lt_one.trans hs)
· rw [Ne.def, cpow_eq_zero_iff, not_and_or, ← Ne.def, of_real_ne_zero]
exact Or.inl pi_pos.ne'
-#align zeta_eq_tsum_of_one_lt_re zeta_eq_tsum_of_one_lt_re
+#align zeta_eq_tsum_one_div_nat_add_one_cpow zeta_eq_tsum_one_div_nat_add_one_cpow
+
+/-- Alternate formulation of `zeta_eq_tsum_one_div_nat_add_one_cpow` without the `+ 1`, using the
+fact that for `s ≠ 0` we define `0 ^ s = 0`. -/
+theorem zeta_eq_tsum_one_div_nat_cpow {s : ℂ} (hs : 1 < re s) :
+ riemannZeta s = ∑' n : ℕ, 1 / n ^ s :=
+ by
+ have hs' : s ≠ 0 := by contrapose! hs; rw [hs, zero_re]; exact zero_le_one
+ rw [tsum_eq_zero_add]
+ ·
+ simp_rw [Nat.cast_zero, zero_cpow hs', div_zero, zero_add,
+ zeta_eq_tsum_one_div_nat_add_one_cpow hs, Nat.cast_add, Nat.cast_one]
+ · rw [← summable_norm_iff]
+ simp_rw [norm_div, norm_one, Complex.norm_eq_abs, ← of_real_nat_cast,
+ abs_cpow_eq_rpow_re_of_nonneg (Nat.cast_nonneg _) (zero_lt_one.trans hs).ne',
+ summable_one_div_nat_rpow]
+ assumption
+#align zeta_eq_tsum_one_div_nat_cpow zeta_eq_tsum_one_div_nat_cpow
+
+/-- Special case of `zeta_eq_tsum_one_div_nat_cpow` when the argument is in `ℕ`, so the power
+function can be expressed using naïve `pow` rather than `cpow`. -/
+theorem zeta_nat_eq_tsum_of_gt_one {k : ℕ} (hk : 1 < k) : riemannZeta k = ∑' n : ℕ, 1 / n ^ k := by
+ simp only [zeta_eq_tsum_one_div_nat_cpow
+ (by rwa [← of_real_nat_cast, of_real_re, ← Nat.cast_one, Nat.cast_lt] : 1 < re k),
+ cpow_nat_cast]
+#align zeta_nat_eq_tsum_of_gt_one zeta_nat_eq_tsum_of_gt_one
+
+/-- Explicit formula for `ζ (2 * k)`, for `k ∈ ℕ` with `k ≠ 0`: we have
+`ζ (2 * k) = (-1) ^ (k + 1) * 2 ^ (2 * k - 1) * π ^ (2 * k) * bernoulli (2 * k) / (2 * k)!`.
+Compare `has_sum_zeta_nat` for a version formulated explicitly as a sum, and
+`riemann_zeta_neg_nat_eq_bernoulli` for values at negative integers (equivalent to the above via
+the functional equation). -/
+theorem riemannZeta_two_mul_nat {k : ℕ} (hk : k ≠ 0) :
+ riemannZeta (2 * k) =
+ (-1) ^ (k + 1) * 2 ^ (2 * k - 1) * π ^ (2 * k) * bernoulli (2 * k) / (2 * k)! :=
+ by
+ convert congr_arg (coe : ℝ → ℂ) (hasSum_zeta_nat hk).tsum_eq
+ · rw [← Nat.cast_two, ← Nat.cast_mul, zeta_nat_eq_tsum_of_gt_one]
+ · push_cast
+ · refine' one_lt_two.trans_le _
+ conv_lhs => rw [← mul_one 2]
+ rwa [mul_le_mul_left (zero_lt_two' ℕ), Nat.one_le_iff_ne_zero]
+ · push_cast
+#align riemann_zeta_two_mul_nat riemannZeta_two_mul_nat
+
+theorem riemannZeta_two : riemannZeta 2 = π ^ 2 / 6 :=
+ by
+ convert congr_arg coe has_sum_zeta_two.tsum_eq
+ · rw [← Nat.cast_two, zeta_nat_eq_tsum_of_gt_one one_lt_two, of_real_tsum]
+ push_cast
+ · push_cast
+#align riemann_zeta_two riemannZeta_two
+
+theorem riemannZeta_four : riemannZeta 4 = π ^ 4 / 90 :=
+ by
+ convert congr_arg coe has_sum_zeta_four.tsum_eq
+ · rw [← Nat.cast_one, ← Nat.cast_bit0, ← Nat.cast_bit0,
+ zeta_nat_eq_tsum_of_gt_one (by norm_num : 1 < 4), of_real_tsum]
+ push_cast
+ · push_cast
+#align riemann_zeta_four riemannZeta_four
+
+/-!
+## Functional equation
+-/
+
+
+/-- Riemann zeta functional equation, formulated for `Λ₀`: for any complex `s` we have
+`Λ₀(1 - s) = Λ₀ s`. -/
+theorem riemannCompletedZeta₀_one_sub (s : ℂ) :
+ riemannCompletedZeta₀ (1 - s) = riemannCompletedZeta₀ s :=
+ by
+ have := mellin_comp_rpow zetaKernel₂ (s / 2 - 1 / 2) neg_one_lt_zero.ne
+ simp_rw [rpow_neg_one, ← one_div, abs_neg, abs_one, div_one, one_smul, of_real_neg, of_real_one,
+ div_neg, div_one, neg_sub] at this
+ conv_lhs => rw [riemannCompletedZeta₀, sub_div, ← this]
+ refine' set_integral_congr measurableSet_Ioi fun t ht => _
+ simp_rw [zetaKernel₂_one_div ht, smul_eq_mul, ← mul_assoc, sqrt_eq_rpow,
+ of_real_cpow (le_of_lt ht), ← cpow_add _ _ (of_real_ne_zero.mpr <| ne_of_gt ht)]
+ congr 2
+ push_cast
+ ring
+#align riemann_completed_zeta₀_one_sub riemannCompletedZeta₀_one_sub
+
+/-- Riemann zeta functional equation, formulated for `Λ`: for any complex `s` we have
+`Λ (1 - s) = Λ s`. -/
+theorem riemannCompletedZeta_one_sub (s : ℂ) :
+ riemannCompletedZeta (1 - s) = riemannCompletedZeta s := by
+ simp_rw [riemannCompletedZeta, riemannCompletedZeta₀_one_sub, sub_add, (by abel : 1 - s - 1 = -s),
+ (by abel : 1 - s = -(s - 1)), div_neg, neg_sub_neg]
+#align riemann_completed_zeta_one_sub riemannCompletedZeta_one_sub
+
+/-- Riemann zeta functional equation, formulated for `ζ`: if `1 - s ∉ ℕ`, then we have
+`ζ (1 - s) = 2 ^ (1 - s) * π ^ (-s) * Γ s * sin (π * (1 - s) / 2) * ζ s`. -/
+theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠ 1) :
+ riemannZeta (1 - s) =
+ 2 ^ (1 - s) * π ^ (-s) * gamma s * sin (π * (1 - s) / 2) * riemannZeta s :=
+ by
+ -- Deducing this from the previous formulations is quite involved. The proof uses two
+ -- nontrivial facts (the doubling formula and reflection formula for Gamma) and a lot of careful
+ -- rearrangement, requiring several non-vanishing statements as input to `field_simp`.
+ have hs_ne : s ≠ 0 := by contrapose! hs; rw [hs]; exact ⟨0, by rw [Nat.cast_zero, neg_zero]⟩
+ have h_sqrt : (sqrt π : ℂ) ≠ 0 := of_real_ne_zero.mpr (sqrt_ne_zero'.mpr pi_pos)
+ have h_pow : (2 : ℂ) ^ (s - 1) ≠ 0 := by rw [Ne.def, cpow_eq_zero_iff, not_and_or];
+ exact Or.inl two_ne_zero
+ have h_Ga_ne1 : Gamma (s / 2) ≠ 0 :=
+ by
+ rw [Ne.def, Complex.gamma_eq_zero_iff]
+ contrapose! hs
+ obtain ⟨m, hm⟩ := hs
+ rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
+ exact ⟨m * 2, by rw [hm]⟩
+ have h_Ga_eq : Gamma s = Gamma (s / 2) * Gamma ((s + 1) / 2) * 2 ^ (s - 1) / sqrt π := by
+ rw [add_div, Complex.gamma_mul_gamma_add_half, mul_div_cancel' _ (two_ne_zero' ℂ),
+ (by ring : 1 - s = -(s - 1)), cpow_neg, ← div_eq_mul_inv, eq_div_iff h_sqrt,
+ div_mul_eq_mul_div₀, div_mul_cancel _ h_pow]
+ have h_Ga_ne3 : Gamma ((s + 1) / 2) ≠ 0 :=
+ by
+ have h_Ga_aux : Gamma s ≠ 0 := Complex.gamma_ne_zero hs
+ contrapose! h_Ga_aux
+ rw [h_Ga_eq, h_Ga_aux, MulZeroClass.mul_zero, MulZeroClass.zero_mul, zero_div]
+ rw [riemannZeta, Function.update_noteq (by rwa [sub_ne_zero, ne_comm] : 1 - s ≠ 0),
+ Function.update_noteq hs_ne, riemannCompletedZeta_one_sub, mul_div, eq_div_iff h_Ga_ne1,
+ mul_comm, ← mul_div_assoc]
+ -- Now rule out case of s = positive odd integer & deduce further non-vanishing statements
+ by_cases hs_pos_odd : ∃ n : ℕ, s = 1 + 2 * n
+ · -- Note the case n = 0 (i.e. s = 1) works OK here, but only because we have used
+ -- `function.update_noteq` to change the goal; the original goal is genuinely false for s = 1.
+ obtain ⟨n, rfl⟩ := hs_pos_odd
+ have : (1 - (1 + 2 * (n : ℂ))) / 2 = -↑n := by
+ rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left _ (two_ne_zero' ℂ)]
+ rw [this, Complex.gamma_neg_nat_eq_zero, div_zero]
+ have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast ; field_simp; ring
+ rw [this, Complex.sin_int_mul_pi, MulZeroClass.mul_zero, MulZeroClass.zero_mul]
+ have h_Ga_ne4 : Gamma ((1 - s) / 2) ≠ 0 :=
+ by
+ rw [Ne.def, Complex.gamma_eq_zero_iff]
+ contrapose! hs_pos_odd
+ obtain ⟨m, hm⟩ := hs_pos_odd
+ rw [div_eq_iff (two_ne_zero' ℂ), sub_eq_iff_eq_add, neg_mul, ← sub_eq_neg_add,
+ eq_sub_iff_add_eq] at hm
+ exact ⟨m, by rw [← hm, mul_comm]⟩
+ -- At last the main proof
+ rw [show sin (↑π * (1 - s) / 2) = π * (Gamma ((1 - s) / 2) * Gamma (s / 2 + 1 / 2))⁻¹
+ by
+ have := congr_arg Inv.inv (Complex.gamma_mul_gamma_one_sub ((1 - s) / 2)).symm
+ rwa [(by ring : 1 - (1 - s) / 2 = s / 2 + 1 / 2), inv_div,
+ div_eq_iff (of_real_ne_zero.mpr pi_pos.ne'), mul_comm _ ↑π, mul_div_assoc'] at this ]
+ rw [(by rw [← neg_sub] : (2 : ℂ) ^ (1 - s) = 2 ^ (-(s - 1))), cpow_neg, h_Ga_eq]
+ suffices (π : ℂ) ^ ((1 - s) / 2) = π ^ (-s) * sqrt π * π ^ (s / 2) by rw [this]; field_simp;
+ ring_nf; rw [← of_real_pow, sq_sqrt pi_pos.le]; ring
+ simp_rw [sqrt_eq_rpow, of_real_cpow pi_pos.le, ← cpow_add _ _ (of_real_ne_zero.mpr pi_pos.ne')]
+ congr 1
+ push_cast
+ field_simp
+ ring
+#align riemann_zeta_one_sub riemannZeta_one_sub
+
+theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
+ riemannZeta (-k) = (-1) ^ k * bernoulli (k + 1) / (k + 1) :=
+ by
+ rcases Nat.even_or_odd' k with ⟨m, rfl | rfl⟩
+ · cases m
+ ·-- k = 0 : evaluate explicitly
+ rw [MulZeroClass.mul_zero, Nat.cast_zero, pow_zero, one_mul, zero_add, neg_zero, zero_add,
+ div_one, bernoulli_one, riemannZeta_zero, Rat.cast_div, Rat.cast_neg, Rat.cast_one,
+ Rat.cast_bit0, Rat.cast_one]
+ · -- k = 2 * (m + 1) : both sides "trivially" zero
+ rw [Nat.cast_mul, ← neg_mul, Nat.cast_two, Nat.cast_succ, riemannZeta_neg_two_mul_nat_add_one,
+ bernoulli_eq_bernoulli'_of_ne_one]
+ swap; · apply ne_of_gt; norm_num
+ rw [bernoulli'_odd_eq_zero ⟨m + 1, rfl⟩ (by norm_num), Rat.cast_zero, MulZeroClass.mul_zero,
+ zero_div]
+ · -- k = 2 * m + 1 : the interesting case
+ rw [Odd.neg_one_pow ⟨m, rfl⟩]
+ rw [show -(↑(2 * m + 1) : ℂ) = 1 - (2 * m + 2) by push_cast ; ring]
+ rw [riemannZeta_one_sub]
+ rotate_left
+ · intro n
+ rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), ← Int.cast_neg_natCast, ← Int.cast_ofNat,
+ Ne.def, Int.cast_inj]
+ apply ne_of_gt
+ refine' lt_of_le_of_lt (by norm_num : (-n : ℤ) ≤ 0) (by positivity)
+ · rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), Ne.def, Nat.cast_eq_one]; norm_num
+ -- get rid of sine term
+ rw [show Complex.sin (↑π * (1 - (2 * ↑m + 2)) / 2) = -(-1) ^ m
+ by
+ rw [(by field_simp; ring : (π : ℂ) * (1 - (2 * ↑m + 2)) / 2 = π / 2 - (π * m + π))]
+ rw [Complex.sin_pi_div_two_sub, Complex.cos_add_pi, neg_inj]
+ rcases Nat.even_or_odd' m with ⟨t, rfl | rfl⟩
+ · rw [pow_mul, neg_one_sq, one_pow]
+ convert Complex.cos_nat_mul_two_pi t using 2; push_cast ; ring
+ · rw [pow_add, pow_one, pow_mul, neg_one_sq, one_pow, one_mul]
+ convert Complex.cos_nat_mul_two_pi_add_pi t using 2; push_cast ; ring]
+ -- substitute in what we know about zeta values at positive integers
+ have step1 := congr_arg (coe : ℝ → ℂ) (hasSum_zeta_nat (by norm_num : m + 1 ≠ 0)).tsum_eq
+ have step2 := zeta_nat_eq_tsum_of_gt_one (by rw [mul_add]; norm_num : 1 < 2 * (m + 1))
+ simp_rw [of_real_tsum, of_real_div, of_real_one, of_real_pow, of_real_nat_cast] at step1
+ rw [step1, (by norm_cast : (↑(2 * (m + 1)) : ℂ) = 2 * ↑m + 2)] at step2
+ rw [step2, mul_div]
+ -- now the rest is just a lengthy but elementary rearrangement
+ rw [show ((2 * (m + 1))! : ℂ) = Gamma (2 * m + 2) * (↑(2 * m + 1) + 1)
+ by
+ rw [(by push_cast ; ring : (2 * m + 2 : ℂ) = ↑(2 * m + 1) + 1),
+ Complex.gamma_nat_eq_factorial, (by ring : 2 * (m + 1) = 2 * m + 1 + 1),
+ Nat.factorial_succ, Nat.cast_mul, mul_comm]
+ push_cast ]
+ rw [← div_div, neg_one_mul]
+ congr 1
+ rw [div_eq_iff (Gamma_ne_zero_of_re_pos _)]
+ swap; · rw [(by push_cast : 2 * (m : ℂ) + 2 = ↑(2 * (m : ℝ) + 2)), of_real_re]; positivity
+ simp_rw [of_real_mul, ← mul_assoc, of_real_rat_cast, mul_add, Nat.add_assoc, mul_one,
+ one_add_one_eq_two, mul_neg, neg_mul, neg_inj]
+ conv_rhs => rw [mul_comm]
+ congr 1
+ rw [of_real_pow, of_real_neg, of_real_one, pow_add, neg_one_sq, mul_one]
+ conv_lhs =>
+ congr
+ congr
+ rw [mul_assoc, ← pow_add, ← two_mul, pow_mul, neg_one_sq, one_pow, mul_one]
+ rw [show (2 : ℂ) ^ (1 - (2 * (m : ℂ) + 2)) = (↑((2 : ℝ) ^ (2 * m + 2 - 1)))⁻¹
+ by
+ rw [of_real_pow, ← cpow_nat_cast, ← cpow_neg, of_real_bit0, of_real_one]
+ congr 1
+ rw [Nat.add_sub_assoc one_le_two, Nat.cast_add, Nat.cast_mul, Nat.cast_two,
+ (by norm_num : 2 - 1 = 1)]
+ push_cast ; ring]
+ rw [show (π : ℂ) ^ (-(2 * (m : ℂ) + 2)) = (↑(π ^ (2 * m + 2)))⁻¹ by
+ rw [of_real_pow, ← cpow_nat_cast, ← cpow_neg, Nat.cast_add, Nat.cast_mul, Nat.cast_two]]
+ rw [(by intros; ring : ∀ a b c d e : ℂ, a * b * c * d * e = a * d * (b * e) * c)]
+ rw [inv_mul_cancel (of_real_ne_zero.mpr <| pow_ne_zero _ pi_pos.ne'),
+ inv_mul_cancel (of_real_ne_zero.mpr <| pow_ne_zero _ two_ne_zero), one_mul, one_mul]
+#align riemann_zeta_neg_nat_eq_bernoulli riemannZeta_neg_nat_eq_bernoulli
mathlib commit https://github.com/leanprover-community/mathlib/commit/5f25c089cb34db4db112556f23c50d12da81b297
@@ -154,7 +154,7 @@ theorem locally_integrable_zetaKernel₂ : LocallyIntegrableOn zetaKernel₂ (Io
rw [integrable_on, measure.restrict_restrict, ← integrable_on]
swap; · exact measurableSet_Ioc
apply ContinuousOn.integrableOn_compact
- · convert(is_compact_Icc : IsCompact <| Icc 0 1).inter hk' using 1
+ · convert (is_compact_Icc : IsCompact <| Icc 0 1).inter hk' using 1
exact
Set.ext fun t => ⟨fun h => ⟨Ioc_subset_Icc_self h.1, h.2⟩, fun h => ⟨⟨hk h.2, h.1.2⟩, h.2⟩⟩
· refine' ContinuousOn.mono _ ((inter_subset_right _ _).trans hk)
@@ -214,7 +214,8 @@ theorem isBigO_atTop_zetaKernel₁ : IsBigO atTop zetaKernel₁ fun t => exp (-
convert tendsto_id
ext1 t
rw [Function.comp_apply, mul_I_im, of_real_re, id.def]
- convert((h.norm_left.comp_tendsto h').congr' (eventually_of_mem (Ioi_mem_at_top 0) fun t ht => _)
+ convert
+ ((h.norm_left.comp_tendsto h').congr' (eventually_of_mem (Ioi_mem_at_top 0) fun t ht => _)
(eventually_of_mem (Ioi_mem_at_top 0) fun t ht => _)).of_norm_left
· rw [Function.comp_apply, ← zetaKernel₁_eq_jacobiTheta ht]
· rw [Function.comp_apply, mul_I_im, of_real_re]
@@ -350,11 +351,11 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
by
have h1 : tendsto (fun z : ℂ => (π : ℂ) ^ (z / 2)) (𝓝 0) (𝓝 1) :=
by
- convert(continuousAt_const_cpow (of_real_ne_zero.mpr pi_pos.ne')).comp _
+ convert (continuousAt_const_cpow (of_real_ne_zero.mpr pi_pos.ne')).comp _
· simp_rw [Function.comp_apply, zero_div, cpow_zero]
· exact continuous_at_id.div continuousAt_const two_ne_zero
suffices h2 : tendsto (fun z => riemannCompletedZeta z / Gamma (z / 2)) (𝓝[≠] 0) (𝓝 <| -1 / 2)
- · convert(h1.mono_left nhdsWithin_le_nhds).mul h2
+ · convert (h1.mono_left nhdsWithin_le_nhds).mul h2
· ext1 x; rw [mul_div]; · simp only [one_mul]
suffices h3 :
tendsto (fun z => riemannCompletedZeta z * (z / 2) / (z / 2 * Gamma (z / 2))) (𝓝[≠] 0)
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -190,7 +190,7 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) : zetaKernel₂ (1 / t) = s
· exact aux h
· simp only [div_self, Ne.def, one_ne_zero, not_false_iff, sqrt_one, of_real_one, one_mul]
· have := aux (show 1 < 1 / t by rwa [lt_one_div (zero_lt_one' ℝ) ht, div_one])
- rw [one_div_one_div] at this
+ rw [one_div_one_div] at this
rw [this, ← mul_assoc, ← of_real_mul, ← sqrt_mul ht.le, mul_one_div_cancel ht.ne', sqrt_one,
of_real_one, one_mul]
#align zeta_kernel₂_one_div zetaKernel₂_one_div
@@ -207,7 +207,7 @@ show holomorphy of their Mellin transforms (for `1 / 2 < re s` for `zeta_kernel
theorem isBigO_atTop_zetaKernel₁ : IsBigO atTop zetaKernel₁ fun t => exp (-π * t) :=
by
have h := isBigO_at_im_infty_jacobiTheta_sub_one.const_mul_left (1 / 2)
- simp_rw [mul_comm (1 / 2 : ℂ) _, mul_one_div] at h
+ simp_rw [mul_comm (1 / 2 : ℂ) _, mul_one_div] at h
have h' : tendsto (fun t : ℝ => ↑t * I) at_top (comap im at_top) :=
by
rw [tendsto_comap_iff]
@@ -233,7 +233,7 @@ theorem isBigO_atTop_zetaKernel₂ : IsBigO atTop zetaKernel₂ fun t => exp (-
theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => exp (-π / t) / sqrt t :=
by
have h1 := isBigO_atTop_zetaKernel₂.comp_tendsto tendsto_inv_zero_atTop
- simp_rw [← one_div] at h1
+ simp_rw [← one_div] at h1
have h2 : zetaKernel₂ ∘ Div.div 1 =ᶠ[𝓝[>] 0] fun t => sqrt t * zetaKernel₂ t :=
eventually_of_mem self_mem_nhdsWithin fun t ht => by simp_rw [← zetaKernel₂_one_div ht]
have h3 := h1.congr' h2 (eventually_eq.refl _ _)
@@ -371,7 +371,7 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
suffices tendsto (fun z => riemannCompletedZeta z * z / 2) (𝓝[≠] 0) (𝓝 (-1 / 2 : ℂ))
by
have := this.div h4 one_ne_zero
- simp_rw [div_one, mul_div_assoc] at this
+ simp_rw [div_one, mul_div_assoc] at this
exact this
refine' tendsto.div _ tendsto_const_nhds two_ne_zero
simp_rw [riemannCompletedZeta, add_mul, sub_mul]
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
set_integral
with setIntegral
(#12215)
Done with a global search and replace, and then (to fix the #align
lines), replace (#align \S*)setIntegral
with $1set_integral
.
@@ -501,7 +501,7 @@ theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ)
exact Nat.cast_nonneg _
conv_rhs => rw [this, mul_comm, ← smul_eq_mul]
rw [← mellin_comp_mul_right _ _ (show 0 < ((n : ℝ) + 1) ^ (2 : ℝ) by positivity)]
- refine set_integral_congr measurableSet_Ioi fun t _ => ?_
+ refine setIntegral_congr measurableSet_Ioi fun t _ => ?_
simp_rw [smul_eq_mul]
congr 3
conv_rhs => rw [← Nat.cast_two, rpow_natCast]
@@ -648,7 +648,7 @@ theorem riemannCompletedZeta₀_one_sub (s : ℂ) :
simp_rw [rpow_neg_one, ← one_div, abs_neg, abs_one, div_one, one_smul, ofReal_neg, ofReal_one,
div_neg, div_one, neg_sub] at this
conv_lhs => rw [riemannCompletedZeta₀, sub_div, ← this]
- refine set_integral_congr measurableSet_Ioi fun t ht => ?_
+ refine setIntegral_congr measurableSet_Ioi fun t ht => ?_
simp_rw [zetaKernel₂_one_div (le_of_lt ht), smul_eq_mul, ← mul_assoc, sqrt_eq_rpow,
ofReal_cpow (le_of_lt ht), ← cpow_add _ _ (ofReal_ne_zero.mpr <| ne_of_gt ht)]
congr 2
@@ -753,7 +753,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
exact lt_of_le_of_lt
(by set_option tactic.skipAssignedInstances false in norm_num : (-n : ℤ) ≤ 0)
(by positivity)
- · rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), Ne, Nat.cast_eq_one]; norm_num
+ · rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), Ne, Nat.cast_eq_one]; omega
-- get rid of sine term
rw [show Complex.sin (↑π * (1 - (2 * ↑m + 2)) / 2) = -(-1 : ℂ) ^ m by
rw [(by field_simp; ring : (π : ℂ) * (1 - (2 * ↑m + 2)) / 2 = π / 2 - (π * m + π))]
nat_cast
/int_cast
/rat_cast
to natCast
/intCast
/ratCast
(#11486)
Now that I am defining NNRat.cast
, I want a definitive answer to this naming issue. Plenty of lemmas in mathlib already use natCast
/intCast
/ratCast
over nat_cast
/int_cast
/rat_cast
, and this matches with the general expectation that underscore-separated name parts correspond to a single declaration.
@@ -504,7 +504,7 @@ theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ)
refine set_integral_congr measurableSet_Ioi fun t _ => ?_
simp_rw [smul_eq_mul]
congr 3
- conv_rhs => rw [← Nat.cast_two, rpow_nat_cast]
+ conv_rhs => rw [← Nat.cast_two, rpow_natCast]
ring
#align integral_cpow_mul_exp_neg_pi_mul_sq integral_cpow_mul_exp_neg_pi_mul_sq
@@ -534,7 +534,7 @@ theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
convert
(hasSum_ofReal.mpr (summable_exp_neg_pi_mul_nat_sq ht).hasSum).mul_left ((t : ℂ) ^ (s - 1))
simp only [neg_mul, ofReal_exp, ofReal_neg, ofReal_mul, ofReal_pow, ofReal_add,
- ofReal_nat_cast, ofReal_one, ofReal_tsum]
+ ofReal_natCast, ofReal_one, ofReal_tsum]
have h_sum' : ∀ᵐ t : ℝ ∂volume.restrict (Ioi 0), HasSum (fun n : ℕ => f n t)
((t : ℂ) ^ (s - 1) * zetaKernel₁ t) :=
(ae_restrict_iff' hm).mpr (ae_of_all _ fun t ht => h_sum0 ht)
@@ -587,7 +587,7 @@ theorem zeta_eq_tsum_one_div_nat_cpow {s : ℂ} (hs : 1 < re s) :
· simp_rw [Nat.cast_zero, zero_cpow hs', div_zero, zero_add,
zeta_eq_tsum_one_div_nat_add_one_cpow hs, Nat.cast_add, Nat.cast_one]
· refine .of_norm ?_
- simp_rw [norm_div, norm_one, Complex.norm_eq_abs, ← ofReal_nat_cast,
+ simp_rw [norm_div, norm_one, Complex.norm_eq_abs, ← ofReal_natCast,
abs_cpow_eq_rpow_re_of_nonneg (Nat.cast_nonneg _) (zero_lt_one.trans hs).ne',
summable_one_div_nat_rpow]
assumption
@@ -598,8 +598,8 @@ function can be expressed using naïve `pow` rather than `cpow`. -/
theorem zeta_nat_eq_tsum_of_gt_one {k : ℕ} (hk : 1 < k) :
riemannZeta k = ∑' n : ℕ, 1 / (n : ℂ) ^ k := by
simp only [zeta_eq_tsum_one_div_nat_cpow
- (by rwa [← ofReal_nat_cast, ofReal_re, ← Nat.cast_one, Nat.cast_lt] : 1 < re k),
- cpow_nat_cast]
+ (by rwa [← ofReal_natCast, ofReal_re, ← Nat.cast_one, Nat.cast_lt] : 1 < re k),
+ cpow_natCast]
#align zeta_nat_eq_tsum_of_gt_one zeta_nat_eq_tsum_of_gt_one
/-- Explicit formula for `ζ (2 * k)`, for `k ∈ ℕ` with `k ≠ 0`: we have
@@ -768,7 +768,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
-- substitute in what we know about zeta values at positive integers
have step1 := congr_arg ((↑) : ℝ → ℂ) (hasSum_zeta_nat (by norm_num : m + 1 ≠ 0)).tsum_eq
have step2 := zeta_nat_eq_tsum_of_gt_one (by rw [mul_add]; norm_num : 1 < 2 * (m + 1))
- simp_rw [ofReal_tsum, ofReal_div, ofReal_one, ofReal_pow, ofReal_nat_cast] at step1
+ simp_rw [ofReal_tsum, ofReal_div, ofReal_one, ofReal_pow, ofReal_natCast] at step1
rw [step1, (by norm_cast : (↑(2 * (m + 1)) : ℂ) = 2 * ↑m + 2)] at step2
rw [step2, mul_div]
-- now the rest is just a lengthy but elementary rearrangement
@@ -781,7 +781,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
congr 1
rw [div_eq_iff (Gamma_ne_zero_of_re_pos _)]
swap; · rw [(by norm_num : 2 * (m : ℂ) + 2 = ↑(2 * (m : ℝ) + 2)), ofReal_re]; positivity
- simp_rw [ofReal_mul, ← mul_assoc, ofReal_rat_cast, mul_add, Nat.add_assoc, mul_one,
+ simp_rw [ofReal_mul, ← mul_assoc, ofReal_ratCast, mul_add, Nat.add_assoc, mul_one,
one_add_one_eq_two, mul_neg, neg_mul, neg_inj]
conv_rhs => rw [mul_comm]
congr 1
@@ -791,13 +791,13 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
congr
rw [mul_assoc, ← pow_add, ← two_mul, pow_mul, neg_one_sq, one_pow, mul_one]
rw [show (2 : ℂ) ^ (1 - (2 * (m : ℂ) + 2)) = (↑((2 : ℝ) ^ (2 * m + 2 - 1)))⁻¹ by
- rw [ofReal_pow, ← cpow_nat_cast, ← cpow_neg, show (2 : ℝ) = (2 : ℂ) by norm_num]
+ rw [ofReal_pow, ← cpow_natCast, ← cpow_neg, show (2 : ℝ) = (2 : ℂ) by norm_num]
congr 1
rw [Nat.add_sub_assoc one_le_two, Nat.cast_add, Nat.cast_mul, Nat.cast_two,
(by norm_num : 2 - 1 = 1)]
push_cast; ring]
rw [show (π : ℂ) ^ (-(2 * (m : ℂ) + 2)) = (↑(π ^ (2 * m + 2)))⁻¹ by
- rw [ofReal_pow, ← cpow_nat_cast, ← cpow_neg, Nat.cast_add, Nat.cast_mul, Nat.cast_two]]
+ rw [ofReal_pow, ← cpow_natCast, ← cpow_neg, Nat.cast_add, Nat.cast_mul, Nat.cast_two]]
rw [(by intros; ring : ∀ a b c d e : ℂ, a * b * c * d * e = a * d * (b * e) * c)]
rw [inv_mul_cancel (ofReal_ne_zero.mpr <| pow_ne_zero _ pi_pos.ne'),
inv_mul_cancel (ofReal_ne_zero.mpr <| pow_ne_zero _ two_ne_zero), one_mul, one_mul]
@@ -219,7 +219,7 @@ theorem isBigO_atTop_zetaKernel₁ : IsBigO atTop zetaKernel₁ fun t => exp (-
rw [tendsto_comap_iff]
convert tendsto_id
ext1 t
- rw [Function.comp_apply, mul_I_im, ofReal_re, id.def]
+ rw [Function.comp_apply, mul_I_im, ofReal_re, id]
convert ((h.norm_left.comp_tendsto h').congr' (eventually_of_mem (Ioi_mem_atTop 0) fun t ht => _)
(eventually_of_mem (Ioi_mem_atTop 0) fun t _ => _)).of_norm_left (E' := ℂ)
· rw [Function.comp_apply, ← zetaKernel₁_eq_jacobiTheta ht]
@@ -377,12 +377,12 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
· refine Tendsto.mono_left ?_ nhdsWithin_le_nhds
have : ContinuousAt riemannCompletedZeta₀ 0 :=
differentiable_completed_zeta₀.continuous.continuousAt
- simpa only [id.def, mul_zero] using Tendsto.mul this tendsto_id
+ simpa only [id, mul_zero] using Tendsto.mul this tendsto_id
· refine tendsto_const_nhds.congr' (eventuallyEq_of_mem self_mem_nhdsWithin fun t ht => ?_)
simp_rw [one_div_mul_cancel ht]
· refine Tendsto.mono_left ?_ nhdsWithin_le_nhds
suffices ContinuousAt (fun z : ℂ => 1 / (z - 1)) 0 by
- simpa only [id.def, mul_zero] using Tendsto.mul this tendsto_id
+ simpa only [id, mul_zero] using Tendsto.mul this tendsto_id
refine continuousAt_const.div (continuousAt_id.sub continuousAt_const) ?_
simpa only [zero_sub] using neg_ne_zero.mpr one_ne_zero
-- Now the main proof.
This adds the notation √r
for Real.sqrt r
. The precedence is such that √x⁻¹
is parsed as √(x⁻¹)
; not because this is particularly desirable, but because it's the default and the choice doesn't really matter.
This is extracted from #7907, which adds a more general nth root typeclass.
The idea is to perform all the boring substitutions downstream quickly, so that we can play around with custom elaborators with a much slower rate of code-rot.
This PR also won't rot as quickly, as it does not forbid writing x.sqrt
as that PR does.
While perhaps claiming √
for Real.sqrt
is greedy; it:
NNReal.sqrt
and Nat.sqrt
sqrt
on Float
Co-authored-by: Yury G. Kudryashov <urkud@urkud.name>
@@ -76,7 +76,7 @@ def zetaKernel₁ (t : ℝ) : ℂ :=
/-- Modified zeta kernel, whose Mellin transform is entire. --/
def zetaKernel₂ : ℝ → ℂ :=
- zetaKernel₁ + indicator (Ioc 0 1) fun t => ((1 - 1 / sqrt t) / 2 : ℂ)
+ zetaKernel₁ + indicator (Ioc 0 1) fun t => ((1 - 1 / (√t : ℝ)) / 2 : ℂ)
#align zeta_kernel₂ zetaKernel₂
/-- The completed Riemann zeta function with its poles removed, `Λ(s) + 1 / s - 1 / (s - 1)`. -/
@@ -177,14 +177,14 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 ≤ t) :
zetaKernel₂ (1 / t) = sqrt t * zetaKernel₂ t := by
rcases ht.eq_or_lt with rfl|h't
· simp [zetaKernel₂, zetaKernel₁]
- have aux : ∀ {u : ℝ} (_ : 1 < u), zetaKernel₂ (1 / u) = sqrt u * zetaKernel₂ u := by
+ have aux : ∀ {u : ℝ} (_ : 1 < u), zetaKernel₂ (1 / u) = √u * zetaKernel₂ u := by
intro u hu
simp_rw [zetaKernel₂, Pi.add_apply]
rw [indicator_of_mem, indicator_of_not_mem (not_mem_Ioc_of_gt hu), add_zero]
swap; · exact ⟨one_div_pos.mpr (zero_lt_one.trans hu), (one_div u).symm ▸ inv_le_one hu.le⟩
rw [zetaKernel₁_eq_jacobiTheta (one_div_pos.mpr <| zero_lt_one.trans hu),
zetaKernel₁_eq_jacobiTheta (zero_lt_one.trans hu), ← add_div, ← mul_div_assoc, add_sub,
- sub_add_cancel, sqrt_div zero_le_one, sqrt_one, one_div (sqrt _), ofReal_inv, ← one_div,
+ sub_add_cancel, sqrt_div zero_le_one, sqrt_one, one_div (√_), ofReal_inv, ← one_div,
one_div_one_div, mul_sub, mul_one]
congr 2
let τ : UpperHalfPlane := .mk (u * I) ((mul_I_im u).symm ▸ zero_lt_one.trans hu)
@@ -238,14 +238,14 @@ set_option linter.uppercaseLean3 false in
#align is_O_at_top_zeta_kernel₂ isBigO_atTop_zetaKernel₂
/-- Precise but awkward-to-use bound for `zetaKernel₂` for `t → 0`. -/
-theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => exp (-π / t) / sqrt t := by
+theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => exp (-π / t) / √t := by
have h1 := isBigO_atTop_zetaKernel₂.comp_tendsto tendsto_inv_zero_atTop
simp_rw [← one_div] at h1
- have h2 : zetaKernel₂ ∘ Div.div 1 =ᶠ[𝓝[>] 0] fun t => sqrt t * zetaKernel₂ t :=
+ have h2 : zetaKernel₂ ∘ Div.div 1 =ᶠ[𝓝[>] 0] fun t => √t * zetaKernel₂ t :=
eventually_of_mem self_mem_nhdsWithin fun t ht => by
dsimp only; rw [← zetaKernel₂_one_div (le_of_lt ht)]; rfl
have h3 := h1.congr' h2 (EventuallyEq.refl _ _)
- have h4 := h3.mul (isBigO_refl (fun t : ℝ => 1 / (sqrt t : ℂ)) (𝓝[>] 0)).norm_right
+ have h4 := h3.mul (isBigO_refl (fun t : ℝ => 1 / (↑(√t) : ℂ)) (𝓝[>] 0)).norm_right
refine h4.congr' ?_ ?_
· refine eventually_of_mem self_mem_nhdsWithin fun x hx => ?_
dsimp
@@ -253,7 +253,7 @@ theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => ex
exact ofReal_ne_zero.mpr ((sqrt_ne_zero <| le_of_lt hx).mpr (ne_of_gt hx))
· refine eventually_of_mem self_mem_nhdsWithin fun x _ => ?_
dsimp only
- rw [Function.comp_apply, mul_one_div, one_div (sqrt x : ℂ), norm_inv, Complex.norm_eq_abs,
+ rw [Function.comp_apply, mul_one_div, one_div, norm_inv, Complex.norm_eq_abs,
abs_ofReal, abs_of_nonneg (sqrt_nonneg _), ← div_eq_mul_inv]
set_option linter.uppercaseLean3 false in
#align is_O_zero_zeta_kernel₂ isBigO_zero_zetaKernel₂
@@ -262,8 +262,8 @@ set_option linter.uppercaseLean3 false in
theorem isBigO_zero_zetaKernel₂_rpow (a : ℝ) : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => t ^ a := by
have aux1 : IsBigO atTop (fun t => exp (-π * t)) fun t => t ^ (-a - 1 / 2) :=
(isLittleO_exp_neg_mul_rpow_atTop pi_pos _).isBigO
- have aux2 : IsBigO atTop (fun t => exp (-π * t) * sqrt t) fun t => t ^ (-a) := by
- refine (aux1.mul (isBigO_refl sqrt _)).congr' (EventuallyEq.refl _ _) ?_
+ have aux2 : IsBigO atTop (fun t => exp (-π * t) * √t) fun t => t ^ (-a) := by
+ refine (aux1.mul (isBigO_refl _ _)).congr' (EventuallyEq.refl _ _) ?_
refine (eventually_gt_atTop 0).mp (eventually_of_forall fun t ht => ?_)
simp_rw [sqrt_eq_rpow, ← rpow_add ht, sub_add_cancel]
refine isBigO_zero_zetaKernel₂.trans ((aux2.comp_tendsto tendsto_inv_zero_atTop).congr' ?_ ?_)
@@ -276,9 +276,8 @@ set_option linter.uppercaseLean3 false in
/-- Bound for `zetaKernel₁` for `t → 0`. -/
theorem isBigO_zero_zetaKernel₁ : IsBigO (𝓝[>] 0) zetaKernel₁ fun t => t ^ (-(1 / 2) : ℝ) := by
- have : zetaKernel₁ =ᶠ[𝓝[>] 0] zetaKernel₂ + fun t => ((1 / sqrt t - 1) / 2 : ℂ) := by
- refine
- eventuallyEq_of_mem (Ioc_mem_nhdsWithin_Ioi <| left_mem_Ico.mpr zero_lt_one) fun t h => ?_
+ have : zetaKernel₁ =ᶠ[𝓝[>] 0] zetaKernel₂ + fun t => ((1 / (√t : ℝ) - 1) / 2 : ℂ) := by
+ filter_upwards [Ioc_mem_nhdsWithin_Ioi' zero_lt_one] with t h
rw [Pi.add_apply, zetaKernel₂, Pi.add_apply, indicator_of_mem h]
ring
refine ((isBigO_zero_zetaKernel₂_rpow _).add ?_).congr' this.symm (EventuallyEq.refl _ _)
@@ -334,7 +333,7 @@ theorem differentiableAt_completed_zeta {s : ℂ} (hs : s ≠ 0) (hs' : s ≠ 1)
theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableAt ℂ riemannZeta s := by
/- First claim: the result holds at `t` for `t ≠ 0`. Note we will need to use this for the case
`s = 0` also, as a hypothesis for the removable-singularity criterion. -/
- have c1 : ∀ (t : ℂ) (_ : t ≠ 0) (_ : t ≠ 1),
+ have c1 : ∀ t : ℂ, t ≠ 0 → t ≠ 1 →
DifferentiableAt ℂ
(fun u : ℂ => (π : ℂ) ^ (u / 2) * riemannCompletedZeta u / Gamma (u / 2)) t := by
intro t ht ht'
@@ -428,8 +427,8 @@ def RiemannHypothesis : Prop :=
theorem hasMellin_one_div_sqrt_Ioc {s : ℂ} (hs : 1 / 2 < re s) :
- HasMellin (indicator (Ioc 0 1) (fun t => 1 / ↑(sqrt t) : ℝ → ℂ)) s (1 / (s - 1 / 2)) := by
- have h1 : EqOn (fun t => 1 / ↑(sqrt t) : ℝ → ℂ) (fun t => (t : ℂ) ^ (-1 / 2 : ℂ)) (Ioc 0 1) := by
+ HasMellin (indicator (Ioc 0 1) (fun t => 1 / ↑(√t) : ℝ → ℂ)) s (1 / (s - 1 / 2)) := by
+ have h1 : EqOn (fun t => 1 / ↑(√t) : ℝ → ℂ) (fun t => (t : ℂ) ^ (-1 / 2 : ℂ)) (Ioc 0 1) := by
intro t ht
simp_rw [neg_div, cpow_neg, ← one_div, sqrt_eq_rpow, ofReal_cpow ht.1.le]
norm_num
@@ -441,18 +440,18 @@ theorem hasMellin_one_div_sqrt_Ioc {s : ℂ} (hs : 1 / 2 < re s) :
/-- Evaluate the Mellin transform of the "fudge factor" in `zetaKernel₂` -/
theorem hasMellin_one_div_sqrt_sub_one_div_two_Ioc {s : ℂ} (hs : 1 / 2 < s.re) :
- HasMellin ((Ioc 0 1).indicator fun t => (1 - 1 / (sqrt t : ℂ)) / 2) s
+ HasMellin ((Ioc 0 1).indicator fun t => (1 - 1 / (↑(√t) : ℂ)) / 2) s
(1 / (2 * s) - 1 / (2 * s - 1)) := by
have step1 :
- HasMellin (indicator (Ioc 0 1) (fun t => 1 - 1 / ↑(sqrt t) : ℝ → ℂ)) s
+ HasMellin (indicator (Ioc 0 1) (fun t => 1 - 1 / ↑(√t) : ℝ → ℂ)) s
(1 / s - 1 / (s - 1 / 2)) := by
have a := hasMellin_one_Ioc (one_half_pos.trans hs)
have b := hasMellin_one_div_sqrt_Ioc hs
simpa only [a.2, b.2, ← indicator_sub] using hasMellin_sub a.1 b.1
-- todo: implement something like "indicator.const_div" (blocked by the port for now)
rw [show
- ((Ioc 0 1).indicator fun t => (1 - 1 / (sqrt t : ℂ)) / 2) = fun t =>
- (Ioc 0 1).indicator (fun t => 1 - 1 / (sqrt t : ℂ)) t / 2
+ ((Ioc 0 1).indicator fun t => (1 - 1 / ((√t : ℝ) : ℂ)) / 2) = fun t =>
+ (Ioc 0 1).indicator (fun t => 1 - 1 / ((√t : ℝ) : ℂ)) t / 2
by ext1 t; simp_rw [div_eq_inv_mul, indicator_mul_right]]
simp_rw [HasMellin, mellin_div_const, step1.2, sub_div, div_div]
refine ⟨step1.1.div_const _, ?_⟩
@@ -674,7 +673,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
-- nontrivial facts (the doubling formula and reflection formula for Gamma) and a lot of careful
-- rearrangement, requiring several non-vanishing statements as input to `field_simp`.
have hs_ne : s ≠ 0 := by contrapose! hs; rw [hs]; exact ⟨0, by rw [Nat.cast_zero, neg_zero]⟩
- have h_sqrt : (sqrt π : ℂ) ≠ 0 := ofReal_ne_zero.mpr (sqrt_ne_zero'.mpr pi_pos)
+ have h_sqrt : ((√π : ℝ) : ℂ) ≠ 0 := ofReal_ne_zero.mpr (sqrt_ne_zero'.mpr pi_pos)
have h_pow : (2 : ℂ) ^ (s - 1) ≠ 0 := by
rw [Ne, cpow_eq_zero_iff, not_and_or]
exact Or.inl two_ne_zero
@@ -684,7 +683,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
obtain ⟨m, hm⟩ := hs
rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
exact ⟨m * 2, by rw [hm]⟩
- have h_Ga_eq : Gamma s = Gamma (s / 2) * Gamma ((s + 1) / 2) * (2 : ℂ) ^ (s - 1) / sqrt π := by
+ have h_Ga_eq : Gamma s = Gamma (s / 2) * Gamma ((s + 1) / 2) * (2 : ℂ) ^ (s - 1) / √π := by
rw [add_div, Complex.Gamma_mul_Gamma_add_half, mul_div_cancel₀ _ (two_ne_zero' ℂ),
(by ring : 1 - s = -(s - 1)), cpow_neg, ← div_eq_mul_inv, eq_div_iff h_sqrt,
div_mul_eq_mul_div₀, div_mul_cancel₀ _ h_pow]
@@ -718,7 +717,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
rwa [(by ring : 1 - (1 - s) / 2 = s / 2 + 1 / 2), inv_div,
div_eq_iff (ofReal_ne_zero.mpr pi_pos.ne'), mul_comm _ (π : ℂ), mul_div_assoc'] at this]
rw [(by rw [← neg_sub] : (2 : ℂ) ^ (1 - s) = (2 : ℂ) ^ (-(s - 1))), cpow_neg, h_Ga_eq]
- suffices (π : ℂ) ^ ((1 - s) / 2) = (π : ℂ) ^ (-s) * sqrt π * (π : ℂ) ^ (s / 2) by
+ suffices (π : ℂ) ^ ((1 - s) / 2) = (π : ℂ) ^ (-s) * √π * (π : ℂ) ^ (s / 2) by
rw [this]; field_simp;
ring_nf; rw [← ofReal_pow, sq_sqrt pi_pos.le]; ring
simp_rw [sqrt_eq_rpow, ofReal_cpow pi_pos.le, ← cpow_add _ _ (ofReal_ne_zero.mpr pi_pos.ne')]
This is a rewrite of JacobiTheta/TwoVariable.lean
, adding a number of new results needed for Hurwitz and Dirichlet L-series.
The main addition is developing the theory of the z
-derivative of the theta function, as an object of study in its own right (functional equations, periodicity, holomorphy etc) – this is needed to prove analytic continuation + functional equations for odd Dirichlet characters.
We also add a number of new results about the existing jacobiTheta2
function:
@@ -6,6 +6,7 @@ Authors: David Loeffler
import Mathlib.Analysis.SpecialFunctions.Gamma.Beta
import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable
import Mathlib.NumberTheory.ZetaValues
+import Mathlib.Analysis.Complex.RemovableSingularity
#align_import number_theory.zeta_function from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf"
OfNat
and Nat.cast
lemmas (#11861)
This renames
Int.cast_ofNat
to Int.cast_natCast
Int.int_cast_ofNat
to Int.cast_ofNat
I think the history here is that this lemma was previously about Int.ofNat
, before we globally fixed the simp-normal form to be Nat.cast
.
Since the Int.cast_ofNat
name is repurposed, it can't be deprecated. Int.int_cast_ofNat
is such a wonky name that it was probably never used.
@@ -747,8 +747,8 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [riemannZeta_one_sub]
rotate_left
· intro n
- rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), ← Int.cast_neg_natCast, ← Int.cast_ofNat,
- Ne, Int.cast_inj]
+ rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), ← Int.cast_neg_natCast,
+ ← Int.cast_natCast, Ne, Int.cast_inj]
apply ne_of_gt
exact lt_of_le_of_lt
(by set_option tactic.skipAssignedInstances false in norm_num : (-n : ℤ) ≤ 0)
@@ -196,7 +196,7 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 ≤ t) :
rfl
rcases lt_trichotomy 1 t with (h | h | h)
· exact aux h
- · simp only [← h, div_self, Ne.def, one_ne_zero, not_false_iff, sqrt_one, ofReal_one, one_mul]
+ · simp only [← h, div_self, Ne, one_ne_zero, not_false_iff, sqrt_one, ofReal_one, one_mul]
· have := aux (show 1 < 1 / t by rwa [lt_one_div (zero_lt_one' ℝ) h't, div_one])
rw [one_div_one_div] at this
rw [this, ← mul_assoc, ← ofReal_mul, ← sqrt_mul ht, mul_one_div_cancel h't.ne', sqrt_one,
@@ -574,7 +574,7 @@ theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) :
· apply Gamma_ne_zero_of_re_pos
rw [div_eq_mul_inv, mul_comm, show (2⁻¹ : ℂ) = (2⁻¹ : ℝ) by norm_num, re_ofReal_mul]
exact mul_pos (inv_pos_of_pos two_pos) (zero_lt_one.trans hs)
- · rw [Ne.def, cpow_eq_zero_iff, not_and_or, ← Ne.def, ofReal_ne_zero]
+ · rw [Ne, cpow_eq_zero_iff, not_and_or, ← Ne, ofReal_ne_zero]
exact Or.inl pi_pos.ne'
#align zeta_eq_tsum_one_div_nat_add_one_cpow zeta_eq_tsum_one_div_nat_add_one_cpow
@@ -675,10 +675,10 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
have hs_ne : s ≠ 0 := by contrapose! hs; rw [hs]; exact ⟨0, by rw [Nat.cast_zero, neg_zero]⟩
have h_sqrt : (sqrt π : ℂ) ≠ 0 := ofReal_ne_zero.mpr (sqrt_ne_zero'.mpr pi_pos)
have h_pow : (2 : ℂ) ^ (s - 1) ≠ 0 := by
- rw [Ne.def, cpow_eq_zero_iff, not_and_or]
+ rw [Ne, cpow_eq_zero_iff, not_and_or]
exact Or.inl two_ne_zero
have h_Ga_ne1 : Gamma (s / 2) ≠ 0 := by
- rw [Ne.def, Complex.Gamma_eq_zero_iff]
+ rw [Ne, Complex.Gamma_eq_zero_iff]
contrapose! hs
obtain ⟨m, hm⟩ := hs
rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
@@ -705,7 +705,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast; field_simp; ring
rw [this, Complex.sin_int_mul_pi, mul_zero, zero_mul]
have h_Ga_ne4 : Gamma ((1 - s) / 2) ≠ 0 := by
- rw [Ne.def, Complex.Gamma_eq_zero_iff]
+ rw [Ne, Complex.Gamma_eq_zero_iff]
contrapose! hs_pos_odd
obtain ⟨m, hm⟩ := hs_pos_odd
rw [div_eq_iff (two_ne_zero' ℂ), sub_eq_iff_eq_add, neg_mul, ← sub_eq_neg_add,
@@ -748,12 +748,12 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rotate_left
· intro n
rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), ← Int.cast_neg_natCast, ← Int.cast_ofNat,
- Ne.def, Int.cast_inj]
+ Ne, Int.cast_inj]
apply ne_of_gt
exact lt_of_le_of_lt
(by set_option tactic.skipAssignedInstances false in norm_num : (-n : ℤ) ≤ 0)
(by positivity)
- · rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), Ne.def, Nat.cast_eq_one]; norm_num
+ · rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), Ne, Nat.cast_eq_one]; norm_num
-- get rid of sine term
rw [show Complex.sin (↑π * (1 - (2 * ↑m + 2)) / 2) = -(-1 : ℂ) ^ m by
rw [(by field_simp; ring : (π : ℂ) * (1 - (2 * ↑m + 2)) / 2 = π / 2 - (π * m + π))]
mul
-div
cancellation lemmas (#11530)
Lemma names around cancellation of multiplication and division are a mess.
This PR renames a handful of them according to the following table (each big row contains the multiplicative statement, then the three rows contain the GroupWithZero
lemma name, the Group
lemma, the AddGroup
lemma name).
| Statement | New name | Old name | |
@@ -127,8 +127,8 @@ of `zetaKernel₁`, since the sum over `ℕ` rather than `ℤ` is more convenien
the Dirichlet series for `re s > 1`.) -/
theorem zetaKernel₁_eq_jacobiTheta {t : ℝ} (ht : 0 < t) :
zetaKernel₁ t = (jacobiTheta (t * I) - 1) / 2 := by
- rw [jacobiTheta_eq_tsum_nat ((mul_I_im t).symm ▸ ht : 0 < (↑t * I).im), add_comm, add_sub_cancel,
- mul_div_cancel_left _ (two_ne_zero' ℂ), zetaKernel₁]
+ rw [jacobiTheta_eq_tsum_nat ((mul_I_im t).symm ▸ ht : 0 < (↑t * I).im), add_comm,
+ add_sub_cancel_right, mul_div_cancel_left₀ _ (two_ne_zero' ℂ), zetaKernel₁]
congr 1 with n : 1
push_cast
rw [(by ring : ↑π * I * ((n : ℂ) + 1) ^ 2 * (t * I) = I ^ 2 * π * t * ((n : ℂ) + 1) ^ 2),
@@ -360,7 +360,7 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
Tendsto (fun z => riemannCompletedZeta z * (z / 2) / (z / 2 * Gamma (z / 2))) (𝓝[≠] 0)
(𝓝 <| -1 / 2) by
refine Tendsto.congr' (eventuallyEq_of_mem self_mem_nhdsWithin fun z hz ↦ ?_) h3
- rw [← div_div, mul_div_cancel _ (div_ne_zero hz two_ne_zero)]
+ rw [← div_div, mul_div_cancel_right₀ _ (div_ne_zero hz two_ne_zero)]
have h4 : Tendsto (fun z : ℂ => z / 2 * Gamma (z / 2)) (𝓝[≠] 0) (𝓝 1) := by
refine tendsto_self_mul_Gamma_nhds_zero.comp ?_
rw [tendsto_nhdsWithin_iff, (by simp : 𝓝 (0 : ℂ) = 𝓝 (0 / 2))]
@@ -455,7 +455,7 @@ theorem hasMellin_one_div_sqrt_sub_one_div_two_Ioc {s : ℂ} (hs : 1 / 2 < s.re)
by ext1 t; simp_rw [div_eq_inv_mul, indicator_mul_right]]
simp_rw [HasMellin, mellin_div_const, step1.2, sub_div, div_div]
refine ⟨step1.1.div_const _, ?_⟩
- rw [mul_comm, sub_mul, div_mul_cancel _ (two_ne_zero' ℂ), mul_comm s 2]
+ rw [mul_comm, sub_mul, div_mul_cancel₀ _ (two_ne_zero' ℂ), mul_comm s 2]
#align has_mellin_one_div_sqrt_sub_one_div_two_Ioc hasMellin_one_div_sqrt_sub_one_div_two_Ioc
theorem mellin_zetaKernel₂_eq_of_lt_re {s : ℂ} (hs : 1 / 2 < s.re) :
@@ -476,7 +476,7 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
sub_sub, ← add_sub]
conv_rhs => rw [← add_zero (mellin zetaKernel₁ <| s / 2)]
congr 1
- rw [mul_div_cancel' _ (two_ne_zero' ℂ)]
+ rw [mul_div_cancel₀ _ (two_ne_zero' ℂ)]
abel
#align completed_zeta_eq_mellin_of_one_lt_re completed_zeta_eq_mellin_of_one_lt_re
@@ -558,7 +558,7 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
riemannCompletedZeta s =
(π : ℂ) ^ (-s / 2) * Gamma (s / 2) * ∑' n : ℕ, 1 / ((n : ℂ) + 1) ^ s := by
rw [completed_zeta_eq_mellin_of_one_lt_re hs, mellin_zetaKernel₁_eq_tsum, neg_div,
- mul_div_cancel' _ (two_ne_zero' ℂ)]
+ mul_div_cancel₀ _ (two_ne_zero' ℂ)]
rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
rwa [re_ofReal_mul, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
#align completed_zeta_eq_tsum_of_one_lt_re completed_zeta_eq_tsum_of_one_lt_re
@@ -570,7 +570,7 @@ theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) :
riemannZeta s = ∑' n : ℕ, 1 / ((n : ℂ) + 1) ^ s := by
have : s ≠ 0 := by contrapose! hs; rw [hs, zero_re]; exact zero_le_one
rw [riemannZeta, Function.update_noteq this, completed_zeta_eq_tsum_of_one_lt_re hs, ← mul_assoc,
- neg_div, cpow_neg, mul_inv_cancel_left₀, mul_div_cancel_left]
+ neg_div, cpow_neg, mul_inv_cancel_left₀, mul_div_cancel_left₀]
· apply Gamma_ne_zero_of_re_pos
rw [div_eq_mul_inv, mul_comm, show (2⁻¹ : ℂ) = (2⁻¹ : ℝ) by norm_num, re_ofReal_mul]
exact mul_pos (inv_pos_of_pos two_pos) (zero_lt_one.trans hs)
@@ -684,9 +684,9 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
rw [div_eq_iff (two_ne_zero' ℂ), ← Nat.cast_two, neg_mul, ← Nat.cast_mul] at hm
exact ⟨m * 2, by rw [hm]⟩
have h_Ga_eq : Gamma s = Gamma (s / 2) * Gamma ((s + 1) / 2) * (2 : ℂ) ^ (s - 1) / sqrt π := by
- rw [add_div, Complex.Gamma_mul_Gamma_add_half, mul_div_cancel' _ (two_ne_zero' ℂ),
+ rw [add_div, Complex.Gamma_mul_Gamma_add_half, mul_div_cancel₀ _ (two_ne_zero' ℂ),
(by ring : 1 - s = -(s - 1)), cpow_neg, ← div_eq_mul_inv, eq_div_iff h_sqrt,
- div_mul_eq_mul_div₀, div_mul_cancel _ h_pow]
+ div_mul_eq_mul_div₀, div_mul_cancel₀ _ h_pow]
have h_Ga_ne3 : Gamma ((s + 1) / 2) ≠ 0 := by
have h_Ga_aux : Gamma s ≠ 0 := Complex.Gamma_ne_zero hs
contrapose! h_Ga_aux
@@ -700,7 +700,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
-- `Function.update_noteq` to change the goal; the original goal is genuinely false for s = 1.
obtain ⟨n, rfl⟩ := hs_pos_odd
have : (1 - (1 + 2 * (n : ℂ))) / 2 = -↑n := by
- rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left _ (two_ne_zero' ℂ)]
+ rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left₀ _ (two_ne_zero' ℂ)]
rw [this, Complex.Gamma_neg_nat_eq_zero, div_zero]
have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast; field_simp; ring
rw [this, Complex.sin_int_mul_pi, mul_zero, zero_mul]
Mathematicians will be unnerved by us evaluating the zeta function at 1 and getting a complex number. Pointed out by Jordan Ellenberg on Twitter.
@@ -417,7 +417,8 @@ theorem riemannZeta_neg_two_mul_nat_add_one (n : ℕ) : riemannZeta (-2 * (n + 1
/-- A formal statement of the **Riemann hypothesis** – constructing a term of this type is worth a
million dollars. -/
def RiemannHypothesis : Prop :=
- ∀ (s : ℂ) (_ : riemannCompletedZeta s = 0) (_ : ¬∃ n : ℕ, s = -2 * (n + 1)), s.re = 1 / 2
+ ∀ (s : ℂ) (_ : s ≠ 1) (_ : riemannCompletedZeta s = 0) (_ : ¬∃ n : ℕ, s = -2 * (n + 1)),
+ s.re = 1 / 2
#align riemann_hypothesis RiemannHypothesis
/-!
This is a very large PR, but it has been reviewed piecemeal already in PRs to the bump/v4.7.0
branch as we update to intermediate nightlies.
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: damiano <adomani@gmail.com>
@@ -616,7 +616,7 @@ theorem riemannZeta_two_mul_nat {k : ℕ} (hk : k ≠ 0) :
· refine one_lt_two.trans_le ?_
conv_lhs => rw [← mul_one 2]
rwa [mul_le_mul_left (zero_lt_two' ℕ), Nat.one_le_iff_ne_zero]
- · norm_num
+ · set_option tactic.skipAssignedInstances false in norm_num
#align riemann_zeta_two_mul_nat riemannZeta_two_mul_nat
theorem riemannZeta_two : riemannZeta 2 = (π : ℂ) ^ 2 / 6 := by
@@ -749,7 +749,9 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), ← Int.cast_neg_natCast, ← Int.cast_ofNat,
Ne.def, Int.cast_inj]
apply ne_of_gt
- exact lt_of_le_of_lt (by norm_num : (-n : ℤ) ≤ 0) (by positivity)
+ exact lt_of_le_of_lt
+ (by set_option tactic.skipAssignedInstances false in norm_num : (-n : ℤ) ≤ 0)
+ (by positivity)
· rw [(by norm_cast : 2 * (m : ℂ) + 2 = ↑(2 * m + 2)), Ne.def, Nat.cast_eq_one]; norm_num
-- get rid of sine term
rw [show Complex.sin (↑π * (1 - (2 * ↑m + 2)) / 2) = -(-1 : ℂ) ^ m by
have
, replace
and suffices
(#10640)
No changes to tactic file, it's just boring fixes throughout the library.
This follows on from #6964.
Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
@@ -351,21 +351,21 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
(continuousAt_const_cpow (ofReal_ne_zero.mpr pi_pos.ne')) ?_).tendsto using 2
· simp_rw [Function.comp_apply, zero_div, cpow_zero]
· exact continuousAt_id.div continuousAt_const two_ne_zero
- suffices h2 : Tendsto (fun z => riemannCompletedZeta z / Gamma (z / 2)) (𝓝[≠] 0) (𝓝 <| -1 / 2)
- · convert (h1.mono_left nhdsWithin_le_nhds).mul h2 using 1
+ suffices h2 : Tendsto (fun z ↦ riemannCompletedZeta z / Gamma (z / 2)) (𝓝[≠] 0)
+ (𝓝 <| -1 / 2) by
+ convert (h1.mono_left nhdsWithin_le_nhds).mul h2 using 1
· ext1 x; rw [mul_div]
· simp only [one_mul]
suffices h3 :
- Tendsto (fun z => riemannCompletedZeta z * (z / 2) / (z / 2 * Gamma (z / 2))) (𝓝[≠] 0)
- (𝓝 <| -1 / 2)
- · refine Tendsto.congr' (eventuallyEq_of_mem self_mem_nhdsWithin fun z hz => ?_) h3
+ Tendsto (fun z => riemannCompletedZeta z * (z / 2) / (z / 2 * Gamma (z / 2))) (𝓝[≠] 0)
+ (𝓝 <| -1 / 2) by
+ refine Tendsto.congr' (eventuallyEq_of_mem self_mem_nhdsWithin fun z hz ↦ ?_) h3
rw [← div_div, mul_div_cancel _ (div_ne_zero hz two_ne_zero)]
have h4 : Tendsto (fun z : ℂ => z / 2 * Gamma (z / 2)) (𝓝[≠] 0) (𝓝 1) := by
refine tendsto_self_mul_Gamma_nhds_zero.comp ?_
rw [tendsto_nhdsWithin_iff, (by simp : 𝓝 (0 : ℂ) = 𝓝 (0 / 2))]
- exact
- ⟨(tendsto_id.div_const _).mono_left nhdsWithin_le_nhds,
- eventually_of_mem self_mem_nhdsWithin fun x hx => div_ne_zero hx two_ne_zero⟩
+ exact ⟨(tendsto_id.div_const _).mono_left nhdsWithin_le_nhds,
+ eventually_of_mem self_mem_nhdsWithin fun x hx => div_ne_zero hx two_ne_zero⟩
suffices Tendsto (fun z => riemannCompletedZeta z * z / 2) (𝓝[≠] 0) (𝓝 (-1 / 2 : ℂ)) by
have := this.div h4 one_ne_zero
simp_rw [div_one, mul_div_assoc] at this
@@ -817,16 +817,16 @@ lemma riemannCompletedZeta_residue_one :
/-- The residue of `ζ(s)` at `s = 1` is equal to 1. -/
lemma riemannZeta_residue_one : Tendsto (fun s ↦ (s - 1) * riemannZeta s) (𝓝[≠] 1) (𝓝 1) := by
- suffices : Tendsto (fun s => (s - 1) *
- (π ^ (s / 2) * riemannCompletedZeta s / Gamma (s / 2))) (𝓝[≠] 1) (𝓝 1)
- · refine this.congr' <| (eventually_ne_nhdsWithin one_ne_zero).mp (eventually_of_forall ?_)
+ suffices Tendsto (fun s => (s - 1) *
+ (π ^ (s / 2) * riemannCompletedZeta s / Gamma (s / 2))) (𝓝[≠] 1) (𝓝 1) by
+ refine this.congr' <| (eventually_ne_nhdsWithin one_ne_zero).mp (eventually_of_forall ?_)
intro x hx
simp [riemannZeta_def, Function.update_noteq hx]
- have h0 : Tendsto (fun s ↦ π ^ (s / 2) : ℂ → ℂ) (𝓝[≠] 1) (𝓝 (π ^ (1 / 2 : ℂ)))
- · refine ((continuousAt_id.div_const _).const_cpow ?_).tendsto.mono_left nhdsWithin_le_nhds
+ have h0 : Tendsto (fun s ↦ π ^ (s / 2) : ℂ → ℂ) (𝓝[≠] 1) (𝓝 (π ^ (1 / 2 : ℂ))) := by
+ refine ((continuousAt_id.div_const _).const_cpow ?_).tendsto.mono_left nhdsWithin_le_nhds
exact Or.inl <| ofReal_ne_zero.mpr pi_ne_zero
- have h1 : Tendsto (fun s : ℂ ↦ 1 / Gamma (s / 2)) (𝓝[≠] 1) (𝓝 (1 / π ^ (1 / 2 : ℂ)))
- · rw [← Complex.Gamma_one_half_eq]
+ have h1 : Tendsto (fun s : ℂ ↦ 1 / Gamma (s / 2)) (𝓝[≠] 1) (𝓝 (1 / π ^ (1 / 2 : ℂ))) := by
+ rw [← Complex.Gamma_one_half_eq]
refine (Continuous.tendsto ?_ _).mono_left nhdsWithin_le_nhds
simpa using differentiable_one_div_Gamma.continuous.comp (continuous_id.div_const _)
convert (riemannCompletedZeta_residue_one.mul h0).mul h1 using 2 with s
Add a more general version of the Jacobi theta function with a second variable, and prove the transformation law for this more general function rather than just for the one-variable version. Preparatory to functional equations for Dirichlet L-functions.
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
-/
import Mathlib.Analysis.SpecialFunctions.Gamma.Beta
-import Mathlib.NumberTheory.ModularForms.JacobiTheta.Basic
+import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable
import Mathlib.NumberTheory.ZetaValues
#align_import number_theory.zeta_function from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf"
Complex
lemmas (#9527)
and rename ofReal_mul_re → re_mul_ofReal
, ofReal_mul_im → im_mul_ofReal
.
From LeanAPAP
@@ -113,7 +113,7 @@ theorem riemannZeta_zero : riemannZeta 0 = -1 / 2 := by
/-- The sum defining `zetaKernel₁` is convergent. -/
theorem summable_exp_neg_pi_mul_nat_sq {t : ℝ} (ht : 0 < t) :
Summable fun n : ℕ => rexp (-π * t * ((n : ℝ) + 1) ^ 2) := by
- have : 0 < (↑t * I).im := by rwa [ofReal_mul_im, I_im, mul_one]
+ have : 0 < (↑t * I).im := by rwa [im_ofReal_mul, I_im, mul_one]
convert (hasSum_nat_jacobiTheta this).summable.norm using 1
ext1 n
rw [Complex.norm_eq_abs, Complex.abs_exp]
@@ -470,7 +470,7 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
riemannCompletedZeta s = mellin zetaKernel₁ (s / 2) := by
have : 1 / 2 < (s / 2).re := by
rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
- rwa [ofReal_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
+ rwa [re_ofReal_mul, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
rw [riemannCompletedZeta, riemannCompletedZeta₀, mellin_zetaKernel₂_eq_of_lt_re this, sub_add,
sub_sub, ← add_sub]
conv_rhs => rw [← add_zero (mellin zetaKernel₁ <| s / 2)]
@@ -559,7 +559,7 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
rw [completed_zeta_eq_mellin_of_one_lt_re hs, mellin_zetaKernel₁_eq_tsum, neg_div,
mul_div_cancel' _ (two_ne_zero' ℂ)]
rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
- rwa [ofReal_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
+ rwa [re_ofReal_mul, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
#align completed_zeta_eq_tsum_of_one_lt_re completed_zeta_eq_tsum_of_one_lt_re
/-- The Riemann zeta function agrees with the naive Dirichlet-series definition when the latter
@@ -571,7 +571,7 @@ theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) :
rw [riemannZeta, Function.update_noteq this, completed_zeta_eq_tsum_of_one_lt_re hs, ← mul_assoc,
neg_div, cpow_neg, mul_inv_cancel_left₀, mul_div_cancel_left]
· apply Gamma_ne_zero_of_re_pos
- rw [div_eq_mul_inv, mul_comm, show (2⁻¹ : ℂ) = (2⁻¹ : ℝ) by norm_num, ofReal_mul_re]
+ rw [div_eq_mul_inv, mul_comm, show (2⁻¹ : ℂ) = (2⁻¹ : ℝ) by norm_num, re_ofReal_mul]
exact mul_pos (inv_pos_of_pos two_pos) (zero_lt_one.trans hs)
· rw [Ne.def, cpow_eq_zero_iff, not_and_or, ← Ne.def, ofReal_ne_zero]
exact Or.inl pi_pos.ne'
rpow_nonneg_of_nonneg
to rpow_nonneg
(#9518)
This better matches other lemma names.
From LeanAPAP
@@ -292,7 +292,7 @@ theorem isBigO_zero_zetaKernel₁ : IsBigO (𝓝[>] 0) zetaKernel₁ fun t => t
· refine isBigO_iff.mpr ⟨‖(1 / 2 : ℂ)‖, ?_⟩
refine eventually_of_mem (Ioc_mem_nhdsWithin_Ioi <| left_mem_Ico.mpr zero_lt_one) fun t ht => ?_
refine le_mul_of_one_le_right (norm_nonneg _) ?_
- rw [norm_of_nonneg (rpow_nonneg_of_nonneg ht.1.le _), rpow_neg ht.1.le]
+ rw [norm_of_nonneg (rpow_nonneg ht.1.le _), rpow_neg ht.1.le]
exact one_le_inv (rpow_pos_of_pos ht.1 _) (rpow_le_one ht.1.le ht.2 one_half_pos.le)
set_option linter.uppercaseLean3 false in
#align is_O_zero_zeta_kernel₁ isBigO_zero_zetaKernel₁
@@ -512,7 +512,7 @@ theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
let bd : ℕ → ℝ → ℝ := fun n t => t ^ (s.re - 1) * exp (-π * t * ((n : ℝ) + 1) ^ 2)
let f : ℕ → ℝ → ℂ := fun n t => (t : ℂ) ^ (s - 1) * exp (-π * t * ((n : ℝ) + 1) ^ 2)
have hm : MeasurableSet (Ioi (0 : ℝ)) := measurableSet_Ioi
- have h_norm : ∀ (n : ℕ) {t : ℝ} (_ : 0 < t), ‖f n t‖ = bd n t := by
+ have h_norm : ∀ (n : ℕ) {t : ℝ}, 0 < t → ‖f n t‖ = bd n t := by
intro n t ht
rw [norm_mul, Complex.norm_eq_abs, Complex.norm_eq_abs, Complex.abs_of_nonneg (exp_pos _).le,
abs_cpow_eq_rpow_re_of_pos ht, sub_re, one_re]
@@ -526,7 +526,7 @@ theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
(continuous_exp.comp ((continuous_const.mul continuous_id').mul continuous_const))
have h_le : ∀ n : ℕ, ∀ᵐ t : ℝ ∂volume.restrict (Ioi 0), ‖f n t‖ ≤ bd n t := fun n =>
(ae_restrict_iff' hm).mpr (ae_of_all _ fun t ht => le_of_eq (h_norm n ht))
- have h_sum0 : ∀ {t : ℝ} (_ : 0 < t), HasSum (fun n => f n t)
+ have h_sum0 : ∀ {t : ℝ}, 0 < t → HasSum (fun n => f n t)
((t : ℂ) ^ (s - 1) * zetaKernel₁ t) := by
intro t ht
rw [zetaKernel₁]
We add the computation of the residue of the completed and non-completed Riemann zeta functions at s = 1
.
@@ -799,3 +799,37 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [inv_mul_cancel (ofReal_ne_zero.mpr <| pow_ne_zero _ pi_pos.ne'),
inv_mul_cancel (ofReal_ne_zero.mpr <| pow_ne_zero _ two_ne_zero), one_mul, one_mul]
#align riemann_zeta_neg_nat_eq_bernoulli riemannZeta_neg_nat_eq_bernoulli
+
+/-- The residue of `Λ(s)` at `s = 1` is equal to 1. -/
+lemma riemannCompletedZeta_residue_one :
+ Tendsto (fun s ↦ (s - 1) * riemannCompletedZeta s) (𝓝[≠] 1) (𝓝 1) := by
+ unfold riemannCompletedZeta
+ simp_rw [mul_add, mul_sub, (by simp : 𝓝 (1 : ℂ) = 𝓝 (0 - 0 + 1))]
+ refine ((Tendsto.sub ?_ ?_).mono_left nhdsWithin_le_nhds).add ?_
+ · rw [(by simp : 𝓝 (0 : ℂ) = 𝓝 ((1 - 1) * riemannCompletedZeta₀ 1))]
+ apply ((continuous_sub_right _).mul differentiable_completed_zeta₀.continuous).tendsto
+ · rw [(by simp : 𝓝 (0 : ℂ) = 𝓝 ((1 - 1) * (1 / 1)))]
+ exact (((continuous_sub_right _).continuousAt).mul <|
+ continuousAt_const.div continuousAt_id one_ne_zero)
+ · refine (tendsto_const_nhds.mono_left nhdsWithin_le_nhds).congr' ?_
+ refine eventually_nhdsWithin_of_forall (fun s hs ↦ ?_)
+ simpa using (div_self <| sub_ne_zero_of_ne <| Set.mem_compl_singleton_iff.mpr hs).symm
+
+/-- The residue of `ζ(s)` at `s = 1` is equal to 1. -/
+lemma riemannZeta_residue_one : Tendsto (fun s ↦ (s - 1) * riemannZeta s) (𝓝[≠] 1) (𝓝 1) := by
+ suffices : Tendsto (fun s => (s - 1) *
+ (π ^ (s / 2) * riemannCompletedZeta s / Gamma (s / 2))) (𝓝[≠] 1) (𝓝 1)
+ · refine this.congr' <| (eventually_ne_nhdsWithin one_ne_zero).mp (eventually_of_forall ?_)
+ intro x hx
+ simp [riemannZeta_def, Function.update_noteq hx]
+ have h0 : Tendsto (fun s ↦ π ^ (s / 2) : ℂ → ℂ) (𝓝[≠] 1) (𝓝 (π ^ (1 / 2 : ℂ)))
+ · refine ((continuousAt_id.div_const _).const_cpow ?_).tendsto.mono_left nhdsWithin_le_nhds
+ exact Or.inl <| ofReal_ne_zero.mpr pi_ne_zero
+ have h1 : Tendsto (fun s : ℂ ↦ 1 / Gamma (s / 2)) (𝓝[≠] 1) (𝓝 (1 / π ^ (1 / 2 : ℂ)))
+ · rw [← Complex.Gamma_one_half_eq]
+ refine (Continuous.tendsto ?_ _).mono_left nhdsWithin_le_nhds
+ simpa using differentiable_one_div_Gamma.continuous.comp (continuous_id.div_const _)
+ convert (riemannCompletedZeta_residue_one.mul h0).mul h1 using 2 with s
+ · ring
+ · have := fun h ↦ ofReal_ne_zero.mpr pi_ne_zero ((cpow_eq_zero_iff _ (1 / 2)).mp h).1
+ field_simp
[a, +oo)
(#8712)
We have in the library the lemma not_intervalIntegrable_of_tendsto_norm_atTop_of_deriv_isBigO_filter
, saying that if a function tends to infinity at a point in an interval [a, b]
, then its derivative is not interval-integrable on [a, b]
. We generalize this result to allow for any set instead of [a, b]
, and apply it to half-infinite intervals.
In particular, we characterize integrability of x^s
on [a, +oo)
, and deduce that x^s
is never integrable on [0, +oo)
. This makes it possible to remove one assumption in Lemma mellin_comp_rpow
on the Mellin transform.
@@ -172,8 +172,10 @@ theorem locally_integrable_zetaKernel₂ : LocallyIntegrableOn zetaKernel₂ (Io
#align locally_integrable_zeta_kernel₂ locally_integrable_zetaKernel₂
/-- Functional equation for `zetaKernel₂`. -/
-theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) :
+theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 ≤ t) :
zetaKernel₂ (1 / t) = sqrt t * zetaKernel₂ t := by
+ rcases ht.eq_or_lt with rfl|h't
+ · simp [zetaKernel₂, zetaKernel₁]
have aux : ∀ {u : ℝ} (_ : 1 < u), zetaKernel₂ (1 / u) = sqrt u * zetaKernel₂ u := by
intro u hu
simp_rw [zetaKernel₂, Pi.add_apply]
@@ -195,9 +197,9 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) :
rcases lt_trichotomy 1 t with (h | h | h)
· exact aux h
· simp only [← h, div_self, Ne.def, one_ne_zero, not_false_iff, sqrt_one, ofReal_one, one_mul]
- · have := aux (show 1 < 1 / t by rwa [lt_one_div (zero_lt_one' ℝ) ht, div_one])
+ · have := aux (show 1 < 1 / t by rwa [lt_one_div (zero_lt_one' ℝ) h't, div_one])
rw [one_div_one_div] at this
- rw [this, ← mul_assoc, ← ofReal_mul, ← sqrt_mul ht.le, mul_one_div_cancel ht.ne', sqrt_one,
+ rw [this, ← mul_assoc, ← ofReal_mul, ← sqrt_mul ht, mul_one_div_cancel h't.ne', sqrt_one,
ofReal_one, one_mul]
#align zeta_kernel₂_one_div zetaKernel₂_one_div
@@ -240,7 +242,7 @@ theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => ex
simp_rw [← one_div] at h1
have h2 : zetaKernel₂ ∘ Div.div 1 =ᶠ[𝓝[>] 0] fun t => sqrt t * zetaKernel₂ t :=
eventually_of_mem self_mem_nhdsWithin fun t ht => by
- dsimp only; rw [← zetaKernel₂_one_div ht]; rfl
+ dsimp only; rw [← zetaKernel₂_one_div (le_of_lt ht)]; rfl
have h3 := h1.congr' h2 (EventuallyEq.refl _ _)
have h4 := h3.mul (isBigO_refl (fun t : ℝ => 1 / (sqrt t : ℂ)) (𝓝[>] 0)).norm_right
refine h4.congr' ?_ ?_
@@ -641,12 +643,12 @@ theorem riemannZeta_four : riemannZeta 4 = π ^ 4 / 90 := by
`Λ₀(1 - s) = Λ₀ s`. -/
theorem riemannCompletedZeta₀_one_sub (s : ℂ) :
riemannCompletedZeta₀ (1 - s) = riemannCompletedZeta₀ s := by
- have := mellin_comp_rpow zetaKernel₂ (s / 2 - 1 / 2) neg_one_lt_zero.ne
+ have := mellin_comp_rpow zetaKernel₂ (s / 2 - 1 / 2) (-1)
simp_rw [rpow_neg_one, ← one_div, abs_neg, abs_one, div_one, one_smul, ofReal_neg, ofReal_one,
div_neg, div_one, neg_sub] at this
conv_lhs => rw [riemannCompletedZeta₀, sub_div, ← this]
refine set_integral_congr measurableSet_Ioi fun t ht => ?_
- simp_rw [zetaKernel₂_one_div ht, smul_eq_mul, ← mul_assoc, sqrt_eq_rpow,
+ simp_rw [zetaKernel₂_one_div (le_of_lt ht), smul_eq_mul, ← mul_assoc, sqrt_eq_rpow,
ofReal_cpow (le_of_lt ht), ← cpow_add _ _ (ofReal_ne_zero.mpr <| ne_of_gt ht)]
congr 2
push_cast
@@ -412,7 +412,7 @@ theorem riemannZeta_neg_two_mul_nat_add_one (n : ℕ) : riemannZeta (-2 * (n + 1
div_zero]
#align riemann_zeta_neg_two_mul_nat_add_one riemannZeta_neg_two_mul_nat_add_one
-/-- A formal statement of the Riemann hypothesis – constructing a term of this type is worth a
+/-- A formal statement of the **Riemann hypothesis** – constructing a term of this type is worth a
million dollars. -/
def RiemannHypothesis : Prop :=
∀ (s : ℂ) (_ : riemannCompletedZeta s = 0) (_ : ¬∃ n : ℕ, s = -2 * (n + 1)), s.re = 1 / 2
This is the supremum of
along with some minor fixes from failures on nightly-testing as Mathlib master
is merged into it.
Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.
I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0
branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.
In particular this includes adjustments for the Lean PRs
We can get rid of all the
local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)
macros across Mathlib (and in any projects that want to write natural number powers of reals).
Changes the default behaviour of simp
to (config := {decide := false})
. This makes simp
(and consequentially norm_num
) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp
or norm_num
to decide
or rfl
, or adding (config := {decide := true})
.
This changed the behaviour of simp
so that simp [f]
will only unfold "fully applied" occurrences of f
. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true })
. We may in future add a syntax for this, e.g. simp [!f]
; please provide feedback! In the meantime, we have made the following changes:
(config := { unfoldPartialApp := true })
in some places, to recover the old behaviour@[eqns]
to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp
and Function.flip
.This change in Lean may require further changes down the line (e.g. adding the !f
syntax, and/or upstreaming the special treatment for Function.comp
and Function.flip
, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!
Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>
@@ -68,8 +68,6 @@ noncomputable section
## Definition of the Riemann zeta function and related functions
-/
-local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue lean4#2220
-
/-- Function whose Mellin transform is `π ^ (-s) * Γ(s) * zeta (2 * s)`, for `1 / 2 < Re s`. -/
def zetaKernel₁ (t : ℝ) : ℂ :=
∑' n : ℕ, rexp (-π * t * ((n : ℝ) + 1) ^ 2)
@@ -493,7 +491,7 @@ theorem integral_cpow_mul_exp_neg_pi_mul_sq {s : ℂ} (hs : 0 < s.re) (n : ℕ)
conv_rhs =>
congr
rw [← smul_eq_mul, ← mellin_comp_mul_left _ _ pi_pos]
- have : 1 / ((n : ℂ) + 1) ^ (2 * s) = (((n : ℝ) + 1) ^ (2 : ℝ) : ℂ) ^ (-s) := by
+ have : 1 / ((n : ℂ) + 1) ^ (2 * s) = (((n + 1) ^ (2 : ℝ) : ℝ) : ℂ) ^ (-s) := by
rw [(by norm_num : (n : ℂ) + 1 = ↑((n : ℝ) + 1)), (by norm_num : 2 * s = ↑(2 : ℝ) * s),
cpow_mul_ofReal_nonneg, one_div, cpow_neg]
rw [← Nat.cast_succ]
summable_of_norm_bounded
-> Summable.of_norm_bounded
;summable_of_norm_bounded_eventually
-> Summable.of_norm_bounded_eventually
;summable_of_nnnorm_bounded
-> Summable.of_nnnorm_bounded
;summable_of_summable_norm
-> Summable.of_norm
;summable_of_summable_nnnorm
-> Summable.of_nnnorm
;Summable.of_norm_bounded_eventually_nat
Summable.norm
@@ -116,7 +116,7 @@ theorem riemannZeta_zero : riemannZeta 0 = -1 / 2 := by
theorem summable_exp_neg_pi_mul_nat_sq {t : ℝ} (ht : 0 < t) :
Summable fun n : ℕ => rexp (-π * t * ((n : ℝ) + 1) ^ 2) := by
have : 0 < (↑t * I).im := by rwa [ofReal_mul_im, I_im, mul_one]
- convert summable_norm_iff.mpr (hasSum_nat_jacobiTheta this).summable using 1
+ convert (hasSum_nat_jacobiTheta this).summable.norm using 1
ext1 n
rw [Complex.norm_eq_abs, Complex.abs_exp]
rw [show ↑π * I * ((n : ℂ) + 1) ^ 2 * (↑t * I) = ((π * t * ((n : ℝ) + 1) ^ 2) : ℝ) * I ^ 2 by
@@ -539,7 +539,7 @@ theorem mellin_zetaKernel₁_eq_tsum {s : ℂ} (hs : 1 / 2 < s.re) :
(ae_restrict_iff' hm).mpr (ae_of_all _ fun t ht => h_sum0 ht)
have h_sum : ∀ᵐ t : ℝ ∂volume.restrict (Ioi 0), Summable fun n : ℕ => bd n t := by
refine (ae_restrict_iff' hm).mpr (ae_of_all _ fun t ht => ?_)
- simpa only [fun n => h_norm n ht] using summable_norm_iff.mpr (h_sum0 ht).summable
+ simpa only [fun n => h_norm n ht] using (h_sum0 ht).summable.norm
have h_int : Integrable (fun t : ℝ => ∑' n : ℕ, bd n t) (volume.restrict (Ioi 0)) := by
refine IntegrableOn.congr_fun
(mellinConvergent_of_isBigO_rpow_exp pi_pos locally_integrable_zetaKernel₁
@@ -585,7 +585,7 @@ theorem zeta_eq_tsum_one_div_nat_cpow {s : ℂ} (hs : 1 < re s) :
rw [tsum_eq_zero_add]
· simp_rw [Nat.cast_zero, zero_cpow hs', div_zero, zero_add,
zeta_eq_tsum_one_div_nat_add_one_cpow hs, Nat.cast_add, Nat.cast_one]
- · rw [← summable_norm_iff]
+ · refine .of_norm ?_
simp_rw [norm_div, norm_one, Complex.norm_eq_abs, ← ofReal_nat_cast,
abs_cpow_eq_rpow_re_of_nonneg (Nat.cast_nonneg _) (zero_lt_one.trans hs).ne',
summable_one_div_nat_rpow]
Fix a typo in module doc string (pointed out on zulip: https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/Euler.20products/near/400126787)
@@ -30,7 +30,7 @@ I haven't checked exactly what they are).
* `differentiableAt_completed_zeta` : the function `Λ(s)` is differentiable away from `s = 0` and
`s = 1`.
* `differentiableAt_riemannZeta` : the function `ζ(s)` is differentiable away from `s = 1`.
-* `zeta_eq_tsum_of_one_lt_re` : for `1 < re s`, we have
+* `zeta_eq_tsum_one_div_nat_add_one_cpow` : for `1 < re s`, we have
`ζ(s) = ∑' (n : ℕ), 1 / (n + 1) ^ s`.
* `riemannCompletedZeta₀_one_sub`, `riemannCompletedZeta_one_sub`, and `riemannZeta_one_sub` :
functional equation relating values at `s` and `1 - s`
MulZeroClass.
in mul_zero
/zero_mul
(#6682)
Search&replace MulZeroClass.mul_zero
-> mul_zero
, MulZeroClass.zero_mul
-> zero_mul
.
These were introduced by Mathport, as the full name of mul_zero
is actually MulZeroClass.mul_zero
(it's exported with the short name).
@@ -377,12 +377,12 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
· refine Tendsto.mono_left ?_ nhdsWithin_le_nhds
have : ContinuousAt riemannCompletedZeta₀ 0 :=
differentiable_completed_zeta₀.continuous.continuousAt
- simpa only [id.def, MulZeroClass.mul_zero] using Tendsto.mul this tendsto_id
+ simpa only [id.def, mul_zero] using Tendsto.mul this tendsto_id
· refine tendsto_const_nhds.congr' (eventuallyEq_of_mem self_mem_nhdsWithin fun t ht => ?_)
simp_rw [one_div_mul_cancel ht]
· refine Tendsto.mono_left ?_ nhdsWithin_le_nhds
suffices ContinuousAt (fun z : ℂ => 1 / (z - 1)) 0 by
- simpa only [id.def, MulZeroClass.mul_zero] using Tendsto.mul this tendsto_id
+ simpa only [id.def, mul_zero] using Tendsto.mul this tendsto_id
refine continuousAt_const.div (continuousAt_id.sub continuousAt_const) ?_
simpa only [zero_sub] using neg_ne_zero.mpr one_ne_zero
-- Now the main proof.
@@ -397,7 +397,7 @@ theorem differentiableAt_riemannZeta {s : ℂ} (hs' : s ≠ 1) : DifferentiableA
have S_nhds : {(1 : ℂ)}ᶜ ∈ 𝓝 (0 : ℂ) := isOpen_compl_singleton.mem_nhds hs'
refine ((Complex.differentiableOn_update_limUnder_of_isLittleO S_nhds
(fun t ht => (c1 t ht.2 ht.1).differentiableWithinAt) ?_) 0 hs').differentiableAt S_nhds
- simp only [zero_div, div_zero, Complex.Gamma_zero, MulZeroClass.mul_zero, cpow_zero, sub_zero]
+ simp only [zero_div, div_zero, Complex.Gamma_zero, mul_zero, cpow_zero, sub_zero]
-- Remains to show completed zeta is `o (s ^ (-1))` near 0.
refine (isBigO_const_of_tendsto c2 <| one_ne_zero' ℂ).trans_isLittleO ?_
rw [isLittleO_iff_tendsto']
@@ -689,7 +689,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
have h_Ga_ne3 : Gamma ((s + 1) / 2) ≠ 0 := by
have h_Ga_aux : Gamma s ≠ 0 := Complex.Gamma_ne_zero hs
contrapose! h_Ga_aux
- rw [h_Ga_eq, h_Ga_aux, MulZeroClass.mul_zero, MulZeroClass.zero_mul, zero_div]
+ rw [h_Ga_eq, h_Ga_aux, mul_zero, zero_mul, zero_div]
rw [riemannZeta, Function.update_noteq (by rwa [sub_ne_zero, ne_comm] : 1 - s ≠ 0),
Function.update_noteq hs_ne, riemannCompletedZeta_one_sub, mul_div, eq_div_iff h_Ga_ne1,
mul_comm, ← mul_div_assoc]
@@ -702,7 +702,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left _ (two_ne_zero' ℂ)]
rw [this, Complex.Gamma_neg_nat_eq_zero, div_zero]
have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast; field_simp; ring
- rw [this, Complex.sin_int_mul_pi, MulZeroClass.mul_zero, MulZeroClass.zero_mul]
+ rw [this, Complex.sin_int_mul_pi, mul_zero, zero_mul]
have h_Ga_ne4 : Gamma ((1 - s) / 2) ≠ 0 := by
rw [Ne.def, Complex.Gamma_eq_zero_iff]
contrapose! hs_pos_odd
@@ -738,7 +738,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [Nat.cast_mul, ← neg_mul, Nat.cast_two, Nat.cast_succ, riemannZeta_neg_two_mul_nat_add_one,
bernoulli_eq_bernoulli'_of_ne_one]
swap; · apply ne_of_gt; norm_num
- rw [bernoulli'_odd_eq_zero ⟨m + 1, rfl⟩ (by norm_num), Rat.cast_zero, MulZeroClass.mul_zero,
+ rw [bernoulli'_odd_eq_zero ⟨m + 1, rfl⟩ (by norm_num), Rat.cast_zero, mul_zero,
zero_div]
· -- k = 2 * m + 1 : the interesting case
rw [Odd.neg_one_pow ⟨m, rfl⟩]
@@ -247,7 +247,7 @@ theorem isBigO_zero_zetaKernel₂ : IsBigO (𝓝[>] 0) zetaKernel₂ fun t => ex
have h4 := h3.mul (isBigO_refl (fun t : ℝ => 1 / (sqrt t : ℂ)) (𝓝[>] 0)).norm_right
refine h4.congr' ?_ ?_
· refine eventually_of_mem self_mem_nhdsWithin fun x hx => ?_
- simp_rw [← mul_assoc]
+ dsimp
rw [mul_comm, ← mul_assoc, one_div_mul_cancel, one_mul]
exact ofReal_ne_zero.mpr ((sqrt_ne_zero <| le_of_lt hx).mpr (ne_of_gt hx))
· refine eventually_of_mem self_mem_nhdsWithin fun x _ => ?_
@@ -68,8 +68,7 @@ noncomputable section
## Definition of the Riemann zeta function and related functions
-/
--- Porting note: see https://github.com/leanprover/lean4/issues/2220
-local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y)
+local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue lean4#2220
/-- Function whose Mellin transform is `π ^ (-s) * Γ(s) * zeta (2 * s)`, for `1 / 2 < Re s`. -/
def zetaKernel₁ (t : ℝ) : ℂ :=
@@ -2,16 +2,13 @@
Copyright (c) 2023 David Loeffler. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Loeffler
-
-! This file was ported from Lean 3 source module number_theory.zeta_function
-! leanprover-community/mathlib commit 57f9349f2fe19d2de7207e99b0341808d977cdcf
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathlib.Analysis.SpecialFunctions.Gamma.Beta
import Mathlib.NumberTheory.ModularForms.JacobiTheta.Basic
import Mathlib.NumberTheory.ZetaValues
+#align_import number_theory.zeta_function from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf"
+
/-!
# Definition of the Riemann zeta function
This is the second half of the changes originally in #5699, removing all occurrences of ;
after a space and implementing a linter rule to enforce it.
In most cases this 2-character substring has a space after it, so the following command was run first:
find . -type f -name "*.lean" -exec sed -i -E 's/ ; /; /g' {} \;
The remaining cases were few enough in number that they were done manually.
@@ -124,7 +124,7 @@ theorem summable_exp_neg_pi_mul_nat_sq {t : ℝ} (ht : 0 < t) :
ext1 n
rw [Complex.norm_eq_abs, Complex.abs_exp]
rw [show ↑π * I * ((n : ℂ) + 1) ^ 2 * (↑t * I) = ((π * t * ((n : ℝ) + 1) ^ 2) : ℝ) * I ^ 2 by
- push_cast ; ring]
+ push_cast; ring]
rw [I_sq, mul_neg_one, ← ofReal_neg, ofReal_re, neg_mul, neg_mul]
#align summable_exp_neg_pi_mul_nat_sq summable_exp_neg_pi_mul_nat_sq
@@ -414,7 +414,7 @@ theorem riemannZeta_neg_two_mul_nat_add_one (n : ℕ) : riemannZeta (-2 * (n + 1
have : (-2 : ℂ) * (n + 1) ≠ 0 :=
mul_ne_zero (neg_ne_zero.mpr two_ne_zero) (Nat.cast_add_one_ne_zero n)
rw [riemannZeta, Function.update_noteq this,
- show -2 * ((n : ℂ) + 1) / 2 = -↑(n + 1) by push_cast ; ring, Complex.Gamma_neg_nat_eq_zero,
+ show -2 * ((n : ℂ) + 1) / 2 = -↑(n + 1) by push_cast; ring, Complex.Gamma_neg_nat_eq_zero,
div_zero]
#align riemann_zeta_neg_two_mul_nat_add_one riemannZeta_neg_two_mul_nat_add_one
@@ -473,7 +473,7 @@ theorem mellin_zetaKernel₂_eq_of_lt_re {s : ℂ} (hs : 1 / 2 < s.re) :
theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
riemannCompletedZeta s = mellin zetaKernel₁ (s / 2) := by
have : 1 / 2 < (s / 2).re := by
- rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast ; rw [mul_comm]; rfl]
+ rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
rwa [ofReal_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
rw [riemannCompletedZeta, riemannCompletedZeta₀, mellin_zetaKernel₂_eq_of_lt_re this, sub_add,
sub_sub, ← add_sub]
@@ -562,7 +562,7 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) :
(π : ℂ) ^ (-s / 2) * Gamma (s / 2) * ∑' n : ℕ, 1 / ((n : ℂ) + 1) ^ s := by
rw [completed_zeta_eq_mellin_of_one_lt_re hs, mellin_zetaKernel₁_eq_tsum, neg_div,
mul_div_cancel' _ (two_ne_zero' ℂ)]
- rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast ; rw [mul_comm]; rfl]
+ rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl]
rwa [ofReal_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)]
#align completed_zeta_eq_tsum_of_one_lt_re completed_zeta_eq_tsum_of_one_lt_re
@@ -705,7 +705,7 @@ theorem riemannZeta_one_sub {s : ℂ} (hs : ∀ n : ℕ, s ≠ -n) (hs' : s ≠
have : (1 - (1 + 2 * (n : ℂ))) / 2 = -↑n := by
rw [← sub_sub, sub_self, zero_sub, neg_div, mul_div_cancel_left _ (two_ne_zero' ℂ)]
rw [this, Complex.Gamma_neg_nat_eq_zero, div_zero]
- have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast ; field_simp; ring
+ have : (π : ℂ) * (1 - (1 + 2 * ↑n)) / 2 = ↑(-n : ℤ) * π := by push_cast; field_simp; ring
rw [this, Complex.sin_int_mul_pi, MulZeroClass.mul_zero, MulZeroClass.zero_mul]
have h_Ga_ne4 : Gamma ((1 - s) / 2) ≠ 0 := by
rw [Ne.def, Complex.Gamma_eq_zero_iff]
@@ -746,7 +746,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
zero_div]
· -- k = 2 * m + 1 : the interesting case
rw [Odd.neg_one_pow ⟨m, rfl⟩]
- rw [show -(↑(2 * m + 1) : ℂ) = 1 - (2 * m + 2) by push_cast ; ring]
+ rw [show -(↑(2 * m + 1) : ℂ) = 1 - (2 * m + 2) by push_cast; ring]
rw [riemannZeta_one_sub]
rotate_left
· intro n
@@ -762,10 +762,10 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rcases Nat.even_or_odd' m with ⟨t, rfl | rfl⟩
· rw [pow_mul, neg_one_sq, one_pow]
convert Complex.cos_nat_mul_two_pi t using 2
- push_cast ; ring_nf
+ push_cast; ring_nf
· rw [pow_add, pow_one, pow_mul, neg_one_sq, one_pow, one_mul]
convert Complex.cos_nat_mul_two_pi_add_pi t using 2
- push_cast ; ring_nf]
+ push_cast; ring_nf]
-- substitute in what we know about zeta values at positive integers
have step1 := congr_arg ((↑) : ℝ → ℂ) (hasSum_zeta_nat (by norm_num : m + 1 ≠ 0)).tsum_eq
have step2 := zeta_nat_eq_tsum_of_gt_one (by rw [mul_add]; norm_num : 1 < 2 * (m + 1))
@@ -774,7 +774,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
rw [step2, mul_div]
-- now the rest is just a lengthy but elementary rearrangement
rw [show ((2 * (m + 1))! : ℂ) = Complex.Gamma (2 * m + 2) * (↑(2 * m + 1) + 1) by
- rw [(by push_cast ; ring : (2 * m + 2 : ℂ) = ↑(2 * m + 1) + 1),
+ rw [(by push_cast; ring : (2 * m + 2 : ℂ) = ↑(2 * m + 1) + 1),
Complex.Gamma_nat_eq_factorial, (by ring : 2 * (m + 1) = 2 * m + 1 + 1),
Nat.factorial_succ, Nat.cast_mul, mul_comm]
norm_num]
@@ -796,7 +796,7 @@ theorem riemannZeta_neg_nat_eq_bernoulli (k : ℕ) :
congr 1
rw [Nat.add_sub_assoc one_le_two, Nat.cast_add, Nat.cast_mul, Nat.cast_two,
(by norm_num : 2 - 1 = 1)]
- push_cast ; ring]
+ push_cast; ring]
rw [show (π : ℂ) ^ (-(2 * (m : ℂ) + 2)) = (↑(π ^ (2 * m + 2)))⁻¹ by
rw [ofReal_pow, ← cpow_nat_cast, ← cpow_neg, Nat.cast_add, Nat.cast_mul, Nat.cast_two]]
rw [(by intros; ring : ∀ a b c d e : ℂ, a * b * c * d * e = a * d * (b * e) * c)]
Also define UpperHalfPlane.coe
so that type synonym doesn't leak through API.
@@ -190,12 +190,12 @@ theorem zetaKernel₂_one_div {t : ℝ} (ht : 0 < t) :
sub_add_cancel, sqrt_div zero_le_one, sqrt_one, one_div (sqrt _), ofReal_inv, ← one_div,
one_div_one_div, mul_sub, mul_one]
congr 2
- let τ : UpperHalfPlane := ⟨u * I, (mul_I_im u).symm ▸ zero_lt_one.trans hu⟩
+ let τ : UpperHalfPlane := .mk (u * I) ((mul_I_im u).symm ▸ zero_lt_one.trans hu)
convert jacobiTheta_S_smul τ using 2
- · rw [UpperHalfPlane.modular_S_smul, UpperHalfPlane.coe_mk, Subtype.coe_mk, ← neg_inv, mul_inv,
- inv_I, mul_neg, neg_neg, one_div, ofReal_inv]
- · rw [Subtype.coe_mk, mul_comm, mul_assoc, mul_neg, I_mul_I, neg_neg, mul_one, sqrt_eq_rpow,
- ofReal_cpow (zero_lt_one.trans hu).le]
+ · rw [UpperHalfPlane.modular_S_smul, UpperHalfPlane.coe_mk, UpperHalfPlane.coe_mk, ← neg_inv,
+ mul_inv, inv_I, mul_neg, neg_neg, one_div, ofReal_inv]
+ · rw [UpperHalfPlane.coe_mk, mul_comm, mul_assoc, mul_neg, I_mul_I, neg_neg, mul_one,
+ sqrt_eq_rpow, ofReal_cpow (zero_lt_one.trans hu).le]
push_cast
rfl
rcases lt_trichotomy 1 t with (h | h | h)
@@ -214,7 +214,6 @@ We now establish asymptotic bounds for the zeta kernels as `t → ∞` and `t
show holomorphy of their Mellin transforms (for `1 / 2 < re s` for `zetaKernel₁`, and all `s` for
`zetaKernel₂`). -/
-
/-- Bound for `zetaKernel₁` for large `t`. -/
theorem isBigO_atTop_zetaKernel₁ : IsBigO atTop zetaKernel₁ fun t => exp (-π * t) := by
have h := isBigO_at_im_infty_jacobiTheta_sub_one.const_mul_left (1 / 2)
@@ -306,7 +305,6 @@ set_option linter.uppercaseLean3 false in
## Differentiability of the completed zeta function
-/
-
/-- The Mellin transform of the first zeta kernel is holomorphic for `1 / 2 < re s`. -/
theorem differentiableAt_mellin_zetaKernel₁ {s : ℂ} (hs : 1 / 2 < s.re) :
DifferentiableAt ℂ (mellin zetaKernel₁) s :=
@@ -103,7 +103,7 @@ irreducible_def riemannZeta :=
#align riemann_zeta riemannZeta
/- Note the next lemma is true by definition; what's hard is to show that with this definition, `ζ`
-is continuous (and indeed analytic) at 0, see `differentiable_riemann_zeta` below. -/
+is continuous (and indeed analytic) at 0, see `differentiableAt_riemannZeta` below. -/
/-- We have `ζ(0) = -1 / 2`. -/
theorem riemannZeta_zero : riemannZeta 0 = -1 / 2 := by
rw [riemannZeta_def]
The unported dependencies are
algebra.order.module
init.core
linear_algebra.free_module.finite.rank
algebra.order.monoid.cancel.defs
algebra.abs
algebra.group_power.lemmas
init.data.list.basic
linear_algebra.free_module.rank
algebra.order.monoid.cancel.basic
init.data.list.default
topology.subset_properties
init.logic
The following 1 dependencies have changed in mathlib3 since they were ported, which may complicate porting this file