l3lab/ntp-mathlib huggingface dataset:
theorem rank_real_of_complex (E : Type*) [AddCommGroup E] [Module ℂ E] :
    Module.rank ℝ E = 2 * Module.rank ℂ E :=
  Cardinal.lift_inj.1 <| by
    rw [← lift_rank_mul_lift_rank ℝ ℂ E, Complex.rank_real_complex']
    

Proof state:
E : Type u_1
inst✝¹ : AddCommGroup E
inst✝ : Module ℂ E
⊢ 2 * Cardinal.lift.{0, u_1} (Module.rank ℂ E) = Cardinal.lift.{0, u_1} (2 * Module.rank ℂ E)

Next tactic:
simp only [Cardinal.lift_id']
theorem finrank_real_of_complex (E : Type*) [AddCommGroup E] [Module ℂ E] :
    FiniteDimensional.finrank ℝ E = 2 * FiniteDimensional.finrank ℂ E := by
  

Proof state:
E : Type u_1
inst✝¹ : AddCommGroup E
inst✝ : Module ℂ E
⊢ FiniteDimensional.finrank ℝ E = 2 * FiniteDimensional.finrank ℂ E

Next tactic:
rw [← FiniteDimensional.finrank_mul_finrank ℝ ℂ E, Complex.finrank_real_complex]
instance (priority := 900) StarModule.complexToReal {E : Type*} [AddCommGroup E] [Star E]
    [Module ℂ E] [StarModule ℂ E] : StarModule ℝ E :=
  ⟨fun r a => by 

Proof state:
E : Type u_1
inst✝³ : AddCommGroup E
inst✝² : Star E
inst✝¹ : Module ℂ E
inst✝ : StarModule ℂ E
r : ℝ
a : E
⊢ star (r • a) = star r • star a

Next tactic:
rw [← smul_one_smul ℂ r a, star_smul, star_smul, star_one, smul_one_smul]
/-- Linear map version of the real part function, from `ℂ` to `ℝ`. -/
def reLm : ℂ →ₗ[ℝ] ℝ where
  toFun x := x.re
  map_add' := add_re
  map_smul' := by 

Proof state:
⊢ ∀ (r : ℝ) (x : ℂ),
    AddHom.toFun { toFun := fun x => x.re, map_add' := add_re } (r • x) =
      (RingHom.id ℝ) r • AddHom.toFun { toFun := fun x => x.re, map_add' := add_re } x

Next tactic:
simp
/-- Linear map version of the imaginary part function, from `ℂ` to `ℝ`. -/
def imLm : ℂ →ₗ[ℝ] ℝ where
  toFun x := x.im
  map_add' := add_im
  map_smul' := by 

Proof state:
⊢ ∀ (r : ℝ) (x : ℂ),
    AddHom.toFun { toFun := fun x => x.im, map_add' := add_im } (r • x) =
      (RingHom.id ℝ) r • AddHom.toFun { toFun := fun x => x.im, map_add' := add_im } x

Next tactic:
simp
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  

Proof state:
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) = Matrix.of ![![1, 0], ![0, -1]]

Next tactic:
ext i j
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  ext i j
  -- Porting note: replaced non-terminal `simp [LinearMap.toMatrix_apply]`
  

Proof state:
case a.h
i j : Fin 2
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) i j = Matrix.of ![![1, 0], ![0, -1]] i j

Next tactic:
fin_cases i
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  ext i j
  -- Porting note: replaced non-terminal `simp [LinearMap.toMatrix_apply]`
  fin_cases i <;> 

Proof state:
case a.h.head
j : Fin 2
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) { val := 0, isLt := (_ : 0 < 2) } j =
    Matrix.of ![![1, 0], ![0, -1]] { val := 0, isLt := (_ : 0 < 2) } j

Next tactic:
fin_cases j
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  ext i j
  -- Porting note: replaced non-terminal `simp [LinearMap.toMatrix_apply]`
  fin_cases i <;> 

Proof state:
case a.h.tail.head
j : Fin 2
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) { val := 1, isLt := (_ : (fun a => a < 2) 1) }
      j =
    Matrix.of ![![1, 0], ![0, -1]] { val := 1, isLt := (_ : (fun a => a < 2) 1) } j

Next tactic:
fin_cases j
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  ext i j
  -- Porting note: replaced non-terminal `simp [LinearMap.toMatrix_apply]`
  fin_cases i <;> fin_cases j <;> 

Proof state:
case a.h.head.head
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) { val := 0, isLt := (_ : 0 < 2) }
      { val := 0, isLt := (_ : 0 < 2) } =
    Matrix.of ![![1, 0], ![0, -1]] { val := 0, isLt := (_ : 0 < 2) } { val := 0, isLt := (_ : 0 < 2) }

Next tactic:
simp [LinearMap.toMatrix_apply]
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  ext i j
  -- Porting note: replaced non-terminal `simp [LinearMap.toMatrix_apply]`
  fin_cases i <;> fin_cases j <;> 

Proof state:
case a.h.head.tail.head
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) { val := 0, isLt := (_ : 0 < 2) }
      { val := 1, isLt := (_ : (fun a => a < 2) 1) } =
    Matrix.of ![![1, 0], ![0, -1]] { val := 0, isLt := (_ : 0 < 2) } { val := 1, isLt := (_ : (fun a => a < 2) 1) }

