File: Mathlib/Data/Matrix/Notation.lean

full_name: Matrix.toExpr
code: /-- Matrices can be reflected whenever their entries can. We insert a `Matrix.of` to
prevent immediate decay to a function. -/
protected instance toExpr [ToLevel.{u}] [ToLevel.{uₘ}] [ToLevel.{uₙ}]
    [Lean.ToExpr α] [Lean.ToExpr m'] [Lean.ToExpr n'] [Lean.ToExpr (m' → n' → α)] :
    Lean.ToExpr (Matrix m' n' α) 
goal: Lean.ToExpr (Matrix m' n' α)

full_name: Matrix.matrixNotation
code: /-- Notation for m×n matrices, aka `Matrix (Fin m) (Fin n) α`.

For instance:
* `!![a, b, c; d, e, f]` is the matrix with two rows and three columns, of type
  `Matrix (Fin 2) (Fin 3) α`
* `!![a, b, c]` is a row vector of type `Matrix (Fin 1) (Fin 3) α` (see also `Matrix.row`).
* `!![a; b; c]` is a column vector of type `Matrix (Fin 3) (Fin 1) α` (see also `Matrix.col`).

This notation implements some special cases:

* `![,,]`, with `n` `,`s, is a term of type `Matrix (Fin 0) (Fin n) α`
* `![;;]`, with `m` `;`s, is a term of type `Matrix (Fin m) (Fin 0) α`
* `![]` is the 0×0 matrix

Note that vector notation is provided elsewhere (by `Matrix.vecNotation`) as `![a, b, c]`.
Under the hood, `!![a, b, c; d, e, f]` is syntax for `Matrix.of ![![a, b, c], ![d, e, f]]`.
-/
syntax (name := matrixNotation)
  "!![" ppRealGroup(sepBy1(ppGroup(term,+,?), ";", "; ", allowTrailingSep)) "]" : term
goal: Lean.ParserDescr

full_name: Matrix.matrixNotationRx0
code: @[inherit_doc matrixNotation]
syntax (name := matrixNotationRx0) "!![" ";"+ "]" : term
goal: Lean.ParserDescr

full_name: Matrix.matrixNotation0xC
code: @[inherit_doc matrixNotation]
syntax (name := matrixNotation0xC) "!![" ","* "]" : term
goal: Lean.ParserDescr

full_name: Matrix._aux_Mathlib_Data_Matrix_Notation___macroRules_Matrix_matrixNotation0xC_1
code: macro_rules
  | `(!![$[$[$rows],*];*]) => do
    let m := rows.size
    let n := if h : 0 < m then rows[0].size else 0
    let rowVecs ← rows.mapM fun row : Array Term => do
      unless row.size = n do
        Macro.throwErrorAt (mkNullNode row) s!"\
          Rows must be of equal length; this row has {row.size} items, \
          the previous rows have {n}"
      `(![$row,*])
    `(@Matrix.of (Fin $(quote m)) (Fin $(quote n)) _ ![$rowVecs,*])
  | `(!![$[;%$semicolons]*]) => do
    let emptyVec ← `(![])
    let emptyVecs := semicolons.map (fun _ => emptyVec)
    `(@Matrix.of (Fin $(quote semicolons.size)) (Fin 0) _ ![$emptyVecs,*])
  | `(!![$[,%$commas]*]) => `(@Matrix.of (Fin 0) (Fin $(quote commas.size)) _ ![])
goal: Lean.Macro

full_name: Matrix._aux_Mathlib_Data_Matrix_Notation___macroRules_Matrix_matrixNotationRx0_1
code: macro_rules
  | `(!![$[$[$rows],*];*]) => do
    let m := rows.size
    let n := if h : 0 < m then rows[0].size else 0
    let rowVecs ← rows.mapM fun row : Array Term => do
      unless row.size = n do
        Macro.throwErrorAt (mkNullNode row) s!"\
          Rows must be of equal length; this row has {row.size} items, \
          the previous rows have {n}"
      `(![$row,*])
    `(@Matrix.of (Fin $(quote m)) (Fin $(quote n)) _ ![$rowVecs,*])
  | `(!![$[;%$semicolons]*]) => do
    let emptyVec ← `(![])
    let emptyVecs := semicolons.map (fun _ => emptyVec)
    `(@Matrix.of (Fin $(quote semicolons.size)) (Fin 0) _ ![$emptyVecs,*])
  | `(!![$[,%$commas]*]) => `(@Matrix.of (Fin 0) (Fin $(quote commas.size)) _ ![])
