File: Mathlib/LinearAlgebra/Matrix/SchurComplement.lean

full_name: Matrix.fromBlocks_eq_of_invertible₁₁
code: /-- LDU decomposition of a block matrix with an invertible top-left corner, using the
Schur complement. -/
theorem fromBlocks_eq_of_invertible₁₁ (A : Matrix m m α) (B : Matrix m n α) (C : Matrix l m α)
    (D : Matrix l n α) [Invertible A] :
    fromBlocks A B C D =
      fromBlocks 1 0 (C * ⅟ A) 1 * fromBlocks A 0 0 (D - C * ⅟ A * B) *
        fromBlocks 1 (⅟ A * B) 0 1 
goal: Matrix.fromBlocks A B C D =
  Matrix.fromBlocks 1 0 (C * ⅟A) 1 * Matrix.fromBlocks A 0 0 (D - C * ⅟A * B) * Matrix.fromBlocks 1 (⅟A * B) 0 1

full_name: Matrix.fromBlocks_eq_of_invertible₂₂
code: /-- LDU decomposition of a block matrix with an invertible bottom-right corner, using the
Schur complement. -/
theorem fromBlocks_eq_of_invertible₂₂ (A : Matrix l m α) (B : Matrix l n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible D] :
    fromBlocks A B C D =
      fromBlocks 1 (B * ⅟ D) 0 1 * fromBlocks (A - B * ⅟ D * C) 0 0 D *
        fromBlocks 1 0 (⅟ D * C) 1 
goal: Matrix.fromBlocks A B C D =
  Matrix.fromBlocks 1 (B * ⅟D) 0 1 * Matrix.fromBlocks (A - B * ⅟D * C) 0 0 D * Matrix.fromBlocks 1 0 (⅟D * C) 1

full_name: Matrix.fromBlocksZero₂₁Invertible
code: /-- An upper-block-triangular matrix is invertible if its diagonal is. -/
def fromBlocksZero₂₁Invertible (A : Matrix m m α) (B : Matrix m n α) (D : Matrix n n α)
    [Invertible A] [Invertible D] : Invertible (fromBlocks A B 0 D) 
goal: Invertible (Matrix.fromBlocks A B 0 D)

full_name: Matrix.fromBlocksZero₁₂Invertible
code: /-- A lower-block-triangular matrix is invertible if its diagonal is. -/
def fromBlocksZero₁₂Invertible (A : Matrix m m α) (C : Matrix n m α) (D : Matrix n n α)
    [Invertible A] [Invertible D] : Invertible (fromBlocks A 0 C D) 
goal: Invertible (Matrix.fromBlocks A 0 C D)

full_name: Matrix.invOf_fromBlocks_zero₂₁_eq
code: theorem invOf_fromBlocks_zero₂₁_eq (A : Matrix m m α) (B : Matrix m n α) (D : Matrix n n α)
    [Invertible A] [Invertible D] [Invertible (fromBlocks A B 0 D)] :
    ⅟ (fromBlocks A B 0 D) = fromBlocks (⅟ A) (-(⅟ A * B * ⅟ D)) 0 (⅟ D) 
goal: ⅟(Matrix.fromBlocks A B 0 D) = Matrix.fromBlocks (⅟A) (-(⅟A * B * ⅟D)) 0 ⅟D

full_name: Matrix.invOf_fromBlocks_zero₁₂_eq
code: theorem invOf_fromBlocks_zero₁₂_eq (A : Matrix m m α) (C : Matrix n m α) (D : Matrix n n α)
    [Invertible A] [Invertible D] [Invertible (fromBlocks A 0 C D)] :
    ⅟ (fromBlocks A 0 C D) = fromBlocks (⅟ A) 0 (-(⅟ D * C * ⅟ A)) (⅟ D) 
goal: ⅟(Matrix.fromBlocks A 0 C D) = Matrix.fromBlocks (⅟A) 0 (-(⅟D * C * ⅟A)) ⅟D

full_name: Matrix.invertibleOfFromBlocksZero₂₁Invertible
code: /-- Both diagonal entries of an invertible upper-block-triangular matrix are invertible (by reading
off the diagonal entries of the inverse). -/
def invertibleOfFromBlocksZero₂₁Invertible (A : Matrix m m α) (B : Matrix m n α) (D : Matrix n n α)
    [Invertible (fromBlocks A B 0 D)] : Invertible A × Invertible D 
