dpbtf2.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright ©2017 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 (
  6. "math"
  7. "gonum.org/v1/gonum/blas"
  8. "gonum.org/v1/gonum/blas/blas64"
  9. )
  10. // Dpbtf2 computes the Cholesky factorization of a symmetric positive banded
  11. // matrix ab. The matrix ab is n×n with kd diagonal bands. The Cholesky
  12. // factorization computed is
  13. // A = Uᵀ * U if ul == blas.Upper
  14. // A = L * Lᵀ if ul == blas.Lower
  15. // ul also specifies the storage of ab. If ul == blas.Upper, then
  16. // ab is stored as an upper-triangular banded matrix with kd super-diagonals,
  17. // and if ul == blas.Lower, ab is stored as a lower-triangular banded matrix
  18. // with kd sub-diagonals. On exit, the banded matrix U or L is stored in-place
  19. // into ab depending on the value of ul. Dpbtf2 returns whether the factorization
  20. // was successfully completed.
  21. //
  22. // The band storage scheme is illustrated below when n = 6, and kd = 2.
  23. // The resulting Cholesky decomposition is stored in the same elements as the
  24. // input band matrix (a11 becomes u11 or l11, etc.).
  25. //
  26. // ul = blas.Upper
  27. // a11 a12 a13
  28. // a22 a23 a24
  29. // a33 a34 a35
  30. // a44 a45 a46
  31. // a55 a56 *
  32. // a66 * *
  33. //
  34. // ul = blas.Lower
  35. // * * a11
  36. // * a21 a22
  37. // a31 a32 a33
  38. // a42 a43 a44
  39. // a53 a54 a55
  40. // a64 a65 a66
  41. //
  42. // Dpbtf2 is the unblocked version of the algorithm, see Dpbtrf for the blocked
  43. // version.
  44. //
  45. // Dpbtf2 is an internal routine, exported for testing purposes.
  46. func (Implementation) Dpbtf2(uplo blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) {
  47. switch {
  48. case uplo != blas.Upper && uplo != blas.Lower:
  49. panic(badUplo)
  50. case n < 0:
  51. panic(nLT0)
  52. case kd < 0:
  53. panic(kdLT0)
  54. case ldab < kd+1:
  55. panic(badLdA)
  56. }
  57. // Quick return if possible.
  58. if n == 0 {
  59. return true
  60. }
  61. if len(ab) < (n-1)*ldab+kd+1 {
  62. panic(shortAB)
  63. }
  64. bi := blas64.Implementation()
  65. kld := max(1, ldab-1)
  66. if uplo == blas.Upper {
  67. // Compute the Cholesky factorization A = Uᵀ * U.
  68. for j := 0; j < n; j++ {
  69. // Compute U(j,j) and test for non-positive-definiteness.
  70. ajj := ab[j*ldab]
  71. if ajj <= 0 {
  72. return false
  73. }
  74. ajj = math.Sqrt(ajj)
  75. ab[j*ldab] = ajj
  76. // Compute elements j+1:j+kn of row j and update the trailing submatrix
  77. // within the band.
  78. kn := min(kd, n-j-1)
  79. if kn > 0 {
  80. bi.Dscal(kn, 1/ajj, ab[j*ldab+1:], 1)
  81. bi.Dsyr(blas.Upper, kn, -1, ab[j*ldab+1:], 1, ab[(j+1)*ldab:], kld)
  82. }
  83. }
  84. return true
  85. }
  86. // Compute the Cholesky factorization A = L * Lᵀ.
  87. for j := 0; j < n; j++ {
  88. // Compute L(j,j) and test for non-positive-definiteness.
  89. ajj := ab[j*ldab+kd]
  90. if ajj <= 0 {
  91. return false
  92. }
  93. ajj = math.Sqrt(ajj)
  94. ab[j*ldab+kd] = ajj
  95. // Compute elements j+1:j+kn of column j and update the trailing submatrix
  96. // within the band.
  97. kn := min(kd, n-j-1)
  98. if kn > 0 {
  99. bi.Dscal(kn, 1/ajj, ab[(j+1)*ldab+kd-1:], kld)
  100. bi.Dsyr(blas.Lower, kn, -1, ab[(j+1)*ldab+kd-1:], kld, ab[(j+1)*ldab+kd:], kld)
  101. }
  102. }
  103. return true
  104. }