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