goal: Invertible A × Invertible D

full_name: Matrix.invertibleOfFromBlocksZero₁₂Invertible
code: /-- Both diagonal entries of an invertible lower-block-triangular matrix are invertible (by reading
off the diagonal entries of the inverse). -/
def invertibleOfFromBlocksZero₁₂Invertible (A : Matrix m m α) (C : Matrix n m α) (D : Matrix n n α)
    [Invertible (fromBlocks A 0 C D)] : Invertible A × Invertible D 
goal: Invertible A × Invertible D

full_name: Matrix.fromBlocksZero₂₁InvertibleEquiv
code: /-- `invertibleOfFromBlocksZero₂₁Invertible` and `Matrix.fromBlocksZero₂₁Invertible` form
an equivalence. -/
def fromBlocksZero₂₁InvertibleEquiv (A : Matrix m m α) (B : Matrix m n α) (D : Matrix n n α) :
    Invertible (fromBlocks A B 0 D) ≃ Invertible A × Invertible D 
goal: Invertible (Matrix.fromBlocks A B 0 D) ≃ Invertible A × Invertible D

full_name: Matrix.fromBlocksZero₁₂InvertibleEquiv
code: /-- `invertibleOfFromBlocksZero₁₂Invertible` and `Matrix.fromBlocksZero₁₂Invertible` form
an equivalence. -/
def fromBlocksZero₁₂InvertibleEquiv (A : Matrix m m α) (C : Matrix n m α) (D : Matrix n n α) :
    Invertible (fromBlocks A 0 C D) ≃ Invertible A × Invertible D 
goal: Invertible (Matrix.fromBlocks A 0 C D) ≃ Invertible A × Invertible D

full_name: Matrix.isUnit_fromBlocks_zero₂₁
code: /-- An upper block-triangular matrix is invertible iff both elements of its diagonal are.

This is a propositional form of `Matrix.fromBlocksZero₂₁InvertibleEquiv`. -/
@[simp]
theorem isUnit_fromBlocks_zero₂₁ {A : Matrix m m α} {B : Matrix m n α} {D : Matrix n n α} :
    IsUnit (fromBlocks A B 0 D) ↔ IsUnit A ∧ IsUnit D 
goal: IsUnit (Matrix.fromBlocks A B 0 D) ↔ IsUnit A ∧ IsUnit D

full_name: Matrix.isUnit_fromBlocks_zero₁₂
code: /-- A lower block-triangular matrix is invertible iff both elements of its diagonal are.

This is a propositional form of `Matrix.fromBlocksZero₁₂InvertibleEquiv` forms an `iff`. -/
@[simp]
theorem isUnit_fromBlocks_zero₁₂ {A : Matrix m m α} {C : Matrix n m α} {D : Matrix n n α} :
    IsUnit (fromBlocks A 0 C D) ↔ IsUnit A ∧ IsUnit D 
goal: IsUnit (Matrix.fromBlocks A 0 C D) ↔ IsUnit A ∧ IsUnit D

full_name: Matrix.inv_fromBlocks_zero₂₁_of_isUnit_iff
code: /-- An expression for the inverse of an upper block-triangular matrix, when either both elements of
diagonal are invertible, or both are not. -/
theorem inv_fromBlocks_zero₂₁_of_isUnit_iff (A : Matrix m m α) (B : Matrix m n α) (D : Matrix n n α)
    (hAD : IsUnit A ↔ IsUnit D) :
    (fromBlocks A B 0 D)⁻¹ = fromBlocks A⁻¹ (-(A⁻¹ * B * D⁻¹)) 0 D⁻¹ 
goal: (Matrix.fromBlocks A B 0 D)⁻¹ = Matrix.fromBlocks A⁻¹ (-(A⁻¹ * B * D⁻¹)) 0 D⁻¹

