Skip to content

Commit 7a825c2

Browse files
committed
return SVD from pinv(::SVD)
1 parent b7fd696 commit 7a825c2

File tree

3 files changed

+10
-7
lines changed

3 files changed

+10
-7
lines changed

src/dense.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1756,7 +1756,8 @@ SVD-based algorithm, it is better to employ the SVD directly via `svd(M; rtol, a
17561756
or `ldiv!(svd(M), b; rtol, atol)`.
17571757
17581758
One can also pass `M = svd(A)` as the argument to `pinv` in order to re-use
1759-
an existing [`SVD`](@ref) factorization.
1759+
an existing [`SVD`](@ref) factorization. In this case, `pinv` will return
1760+
the SVD of the pseudo-inverse, which can be applied accurately, instead of an explicit matrix.
17601761
17611762
!!! compat "Julia 1.13"
17621763
Passing an `SVD` object to `pinv` requires Julia 1.13 or later.

src/svd.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,17 +306,18 @@ function ldiv!(F::SVD{T}, B::AbstractVecOrMat; atol::Real=0, rtol::Real = (eps(r
306306
return B
307307
end
308308

309-
function pinv(F::SVD{T}; atol::Real=0, rtol::Real = (eps(real(float(oneunit(T))))*min(size(F)...))*iszero(atol)) where T
309+
function pinv(F::SVD{T,<:Any,M}; atol::Real=0, rtol::Real = (eps(real(float(oneunit(T))))*min(size(F)...))*iszero(atol)) where {T,M}
310310
k = _count_svdvals(F.S, atol, rtol)
311-
@views (F.S[1:k] .\ F.Vt[1:k, :])' * F.U[:,1:k]'
311+
@views SVD(M(F.Vt[1:k, :]'), inv.(F.S[1:k]), M(F.U[:,1:k]'))
312312
end
313313

314314
function inv(F::SVD)
315315
# TODO: checksquare(F)
316316
@inbounds for i in eachindex(F.S)
317317
iszero(F.S[i]) && throw(SingularException(i))
318318
end
319-
pinv(F; rtol=eps(real(eltype(F))))
319+
k = _count_svdvals(F.S, 0, eps(real(eltype(F))))
320+
return @views (F.S[1:k] .\ F.Vt[1:k, :])' * F.U[:,1:k]'
320321
end
321322

322323
size(A::SVD, dim::Integer) = dim == 1 ? size(A.U, dim) : size(A.Vt, dim)

test/svd.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,13 @@ end
239239
@testset "SVD pinv and truncation" begin
240240
m, n = 10,5
241241
A = randn(m,n) * [1/(i+j-1) for i = 1:n, j=1:n] # badly conditioned Hilbert matrix
242-
@test pinv(A) pinv(svd(A)) rtol=1e-13
242+
@test pinv(A) Matrix(pinv(svd(A))) rtol=1e-13
243243
pinv_3 = pinv(A, rtol=1e-3)
244-
@test pinv_3 pinv(svd(A), rtol=1e-3) rtol=1e-13
245-
@test pinv_3 pinv(svd(A, rtol=1e-3)) rtol=1e-13
244+
@test pinv_3 Matrix(pinv(svd(A), rtol=1e-3)) rtol=1e-13
245+
@test pinv_3 Matrix(pinv(svd(A, rtol=1e-3))) rtol=1e-13
246246
b = float([1:m;]) # arbitrary rhs
247247
@test pinv_3 * b svd(A, rtol=1e-3) \ b rtol=1e-13
248+
@test pinv_3 * b pinv(svd(A, rtol=1e-3)) * b rtol=1e-13
248249
@test pinv_3 * b ldiv!(svd(A), copy(b), rtol=1e-3)[1:n] rtol=1e-13
249250
@test pinv(A, atol=100) == pinv(svd(A), atol=100) == pinv(svd(A, atol=100)) == zeros(5,10)
250251
end

0 commit comments

Comments
 (0)