133 lines
3.1 KiB
Go
133 lines
3.1 KiB
Go
|
|
// Copyright ©2016 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"
|
|||
|
|
|
|||
|
|
// Dlanv2 computes the Schur factorization of a real 2×2 matrix:
|
|||
|
|
// [ a b ] = [ cs -sn ] * [ aa bb ] * [ cs sn ]
|
|||
|
|
// [ c d ] [ sn cs ] [ cc dd ] * [-sn cs ]
|
|||
|
|
// If cc is zero, aa and dd are real eigenvalues of the matrix. Otherwise it
|
|||
|
|
// holds that aa = dd and bb*cc < 0, and aa ± sqrt(bb*cc) are complex conjugate
|
|||
|
|
// eigenvalues. The real and imaginary parts of the eigenvalues are returned in
|
|||
|
|
// (rt1r,rt1i) and (rt2r,rt2i).
|
|||
|
|
func (impl Implementation) Dlanv2(a, b, c, d float64) (aa, bb, cc, dd float64, rt1r, rt1i, rt2r, rt2i float64, cs, sn float64) {
|
|||
|
|
switch {
|
|||
|
|
case c == 0: // Matrix is already upper triangular.
|
|||
|
|
aa = a
|
|||
|
|
bb = b
|
|||
|
|
cc = 0
|
|||
|
|
dd = d
|
|||
|
|
cs = 1
|
|||
|
|
sn = 0
|
|||
|
|
case b == 0: // Matrix is lower triangular, swap rows and columns.
|
|||
|
|
aa = d
|
|||
|
|
bb = -c
|
|||
|
|
cc = 0
|
|||
|
|
dd = a
|
|||
|
|
cs = 0
|
|||
|
|
sn = 1
|
|||
|
|
case a == d && math.Signbit(b) != math.Signbit(c): // Matrix is already in the standard Schur form.
|
|||
|
|
aa = a
|
|||
|
|
bb = b
|
|||
|
|
cc = c
|
|||
|
|
dd = d
|
|||
|
|
cs = 1
|
|||
|
|
sn = 0
|
|||
|
|
default:
|
|||
|
|
temp := a - d
|
|||
|
|
p := temp / 2
|
|||
|
|
bcmax := math.Max(math.Abs(b), math.Abs(c))
|
|||
|
|
bcmis := math.Min(math.Abs(b), math.Abs(c))
|
|||
|
|
if b*c < 0 {
|
|||
|
|
bcmis *= -1
|
|||
|
|
}
|
|||
|
|
scale := math.Max(math.Abs(p), bcmax)
|
|||
|
|
z := p/scale*p + bcmax/scale*bcmis
|
|||
|
|
eps := dlamchP
|
|||
|
|
|
|||
|
|
if z >= 4*eps {
|
|||
|
|
// Real eigenvalues. Compute aa and dd.
|
|||
|
|
if p > 0 {
|
|||
|
|
z = p + math.Sqrt(scale)*math.Sqrt(z)
|
|||
|
|
} else {
|
|||
|
|
z = p - math.Sqrt(scale)*math.Sqrt(z)
|
|||
|
|
}
|
|||
|
|
aa = d + z
|
|||
|
|
dd = d - bcmax/z*bcmis
|
|||
|
|
// Compute bb and the rotation matrix.
|
|||
|
|
tau := impl.Dlapy2(c, z)
|
|||
|
|
cs = z / tau
|
|||
|
|
sn = c / tau
|
|||
|
|
bb = b - c
|
|||
|
|
cc = 0
|
|||
|
|
} else {
|
|||
|
|
// Complex eigenvalues, or real (almost) equal eigenvalues.
|
|||
|
|
// Make diagonal elements equal.
|
|||
|
|
sigma := b + c
|
|||
|
|
tau := impl.Dlapy2(sigma, temp)
|
|||
|
|
cs = math.Sqrt((1 + math.Abs(sigma)/tau) / 2)
|
|||
|
|
sn = -p / (tau * cs)
|
|||
|
|
if sigma < 0 {
|
|||
|
|
sn *= -1
|
|||
|
|
}
|
|||
|
|
// Compute [ aa bb ] = [ a b ] [ cs -sn ]
|
|||
|
|
// [ cc dd ] [ c d ] [ sn cs ]
|
|||
|
|
aa = a*cs + b*sn
|
|||
|
|
bb = -a*sn + b*cs
|
|||
|
|
cc = c*cs + d*sn
|
|||
|
|
dd = -c*sn + d*cs
|
|||
|
|
// Compute [ a b ] = [ cs sn ] [ aa bb ]
|
|||
|
|
// [ c d ] [-sn cs ] [ cc dd ]
|
|||
|
|
a = aa*cs + cc*sn
|
|||
|
|
b = bb*cs + dd*sn
|
|||
|
|
c = -aa*sn + cc*cs
|
|||
|
|
d = -bb*sn + dd*cs
|
|||
|
|
|
|||
|
|
temp = (a + d) / 2
|
|||
|
|
aa = temp
|
|||
|
|
bb = b
|
|||
|
|
cc = c
|
|||
|
|
dd = temp
|
|||
|
|
|
|||
|
|
if cc != 0 {
|
|||
|
|
if bb != 0 {
|
|||
|
|
if math.Signbit(bb) == math.Signbit(cc) {
|
|||
|
|
// Real eigenvalues, reduce to
|
|||
|
|
// upper triangular form.
|
|||
|
|
sab := math.Sqrt(math.Abs(bb))
|
|||
|
|
sac := math.Sqrt(math.Abs(cc))
|
|||
|
|
p = sab * sac
|
|||
|
|
if cc < 0 {
|
|||
|
|
p *= -1
|
|||
|
|
}
|
|||
|
|
tau = 1 / math.Sqrt(math.Abs(bb+cc))
|
|||
|
|
aa = temp + p
|
|||
|
|
bb = bb - cc
|
|||
|
|
cc = 0
|
|||
|
|
dd = temp - p
|
|||
|
|
cs1 := sab * tau
|
|||
|
|
sn1 := sac * tau
|
|||
|
|
cs, sn = cs*cs1-sn*sn1, cs*sn1+sn+cs1
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
bb = -cc
|
|||
|
|
cc = 0
|
|||
|
|
cs, sn = -sn, cs
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Store eigenvalues in (rt1r,rt1i) and (rt2r,rt2i).
|
|||
|
|
rt1r = aa
|
|||
|
|
rt2r = dd
|
|||
|
|
if cc != 0 {
|
|||
|
|
rt1i = math.Sqrt(math.Abs(bb)) * math.Sqrt(math.Abs(cc))
|
|||
|
|
rt2i = -rt1i
|
|||
|
|
}
|
|||
|
|
return
|
|||
|
|
}
|