@@ -1967,6 +1967,27 @@ for (gesvd, gesdd, gesvdx, gejsv, gesvj, elty, relty) in
19671967 chkstride1 (A, U, Vᴴ, S)
19681968 m, n = size (A)
19691969 minmn = min (m, n)
1970+ work = Vector {$elty} (undef, 1 )
1971+ cmplx = eltype (A) <: Complex
1972+ if cmplx
1973+ rwork = Vector {$relty} (undef, 5 * minmn)
1974+ else
1975+ rwork = nothing
1976+ end
1977+ (S, U, Vᴴ), info = _gesvd_body! (A, S, U, Vᴴ, work, rwork)
1978+ chklapackerror (info)
1979+ return S, U, Vᴴ
1980+ end
1981+ function _gesvd_body! (
1982+ A:: AbstractMatrix{$elty} ,
1983+ S:: AbstractVector{$relty} ,
1984+ U:: AbstractMatrix{$elty} ,
1985+ Vᴴ:: AbstractMatrix{$elty} ,
1986+ work:: Vector{$elty} ,
1987+ rwork:: Union{Vector{$relty}, Nothing}
1988+ )
1989+ m, n = size (A)
1990+ minmn = min (m, n)
19701991 if length (U) == 0
19711992 jobu = ' N'
19721993 else
@@ -2007,16 +2028,11 @@ for (gesvd, gesdd, gesvdx, gejsv, gesvj, elty, relty) in
20072028 lda = max (1 , stride (A, 2 ))
20082029 ldu = max (1 , stride (U, 2 ))
20092030 ldv = max (1 , stride (Vᴴ, 2 ))
2010- work = Vector {$elty} (undef, 1 )
20112031 lwork = BlasInt (- 1 )
2012- cmplx = eltype (A) <: Complex
2013- if cmplx
2014- rwork = Vector {$relty} (undef, 5 * minmn)
2015- end
20162032 info = Ref {BlasInt} ()
20172033 for i in 1 : 2 # first call returns lwork as work[1]
20182034 # ! format: off
2019- if cmplx
2035+ if eltype (A) <: Complex
20202036 ccall ((@blasfunc ($ gesvd), libblastrampoline), Cvoid,
20212037 (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ptr{$ elty}, Ref{BlasInt},
20222038 Ptr{$ relty}, Ptr{$ elty}, Ref{BlasInt}, Ptr{$ elty}, Ref{BlasInt},
@@ -2038,13 +2054,13 @@ for (gesvd, gesdd, gesvdx, gejsv, gesvj, elty, relty) in
20382054 info, 1 , 1 )
20392055 end
20402056 # ! format: on
2041- chklapackerror (info[])
20422057 if i == 1
2058+ chklapackerror (info[]) # bail out early if even the workspace query failed
20432059 lwork = BlasInt (real (work[1 ]))
20442060 resize! (work, lwork)
20452061 end
20462062 end
2047- return (S, U, Vᴴ)
2063+ return (S, U, Vᴴ), info[]
20482064 end
20492065 # ! format: off
20502066 function gesdd! (
@@ -2058,6 +2074,33 @@ for (gesvd, gesdd, gesvdx, gejsv, gesvj, elty, relty) in
20582074 chkstride1 (A, U, Vᴴ, S)
20592075 m, n = size (A)
20602076 minmn = min (m, n)
2077+ work = Vector {$elty} (undef, 1 )
2078+ if eltype (A) <: Complex
2079+ if length (U) == 0 && length (Vᴴ) == 0
2080+ lrwork = (LAPACK. version () <= v " 3.6" ) ? 7 * minmn : 5 * minmn
2081+ else
2082+ lrwork = minmn * max (5 * minmn + 5 , 2 * max (m, n) + 2 * minmn + 1 )
2083+ end
2084+ rwork = Vector {$relty} (undef, lrwork)
2085+ else
2086+ rwork = nothing
2087+ end
2088+ (S, U, Vᴴ), info = _gesdd_body! (A, S, U, Vᴴ, work, rwork)
2089+ chklapackerror (info)
2090+ return S, U, Vᴴ
2091+ end
2092+ # ! format: off
2093+ function _gesdd_body! (
2094+ A:: AbstractMatrix{$elty} ,
2095+ S:: AbstractVector{$relty} ,
2096+ U:: AbstractMatrix{$elty} ,
2097+ Vᴴ:: AbstractMatrix{$elty} ,
2098+ work:: Vector{$elty} ,
2099+ rwork:: Union{Vector{$relty}, Nothing}
2100+ )
2101+ # ! format: on
2102+ m, n = size (A)
2103+ minmn = min (m, n)
20612104
20622105 if length (U) == 0 && length (Vᴴ) == 0
20632106 job = ' N'
@@ -2086,19 +2129,12 @@ for (gesvd, gesdd, gesvdx, gejsv, gesvj, elty, relty) in
20862129 lda = max (1 , stride (A, 2 ))
20872130 ldu = max (1 , stride (U, 2 ))
20882131 ldv = max (1 , stride (Vᴴ, 2 ))
2089- work = Vector {$elty} (undef, 1 )
20902132 lwork = BlasInt (- 1 )
2091- cmplx = eltype (A) <: Complex
2092- if cmplx
2093- lrwork = job == ' N' ? 7 * minmn :
2094- minmn * max (5 * minmn + 7 , 2 * max (m, n) + 2 * minmn + 1 )
2095- rwork = Vector {$relty} (undef, lrwork)
2096- end
20972133 iwork = Vector {BlasInt} (undef, 8 * minmn)
20982134 info = Ref {BlasInt} ()
20992135 for i in 1 : 2 # first call returns lwork as work[1]
21002136 # ! format: off
2101- if cmplx
2137+ if eltype (A) <: Complex
21022138 ccall ((@blasfunc ($ gesdd), libblastrampoline), Cvoid,
21032139 (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ptr{$ elty}, Ref{BlasInt},
21042140 Ptr{$ relty}, Ptr{$ elty}, Ref{BlasInt}, Ptr{$ elty}, Ref{BlasInt},
@@ -2120,8 +2156,8 @@ for (gesvd, gesdd, gesvdx, gejsv, gesvj, elty, relty) in
21202156 info, 1 )
21212157 end
21222158 # ! format: on
2123- chklapackerror (info[])
21242159 if i == 1
2160+ chklapackerror (info[]) # bail out if even the workspace query failed
21252161 # Work around issue with truncated Float32 representation of lwork in
21262162 # sgesdd by using nextfloat. See
21272163 # http://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=13&t=4587&p=11036&hilit=sgesdd#p11036
@@ -2131,7 +2167,38 @@ for (gesvd, gesdd, gesvdx, gejsv, gesvj, elty, relty) in
21312167 resize! (work, lwork)
21322168 end
21332169 end
2134- return (S, U, Vᴴ)
2170+ return (S, U, Vᴴ), info[]
2171+ end
2172+ # ! format: off
2173+ function gesdvd! ( # SafeSVD implementation
2174+ A:: AbstractMatrix{$elty} ,
2175+ S:: AbstractVector{$relty} = similar (A, $ relty, min (size (A)... )),
2176+ U:: AbstractMatrix{$elty} = similar (A, $ elty, size (A, 1 ), min (size (A)... )),
2177+ Vᴴ:: AbstractMatrix{$elty} = similar (A, $ elty, min (size (A)... ), size (A, 2 ))
2178+ )
2179+ # ! format: on
2180+ require_one_based_indexing (A, U, Vᴴ, S)
2181+ chkstride1 (A, U, Vᴴ, S)
2182+ m, n = size (A)
2183+ minmn = min (m, n)
2184+ work = Vector {$elty} (undef, 1 )
2185+ if eltype (A) <: Complex
2186+ if length (U) == 0 && length (Vᴴ) == 0
2187+ lrwork = (LAPACK. version () <= v " 3.6" ) ? 7 * minmn : 5 * minmn
2188+ else
2189+ lrwork = minmn * max (5 * minmn + 5 , 2 * max (m, n) + 2 * minmn + 1 )
2190+ end
2191+ rwork = Vector {$relty} (undef, lrwork)
2192+ else
2193+ rwork = nothing
2194+ end
2195+ Ac = copy (A)
2196+ (S, U, Vᴴ), info = _gesdd_body! (Ac, S, U, Vᴴ, work, rwork)
2197+ if info > 0
2198+ (S, U, Vᴴ), info = _gesvd_body! (A, S, U, Vᴴ, work, rwork)
2199+ end
2200+ chklapackerror (info)
2201+ return S, U, Vᴴ
21352202 end
21362203 # ! format: off
21372204 function gesvdx! (
0 commit comments