l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem IsUnit.mul [Monoid M] {x y : M} : IsUnit x → IsUnit y → IsUnit (x * y) := by
  rintro ⟨x, rfl⟩ ⟨y, rfl⟩
  

Proof state:
case intro.intro
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
x y : Mˣ
⊢ IsUnit (↑x * ↑y)

Next tactic:
exact ⟨x * y, Units.val_mul _ _⟩
/-- Multiplication by a `u : Mˣ` on the right doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the right doesn't affect `IsAddUnit`."]
theorem Units.isUnit_mul_units [Monoid M] (a : M) (u : Mˣ) : IsUnit (a * u) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a : M
u : Mˣ
x✝ : IsUnit (a * ↑u)
v : Mˣ
hv : ↑v = a * ↑u
⊢ IsUnit a

Next tactic:
have : IsUnit (a * ↑u * ↑u⁻¹) := by exists v * u⁻¹; rw [← hv, Units.val_mul]
/-- Multiplication by a `u : Mˣ` on the right doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the right doesn't affect `IsAddUnit`."]
theorem Units.isUnit_mul_units [Monoid M] (a : M) (u : Mˣ) : IsUnit (a * u) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      have : IsUnit (a * ↑u * ↑u⁻¹) := by 

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a : M
u : Mˣ
x✝ : IsUnit (a * ↑u)
v : Mˣ
hv : ↑v = a * ↑u
⊢ IsUnit (a * ↑u * ↑u⁻¹)

Next tactic:
exists v * u⁻¹
/-- Multiplication by a `u : Mˣ` on the right doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the right doesn't affect `IsAddUnit`."]
theorem Units.isUnit_mul_units [Monoid M] (a : M) (u : Mˣ) : IsUnit (a * u) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      have : IsUnit (a * ↑u * ↑u⁻¹) := by exists v * u⁻¹; 

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a : M
u : Mˣ
x✝ : IsUnit (a * ↑u)
v : Mˣ
hv : ↑v = a * ↑u
⊢ ↑(v * u⁻¹) = a * ↑u * ↑u⁻¹

Next tactic:
rw [← hv, Units.val_mul]
/-- Multiplication by a `u : Mˣ` on the right doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the right doesn't affect `IsAddUnit`."]
theorem Units.isUnit_mul_units [Monoid M] (a : M) (u : Mˣ) : IsUnit (a * u) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      have : IsUnit (a * ↑u * ↑u⁻¹) := by exists v * u⁻¹; rw [← hv, Units.val_mul]
      

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a : M
u : Mˣ
x✝ : IsUnit (a * ↑u)
v : Mˣ
hv : ↑v = a * ↑u
this : IsUnit (a * ↑u * ↑u⁻¹)
⊢ IsUnit a

Next tactic:
rwa [mul_assoc, Units.mul_inv, mul_one] at this
/-- Multiplication by a `u : Mˣ` on the left doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the left doesn't affect `IsAddUnit`."]
theorem Units.isUnit_units_mul {M : Type*} [Monoid M] (u : Mˣ) (a : M) :
    IsUnit (↑u * a) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      

Proof state:
α : Type u
M✝ : Type u_1
N : Type u_2
M : Type u_3
inst✝ : Monoid M
u : Mˣ
a : M
x✝ : IsUnit (↑u * a)
v : Mˣ
hv : ↑v = ↑u * a
⊢ IsUnit a

Next tactic:
have : IsUnit (↑u⁻¹ * (↑u * a)) := by exists u⁻¹ * v; rw [← hv, Units.val_mul]
/-- Multiplication by a `u : Mˣ` on the left doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the left doesn't affect `IsAddUnit`."]
theorem Units.isUnit_units_mul {M : Type*} [Monoid M] (u : Mˣ) (a : M) :
    IsUnit (↑u * a) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      have : IsUnit (↑u⁻¹ * (↑u * a)) := by 

Proof state:
α : Type u
M✝ : Type u_1
N : Type u_2
M : Type u_3
inst✝ : Monoid M
u : Mˣ
a : M
x✝ : IsUnit (↑u * a)
v : Mˣ
hv : ↑v = ↑u * a
⊢ IsUnit (↑u⁻¹ * (↑u * a))

