dgehd2.go 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. package gonum
  5. import "gonum.org/v1/gonum/blas"
  6. // Dgehd2 reduces a block of a general n×n matrix A to upper Hessenberg form H
  7. // by an orthogonal similarity transformation Qᵀ * A * Q = H.
  8. //
  9. // The matrix Q is represented as a product of (ihi-ilo) elementary
  10. // reflectors
  11. // Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}.
  12. // Each H_i has the form
  13. // H_i = I - tau[i] * v * vᵀ
  14. // where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0.
  15. // v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i].
  16. //
  17. // On entry, a contains the n×n general matrix to be reduced. On return, the
  18. // upper triangle and the first subdiagonal of A are overwritten with the upper
  19. // Hessenberg matrix H, and the elements below the first subdiagonal, with the
  20. // slice tau, represent the orthogonal matrix Q as a product of elementary
  21. // reflectors.
  22. //
  23. // The contents of A are illustrated by the following example, with n = 7, ilo =
  24. // 1 and ihi = 5.
  25. // On entry,
  26. // [ a a a a a a a ]
  27. // [ a a a a a a ]
  28. // [ a a a a a a ]
  29. // [ a a a a a a ]
  30. // [ a a a a a a ]
  31. // [ a a a a a a ]
  32. // [ a ]
  33. // on return,
  34. // [ a a h h h h a ]
  35. // [ a h h h h a ]
  36. // [ h h h h h h ]
  37. // [ v1 h h h h h ]
  38. // [ v1 v2 h h h h ]
  39. // [ v1 v2 v3 h h h ]
  40. // [ a ]
  41. // where a denotes an element of the original matrix A, h denotes a
  42. // modified element of the upper Hessenberg matrix H, and vi denotes an
  43. // element of the vector defining H_i.
  44. //
  45. // ilo and ihi determine the block of A that will be reduced to upper Hessenberg
  46. // form. It must hold that 0 <= ilo <= ihi <= max(0, n-1), otherwise Dgehd2 will
  47. // panic.
  48. //
  49. // On return, tau will contain the scalar factors of the elementary reflectors.
  50. // It must have length equal to n-1, otherwise Dgehd2 will panic.
  51. //
  52. // work must have length at least n, otherwise Dgehd2 will panic.
  53. //
  54. // Dgehd2 is an internal routine. It is exported for testing purposes.
  55. func (impl Implementation) Dgehd2(n, ilo, ihi int, a []float64, lda int, tau, work []float64) {
  56. switch {
  57. case n < 0:
  58. panic(nLT0)
  59. case ilo < 0 || max(0, n-1) < ilo:
  60. panic(badIlo)
  61. case ihi < min(ilo, n-1) || n <= ihi:
  62. panic(badIhi)
  63. case lda < max(1, n):
  64. panic(badLdA)
  65. }
  66. // Quick return if possible.
  67. if n == 0 {
  68. return
  69. }
  70. switch {
  71. case len(a) < (n-1)*lda+n:
  72. panic(shortA)
  73. case len(tau) != n-1:
  74. panic(badLenTau)
  75. case len(work) < n:
  76. panic(shortWork)
  77. }
  78. for i := ilo; i < ihi; i++ {
  79. // Compute elementary reflector H_i to annihilate A[i+2:ihi+1,i].
  80. var aii float64
  81. aii, tau[i] = impl.Dlarfg(ihi-i, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda)
  82. a[(i+1)*lda+i] = 1
  83. // Apply H_i to A[0:ihi+1,i+1:ihi+1] from the right.
  84. impl.Dlarf(blas.Right, ihi+1, ihi-i, a[(i+1)*lda+i:], lda, tau[i], a[i+1:], lda, work)
  85. // Apply H_i to A[i+1:ihi+1,i+1:n] from the left.
  86. impl.Dlarf(blas.Left, ihi-i, n-i-1, a[(i+1)*lda+i:], lda, tau[i], a[(i+1)*lda+i+1:], lda, work)
  87. a[(i+1)*lda+i] = aii
  88. }
  89. }