l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
noncomputable instance colimitCommMonoid : CommMonoid.{max v u} (M.{v, u} F) :=
  { (M.{v, u} F) with
    mul_comm := fun x y => by
      refine Quot.induction_on₂ x y ?_
      clear x y
      intro x y
      let k := max' x.1 y.1
      let f := IsFiltered.leftToMax x.1 y.1
      let g := IsFiltered.rightToMax x.1 y.1
      rw [colimit_mul_mk_eq.{v, u} (F ⋙ forget₂ CommMonCat MonCat) x y k f g,
        colimit_mul_mk_eq.{v, u} (F ⋙ forget₂ CommMonCat MonCat) y x k g f]
      dsimp
      

Proof state:
J : Type v
inst✝¹ : SmallCategory J
inst✝ : IsFiltered J
F : J ⥤ CommMonCat
src✝ : MonCat := M F
x y : (j : J) × ((F ⋙ forget₂ CommMonCat MonCat) ⋙ forget MonCat).obj j
k : J := IsFiltered.max x.fst y.fst
f : x.fst ⟶ IsFiltered.max x.fst y.fst := IsFiltered.leftToMax x.fst y.fst
g : y.fst ⟶ IsFiltered.max x.fst y.fst := IsFiltered.rightToMax x.fst y.fst
⊢ MonCat.FilteredColimits.M.mk (F ⋙ forget₂ CommMonCat MonCat)
      { fst := IsFiltered.max x.fst y.fst,
        snd :=
          ((forget₂ CommMonCat MonCat).map (F.map (IsFiltered.leftToMax x.fst y.fst))) x.snd *
            ((forget₂ CommMonCat MonCat).map (F.map (IsFiltered.rightToMax x.fst y.fst))) y.snd } =
    MonCat.FilteredColimits.M.mk (F ⋙ forget₂ CommMonCat MonCat)
      { fst := IsFiltered.max x.fst y.fst,
        snd :=
          ((forget₂ CommMonCat MonCat).map (F.map (IsFiltered.rightToMax x.fst y.fst))) y.snd *
            ((forget₂ CommMonCat MonCat).map (F.map (IsFiltered.leftToMax x.fst y.fst))) x.snd }

Next tactic:
rw [mul_comm]
/-- An additive character maps `0` to `1`. -/
@[simp]
theorem map_zero_one (ψ : AddChar R R') : ψ 0 = 1 := by 

Proof state:
R : Type u
inst✝¹ : AddMonoid R
R' : Type v
inst✝ : CommMonoid R'
ψ : AddChar R R'
⊢ ψ 0 = 1

Next tactic:
rw [coe_to_fun_apply, ofAdd_zero, map_one]
/-- An additive character maps sums to products. -/
@[simp]
theorem map_add_mul (ψ : AddChar R R') (x y : R) : ψ (x + y) = ψ x * ψ y := by
  

Proof state:
R : Type u
inst✝¹ : AddMonoid R
R' : Type v
inst✝ : CommMonoid R'
ψ : AddChar R R'
x y : R
⊢ ψ (x + y) = ψ x * ψ y

Next tactic:
rw [coe_to_fun_apply, coe_to_fun_apply _ x, coe_to_fun_apply _ y, ofAdd_add, map_mul]
/-- An additive character maps multiples by natural numbers to powers. -/
@[simp]
theorem map_nsmul_pow (ψ : AddChar R R') (n : ℕ) (x : R) : ψ (n • x) = ψ x ^ n := by
  

Proof state:
R : Type u
inst✝¹ : AddMonoid R
R' : Type v
inst✝ : CommMonoid R'
ψ : AddChar R R'
n : ℕ
x : R
⊢ ψ (n • x) = ψ x ^ n

Next tactic:
rw [coe_to_fun_apply, coe_to_fun_apply _ x, ofAdd_nsmul, map_pow]
/-- An additive character maps multiples by integers to powers. -/
@[simp]
theorem map_zsmul_zpow {R' : Type v} [CommGroup R'] (ψ : AddChar R R') (n : ℤ) (x : R) :
    ψ (n • x) = ψ x ^ n := by 

Proof state:
R : Type u
inst✝² : AddCommGroup R
R'✝ : Type v
inst✝¹ : CommMonoid R'✝
R' : Type v
inst✝ : CommGroup R'
ψ : AddChar R R'
n : ℤ
x : R
⊢ ψ (n • x) = ψ x ^ n

Next tactic:
rw [coe_to_fun_apply, coe_to_fun_apply _ x, ofAdd_zsmul, map_zpow]
/-- The additive characters on a commutative additive group form a commutative group. -/
instance commGroup : CommGroup (AddChar R R') :=
  { MonoidHom.commMonoid with
    inv := Inv.inv
    mul_left_inv := fun ψ => by
      

Proof state:
R : Type u
inst✝¹ : AddCommGroup R
R' : Type v
inst✝ : CommMonoid R'
src✝ : CommMonoid (Multiplicative R →* R') := MonoidHom.commMonoid
ψ : AddChar R R'
⊢ ψ⁻¹ * ψ = 1

Next tactic:
ext x
/-- The additive characters on a commutative additive group form a commutative group. -/
instance commGroup : CommGroup (AddChar R R') :=
  { MonoidHom.commMonoid with
    inv := Inv.inv
    mul_left_inv := fun ψ => by
      ext x
      

Proof state:
case h
R : Type u
inst✝¹ : AddCommGroup R
R' : Type v
inst✝ : CommMonoid R'
src✝ : CommMonoid (Multiplicative R →* R') := MonoidHom.commMonoid
ψ : AddChar R R'
x : R
⊢ (ψ⁻¹ * ψ) x = 1 x

Next tactic:
rw [AddChar.mul_apply, AddChar.one_apply, inv_apply, ← map_add_mul, add_left_neg,
        map_zero_one]
/-- An additive character is nontrivial iff it is not the trivial character. -/
theorem isNontrivial_iff_ne_trivial (ψ : AddChar R R') : IsNontrivial ψ ↔ ψ ≠ 1 := by
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
⊢ IsNontrivial ψ ↔ ψ ≠ 1

Next tactic:
refine' not_forall.symm.trans (Iff.not _)
/-- An additive character is nontrivial iff it is not the trivial character. -/
theorem isNontrivial_iff_ne_trivial (ψ : AddChar R R') : IsNontrivial ψ ↔ ψ ≠ 1 := by
  refine' not_forall.symm.trans (Iff.not _)
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
⊢ (∀ (x : R), ψ x = 1) ↔ ψ = 1

Next tactic:
rw [FunLike.ext_iff]
/-- An additive character is nontrivial iff it is not the trivial character. -/
theorem isNontrivial_iff_ne_trivial (ψ : AddChar R R') : IsNontrivial ψ ↔ ψ ≠ 1 := by
  refine' not_forall.symm.trans (Iff.not _)
  rw [FunLike.ext_iff]
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
⊢ (∀ (x : R), ψ x = 1) ↔ ∀ (x : R), ψ x = 1 x

Next tactic:
rfl
/-- `ψ⁻¹ = mulShift ψ (-1))`. -/
theorem inv_mulShift (ψ : AddChar R R') : ψ⁻¹ = mulShift ψ (-1) := by
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
⊢ ψ⁻¹ = mulShift ψ (-1)

Next tactic:
ext
/-- `ψ⁻¹ = mulShift ψ (-1))`. -/
theorem inv_mulShift (ψ : AddChar R R') : ψ⁻¹ = mulShift ψ (-1) := by
  ext
  

Proof state:
case h
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
x✝ : R
⊢ ψ⁻¹ x✝ = (mulShift ψ (-1)) x✝

Next tactic:
rw [inv_apply, mulShift_apply, neg_mul, one_mul]
/-- If `n` is a natural number, then `mulShift ψ n x = (ψ x) ^ n`. -/
theorem mulShift_spec' (ψ : AddChar R R') (n : ℕ) (x : R) : mulShift ψ n x = ψ x ^ n := by
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
n : ℕ
x : R
⊢ (mulShift ψ ↑n) x = ψ x ^ n

Next tactic:
rw [mulShift_apply, ← nsmul_eq_mul, map_nsmul_pow]
/-- If `n` is a natural number, then `ψ ^ n = mulShift ψ n`. -/
theorem pow_mulShift (ψ : AddChar R R') (n : ℕ) : ψ ^ n = mulShift ψ n := by
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
n : ℕ
⊢ ψ ^ n = mulShift ψ ↑n

Next tactic:
ext x
/-- If `n` is a natural number, then `ψ ^ n = mulShift ψ n`. -/
theorem pow_mulShift (ψ : AddChar R R') (n : ℕ) : ψ ^ n = mulShift ψ n := by
  ext x
  

Proof state:
case h
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
n : ℕ
x : R
⊢ (ψ ^ n) x = (mulShift ψ ↑n) x

Next tactic:
rw [show (ψ ^ n) x = ψ x ^ n from rfl, ← mulShift_spec']
/-- The product of `mulShift ψ a` and `mulShift ψ b` is `mulShift ψ (a + b)`. -/
theorem mulShift_mul (ψ : AddChar R R') (a b : R) :
    mulShift ψ a * mulShift ψ b = mulShift ψ (a + b) := by
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
a b : R
⊢ mulShift ψ a * mulShift ψ b = mulShift ψ (a + b)

Next tactic:
ext
/-- The product of `mulShift ψ a` and `mulShift ψ b` is `mulShift ψ (a + b)`. -/
theorem mulShift_mul (ψ : AddChar R R') (a b : R) :
    mulShift ψ a * mulShift ψ b = mulShift ψ (a + b) := by
  ext
  

Proof state:
case h
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
a b x✝ : R
⊢ (mulShift ψ a * mulShift ψ b) x✝ = (mulShift ψ (a + b)) x✝

Next tactic:
rw [mulShift_apply, right_distrib, map_add_mul]
/-- The product of `mulShift ψ a` and `mulShift ψ b` is `mulShift ψ (a + b)`. -/
theorem mulShift_mul (ψ : AddChar R R') (a b : R) :
    mulShift ψ a * mulShift ψ b = mulShift ψ (a + b) := by
  ext
  rw [mulShift_apply, right_distrib, map_add_mul]; 

Proof state:
case h
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
a b x✝ : R
⊢ (mulShift ψ a * mulShift ψ b) x✝ = ψ (a * x✝) * ψ (b * x✝)

Next tactic:
norm_cast
/-- `mulShift ψ 0` is the trivial character. -/
@[simp]
theorem mulShift_zero (ψ : AddChar R R') : mulShift ψ 0 = 1 := by
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
⊢ mulShift ψ 0 = 1

Next tactic:
ext
/-- `mulShift ψ 0` is the trivial character. -/
@[simp]
theorem mulShift_zero (ψ : AddChar R R') : mulShift ψ 0 = 1 := by
  ext
  

Proof state:
case h
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
x✝ : R
⊢ (mulShift ψ 0) x✝ = 1 x✝

Next tactic:
rw [mulShift_apply, zero_mul, map_zero_one]
/-- `mulShift ψ 0` is the trivial character. -/
@[simp]
theorem mulShift_zero (ψ : AddChar R R') : mulShift ψ 0 = 1 := by
  ext
  rw [mulShift_apply, zero_mul, map_zero_one]; 

Proof state:
case h
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
x✝ : R
⊢ 1 = 1 x✝

Next tactic:
norm_cast
/-- The map associating to `a : R` the multiplicative shift of `ψ` by `a`
is injective when `ψ` is primitive. -/
theorem to_mulShift_inj_of_isPrimitive {ψ : AddChar R R'} (hψ : IsPrimitive ψ) :
    Function.Injective ψ.mulShift := by
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
hψ : IsPrimitive ψ
⊢ Function.Injective (mulShift ψ)

Next tactic:
intro a b h
/-- The map associating to `a : R` the multiplicative shift of `ψ` by `a`
is injective when `ψ` is primitive. -/
theorem to_mulShift_inj_of_isPrimitive {ψ : AddChar R R'} (hψ : IsPrimitive ψ) :
    Function.Injective ψ.mulShift := by
  intro a b h
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
hψ : IsPrimitive ψ
a b : R
h : mulShift ψ a = mulShift ψ b
⊢ a = b

Next tactic:
apply_fun fun x => x * mulShift ψ (-b) at h
/-- The map associating to `a : R` the multiplicative shift of `ψ` by `a`
is injective when `ψ` is primitive. -/
theorem to_mulShift_inj_of_isPrimitive {ψ : AddChar R R'} (hψ : IsPrimitive ψ) :
    Function.Injective ψ.mulShift := by
  intro a b h
  apply_fun fun x => x * mulShift ψ (-b) at h
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
hψ : IsPrimitive ψ
a b : R
h : mulShift ψ a * mulShift ψ (-b) = mulShift ψ b * mulShift ψ (-b)
⊢ a = b

Next tactic:
simp only [mulShift_mul, mulShift_zero, add_right_neg] at h
/-- The map associating to `a : R` the multiplicative shift of `ψ` by `a`
is injective when `ψ` is primitive. -/
theorem to_mulShift_inj_of_isPrimitive {ψ : AddChar R R'} (hψ : IsPrimitive ψ) :
    Function.Injective ψ.mulShift := by
  intro a b h
  apply_fun fun x => x * mulShift ψ (-b) at h
  simp only [mulShift_mul, mulShift_zero, add_right_neg] at h
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
hψ : IsPrimitive ψ
a b : R
h : mulShift ψ (a + -b) = 1
⊢ a = b

Next tactic:
have h₂ := hψ (a + -b)
/-- The map associating to `a : R` the multiplicative shift of `ψ` by `a`
is injective when `ψ` is primitive. -/
theorem to_mulShift_inj_of_isPrimitive {ψ : AddChar R R'} (hψ : IsPrimitive ψ) :
    Function.Injective ψ.mulShift := by
  intro a b h
  apply_fun fun x => x * mulShift ψ (-b) at h
  simp only [mulShift_mul, mulShift_zero, add_right_neg] at h
  have h₂ := hψ (a + -b)
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
hψ : IsPrimitive ψ
a b : R
h : mulShift ψ (a + -b) = 1
h₂ : a + -b ≠ 0 → IsNontrivial (mulShift ψ (a + -b))
⊢ a = b

Next tactic:
rw [h, isNontrivial_iff_ne_trivial, ← sub_eq_add_neg, sub_ne_zero] at h₂
/-- The map associating to `a : R` the multiplicative shift of `ψ` by `a`
is injective when `ψ` is primitive. -/
theorem to_mulShift_inj_of_isPrimitive {ψ : AddChar R R'} (hψ : IsPrimitive ψ) :
    Function.Injective ψ.mulShift := by
  intro a b h
  apply_fun fun x => x * mulShift ψ (-b) at h
  simp only [mulShift_mul, mulShift_zero, add_right_neg] at h
  have h₂ := hψ (a + -b)
  rw [h, isNontrivial_iff_ne_trivial, ← sub_eq_add_neg, sub_ne_zero] at h₂
  

Proof state:
R : Type u
inst✝¹ : CommRing R
R' : Type v
inst✝ : CommRing R'
ψ : AddChar R R'
hψ : IsPrimitive ψ
a b : R
h : mulShift ψ (a + -b) = 1
h₂ : a ≠ b → 1 ≠ 1
⊢ a = b

Next tactic:
exact not_not.mp fun h => h₂ h rfl
/-- When `R` is a field `F`, then a nontrivial additive character is primitive -/
theorem IsNontrivial.isPrimitive {F : Type u} [Field F] {ψ : AddChar F R'} (hψ : IsNontrivial ψ) :
    IsPrimitive ψ := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
F : Type u
inst✝ : Field F
ψ : AddChar F R'
hψ : IsNontrivial ψ
⊢ IsPrimitive ψ

Next tactic:
intro a ha
/-- When `R` is a field `F`, then a nontrivial additive character is primitive -/
theorem IsNontrivial.isPrimitive {F : Type u} [Field F] {ψ : AddChar F R'} (hψ : IsNontrivial ψ) :
    IsPrimitive ψ := by
  intro a ha
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
F : Type u
inst✝ : Field F
ψ : AddChar F R'
hψ : IsNontrivial ψ
a : F
ha : a ≠ 0
⊢ IsNontrivial (mulShift ψ a)

Next tactic:
cases' hψ with x h
/-- When `R` is a field `F`, then a nontrivial additive character is primitive -/
theorem IsNontrivial.isPrimitive {F : Type u} [Field F] {ψ : AddChar F R'} (hψ : IsNontrivial ψ) :
    IsPrimitive ψ := by
  intro a ha
  cases' hψ with x h
  

Proof state:
case intro
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
F : Type u
inst✝ : Field F
ψ : AddChar F R'
a : F
ha : a ≠ 0
x : F
h : ψ x ≠ 1
⊢ IsNontrivial (mulShift ψ a)

Next tactic:
use a⁻¹ * x
/-- When `R` is a field `F`, then a nontrivial additive character is primitive -/
theorem IsNontrivial.isPrimitive {F : Type u} [Field F] {ψ : AddChar F R'} (hψ : IsNontrivial ψ) :
    IsPrimitive ψ := by
  intro a ha
  cases' hψ with x h
  use a⁻¹ * x
  

Proof state:
case h
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
F : Type u
inst✝ : Field F
ψ : AddChar F R'
a : F
ha : a ≠ 0
x : F
h : ψ x ≠ 1
⊢ (mulShift ψ a) (a⁻¹ * x) ≠ 1

Next tactic:
rwa [mulShift_apply, mul_inv_cancel_left₀ ha]
/-- We can define an additive character on `ZMod n` when we have an `n`th root of unity `ζ : C`. -/
def zmodChar (n : ℕ+) {ζ : C} (hζ : ζ ^ (n : ℕ) = 1) : AddChar (ZMod n) C where
  toFun := fun a : Multiplicative (ZMod n) => ζ ^ a.toAdd.val
  map_one' := by 

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
hζ : ζ ^ ↑n = 1
⊢ (fun a => ζ ^ ZMod.val (toAdd a)) 1 = 1

Next tactic:
simp only [toAdd_one, ZMod.val_zero, pow_zero]
/-- We can define an additive character on `ZMod n` when we have an `n`th root of unity `ζ : C`. -/
def zmodChar (n : ℕ+) {ζ : C} (hζ : ζ ^ (n : ℕ) = 1) : AddChar (ZMod n) C where
  toFun := fun a : Multiplicative (ZMod n) => ζ ^ a.toAdd.val
  map_one' := by simp only [toAdd_one, ZMod.val_zero, pow_zero]
  map_mul' x y := by
    

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
hζ : ζ ^ ↑n = 1
x y : Multiplicative (ZMod ↑n)
⊢ OneHom.toFun { toFun := fun a => ζ ^ ZMod.val (toAdd a), map_one' := (_ : ζ ^ ZMod.val 0 = 1) } (x * y) =
    OneHom.toFun { toFun := fun a => ζ ^ ZMod.val (toAdd a), map_one' := (_ : ζ ^ ZMod.val 0 = 1) } x *
      OneHom.toFun { toFun := fun a => ζ ^ ZMod.val (toAdd a), map_one' := (_ : ζ ^ ZMod.val 0 = 1) } y

Next tactic:
dsimp only
/-- We can define an additive character on `ZMod n` when we have an `n`th root of unity `ζ : C`. -/
def zmodChar (n : ℕ+) {ζ : C} (hζ : ζ ^ (n : ℕ) = 1) : AddChar (ZMod n) C where
  toFun := fun a : Multiplicative (ZMod n) => ζ ^ a.toAdd.val
  map_one' := by simp only [toAdd_one, ZMod.val_zero, pow_zero]
  map_mul' x y := by
    dsimp only
    

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
hζ : ζ ^ ↑n = 1
x y : Multiplicative (ZMod ↑n)
⊢ ζ ^ ZMod.val (toAdd (x * y)) = ζ ^ ZMod.val (toAdd x) * ζ ^ ZMod.val (toAdd y)

Next tactic:
rw [toAdd_mul, ← pow_add, ZMod.val_add (toAdd x) (toAdd y), ← pow_eq_pow_mod _ hζ]
theorem zmodChar_apply' {n : ℕ+} {ζ : C} (hζ : ζ ^ (n : ℕ) = 1) (a : ℕ) :
    zmodChar n hζ a = ζ ^ a := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ζ : C
hζ : ζ ^ ↑n = 1
a : ℕ
⊢ (zmodChar n hζ) ↑a = ζ ^ a

Next tactic:
rw [pow_eq_pow_mod a hζ, zmodChar_apply, ZMod.val_nat_cast a]
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
⊢ IsNontrivial ψ ↔ ψ 1 ≠ 1

Next tactic:
refine' ⟨_, fun h => ⟨1, h⟩⟩
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  refine' ⟨_, fun h => ⟨1, h⟩⟩
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
⊢ IsNontrivial ψ → ψ 1 ≠ 1

Next tactic:
contrapose!
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  refine' ⟨_, fun h => ⟨1, h⟩⟩
  contrapose!
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
⊢ ψ 1 = 1 → ¬IsNontrivial ψ

Next tactic:
rintro h₁ ⟨a, ha⟩
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  refine' ⟨_, fun h => ⟨1, h⟩⟩
  contrapose!
  rintro h₁ ⟨a, ha⟩
  

Proof state:
case intro
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
h₁ : ψ 1 = 1
a : ZMod ↑n
ha : ψ a ≠ 1
⊢ False

Next tactic:
have ha₁ : a = a.val • (1 : ZMod ↑n) := by
    rw [nsmul_eq_mul, mul_one]; exact (ZMod.nat_cast_zmod_val a).symm
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  refine' ⟨_, fun h => ⟨1, h⟩⟩
  contrapose!
  rintro h₁ ⟨a, ha⟩
  have ha₁ : a = a.val • (1 : ZMod ↑n) := by
    

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
h₁ : ψ 1 = 1
a : ZMod ↑n
ha : ψ a ≠ 1
⊢ a = ZMod.val a • 1

Next tactic:
rw [nsmul_eq_mul, mul_one]
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  refine' ⟨_, fun h => ⟨1, h⟩⟩
  contrapose!
  rintro h₁ ⟨a, ha⟩
  have ha₁ : a = a.val • (1 : ZMod ↑n) := by
    rw [nsmul_eq_mul, mul_one]; 

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
h₁ : ψ 1 = 1
a : ZMod ↑n
ha : ψ a ≠ 1
⊢ a = ↑(ZMod.val a)

Next tactic:
exact (ZMod.nat_cast_zmod_val a).symm
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  refine' ⟨_, fun h => ⟨1, h⟩⟩
  contrapose!
  rintro h₁ ⟨a, ha⟩
  have ha₁ : a = a.val • (1 : ZMod ↑n) := by
    rw [nsmul_eq_mul, mul_one]; exact (ZMod.nat_cast_zmod_val a).symm
  

Proof state:
case intro
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
h₁ : ψ 1 = 1
a : ZMod ↑n
ha : ψ a ≠ 1
ha₁ : a = ZMod.val a • 1
⊢ False

Next tactic:
rw [ha₁, map_nsmul_pow, h₁, one_pow] at ha
/-- An additive character on `ZMod n` is nontrivial iff it takes a value `≠ 1` on `1`. -/
theorem zmod_char_isNontrivial_iff (n : ℕ+) (ψ : AddChar (ZMod n) C) :
    IsNontrivial ψ ↔ ψ 1 ≠ 1 := by
  refine' ⟨_, fun h => ⟨1, h⟩⟩
  contrapose!
  rintro h₁ ⟨a, ha⟩
  have ha₁ : a = a.val • (1 : ZMod ↑n) := by
    rw [nsmul_eq_mul, mul_one]; exact (ZMod.nat_cast_zmod_val a).symm
  rw [ha₁, map_nsmul_pow, h₁, one_pow] at ha
  

Proof state:
case intro
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
h₁ : ψ 1 = 1
a : ZMod ↑n
ha : 1 ≠ 1
ha₁ : a = ZMod.val a • 1
⊢ False

Next tactic:
exact ha rfl
/-- A primitive additive character on `ZMod n` takes the value `1` only at `0`. -/
theorem IsPrimitive.zmod_char_eq_one_iff (n : ℕ+) {ψ : AddChar (ZMod n) C} (hψ : IsPrimitive ψ)
    (a : ZMod n) : ψ a = 1 ↔ a = 0 := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
hψ : IsPrimitive ψ
a : ZMod ↑n
⊢ ψ a = 1 ↔ a = 0

Next tactic:
refine' ⟨fun h => not_imp_comm.mp (hψ a) _, fun ha => by rw [ha, map_zero_one]⟩
/-- A primitive additive character on `ZMod n` takes the value `1` only at `0`. -/
theorem IsPrimitive.zmod_char_eq_one_iff (n : ℕ+) {ψ : AddChar (ZMod n) C} (hψ : IsPrimitive ψ)
    (a : ZMod n) : ψ a = 1 ↔ a = 0 := by
  refine' ⟨fun h => not_imp_comm.mp (hψ a) _, fun ha => by 

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
hψ : IsPrimitive ψ
a : ZMod ↑n
ha : a = 0
⊢ ψ a = 1

Next tactic:
rw [ha, map_zero_one]
/-- A primitive additive character on `ZMod n` takes the value `1` only at `0`. -/
theorem IsPrimitive.zmod_char_eq_one_iff (n : ℕ+) {ψ : AddChar (ZMod n) C} (hψ : IsPrimitive ψ)
    (a : ZMod n) : ψ a = 1 ↔ a = 0 := by
  refine' ⟨fun h => not_imp_comm.mp (hψ a) _, fun ha => by rw [ha, map_zero_one]⟩
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ+
ψ : AddChar (ZMod ↑n) C
hψ : IsPrimitive ψ
a : ZMod ↑n
h : ψ a = 1
⊢ ¬IsNontrivial (mulShift ψ a)

Next tactic:
rw [zmod_char_isNontrivial_iff n (mulShift ψ a), mulShift_apply, mul_one, h, Classical.not_not]
/-- The converse: if the additive character takes the value `1` only at `0`,
then it is primitive. -/
theorem zmod_char_primitive_of_eq_one_only_at_zero (n : ℕ) (ψ : AddChar (ZMod n) C)
    (hψ : ∀ a, ψ a = 1 → a = 0) : IsPrimitive ψ := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ
ψ : AddChar (ZMod n) C
hψ : ∀ (a : ZMod n), ψ a = 1 → a = 0
⊢ IsPrimitive ψ

Next tactic:
refine' fun a ha => (isNontrivial_iff_ne_trivial _).mpr fun hf => _
/-- The converse: if the additive character takes the value `1` only at `0`,
then it is primitive. -/
theorem zmod_char_primitive_of_eq_one_only_at_zero (n : ℕ) (ψ : AddChar (ZMod n) C)
    (hψ : ∀ a, ψ a = 1 → a = 0) : IsPrimitive ψ := by
  refine' fun a ha => (isNontrivial_iff_ne_trivial _).mpr fun hf => _
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ
ψ : AddChar (ZMod n) C
hψ : ∀ (a : ZMod n), ψ a = 1 → a = 0
a : ZMod n
ha : a ≠ 0
hf : mulShift ψ a = 1
⊢ False

Next tactic:
have h : mulShift ψ a 1 = (1 : AddChar (ZMod n) C) (1 : ZMod n) :=
    congr_fun (congr_arg (↑) hf) 1
/-- The converse: if the additive character takes the value `1` only at `0`,
then it is primitive. -/
theorem zmod_char_primitive_of_eq_one_only_at_zero (n : ℕ) (ψ : AddChar (ZMod n) C)
    (hψ : ∀ a, ψ a = 1 → a = 0) : IsPrimitive ψ := by
  refine' fun a ha => (isNontrivial_iff_ne_trivial _).mpr fun hf => _
  have h : mulShift ψ a 1 = (1 : AddChar (ZMod n) C) (1 : ZMod n) :=
    congr_fun (congr_arg (↑) hf) 1
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
C : Type v
inst✝ : CommRing C
n : ℕ
ψ : AddChar (ZMod n) C
hψ : ∀ (a : ZMod n), ψ a = 1 → a = 0
a : ZMod n
ha : a ≠ 0
hf : mulShift ψ a = 1
h : (mulShift ψ a) 1 = 1 1
⊢ False

Next tactic:
rw [mulShift_apply, mul_one] at h