docs: def eigen(matrix):
      """ Calculates the eigenvalues and eigenvectors of the input matrix.
      Returns a tuple of (eigenvalues, eigenvectors, cumulative percentage of
      variance explained). Eigenvalues and eigenvectors are sorted in order of
      eigenvalue magnitude, high to low """
  
      (vals, vecs) = np.linalg.eigh(matrix)
      ind = vals.argsort()[::-1]
      vals = vals[ind]
      vecs = vecs[:, ind]
      vals_ = vals.copy()
      vals_[vals_ < 0] = 0.
      cum_var_exp = np.cumsum(vals_ / vals_.sum())
      return Decomp(matrix.copy(), vals, vecs, cum_var_exp)