+++ /dev/null
-// Copyright ©2016 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 testlapack
-
-import (
- "fmt"
- "testing"
-
- "golang.org/x/exp/rand"
-
- "gonum.org/v1/gonum/blas"
- "gonum.org/v1/gonum/blas/blas64"
-)
-
-type Dlaqr23er interface {
- 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)
-}
-
-type dlaqr23Test struct {
- wantt, wantz bool
- ktop, kbot int
- nw int
- h blas64.General
- iloz, ihiz int
-
- evWant []complex128 // Optional slice with known eigenvalues.
-}
-
-func Dlaqr23Test(t *testing.T, impl Dlaqr23er) {
- rnd := rand.New(rand.NewSource(1))
-
- for _, wantt := range []bool{true, false} {
- for _, wantz := range []bool{true, false} {
- for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 100} {
- for _, extra := range []int{0, 11} {
- for cas := 0; cas < 30; cas++ {
- var nw int
- if nw <= 75 {
- nw = rnd.Intn(n) + 1
- } else {
- nw = 76 + rnd.Intn(n-75)
- }
- ktop := rnd.Intn(n - nw + 1)
- kbot := ktop + nw - 1
- kbot += rnd.Intn(n - kbot)
- h := randomHessenberg(n, n+extra, rnd)
- if ktop-1 >= 0 {
- h.Data[ktop*h.Stride+ktop-1] = 0
- }
- if kbot+1 < n {
- h.Data[(kbot+1)*h.Stride+kbot] = 0
- }
- iloz := rnd.Intn(ktop + 1)
- ihiz := kbot + rnd.Intn(n-kbot)
- test := dlaqr23Test{
- wantt: wantt,
- wantz: wantz,
- ktop: ktop,
- kbot: kbot,
- nw: nw,
- h: h,
- iloz: iloz,
- ihiz: ihiz,
- }
- testDlaqr23(t, impl, test, false, 1, rnd)
- testDlaqr23(t, impl, test, true, 1, rnd)
- testDlaqr23(t, impl, test, false, 0, rnd)
- testDlaqr23(t, impl, test, true, 0, rnd)
- }
- }
- }
- }
- }
-
- // Tests with n=0.
- for _, wantt := range []bool{true, false} {
- for _, wantz := range []bool{true, false} {
- for _, extra := range []int{0, 1, 11} {
- test := dlaqr23Test{
- wantt: wantt,
- wantz: wantz,
- h: randomHessenberg(0, extra, rnd),
- ktop: 0,
- kbot: -1,
- iloz: 0,
- ihiz: -1,
- nw: 0,
- }
- testDlaqr23(t, impl, test, true, 1, rnd)
- testDlaqr23(t, impl, test, false, 1, rnd)
- testDlaqr23(t, impl, test, true, 0, rnd)
- testDlaqr23(t, impl, test, false, 0, rnd)
- }
- }
- }
-
- // Tests with explicit eigenvalues computed by Octave.
- for _, test := range []dlaqr23Test{
- {
- h: blas64.General{
- Rows: 1,
- Cols: 1,
- Stride: 1,
- Data: []float64{7.09965484086874e-1},
- },
- ktop: 0,
- kbot: 0,
- iloz: 0,
- ihiz: 0,
- evWant: []complex128{7.09965484086874e-1},
- },
- {
- h: blas64.General{
- Rows: 2,
- Cols: 2,
- Stride: 2,
- Data: []float64{
- 0, -1,
- 1, 0,
- },
- },
- ktop: 0,
- kbot: 1,
- iloz: 0,
- ihiz: 1,
- evWant: []complex128{1i, -1i},
- },
- {
- h: blas64.General{
- Rows: 2,
- Cols: 2,
- Stride: 2,
- Data: []float64{
- 6.25219991450918e-1, 8.17510791994361e-1,
- 3.31218891622294e-1, 1.24103744878131e-1,
- },
- },
- ktop: 0,
- kbot: 1,
- iloz: 0,
- ihiz: 1,
- evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1},
- },
- {
- h: blas64.General{
- Rows: 4,
- Cols: 4,
- Stride: 4,
- Data: []float64{
- 1, 0, 0, 0,
- 0, 6.25219991450918e-1, 8.17510791994361e-1, 0,
- 0, 3.31218891622294e-1, 1.24103744878131e-1, 0,
- 0, 0, 0, 1,
- },
- },
- ktop: 1,
- kbot: 2,
- iloz: 0,
- ihiz: 3,
- evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1},
- },
- {
- h: blas64.General{
- Rows: 2,
- Cols: 2,
- Stride: 2,
- Data: []float64{
- -1.1219562276608, 6.85473513349362e-1,
- -8.19951061145131e-1, 1.93728523178888e-1,
- },
- },
- ktop: 0,
- kbot: 1,
- iloz: 0,
- ihiz: 1,
- evWant: []complex128{
- -4.64113852240958e-1 + 3.59580510817350e-1i,
- -4.64113852240958e-1 - 3.59580510817350e-1i,
- },
- },
- {
- h: blas64.General{
- Rows: 5,
- Cols: 5,
- Stride: 5,
- Data: []float64{
- 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2,
- -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1,
- 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1,
- 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1,
- 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1,
- },
- },
- ktop: 0,
- kbot: 4,
- iloz: 0,
- ihiz: 4,
- evWant: []complex128{
- 2.94393309555622,
- 4.97029793606701e-1 + 3.63041654992384e-1i,
- 4.97029793606701e-1 - 3.63041654992384e-1i,
- -1.74079119166145e-1 + 2.01570009462092e-1i,
- -1.74079119166145e-1 - 2.01570009462092e-1i,
- },
- },
- } {
- test.wantt = true
- test.wantz = true
- test.nw = test.kbot - test.ktop + 1
- testDlaqr23(t, impl, test, true, 1, rnd)
- testDlaqr23(t, impl, test, false, 1, rnd)
- testDlaqr23(t, impl, test, true, 0, rnd)
- testDlaqr23(t, impl, test, false, 0, rnd)
- }
-}
-
-func testDlaqr23(t *testing.T, impl Dlaqr23er, test dlaqr23Test, opt bool, recur int, rnd *rand.Rand) {
- const tol = 1e-14
-
- h := cloneGeneral(test.h)
- n := h.Cols
- extra := h.Stride - h.Cols
- wantt := test.wantt
- wantz := test.wantz
- ktop := test.ktop
- kbot := test.kbot
- nw := test.nw
- iloz := test.iloz
- ihiz := test.ihiz
-
- var z, zCopy blas64.General
- if wantz {
- z = eye(n, n+extra)
- zCopy = cloneGeneral(z)
- }
-
- sr := nanSlice(kbot + 1)
- si := nanSlice(kbot + 1)
-
- v := randomGeneral(nw, nw, nw+extra, rnd)
- var nh int
- if nw > 0 {
- nh = nw + rnd.Intn(nw) // nh must be at least nw.
- }
- tmat := randomGeneral(nw, nh, nh+extra, rnd)
- var nv int
- if nw > 0 {
- nv = rnd.Intn(nw) + 1
- }
- wv := randomGeneral(nv, nw, nw+extra, rnd)
-
- var work []float64
- if opt {
- work = nanSlice(1)
- impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, nil, h.Stride, iloz, ihiz, nil, z.Stride,
- nil, nil, nil, v.Stride, tmat.Cols, nil, tmat.Stride, wv.Rows, nil, wv.Stride, work, -1, recur)
- work = nanSlice(int(work[0]))
- } else {
- work = nanSlice(max(1, 2*nw))
- }
-
- ns, nd := impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, h.Data, h.Stride, iloz, ihiz, z.Data, z.Stride,
- sr, si, v.Data, v.Stride, tmat.Cols, tmat.Data, tmat.Stride, wv.Rows, wv.Data, wv.Stride, work, len(work), recur)
-
- prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ktop=%v, kbot=%v, nw=%v, iloz=%v, ihiz=%v, extra=%v",
- wantt, wantz, n, ktop, kbot, nw, iloz, ihiz, extra)
-
- if !generalOutsideAllNaN(h) {
- t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data)
- }
- if !generalOutsideAllNaN(z) {
- t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data)
- }
- if !generalOutsideAllNaN(v) {
- t.Errorf("%v: out-of-range write to V\n%v", prefix, v.Data)
- }
- if !generalOutsideAllNaN(tmat) {
- t.Errorf("%v: out-of-range write to T\n%v", prefix, tmat.Data)
- }
- if !generalOutsideAllNaN(wv) {
- t.Errorf("%v: out-of-range write to WV\n%v", prefix, wv.Data)
- }
- if !isAllNaN(sr[:kbot-nd-ns+1]) || !isAllNaN(sr[kbot+1:]) {
- t.Errorf("%v: out-of-range write to sr", prefix)
- }
- if !isAllNaN(si[:kbot-nd-ns+1]) || !isAllNaN(si[kbot+1:]) {
- t.Errorf("%v: out-of-range write to si", prefix)
- }
-
- if !isUpperHessenberg(h) {
- t.Errorf("%v: H is not upper Hessenberg", prefix)
- }
-
- if test.evWant != nil {
- for i := kbot - nd + 1; i <= kbot; i++ {
- ev := complex(sr[i], si[i])
- found, _ := containsComplex(test.evWant, ev, tol)
- if !found {
- t.Errorf("%v: unexpected eigenvalue %v", prefix, ev)
- }
- }
- }
-
- if !wantz {
- return
- }
-
- var zmod bool
- for i := 0; i < n; i++ {
- for j := 0; j < n; j++ {
- if z.Data[i*z.Stride+j] == zCopy.Data[i*zCopy.Stride+j] {
- continue
- }
- if i < iloz || i > ihiz || j < kbot-nw+1 || j > kbot {
- zmod = true
- }
- }
- }
- if zmod {
- t.Errorf("%v: unexpected modification of Z", prefix)
- }
- if !isOrthonormal(z) {
- t.Errorf("%v: Z is not orthogonal", prefix)
- }
- if wantt {
- hu := eye(n, n)
- blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hu)
- uhu := eye(n, n)
- blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hu, 0, uhu)
- if !equalApproxGeneral(uhu, h, 10*tol) {
- t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix)
- }
- }
-}