Skip to content

Commit 2171e8d

Browse files
feat: add API for additive characters (#13389)
This adds some API lemmas for additive characters. * Name change: `AddChar.primitiveCharFiniteField` to `AddChar.FiniteField.primitiveChar` We also remove a porting note (`AddChar.PrimitiveAddChar` can be a structure again) and fix a typo in a lemma name from another recent PR.
1 parent 86ab5d5 commit 2171e8d

File tree

4 files changed

+85
-24
lines changed

4 files changed

+85
-24
lines changed

Mathlib/Algebra/Group/AddChar.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,14 @@ instance instCommGroup : CommGroup (AddChar A M) :=
237237

238238
end fromAddCommGroup
239239

240+
section fromAddGrouptoCommMonoid
241+
242+
/-- The values of an additive character on an additive group are units. -/
243+
lemma val_isUnit {A M} [AddGroup A] [Monoid M] (φ : AddChar A M) (a : A) : IsUnit (φ a) :=
244+
IsUnit.map φ.toMonoidHom <| Group.isUnit (Multiplicative.ofAdd a)
245+
246+
end fromAddGrouptoCommMonoid
247+
240248
section fromAddGrouptoDivisionMonoid
241249

242250
variable {A M : Type*} [AddGroup A] [DivisionMonoid M]

Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Mathlib.NumberTheory.Cyclotomic.PrimitiveRoots
77
import Mathlib.FieldTheory.Finite.Trace
88
import Mathlib.Algebra.Group.AddChar
99
import Mathlib.Data.ZMod.Units
10+
import Mathlib.Analysis.Complex.Polynomial
1011

1112
#align_import number_theory.legendre_symbol.add_character from "leanprover-community/mathlib"@"0723536a0522d24fc2f159a096fb3304bef77472"
1213

@@ -47,12 +48,29 @@ section Additive
4748
-- The domain and target of our additive characters. Now we restrict to a ring in the domain.
4849
variable {R : Type u} [CommRing R] {R' : Type v} [CommMonoid R']
4950

51+
/-- The values of an additive character on a ring of positive characteristic are roots of unity. -/
52+
lemma val_mem_rootsOfUnity (φ : AddChar R R') (a : R) (h : 0 < ringChar R) :
53+
(φ.val_isUnit a).unit ∈ rootsOfUnity (ringChar R).toPNat' R' := by
54+
simp only [mem_rootsOfUnity', IsUnit.unit_spec, Nat.toPNat'_coe, h, ↓reduceIte, ← map_nsmul_pow,
55+
nsmul_eq_mul, CharP.cast_eq_zero, zero_mul, map_zero_one]
56+
5057
/-- An additive character is *primitive* iff all its multiplicative shifts by nonzero
5158
elements are nontrivial. -/
5259
def IsPrimitive (ψ : AddChar R R') : Prop :=
5360
∀ a : R, a ≠ 0 → IsNontrivial (mulShift ψ a)
5461
#align add_char.is_primitive AddChar.IsPrimitive
5562

63+
/-- The composition of a primitive additive character with an injective mooid homomorphism
64+
is also primitive. -/
65+
lemma IsPrimitive.compMulHom_of_isPrimitive {R'' : Type*} [CommMonoid R''] {φ : AddChar R R'}
66+
{f : R' →* R''} (hφ : φ.IsPrimitive) (hf : Function.Injective f) :
67+
(f.compAddChar φ).IsPrimitive := by
68+
intro a a_ne_zero
69+
obtain ⟨r, ne_one⟩ := hφ a a_ne_zero
70+
rw [mulShift_apply] at ne_one
71+
simp only [IsNontrivial, mulShift_apply, f.coe_compAddChar, Function.comp_apply]
72+
exact ⟨r, fun H ↦ ne_one <| hf <| f.map_one ▸ H⟩
73+
5674
/-- The map associating to `a : R` the multiplicative shift of `ψ` by `a`
5775
is injective when `ψ` is primitive. -/
5876
theorem to_mulShift_inj_of_isPrimitive {ψ : AddChar R R'} (hψ : IsPrimitive ψ) :
@@ -87,33 +105,22 @@ lemma not_isPrimitive_mulShift [Finite R] (e : AddChar R R') {r : R}
87105
exact ⟨x, h', by simp only [mulShift_mulShift, mul_comm r, h, mulShift_zero, not_ne_iff,
88106
isNontrivial_iff_ne_trivial]⟩
89107

90-
-- Porting note: Using `structure` gives a timeout, see
91-
-- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/mysterious.20finsupp.20related.20timeout/near/365719262 and
92-
-- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/mysterious.20finsupp.20related.20timeout
93-
-- In Lean4, `set_option genInjectivity false in` may solve this issue.
94-
-- can't prove that they always exist (referring to providing an `Inhabited` instance)
95108
/-- Definition for a primitive additive character on a finite ring `R` into a cyclotomic extension
96109
of a field `R'`. It records which cyclotomic extension it is, the character, and the
97110
fact that the character is primitive. -/
98111
-- Porting note(#5171): this linter isn't ported yet.
112+
-- can't prove that they always exist (referring to providing an `Inhabited` instance)
99113
-- @[nolint has_nonempty_instance]
100-
def PrimitiveAddChar (R : Type u) [CommRing R] (R' : Type v) [Field R'] :=
101-
Σ n : ℕ+, Σ' char : AddChar R (CyclotomicField n R'), IsPrimitive char
114+
structure PrimitiveAddChar (R : Type u) [CommRing R] (R' : Type v) [Field R'] where
115+
/-- The first projection from `PrimitiveAddChar`, giving the cyclotomic field. -/
116+
n : ℕ+
117+
/-- The second projection from `PrimitiveAddChar`, giving the character. -/
118+
char : AddChar R (CyclotomicField n R')
119+
/-- The third projection from `PrimitiveAddChar`, showing that `χ.char` is primitive. -/
120+
prim : IsPrimitive char
102121
#align add_char.primitive_add_char AddChar.PrimitiveAddChar
103-
104-
/-- The first projection from `PrimitiveAddChar`, giving the cyclotomic field. -/
105-
noncomputable def PrimitiveAddChar.n {R : Type u} [CommRing R] {R' : Type v} [Field R'] :
106-
PrimitiveAddChar R R' → ℕ+ := fun χ => χ.1
107122
#align add_char.primitive_add_char.n AddChar.PrimitiveAddChar.n
108-
109-
/-- The second projection from `PrimitiveAddChar`, giving the character. -/
110-
noncomputable def PrimitiveAddChar.char {R : Type u} [CommRing R] {R' : Type v} [Field R'] :
111-
∀ χ : PrimitiveAddChar R R', AddChar R (CyclotomicField χ.n R') := fun χ => χ.2.1
112123
#align add_char.primitive_add_char.char AddChar.PrimitiveAddChar.char
113-
114-
/-- The third projection from `PrimitiveAddChar`, showing that `χ.char` is primitive. -/
115-
theorem PrimitiveAddChar.prim {R : Type u} [CommRing R] {R' : Type v} [Field R'] :
116-
∀ χ : PrimitiveAddChar R R', IsPrimitive χ.char := fun χ => χ.2.2
117124
#align add_char.primitive_add_char.prim AddChar.PrimitiveAddChar.prim
118125

119126
/-!
@@ -225,9 +232,10 @@ end Additive
225232

226233
/-- There is a primitive additive character on the finite field `F` if the characteristic
227234
of the target is different from that of `F`.
235+
228236
We obtain it as the composition of the trace from `F` to `ZMod p` with a primitive
229237
additive character on `ZMod p`, where `p` is the characteristic of `F`. -/
230-
noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Finite F] [Field F']
238+
noncomputable def FiniteField.primitiveChar (F F' : Type*) [Field F] [Finite F] [Field F']
231239
(h : ringChar F' ≠ ringChar F) : PrimitiveAddChar F F' := by
232240
let p := ringChar F
233241
haveI hp : Fact p.Prime := ⟨CharP.char_is_prime F _⟩
@@ -245,13 +253,13 @@ noncomputable def primitiveCharFiniteField (F F' : Type*) [Field F] [Finite F] [
245253
rw [one_mul] at ha
246254
exact ⟨a, fun hf => ha <| (ψ.prim.zmod_char_eq_one_iff pp <| Algebra.trace (ZMod p) F a).mp hf⟩
247255
exact ⟨ψ.n, ψ', hψ'.isPrimitive⟩
248-
#align add_char.primitive_char_finite_field AddChar.primitiveCharFiniteField
256+
#align add_char.primitive_char_finite_field AddChar.FiniteField.primitiveChar
257+
@[deprecated (since := "2024-05-30")] alias primitiveCharFiniteField := FiniteField.primitiveChar
249258

250259
/-!
251260
### The sum of all character values
252261
-/
253262

254-
255263
section sum
256264

257265
variable {R : Type*} [AddGroup R] [Fintype R] {R' : Type*} [CommRing R']
@@ -294,4 +302,49 @@ theorem sum_mulShift {R : Type*} [CommRing R] [Fintype R] [DecidableEq R]
294302
exact mod_cast sum_eq_zero_of_isNontrivial (hψ b h)
295303
#align add_char.sum_mul_shift AddChar.sum_mulShift
296304

305+
/-!
306+
### Complex-valued additive characters
307+
-/
308+
309+
section Ring
310+
311+
variable {R : Type*} [CommRing R]
312+
313+
/-- Post-composing an additive character to `ℂ` with complex conjugation gives the inverse
314+
character. -/
315+
lemma starComp_eq_inv (hR : 0 < ringChar R) {φ : AddChar R ℂ} :
316+
(starRingEnd ℂ).compAddChar φ = φ⁻¹ := by
317+
ext1 a
318+
simp only [RingHom.toMonoidHom_eq_coe, MonoidHom.coe_compAddChar, MonoidHom.coe_coe,
319+
Function.comp_apply, inv_apply']
320+
have H := Complex.norm_eq_one_of_mem_rootsOfUnity <| φ.val_mem_rootsOfUnity a hR
321+
exact (Complex.inv_eq_conj H).symm
322+
323+
lemma starComp_apply (hR : 0 < ringChar R) {φ : AddChar R ℂ} (a : R) :
324+
(starRingEnd ℂ) (φ a) = φ⁻¹ a := by
325+
rw [← starComp_eq_inv hR]
326+
rfl
327+
328+
end Ring
329+
330+
section Field
331+
332+
variable (F : Type*) [Field F] [Finite F] [DecidableEq F]
333+
334+
private lemma ringChar_ne : ringChar ℂ ≠ ringChar F := by
335+
simpa only [ringChar.eq_zero] using (CharP.ringChar_ne_zero_of_finite F).symm
336+
337+
/-- A primitive additive character on the finite field `F` with values in `ℂ`. -/
338+
noncomputable def FiniteField.primitiveChar_to_Complex : AddChar F ℂ := by
339+
refine MonoidHom.compAddChar ?_ (primitiveChar F ℂ <| ringChar_ne F).char
340+
exact (IsCyclotomicExtension.algEquiv ?n ℂ (CyclotomicField ?n ℂ) ℂ : CyclotomicField ?n ℂ →* ℂ)
341+
342+
lemma FiniteField.primitiveChar_to_Complex_isPrimitive :
343+
(primitiveChar_to_Complex F).IsPrimitive := by
344+
refine IsPrimitive.compMulHom_of_isPrimitive (PrimitiveAddChar.prim _) ?_
345+
let nn := (primitiveChar F ℂ <| ringChar_ne F).n
346+
exact (IsCyclotomicExtension.algEquiv nn ℂ (CyclotomicField nn ℂ) ℂ).injective
347+
348+
end Field
349+
297350
end AddChar

Mathlib/NumberTheory/LegendreSymbol/GaussSum.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ theorem Char.card_pow_card {F : Type*} [Field F] [Fintype F] {F' : Type*} [Field
215215
(χ (-1) * Fintype.card F) ^ (Fintype.card F' / 2) = χ (Fintype.card F') := by
216216
obtain ⟨n, hp, hc⟩ := FiniteField.card F (ringChar F)
217217
obtain ⟨n', hp', hc'⟩ := FiniteField.card F' (ringChar F')
218-
let ψ := primitiveCharFiniteField F F' hch₁
218+
let ψ := FiniteField.primitiveChar F F' hch₁
219219
-- Porting note: this was a `let` but then Lean would time out at
220220
-- unification so it is changed to a `set` and `FF'` is replaced by its
221221
-- definition before unification

Mathlib/RingTheory/RootsOfUnity/Complex.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ theorem IsPrimitiveRoot.arg {n : ℕ} {ζ : ℂ} (h : IsPrimitiveRoot ζ n) (hn
188188
· exact Nat.cast_pos.mpr hn.bot_lt
189189
#align is_primitive_root.arg IsPrimitiveRoot.arg
190190

191-
lemma Complex.norm_eq_one_of_mem_rootOfUnity {ζ : ℂˣ} {n : ℕ+} (hζ : ζ ∈ rootsOfUnity n ℂ) :
191+
lemma Complex.norm_eq_one_of_mem_rootsOfUnity {ζ : ℂˣ} {n : ℕ+} (hζ : ζ ∈ rootsOfUnity n ℂ) :
192192
‖(ζ : ℂ)‖ = 1 := by
193193
refine norm_eq_one_of_pow_eq_one ?_ <| n.ne_zero
194194
norm_cast

0 commit comments

Comments
 (0)