// NewNormal creates a new Normal with the given mean and covariance matrix. // NewNormal panics if len(mu) == 0, or if len(mu) != sigma.N. If the covariance // matrix is not positive-definite, the returned boolean is false. func NewNormal(mu []float64, sigma mat64.Symmetric, src *rand.Rand) (*Normal, bool) { if len(mu) == 0 { panic(badZeroDimension) } dim := sigma.Symmetric() if dim != len(mu) { panic(badSizeMismatch) } n := &Normal{ src: src, dim: dim, mu: make([]float64, dim), sigma: mat64.NewSymDense(dim, nil), chol: mat64.NewTriDense(dim, true, nil), } copy(n.mu, mu) n.sigma.CopySym(sigma) // TODO(btracey): Change this to the input Sigma, in case it is diagonal or // banded. ok := n.chol.Cholesky(n.sigma, true) if !ok { return nil, false } for i := 0; i < dim; i++ { n.logSqrtDet += math.Log(n.chol.At(i, i)) } return n, true }
func cholesky(order int, elements []float64) fmt.Formatter { t := mat64.NewTriDense(order, false, nil) t.Cholesky(mat64.NewSymDense(order, elements), false) return mat64.Formatted(t) }
func resizeTriDense(m *mat64.TriDense, dim int) *mat64.TriDense { if m == nil || cap(m.RawTriangular().Data) < dim*dim { return mat64.NewTriDense(dim, true, nil) } return mat64.NewTriDense(dim, true, m.RawTriangular().Data[:dim*dim]) }