mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 23:26:52 +08:00
testlapack: use bad matrices in tests for Dtrexc and Dlaexc
This commit is contained in:

committed by
Vladimír Chalupecký

parent
887ddf9cc3
commit
315a975e1d
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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 {
|
||||||
|
Reference in New Issue
Block a user