@@ -117,11 +117,34 @@ for f! in (:gesdd!, :gesvd!, :gesvdj!, :gesvdp!, :gesvdx!, :gesvdr!, :gesdvd!)
117117 @eval $ f! (driver:: Driver , args... ) = throw (ArgumentError (" $driver does not provide $f! " ))
118118end
119119
120+ """
121+ svd_via_adjoint!(f!, driver, A, S, U, Vᴴ; kwargs...)
122+
123+ Compute the SVD of `A` (m × n, m < n) by computing the SVD of `adjoint(A)` using
124+ the provided function `f!(driver, A, S, U, Vᴴ; kwargs...)`. Use this as a building
125+ block for drivers whose SVD routines require m ≥ n.
126+ """
127+ function svd_via_adjoint! (f!:: F , driver:: Driver , A, S, U, Vᴴ; kwargs... ) where {F}
128+ Aᴴ = adjoint! (similar (A' ), A)
129+ Uᴴ = similar (U' )
130+ V = similar (Vᴴ' )
131+ f! (driver, Aᴴ, S, V, Uᴴ; kwargs... )
132+ length (U) > 0 && adjoint! (U, Uᴴ)
133+ length (Vᴴ) > 0 && adjoint! (Vᴴ, V)
134+ return S, U, Vᴴ
135+ end
136+
120137# LAPACK
121- for f! in (:gesdd! , :gesvd! , :gesvdj! , : gesvdx! , :gesdvd! )
138+ for f! in (:gesdd! , :gesvd! , :gesvdx! , :gesdvd! )
122139 @eval $ f! (:: LAPACK , args... ; kwargs... ) = YALAPACK.$ f! (args... ; kwargs... )
123140end
124141
142+ function gesvdj! (:: LAPACK , A, S, U, Vᴴ; kwargs... )
143+ m, n = size (A)
144+ m >= n && return YALAPACK. gesvdj! (A, S, U, Vᴴ)
145+ return svd_via_adjoint! (gesvdj!, LAPACK (), A, S, U, Vᴴ; kwargs... )
146+ end
147+
125148for (f, f_lapack!, Alg) in (
126149 (:safe_divide_and_conquer , :gesdvd! , :SafeDivideAndConquer ),
127150 (:divide_and_conquer , :gesdd! , :DivideAndConquer ),
0 commit comments