testlapack: use bad matrices in tests for Dtrexc and Dlaexc

This commit is contained in:
Vladimir Chalupecky
2020-02-16 00:56:32 +01:00
committed by Vladimír Chalupecký
parent 887ddf9cc3
commit 315a975e1d
2 changed files with 4 additions and 86 deletions

View File

@@ -6,8 +6,6 @@ package testlapack
import ( import (
"fmt" "fmt"
"math"
"math/cmplx"
"testing" "testing"
"golang.org/x/exp/rand" "golang.org/x/exp/rand"
@@ -37,7 +35,7 @@ func testDlaexc(t *testing.T, impl Dlaexcer, rnd *rand.Rand, n, extra int) {
const tol = 1e-14 const tol = 1e-14
// Generate random T in Schur canonical form. // Generate random T in Schur canonical form.
tmat, wr, _ := randomSchurCanonical(n, n+extra, false, rnd) tmat, _, _ := randomSchurCanonical(n, n+extra, true, rnd)
tmatCopy := cloneGeneral(tmat) tmatCopy := cloneGeneral(tmat)
// Randomly pick the index of the first block. // Randomly pick the index of the first block.
@@ -160,55 +158,6 @@ func testDlaexc(t *testing.T, impl Dlaexcer, rnd *rand.Rand, n, extra int) {
t.Errorf("%v: T is not in Schur canonical form", name) t.Errorf("%v: T is not in Schur canonical form", name)
} }
if n1 == 1 {
// 1×1 blocks are swapped exactly.
got := tmat.Data[(j1+n2)*tmat.Stride+j1+n2]
want := wr[j1]
if want != got {
t.Errorf("%v: unexpected value of T[%v,%v]; got %v, want %v", name, j1+n2, j1+n2, got, want)
}
} else {
// Compute eigenvalues of the n1×n1 block which is now located at T[j1+n2,j1+n2].
a, b, c, d := extract2x2Block(tmat.Data[(j1+n2)*tmat.Stride+j1+n2:], tmat.Stride)
ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d)
// Check that the swapped 2×2 block has the same eigenvalues.
// The n1×n1 block was originally located at T[j1,j1].
a, b, c, d = extract2x2Block(tmatCopy.Data[j1*tmatCopy.Stride+j1:], tmatCopy.Stride)
ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d)
diff1 := math.Min(cmplx.Abs(ev1Got-ev1Want), cmplx.Abs(ev1Got-ev2Want))
diff2 := math.Min(cmplx.Abs(ev2Got-ev1Want), cmplx.Abs(ev2Got-ev2Want))
diff := math.Min(diff1, diff2)
if diff > tol {
t.Errorf("%v: unexpected eigenvalues of 2×2 block; diff=%v, want<=%v", name, diff, tol)
}
}
if n2 == 1 {
// 1×1 blocks are swapped exactly.
got := tmat.Data[j1*tmat.Stride+j1]
want := wr[j1+n1]
if want != got {
t.Errorf("%v: unexpected value of T[%v,%v];got %v, want %v", name, j1, j1, got, want)
}
} else {
// Compute eigenvalues of the n2×n2 block which is now located at T[j1,j1].
a, b, c, d := extract2x2Block(tmat.Data[j1*tmat.Stride+j1:], tmat.Stride)
ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d)
// Check that the swapped 2×2 block has the same eigenvalues.
// The n2×n2 block was originally located at T[j1+n1,j1+n1].
a, b, c, d = extract2x2Block(tmatCopy.Data[(j1+n1)*tmatCopy.Stride+j1+n1:], tmatCopy.Stride)
ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d)
diff1 := math.Min(cmplx.Abs(ev1Got-ev1Want), cmplx.Abs(ev1Got-ev2Want))
diff2 := math.Min(cmplx.Abs(ev2Got-ev1Want), cmplx.Abs(ev2Got-ev2Want))
diff := math.Min(diff1, diff2)
if diff > tol {
t.Errorf("%v: unexpected eigenvalues of 2×2 block; diff=%v, want<=%v", name, diff, tol)
}
}
// Check that Q is orthogonal. // Check that Q is orthogonal.
resid := residualOrthogonal(q, false) resid := residualOrthogonal(q, false)
if resid > tol { if resid > tol {
@@ -234,8 +183,8 @@ func testDlaexc(t *testing.T, impl Dlaexcer, rnd *rand.Rand, n, extra int) {
qtq := cloneGeneral(tmat) qtq := cloneGeneral(tmat)
blas64.Gemm(blas.NoTrans, blas.NoTrans, -1, qt, q, 1, qtq) blas64.Gemm(blas.NoTrans, blas.NoTrans, -1, qt, q, 1, qtq)
resid = dlange(lapack.MaxColumnSum, n, n, qtq.Data, qtq.Stride) resid = dlange(lapack.MaxColumnSum, n, n, qtq.Data, qtq.Stride)
if resid > tol { if resid > float64(n)*tol {
t.Errorf("%v: mismatch between Qᵀ*(initial T)*Q and (final T); resid=%v, want<=%v", t.Errorf("%v: mismatch between Qᵀ*(initial T)*Q and (final T); resid=%v, want<=%v",
name, resid, tol) name, resid, float64(n)*tol)
} }
} }

View File

@@ -7,7 +7,6 @@ package testlapack
import ( import (
"fmt" "fmt"
"math" "math"
"math/cmplx"
"testing" "testing"
"golang.org/x/exp/rand" "golang.org/x/exp/rand"
@@ -41,7 +40,7 @@ func DtrexcTest(t *testing.T, impl Dtrexcer) {
func dtrexcTest(t *testing.T, impl Dtrexcer, rnd *rand.Rand, n, ifst, ilst, extra int) { func dtrexcTest(t *testing.T, impl Dtrexcer, rnd *rand.Rand, n, ifst, ilst, extra int) {
const tol = 1e-13 const tol = 1e-13
tmat, wr, wi := randomSchurCanonical(n, n+extra, false, rnd) tmat, _, _ := randomSchurCanonical(n, n+extra, true, rnd)
tmatCopy := cloneGeneral(tmat) tmatCopy := cloneGeneral(tmat)
fstSize, fstFirst := schurBlockSize(tmat, ifst) fstSize, fstFirst := schurBlockSize(tmat, ifst)
@@ -165,36 +164,6 @@ func dtrexcTest(t *testing.T, impl Dtrexcer, rnd *rand.Rand, n, ifst, ilst, extr
} }
} }
// Check that the block at ifstGot was delivered to ilstGot correctly.
if fstSize == 1 {
// 1×1 blocks are swapped exactly.
got := tmat.Data[ilstGot*tmat.Stride+ilstGot]
want := wr[ifstGot]
if want != got {
t.Errorf("%v: unexpected 1×1 block at T[%v,%v]; got %v, want %v",
name, ilstGot, ilstGot, got, want)
}
} else {
// Check that the swapped 2×2 block has the same eigenvalues.
a, b, c, d := extract2x2Block(tmat.Data[ilstGot*tmat.Stride+ilstGot:], tmat.Stride)
ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d)
// The block was originally located at T[ifstGot,ifstGot].
ev1Want := complex(wr[ifstGot], wi[ifstGot])
ev2Want := complex(wr[ifstGot+1], wi[ifstGot+1])
diff := cmplx.Abs(ev1Got - ev1Want)
if diff > tol {
t.Errorf("%v: unexpected first eigenvalue of 2×2 block at T[%v,%v]; diff=%v, want<=%v",
name, ilstGot, ilstGot, diff, tol)
}
diff = cmplx.Abs(ev2Got - ev2Want)
if diff > tol {
t.Errorf("%v: unexpected second eigenvalue of 2×2 block at T[%v,%v]; diff=%v, want<=%v",
name, ilstGot, ilstGot, diff, tol)
}
}
// Check that Q is orthogonal. // Check that Q is orthogonal.
resid := residualOrthogonal(q, false) resid := residualOrthogonal(q, false)
if resid > tol { if resid > tol {