// Cholesky calculates the Cholesky decomposition of the matrix A and returns // whether the matrix is positive definite. The returned matrix is either a // lower triangular matrix such that A = L * L^T or an upper triangular matrix // such that A = U^T * U depending on the upper parameter. func (t *TriDense) Cholesky(a Symmetric, upper bool) (ok bool) { n := a.Symmetric() if t.isZero() { t.mat = blas64.Triangular{ N: n, Stride: n, Diag: blas.NonUnit, Data: use(t.mat.Data, n*n), } if upper { t.mat.Uplo = blas.Upper } else { t.mat.Uplo = blas.Lower } } else { if n != t.mat.N { panic(ErrShape) } if (upper && t.mat.Uplo != blas.Upper) || (!upper && t.mat.Uplo != blas.Lower) { panic(ErrTriangle) } } copySymIntoTriangle(t, a) // Potrf modifies the data in place _, ok = lapack64.Potrf( blas64.Symmetric{ N: t.mat.N, Stride: t.mat.Stride, Data: t.mat.Data, Uplo: t.mat.Uplo, }) return ok }
// Factorize calculates the Cholesky decomposition of the matrix A and returns // whether the matrix is positive definite. func (c *Cholesky) Factorize(a Symmetric) (ok bool) { n := a.Symmetric() if c.chol == nil { c.chol = NewTriDense(n, true, nil) } else { c.chol = NewTriDense(n, true, use(c.chol.mat.Data, n*n)) } copySymIntoTriangle(c.chol, a) sym := c.chol.asSymBlas() work := make([]float64, c.chol.mat.N) norm := lapack64.Lansy(matrix.CondNorm, sym, work) _, ok = lapack64.Potrf(sym) if ok { c.updateCond(norm) } else { c.cond = math.Inf(1) } return ok }