full_name: Matrix.inv_fromBlocks_zero₁₂_of_isUnit_iff
code: /-- An expression for the inverse of a lower block-triangular matrix, when either both elements of
diagonal are invertible, or both are not. -/
theorem inv_fromBlocks_zero₁₂_of_isUnit_iff (A : Matrix m m α) (C : Matrix n m α) (D : Matrix n n α)
    (hAD : IsUnit A ↔ IsUnit D) :
    (fromBlocks A 0 C D)⁻¹ = fromBlocks A⁻¹ 0 (-(D⁻¹ * C * A⁻¹)) D⁻¹ 
goal: (Matrix.fromBlocks A 0 C D)⁻¹ = Matrix.fromBlocks A⁻¹ 0 (-(D⁻¹ * C * A⁻¹)) D⁻¹

full_name: Matrix.fromBlocks₂₂Invertible
code: /-- A block matrix is invertible if the bottom right corner and the corresponding schur complement
is. -/
def fromBlocks₂₂Invertible (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible D] [Invertible (A - B * ⅟ D * C)] :
    Invertible (fromBlocks A B C D) 
goal: Invertible (Matrix.fromBlocks A B C D)

full_name: Matrix.fromBlocks₁₁Invertible
code: /-- A block matrix is invertible if the top left corner and the corresponding schur complement
is. -/
def fromBlocks₁₁Invertible (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible A] [Invertible (D - C * ⅟ A * B)] :
    Invertible (fromBlocks A B C D) 
goal: Invertible (Matrix.fromBlocks A B C D)

full_name: Matrix.invOf_fromBlocks₂₂_eq
code: theorem invOf_fromBlocks₂₂_eq (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible D] [Invertible (A - B * ⅟ D * C)]
    [Invertible (fromBlocks A B C D)] :
    ⅟ (fromBlocks A B C D) =
      fromBlocks (⅟ (A - B * ⅟ D * C)) (-(⅟ (A - B * ⅟ D * C) * B * ⅟ D))
        (-(⅟ D * C * ⅟ (A - B * ⅟ D * C))) (⅟ D + ⅟ D * C * ⅟ (A - B * ⅟ D * C) * B * ⅟ D) 
goal: ⅟(Matrix.fromBlocks A B C D) =
  Matrix.fromBlocks (⅟(A - B * ⅟D * C)) (-(⅟(A - B * ⅟D * C) * B * ⅟D)) (-(⅟D * C * ⅟(A - B * ⅟D * C)))
    (⅟D + ⅟D * C * ⅟(A - B * ⅟D * C) * B * ⅟D)

full_name: Matrix.invOf_fromBlocks₁₁_eq
code: theorem invOf_fromBlocks₁₁_eq (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible A] [Invertible (D - C * ⅟ A * B)]
    [Invertible (fromBlocks A B C D)] :
    ⅟ (fromBlocks A B C D) =
      fromBlocks (⅟ A + ⅟ A * B * ⅟ (D - C * ⅟ A * B) * C * ⅟ A) (-(⅟ A * B * ⅟ (D - C * ⅟ A * B)))
        (-(⅟ (D - C * ⅟ A * B) * C * ⅟ A)) (⅟ (D - C * ⅟ A * B)) 
goal: ⅟(Matrix.fromBlocks A B C D) =
  Matrix.fromBlocks (⅟A + ⅟A * B * ⅟(D - C * ⅟A * B) * C * ⅟A) (-(⅟A * B * ⅟(D - C * ⅟A * B)))
    (-(⅟(D - C * ⅟A * B) * C * ⅟A)) ⅟(D - C * ⅟A * B)

full_name: Matrix.invertibleOfFromBlocks₂₂Invertible
code: /-- If a block matrix is invertible and so is its bottom left element, then so is the corresponding
Schur complement. -/
def invertibleOfFromBlocks₂₂Invertible (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible D] [Invertible (fromBlocks A B C D)] :
    Invertible (A - B * ⅟ D * C) 
goal: Invertible (A - B * ⅟D * C)

full_name: Matrix.invertibleOfFromBlocks₁₁Invertible
code: /-- If a block matrix is invertible and so is its bottom left element, then so is the corresponding
Schur complement. -/
def invertibleOfFromBlocks₁₁Invertible (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible A] [Invertible (fromBlocks A B C D)] :
    Invertible (D - C * ⅟ A * B) 
