Lapack: dhseqr 给出错误的结果

创建于 2018-07-05  ·  2评论  ·  资料来源: Reference-LAPACK/lapack

这个节目

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

在我装有 LAPACK 3.8 的机器上。

我不认为这里应该有条件问题。 我想收敛标准可能会被零对角线混淆。

High Bug

所有2条评论

我已经破解了这个错误。 我不确定,但看起来它是由 dlanv2 中的下溢/舍入错误引起的。

在迭代过程中会发生以下情况:

  • 如果移位是纯虚的,则结构将被保留
  • 因为我们与对角线元素进行比较,我们需要 H(3,2) 低于 sfmin 才能获得通货紧缩
  • 在 10 次迭代后,我们使用临时偏移(这不是纯虚构的)并得到通货紧缩

对于前 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
此页面是否有帮助?
0 / 5 - 0 等级