github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/native/dsytd2.go (about) 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. 4 5 package native 6 7 import ( 8 "github.com/gonum/blas" 9 "github.com/gonum/blas/blas64" 10 ) 11 12 // Dsytd2 reduces a symmetric n×n matrix A to symmetric tridiagonal form T by an 13 // orthogonal similarity transformation 14 // Q^T * A * Q = T 15 // On entry, the matrix is contained in the specified triangle of a. On exit, 16 // if uplo == blas.Upper, the diagonal and first super-diagonal of a are 17 // overwritten with the elements of T. The elements above the first super-diagonal 18 // are overwritten with the the elementary reflectors that are used with the 19 // elements written to tau in order to construct Q. If uplo == blas.Lower, the 20 // elements are written in the lower triangular region. 21 // 22 // d must have length at least n. e and tau must have length at least n-1. Dsytd2 23 // will panic if these sizes are not met. 24 // 25 // Q is represented as a product of elementary reflectors. 26 // If uplo == blas.Upper 27 // Q = H_{n-2} * ... * H_1 * H_0 28 // and if uplo == blas.Lower 29 // Q = H_0 * H_1 * ... * H_{n-2} 30 // where 31 // H_i = I - tau * v * v^T 32 // where tau is stored in tau[i], and v is stored in a. 33 // 34 // If uplo == blas.Upper, v[0:i-1] is stored in A[0:i-1,i+1], v[i] = 1, and 35 // v[i+1:] = 0. The elements of a are 36 // [ d e v2 v3 v4] 37 // [ d e v3 v4] 38 // [ d e v4] 39 // [ d e] 40 // [ d] 41 // If uplo == blas.Lower, v[0:i+1] = 0, v[i+1] = 1, and v[i+2:] is stored in 42 // A[i+2:n,i]. 43 // The elements of a are 44 // [ d ] 45 // [ e d ] 46 // [v1 e d ] 47 // [v1 v2 e d ] 48 // [v1 v2 v3 e d] 49 // 50 // Dsytd2 is an internal routine. It is exported for testing purposes. 51 func (impl Implementation) Dsytd2(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau []float64) { 52 checkMatrix(n, n, a, lda) 53 if len(d) < n { 54 panic(badD) 55 } 56 if len(e) < n-1 { 57 panic(badE) 58 } 59 if len(tau) < n-1 { 60 panic(badTau) 61 } 62 if n <= 0 { 63 return 64 } 65 bi := blas64.Implementation() 66 if uplo == blas.Upper { 67 // Reduce the upper triangle of A. 68 for i := n - 2; i >= 0; i-- { 69 // Generate elementary reflector H_i = I - tau * v * v^T to 70 // annihilate A[i:i-1, i+1]. 71 var taui float64 72 a[i*lda+i+1], taui = impl.Dlarfg(i+1, a[i*lda+i+1], a[i+1:], lda) 73 e[i] = a[i*lda+i+1] 74 if taui != 0 { 75 // Apply H_i from both sides to A[0:i,0:i]. 76 a[i*lda+i+1] = 1 77 78 // Compute x := tau * A * v storing x in tau[0:i]. 79 bi.Dsymv(uplo, i+1, taui, a, lda, a[i+1:], lda, 0, tau, 1) 80 81 // Compute w := x - 1/2 * tau * (x^T * v) * v. 82 alpha := -0.5 * taui * bi.Ddot(i+1, tau, 1, a[i+1:], lda) 83 bi.Daxpy(i+1, alpha, a[i+1:], lda, tau, 1) 84 85 // Apply the transformation as a rank-2 update 86 // A = A - v * w^T - w * v^T. 87 bi.Dsyr2(uplo, i+1, -1, a[i+1:], lda, tau, 1, a, lda) 88 a[i*lda+i+1] = e[i] 89 } 90 d[i+1] = a[(i+1)*lda+i+1] 91 tau[i] = taui 92 } 93 d[0] = a[0] 94 return 95 } 96 // Reduce the lower triangle of A. 97 for i := 0; i < n-1; i++ { 98 // Generate elementary reflector H_i = I - tau * v * v^T to 99 // annihilate A[i+2:n, i]. 100 var taui float64 101 a[(i+1)*lda+i], taui = impl.Dlarfg(n-i-1, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) 102 e[i] = a[(i+1)*lda+i] 103 if taui != 0 { 104 // Apply H_i from both sides to A[i+1:n, i+1:n]. 105 a[(i+1)*lda+i] = 1 106 107 // Compute x := tau * A * v, storing y in tau[i:n-1]. 108 bi.Dsymv(uplo, n-i-1, taui, a[(i+1)*lda+i+1:], lda, a[(i+1)*lda+i:], lda, 0, tau[i:], 1) 109 110 // Compute w := x - 1/2 * tau * (x^T * v) * v. 111 alpha := -0.5 * taui * bi.Ddot(n-i-1, tau[i:], 1, a[(i+1)*lda+i:], lda) 112 bi.Daxpy(n-i-1, alpha, a[(i+1)*lda+i:], lda, tau[i:], 1) 113 114 // Apply the transformation as a rank-2 update 115 // A = A - v * w^T - w * v^T. 116 bi.Dsyr2(uplo, n-i-1, -1, a[(i+1)*lda+i:], lda, tau[i:], 1, a[(i+1)*lda+i+1:], lda) 117 a[(i+1)*lda+i] = e[i] 118 } 119 d[i] = a[i*lda+i] 120 tau[i] = taui 121 } 122 d[n-1] = a[(n-1)*lda+n-1] 123 }