dgeqr2.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Copyright ©2015 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. // Dgeqr2 computes a QR factorization of the m×n matrix A.
  7. //
  8. // In a QR factorization, Q is an m×m orthonormal matrix, and R is an
  9. // upper triangular m×n matrix.
  10. //
  11. // A is modified to contain the information to construct Q and R.
  12. // The upper triangle of a contains the matrix R. The lower triangular elements
  13. // (not including the diagonal) contain the elementary reflectors. tau is modified
  14. // to contain the reflector scales. tau must have length at least min(m,n), and
  15. // this function will panic otherwise.
  16. //
  17. // The ith elementary reflector can be explicitly constructed by first extracting
  18. // the
  19. // v[j] = 0 j < i
  20. // v[j] = 1 j == i
  21. // v[j] = a[j*lda+i] j > i
  22. // and computing H_i = I - tau[i] * v * vᵀ.
  23. //
  24. // The orthonormal matrix Q can be constructed from a product of these elementary
  25. // reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n).
  26. //
  27. // work is temporary storage of length at least n and this function will panic otherwise.
  28. //
  29. // Dgeqr2 is an internal routine. It is exported for testing purposes.
  30. func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []float64) {
  31. // TODO(btracey): This is oriented such that columns of a are eliminated.
  32. // This likely could be re-arranged to take better advantage of row-major
  33. // storage.
  34. switch {
  35. case m < 0:
  36. panic(mLT0)
  37. case n < 0:
  38. panic(nLT0)
  39. case lda < max(1, n):
  40. panic(badLdA)
  41. case len(work) < n:
  42. panic(shortWork)
  43. }
  44. // Quick return if possible.
  45. k := min(m, n)
  46. if k == 0 {
  47. return
  48. }
  49. switch {
  50. case len(a) < (m-1)*lda+n:
  51. panic(shortA)
  52. case len(tau) < k:
  53. panic(shortTau)
  54. }
  55. for i := 0; i < k; i++ {
  56. // Generate elementary reflector H_i.
  57. a[i*lda+i], tau[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min((i+1), m-1)*lda+i:], lda)
  58. if i < n-1 {
  59. aii := a[i*lda+i]
  60. a[i*lda+i] = 1
  61. impl.Dlarf(blas.Left, m-i, n-i-1,
  62. a[i*lda+i:], lda,
  63. tau[i],
  64. a[i*lda+i+1:], lda,
  65. work)
  66. a[i*lda+i] = aii
  67. }
  68. }
  69. }