l3lab/ntp-mathlib huggingface dataset:
/-- The equivalence between multiplicative characters and homomorphisms of unit groups. -/
noncomputable def equivToUnitHom : MulChar R R' ≃ (Rˣ →* R'ˣ) where
  toFun := toUnitHom
  invFun := ofUnitHom
  left_inv := by
    intro χ
    ext x
    rw [ofUnitHom_coe, coe_toUnitHom]
  right_inv := by
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ Function.RightInverse ofUnitHom toUnitHom

Next tactic:
intro f
/-- The equivalence between multiplicative characters and homomorphisms of unit groups. -/
noncomputable def equivToUnitHom : MulChar R R' ≃ (Rˣ →* R'ˣ) where
  toFun := toUnitHom
  invFun := ofUnitHom
  left_inv := by
    intro χ
    ext x
    rw [ofUnitHom_coe, coe_toUnitHom]
  right_inv := by
    intro f
    

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
⊢ toUnitHom (ofUnitHom f) = f

Next tactic:
ext x
/-- The equivalence between multiplicative characters and homomorphisms of unit groups. -/
noncomputable def equivToUnitHom : MulChar R R' ≃ (Rˣ →* R'ˣ) where
  toFun := toUnitHom
  invFun := ofUnitHom
  left_inv := by
    intro χ
    ext x
    rw [ofUnitHom_coe, coe_toUnitHom]
  right_inv := by
    intro f
    ext x
    

Proof state:
case h.a
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
f : Rˣ →* R'ˣ
x : Rˣ
⊢ ↑((toUnitHom (ofUnitHom f)) x) = ↑(f x)

