Julia: Inverse of a SVD factorization of a complex matrix broken in Julia 1.3

Created on 25 Feb 2020  路  10Comments  路  Source: JuliaLang/julia

On Julia 1.1:

julia> using LinearAlgebra

julia> inv(svd(rand(ComplexF64,2,2)))
2脳2 Array{Complex{Float64},2}:
 -1.03305+2.82321im  -1.07298-3.37716im
 0.623141-1.89883im  0.946827+1.23427im

On Julia 1.3:

julia> using LinearAlgebra

julia> inv(svd(rand(ComplexF64,2,2)))
ERROR: MethodError: no method matching eps(::Type{Complex{Float64}})
Closest candidates are:
  eps(::Dates.Time) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.3\Dates\src\types.jl:387
  eps(::Dates.Date) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.3\Dates\src\types.jl:386
  eps(::Dates.DateTime) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.3\Dates\src\types.jl:385
  ...
Stacktrace:
 [1] inv(::SVD{Complex{Float64},Float64,Array{Complex{Float64},2}}) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.3\LinearAlgebra\src\svd.jl:284
 [2] top-level scope at REPL[2]:1

The relevant eps(T) call is here.

I guess I'm to blame for this, because it seems this was introduced in https://github.com/JuliaLang/julia/pull/32126. Sorry 馃う鈥嶁檪

bug linear algebra

Most helpful comment

Goes without saying that I'll prepare a PR to fix this :)

All 10 comments

Goes without saying that I'll prepare a PR to fix this :)

Can't you quickly fix it by replacing eps(T)*F.S[1] by eps(abs(F.S[1]))*one(T)?

I was thinking eps(real(T))*F.S[1].

Isn't it better to take the eps of F.S[1] instead of multiplying?

Well, strictly speaking, this would be a slightly different truncation. I chose eps(real(T))*F.S[1] to match what we do in ldiv!.

Personally, I don't mind if we'd drop the truncation altogether. But in any case, I think truncation changes should be discussed in https://github.com/JuliaLang/julia/issues/32880.

On an unrelated note, shouldn't this issue get a bug label (or similar)?

But isn't eps(real(T))*F.S[1] == eps(F.S[1]) just without multiplication? In my suggestion, I forgot that singular values are real, so away goes the abs and the *one(T).

Maybe I'm misunderstanding - which might well be the case when talking about floating point numbers - but why would the two be equivalent? Wouldn't it depend on the value of F.S[1]?

julia> s = rand()
0.9013815392525062

julia> eps(real(typeof(s)))*s == eps(s)
false

julia> eps(real(typeof(s)))*s - eps(s)
8.912460530752368e-17

This value is smaller than eps(s) but in a comparison the difference would still matter, wouldn't it?

But if you divide the difference by s, you get 9.887556093220253e-17, so the _relative_ error of the two epss is below eps(Float64).

This I get. But isn't it the absolute value that matters here? Eventually, in searchsortedlast, we are comparing the elements of F.S to our eps in absolute terms, aren't we?

Sorry for perhaps asking the obvious :)

Was this page helpful?
0 / 5 - 0 ratings