goal: Invertible (D - C * ⅟A * B)

full_name: Matrix.invertibleEquivFromBlocks₂₂Invertible
code: /-- `Matrix.invertibleOfFromBlocks₂₂Invertible` and `Matrix.fromBlocks₂₂Invertible` as an
equivalence. -/
def invertibleEquivFromBlocks₂₂Invertible (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible D] :
    Invertible (fromBlocks A B C D) ≃ Invertible (A - B * ⅟ D * C) 
goal: Invertible (Matrix.fromBlocks A B C D) ≃ Invertible (A - B * ⅟D * C)

full_name: Matrix.invertibleEquivFromBlocks₁₁Invertible
code: /-- `Matrix.invertibleOfFromBlocks₁₁Invertible` and `Matrix.fromBlocks₁₁Invertible` as an
equivalence. -/
def invertibleEquivFromBlocks₁₁Invertible (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible A] :
    Invertible (fromBlocks A B C D) ≃ Invertible (D - C * ⅟ A * B) 
goal: Invertible (Matrix.fromBlocks A B C D) ≃ Invertible (D - C * ⅟A * B)

full_name: Matrix.isUnit_fromBlocks_iff_of_invertible₂₂
code: /-- If the bottom-left element of a block matrix is invertible, then the whole matrix is invertible
iff the corresponding schur complement is. -/
theorem isUnit_fromBlocks_iff_of_invertible₂₂ {A : Matrix m m α} {B : Matrix m n α}
    {C : Matrix n m α} {D : Matrix n n α} [Invertible D] :
    IsUnit (fromBlocks A B C D) ↔ IsUnit (A - B * ⅟ D * C) 
goal: IsUnit (Matrix.fromBlocks A B C D) ↔ IsUnit (A - B * ⅟D * C)

full_name: Matrix.isUnit_fromBlocks_iff_of_invertible₁₁
code: /-- If the top-right element of a block matrix is invertible, then the whole matrix is invertible
iff the corresponding schur complement is. -/
theorem isUnit_fromBlocks_iff_of_invertible₁₁ {A : Matrix m m α} {B : Matrix m n α}
    {C : Matrix n m α} {D : Matrix n n α} [Invertible A] :
    IsUnit (fromBlocks A B C D) ↔ IsUnit (D - C * ⅟ A * B) 
goal: IsUnit (Matrix.fromBlocks A B C D) ↔ IsUnit (D - C * ⅟A * B)

full_name: Matrix.det_fromBlocks₁₁
code: /-- Determinant of a 2×2 block matrix, expanded around an invertible top left element in terms of
the Schur complement. -/
theorem det_fromBlocks₁₁ (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible A] :
    (Matrix.fromBlocks A B C D).det = det A * det (D - C * ⅟ A * B) 
goal: (Matrix.fromBlocks A B C D).det = A.det * (D - C * ⅟A * B).det

full_name: Matrix.det_fromBlocks_one₁₁
code: @[simp]
theorem det_fromBlocks_one₁₁ (B : Matrix m n α) (C : Matrix n m α) (D : Matrix n n α) :
    (Matrix.fromBlocks 1 B C D).det = det (D - C * B) 
goal: (Matrix.fromBlocks 1 B C D).det = (D - C * B).det

full_name: Matrix.det_fromBlocks₂₂
code: /-- Determinant of a 2×2 block matrix, expanded around an invertible bottom right element in terms
of the Schur complement. -/
theorem det_fromBlocks₂₂ (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α)
    (D : Matrix n n α) [Invertible D] :
    (Matrix.fromBlocks A B C D).det = det D * det (A - B * ⅟ D * C) 
goal: (Matrix.fromBlocks A B C D).det = D.det * (A - B * ⅟D * C).det

full_name: Matrix.det_fromBlocks_one₂₂
code: @[simp]
theorem det_fromBlocks_one₂₂ (A : Matrix m m α) (B : Matrix m n α) (C : Matrix n m α) :
    (Matrix.fromBlocks A B C 1).det = det (A - B * C) 
goal: (Matrix.fromBlocks A B C 1).det = (A - B * C).det