Next tactic:
exists u⁻¹ * v
/-- Multiplication by a `u : Mˣ` on the left doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the left doesn't affect `IsAddUnit`."]
theorem Units.isUnit_units_mul {M : Type*} [Monoid M] (u : Mˣ) (a : M) :
    IsUnit (↑u * a) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      have : IsUnit (↑u⁻¹ * (↑u * a)) := by exists u⁻¹ * v; 

Proof state:
α : Type u
M✝ : Type u_1
N : Type u_2
M : Type u_3
inst✝ : Monoid M
u : Mˣ
a : M
x✝ : IsUnit (↑u * a)
v : Mˣ
hv : ↑v = ↑u * a
⊢ ↑(u⁻¹ * v) = ↑u⁻¹ * (↑u * a)

Next tactic:
rw [← hv, Units.val_mul]
/-- Multiplication by a `u : Mˣ` on the left doesn't affect `IsUnit`. -/
@[to_additive (attr := simp)
"Addition of a `u : AddUnits M` on the left doesn't affect `IsAddUnit`."]
theorem Units.isUnit_units_mul {M : Type*} [Monoid M] (u : Mˣ) (a : M) :
    IsUnit (↑u * a) ↔ IsUnit a :=
  Iff.intro
    (fun ⟨v, hv⟩ => by
      have : IsUnit (↑u⁻¹ * (↑u * a)) := by exists u⁻¹ * v; rw [← hv, Units.val_mul]
      

Proof state:
α : Type u
M✝ : Type u_1
N : Type u_2
M : Type u_3
inst✝ : Monoid M
u : Mˣ
a : M
x✝ : IsUnit (↑u * a)
v : Mˣ
hv : ↑v = ↑u * a
this : IsUnit (↑u⁻¹ * (↑u * a))
⊢ IsUnit a

Next tactic:
rwa [← mul_assoc, Units.inv_mul, one_mul] at this
@[to_additive]
theorem isUnit_of_mul_isUnit_left [CommMonoid M] {x y : M} (hu : IsUnit (x * y)) : IsUnit x :=
  let ⟨z, hz⟩ := isUnit_iff_exists_inv.1 hu
  isUnit_iff_exists_inv.2 ⟨y * z, by 

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : CommMonoid M
x y : M
hu : IsUnit (x * y)
z : M
hz : x * y * z = 1
⊢ x * (y * z) = 1

Next tactic:
rwa [← mul_assoc]
@[to_additive]
theorem isUnit_of_mul_isUnit_right [CommMonoid M] {x y : M} (hu : IsUnit (x * y)) : IsUnit y :=
  @isUnit_of_mul_isUnit_left _ _ y x <| by 

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : CommMonoid M
x y : M
hu : IsUnit (x * y)
⊢ IsUnit (y * x)

Next tactic:
rwa [mul_comm]
@[to_additive (attr := simp)]
theorem mul_val_inv (h : IsUnit a) : a * ↑h.unit⁻¹ = 1 := by
  

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a b c : M
h : IsUnit a
⊢ a * ↑(IsUnit.unit h)⁻¹ = 1

Next tactic:
rw [← h.unit.mul_inv]
@[to_additive (attr := simp)]
theorem mul_val_inv (h : IsUnit a) : a * ↑h.unit⁻¹ = 1 := by
  rw [← h.unit.mul_inv]; 

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a b c : M
h : IsUnit a
⊢ a * ↑(IsUnit.unit h)⁻¹ = ↑(IsUnit.unit h) * ↑(IsUnit.unit h)⁻¹

Next tactic:
congr
@[to_additive (attr := simp)]
protected theorem inv_mul_cancel : IsUnit a → a⁻¹ * a = 1 := by
  

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : DivisionMonoid M
a : M
⊢ IsUnit a → a⁻¹ * a = 1

Next tactic:
rintro ⟨u, rfl⟩
@[to_additive (attr := simp)]
protected theorem inv_mul_cancel : IsUnit a → a⁻¹ * a = 1 := by
  rintro ⟨u, rfl⟩
  

Proof state:
case intro
α : Type u
M : Type u_1
N : Type u_2
inst✝ : DivisionMonoid M
u : Mˣ
⊢ (↑u)⁻¹ * ↑u = 1

Next tactic:
rw [← Units.val_inv_eq_inv_val, Units.inv_mul]
@[to_additive (attr := simp)]
protected theorem mul_inv_cancel : IsUnit a → a * a⁻¹ = 1 := by
  

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : DivisionMonoid M
a : M
⊢ IsUnit a → a * a⁻¹ = 1

Next tactic:
rintro ⟨u, rfl⟩
@[to_additive (attr := simp)]
protected theorem mul_inv_cancel : IsUnit a → a * a⁻¹ = 1 := by
  rintro ⟨u, rfl⟩
  

Proof state:
case intro
α : Type u
M : Type u_1
N : Type u_2
inst✝ : DivisionMonoid M
u : Mˣ
⊢ ↑u * (↑u)⁻¹ = 1

Next tactic:
rw [← Units.val_inv_eq_inv_val, Units.mul_inv]
/-- Constructs a `Group` structure on a `Monoid` consisting only of units. -/
noncomputable def groupOfIsUnit [hM : Monoid M] (h : ∀ a : M, IsUnit a) : Group M :=
  { hM with
    inv := fun a => ↑(h a).unit⁻¹,
    mul_left_inv := fun a => by
      

Proof state:
α : Type u
M : Type u_1
hM : Monoid M
h : ∀ (a : M), IsUnit a
a : M
⊢ a⁻¹ * a = 1

Next tactic:
change ↑(h a).unit⁻¹ * a = 1
/-- Constructs a `Group` structure on a `Monoid` consisting only of units. -/
noncomputable def groupOfIsUnit [hM : Monoid M] (h : ∀ a : M, IsUnit a) : Group M :=
  { hM with
    inv := fun a => ↑(h a).unit⁻¹,
    mul_left_inv := fun a => by
      change ↑(h a).unit⁻¹ * a = 1
      

Proof state:
α : Type u
M : Type u_1
hM : Monoid M
h : ∀ (a : M), IsUnit a
a : M
⊢ ↑(IsUnit.unit (_ : IsUnit a))⁻¹ * a = 1

Next tactic:
rw [Units.inv_mul_eq_iff_eq_mul, (h a).unit_spec, mul_one]
/-- Constructs a `CommGroup` structure on a `CommMonoid` consisting only of units. -/
noncomputable def commGroupOfIsUnit [hM : CommMonoid M] (h : ∀ a : M, IsUnit a) : CommGroup M :=
  { hM with
    inv := fun a => ↑(h a).unit⁻¹,
    mul_left_inv := fun a => by
      

Proof state:
α : Type u
M : Type u_1
hM : CommMonoid M
h : ∀ (a : M), IsUnit a
a : M
⊢ a⁻¹ * a = 1

Next tactic:
change ↑(h a).unit⁻¹ * a = 1
/-- Constructs a `CommGroup` structure on a `CommMonoid` consisting only of units. -/
noncomputable def commGroupOfIsUnit [hM : CommMonoid M] (h : ∀ a : M, IsUnit a) : CommGroup M :=
  { hM with
    inv := fun a => ↑(h a).unit⁻¹,
    mul_left_inv := fun a => by
      change ↑(h a).unit⁻¹ * a = 1
      

Proof state:
α : Type u
M : Type u_1
hM : CommMonoid M
h : ∀ (a : M), IsUnit a
a : M
⊢ ↑(IsUnit.unit (_ : IsUnit a))⁻¹ * a = 1

Next tactic:
rw [Units.inv_mul_eq_iff_eq_mul, (h a).unit_spec, mul_one]
/-- The map from `Matrix n n R` to bilinear forms on `n → R`.

This is an auxiliary definition for the equivalence `Matrix.toBilin'`. -/
def Matrix.toBilin'Aux [Fintype n] (M : Matrix n n R₂) : BilinForm R₂ (n → R₂) where
  bilin v w := ∑ i, ∑ j, v i * M i j * w j
  bilin_add_left x y z := by 

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁵ : Semiring R
inst✝¹⁴ : AddCommMonoid M✝
inst✝¹³ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹² : Ring R₁
inst✝¹¹ : AddCommGroup M₁
inst✝¹⁰ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝⁹ : CommSemiring R₂
inst✝⁸ : AddCommMonoid M₂
inst✝⁷ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁶ : CommRing R₃
inst✝⁵ : AddCommGroup M₃
inst✝⁴ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝³ : Field K
inst✝² : AddCommGroup V
inst✝¹ : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝ : Fintype n
M : Matrix n n R₂
x y z : n → R₂
⊢ (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) (x + y) z =
    (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) x z + (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) y z

Next tactic:
simp only [Pi.add_apply, add_mul, sum_add_distrib]
/-- The map from `Matrix n n R` to bilinear forms on `n → R`.

This is an auxiliary definition for the equivalence `Matrix.toBilin'`. -/
def Matrix.toBilin'Aux [Fintype n] (M : Matrix n n R₂) : BilinForm R₂ (n → R₂) where
  bilin v w := ∑ i, ∑ j, v i * M i j * w j
  bilin_add_left x y z := by simp only [Pi.add_apply, add_mul, sum_add_distrib]
  bilin_smul_left a x y := by 

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁵ : Semiring R
inst✝¹⁴ : AddCommMonoid M✝
inst✝¹³ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹² : Ring R₁
inst✝¹¹ : AddCommGroup M₁
inst✝¹⁰ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝⁹ : CommSemiring R₂
inst✝⁸ : AddCommMonoid M₂
inst✝⁷ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁶ : CommRing R₃
inst✝⁵ : AddCommGroup M₃
inst✝⁴ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝³ : Field K
inst✝² : AddCommGroup V
inst✝¹ : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝ : Fintype n
M : Matrix n n R₂
a : R₂
x y : n → R₂
⊢ (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) (a • x) y = a * (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) x y

Next tactic:
simp only [Pi.smul_apply, smul_eq_mul, mul_assoc, mul_sum]
/-- The map from `Matrix n n R` to bilinear forms on `n → R`.

This is an auxiliary definition for the equivalence `Matrix.toBilin'`. -/
def Matrix.toBilin'Aux [Fintype n] (M : Matrix n n R₂) : BilinForm R₂ (n → R₂) where
  bilin v w := ∑ i, ∑ j, v i * M i j * w j
  bilin_add_left x y z := by simp only [Pi.add_apply, add_mul, sum_add_distrib]
  bilin_smul_left a x y := by simp only [Pi.smul_apply, smul_eq_mul, mul_assoc, mul_sum]
  bilin_add_right x y z := by 

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁵ : Semiring R
inst✝¹⁴ : AddCommMonoid M✝
inst✝¹³ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹² : Ring R₁
inst✝¹¹ : AddCommGroup M₁
inst✝¹⁰ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝⁹ : CommSemiring R₂
inst✝⁸ : AddCommMonoid M₂
inst✝⁷ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁶ : CommRing R₃
inst✝⁵ : AddCommGroup M₃
inst✝⁴ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝³ : Field K
inst✝² : AddCommGroup V
inst✝¹ : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝ : Fintype n
M : Matrix n n R₂
x y z : n → R₂
⊢ (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) x (y + z) =
    (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) x y + (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) x z

Next tactic:
simp only [Pi.add_apply, mul_add, sum_add_distrib]
/-- The map from `Matrix n n R` to bilinear forms on `n → R`.

This is an auxiliary definition for the equivalence `Matrix.toBilin'`. -/
def Matrix.toBilin'Aux [Fintype n] (M : Matrix n n R₂) : BilinForm R₂ (n → R₂) where
  bilin v w := ∑ i, ∑ j, v i * M i j * w j
  bilin_add_left x y z := by simp only [Pi.add_apply, add_mul, sum_add_distrib]
  bilin_smul_left a x y := by simp only [Pi.smul_apply, smul_eq_mul, mul_assoc, mul_sum]
  bilin_add_right x y z := by simp only [Pi.add_apply, mul_add, sum_add_distrib]
  bilin_smul_right a x y := by
    

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁵ : Semiring R
inst✝¹⁴ : AddCommMonoid M✝
inst✝¹³ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹² : Ring R₁
inst✝¹¹ : AddCommGroup M₁
inst✝¹⁰ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝⁹ : CommSemiring R₂
inst✝⁸ : AddCommMonoid M₂
inst✝⁷ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁶ : CommRing R₃
inst✝⁵ : AddCommGroup M₃
inst✝⁴ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝³ : Field K
inst✝² : AddCommGroup V
inst✝¹ : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝ : Fintype n
M : Matrix n n R₂
a : R₂
x y : n → R₂
⊢ (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) x (a • y) = a * (fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j) x y

Next tactic:
simp only [Pi.smul_apply, smul_eq_mul, mul_assoc, mul_left_comm, mul_sum]
theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) :
    M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1)
      (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by
  

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁶ : Semiring R
inst✝¹⁵ : AddCommMonoid M✝
inst✝¹⁴ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹³ : Ring R₁
inst✝¹² : AddCommGroup M₁
inst✝¹¹ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝¹⁰ : CommSemiring R₂
inst✝⁹ : AddCommMonoid M₂
inst✝⁸ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁷ : CommRing R₃
inst✝⁶ : AddCommGroup M₃
inst✝⁵ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n R₂
i j : n
⊢ bilin (toBilin'Aux M) ((LinearMap.stdBasis R₂ (fun x => R₂) i) 1) ((LinearMap.stdBasis R₂ (fun x => R₂) j) 1) = M i j

Next tactic:
rw [Matrix.toBilin'Aux]
theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) :
    M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1)
      (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by
  rw [Matrix.toBilin'Aux]
  

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁶ : Semiring R
inst✝¹⁵ : AddCommMonoid M✝
inst✝¹⁴ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹³ : Ring R₁
inst✝¹² : AddCommGroup M₁
inst✝¹¹ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝¹⁰ : CommSemiring R₂
inst✝⁹ : AddCommMonoid M₂
inst✝⁸ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁷ : CommRing R₃
inst✝⁶ : AddCommGroup M₃
inst✝⁵ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n R₂
i j : n
⊢ bilin
      { bilin := fun v w => ∑ i : n, ∑ j : n, v i * M i j * w j,
        bilin_add_left :=
          (_ :
            ∀ (x y z : n → R₂),
              ∑ i : n, ∑ j : n, (x + y) i * M i j * z j =
                ∑ x_1 : n, ∑ x_2 : n, x x_1 * M x_1 x_2 * z x_2 + ∑ x : n, ∑ x_1 : n, y x * M x x_1 * z x_1),
        bilin_smul_left :=
          (_ :
            ∀ (a : R₂) (x y : n → R₂),
              ∑ i : n, ∑ j : n, (a • x) i * M i j * y j = a * ∑ i : n, ∑ j : n, x i * M i j * y j),
        bilin_add_right :=
          (_ :
            ∀ (x y z : n → R₂),
              ∑ i : n, ∑ j : n, x i * M i j * (y + z) j =
                ∑ x_1 : n, ∑ x_2 : n, x x_1 * M x_1 x_2 * y x_2 + ∑ x_1 : n, ∑ x_2 : n, x x_1 * M x_1 x_2 * z x_2),
        bilin_smul_right :=
          (_ :
            ∀ (a : R₂) (x y : n → R₂),
              ∑ i : n, ∑ j : n, x i * M i j * (a • y) j = a * ∑ i : n, ∑ j : n, x i * M i j * y j) }
      ((LinearMap.stdBasis R₂ (fun x => R₂) i) 1) ((LinearMap.stdBasis R₂ (fun x => R₂) j) 1) =
    M i j

Next tactic:
dsimp only
theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) :
    M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1)
      (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by
  rw [Matrix.toBilin'Aux]
  dsimp only -- Porting note: had to add `dsimp only` to get rid of the projections
  

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁶ : Semiring R
inst✝¹⁵ : AddCommMonoid M✝
inst✝¹⁴ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹³ : Ring R₁
inst✝¹² : AddCommGroup M₁
inst✝¹¹ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝¹⁰ : CommSemiring R₂
inst✝⁹ : AddCommMonoid M₂
inst✝⁸ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁷ : CommRing R₃
inst✝⁶ : AddCommGroup M₃
inst✝⁵ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n R₂
i j : n
⊢ ∑ i_1 : n,
      ∑ j_1 : n,
        (LinearMap.stdBasis R₂ (fun x => R₂) i) 1 i_1 * M i_1 j_1 * (LinearMap.stdBasis R₂ (fun x => R₂) j) 1 j_1 =
    M i j

Next tactic:
rw [sum_eq_single i, sum_eq_single j]
theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) :
    M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1)
      (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by
  rw [Matrix.toBilin'Aux]
  dsimp only -- Porting note: had to add `dsimp only` to get rid of the projections
  rw [sum_eq_single i, sum_eq_single j]
  · 

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝¹⁶ : Semiring R
inst✝¹⁵ : AddCommMonoid M✝
inst✝¹⁴ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹³ : Ring R₁
inst✝¹² : AddCommGroup M₁
inst✝¹¹ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝¹⁰ : CommSemiring R₂
inst✝⁹ : AddCommMonoid M₂
inst✝⁸ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁷ : CommRing R₃
inst✝⁶ : AddCommGroup M₃
inst✝⁵ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n R₂
i j : n
⊢ (LinearMap.stdBasis R₂ (fun x => R₂) i) 1 i * M i j * (LinearMap.stdBasis R₂ (fun x => R₂) j) 1 j = M i j

Next tactic:
simp only [stdBasis_same, stdBasis_same, one_mul, mul_one]
theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) :
    M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1)
      (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by
  rw [Matrix.toBilin'Aux]
  dsimp only -- Porting note: had to add `dsimp only` to get rid of the projections
  rw [sum_eq_single i, sum_eq_single j]
  · simp only [stdBasis_same, stdBasis_same, one_mul, mul_one]
  · 

Proof state:
case h₀
R : Type u_1
M✝ : Type u_2
inst✝¹⁶ : Semiring R
inst✝¹⁵ : AddCommMonoid M✝
inst✝¹⁴ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹³ : Ring R₁
inst✝¹² : AddCommGroup M₁
inst✝¹¹ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝¹⁰ : CommSemiring R₂
inst✝⁹ : AddCommMonoid M₂
inst✝⁸ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁷ : CommRing R₃
inst✝⁶ : AddCommGroup M₃
inst✝⁵ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n R₂
i j : n
⊢ ∀ b ∈ univ,
    b ≠ j → (LinearMap.stdBasis R₂ (fun x => R₂) i) 1 i * M i b * (LinearMap.stdBasis R₂ (fun x => R₂) j) 1 b = 0

Next tactic:
rintro j' - hj'
theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) :
    M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1)
      (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by
  rw [Matrix.toBilin'Aux]
  dsimp only -- Porting note: had to add `dsimp only` to get rid of the projections
  rw [sum_eq_single i, sum_eq_single j]
  · simp only [stdBasis_same, stdBasis_same, one_mul, mul_one]
  · rintro j' - hj'
    

Proof state:
case h₀
R : Type u_1
M✝ : Type u_2
inst✝¹⁶ : Semiring R
inst✝¹⁵ : AddCommMonoid M✝
inst✝¹⁴ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹³ : Ring R₁
inst✝¹² : AddCommGroup M₁
inst✝¹¹ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝¹⁰ : CommSemiring R₂
inst✝⁹ : AddCommMonoid M₂
inst✝⁸ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁷ : CommRing R₃
inst✝⁶ : AddCommGroup M₃
inst✝⁵ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n R₂
i j j' : n
hj' : j' ≠ j
⊢ (LinearMap.stdBasis R₂ (fun x => R₂) i) 1 i * M i j' * (LinearMap.stdBasis R₂ (fun x => R₂) j) 1 j' = 0

Next tactic:
apply mul_eq_zero_of_right
theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) :
    M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1)
      (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by
  rw [Matrix.toBilin'Aux]
  dsimp only -- Porting note: had to add `dsimp only` to get rid of the projections
  rw [sum_eq_single i, sum_eq_single j]
  · simp only [stdBasis_same, stdBasis_same, one_mul, mul_one]
  · rintro j' - hj'
    apply mul_eq_zero_of_right
    

Proof state:
case h₀.h
R : Type u_1
M✝ : Type u_2
inst✝¹⁶ : Semiring R
inst✝¹⁵ : AddCommMonoid M✝
inst✝¹⁴ : Module R M✝
R₁ : Type u_3
M₁ : Type u_4
inst✝¹³ : Ring R₁
inst✝¹² : AddCommGroup M₁
inst✝¹¹ : Module R₁ M₁
R₂ : Type u_5
M₂ : Type u_6
inst✝¹⁰ : CommSemiring R₂
inst✝⁹ : AddCommMonoid M₂
inst✝⁸ : Module R₂ M₂
R₃ : Type u_7
M₃ : Type u_8
inst✝⁷ : CommRing R₃
inst✝⁶ : AddCommGroup M₃
inst✝⁵ : Module R₃ M₃
V : Type u_9
K : Type u_10
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
B : BilinForm R M✝
B₁ : BilinForm R₁ M₁
B₂ : BilinForm R₂ M₂
n : Type u_11
o : Type u_12
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M : Matrix n n R₂
i j j' : n
hj' : j' ≠ j
⊢ (LinearMap.stdBasis R₂ (fun x => R₂) j) 1 j' = 0

Next tactic:
exact stdBasis_ne R₂ (fun _ => R₂) _ _ hj' 1