Repository: JuliaLinearAlgebra/GenericLinearAlgebra.jl (julia)

Issue:
BoundsError bug in SVD for zero matrix
I see the following behavior in v0.3.8 (not sure when it started, but this error did not occur before about Dec 5, 2022, the last time I ran Hypatia.jl's test suite):
```
julia> svd(zeros(BigFloat, 2, 2))
ERROR: BoundsError: attempt to access 1-element Vector{BigFloat} at index [0]
Stacktrace:
 [1] setindex!
   @ ./array.jl:966 [inlined]
 [2] svdDemmelKahan!(B::Bidiagonal{BigFloat, Vector{BigFloat}}, n1::Int64, n2::Int64, U::Matrix{BigFloat}, Vᴴ::Matrix{BigFloat})
   @ GenericLinearAlgebra ~/.julia/packages/GenericLinearAlgebra/ilNvI/src/svd.jl:110
 [3] __svd!(B::Bidiagonal{BigFloat, Vector{BigFloat}}, U::Matrix{BigFloat}, Vᴴ::Matrix{BigFloat}; tol::BigFloat, debug::Bool)
   @ GenericLinearAlgebra ~/.julia/packages/GenericLinearAlgebra/ilNvI/src/svd.jl:184
 [4] _svd!(B::Bidiagonal{BigFloat, Vector{BigFloat}}; tol::BigFloat, debug::Bool)
   @ GenericLinearAlgebra ~/.julia/packages/GenericLinearAlgebra/ilNvI/src/svd.jl:301
 [5] svd!(A::Matrix{BigFloat}; tol::BigFloat, full::Bool, alg::LinearAlgebra.DivideAndConquer, debug::Bool)
   @ GenericLinearAlgebra ~/.julia/packages/GenericLinearAlgebra/ilNvI/src/svd.jl:658
 [6] #svd#114
   @ ~/julia/usr/share/julia/stdlib/v1.8/LinearAlgebra/src/svd.jl:179 [inlined]
 [7] svd(A::Matrix{BigFloat})
   @ LinearAlgebra ~/julia/usr/share/julia/stdlib/v1.8/LinearAlgebra/src/svd.jl:178
 [8] top-level scope
   @ REPL[15]:1
```

Pull request description:
zero singular values

Closes #119

Patch:
diff --git a/src/svd.jl b/src/svd.jl
index dd21116..1d53d65 100644
--- a/src/svd.jl
+++ b/src/svd.jl
@@ -253,12 +253,16 @@ function _svdvals!(B::Bidiagonal{T}; tol = eps(T)) where {T<:Real}
     return sort(abs.(diag(B)), rev = true)
 end
 
+# We want to avoid that zero eigenvalues zero out any singular vectors so we'd
+# have to use a modified sign function
+_sign(x) = ifelse(iszero(x), one(x), sign(x))
+
 function _sort_and_adjust!(U, s, Vᴴ)
     n = length(s)
 
     # Adjust sign of singular values if necessary
     if any(!isposdef, s)
-        rmul!(U, Diagonal(sign.(s)))
+        rmul!(U, Diagonal(_sign.(s)))
         map!(abs, s, s)
     end
 


Test patch:
diff --git a/test/svd.jl b/test/svd.jl
index eb60047..8fddc86 100644
--- a/test/svd.jl
+++ b/test/svd.jl
@@ -241,4 +241,11 @@ using Test, GenericLinearAlgebra, LinearAlgebra, Quaternions, DoubleFloats
         BF = GenericLinearAlgebra.bidiagonalize!(copy(A))
         @test (BF.rightQ' * Matrix(I, size(A)...)) * BF.rightQ ≈ I
     end
+
+    @testset "Issue 119" begin
+        F = svd(zeros(BigFloat, 2, 2))
+        @test F.S == zeros(2)
+        @test F.U == I
+        @test F.Vt == I
+    end
 end