File: dpbtf2.go

package info (click to toggle)
golang-gonum-v1-gonum 0.15.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 18,792 kB
  • sloc: asm: 6,252; fortran: 5,271; sh: 377; ruby: 211; makefile: 98
file content (114 lines) | stat: -rw-r--r-- 3,038 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright ©2017 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gonum

import (
	"math"

	"gonum.org/v1/gonum/blas"
	"gonum.org/v1/gonum/blas/blas64"
)

// Dpbtf2 computes the Cholesky factorization of a symmetric positive banded
// matrix ab. The matrix ab is n×n with kd diagonal bands. The Cholesky
// factorization computed is
//
//	A = Uᵀ * U  if ul == blas.Upper
//	A = L * Lᵀ  if ul == blas.Lower
//
// ul also specifies the storage of ab. If ul == blas.Upper, then
// ab is stored as an upper-triangular banded matrix with kd super-diagonals,
// and if ul == blas.Lower, ab is stored as a lower-triangular banded matrix
// with kd sub-diagonals. On exit, the banded matrix U or L is stored in-place
// into ab depending on the value of ul. Dpbtf2 returns whether the factorization
// was successfully completed.
//
// The band storage scheme is illustrated below when n = 6, and kd = 2.
// The resulting Cholesky decomposition is stored in the same elements as the
// input band matrix (a11 becomes u11 or l11, etc.).
//
//	ul = blas.Upper
//	a11 a12 a13
//	a22 a23 a24
//	a33 a34 a35
//	a44 a45 a46
//	a55 a56  *
//	a66  *   *
//
//	ul = blas.Lower
//	 *   *  a11
//	 *  a21 a22
//	a31 a32 a33
//	a42 a43 a44
//	a53 a54 a55
//	a64 a65 a66
//
// Dpbtf2 is the unblocked version of the algorithm, see Dpbtrf for the blocked
// version.
//
// Dpbtf2 is an internal routine, exported for testing purposes.
func (Implementation) Dpbtf2(uplo blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) {
	switch {
	case uplo != blas.Upper && uplo != blas.Lower:
		panic(badUplo)
	case n < 0:
		panic(nLT0)
	case kd < 0:
		panic(kdLT0)
	case ldab < kd+1:
		panic(badLdA)
	}

	// Quick return if possible.
	if n == 0 {
		return true
	}

	if len(ab) < (n-1)*ldab+kd+1 {
		panic(shortAB)
	}

	bi := blas64.Implementation()

	kld := max(1, ldab-1)
	if uplo == blas.Upper {
		// Compute the Cholesky factorization A = Uᵀ * U.
		for j := 0; j < n; j++ {
			// Compute U(j,j) and test for non-positive-definiteness.
			ajj := ab[j*ldab]
			if ajj <= 0 {
				return false
			}
			ajj = math.Sqrt(ajj)
			ab[j*ldab] = ajj
			// Compute elements j+1:j+kn of row j and update the trailing submatrix
			// within the band.
			kn := min(kd, n-j-1)
			if kn > 0 {
				bi.Dscal(kn, 1/ajj, ab[j*ldab+1:], 1)
				bi.Dsyr(blas.Upper, kn, -1, ab[j*ldab+1:], 1, ab[(j+1)*ldab:], kld)
			}
		}
		return true
	}
	// Compute the Cholesky factorization A = L * Lᵀ.
	for j := 0; j < n; j++ {
		// Compute L(j,j) and test for non-positive-definiteness.
		ajj := ab[j*ldab+kd]
		if ajj <= 0 {
			return false
		}
		ajj = math.Sqrt(ajj)
		ab[j*ldab+kd] = ajj
		// Compute elements j+1:j+kn of column j and update the trailing submatrix
		// within the band.
		kn := min(kd, n-j-1)
		if kn > 0 {
			bi.Dscal(kn, 1/ajj, ab[(j+1)*ldab+kd-1:], kld)
			bi.Dsyr(blas.Lower, kn, -1, ab[(j+1)*ldab+kd-1:], kld, ab[(j+1)*ldab+kd:], kld)
		}
	}
	return true
}