Next tactic:
simp only [coe_toUnitHom, ofUnitHom_coe]
/-- If the domain has a zero (and is nontrivial), then `χ 0 = 0`. -/
protected theorem map_zero {R : Type u} [CommMonoidWithZero R] [Nontrivial R] (χ : MulChar R R') :
    χ (0 : R) = 0 := by 

Proof state:
R✝ : Type u
inst✝³ : CommMonoid R✝
R' : Type v
inst✝² : CommMonoidWithZero R'
R : Type u
inst✝¹ : CommMonoidWithZero R
inst✝ : Nontrivial R
χ : MulChar R R'
⊢ χ 0 = 0

Next tactic:
rw [map_nonunit χ not_isUnit_zero]
/-- If the domain is a ring `R`, then `χ (ringChar R) = 0`. -/
theorem map_ringChar {R : Type u} [CommRing R] [Nontrivial R] (χ : MulChar R R') :
    χ (ringChar R) = 0 := by 

Proof state:
R✝ : Type u
inst✝³ : CommMonoid R✝
R' : Type v
inst✝² : CommMonoidWithZero R'
R : Type u
inst✝¹ : CommRing R
inst✝ : Nontrivial R
χ : MulChar R R'
⊢ χ ↑(ringChar R) = 0

Next tactic:
rw [ringChar.Nat.cast_ringChar, χ.map_zero]
/-- Evaluation of the trivial character -/
@[simp]
theorem one_apply_coe (a : Rˣ) : (1 : MulChar R R') a = 1 := by 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
a : Rˣ
⊢ 1 ↑a = 1

Next tactic:
classical exact dif_pos a.isUnit
/-- Evaluation of the trivial character -/
@[simp]
theorem one_apply_coe (a : Rˣ) : (1 : MulChar R R') a = 1 := by classical 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
a : Rˣ
⊢ 1 ↑a = 1

Next tactic:
exact dif_pos a.isUnit
/-- Multiplication of multiplicative characters. (This needs the target to be commutative.) -/
def mul (χ χ' : MulChar R R') : MulChar R R' :=
  { χ.toMonoidHom * χ'.toMonoidHom with
    toFun := χ * χ'
    map_nonunit' := fun a ha => by 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ χ' : MulChar R R'
src✝ : R →* R' := χ.toMonoidHom * χ'.toMonoidHom
a : R
ha : ¬IsUnit a
⊢ OneHom.toFun
      (↑{ toOneHom := { toFun := ⇑χ * ⇑χ', map_one' := (_ : OneHom.toFun (↑src✝) 1 = 1) },
          map_mul' :=
            (_ : ∀ (x y : R), OneHom.toFun (↑src✝) (x * y) = OneHom.toFun (↑src✝) x * OneHom.toFun (↑src✝) y) })
      a =
    0

Next tactic:
simp only [map_nonunit χ ha, zero_mul, Pi.mul_apply]
protected theorem one_mul (χ : MulChar R R') : (1 : MulChar R R') * χ = χ := by
  

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
⊢ 1 * χ = χ

Next tactic:
ext
protected theorem one_mul (χ : MulChar R R') : (1 : MulChar R R') * χ = χ := by
  ext
  

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
a✝ : Rˣ
⊢ (1 * χ) ↑a✝ = χ ↑a✝

Next tactic:
simp only [one_mul, Pi.mul_apply, MulChar.coeToFun_mul, MulChar.one_apply_coe]
protected theorem mul_one (χ : MulChar R R') : χ * 1 = χ := by
  

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
⊢ χ * 1 = χ

Next tactic:
ext
protected theorem mul_one (χ : MulChar R R') : χ * 1 = χ := by
  ext
  

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
a✝ : Rˣ
⊢ (χ * 1) ↑a✝ = χ ↑a✝

Next tactic:
simp only [mul_one, Pi.mul_apply, MulChar.coeToFun_mul, MulChar.one_apply_coe]
/-- The inverse of a multiplicative character. We define it as `inverse ∘ χ`. -/
noncomputable def inv (χ : MulChar R R') : MulChar R R' :=
  { MonoidWithZero.inverse.toMonoidHom.comp χ.toMonoidHom with
    toFun := fun a => MonoidWithZero.inverse (χ a)
    map_nonunit' := fun a ha => by 

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
src✝ : R →* R' := MonoidHom.comp (↑MonoidWithZero.inverse) χ.toMonoidHom
a : R
ha : ¬IsUnit a
⊢ OneHom.toFun
      (↑{ toOneHom := { toFun := fun a => MonoidWithZero.inverse (χ a), map_one' := (_ : OneHom.toFun (↑src✝) 1 = 1) },
          map_mul' :=
            (_ : ∀ (x y : R), OneHom.toFun (↑src✝) (x * y) = OneHom.toFun (↑src✝) x * OneHom.toFun (↑src✝) y) })
      a =
    0

Next tactic:
simp [map_nonunit _ ha]
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  

Proof state:
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
⊢ χ⁻¹ a = χ (Ring.inverse a)

Next tactic:
by_cases ha : IsUnit a
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · 

Proof state:
case pos
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
ha : IsUnit a
⊢ χ⁻¹ a = χ (Ring.inverse a)

Next tactic:
rw [inv_apply_eq_inv]
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    

Proof state:
case pos
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
ha : IsUnit a
⊢ Ring.inverse (χ a) = χ (Ring.inverse a)

Next tactic:
have h := IsUnit.map χ ha
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    

Proof state:
case pos
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
ha : IsUnit a
h : IsUnit (χ a)
⊢ Ring.inverse (χ a) = χ (Ring.inverse a)

Next tactic:
apply_fun (χ a * ·) using IsUnit.mul_right_injective h
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    apply_fun (χ a * ·) using IsUnit.mul_right_injective h
    

Proof state:
case pos
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
ha : IsUnit a
h : IsUnit (χ a)
⊢ (fun x => χ a * x) (Ring.inverse (χ a)) = (fun x => χ a * x) (χ (Ring.inverse a))

Next tactic:
dsimp only
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    apply_fun (χ a * ·) using IsUnit.mul_right_injective h
    dsimp only
    -- Porting note: was
    -- rw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha, MulChar.map_one]
    

Proof state:
case pos
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
ha : IsUnit a
h : IsUnit (χ a)
⊢ χ a * Ring.inverse (χ a) = χ a * χ (Ring.inverse a)

Next tactic:
erw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha]
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    apply_fun (χ a * ·) using IsUnit.mul_right_injective h
    dsimp only
    -- Porting note: was
    -- rw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha, MulChar.map_one]
    erw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha]
    

Proof state:
case pos
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
ha : IsUnit a
h : IsUnit (χ a)
⊢ 1 = χ 1

Next tactic:
exact (MulChar.map_one χ).symm
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    apply_fun (χ a * ·) using IsUnit.mul_right_injective h
    dsimp only
    -- Porting note: was
    -- rw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha, MulChar.map_one]
    erw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha]
    exact (MulChar.map_one χ).symm
  · 

Proof state:
case neg
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
ha : ¬IsUnit a
⊢ χ⁻¹ a = χ (Ring.inverse a)

Next tactic:
revert ha
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    apply_fun (χ a * ·) using IsUnit.mul_right_injective h
    dsimp only
    -- Porting note: was
    -- rw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha, MulChar.map_one]
    erw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha]
    exact (MulChar.map_one χ).symm
  · revert ha
    

Proof state:
case neg
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
⊢ ¬IsUnit a → χ⁻¹ a = χ (Ring.inverse a)

Next tactic:
nontriviality R
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    apply_fun (χ a * ·) using IsUnit.mul_right_injective h
    dsimp only
    -- Porting note: was
    -- rw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha, MulChar.map_one]
    erw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha]
    exact (MulChar.map_one χ).symm
  · revert ha
    nontriviality R
    

