// 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 }
// Norm returns the specified (induced) norm of the matrix a. See // https://en.wikipedia.org/wiki/Matrix_norm for the definition of an induced norm. // // Valid norms are: // 1 - The maximum absolute column sum // 2 - Frobenius norm, the square root of the sum of the squares of the elements. // Inf - The maximum absolute row sum. // Norm will panic with ErrNormOrder if an illegal norm order is specified. func Norm(a Matrix, norm float64) float64 { r, c := a.Dims() aMat, aTrans := untranspose(a) var work []float64 switch rma := aMat.(type) { case RawMatrixer: rm := rma.RawMatrix() n := normLapack(norm, aTrans) if n == lapack.MaxColumnSum { work = make([]float64, rm.Cols) } return lapack64.Lange(n, rm, work) case RawTriangular: rm := rma.RawTriangular() n := normLapack(norm, aTrans) if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { work = make([]float64, rm.N) } return lapack64.Lantr(n, rm, work) case RawSymmetricer: rm := rma.RawSymmetric() n := normLapack(norm, aTrans) if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { work = make([]float64, rm.N) } return lapack64.Lansy(n, rm, work) } switch norm { default: panic("unreachable") case 1: var max float64 for j := 0; j < c; j++ { var sum float64 for i := 0; i < r; i++ { sum += math.Abs(a.At(i, j)) } if sum > max { max = sum } } return max case 2: var sum float64 for i := 0; i < r; i++ { for j := 0; j < c; j++ { v := a.At(i, j) sum += v * v } } return math.Sqrt(sum) case math.Inf(1): var max float64 for i := 0; i < r; i++ { var sum float64 for j := 0; j < c; j++ { sum += math.Abs(a.At(i, j)) } if sum > max { max = sum } } return max } }
// Norm returns the specified (induced) norm of the matrix a. See // https://en.wikipedia.org/wiki/Matrix_norm for the definition of an induced norm. // // Valid norms are: // 1 - The maximum absolute column sum // 2 - Frobenius norm, the square root of the sum of the squares of the elements. // Inf - The maximum absolute row sum. // Norm will panic with ErrNormOrder if an illegal norm order is specified and // with matrix.ErrShape if the matrix has zero size. func Norm(a Matrix, norm float64) float64 { r, c := a.Dims() if r == 0 || c == 0 { panic(matrix.ErrShape) } aU, aTrans := untranspose(a) var work []float64 switch rma := aU.(type) { case RawMatrixer: rm := rma.RawMatrix() n := normLapack(norm, aTrans) if n == lapack.MaxColumnSum { work = make([]float64, rm.Cols) } return lapack64.Lange(n, rm, work) case RawTriangular: rm := rma.RawTriangular() n := normLapack(norm, aTrans) if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { work = make([]float64, rm.N) } return lapack64.Lantr(n, rm, work) case RawSymmetricer: rm := rma.RawSymmetric() n := normLapack(norm, aTrans) if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { work = make([]float64, rm.N) } return lapack64.Lansy(n, rm, work) case *Vector: rv := rma.RawVector() switch norm { default: panic("unreachable") case 1: if aTrans { imax := blas64.Iamax(rma.n, rv) return math.Abs(rma.At(imax, 0)) } return blas64.Asum(rma.n, rv) case 2: return blas64.Nrm2(rma.n, rv) case math.Inf(1): if aTrans { return blas64.Asum(rma.n, rv) } imax := blas64.Iamax(rma.n, rv) return math.Abs(rma.At(imax, 0)) } } switch norm { default: panic("unreachable") case 1: var max float64 for j := 0; j < c; j++ { var sum float64 for i := 0; i < r; i++ { sum += math.Abs(a.At(i, j)) } if sum > max { max = sum } } return max case 2: var sum float64 for i := 0; i < r; i++ { for j := 0; j < c; j++ { v := a.At(i, j) sum += v * v } } return math.Sqrt(sum) case math.Inf(1): var max float64 for i := 0; i < r; i++ { var sum float64 for j := 0; j < c; j++ { sum += math.Abs(a.At(i, j)) } if sum > max { max = sum } } return max } }