1 // Copyright ©2016 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"
14 "gonum.org/v1/gonum/blas/blas64"
17 type Dlaqr23er interface {
18 Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, sr, si []float64, v []float64, ldv int, nh int, t []float64, ldt int, nv int, wv []float64, ldwv int, work []float64, lwork int, recur int) (ns, nd int)
21 type dlaqr23Test struct {
28 evWant []complex128 // Optional slice with known eigenvalues.
31 func Dlaqr23Test(t *testing.T, impl Dlaqr23er) {
32 rnd := rand.New(rand.NewSource(1))
34 for _, wantt := range []bool{true, false} {
35 for _, wantz := range []bool{true, false} {
36 for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 100} {
37 for _, extra := range []int{0, 11} {
38 for cas := 0; cas < 30; cas++ {
43 nw = 76 + rnd.Intn(n-75)
45 ktop := rnd.Intn(n - nw + 1)
47 kbot += rnd.Intn(n - kbot)
48 h := randomHessenberg(n, n+extra, rnd)
50 h.Data[ktop*h.Stride+ktop-1] = 0
53 h.Data[(kbot+1)*h.Stride+kbot] = 0
55 iloz := rnd.Intn(ktop + 1)
56 ihiz := kbot + rnd.Intn(n-kbot)
67 testDlaqr23(t, impl, test, false, 1, rnd)
68 testDlaqr23(t, impl, test, true, 1, rnd)
69 testDlaqr23(t, impl, test, false, 0, rnd)
70 testDlaqr23(t, impl, test, true, 0, rnd)
78 for _, wantt := range []bool{true, false} {
79 for _, wantz := range []bool{true, false} {
80 for _, extra := range []int{0, 1, 11} {
84 h: randomHessenberg(0, extra, rnd),
91 testDlaqr23(t, impl, test, true, 1, rnd)
92 testDlaqr23(t, impl, test, false, 1, rnd)
93 testDlaqr23(t, impl, test, true, 0, rnd)
94 testDlaqr23(t, impl, test, false, 0, rnd)
99 // Tests with explicit eigenvalues computed by Octave.
100 for _, test := range []dlaqr23Test{
106 Data: []float64{7.09965484086874e-1},
112 evWant: []complex128{7.09965484086874e-1},
128 evWant: []complex128{1i, -1i},
136 6.25219991450918e-1, 8.17510791994361e-1,
137 3.31218891622294e-1, 1.24103744878131e-1,
144 evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1},
153 0, 6.25219991450918e-1, 8.17510791994361e-1, 0,
154 0, 3.31218891622294e-1, 1.24103744878131e-1, 0,
162 evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1},
170 -1.1219562276608, 6.85473513349362e-1,
171 -8.19951061145131e-1, 1.93728523178888e-1,
178 evWant: []complex128{
179 -4.64113852240958e-1 + 3.59580510817350e-1i,
180 -4.64113852240958e-1 - 3.59580510817350e-1i,
189 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2,
190 -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1,
191 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1,
192 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1,
193 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1,
200 evWant: []complex128{
202 4.97029793606701e-1 + 3.63041654992384e-1i,
203 4.97029793606701e-1 - 3.63041654992384e-1i,
204 -1.74079119166145e-1 + 2.01570009462092e-1i,
205 -1.74079119166145e-1 - 2.01570009462092e-1i,
211 test.nw = test.kbot - test.ktop + 1
212 testDlaqr23(t, impl, test, true, 1, rnd)
213 testDlaqr23(t, impl, test, false, 1, rnd)
214 testDlaqr23(t, impl, test, true, 0, rnd)
215 testDlaqr23(t, impl, test, false, 0, rnd)
219 func testDlaqr23(t *testing.T, impl Dlaqr23er, test dlaqr23Test, opt bool, recur int, rnd *rand.Rand) {
222 h := cloneGeneral(test.h)
224 extra := h.Stride - h.Cols
233 var z, zCopy blas64.General
236 zCopy = cloneGeneral(z)
239 sr := nanSlice(kbot + 1)
240 si := nanSlice(kbot + 1)
242 v := randomGeneral(nw, nw, nw+extra, rnd)
245 nh = nw + rnd.Intn(nw) // nh must be at least nw.
247 tmat := randomGeneral(nw, nh, nh+extra, rnd)
250 nv = rnd.Intn(nw) + 1
252 wv := randomGeneral(nv, nw, nw+extra, rnd)
257 impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, nil, h.Stride, iloz, ihiz, nil, z.Stride,
258 nil, nil, nil, v.Stride, tmat.Cols, nil, tmat.Stride, wv.Rows, nil, wv.Stride, work, -1, recur)
259 work = nanSlice(int(work[0]))
261 work = nanSlice(max(1, 2*nw))
264 ns, nd := impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, h.Data, h.Stride, iloz, ihiz, z.Data, z.Stride,
265 sr, si, v.Data, v.Stride, tmat.Cols, tmat.Data, tmat.Stride, wv.Rows, wv.Data, wv.Stride, work, len(work), recur)
267 prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ktop=%v, kbot=%v, nw=%v, iloz=%v, ihiz=%v, extra=%v",
268 wantt, wantz, n, ktop, kbot, nw, iloz, ihiz, extra)
270 if !generalOutsideAllNaN(h) {
271 t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data)
273 if !generalOutsideAllNaN(z) {
274 t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data)
276 if !generalOutsideAllNaN(v) {
277 t.Errorf("%v: out-of-range write to V\n%v", prefix, v.Data)
279 if !generalOutsideAllNaN(tmat) {
280 t.Errorf("%v: out-of-range write to T\n%v", prefix, tmat.Data)
282 if !generalOutsideAllNaN(wv) {
283 t.Errorf("%v: out-of-range write to WV\n%v", prefix, wv.Data)
285 if !isAllNaN(sr[:kbot-nd-ns+1]) || !isAllNaN(sr[kbot+1:]) {
286 t.Errorf("%v: out-of-range write to sr", prefix)
288 if !isAllNaN(si[:kbot-nd-ns+1]) || !isAllNaN(si[kbot+1:]) {
289 t.Errorf("%v: out-of-range write to si", prefix)
292 if !isUpperHessenberg(h) {
293 t.Errorf("%v: H is not upper Hessenberg", prefix)
296 if test.evWant != nil {
297 for i := kbot - nd + 1; i <= kbot; i++ {
298 ev := complex(sr[i], si[i])
299 found, _ := containsComplex(test.evWant, ev, tol)
301 t.Errorf("%v: unexpected eigenvalue %v", prefix, ev)
311 for i := 0; i < n; i++ {
312 for j := 0; j < n; j++ {
313 if z.Data[i*z.Stride+j] == zCopy.Data[i*zCopy.Stride+j] {
316 if i < iloz || i > ihiz || j < kbot-nw+1 || j > kbot {
322 t.Errorf("%v: unexpected modification of Z", prefix)
324 if !isOrthonormal(z) {
325 t.Errorf("%v: Z is not orthogonal", prefix)
329 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hu)
331 blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hu, 0, uhu)
332 if !equalApproxGeneral(uhu, h, 10*tol) {
333 t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix)