このプログラム
program bug
implicit none
double precision :: H1(4, 4), H2(4, 4), wr1(4), wi1(4), wr2(4), wi2(4), Z, work(10), dble, epsilon
integer*8 :: info
H1(:,:) = 0
H1(2, 1) = dble(z'bfdf916d32df0e1d')
H1(3, 2) = dble(z'bf782807624514d9')
H1(4, 3) = dble(z'bf80d94d89578784')
H1(1, 2) = dble(z'3fdf916d32df0e1d')
H1(2, 3) = dble(z'3f782807624514da')
H1(3, 4) = dble(z'3f80d94d89578784')
H2(:,:) = H1
H2(4,4) = epsilon(H2(4,4))
call dhseqr('E', 'N', 4_8, 1_8, 4_8, H1, 4_8, wr1, wi1, Z, 1_8, work, 10, info)
call dhseqr('E', 'N', 4_8, 1_8, 4_8, H2, 4_8, wr2, wi2, Z, 1_8, work, 10, info)
write(*,*) 'wr1: ', wr1
write(*,*) 'wi1: ', wi1
write(*,*) 'wr2: ', wr2
write(*,*) 'wi2: ', wi2
end program bug
を生成します
wr1: 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
wi1: 0.73992959728054897 -0.73992959728054897 8.2263841908860064E-003 -8.2263841908860064E-003
wr2: 0.0000000000000000 0.0000000000000000 1.1102230246251565E-016 1.1102230246251565E-016
wi2: 0.49328639818703252 -0.49328639818703252 8.2263841908860116E-003 -8.2263841908860116E-003
LAPACK3.8を搭載した私のマシンで。
ここで条件付けの問題があるべきではないと思います。 収束基準は、ゼロ対角によって混乱する可能性があると思います。
私はこのバグにひびが入った。 よくわかりませんが、dlanv2のアンダーフロー/丸め誤差が原因のようです。
反復中に次のことが発生します。
最終的に、最初の2つの固有値に対して次のサブブロックが作成されます。
0.0000E+00 4.9329E-01
-4.9329E-01 -9.8813-324
DLANV2はこれを次のように変換します。
0.0000E+00 7.3993E-01
-7.3993E-01 0.0000E+00
原因は、DLANV2の218行目の丸め誤差です。CSはsqrt(0.5)であるため、SNもsqrt(0.5)である必要がありますが、代わりに-1になります。 2x2ブロックを正しく正規化するローテーションは言うまでもなく、有効なローテーションでさえありません。
実際、対角線のゼロ以外の小さな値は、計算を完全に台無しにしているようです
julia> eigvals([0.0 1.0; -1.0 0.0])
2-element Array{Complex{Float64},1}:
0.0 - 1.0im
0.0 + 1.0im
julia> eigvals([0.0 1.0; -1.0 nextfloat(0.0)])
2-element Array{Complex{Float64},1}:
0.0 - 0.5000000000000001im
0.0 + 0.5000000000000001im
julia> eigvals([0.0 1.0; -1.0 1e-310])
2-element Array{Complex{Float64},1}:
0.0 - 1.000000000000023im
0.0 + 1.000000000000023im