-- CvxLean/Lib/Math/LinearAlgebra/Matrix/PosDef.lean

import Mathlib.LinearAlgebra.Matrix.PosDef

import Mathlib.Algebra.Star.Pi

namespace Matrix

variable {m n : Type _} [Fintype m] [Fintype n]

variable {𝕜 : Type _}

variable [NormedField 𝕜] [PartialOrder 𝕜] [StarRing 𝕜] [StarOrderedRing 𝕜]

variable [RCLike 𝕜]

noncomputable instance PosDef.Invertible [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.PosDef) :
    Invertible M :=
  invertibleOfIsUnitDet M (isUnit_iff_ne_zero.2 hM.det_ne_zero)

-- Repository definitions used:
content: ...

-- Repository lemmas used:
content: theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

-- Local definitions used:
content: noncomputable instance PosDef.Invertible [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.PosDef) :
    Invertible M :=
  invertibleOfIsUnitDet M (isUnit_iff_ne_zero.2 hM.det_ne_zero)

-- Local lemmas used:
content: lemma PosDef.det_ne_zero [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.PosDef) : M.det ≠ 0

content: lemma IsHermitian.nonsingular_inv [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.IsHermitian)
    (hMdet : IsUnit M.det) : M⁻¹.IsHermitian

content: lemma conj_symm {x : n → 𝕜} {M : Matrix n n 𝕜} (hM : M.IsHermitian) :
    star (star x ⬝ᵥ mulVec M x) = star x ⬝ᵥ mulVec M x

-- Target theorem and proof:
lemma PosDef.nonsingular_inv [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.PosDef) : M⁻¹.PosDef
:= by
  refine' ⟨hM.1.nonsingular_inv (isUnit_iff_ne_zero.2 hM.det_ne_zero), _⟩
  intros x hx
  have hMMinv := mul_nonsing_inv _ (isUnit_iff_ne_zero.2 hM.det_ne_zero)
  have hMinvdet : M⁻¹.det ≠ 0 := det_ne_zero_of_left_inverse hMMinv
  have hres :=
    hM.2 (M⁻¹.mulVec x) (fun h => hx (eq_zero_of_mulVec_eq_zero hMinvdet h))
  rw [mulVec_mulVec, hMMinv, one_mulVec, star_dotProduct] at hres
  rw [conj_symm ((@isHermitian_inv _ _ _ _ _ _ M hM.Invertible).2 hM.1)] at hres
  exact hres