mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 23:26:52 +08:00
83 lines
1.7 KiB
Go
83 lines
1.7 KiB
Go
// Copyright ©2015 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 native
|
||
|
||
import "math"
|
||
|
||
// Dlaev2 computes the Eigen decomposition of a symmetric 2×2 matrix.
|
||
// The matrix is given by
|
||
// [a b]
|
||
// [b c]
|
||
// Dlaev2 returns rt1 and rt2, the eigenvalues of the matrix where |RT1| > |RT2|,
|
||
// and [cs1, sn1] which is the unit right eigenvalue for RT1.
|
||
// [ cs1 sn1] [a b] [cs1 -sn1] = [rt1 0]
|
||
// [-sn1 cs1] [b c] [sn1 cs1] [ 0 rt2]
|
||
//
|
||
// Dlaev2 is an internal routine. It is exported for testing purposes.
|
||
func (impl Implementation) Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) {
|
||
sm := a + c
|
||
df := a - c
|
||
adf := math.Abs(df)
|
||
tb := b + b
|
||
ab := math.Abs(tb)
|
||
acmx := c
|
||
acmn := a
|
||
if math.Abs(a) > math.Abs(c) {
|
||
acmx = a
|
||
acmn = c
|
||
}
|
||
var rt float64
|
||
if adf > ab {
|
||
rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf))
|
||
} else if adf < ab {
|
||
rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab))
|
||
} else {
|
||
rt = ab * math.Sqrt(2)
|
||
}
|
||
var sgn1 float64
|
||
if sm < 0 {
|
||
rt1 = 0.5 * (sm - rt)
|
||
sgn1 = -1
|
||
rt2 = (acmx/rt1)*acmn - (b/rt1)*b
|
||
} else if sm > 0 {
|
||
rt1 = 0.5 * (sm + rt)
|
||
sgn1 = 1
|
||
rt2 = (acmx/rt1)*acmn - (b/rt1)*b
|
||
} else {
|
||
rt1 = 0.5 * rt
|
||
rt2 = -0.5 * rt
|
||
sgn1 = 1
|
||
}
|
||
var cs, sgn2 float64
|
||
if df >= 0 {
|
||
cs = df + rt
|
||
sgn2 = 1
|
||
} else {
|
||
cs = df - rt
|
||
sgn2 = -1
|
||
}
|
||
acs := math.Abs(cs)
|
||
if acs > ab {
|
||
ct := -tb / cs
|
||
sn1 = 1 / math.Sqrt(1+ct*ct)
|
||
cs1 = ct * sn1
|
||
} else {
|
||
if ab == 0 {
|
||
cs1 = 1
|
||
sn1 = 0
|
||
} else {
|
||
tn := -cs / tb
|
||
cs1 = 1 / math.Sqrt(1+tn*tn)
|
||
sn1 = tn * cs1
|
||
}
|
||
}
|
||
if sgn1 == sgn2 {
|
||
tn := cs1
|
||
cs1 = -sn1
|
||
sn1 = tn
|
||
}
|
||
return rt1, rt2, cs1, sn1
|
||
}
|