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