1 // Copyright ©2013 The Gonum Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 "golang.org/x/exp/rand"
13 "gonum.org/v1/gonum/blas/blas64"
16 func TestQR(t *testing.T) {
17 for _, test := range []struct {
25 a := NewDense(m, n, nil)
26 for i := 0; i < m; i++ {
27 for j := 0; j < n; j++ {
28 a.Set(i, j, rand.NormFloat64())
38 if !isOrthonormal(q, 1e-10) {
39 t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n)
46 if !EqualApprox(&got, &want, 1e-12) {
47 t.Errorf("QR does not equal original matrix. \nWant: %v\nGot: %v", want, got)
52 func isOrthonormal(q *Dense, tol float64) bool {
57 for i := 0; i < m; i++ {
58 for j := i; j < m; j++ {
60 blas64.Vector{Inc: 1, Data: q.mat.Data[i*q.mat.Stride:]},
61 blas64.Vector{Inc: 1, Data: q.mat.Data[j*q.mat.Stride:]},
63 // Dot product should be 1 if i == j and 0 otherwise.
64 if i == j && math.Abs(dot-1) > tol {
67 if i != j && math.Abs(dot) > tol {
75 func TestSolveQR(t *testing.T) {
76 for _, trans := range []bool{false, true} {
77 for _, test := range []struct {
88 a := NewDense(m, n, nil)
89 for i := 0; i < m; i++ {
90 for j := 0; j < n; j++ {
91 a.Set(i, j, rand.Float64())
98 b := NewDense(br, bc, nil)
99 for i := 0; i < br; i++ {
100 for j := 0; j < bc; j++ {
101 b.Set(i, j, rand.Float64())
107 qr.Solve(&x, trans, b)
109 // Test that the normal equations hold.
110 // A^T * A * x = A^T * b if !trans
111 // A * A^T * x = A * b if trans
125 if !EqualApprox(&lhs, &rhs, 1e-10) {
126 t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs)
130 // TODO(btracey): Add in testOneInput when it exists.
133 func TestSolveQRVec(t *testing.T) {
134 for _, trans := range []bool{false, true} {
135 for _, test := range []struct {
143 a := NewDense(m, n, nil)
144 for i := 0; i < m; i++ {
145 for j := 0; j < n; j++ {
146 a.Set(i, j, rand.Float64())
153 b := NewVecDense(br, nil)
154 for i := 0; i < br; i++ {
155 b.SetVec(i, rand.Float64())
160 qr.SolveVec(&x, trans, b)
162 // Test that the normal equations hold.
163 // A^T * A * x = A^T * b if !trans
164 // A * A^T * x = A * b if trans
178 if !EqualApprox(&lhs, &rhs, 1e-10) {
179 t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs)
183 // TODO(btracey): Add in testOneInput when it exists.
186 func TestSolveQRCond(t *testing.T) {
187 for _, test := range []*Dense{
188 NewDense(2, 2, []float64{1, 0, 0, 1e-20}),
189 NewDense(3, 2, []float64{1, 0, 0, 1e-20, 0, 0}),
194 b := NewDense(m, 2, nil)
196 if err := qr.Solve(&x, false, b); err == nil {
197 t.Error("No error for near-singular matrix in matrix solve.")
200 bvec := NewVecDense(m, nil)
202 if err := qr.SolveVec(&xvec, false, bvec); err == nil {
203 t.Error("No error for near-singular matrix in matrix solve.")