def _LDLdecomposition(self, hermitian=True): """Helper function of LDLdecomposition. Without the error checks. To be used privately. Returns L and D such that L*D*L.H == self if hermitian flag is True, or L*D*L.T == self if hermitian is False. """ # https://en.wikipedia.org/wiki/Cholesky_decomposition#LDL_decomposition_2 D = zeros(self.rows, self.rows) L = eye(self.rows) if hermitian: for i in range(self.rows): for j in range(i): L[i, j] = (1 / D[j, j]) * expand_mul(self[i, j] - sum( L[i, k] * L[j, k].conjugate() * D[k, k] for k in range(j))) D[i, i] = expand_mul(self[i, i] - sum(L[i, k] * L[i, k].conjugate() * D[k, k] for k in range(i))) if D[i, i].is_positive is False: raise NonPositiveDefiniteMatrixError( "Matrix must be positive-definite") else: for i in range(self.rows): for j in range(i): L[i, j] = (1 / D[j, j]) * (self[i, j] - sum(L[i, k] * L[j, k] * D[k, k] for k in range(j))) D[i, i] = self[i, i] - sum(L[i, k]**2 * D[k, k] for k in range(i)) return self._new(L), self._new(D)
def _cholesky(self, hermitian=True): """Helper function of cholesky. Without the error checks. To be used privately. Implements the Cholesky-Banachiewicz algorithm. Returns L such that L*L.H == self if hermitian flag is True, or L*L.T == self if hermitian is False. """ L = zeros(self.rows, self.rows) if hermitian: for i in range(self.rows): for j in range(i): L[i, j] = (1 / L[j, j]) * expand_mul(self[i, j] - sum( L[i, k] * L[j, k].conjugate() for k in range(j))) Lii2 = expand_mul(self[i, i] - sum(L[i, k] * L[i, k].conjugate() for k in range(i))) if Lii2.is_positive is False: raise NonPositiveDefiniteMatrixError( "Matrix must be positive-definite") L[i, i] = sqrt(Lii2) else: for i in range(self.rows): for j in range(i): L[i, j] = (1 / L[j, j]) * (self[i, j] - sum(L[i, k] * L[j, k] for k in range(j))) L[i, i] = sqrt(self[i, i] - sum(L[i, k]**2 for k in range(i))) return self._new(L)