Skip to content

Commit 8292977

Browse files
committed
added threshold for very small sv
1 parent 97a154a commit 8292977

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

src/Arpack.jl

+9-3
Original file line numberDiff line numberDiff line change
@@ -326,20 +326,26 @@ function _svds(X; nsv::Int = 6, ritzvec::Bool = true, tol::Float64 = 0.0, maxite
326326
# ind = [1:2:ncv;]
327327
# sval = abs.(ex[1][ind])
328328

329-
svals = sqrt.(max.(zero(real(otype)), real.(ex[1])))
329+
realex1 = real.(ex[1])
330+
threshold = max(eps(real(otype))*realex1[1], eps(real(otype)))
331+
firstzero = findfirst(v -> v <= threshold, realex1)
332+
r = firstzero === nothing ? nsv : firstzero-1 # rank of the decomposition
333+
realex1[r+1:end] .= zero(real(otype))
334+
svals = sqrt.(realex1)
335+
330336
if ritzvec
331337
# calculating singular vectors
332338
# left_sv = sqrt(2) * ex[2][ 1:size(X,1), ind ] .* sign.(ex[1][ind]')
333339
if size(X, 1) >= size(X, 2)
334340
V = ex[2]
335341
# We cannot assume that X*V is a Matrix even though V is. This is not
336342
# the case for e.g. LinearMaps.jl so we convert to Matrix explicitly
337-
U = Array(qr(rmul!(convert(Matrix, X*V), Diagonal(inv.(svals)))).Q)
343+
U = Array(qr(rmul!(convert(Matrix, X*V), Diagonal([inv.(svals[1:r]); ones(nsv-r)]))).Q)
338344
else
339345
U = ex[2]
340346
# We cannot assume that X'U is a Matrix even though U is. This is not
341347
# the case for e.g. LinearMaps.jl so we convert to Matrix explicitly
342-
V = Array(qr(rmul!(convert(Matrix, X'U), Diagonal(inv.(svals)))).Q)
348+
V = Array(qr(rmul!(convert(Matrix, X'U), Diagonal([inv.(svals[1:r]); ones(nsv-r)]))).Q)
343349
end
344350

345351
# right_sv = sqrt(2) * ex[2][ size(X,1)+1:end, ind ]

test/runtests.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ LinearAlgebra.adjoint(A::MyOp) = MyOp(adjoint(A.mat))
295295
end
296296

297297
@testset "low rank" begin
298+
Random.seed!(123)
298299
@testset "$T coefficients" for T in [Float64, Complex{Float64}]
299300
@testset "rank $r" for r in [2, 5, 10]
300301
m, n = 3*r, 4*r
@@ -310,8 +311,8 @@ end
310311
F = svds(A, nsv=nsv)[1]
311312

312313
@test F.S[1:r] S
313-
@test F.U'*F.U Matrix{Float64}(I, nsv, nsv)
314-
@test F.V'*F.V Matrix{Float64}(I, nsv, nsv)
314+
@test F.U'*F.U Matrix{T}(I, nsv, nsv)
315+
@test F.V'*F.V Matrix{T}(I, nsv, nsv)
315316
end
316317
end
317318
end

0 commit comments

Comments
 (0)