Next tactic:
simp [LinearMap.toMatrix_apply]
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  ext i j
  -- Porting note: replaced non-terminal `simp [LinearMap.toMatrix_apply]`
  fin_cases i <;> fin_cases j <;> 

Proof state:
case a.h.tail.head.head
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) { val := 1, isLt := (_ : (fun a => a < 2) 1) }
      { val := 0, isLt := (_ : 0 < 2) } =
    Matrix.of ![![1, 0], ![0, -1]] { val := 1, isLt := (_ : (fun a => a < 2) 1) } { val := 0, isLt := (_ : 0 < 2) }

Next tactic:
simp [LinearMap.toMatrix_apply]
/-- The matrix representation of `conjAe`. -/
@[simp]
theorem toMatrix_conjAe :
    LinearMap.toMatrix basisOneI basisOneI conjAe.toLinearMap = !![1, 0; 0, -1] := by
  ext i j
  -- Porting note: replaced non-terminal `simp [LinearMap.toMatrix_apply]`
  fin_cases i <;> fin_cases j <;> 

Proof state:
case a.h.tail.head.tail.head
⊢ (LinearMap.toMatrix basisOneI basisOneI) (AlgEquiv.toLinearMap conjAe) { val := 1, isLt := (_ : (fun a => a < 2) 1) }
      { val := 1, isLt := (_ : (fun a => a < 2) 1) } =
    Matrix.of ![![1, 0], ![0, -1]] { val := 1, isLt := (_ : (fun a => a < 2) 1) }
      { val := 1, isLt := (_ : (fun a => a < 2) 1) }

Next tactic:
simp [LinearMap.toMatrix_apply]
/-- The identity and the complex conjugation are the only two `ℝ`-algebra homomorphisms of `ℂ`. -/
theorem real_algHom_eq_id_or_conj (f : ℂ →ₐ[ℝ] ℂ) : f = AlgHom.id ℝ ℂ ∨ f = conjAe := by
  

Proof state:
f : ℂ →ₐ[ℝ] ℂ
⊢ f = AlgHom.id ℝ ℂ ∨ f = ↑conjAe

Next tactic:
refine'
      (eq_or_eq_neg_of_sq_eq_sq (f I) I <| by rw [← map_pow, I_sq, map_neg, map_one]).imp _ _
