mirror of
https://github.com/gonum/gonum.git
synced 2025-10-19 05:24:52 +08:00
lapack/testlapack: add implementation comments to Dlatrd test
This commit is contained in:

committed by
Vladimír Chalupecký

parent
6dfebf106b
commit
c015e0732d
@@ -42,11 +42,15 @@ func DlatrdTest(t *testing.T, impl Dlatrder) {
|
|||||||
ldw = nb
|
ldw = nb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate n×n matrix A and fill it with random numbers.
|
||||||
a := make([]float64, n*lda)
|
a := make([]float64, n*lda)
|
||||||
for i := range a {
|
for i := range a {
|
||||||
a[i] = rnd.NormFloat64()
|
a[i] = rnd.NormFloat64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate output slices and matrix W and fill them
|
||||||
|
// with NaN. All their elements should be overwritten by
|
||||||
|
// Dlatrd.
|
||||||
e := make([]float64, n-1)
|
e := make([]float64, n-1)
|
||||||
for i := range e {
|
for i := range e {
|
||||||
e[i] = math.NaN()
|
e[i] = math.NaN()
|
||||||
@@ -63,30 +67,30 @@ func DlatrdTest(t *testing.T, impl Dlatrder) {
|
|||||||
aCopy := make([]float64, len(a))
|
aCopy := make([]float64, len(a))
|
||||||
copy(aCopy, a)
|
copy(aCopy, a)
|
||||||
|
|
||||||
|
// Reduce nb rows and columns of the symmetric matrix A
|
||||||
|
// defined by uplo triangle to symmetric tridiagonal
|
||||||
|
// form.
|
||||||
impl.Dlatrd(uplo, n, nb, a, lda, e, tau, w, ldw)
|
impl.Dlatrd(uplo, n, nb, a, lda, e, tau, w, ldw)
|
||||||
|
|
||||||
// Construct Q.
|
// Construct Q from elementary reflectors stored in
|
||||||
ldq := n
|
// columns of A.
|
||||||
q := blas64.General{
|
q := blas64.General{
|
||||||
Rows: n,
|
Rows: n,
|
||||||
Cols: n,
|
Cols: n,
|
||||||
Stride: ldq,
|
Stride: n,
|
||||||
Data: make([]float64, n*ldq),
|
Data: make([]float64, n*n),
|
||||||
}
|
}
|
||||||
|
// Initialize Q to the identity matrix.
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
q.Data[i*ldq+i] = 1
|
q.Data[i*q.Stride+i] = 1
|
||||||
}
|
}
|
||||||
if uplo == blas.Upper {
|
if uplo == blas.Upper {
|
||||||
for i := n - 1; i >= n-nb; i-- {
|
for i := n - 1; i >= n-nb; i-- {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
h := blas64.General{
|
|
||||||
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
// Extract the elementary reflector v from A.
|
||||||
}
|
|
||||||
for j := 0; j < n; j++ {
|
|
||||||
h.Data[j*n+j] = 1
|
|
||||||
}
|
|
||||||
v := blas64.Vector{
|
v := blas64.Vector{
|
||||||
Inc: 1,
|
Inc: 1,
|
||||||
Data: make([]float64, n),
|
Data: make([]float64, n),
|
||||||
@@ -96,8 +100,16 @@ func DlatrdTest(t *testing.T, impl Dlatrder) {
|
|||||||
}
|
}
|
||||||
v.Data[i-1] = 1
|
v.Data[i-1] = 1
|
||||||
|
|
||||||
|
// Compute H = I - tau[i-1] * v * v^T.
|
||||||
|
h := blas64.General{
|
||||||
|
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
||||||
|
}
|
||||||
|
for j := 0; j < n; j++ {
|
||||||
|
h.Data[j*n+j] = 1
|
||||||
|
}
|
||||||
blas64.Ger(-tau[i-1], v, v, h)
|
blas64.Ger(-tau[i-1], v, v, h)
|
||||||
|
|
||||||
|
// Update Q <- Q * H.
|
||||||
qTmp := blas64.General{
|
qTmp := blas64.General{
|
||||||
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
||||||
}
|
}
|
||||||
@@ -109,12 +121,8 @@ func DlatrdTest(t *testing.T, impl Dlatrder) {
|
|||||||
if i == n-1 {
|
if i == n-1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
h := blas64.General{
|
|
||||||
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
// Extract the elementary reflector v from A.
|
||||||
}
|
|
||||||
for j := 0; j < n; j++ {
|
|
||||||
h.Data[j*n+j] = 1
|
|
||||||
}
|
|
||||||
v := blas64.Vector{
|
v := blas64.Vector{
|
||||||
Inc: 1,
|
Inc: 1,
|
||||||
Data: make([]float64, n),
|
Data: make([]float64, n),
|
||||||
@@ -123,8 +131,17 @@ func DlatrdTest(t *testing.T, impl Dlatrder) {
|
|||||||
for j := i + 2; j < n; j++ {
|
for j := i + 2; j < n; j++ {
|
||||||
v.Data[j] = a[j*lda+i]
|
v.Data[j] = a[j*lda+i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute H = I - tau[i] * v * v^T.
|
||||||
|
h := blas64.General{
|
||||||
|
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
||||||
|
}
|
||||||
|
for j := 0; j < n; j++ {
|
||||||
|
h.Data[j*n+j] = 1
|
||||||
|
}
|
||||||
blas64.Ger(-tau[i], v, v, h)
|
blas64.Ger(-tau[i], v, v, h)
|
||||||
|
|
||||||
|
// Update Q <- Q * H.
|
||||||
qTmp := blas64.General{
|
qTmp := blas64.General{
|
||||||
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n),
|
||||||
}
|
}
|
||||||
@@ -134,11 +151,11 @@ func DlatrdTest(t *testing.T, impl Dlatrder) {
|
|||||||
}
|
}
|
||||||
errStr := fmt.Sprintf("isUpper = %v, n = %v, nb = %v", uplo == blas.Upper, n, nb)
|
errStr := fmt.Sprintf("isUpper = %v, n = %v, nb = %v", uplo == blas.Upper, n, nb)
|
||||||
if !isOrthogonal(q) {
|
if !isOrthogonal(q) {
|
||||||
t.Errorf("Q not orthogonal. %s", errStr)
|
t.Errorf("Case %v: Q not orthogonal", errStr)
|
||||||
}
|
}
|
||||||
aGen := genFromSym(blas64.Symmetric{N: n, Stride: lda, Uplo: uplo, Data: aCopy})
|
aGen := genFromSym(blas64.Symmetric{N: n, Stride: lda, Uplo: uplo, Data: aCopy})
|
||||||
if !dlatrdCheckDecomposition(t, uplo, n, nb, e, tau, a, lda, aGen, q) {
|
if !dlatrdCheckDecomposition(t, uplo, n, nb, e, a, lda, aGen, q) {
|
||||||
t.Errorf("Decomposition mismatch. %s", errStr)
|
t.Errorf("Case %v: Decomposition mismatch", errStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,44 +163,49 @@ func DlatrdTest(t *testing.T, impl Dlatrder) {
|
|||||||
|
|
||||||
// dlatrdCheckDecomposition checks that the first nb rows have been successfully
|
// dlatrdCheckDecomposition checks that the first nb rows have been successfully
|
||||||
// reduced.
|
// reduced.
|
||||||
func dlatrdCheckDecomposition(t *testing.T, uplo blas.Uplo, n, nb int, e, tau, a []float64, lda int, aGen, q blas64.General) bool {
|
func dlatrdCheckDecomposition(t *testing.T, uplo blas.Uplo, n, nb int, e, a []float64, lda int, aGen, q blas64.General) bool {
|
||||||
// Compute Q^T * A * Q.
|
// Compute ans = Q^T * A * Q.
|
||||||
|
// ans should be a tridiagonal matrix in the first or last nb rows and
|
||||||
|
// columns, depending on uplo.
|
||||||
tmp := blas64.General{
|
tmp := blas64.General{
|
||||||
Rows: n,
|
Rows: n,
|
||||||
Cols: n,
|
Cols: n,
|
||||||
Stride: n,
|
Stride: n,
|
||||||
Data: make([]float64, n*n),
|
Data: make([]float64, n*n),
|
||||||
}
|
}
|
||||||
|
|
||||||
ans := blas64.General{
|
ans := blas64.General{
|
||||||
Rows: n,
|
Rows: n,
|
||||||
Cols: n,
|
Cols: n,
|
||||||
Stride: n,
|
Stride: n,
|
||||||
Data: make([]float64, n*n),
|
Data: make([]float64, n*n),
|
||||||
}
|
}
|
||||||
|
|
||||||
blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aGen, 0, tmp)
|
blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aGen, 0, tmp)
|
||||||
blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, ans)
|
blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, ans)
|
||||||
|
|
||||||
// Compare with T.
|
// Compare the output of Dlatrd (stored in a and e) with the explicit
|
||||||
|
// reduction to tridiagonal matrix Q^T * A * Q (stored in ans).
|
||||||
if uplo == blas.Upper {
|
if uplo == blas.Upper {
|
||||||
for i := n - 1; i >= n-nb; i-- {
|
for i := n - nb; i < n; i++ {
|
||||||
for j := 0; j < n; j++ {
|
for j := 0; j < n; j++ {
|
||||||
v := ans.Data[i*ans.Stride+j]
|
v := ans.Data[i*ans.Stride+j]
|
||||||
switch {
|
switch {
|
||||||
case i == j:
|
case i == j:
|
||||||
|
// Diagonal elements of a and ans should match.
|
||||||
if math.Abs(v-a[i*lda+j]) > 1e-10 {
|
if math.Abs(v-a[i*lda+j]) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case i == j-1:
|
case i == j-1:
|
||||||
|
// Superdiagonal elements in a should be 1.
|
||||||
if math.Abs(a[i*lda+j]-1) > 1e-10 {
|
if math.Abs(a[i*lda+j]-1) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// Superdiagonal elements of ans should match e.
|
||||||
if math.Abs(v-e[i]) > 1e-10 {
|
if math.Abs(v-e[i]) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case i == j+1:
|
case i == j+1:
|
||||||
default:
|
default:
|
||||||
|
// All other elements should be 0.
|
||||||
if math.Abs(v) > 1e-10 {
|
if math.Abs(v) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -196,18 +218,22 @@ func dlatrdCheckDecomposition(t *testing.T, uplo blas.Uplo, n, nb int, e, tau, a
|
|||||||
v := ans.Data[i*ans.Stride+j]
|
v := ans.Data[i*ans.Stride+j]
|
||||||
switch {
|
switch {
|
||||||
case i == j:
|
case i == j:
|
||||||
|
// Diagonal elements of a and ans should match.
|
||||||
if math.Abs(v-a[i*lda+j]) > 1e-10 {
|
if math.Abs(v-a[i*lda+j]) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case i == j-1:
|
case i == j-1:
|
||||||
case i == j+1:
|
case i == j+1:
|
||||||
|
// Subdiagonal elements in a should be 1.
|
||||||
if math.Abs(a[i*lda+j]-1) > 1e-10 {
|
if math.Abs(a[i*lda+j]-1) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// Subdiagonal elements of ans should match e.
|
||||||
if math.Abs(v-e[i-1]) > 1e-10 {
|
if math.Abs(v-e[i-1]) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
// All other elements should be 0.
|
||||||
if math.Abs(v) > 1e-10 {
|
if math.Abs(v) > 1e-10 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user