Skip to content

Commit 49586f3

Browse files
committed
feat(NumberTheory/ArithmeticFunction/LFunction): arithmetic functions from power series (#36642)
This PR constructs arithmetic functions from power series. See #36189 for how this will ultimately be used to construct L-functions. Co-authored-by: tb65536 <thomas.l.browning@gmail.com>
1 parent ff84feb commit 49586f3

3 files changed

Lines changed: 141 additions & 0 deletions

File tree

Mathlib/NumberTheory/ArithmeticFunction/Defs.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ instance {S : Type*} [CommSemiring R] [Semiring S] [Algebra R S] :
338338
.ofModule (fun x f g ↦ ext fun n ↦ by simp [Finset.smul_sum])
339339
fun x f g ↦ ext fun n ↦ by simp [Finset.smul_sum]
340340

341+
@[simp]
342+
theorem algebraMap_apply_one {S : Type*} [CommSemiring R] [Semiring S] [Algebra R S] (x : R) :
343+
algebraMap R (ArithmeticFunction S) x 1 = algebraMap R S x := by
344+
simp [Algebra.algebraMap_eq_smul_one]
345+
341346
instance {M : Type*} [Semiring R] [AddCommMonoid M] [Module R M] :
342347
Module (ArithmeticFunction R) (ArithmeticFunction M) where
343348
one_smul := one_smul'

Mathlib/NumberTheory/ArithmeticFunction/LFunction.lean

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Authors: Thomas Browning
66
module
77

88
public import Mathlib.NumberTheory.ArithmeticFunction.Defs
9+
public import Mathlib.RingTheory.PowerSeries.Basic
910
public import Mathlib.RingTheory.PowerSeries.PiTopology
1011
public import Mathlib.RingTheory.PowerSeries.Substitution
1112

@@ -16,13 +17,139 @@ This file constructs L-functions as formal Dirichlet series.
1617
1718
## Main definitions
1819
20+
* `ArithmeticFunction.ofPowerSeries q f`: L-function `f(q⁻ˢ)` obtained from a power series `f(T)`.
1921
* `ArithmeticFunction.eulerProduct f`: the Euler product of a family `f i` of Dirichlet series.
22+
23+
## Implementation notes
24+
25+
We take the following route from polynomials to L-functions:
26+
* Starting from a polynomial in `T`, `PowerSeries.invOfUnit` gives the reciporical power series.
27+
* `ofPowerSeries` gives the local Euler factor as a formal Dirichlet series on powers of `q`.
28+
* `eulerProduct` gives the L-function as the formal product of these local Euler factors.
29+
* `LSeries` gives the L-function as an analytic function on the right half-plane of convergence.
30+
31+
For example, the Riemann zeta function `ζ(s)` corresponds to taking `1 - T` at each prime `p`.
32+
33+
For context, here is a diagram of the possible routes from polynomials to L-functions:
34+
35+
T=q⁻ˢ s ∈ ℂ
36+
[polynomials in T] ----> [polynomials in q⁻ˢ] ----> [analytic function in s]
37+
| | |
38+
| (reciprocal) | (reciprocal) | (reciprocal)
39+
v T=q⁻ˢ V s ∈ ℂ V
40+
[power series in T] ----> [power series in q⁻ˢ] ----> [analytic function in s] (the Euler factor)
41+
| | |
42+
| (product) | (product) | (product)
43+
v T=q⁻ˢ V s ∈ ℂ V
44+
[multivariate power series] ----> [Dirichlet series] ----> [L-function in s] (the Euler product)
45+
46+
## TODO
47+
48+
* If each `q` is a prime power, then `ArithmeticFunction.ofPowerSeries q f` is multiplicative.
2049
-/
2150

2251
@[expose] public section
2352

2453
namespace ArithmeticFunction
2554

55+
section PowerSeries
56+
57+
variable {R : Type*} [CommSemiring R]
58+
59+
set_option backward.isDefEq.respectTransparency false in
60+
/-- The arithmetic function corresponding to the Dirichlet series `f(q⁻ˢ)`.
61+
For example, if `f = 1 + X + X² + ...` and `q = p`, then `f(q⁻ˢ) = 1 + p⁻ˢ + p⁻²ˢ + ...`.
62+
63+
If `q ≤ 1` then `k ↦ q ^ k` is not injective, so we use the junk value `f.constantCoeff`. -/
64+
noncomputable def ofPowerSeries (q : ℕ) : PowerSeries R →ₐ[R] ArithmeticFunction R where
65+
toFun f := if hq : 1 < q then
66+
⟨Function.extend (q ^ ·) (f.coeff ·) 0, by simp [Nat.ne_zero_of_lt hq]⟩ else
67+
algebraMap R (ArithmeticFunction R) f.constantCoeff
68+
map_zero' := by ext; split_ifs <;> simp [Function.extend]
69+
-- note that `ofPowerSeries.map_one'` relies on the junk value `f.constantCoeff`.
70+
map_one' := by
71+
ext n
72+
split_ifs with hq
73+
· by_cases hn : ∃ k, q ^ k = n
74+
· obtain ⟨a, rfl⟩ := hn
75+
simp [(Nat.pow_right_injective hq).extend_apply, one_apply, hq.ne']
76+
· simp [hn, one_apply_ne (fun H ↦ hn ⟨0, H.symm⟩)]
77+
· simp
78+
map_add' f g := by
79+
ext n
80+
split_ifs with hq
81+
· by_cases h : ∃ a, q ^ a = n
82+
· obtain ⟨a, rfl⟩ := h
83+
simp [(Nat.pow_right_injective hq).extend_apply]
84+
· simp [h]
85+
· by_cases hn : n = 1 <;> simp [hn]
86+
map_mul' f g := by
87+
ext n
88+
split_ifs with hq
89+
· simp_rw [mul_apply, coe_mk]
90+
by_cases hn : ∃ a, q ^ a = n
91+
· obtain ⟨k, rfl⟩ := hn
92+
rw [(Nat.pow_right_injective hq).extend_apply]
93+
have hs : (Finset.antidiagonal k).map (.prodMap ⟨fun k ↦ q ^ k, Nat.pow_right_injective hq⟩
94+
fun k ↦ q ^ k, Nat.pow_right_injective hq⟩) ⊆ (q ^ k).divisorsAntidiagonal :=
95+
Nat.antidiagonal_map_subset_divisorsAntidiagonal_pow hq k
96+
rw [PowerSeries.coeff_mul k f g, ← Finset.sum_subset hs]
97+
· simp [(Nat.pow_right_injective hq).extend_apply]
98+
· intro (a, b) hab h
99+
by_cases ha : ∃ i, q ^ i = a
100+
· by_cases hb : ∃ j, q ^ j = b
101+
· obtain ⟨i, rfl⟩ := ha
102+
obtain ⟨j, rfl⟩ := hb
103+
rw [Nat.mem_divisorsAntidiagonal, ← pow_add, Nat.pow_right_inj hq] at hab
104+
simp_rw [Finset.mem_map, not_exists, not_and, Finset.mem_antidiagonal] at h
105+
simpa using h (i, j) hab.1
106+
· rwa [mul_comm, Function.extend_apply', Pi.zero_apply, zero_mul]
107+
· rwa [Function.extend_apply', Pi.zero_apply, zero_mul]
108+
· rw [Function.extend_apply' _ _ _ hn, Pi.zero_apply, Finset.sum_eq_zero]
109+
intro (a, b) hk
110+
obtain ⟨hab, -⟩ := Nat.mem_divisorsAntidiagonal.mp hk
111+
by_cases ha : ∃ i, q ^ i = a
112+
· by_cases hb : ∃ j, q ^ j = b
113+
· obtain ⟨i, rfl⟩ := ha
114+
obtain ⟨j, rfl⟩ := hb
115+
rw [← pow_add] at hab
116+
exact (hn ⟨i + j, hab⟩).elim
117+
· rwa [mul_comm, Function.extend_apply', Pi.zero_apply, zero_mul]
118+
· rwa [Function.extend_apply', Pi.zero_apply, zero_mul]
119+
· simp
120+
commutes' x := by
121+
ext n
122+
split_ifs with hq
123+
· simp only [Algebra.algebraMap_eq_smul_one, coe_mk]
124+
by_cases hn : ∃ k, q ^ k = n
125+
· obtain ⟨k, rfl⟩ := hn
126+
simp [(Nat.pow_right_injective hq).extend_apply, one_apply, hq.ne']
127+
· rw [Function.extend_apply' _ _ _ hn, Pi.zero_apply, smul_map, one_apply_ne, smul_zero]
128+
contrapose! hn
129+
exact ⟨0, by simp [hn]⟩
130+
· simp
131+
132+
theorem ofPowerSeries_apply {q : ℕ} (hq : 1 < q) (f : PowerSeries R) (n : ℕ) :
133+
ofPowerSeries q f n = Function.extend (q ^ ·) (f.coeff ·) 0 n := by
134+
simp [ofPowerSeries, dif_pos hq]
135+
136+
theorem ofPowerSeries_apply_pow {q : ℕ} (hq : 1 < q) (f : PowerSeries R) (k : ℕ) :
137+
ofPowerSeries q f (q ^ k) = f.coeff k := by
138+
rw [ofPowerSeries_apply hq, (Nat.pow_right_injective hq).extend_apply]
139+
140+
theorem ofPowerSeries_apply_zero (q : ℕ) (f : PowerSeries R) : ofPowerSeries q f 0 = 0 := by
141+
simp
142+
143+
@[simp]
144+
-- note that `ofPowerSeries_apply_one` relies on the junk value `f.constantCoeff`.
145+
theorem ofPowerSeries_apply_one (q : ℕ) (f : PowerSeries R) :
146+
ofPowerSeries q f 1 = f.constantCoeff := by
147+
by_cases hq : 1 < q
148+
· rw [← pow_zero q, ofPowerSeries_apply_pow hq, PowerSeries.coeff_zero_eq_constantCoeff]
149+
· simp [ofPowerSeries, dif_neg hq]
150+
151+
end PowerSeries
152+
26153
section EulerProduct
27154

28155
open Filter

Mathlib/NumberTheory/Divisors.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public import Mathlib.Algebra.Order.BigOperators.Group.Finset
1010
public import Mathlib.Algebra.Order.Interval.Finset.SuccPred
1111
public import Mathlib.Algebra.Order.Ring.Int
1212
public import Mathlib.Algebra.Ring.CharZero
13+
public import Mathlib.Data.Finset.NatAntidiagonal
1314
public import Mathlib.Data.Nat.Cast.Order.Ring
1415
public import Mathlib.Data.Nat.PrimeFin
1516
public import Mathlib.Data.Nat.SuccPred
@@ -605,6 +606,14 @@ lemma divisorsAntidiagonal_eq_prod_filter_of_le {n N : ℕ} (n_ne_zero : n ≠ 0
605606
· intro ⟨⟨hn1, hn2⟩, hn3⟩
606607
exact ⟨hn3, n_ne_zero⟩
607608

609+
/-- `Finset.antidiagonal k` embeds as a subset of `Nat.divisorsAntidiagonal (q ^ k)`. -/
610+
theorem antidiagonal_map_subset_divisorsAntidiagonal_pow {q : ℕ} (hq : 1 < q) (k : ℕ) :
611+
letI ι : ℕ ↪ ℕ := ⟨fun k ↦ q ^ k, Nat.pow_right_injective hq⟩
612+
(Finset.antidiagonal k).map (.prodMap ι ι) ⊆ (q ^ k).divisorsAntidiagonal := by
613+
intro k hk
614+
obtain ⟨i, hi, rfl⟩ := Finset.mem_map.mp hk
615+
simp [Nat.mem_divisorsAntidiagonal, ← Finset.mem_antidiagonal.mp hi, pow_add, ne_zero_of_lt hq]
616+
608617
end Nat
609618

610619
namespace Int

0 commit comments

Comments
 (0)