goal: Lean.Macro

full_name: Matrix._aux_Mathlib_Data_Matrix_Notation___macroRules_Matrix_matrixNotation_1
code: macro_rules
  | `(!![$[$[$rows],*];*]) => do
    let m := rows.size
    let n := if h : 0 < m then rows[0].size else 0
    let rowVecs ← rows.mapM fun row : Array Term => do
      unless row.size = n do
        Macro.throwErrorAt (mkNullNode row) s!"\
          Rows must be of equal length; this row has {row.size} items, \
          the previous rows have {n}"
      `(![$row,*])
    `(@Matrix.of (Fin $(quote m)) (Fin $(quote n)) _ ![$rowVecs,*])
  | `(!![$[;%$semicolons]*]) => do
    let emptyVec ← `(![])
    let emptyVecs := semicolons.map (fun _ => emptyVec)
    `(@Matrix.of (Fin $(quote semicolons.size)) (Fin 0) _ ![$emptyVecs,*])
  | `(!![$[,%$commas]*]) => `(@Matrix.of (Fin 0) (Fin $(quote commas.size)) _ ![])
goal: Lean.Macro

full_name: Matrix.delabMatrixNotation
code: /-- Delaborator for the `!![]` notation. -/
@[delab app.DFunLike.coe]
def delabMatrixNotation : Delab 
goal: Lean.PrettyPrinter.Delaborator.Delab

full_name: Matrix.repr
code: /-- Use `![...]` notation for displaying a `Fin`-indexed matrix, for example:

```
#eval !![1, 2; 3, 4] + !![3, 4; 5, 6]  -- !![4, 6; 8, 10]
```
-/
instance repr [Repr α] : Repr (Matrix (Fin m) (Fin n) α) 
goal: Repr (Matrix (Fin m) (Fin n) α)

