Add Clone method for Cholesky
MODIFY
mat64/cholesky.go
mat64/cholesky.go
@@ -26,6 +26,10 @@ const (
// initialized by a call to Factorize that has returned true. Calls to methods
// of an unsuccessful Cholesky factorization will panic.
type Cholesky struct {
+ // The chol pointer must never be retained as a pointer outside the Cholesky
+ // struct, either by returning chol outside the struct or by setting it to
+ // a pointer coming from outside. The same prohibition applies to the data
+ // slice within chol.
chol *TriDense
cond float64
}
@@ -103,6 +107,23 @@ func (c *Cholesky) SetFromU(t *TriDense) {
c.updateCond(-1)
}
+// Clone makes a copy of the input Cholesky into the receiver, overwriting the
+// previous value of the receiver. Clone does not place any restrictions on receiver
+// shape. Clone panics if the input Cholesky is not the result of a valid decomposition.
+func (c *Cholesky) Clone(chol *Cholesky) {
+ if !chol.valid() {
+ panic(badCholesky)
+ }
+ n := chol.Size()
+ if c.isZero() {
+ c.chol = NewTriDense(n, matrix.Upper, nil)
+ } else {
+ c.chol = NewTriDense(n, matrix.Upper, use(c.chol.mat.Data, n*n))
+ }
+ c.chol.Copy(chol.chol)
+ c.cond = chol.cond
+}
+
// Size returns the dimension of the factorized matrix.
func (c *Cholesky) Size() int {
if !c.valid() {

MODIFY
mat64/cholesky_test.go
mat64/cholesky_test.go
@@ -10,6 +10,7 @@ import (
"testing"
"github.com/gonum/blas/testblas"
+ "github.com/gonum/matrix"
)
func TestCholesky(t *testing.T) {
@@ -182,6 +183,42 @@ func TestFromCholesky(t *testing.T) {
}
}
+func TestCloneCholesky(t *testing.T) {
+ for _, test := range []*SymDense{
+ NewSymDense(3, []float64{
+ 53, 59, 37,
+ 0, 83, 71,
+ 0, 0, 101,
+ }),
+ } {
+ var chol Cholesky
+ ok := chol.Factorize(test)
+ if !ok {
+ panic("bad test")
+ }
+ var chol2 Cholesky
+ chol2.Clone(&chol)
+
+ if chol.cond != chol2.cond {
+ t.Errorf("condition number mismatch from zero")
+ }
+ if !Equal(chol.chol, chol2.chol) {
+ t.Errorf("chol mismatch from zero")
+ }
+
+ // Corrupt chol2 and try again
+ chol2.cond = math.NaN()
+ chol2.chol = NewTriDense(2, matrix.Upper, nil)
+ chol2.Clone(&chol)
+ if chol.cond != chol2.cond {
+ t.Errorf("condition number mismatch from non-zero")
+ }
+ if !Equal(chol.chol, chol2.chol) {
+ t.Errorf("chol mismatch from non-zero")
+ }
+ }
+}
+
func TestInverseCholesky(t *testing.T) {
for _, n := range []int{1, 3, 5, 9} {
data := make([]float64, n*n)

Add Clone method for Cholesky