Proof state:
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
✝ : Nontrivial R
⊢ ¬IsUnit a → χ⁻¹ a = χ (Ring.inverse a)

Next tactic:
intro ha
/-- When the domain has a zero, then the inverse of a multiplicative character `χ`,
applied to `a`, is `χ` applied to the inverse of `a`. -/
theorem inv_apply {R : Type u} [CommMonoidWithZero R] (χ : MulChar R R') (a : R) :
    χ⁻¹ a = χ (Ring.inverse a) := by
  by_cases ha : IsUnit a
  · rw [inv_apply_eq_inv]
    have h := IsUnit.map χ ha
    apply_fun (χ a * ·) using IsUnit.mul_right_injective h
    dsimp only
    -- Porting note: was
    -- rw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha, MulChar.map_one]
    erw [Ring.mul_inverse_cancel _ h, ← map_mul, Ring.mul_inverse_cancel _ ha]
    exact (MulChar.map_one χ).symm
  · revert ha
    nontriviality R
    intro ha
    -- `nontriviality R` by itself doesn't do it
    

Proof state:
R✝ : Type u
inst✝² : CommMonoid R✝
R' : Type v
inst✝¹ : CommMonoidWithZero R'
R : Type u
inst✝ : CommMonoidWithZero R
χ : MulChar R R'
a : R
✝ : Nontrivial R
ha : ¬IsUnit a
⊢ χ⁻¹ a = χ (Ring.inverse a)

