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 115
|
// Copyright ©2020 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/lapack"
)
// Dlangt returns the value of the given norm of an n×n tridiagonal matrix
// represented by the three diagonals.
//
// d must have length at least n and dl and du must have length at least n-1.
func (impl Implementation) Dlangt(norm lapack.MatrixNorm, n int, dl, d, du []float64) float64 {
switch {
case norm != lapack.MaxAbs && norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius:
panic(badNorm)
case n < 0:
panic(nLT0)
}
if n == 0 {
return 0
}
switch {
case len(dl) < n-1:
panic(shortDL)
case len(d) < n:
panic(shortD)
case len(du) < n-1:
panic(shortDU)
}
dl = dl[:n-1]
d = d[:n]
du = du[:n-1]
var anorm float64
switch norm {
case lapack.MaxAbs:
for _, diag := range [][]float64{dl, d, du} {
for _, di := range diag {
if math.IsNaN(di) {
return di
}
di = math.Abs(di)
if di > anorm {
anorm = di
}
}
}
case lapack.MaxColumnSum:
if n == 1 {
return math.Abs(d[0])
}
anorm = math.Abs(d[0]) + math.Abs(dl[0])
if math.IsNaN(anorm) {
return anorm
}
tmp := math.Abs(du[n-2]) + math.Abs(d[n-1])
if math.IsNaN(tmp) {
return tmp
}
if tmp > anorm {
anorm = tmp
}
for i := 1; i < n-1; i++ {
tmp = math.Abs(du[i-1]) + math.Abs(d[i]) + math.Abs(dl[i])
if math.IsNaN(tmp) {
return tmp
}
if tmp > anorm {
anorm = tmp
}
}
case lapack.MaxRowSum:
if n == 1 {
return math.Abs(d[0])
}
anorm = math.Abs(d[0]) + math.Abs(du[0])
if math.IsNaN(anorm) {
return anorm
}
tmp := math.Abs(dl[n-2]) + math.Abs(d[n-1])
if math.IsNaN(tmp) {
return tmp
}
if tmp > anorm {
anorm = tmp
}
for i := 1; i < n-1; i++ {
tmp = math.Abs(dl[i-1]) + math.Abs(d[i]) + math.Abs(du[i])
if math.IsNaN(tmp) {
return tmp
}
if tmp > anorm {
anorm = tmp
}
}
case lapack.Frobenius:
scale := 0.0
ssq := 1.0
scale, ssq = impl.Dlassq(n, d, 1, scale, ssq)
if n > 1 {
scale, ssq = impl.Dlassq(n-1, dl, 1, scale, ssq)
scale, ssq = impl.Dlassq(n-1, du, 1, scale, ssq)
}
anorm = scale * math.Sqrt(ssq)
}
return anorm
}
|