/-- The identity and the complex conjugation are the only two `ℝ`-algebra homomorphisms of `ℂ`. -/
theorem real_algHom_eq_id_or_conj (f : ℂ →ₐ[ℝ] ℂ) : f = AlgHom.id ℝ ℂ ∨ f = conjAe := by
  refine'
      (eq_or_eq_neg_of_sq_eq_sq (f I) I <| by 

Proof state:
f : ℂ →ₐ[ℝ] ℂ
⊢ f I ^ 2 = I ^ 2

Next tactic:
rw [← map_pow, I_sq, map_neg, map_one]
/-- The identity and the complex conjugation are the only two `ℝ`-algebra homomorphisms of `ℂ`. -/
theorem real_algHom_eq_id_or_conj (f : ℂ →ₐ[ℝ] ℂ) : f = AlgHom.id ℝ ℂ ∨ f = conjAe := by
  refine'
      (eq_or_eq_neg_of_sq_eq_sq (f I) I <| by rw [← map_pow, I_sq, map_neg, map_one]).imp _ _ <;>
    

Proof state:
case refine'_1
f : ℂ →ₐ[ℝ] ℂ
⊢ f I = I → f = AlgHom.id ℝ ℂ

Next tactic:
refine' fun h => algHom_ext _
/-- The identity and the complex conjugation are the only two `ℝ`-algebra homomorphisms of `ℂ`. -/
theorem real_algHom_eq_id_or_conj (f : ℂ →ₐ[ℝ] ℂ) : f = AlgHom.id ℝ ℂ ∨ f = conjAe := by
  refine'
      (eq_or_eq_neg_of_sq_eq_sq (f I) I <| by rw [← map_pow, I_sq, map_neg, map_one]).imp _ _ <;>
    

Proof state:
case refine'_2
f : ℂ →ₐ[ℝ] ℂ
⊢ f I = -I → f = ↑conjAe

Next tactic:
refine' fun h => algHom_ext _
/-- The identity and the complex conjugation are the only two `ℝ`-algebra homomorphisms of `ℂ`. -/
theorem real_algHom_eq_id_or_conj (f : ℂ →ₐ[ℝ] ℂ) : f = AlgHom.id ℝ ℂ ∨ f = conjAe := by
  refine'
      (eq_or_eq_neg_of_sq_eq_sq (f I) I <| by rw [← map_pow, I_sq, map_neg, map_one]).imp _ _ <;>
    refine' fun h => algHom_ext _
  

Proof state:
case refine'_1
f : ℂ →ₐ[ℝ] ℂ
h : f I = I
⊢ f I = (AlgHom.id ℝ ℂ) I
case refine'_2 f : ℂ →ₐ[ℝ] ℂ h : f I = -I ⊢ f I = ↑conjAe I

Next tactic:
exacts [h, conj_I.symm ▸ h]
/-- The natural `AddEquiv` from `ℂ` to `ℝ × ℝ`. -/
@[simps! (config := { simpRhs := true }) apply symm_apply_re symm_apply_im]
def equivRealProdAddHom : ℂ ≃+ ℝ × ℝ :=
  { equivRealProd with map_add' := by 

Proof state:
src✝ : ℂ ≃ ℝ × ℝ := equivRealProd
⊢ ∀ (x y : ℂ),
    Equiv.toFun
        { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : Function.LeftInverse src✝.invFun src✝.toFun),
          right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
        (x + y) =
      Equiv.toFun
          { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : Function.LeftInverse src✝.invFun src✝.toFun),
            right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
          x +
        Equiv.toFun
          { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : Function.LeftInverse src✝.invFun src✝.toFun),
            right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
          y

Next tactic:
simp
/-- The natural `LinearEquiv` from `ℂ` to `ℝ × ℝ`. -/
@[simps! (config := { simpRhs := true }) apply symm_apply_re symm_apply_im]
def equivRealProdLm : ℂ ≃ₗ[ℝ] ℝ × ℝ :=
  { equivRealProdAddHom with
    -- Porting note: `simp` has issues with `Prod.smul_def`
    map_smul' := fun r c => by 

Proof state:
src✝ : ℂ ≃+ ℝ × ℝ := equivRealProdAddHom
r : ℝ
c : ℂ
⊢ AddHom.toFun
      { toFun := src✝.toFun,
        map_add' :=
          (_ :
            ∀ (x y : ℂ), Equiv.toFun src✝.toEquiv (x + y) = Equiv.toFun src✝.toEquiv x + Equiv.toFun src✝.toEquiv y) }
      (r • c) =
    (RingHom.id ℝ) r •
      AddHom.toFun
        { toFun := src✝.toFun,
          map_add' :=
            (_ :
              ∀ (x y : ℂ), Equiv.toFun src✝.toEquiv (x + y) = Equiv.toFun src✝.toEquiv x + Equiv.toFun src✝.toEquiv y) }
        c

Next tactic:
simp [equivRealProdAddHom, (Prod.smul_def), smul_eq_mul]
/-- There is an alg_hom from `ℂ` to any `ℝ`-algebra with an element that squares to `-1`.

See `Complex.lift` for this as an equiv. -/
def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A :=
  AlgHom.ofLinearMap
    ((Algebra.linearMap ℝ A).comp reLm + (LinearMap.toSpanSingleton _ _ I').comp imLm)
    (show algebraMap ℝ A 1 + (0 : ℝ) • I' = 1 by 

Proof state:
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hf : I' * I' = -1
⊢ (algebraMap ℝ A) 1 + 0 • I' = 1

Next tactic:
rw [RingHom.map_one, zero_smul, add_zero]
/-- There is an alg_hom from `ℂ` to any `ℝ`-algebra with an element that squares to `-1`.

See `Complex.lift` for this as an equiv. -/
def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A :=
  AlgHom.ofLinearMap
    ((Algebra.linearMap ℝ A).comp reLm + (LinearMap.toSpanSingleton _ _ I').comp imLm)
    (show algebraMap ℝ A 1 + (0 : ℝ) • I' = 1 by rw [RingHom.map_one, zero_smul, add_zero])
    fun ⟨x₁, y₁⟩ ⟨x₂, y₂⟩ =>
    show
      algebraMap ℝ A (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
        (algebraMap ℝ A x₁ + y₁ • I') * (algebraMap ℝ A x₂ + y₂ • I') by
      

Proof state:
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hf : I' * I' = -1
x✝¹ x✝ : ℂ
x₁ y₁ x₂ y₂ : ℝ
⊢ (algebraMap ℝ A) (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
    ((algebraMap ℝ A) x₁ + y₁ • I') * ((algebraMap ℝ A) x₂ + y₂ • I')

Next tactic:
rw [add_mul, mul_add, mul_add, add_comm _ (y₁ • I' * y₂ • I'), add_add_add_comm]
/-- There is an alg_hom from `ℂ` to any `ℝ`-algebra with an element that squares to `-1`.

See `Complex.lift` for this as an equiv. -/
def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A :=
  AlgHom.ofLinearMap
    ((Algebra.linearMap ℝ A).comp reLm + (LinearMap.toSpanSingleton _ _ I').comp imLm)
    (show algebraMap ℝ A 1 + (0 : ℝ) • I' = 1 by rw [RingHom.map_one, zero_smul, add_zero])
    fun ⟨x₁, y₁⟩ ⟨x₂, y₂⟩ =>
    show
      algebraMap ℝ A (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
        (algebraMap ℝ A x₁ + y₁ • I') * (algebraMap ℝ A x₂ + y₂ • I') by
      rw [add_mul, mul_add, mul_add, add_comm _ (y₁ • I' * y₂ • I'), add_add_add_comm]
      

Proof state:
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hf : I' * I' = -1
x✝¹ x✝ : ℂ
x₁ y₁ x₂ y₂ : ℝ
⊢ (algebraMap ℝ A) (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
    (algebraMap ℝ A) x₁ * (algebraMap ℝ A) x₂ + y₁ • I' * y₂ • I' +
      ((algebraMap ℝ A) x₁ * y₂ • I' + y₁ • I' * (algebraMap ℝ A) x₂)

Next tactic:
congr 1
/-- There is an alg_hom from `ℂ` to any `ℝ`-algebra with an element that squares to `-1`.

See `Complex.lift` for this as an equiv. -/
def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A :=
  AlgHom.ofLinearMap
    ((Algebra.linearMap ℝ A).comp reLm + (LinearMap.toSpanSingleton _ _ I').comp imLm)
    (show algebraMap ℝ A 1 + (0 : ℝ) • I' = 1 by rw [RingHom.map_one, zero_smul, add_zero])
    fun ⟨x₁, y₁⟩ ⟨x₂, y₂⟩ =>
    show
      algebraMap ℝ A (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
        (algebraMap ℝ A x₁ + y₁ • I') * (algebraMap ℝ A x₂ + y₂ • I') by
      rw [add_mul, mul_add, mul_add, add_comm _ (y₁ • I' * y₂ • I'), add_add_add_comm]
      congr 1
      -- equate "real" and "imaginary" parts
      · 

Proof state:
case e_a
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hf : I' * I' = -1
x✝¹ x✝ : ℂ
x₁ y₁ x₂ y₂ : ℝ
⊢ (algebraMap ℝ A) (x₁ * x₂ - y₁ * y₂) = (algebraMap ℝ A) x₁ * (algebraMap ℝ A) x₂ + y₁ • I' * y₂ • I'

Next tactic:
let inst : SMulCommClass ℝ A A := by infer_instance
/-- There is an alg_hom from `ℂ` to any `ℝ`-algebra with an element that squares to `-1`.

See `Complex.lift` for this as an equiv. -/
def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A :=
  AlgHom.ofLinearMap
    ((Algebra.linearMap ℝ A).comp reLm + (LinearMap.toSpanSingleton _ _ I').comp imLm)
    (show algebraMap ℝ A 1 + (0 : ℝ) • I' = 1 by rw [RingHom.map_one, zero_smul, add_zero])
    fun ⟨x₁, y₁⟩ ⟨x₂, y₂⟩ =>
    show
      algebraMap ℝ A (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
        (algebraMap ℝ A x₁ + y₁ • I') * (algebraMap ℝ A x₂ + y₂ • I') by
      rw [add_mul, mul_add, mul_add, add_comm _ (y₁ • I' * y₂ • I'), add_add_add_comm]
      congr 1
      -- equate "real" and "imaginary" parts
      · let inst : SMulCommClass ℝ A A := by 

Proof state:
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hf : I' * I' = -1
x✝¹ x✝ : ℂ
x₁ y₁ x₂ y₂ : ℝ
⊢ SMulCommClass ℝ A A

Next tactic:
infer_instance
/-- There is an alg_hom from `ℂ` to any `ℝ`-algebra with an element that squares to `-1`.

See `Complex.lift` for this as an equiv. -/
def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A :=
  AlgHom.ofLinearMap
    ((Algebra.linearMap ℝ A).comp reLm + (LinearMap.toSpanSingleton _ _ I').comp imLm)
    (show algebraMap ℝ A 1 + (0 : ℝ) • I' = 1 by rw [RingHom.map_one, zero_smul, add_zero])
    fun ⟨x₁, y₁⟩ ⟨x₂, y₂⟩ =>
    show
      algebraMap ℝ A (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
        (algebraMap ℝ A x₁ + y₁ • I') * (algebraMap ℝ A x₂ + y₂ • I') by
      rw [add_mul, mul_add, mul_add, add_comm _ (y₁ • I' * y₂ • I'), add_add_add_comm]
      congr 1
      -- equate "real" and "imaginary" parts
      · let inst : SMulCommClass ℝ A A := by infer_instance  -- porting note: added
        

Proof state:
case e_a
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hf : I' * I' = -1
x✝¹ x✝ : ℂ
x₁ y₁ x₂ y₂ : ℝ
inst : SMulCommClass ℝ A A := inferInstance
⊢ (algebraMap ℝ A) (x₁ * x₂ - y₁ * y₂) = (algebraMap ℝ A) x₁ * (algebraMap ℝ A) x₂ + y₁ • I' * y₂ • I'

Next tactic:
rw [smul_mul_smul, hf, smul_neg, ← Algebra.algebraMap_eq_smul_one, ← sub_eq_add_neg, ←
          RingHom.map_mul, ← RingHom.map_sub]
/-- There is an alg_hom from `ℂ` to any `ℝ`-algebra with an element that squares to `-1`.

See `Complex.lift` for this as an equiv. -/
def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A :=
  AlgHom.ofLinearMap
    ((Algebra.linearMap ℝ A).comp reLm + (LinearMap.toSpanSingleton _ _ I').comp imLm)
    (show algebraMap ℝ A 1 + (0 : ℝ) • I' = 1 by rw [RingHom.map_one, zero_smul, add_zero])
    fun ⟨x₁, y₁⟩ ⟨x₂, y₂⟩ =>
    show
      algebraMap ℝ A (x₁ * x₂ - y₁ * y₂) + (x₁ * y₂ + y₁ * x₂) • I' =
        (algebraMap ℝ A x₁ + y₁ • I') * (algebraMap ℝ A x₂ + y₂ • I') by
      rw [add_mul, mul_add, mul_add, add_comm _ (y₁ • I' * y₂ • I'), add_add_add_comm]
      congr 1
      -- equate "real" and "imaginary" parts
      · let inst : SMulCommClass ℝ A A := by infer_instance  -- porting note: added
        rw [smul_mul_smul, hf, smul_neg, ← Algebra.algebraMap_eq_smul_one, ← sub_eq_add_neg, ←
          RingHom.map_mul, ← RingHom.map_sub]
      · 

Proof state:
case e_a
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hf : I' * I' = -1
x✝¹ x✝ : ℂ
x₁ y₁ x₂ y₂ : ℝ
⊢ (x₁ * y₂ + y₁ * x₂) • I' = (algebraMap ℝ A) x₁ * y₂ • I' + y₁ • I' * (algebraMap ℝ A) x₂

Next tactic:
rw [Algebra.smul_def, Algebra.smul_def, Algebra.smul_def, ← Algebra.right_comm _ x₂, ←
          mul_assoc, ← add_mul, ← RingHom.map_mul, ← RingHom.map_mul, ← RingHom.map_add]
theorem liftAux_apply_I (I' : A) (hI') : liftAux I' hI' I = I' := by 

Proof state:
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
I' : A
hI' : I' * I' = -1
⊢ (liftAux I' hI') I = I'

Next tactic:
simp
/-- A universal property of the complex numbers, providing a unique `ℂ →ₐ[ℝ] A` for every element
of `A` which squares to `-1`.

This can be used to embed the complex numbers in the `Quaternion`s.

This isomorphism is named to match the very similar `Zsqrtd.lift`. -/
@[simps (config := { simpRhs := true })]
def lift : { I' : A // I' * I' = -1 } ≃ (ℂ →ₐ[ℝ] A) where
  toFun I' := liftAux I' I'.prop
  invFun F := ⟨F I, by 

Proof state:
A : Type u_1
inst✝¹ : Ring A
inst✝ : Algebra ℝ A
F : ℂ →ₐ[ℝ] A
⊢ F I * F I = -1

Next tactic:
rw [← F.map_mul, I_mul_I, AlgHom.map_neg, AlgHom.map_one]
/-- Create a `selfAdjoint` element from a `skewAdjoint` element by multiplying by the scalar
`-Complex.I`. -/
@[simps]
def skewAdjoint.negISMul : skewAdjoint A →ₗ[ℝ] selfAdjoint A where
  toFun a :=
    ⟨-I • ↑a, by
      

Proof state:
A : Type u_1
inst✝³ : AddCommGroup A
inst✝² : Module ℂ A
inst✝¹ : StarAddMonoid A
inst✝ : StarModule ℂ A
a : ↥(skewAdjoint A)
⊢ -I • ↑a ∈ selfAdjoint A

Next tactic:
simp only [neg_smul, neg_mem_iff, selfAdjoint.mem_iff, star_smul, star_def, conj_I,
        star_val_eq, smul_neg, neg_neg]
/-- Create a `selfAdjoint` element from a `skewAdjoint` element by multiplying by the scalar
`-Complex.I`. -/
@[simps]
def skewAdjoint.negISMul : skewAdjoint A →ₗ[ℝ] selfAdjoint A where
  toFun a :=
    ⟨-I • ↑a, by
      simp only [neg_smul, neg_mem_iff, selfAdjoint.mem_iff, star_smul, star_def, conj_I,
        star_val_eq, smul_neg, neg_neg]⟩
  map_add' a b := by
    

Proof state:
A : Type u_1
inst✝³ : AddCommGroup A
inst✝² : Module ℂ A
inst✝¹ : StarAddMonoid A
inst✝ : StarModule ℂ A
a b : ↥(skewAdjoint A)
⊢ (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) (a + b) =
    (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) a +
      (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) b

Next tactic:
ext
/-- Create a `selfAdjoint` element from a `skewAdjoint` element by multiplying by the scalar
`-Complex.I`. -/
@[simps]
def skewAdjoint.negISMul : skewAdjoint A →ₗ[ℝ] selfAdjoint A where
  toFun a :=
    ⟨-I • ↑a, by
      simp only [neg_smul, neg_mem_iff, selfAdjoint.mem_iff, star_smul, star_def, conj_I,
        star_val_eq, smul_neg, neg_neg]⟩
  map_add' a b := by
    ext
    

Proof state:
case a
A : Type u_1
inst✝³ : AddCommGroup A
inst✝² : Module ℂ A
inst✝¹ : StarAddMonoid A
inst✝ : StarModule ℂ A
a b : ↥(skewAdjoint A)
⊢ ↑((fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) (a + b)) =
    ↑((fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) a +
        (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) b)

Next tactic:
simp only [AddSubgroup.coe_add, smul_add, AddMemClass.mk_add_mk]
/-- Create a `selfAdjoint` element from a `skewAdjoint` element by multiplying by the scalar
`-Complex.I`. -/
@[simps]
def skewAdjoint.negISMul : skewAdjoint A →ₗ[ℝ] selfAdjoint A where
  toFun a :=
    ⟨-I • ↑a, by
      simp only [neg_smul, neg_mem_iff, selfAdjoint.mem_iff, star_smul, star_def, conj_I,
        star_val_eq, smul_neg, neg_neg]⟩
  map_add' a b := by
    ext
    simp only [AddSubgroup.coe_add, smul_add, AddMemClass.mk_add_mk]
  map_smul' a b := by
    

Proof state:
A : Type u_1
inst✝³ : AddCommGroup A
inst✝² : Module ℂ A
inst✝¹ : StarAddMonoid A
inst✝ : StarModule ℂ A
a : ℝ
b : ↥(skewAdjoint A)
⊢ AddHom.toFun
      { toFun := fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) },
        map_add' :=
          (_ :
            ∀ (a b : ↥(skewAdjoint A)),
              (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) (a + b) =
                (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) a +
                  (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) b) }
      (a • b) =
    (RingHom.id ℝ) a •
      AddHom.toFun
        { toFun := fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) },
          map_add' :=
            (_ :
              ∀ (a b : ↥(skewAdjoint A)),
                (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) (a + b) =
                  (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) a +
                    (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) b) }
        b

Next tactic:
ext
/-- Create a `selfAdjoint` element from a `skewAdjoint` element by multiplying by the scalar
`-Complex.I`. -/
@[simps]
def skewAdjoint.negISMul : skewAdjoint A →ₗ[ℝ] selfAdjoint A where
  toFun a :=
    ⟨-I • ↑a, by
      simp only [neg_smul, neg_mem_iff, selfAdjoint.mem_iff, star_smul, star_def, conj_I,
        star_val_eq, smul_neg, neg_neg]⟩
  map_add' a b := by
    ext
    simp only [AddSubgroup.coe_add, smul_add, AddMemClass.mk_add_mk]
  map_smul' a b := by
    ext
    

Proof state:
case a
A : Type u_1
inst✝³ : AddCommGroup A
inst✝² : Module ℂ A
inst✝¹ : StarAddMonoid A
inst✝ : StarModule ℂ A
a : ℝ
b : ↥(skewAdjoint A)
⊢ ↑(AddHom.toFun
        { toFun := fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) },
          map_add' :=
            (_ :
              ∀ (a b : ↥(skewAdjoint A)),
                (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) (a + b) =
                  (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) a +
                    (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) b) }
        (a • b)) =
    ↑((RingHom.id ℝ) a •
        AddHom.toFun
          { toFun := fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) },
            map_add' :=
              (_ :
                ∀ (a b : ↥(skewAdjoint A)),
                  (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) (a + b) =
                    (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) a +
                      (fun a => { val := -I • ↑a, property := (_ : -I • ↑a ∈ selfAdjoint A) }) b) }
          b)

Next tactic:
simp only [neg_smul, skewAdjoint.val_smul, AddSubgroup.coe_mk, RingHom.id_apply,
      selfAdjoint.val_smul, smul_neg, neg_inj]