full_name: Matrix.det_one_add_mul_comm
code: /-- The **Weinstein–Aronszajn identity**. Note the `1` on the LHS is of shape m×m, while the `1` on
the RHS is of shape n×n. -/
theorem det_one_add_mul_comm (A : Matrix m n α) (B : Matrix n m α) :
    det (1 + A * B) = det (1 + B * A) 
goal: (1 + A * B).det = (1 + B * A).det

full_name: Matrix.det_mul_add_one_comm
code: /-- Alternate statement of the **Weinstein–Aronszajn identity** -/
theorem det_mul_add_one_comm (A : Matrix m n α) (B : Matrix n m α) :
    det (A * B + 1) = det (B * A + 1) 
goal: (A * B + 1).det = (B * A + 1).det

full_name: Matrix.det_one_sub_mul_comm
code: theorem det_one_sub_mul_comm (A : Matrix m n α) (B : Matrix n m α) :
    det (1 - A * B) = det (1 - B * A) 
goal: (1 - A * B).det = (1 - B * A).det

full_name: Matrix.det_one_add_col_mul_row
code: /-- A special case of the **Matrix determinant lemma** for when `A = I`. -/
theorem det_one_add_col_mul_row {ι : Type*} [Unique ι] (u v : m → α) :
    det (1 + col ι u * row ι v) = 1 + v ⬝ᵥ u 
goal: (1 + Matrix.col ι u * Matrix.row ι v).det = 1 + Matrix.dotProduct v u

full_name: Matrix.det_add_col_mul_row
code: /-- The **Matrix determinant lemma**

TODO: show the more general version without `hA : IsUnit A.det` as
`(A + col u * row v).det = A.det + v ⬝ᵥ (adjugate A) *ᵥ u`.
-/
theorem det_add_col_mul_row {ι : Type*} [Unique ι]
    {A : Matrix m m α} (hA : IsUnit A.det) (u v : m → α) :
    (A + col ι u * row ι v).det = A.det * (1 + row ι v * A⁻¹ * col ι u).det 
goal: (A + Matrix.col ι u * Matrix.row ι v).det = A.det * (1 + Matrix.row ι v * A⁻¹ * Matrix.col ι u).det

full_name: Matrix.det_add_mul
code: /-- A generalization of the **Matrix determinant lemma** -/
theorem det_add_mul {A : Matrix m m α} (U : Matrix m n α)
    (V : Matrix n m α) (hA : IsUnit A.det) :
    (A + U * V).det = A.det * (1 + V * A⁻¹ * U).det 
goal: (A + U * V).det = A.det * (1 + V * A⁻¹ * U).det

full_name: Matrix.«_aux_Mathlib_LinearAlgebra_Matrix_SchurComplement___macroRules_Matrix_term_⊕ᵥ__1»
code: scoped infixl:65 " ⊕ᵥ " => Sum.elim
goal: Lean.Macro

full_name: Matrix._aux_Mathlib_LinearAlgebra_Matrix_SchurComplement___unexpand_Sum_elim_1
code: scoped infixl:65 " ⊕ᵥ " => Sum.elim
goal: Lean.PrettyPrinter.Unexpander

full_name: Matrix.schur_complement_eq₁₁
code: theorem schur_complement_eq₁₁ [Fintype m] [DecidableEq m] [Fintype n] {A : Matrix m m 𝕜}
    (B : Matrix m n 𝕜) (D : Matrix n n 𝕜) (x : m → 𝕜) (y : n → 𝕜) [Invertible A]
    (hA : A.IsHermitian) :
    (star (x ⊕ᵥ y)) ᵥ* (fromBlocks A B Bᴴ D) ⬝ᵥ (x ⊕ᵥ y) =
      (star (x + (A⁻¹ * B) *ᵥ y)) ᵥ* A ⬝ᵥ (x + (A⁻¹ * B) *ᵥ y) +
        (star y) ᵥ* (D - Bᴴ * A⁻¹ * B) ⬝ᵥ y 
goal: Matrix.dotProduct (Matrix.vecMul (star (Sum.elim x y)) (Matrix.fromBlocks A B B.conjTranspose D)) (Sum.elim x y) =
  Matrix.dotProduct (Matrix.vecMul (star (x + (A⁻¹ * B).mulVec y)) A) (x + (A⁻¹ * B).mulVec y) +
    Matrix.dotProduct (Matrix.vecMul (star y) (D - B.conjTranspose * A⁻¹ * B)) y

