!Uses lapack library to perform the inversion of the matrix
subroutine invert_matrix(dimension, inv_matrix, matrix)

   implicit none

   integer, intent(in) :: dimension
   real(wp), intent(inout) :: inv_matrix(:,:)
   real(wp), intent(in), optional :: matrix(:,:)

   integer :: info, ipiv(dimension) ! pivot indices
   real(wp) :: work(dimension) ! work array for LAPACK

   ! Store matrix in inv_matrix to prevent it from being overwritten by LAPACK
   if (present(matrix)) then
      inv_matrix = matrix
   end if


   ! DGETRF computes an LU factorization of a general M-by-N matrix A
   ! using partial pivoting with row interchanges.
   call DGETRF(dimension, dimension, inv_matrix, dimension, ipiv, info)

   if (info.ne.0) stop 'Matrix is numerically singular!'

   ! DGETRI computes the inverse of a matrix using the LU factorization
   ! computed by DGETRF.
   call DGETRI(dimension, inv_matrix, dimension, ipiv, work, dimension, info)

   if (info.ne.0) stop 'Matrix inversion failed!'


   return
end subroutine invert_matrix

!Uses lapack library to perform the inversion of the matrix
!It only works for positive definite matrixes
subroutine invert_matrix_fast(dimension, inv_matrix, matrix)

   implicit none

   integer, intent(in) :: dimension
   real(wp), intent(inout) :: inv_matrix(:,:)
   real(wp), intent(in), optional :: matrix(:,:)

   integer :: info ! pivot indices

   ! Store matrix in inv_matrix to prevent it from being overwritten by LAPACK
   if (present(matrix)) then
      inv_matrix = matrix
   end if

   !DPOTRF forms the Cholesky factorization of a symmetric
   !positive-definite matrix (!)
   call DPOTRF('U', dimension, inv_matrix, dimension, info)

   if (info.ne.0) stop 'Matrix is numerically singular!'

   !DPOTRI computes the inverse of a symmetric positive definite matrix
   !using the Cholesky factorization computed by DPOTRF
   call DPOTRI('U', dimension, inv_matrix, dimension, info)

   if (info.ne.0) stop 'Matrix inversion failed!'

   return
end subroutine invert_matrix_fast
