1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
|
// Copyright ©2017 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mat
import (
"testing"
"golang.org/x/exp/rand"
)
func TestHOGSVD(t *testing.T) {
t.Parallel()
const tol = 1e-10
rnd := rand.New(rand.NewSource(1))
for cas, test := range []struct {
r, c int
}{
{5, 3},
{5, 5},
{150, 150},
{200, 150},
// Calculating A_i*A_jᵀ and A_j*A_iᵀ fails for wide matrices.
{3, 5},
} {
r := test.r
c := test.c
for n := 3; n < 6; n++ {
data := make([]Matrix, n)
dataCopy := make([]*Dense, n)
for trial := 0; trial < 10; trial++ {
for i := range data {
d := NewDense(r, c, nil)
for j := range d.mat.Data {
d.mat.Data[j] = rnd.Float64()
}
data[i] = d
dataCopy[i] = DenseCopyOf(d)
}
var gsvd HOGSVD
ok := gsvd.Factorize(data...)
if r >= c {
if !ok {
t.Errorf("HOGSVD factorization failed for %d %d×%d matrices: %v", n, r, c, gsvd.Err())
continue
}
} else {
if ok {
t.Errorf("HOGSVD factorization unexpectedly succeeded for %d %d×%d matrices", n, r, c)
}
continue
}
for i := range data {
if !Equal(data[i], dataCopy[i]) {
t.Errorf("A changed during call to HOGSVD.Factorize")
}
}
u, s, v := extractHOGSVD(&gsvd)
for i, want := range data {
var got Dense
sigma := NewDense(c, c, nil)
for j := 0; j < c; j++ {
sigma.Set(j, j, s[i][j])
}
got.Product(u[i], sigma, v.T())
if !EqualApprox(&got, want, tol) {
t.Errorf("test %d n=%d trial %d: unexpected answer\nU_%[4]d * S_%[4]d * Vᵀ:\n% 0.2f\nD_%d:\n% 0.2f",
cas, n, trial, i, Formatted(&got, Excerpt(5)), i, Formatted(want, Excerpt(5)))
}
}
}
}
}
}
func extractHOGSVD(gsvd *HOGSVD) (u []*Dense, s [][]float64, v *Dense) {
u = make([]*Dense, gsvd.Len())
s = make([][]float64, gsvd.Len())
for i := 0; i < gsvd.Len(); i++ {
u[i] = &Dense{}
gsvd.UTo(u[i], i)
s[i] = gsvd.Values(nil, i)
}
v = &Dense{}
gsvd.VTo(v)
return u, s, v
}
|