Next tactic:
rw [map_nonunit _ ha, Ring.inverse_non_unit a ha, MulChar.map_zero χ]
/-- The product of a character with its inverse is the trivial character. -/
-- Porting note: @[simp] can prove this (later)
theorem inv_mul (χ : MulChar R R') : χ⁻¹ * χ = 1 := by
  

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
⊢ χ⁻¹ * χ = 1

Next tactic:
ext x
/-- The product of a character with its inverse is the trivial character. -/
-- Porting note: @[simp] can prove this (later)
theorem inv_mul (χ : MulChar R R') : χ⁻¹ * χ = 1 := by
  ext x
  

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
x : Rˣ
⊢ (χ⁻¹ * χ) ↑x = 1 ↑x

Next tactic:
rw [coeToFun_mul, Pi.mul_apply, inv_apply_eq_inv]
/-- The product of a character with its inverse is the trivial character. -/
-- Porting note: @[simp] can prove this (later)
theorem inv_mul (χ : MulChar R R') : χ⁻¹ * χ = 1 := by
  ext x
  rw [coeToFun_mul, Pi.mul_apply, inv_apply_eq_inv]
  -- Porting note: was
  -- simp only [Ring.inverse_mul_cancel _ (IsUnit.map _ x.isUnit)]
  

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
x : Rˣ
⊢ Ring.inverse (χ ↑x) * χ ↑x = 1 ↑x

Next tactic:
erw [Ring.inverse_mul_cancel _ (IsUnit.map χ x.isUnit)]
/-- The product of a character with its inverse is the trivial character. -/
-- Porting note: @[simp] can prove this (later)
theorem inv_mul (χ : MulChar R R') : χ⁻¹ * χ = 1 := by
  ext x
  rw [coeToFun_mul, Pi.mul_apply, inv_apply_eq_inv]
  -- Porting note: was
  -- simp only [Ring.inverse_mul_cancel _ (IsUnit.map _ x.isUnit)]
  erw [Ring.inverse_mul_cancel _ (IsUnit.map χ x.isUnit)]
  

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
x : Rˣ
⊢ 1 = 1 ↑x

Next tactic:
rw [one_apply_coe]
/-- The commutative group structure on `MulChar R R'`. -/
noncomputable instance commGroup : CommGroup (MulChar R R') :=
  { one := 1
    mul := (· * ·)
    inv := Inv.inv
    mul_left_inv := inv_mul
    mul_assoc := by
      

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ ∀ (a b c : MulChar R R'), a * b * c = a * (b * c)

Next tactic:
intro χ₁ χ₂ χ₃
/-- The commutative group structure on `MulChar R R'`. -/
noncomputable instance commGroup : CommGroup (MulChar R R') :=
  { one := 1
    mul := (· * ·)
    inv := Inv.inv
    mul_left_inv := inv_mul
    mul_assoc := by
      intro χ₁ χ₂ χ₃
      

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ₁ χ₂ χ₃ : MulChar R R'
⊢ χ₁ * χ₂ * χ₃ = χ₁ * (χ₂ * χ₃)

Next tactic:
ext a
/-- The commutative group structure on `MulChar R R'`. -/
noncomputable instance commGroup : CommGroup (MulChar R R') :=
  { one := 1
    mul := (· * ·)
    inv := Inv.inv
    mul_left_inv := inv_mul
    mul_assoc := by
      intro χ₁ χ₂ χ₃
      ext a
      

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ₁ χ₂ χ₃ : MulChar R R'
a : Rˣ
⊢ (χ₁ * χ₂ * χ₃) ↑a = (χ₁ * (χ₂ * χ₃)) ↑a

Next tactic:
simp only [mul_assoc, Pi.mul_apply, MulChar.coeToFun_mul]
/-- The commutative group structure on `MulChar R R'`. -/
noncomputable instance commGroup : CommGroup (MulChar R R') :=
  { one := 1
    mul := (· * ·)
    inv := Inv.inv
    mul_left_inv := inv_mul
    mul_assoc := by
      intro χ₁ χ₂ χ₃
      ext a
      simp only [mul_assoc, Pi.mul_apply, MulChar.coeToFun_mul]
    mul_comm := by
      

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
⊢ ∀ (a b : MulChar R R'), a * b = b * a

Next tactic:
intro χ₁ χ₂
/-- The commutative group structure on `MulChar R R'`. -/
noncomputable instance commGroup : CommGroup (MulChar R R') :=
  { one := 1
    mul := (· * ·)
    inv := Inv.inv
    mul_left_inv := inv_mul
    mul_assoc := by
      intro χ₁ χ₂ χ₃
      ext a
      simp only [mul_assoc, Pi.mul_apply, MulChar.coeToFun_mul]
    mul_comm := by
      intro χ₁ χ₂
      

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ₁ χ₂ : MulChar R R'
⊢ χ₁ * χ₂ = χ₂ * χ₁

Next tactic:
ext a
/-- The commutative group structure on `MulChar R R'`. -/
noncomputable instance commGroup : CommGroup (MulChar R R') :=
  { one := 1
    mul := (· * ·)
    inv := Inv.inv
    mul_left_inv := inv_mul
    mul_assoc := by
      intro χ₁ χ₂ χ₃
      ext a
      simp only [mul_assoc, Pi.mul_apply, MulChar.coeToFun_mul]
    mul_comm := by
      intro χ₁ χ₂
      ext a
      

Proof state:
case h
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ₁ χ₂ : MulChar R R'
a : Rˣ
⊢ (χ₁ * χ₂) ↑a = (χ₂ * χ₁) ↑a

Next tactic:
simp only [mul_comm, Pi.mul_apply, MulChar.coeToFun_mul]
/-- If `a` is a unit and `n : ℕ`, then `(χ ^ n) a = (χ a) ^ n`. -/
theorem pow_apply_coe (χ : MulChar R R') (n : ℕ) (a : Rˣ) : (χ ^ n) a = χ a ^ n := by
  

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
n : ℕ
a : Rˣ
⊢ (χ ^ n) ↑a = χ ↑a ^ n

Next tactic:
induction' n with n ih
/-- If `a` is a unit and `n : ℕ`, then `(χ ^ n) a = (χ a) ^ n`. -/
theorem pow_apply_coe (χ : MulChar R R') (n : ℕ) (a : Rˣ) : (χ ^ n) a = χ a ^ n := by
  induction' n with n ih
  · 

Proof state:
case zero
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
a : Rˣ
⊢ (χ ^ Nat.zero) ↑a = χ ↑a ^ Nat.zero

Next tactic:
rw [pow_zero, pow_zero, one_apply_coe]
/-- If `a` is a unit and `n : ℕ`, then `(χ ^ n) a = (χ a) ^ n`. -/
theorem pow_apply_coe (χ : MulChar R R') (n : ℕ) (a : Rˣ) : (χ ^ n) a = χ a ^ n := by
  induction' n with n ih
  · rw [pow_zero, pow_zero, one_apply_coe]
  · 

Proof state:
case succ
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
a : Rˣ
n : ℕ
ih : (χ ^ n) ↑a = χ ↑a ^ n
⊢ (χ ^ Nat.succ n) ↑a = χ ↑a ^ Nat.succ n

Next tactic:
rw [pow_succ, pow_succ, mul_apply, ih]
/-- If `n` is positive, then `(χ ^ n) a = (χ a) ^ n`. -/
theorem pow_apply' (χ : MulChar R R') {n : ℕ} (hn : 0 < n) (a : R) : (χ ^ n) a = χ a ^ n := by
  

Proof state:
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
n : ℕ
hn : 0 < n
a : R
⊢ (χ ^ n) a = χ a ^ n

Next tactic:
by_cases ha : IsUnit a
/-- If `n` is positive, then `(χ ^ n) a = (χ a) ^ n`. -/
theorem pow_apply' (χ : MulChar R R') {n : ℕ} (hn : 0 < n) (a : R) : (χ ^ n) a = χ a ^ n := by
  by_cases ha : IsUnit a
  · 

Proof state:
case pos
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
n : ℕ
hn : 0 < n
a : R
ha : IsUnit a
⊢ (χ ^ n) a = χ a ^ n

Next tactic:
exact pow_apply_coe χ n ha.unit
/-- If `n` is positive, then `(χ ^ n) a = (χ a) ^ n`. -/
theorem pow_apply' (χ : MulChar R R') {n : ℕ} (hn : 0 < n) (a : R) : (χ ^ n) a = χ a ^ n := by
  by_cases ha : IsUnit a
  · exact pow_apply_coe χ n ha.unit
  · 

Proof state:
case neg
R : Type u
inst✝¹ : CommMonoid R
R' : Type v
inst✝ : CommMonoidWithZero R'
χ : MulChar R R'
n : ℕ
hn : 0 < n
a : R
ha : ¬IsUnit a
⊢ (χ ^ n) a = χ a ^ n

Next tactic:
rw [map_nonunit (χ ^ n) ha, map_nonunit χ ha, zero_pow hn]
/-- A multiplicative character is nontrivial iff it is not the trivial character. -/
theorem isNontrivial_iff (χ : MulChar R R') : χ.IsNontrivial ↔ χ ≠ 1 := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
R'' : Type w
inst✝ : CommRing R''
χ : MulChar R R'
⊢ IsNontrivial χ ↔ χ ≠ 1

Next tactic:
simp only [IsNontrivial, Ne.def, ext_iff, not_forall, one_apply_coe]
/-- We can post-compose a multiplicative character with a ring homomorphism. -/
@[simps]
def ringHomComp (χ : MulChar R R') (f : R' →+* R'') : MulChar R R'' :=
  { f.toMonoidHom.comp χ.toMonoidHom with
    toFun := fun a => f (χ a)
    map_nonunit' := fun a ha => by 

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
R'' : Type w
inst✝ : CommRing R''
χ : MulChar R R'
f : R' →+* R''
src✝ : R →* R'' := MonoidHom.comp (↑f) χ.toMonoidHom
a : R
ha : ¬IsUnit a
⊢ OneHom.toFun
      (↑{ toOneHom := { toFun := fun a => f (χ a), map_one' := (_ : OneHom.toFun (↑src✝) 1 = 1) },
          map_mul' :=
            (_ : ∀ (x y : R), OneHom.toFun (↑src✝) (x * y) = OneHom.toFun (↑src✝) x * OneHom.toFun (↑src✝) y) })
      a =
    0

Next tactic:
simp only [map_nonunit χ ha, map_zero]
/-- Composition with an injective ring homomorphism preserves nontriviality. -/
theorem IsNontrivial.comp {χ : MulChar R R'} (hχ : χ.IsNontrivial) {f : R' →+* R''}
    (hf : Function.Injective f) : (χ.ringHomComp f).IsNontrivial := by
  

Proof state:
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
R'' : Type w
inst✝ : CommRing R''
χ : MulChar R R'
hχ : IsNontrivial χ
f : R' →+* R''
hf : Function.Injective ⇑f
⊢ IsNontrivial (ringHomComp χ f)

Next tactic:
obtain ⟨a, ha⟩ := hχ
/-- Composition with an injective ring homomorphism preserves nontriviality. -/
theorem IsNontrivial.comp {χ : MulChar R R'} (hχ : χ.IsNontrivial) {f : R' →+* R''}
    (hf : Function.Injective f) : (χ.ringHomComp f).IsNontrivial := by
  obtain ⟨a, ha⟩ := hχ
  

Proof state:
case intro
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
R'' : Type w
inst✝ : CommRing R''
χ : MulChar R R'
f : R' →+* R''
hf : Function.Injective ⇑f
a : Rˣ
ha : χ ↑a ≠ 1
⊢ IsNontrivial (ringHomComp χ f)

Next tactic:
use a
/-- Composition with an injective ring homomorphism preserves nontriviality. -/
theorem IsNontrivial.comp {χ : MulChar R R'} (hχ : χ.IsNontrivial) {f : R' →+* R''}
    (hf : Function.Injective f) : (χ.ringHomComp f).IsNontrivial := by
  obtain ⟨a, ha⟩ := hχ
  use a
  

Proof state:
case h
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
R'' : Type w
inst✝ : CommRing R''
χ : MulChar R R'
f : R' →+* R''
hf : Function.Injective ⇑f
a : Rˣ
ha : χ ↑a ≠ 1
⊢ (ringHomComp χ f) ↑a ≠ 1

Next tactic:
simp_rw [ringHomComp_apply, ← RingHom.map_one f]
/-- Composition with an injective ring homomorphism preserves nontriviality. -/
theorem IsNontrivial.comp {χ : MulChar R R'} (hχ : χ.IsNontrivial) {f : R' →+* R''}
    (hf : Function.Injective f) : (χ.ringHomComp f).IsNontrivial := by
  obtain ⟨a, ha⟩ := hχ
  use a
  simp_rw [ringHomComp_apply, ← RingHom.map_one f]
  

Proof state:
case h
R : Type u
inst✝² : CommRing R
R' : Type v
inst✝¹ : CommRing R'
R'' : Type w
inst✝ : CommRing R''
χ : MulChar R R'
f : R' →+* R''
hf : Function.Injective ⇑f
a : Rˣ
ha : χ ↑a ≠ 1
⊢ f (χ ↑a) ≠ f 1

Next tactic:
exact fun h => ha (hf h)