full_name: Matrix.schur_complement_eq₂₂
code: theorem schur_complement_eq₂₂ [Fintype m] [Fintype n] [DecidableEq n] (A : Matrix m m 𝕜)
    (B : Matrix m n 𝕜) {D : Matrix n n 𝕜} (x : m → 𝕜) (y : n → 𝕜) [Invertible D]
    (hD : D.IsHermitian) :
    (star (x ⊕ᵥ y)) ᵥ* (fromBlocks A B Bᴴ D) ⬝ᵥ (x ⊕ᵥ y) =
      (star ((D⁻¹ * Bᴴ) *ᵥ x + y)) ᵥ* D ⬝ᵥ ((D⁻¹ * Bᴴ) *ᵥ x + y) +
        (star x) ᵥ* (A - B * D⁻¹ * Bᴴ) ⬝ᵥ x 
goal: Matrix.dotProduct (Matrix.vecMul (star (Sum.elim x y)) (Matrix.fromBlocks A B B.conjTranspose D)) (Sum.elim x y) =
  Matrix.dotProduct (Matrix.vecMul (star ((D⁻¹ * B.conjTranspose).mulVec x + y)) D)
      ((D⁻¹ * B.conjTranspose).mulVec x + y) +
    Matrix.dotProduct (Matrix.vecMul (star x) (A - B * D⁻¹ * B.conjTranspose)) x

full_name: Matrix.IsHermitian.fromBlocks₁₁
code: theorem IsHermitian.fromBlocks₁₁ [Fintype m] [DecidableEq m] {A : Matrix m m 𝕜} (B : Matrix m n 𝕜)
    (D : Matrix n n 𝕜) (hA : A.IsHermitian) :
    (Matrix.fromBlocks A B Bᴴ D).IsHermitian ↔ (D - Bᴴ * A⁻¹ * B).IsHermitian 
goal: (Matrix.fromBlocks A B B.conjTranspose D).IsHermitian ↔ (D - B.conjTranspose * A⁻¹ * B).IsHermitian

full_name: Matrix.IsHermitian.fromBlocks₂₂
code: theorem IsHermitian.fromBlocks₂₂ [Fintype n] [DecidableEq n] (A : Matrix m m 𝕜) (B : Matrix m n 𝕜)
    {D : Matrix n n 𝕜} (hD : D.IsHermitian) :
    (Matrix.fromBlocks A B Bᴴ D).IsHermitian ↔ (A - B * D⁻¹ * Bᴴ).IsHermitian 
goal: (Matrix.fromBlocks A B B.conjTranspose D).IsHermitian ↔ (A - B * D⁻¹ * B.conjTranspose).IsHermitian

full_name: Matrix.PosSemidef.fromBlocks₁₁
code: theorem PosSemidef.fromBlocks₁₁ [Fintype m] [DecidableEq m] [Fintype n] {A : Matrix m m 𝕜}
    (B : Matrix m n 𝕜) (D : Matrix n n 𝕜) (hA : A.PosDef) [Invertible A] :
    (fromBlocks A B Bᴴ D).PosSemidef ↔ (D - Bᴴ * A⁻¹ * B).PosSemidef 
goal: (Matrix.fromBlocks A B B.conjTranspose D).PosSemidef ↔ (D - B.conjTranspose * A⁻¹ * B).PosSemidef

full_name: Matrix.PosSemidef.fromBlocks₂₂
code: theorem PosSemidef.fromBlocks₂₂ [Fintype m] [Fintype n] [DecidableEq n] (A : Matrix m m 𝕜)
    (B : Matrix m n 𝕜) {D : Matrix n n 𝕜} (hD : D.PosDef) [Invertible D] :
    (fromBlocks A B Bᴴ D).PosSemidef ↔ (A - B * D⁻¹ * Bᴴ).PosSemidef 
goal: (Matrix.fromBlocks A B B.conjTranspose D).PosSemidef ↔ (A - B * D⁻¹ * B.conjTranspose).PosSemidef