full_name: Matrix.cons_val'
code: @[simp]
theorem cons_val' (v : n' → α) (B : Fin m → n' → α) (i j) :
    vecCons v B i j = vecCons (v j) (fun i => B i j) i 
goal: Matrix.vecCons v B i j = Matrix.vecCons (v j) (fun i => B i j) i

full_name: Matrix.head_val'
code: @[simp]
theorem head_val' (B : Fin m.succ → n' → α) (j : n') : (vecHead fun i => B i j) = vecHead B j 
goal: (Matrix.vecHead fun i => B i j) = Matrix.vecHead B j

full_name: Matrix.tail_val'
code: @[simp]
theorem tail_val' (B : Fin m.succ → n' → α) (j : n') :
    (vecTail fun i => B i j) = fun i => vecTail B i j 
goal: (Matrix.vecTail fun i => B i j) = fun i => Matrix.vecTail B i j

full_name: Matrix.dotProduct_empty
code: @[simp]
theorem dotProduct_empty (v w : Fin 0 → α) : dotProduct v w = 0 
goal: Matrix.dotProduct v w = 0

full_name: Matrix.cons_dotProduct
code: @[simp]
theorem cons_dotProduct (x : α) (v : Fin n → α) (w : Fin n.succ → α) :
    dotProduct (vecCons x v) w = x * vecHead w + dotProduct v (vecTail w) 
goal: Matrix.dotProduct (Matrix.vecCons x v) w = x * Matrix.vecHead w + Matrix.dotProduct v (Matrix.vecTail w)

full_name: Matrix.dotProduct_cons
code: @[simp]
theorem dotProduct_cons (v : Fin n.succ → α) (x : α) (w : Fin n → α) :
    dotProduct v (vecCons x w) = vecHead v * x + dotProduct (vecTail v) w 
goal: Matrix.dotProduct v (Matrix.vecCons x w) = Matrix.vecHead v * x + Matrix.dotProduct (Matrix.vecTail v) w

full_name: Matrix.cons_dotProduct_cons
code: theorem cons_dotProduct_cons (x : α) (v : Fin n → α) (y : α) (w : Fin n → α) :
    dotProduct (vecCons x v) (vecCons y w) = x * y + dotProduct v w 
goal: Matrix.dotProduct (Matrix.vecCons x v) (Matrix.vecCons y w) = x * y + Matrix.dotProduct v w

full_name: Matrix.col_empty
code: @[simp]
theorem col_empty (v : Fin 0 → α) : col ι v = vecEmpty 
goal: Matrix.col ι v = ![]

full_name: Matrix.col_cons
code: @[simp]
theorem col_cons (x : α) (u : Fin m → α) :
    col ι (vecCons x u) = of (vecCons (fun _ => x) (col ι u)) 
goal: Matrix.col ι (Matrix.vecCons x u) = Matrix.of (Matrix.vecCons (fun x_1 => x) (Matrix.col ι u))

full_name: Matrix.row_empty
code: @[simp]
theorem row_empty : row ι (vecEmpty : Fin 0 → α) = of fun _ => vecEmpty 
goal: Matrix.row ι ![] = Matrix.of fun x => ![]

full_name: Matrix.row_cons
code: @[simp]
theorem row_cons (x : α) (u : Fin m → α) : row ι (vecCons x u) = of fun _ => vecCons x u 
goal: Matrix.row ι (Matrix.vecCons x u) = Matrix.of fun x_1 => Matrix.vecCons x u

full_name: Matrix.transpose_empty_rows
code: @[simp]
theorem transpose_empty_rows (A : Matrix m' (Fin 0) α) : Aᵀ = of ![] 
goal: A.transpose = Matrix.of ![]

full_name: Matrix.transpose_empty_cols
code: @[simp]
theorem transpose_empty_cols (A : Matrix (Fin 0) m' α) : Aᵀ = of fun _ => ![] 
goal: A.transpose = Matrix.of fun x => ![]

full_name: Matrix.cons_transpose
code: @[simp]
theorem cons_transpose (v : n' → α) (A : Matrix (Fin m) n' α) :
    (of (vecCons v A))ᵀ = of fun i => vecCons (v i) (Aᵀ i) 
goal: (Matrix.of (Matrix.vecCons v A)).transpose = Matrix.of fun i => Matrix.vecCons (v i) (A.transpose i)

full_name: Matrix.head_transpose
code: @[simp]
theorem head_transpose (A : Matrix m' (Fin n.succ) α) :
    vecHead (of.symm Aᵀ) = vecHead ∘ of.symm A 
goal: Matrix.vecHead (Matrix.of.symm A.transpose) = Matrix.vecHead ∘ Matrix.of.symm A

full_name: Matrix.tail_transpose
code: @[simp]
theorem tail_transpose (A : Matrix m' (Fin n.succ) α) : vecTail (of.symm Aᵀ) = (vecTail ∘ A)ᵀ 
goal: Matrix.vecTail (Matrix.of.symm A.transpose) = Matrix.transpose (Matrix.vecTail ∘ A)

full_name: Matrix.empty_mul
code: @[simp]
theorem empty_mul [Fintype n'] (A : Matrix (Fin 0) n' α) (B : Matrix n' o' α) : A * B = of ![] 
goal: A * B = Matrix.of ![]

full_name: Matrix.empty_mul_empty
code: @[simp]
theorem empty_mul_empty (A : Matrix m' (Fin 0) α) (B : Matrix (Fin 0) o' α) : A * B = 0 
goal: A * B = 0

full_name: Matrix.mul_empty
code: @[simp]
theorem mul_empty [Fintype n'] (A : Matrix m' n' α) (B : Matrix n' (Fin 0) α) :
    A * B = of fun _ => ![] 
goal: A * B = Matrix.of fun x => ![]

full_name: Matrix.mul_val_succ
code: theorem mul_val_succ [Fintype n'] (A : Matrix (Fin m.succ) n' α) (B : Matrix n' o' α) (i : Fin m)
    (j : o') : (A * B) i.succ j = (of (vecTail (of.symm A)) * B) i j 
goal: (A * B) i.succ j = (Matrix.of (Matrix.vecTail (Matrix.of.symm A)) * B) i j

full_name: Matrix.cons_mul
code: @[simp]
theorem cons_mul [Fintype n'] (v : n' → α) (A : Fin m → n' → α) (B : Matrix n' o' α) :
    of (vecCons v A) * B = of (vecCons (v ᵥ* B) (of.symm (of A * B))) 
goal: Matrix.of (Matrix.vecCons v A) * B = Matrix.of (Matrix.vecCons (Matrix.vecMul v B) (Matrix.of.symm (Matrix.of A * B)))

full_name: Matrix.empty_vecMul
code: @[simp]
theorem empty_vecMul (v : Fin 0 → α) (B : Matrix (Fin 0) o' α) : v ᵥ* B = 0 
goal: Matrix.vecMul v B = 0

full_name: Matrix.vecMul_empty
code: @[simp]
theorem vecMul_empty [Fintype n'] (v : n' → α) (B : Matrix n' (Fin 0) α) : v ᵥ* B = ![] 
goal: Matrix.vecMul v B = ![]

full_name: Matrix.cons_vecMul
code: @[simp]
theorem cons_vecMul (x : α) (v : Fin n → α) (B : Fin n.succ → o' → α) :
    vecCons x v ᵥ* of B = x • vecHead B + v ᵥ* of (vecTail B) 
goal: Matrix.vecMul (Matrix.vecCons x v) (Matrix.of B) = x • Matrix.vecHead B + Matrix.vecMul v (Matrix.of (Matrix.vecTail B))

full_name: Matrix.vecMul_cons
code: @[simp]
theorem vecMul_cons (v : Fin n.succ → α) (w : o' → α) (B : Fin n → o' → α) :
    v ᵥ* of (vecCons w B) = vecHead v • w + vecTail v ᵥ* of B 
goal: Matrix.vecMul v (Matrix.of (Matrix.vecCons w B)) = Matrix.vecHead v • w + Matrix.vecMul (Matrix.vecTail v) (Matrix.of B)

full_name: Matrix.cons_vecMul_cons
code: theorem cons_vecMul_cons (x : α) (v : Fin n → α) (w : o' → α) (B : Fin n → o' → α) :
    vecCons x v ᵥ* of (vecCons w B) = x • w + v ᵥ* of B 
goal: Matrix.vecMul (Matrix.vecCons x v) (Matrix.of (Matrix.vecCons w B)) = x • w + Matrix.vecMul v (Matrix.of B)

full_name: Matrix.empty_mulVec
code: @[simp]
theorem empty_mulVec [Fintype n'] (A : Matrix (Fin 0) n' α) (v : n' → α) : A *ᵥ v = ![] 
goal: A.mulVec v = ![]

full_name: Matrix.mulVec_empty
code: @[simp]
theorem mulVec_empty (A : Matrix m' (Fin 0) α) (v : Fin 0 → α) : A *ᵥ v = 0 
goal: A.mulVec v = 0

full_name: Matrix.cons_mulVec
code: @[simp]
theorem cons_mulVec [Fintype n'] (v : n' → α) (A : Fin m → n' → α) (w : n' → α) :
    (of <| vecCons v A) *ᵥ w = vecCons (dotProduct v w) (of A *ᵥ w) 
goal: (Matrix.of (Matrix.vecCons v A)).mulVec w = Matrix.vecCons (Matrix.dotProduct v w) ((Matrix.of A).mulVec w)

full_name: Matrix.mulVec_cons
code: @[simp]
theorem mulVec_cons {α} [CommSemiring α] (A : m' → Fin n.succ → α) (x : α) (v : Fin n → α) :
    (of A) *ᵥ (vecCons x v) = x • vecHead ∘ A + (of (vecTail ∘ A)) *ᵥ v 
goal: (Matrix.of A).mulVec (Matrix.vecCons x v) = x • Matrix.vecHead ∘ A + (Matrix.of (Matrix.vecTail ∘ A)).mulVec v

full_name: Matrix.empty_vecMulVec
code: @[simp]
theorem empty_vecMulVec (v : Fin 0 → α) (w : n' → α) : vecMulVec v w = ![] 
goal: Matrix.vecMulVec v w = ![]

full_name: Matrix.vecMulVec_empty
code: @[simp]
theorem vecMulVec_empty (v : m' → α) (w : Fin 0 → α) : vecMulVec v w = of fun _ => ![] 
goal: Matrix.vecMulVec v w = Matrix.of fun x => ![]

full_name: Matrix.cons_vecMulVec
code: @[simp]
theorem cons_vecMulVec (x : α) (v : Fin m → α) (w : n' → α) :
    vecMulVec (vecCons x v) w = vecCons (x • w) (vecMulVec v w) 
goal: Matrix.vecMulVec (Matrix.vecCons x v) w = Matrix.vecCons (x • w) (Matrix.vecMulVec v w)

full_name: Matrix.vecMulVec_cons
code: @[simp]
theorem vecMulVec_cons (v : m' → α) (x : α) (w : Fin n → α) :
    vecMulVec v (vecCons x w) = of fun i => v i • vecCons x w 
goal: Matrix.vecMulVec v (Matrix.vecCons x w) = Matrix.of fun i => v i • Matrix.vecCons x w

full_name: Matrix.smul_mat_empty
code: theorem smul_mat_empty {m' : Type*} (x : α) (A : Fin 0 → m' → α) : x • A = ![] 
goal: x • A = ![]

full_name: Matrix.smul_mat_cons
code: theorem smul_mat_cons (x : α) (v : n' → α) (A : Fin m → n' → α) :
    x • vecCons v A = vecCons (x • v) (x • A) 
goal: x • Matrix.vecCons v A = Matrix.vecCons (x • v) (x • A)

full_name: Matrix.submatrix_empty
code: @[simp]
theorem submatrix_empty (A : Matrix m' n' α) (row : Fin 0 → m') (col : o' → n') :
    submatrix A row col = ![] 
goal: A.submatrix row col = ![]

full_name: Matrix.submatrix_cons_row
code: @[simp]
theorem submatrix_cons_row (A : Matrix m' n' α) (i : m') (row : Fin m → m') (col : o' → n') :
    submatrix A (vecCons i row) col = vecCons (fun j => A i (col j)) (submatrix A row col) 
goal: A.submatrix (Matrix.vecCons i row) col = Matrix.vecCons (fun j => A i (col j)) (A.submatrix row col)

full_name: Matrix.submatrix_updateRow_succAbove
code: /-- Updating a row then removing it is the same as removing it. -/
@[simp]
theorem submatrix_updateRow_succAbove (A : Matrix (Fin m.succ) n' α) (v : n' → α) (f : o' → n')
    (i : Fin m.succ) : (A.updateRow i v).submatrix i.succAbove f = A.submatrix i.succAbove f 
goal: (A.updateRow i v).submatrix i.succAbove f = A.submatrix i.succAbove f

full_name: Matrix.submatrix_updateColumn_succAbove
code: /-- Updating a column then removing it is the same as removing it. -/
@[simp]
theorem submatrix_updateColumn_succAbove (A : Matrix m' (Fin n.succ) α) (v : m' → α) (f : o' → m')
    (i : Fin n.succ) : (A.updateColumn i v).submatrix f i.succAbove = A.submatrix f i.succAbove 
goal: (A.updateColumn i v).submatrix f i.succAbove = A.submatrix f i.succAbove

full_name: Matrix.one_fin_two
code: theorem one_fin_two : (1 : Matrix (Fin 2) (Fin 2) α) = !![1, 0; 0, 1] 
goal: 1 = !![1, 0; 0, 1]

full_name: Matrix.one_fin_three
code: theorem one_fin_three : (1 : Matrix (Fin 3) (Fin 3) α) = !![1, 0, 0; 0, 1, 0; 0, 0, 1] 
goal: 1 = !![1, 0, 0; 0, 1, 0; 0, 0, 1]

full_name: Matrix.natCast_fin_two
code: theorem natCast_fin_two (n : ℕ) : (n : Matrix (Fin 2) (Fin 2) α) = !![↑n, 0; 0, ↑n] 
goal: ↑n = !![↑n, 0; 0, ↑n]

full_name: Matrix.natCast_fin_three
code: theorem natCast_fin_three (n : ℕ) :
    (n : Matrix (Fin 3) (Fin 3) α) = !![↑n, 0, 0; 0, ↑n, 0; 0, 0, ↑n] 
goal: ↑n = !![↑n, 0, 0; 0, ↑n, 0; 0, 0, ↑n]

full_name: Matrix.ofNat_fin_two
code: theorem ofNat_fin_two (n : ℕ) [n.AtLeastTwo] :
    (no_index (OfNat.ofNat n) : Matrix (Fin 2) (Fin 2) α) =
      !![OfNat.ofNat n, 0; 0, OfNat.ofNat n] 
goal: OfNat.ofNat n = !![OfNat.ofNat n, 0; 0, OfNat.ofNat n]

full_name: Matrix.ofNat_fin_three
code: theorem ofNat_fin_three (n : ℕ) [n.AtLeastTwo] :
    (no_index (OfNat.ofNat n) : Matrix (Fin 3) (Fin 3) α) =
      !![OfNat.ofNat n, 0, 0; 0, OfNat.ofNat n, 0; 0, 0, OfNat.ofNat n] 
goal: OfNat.ofNat n = !![OfNat.ofNat n, 0, 0; 0, OfNat.ofNat n, 0; 0, 0, OfNat.ofNat n]

full_name: Matrix.eta_fin_two
code: theorem eta_fin_two (A : Matrix (Fin 2) (Fin 2) α) : A = !![A 0 0, A 0 1; A 1 0, A 1 1] 
goal: A = !![A 0 0, A 0 1; A 1 0, A 1 1]

full_name: Matrix.eta_fin_three
code: theorem eta_fin_three (A : Matrix (Fin 3) (Fin 3) α) :
    A = !![A 0 0, A 0 1, A 0 2;
           A 1 0, A 1 1, A 1 2;
           A 2 0, A 2 1, A 2 2] 
goal: A = !![A 0 0, A 0 1, A 0 2; A 1 0, A 1 1, A 1 2; A 2 0, A 2 1, A 2 2]

full_name: Matrix.mul_fin_two
code: theorem mul_fin_two [AddCommMonoid α] [Mul α] (a₁₁ a₁₂ a₂₁ a₂₂ b₁₁ b₁₂ b₂₁ b₂₂ : α) :
    !![a₁₁, a₁₂;
       a₂₁, a₂₂] * !![b₁₁, b₁₂;
                      b₂₁, b₂₂] = !![a₁₁ * b₁₁ + a₁₂ * b₂₁, a₁₁ * b₁₂ + a₁₂ * b₂₂;
                                     a₂₁ * b₁₁ + a₂₂ * b₂₁, a₂₁ * b₁₂ + a₂₂ * b₂₂] 
goal: !![a₁₁, a₁₂; a₂₁, a₂₂] * !![b₁₁, b₁₂; b₂₁, b₂₂] =
  !![a₁₁ * b₁₁ + a₁₂ * b₂₁, a₁₁ * b₁₂ + a₁₂ * b₂₂; a₂₁ * b₁₁ + a₂₂ * b₂₁, a₂₁ * b₁₂ + a₂₂ * b₂₂]

full_name: Matrix.mul_fin_three
code: theorem mul_fin_three [AddCommMonoid α] [Mul α]
    (a₁₁ a₁₂ a₁₃ a₂₁ a₂₂ a₂₃ a₃₁ a₃₂ a₃₃ b₁₁ b₁₂ b₁₃ b₂₁ b₂₂ b₂₃ b₃₁ b₃₂ b₃₃ : α) :
    !![a₁₁, a₁₂, a₁₃;
       a₂₁, a₂₂, a₂₃;
       a₃₁, a₃₂, a₃₃] * !![b₁₁, b₁₂, b₁₃;
                           b₂₁, b₂₂, b₂₃;
                           b₃₁, b₃₂, b₃₃] =
    !![a₁₁*b₁₁ + a₁₂*b₂₁ + a₁₃*b₃₁, a₁₁*b₁₂ + a₁₂*b₂₂ + a₁₃*b₃₂, a₁₁*b₁₃ + a₁₂*b₂₃ + a₁₃*b₃₃;
       a₂₁*b₁₁ + a₂₂*b₂₁ + a₂₃*b₃₁, a₂₁*b₁₂ + a₂₂*b₂₂ + a₂₃*b₃₂, a₂₁*b₁₃ + a₂₂*b₂₃ + a₂₃*b₃₃;
       a₃₁*b₁₁ + a₃₂*b₂₁ + a₃₃*b₃₁, a₃₁*b₁₂ + a₃₂*b₂₂ + a₃₃*b₃₂, a₃₁*b₁₃ + a₃₂*b₂₃ + a₃₃*b₃₃] 
goal: !![a₁₁, a₁₂, a₁₃; a₂₁, a₂₂, a₂₃; a₃₁, a₃₂, a₃₃] * !![b₁₁, b₁₂, b₁₃; b₂₁, b₂₂, b₂₃; b₃₁, b₃₂, b₃₃] =
  !![a₁₁ * b₁₁ + a₁₂ * b₂₁ + a₁₃ * b₃₁, a₁₁ * b₁₂ + a₁₂ * b₂₂ + a₁₃ * b₃₂, a₁₁ * b₁₃ + a₁₂ * b₂₃ + a₁₃ * b₃₃;
    a₂₁ * b₁₁ + a₂₂ * b₂₁ + a₂₃ * b₃₁, a₂₁ * b₁₂ + a₂₂ * b₂₂ + a₂₃ * b₃₂, a₂₁ * b₁₃ + a₂₂ * b₂₃ + a₂₃ * b₃₃;
    a₃₁ * b₁₁ + a₃₂ * b₂₁ + a₃₃ * b₃₁, a₃₁ * b₁₂ + a₃₂ * b₂₂ + a₃₃ * b₃₂, a₃₁ * b₁₃ + a₃₂ * b₂₃ + a₃₃ * b₃₃]

full_name: Matrix.vec2_eq
code: theorem vec2_eq {a₀ a₁ b₀ b₁ : α} (h₀ : a₀ = b₀) (h₁ : a₁ = b₁) : ![a₀, a₁] = ![b₀, b₁] 
goal: ![a₀, a₁] = ![b₀, b₁]

full_name: Matrix.vec3_eq
code: theorem vec3_eq {a₀ a₁ a₂ b₀ b₁ b₂ : α} (h₀ : a₀ = b₀) (h₁ : a₁ = b₁) (h₂ : a₂ = b₂) :
    ![a₀, a₁, a₂] = ![b₀, b₁, b₂] 
goal: ![a₀, a₁, a₂] = ![b₀, b₁, b₂]

full_name: Matrix.vec2_add
code: theorem vec2_add [Add α] (a₀ a₁ b₀ b₁ : α) : ![a₀, a₁] + ![b₀, b₁] = ![a₀ + b₀, a₁ + b₁] 
goal: ![a₀, a₁] + ![b₀, b₁] = ![a₀ + b₀, a₁ + b₁]

full_name: Matrix.vec3_add
code: theorem vec3_add [Add α] (a₀ a₁ a₂ b₀ b₁ b₂ : α) :
    ![a₀, a₁, a₂] + ![b₀, b₁, b₂] = ![a₀ + b₀, a₁ + b₁, a₂ + b₂] 
goal: ![a₀, a₁, a₂] + ![b₀, b₁, b₂] = ![a₀ + b₀, a₁ + b₁, a₂ + b₂]

full_name: Matrix.smul_vec2
code: theorem smul_vec2 {R : Type*} [SMul R α] (x : R) (a₀ a₁ : α) :
    x • ![a₀, a₁] = ![x • a₀, x • a₁] 
goal: x • ![a₀, a₁] = ![x • a₀, x • a₁]

full_name: Matrix.smul_vec3
code: theorem smul_vec3 {R : Type*} [SMul R α] (x : R) (a₀ a₁ a₂ : α) :
    x • ![a₀, a₁, a₂] = ![x • a₀, x • a₁, x • a₂] 
goal: x • ![a₀, a₁, a₂] = ![x • a₀, x • a₁, x • a₂]

full_name: Matrix.vec2_dotProduct'
code: theorem vec2_dotProduct' {a₀ a₁ b₀ b₁ : α} : ![a₀, a₁] ⬝ᵥ ![b₀, b₁] = a₀ * b₀ + a₁ * b₁ 
goal: Matrix.dotProduct ![a₀, a₁] ![b₀, b₁] = a₀ * b₀ + a₁ * b₁

full_name: Matrix.vec2_dotProduct
code: @[simp]
theorem vec2_dotProduct (v w : Fin 2 → α) : v ⬝ᵥ w = v 0 * w 0 + v 1 * w 1 
goal: Matrix.dotProduct v w = v 0 * w 0 + v 1 * w 1

full_name: Matrix.vec3_dotProduct'
code: theorem vec3_dotProduct' {a₀ a₁ a₂ b₀ b₁ b₂ : α} :
    ![a₀, a₁, a₂] ⬝ᵥ ![b₀, b₁, b₂] = a₀ * b₀ + a₁ * b₁ + a₂ * b₂ 
goal: Matrix.dotProduct ![a₀, a₁, a₂] ![b₀, b₁, b₂] = a₀ * b₀ + a₁ * b₁ + a₂ * b₂

full_name: Matrix.vec3_dotProduct
code: @[simp]
theorem vec3_dotProduct (v w : Fin 3 → α) : v ⬝ᵥ w = v 0 * w 0 + v 1 * w 1 + v 2 * w 2 
goal: Matrix.dotProduct v w = v 0 * w 0 + v 1 * w 1 + v 2 * w 2