complexGEsing(3)
complexGEsing(3) β LAPACK π
okay bestie, welcome to the complex SVD driver function group chat β¨ this is part 1 and we're going in order, no skips, no cap.
πΈ NAME πΈ
complexGEsing β complex π¦
That's it. That's the name. It's giving "mysterious but iconic" π
β¨ SYNOPSIS β¨
π Functions π
subroutine cgejsvβCGEJSVπ
subroutine cgejsv (JOBA, JOBU, JOBV, JOBR, JOBT, JOBP, M, N, A, LDA,
SVA, U, LDU, V, LDV, CWORK, LWORK, RWORK, LRWORK, IWORK, INFO)
subroutine cgesddβCGESDDπ
subroutine cgesdd (JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK,
RWORK, IWORK, INFO)
subroutine cgesvdβCGESVD computes the singular value decomposition (SVD) for GE matricesβ¨
subroutine cgesvd (JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK,
LWORK, RWORK, INFO)
subroutine cgesvdqβCGESVDQ computes the singular value decomposition (SVD) with a QR-Preconditioned QR SVD Method for GE matricesπ«
subroutine cgesvdq (JOBA, JOBP, JOBR, JOBU, JOBV, M, N, A, LDA, S, U,
LDU, V, LDV, NUMRANK, IWORK, LIWORK, CWORK, LCWORK, RWORK, LRWORK,
INFO)
subroutine cgesvdxβCGESVDX computes the singular value decomposition (SVD) for GE matricesπ₯
subroutine cgesvdx (JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU, IL, IU,
NS, S, U, LDU, VT, LDVT, WORK, LWORK, RWORK, IWORK, INFO)
subroutine cggsvd3βCGGSVD3 computes the singular value decomposition (SVD) for OTHER matricesπ
subroutine cggsvd3 (JOBU, JOBV, JOBQ, M, N, P, K, L, A, LDA, B, LDB,
ALPHA, BETA, U, LDU, V, LDV, Q, LDQ, WORK, LWORK, RWORK, IWORK,
INFO)
π Detailed Description π
This is the group of complex singular value driver functions for GE matrices. That's the vibe. π
π Function Documentation π
subroutine cgejsv π¦
subroutine cgejsv (character*1 JOBA, character*1 JOBU, character*1 JOBV,
character*1 JOBR, character*1 JOBT, character*1 JOBP, integer M, integer
N, complex, dimension( lda, * ) A, integer LDA, real, dimension( n )
SVA, complex, dimension( ldu, * ) U, integer LDU, complex, dimension(
ldv, * ) V, integer LDV, complex, dimension( lwork ) CWORK, integer
LWORK, real, dimension( lrwork ) RWORK, integer LRWORK, integer,
dimension( * ) IWORK, integer INFO)
CGEJSV
Purpose:
CGEJSV computes the singular value decomposition (SVD) of a complex M-by-N matrix [A], where M >= N. The SVD of [A] is written as
[A] = [U] * [SIGMA] * [V]^*,
where [SIGMA] is an N-by-N (M-by-N) matrix which is zero except for its N diagonal elements, [U] is an M-by-N (or M-by-M) unitary matrix, and [V] is an N-by-N unitary matrix. The diagonal elements of [SIGMA] are the singular values of [A]. The columns of [U] and [V] are the left and the right singular vectors of [A], respectively. The matrices [U] and [V] are computed and stored in the arrays U and V, respectively. The diagonal of [SIGMA] is computed and stored in the array SVA. β¨
Arguments:
Parameters
JOBA
JOBA is CHARACTER*1. Specifies the level of accuracy:
'C': This option works well (high relative accuracy) ifA = B * D, with well-conditionedBand arbitrary diagonal matrixD. The accuracy cannot be spoiled by COLUMN scaling. The accuracy of the computed output depends on the condition ofB, and the procedure aims at the best theoretical accuracy. The relative errormax_{i=1:N}|d sigma_i| / sigma_iis bounded byf(M,N)*epsilon* cond(B), independent ofD. The input matrix is preprocessed with the QRF with column pivoting. This initial preprocessing and preconditioning by a rank revealing QR factorization is common for all values ofJOBA. Additional actions are specified as follows: π'E': Computation as with'C'with an additional estimate of the condition number ofB. It provides a realistic error bound. π'F': IfA = D1 * C * D2with ill-conditioned diagonal scalingsD1,D2, and well-conditioned matrixC, this option gives higher accuracy than the'C'option. If the structure of the input matrix is not known, and relative accuracy is desirable, then this option is advisable. The input matrixAis preprocessed with QR factorization with FULL (row and column) pivoting. β¨'G': Computation as with'F'with an additional estimate of the condition number ofB, whereA=B*D. IfAhas heavily weighted rows, then using this condition number gives too pessimistic error bound. π'A': Small singular values are not well determined by the data and are considered as noisy; the matrix is treated as numerically rank deficient. The error in the computed singular values is bounded byf(m,n)*epsilon*||A||. The computed SVDA = U * S * V^*restoresAup tof(m,n)*epsilon*||A||. This gives the procedure the licence to discard (set to zero) all singular values belowN*epsilon*||A||. π'R': Similar as in'A'. Rank revealing property of the initial QR factorization is used do reveal (using triangular factor) a gapsigma_{r+1} < epsilon * sigma_rin which case the numerical RANK is declared to ber. The SVD is computed with absolute error bounds, but more accurately than with'A'. π₯
JOBU
JOBU is CHARACTER*1. Specifies whether to compute the columns of U:
'U': N columns ofUare returned in the arrayU. π'F': full set of M left sing. vectors is returned in the arrayU. π'W':Umay be used as workspace of lengthM*N. See the description ofU. π¦'N':Uis not computed. π
JOBV
JOBV is CHARACTER*1. Specifies whether to compute the matrix V:
'V': N columns ofVare returned in the arrayV; Jacobi rotations are not explicitly accumulated. β¨'J': N columns ofVare returned in the arrayV, but they are computed as the product of Jacobi rotations, ifJOBT = 'N'. π'W':Vmay be used as workspace of lengthN*N. See the description ofV. π¦'N':Vis not computed. π
JOBR
JOBR is CHARACTER*1. Specifies the RANGE for the singular values. Issues the licence to set to zero small positive singular values if they are outside specified range. If A .NE. 0 is scaled so that the largest singular value of c*A is around SQRT(BIG), BIG=SLAMCH('O'), then JOBR issues the licence to kill columns of A whose norm in c*A is less than SQRT(SFMIN) (for JOBR = 'R'), or less than SMALL=SFMIN/EPSLN, where SFMIN=SLAMCH('S'), EPSLN=SLAMCH('E'). π³
'N': Do not kill small columns ofc*A. This option assumes that BLAS and QR factorizations and triangular solvers are implemented to work in that range. If the condition ofAis greater thanBIG, useCGESVJ. β οΈ'R': RESTRICTED range forsigma(c*A)is[SQRT(SFMIN), SQRT(BIG)](roughly, as described above). This option is recommended. π
===========================
For computing the singular values in the FULL range [SFMIN,BIG] use CGESVJ. π
JOBT
JOBT is CHARACTER*1. If the matrix is square then the procedure may determine to use transposed A if A^* seems to be better with respect to convergence. If the matrix is not square, JOBT is ignored. The decision is based on two values of entropy over the adjoint orbit of A^* * A. See the descriptions of WORK(6) and WORK(7). π§
'T': transpose if entropy test indicates possibly faster convergence of Jacobi process ifA^*is taken as input. IfAis replaced withA^*, then the row pivoting is included automatically. π'N': do not speculate. π
The option 'T' can be used to compute only the singular values, or the full SVD (U, SIGMA and V). For only one set of singular vectors (U or V), the caller should provide both U and V, as one of the matrices is used as workspace if the matrix A is transposed. The implementer can easily remove this constraint and make the code more complicated. See the descriptions of U and V. In general, this option is considered experimental, and 'N'; should be preferred. This is subject to changes in the future. π
JOBP
JOBP is CHARACTER*1. Issues the licence to introduce structured perturbations to drown denormalized numbers. This licence should be active if the denormals are poorly implemented, causing slow computation, especially in cases of fast convergence (!). For details see [1,2]. For the sake of simplicity, this perturbations are included only when the full SVD or only the singular values are requested. The implementer/user can easily add the perturbation for the cases of computing one set of singular vectors. π
'P': introduce perturbation. π'N': do not perturb. π«
M
M is INTEGER. The number of rows of the input matrix A. M >= 0. π
N
N is INTEGER. The number of columns of the input matrix A. M >= N >= 0. π
A
A is COMPLEX array, dimension (LDA,N). On entry, the M-by-N matrix A. π
LDA
LDA is INTEGER. The leading dimension of the array A. LDA >= max(1,M). π¦
SVA
SVA is REAL array, dimension (N). On exit,
- For
WORK(1)/WORK(2) = ONE: The singular values ofA. During the computationSVAcontains Euclidean column norms of the iterated matrices in the arrayA. β¨ - For
WORK(1) .NE. WORK(2): The singular values ofAare(WORK(1)/WORK(2)) * SVA(1:N). This factored form is used ifsigma_max(A)overflows or if small singular values have been saved from underflow by scaling the input matrixA. π - If
JOBR='R'then some of the singular values may be returned as exact zeros obtained by'set to zero'because they are below the numerical rank threshold or are denormalized numbers. π
U
...and bestie, U is literally next in part 2, so hold that thought π
β¨
U π
okay bestie, U is giving COMPLEX array energy, dimension ( LDU, N ) or ( LDU, M ). Here's the rundown:
- If
JOBU = 'U', thenUcontains on exit theM-by-Nmatrix of the left singular vectors. slay. - If
JOBU = 'F', thenUcontains on exit theM-by-Mmatrix of the left singular vectors, including an ONB of the orthogonal complement of theRange(A). iconic. - If
JOBU = 'W'.AND.(JOBV = 'V'.AND.JOBT = 'T'.AND.M = N), thenUis used as workspace if the procedure replacesAwithA^*. In that case,[V]is computed inUas left singular vectors ofA^*and then copied back to theVarray. This'W'option is just a reminder to the caller that in this caseUis reserved as workspace of lengthN*N. no cap. - If
JOBU = 'N'Uis not referenced, unlessJOBT='T'.
LDU π¦
LDU is INTEGER. It's the leading dimension of the array U, and the rule is LDU >= 1. If JOBU = 'U' or 'F' or 'W', then LDU >= M. periodt.
V πΈ
V is a COMPLEX array, dimension ( LDV, N ). Listen:
- If
JOBV = 'V','J'thenVcontains on exit theN-by-Nmatrix of the right singular vectors; - If
JOBV = 'W', AND (JOBU = 'U'ANDJOBT = 'T'ANDM = N), thenVis used as workspace if the procedure replacesAwithA^*. In that case,[U]is computed inVas right singular vectors ofA^*and then copied back to theUarray. This'W'option is just a reminder to the caller that in this caseVis reserved as workspace of lengthN*N. - If
JOBV = 'N'Vis not referenced, unlessJOBT='T'.
LDV π§
LDV is INTEGER. The leading dimension of the array V, LDV >= 1. If JOBV = 'V' or 'J' or 'W', then LDV >= N. iykyk.
CWORK β¨
CWORK is a COMPLEX array, dimension (MAX(2,LWORK)). If the call to CGEJSV is a workspace query (indicated by LWORK=-1 or LRWORK=-1), then on exit CWORK(1) contains the required length of CWORK for the job parameters used in the call.
LWORK π₯
LWORK is INTEGER. Length of CWORK to confirm proper allocation of workspace. LWORK depends on the job:
- If only
SIGMAis needed (JOBU = 'N',JOBV = 'N') and
1.1 .. no scaled condition estimate required (JOBA.NE.'E'.AND.JOBA.NE.'G'):
LWORK >= 2*N+1. This is the minimal requirement.
->> For optimal performance (blocked code) the optimal value is LWORK >= N + (N+1)*NB. Here NB is the optimal block size for CGEQP3 and CGEQRF.
In general, optimal LWORK is computed as
LWORK >= max(N+LWORK(CGEQP3),N+LWORK(CGEQRF), LWORK(CGESVJ)).
1.2. .. an estimate of the scaled condition number of A is required (JOBA='E', or 'G'). In this case, LWORK the minimal requirement is LWORK >= N*N + 2*N.
->> For optimal performance (blocked code) the optimal value is LWORK >= max(N+(N+1)*NB, N*N+2*N)=N**2+2*N.
In general, the optimal length LWORK is computed as
LWORK >= max(N+LWORK(CGEQP3),N+LWORK(CGEQRF), LWORK(CGESVJ),
N*N+LWORK(CPOCON)).
- If
SIGMAand the right singular vectors are needed (JOBV = 'V'), (JOBU = 'N')
2.1 .. no scaled condition estimate requested (JOBE = 'N'):
-> the minimal requirement is LWORK >= 3*N.
-> For optimal performance,
LWORK >= max(N+(N+1)*NB, 2*N+N*NB)=2*N+N*NB,
where NB is the optimal block size for CGEQP3, CGEQRF, CGELQ, CUNMLQ. In general, the optimal length LWORK is computed as
LWORK >= max(N+LWORK(CGEQP3), N+LWORK(CGESVJ),
N+LWORK(CGELQF), 2*N+LWORK(CGEQRF), N+LWORK(CUNMLQ)).
2.2 .. an estimate of the scaled condition number of A is required (JOBA='E', or 'G').
-> the minimal requirement is LWORK >= 3*N.
-> For optimal performance,
LWORK >= max(N+(N+1)*NB, 2*N,2*N+N*NB)=2*N+N*NB,
where NB is the optimal block size for CGEQP3, CGEQRF, CGELQ, CUNMLQ. In general, the optimal length LWORK is computed as
LWORK >= max(N+LWORK(CGEQP3), LWORK(CPOCON), N+LWORK(CGESVJ),
N+LWORK(CGELQF), 2*N+LWORK(CGEQRF), N+LWORK(CUNMLQ)).
- If
SIGMAand the left singular vectors are needed
3.1 .. no scaled condition estimate requested (JOBE = 'N'):
-> the minimal requirement is LWORK >= 3*N.
-> For optimal performance:
if JOBU = 'U' :: LWORK >= max(3*N, N+(N+1)*NB, 2*N+N*NB)=2*N+N*NB,
where NB is the optimal block size for CGEQP3, CGEQRF, CUNMQR.
In general, the optimal length LWORK is computed as
LWORK >= max(N+LWORK(CGEQP3), 2*N+LWORK(CGEQRF), N+LWORK(CUNMQR)).
3.2 .. an estimate of the scaled condition number of A is required (JOBA='E', or 'G').
-> the minimal requirement is LWORK >= 3*N.
-> For optimal performance:
if JOBU = 'U' :: LWORK >= max(3*N, N+(N+1)*NB, 2*N+N*NB)=2*N+N*NB,
where NB is the optimal block size for CGEQP3, CGEQRF, CUNMQR.
In general, the optimal length LWORK is computed as
LWORK >= max(N+LWORK(CGEQP3),N+LWORK(CPOCON),
2*N+LWORK(CGEQRF), N+LWORK(CUNMQR)).
- If the full SVD is needed: (
JOBU = 'U'orJOBU = 'F') and
4.1. if JOBV = 'V'
the minimal requirement is LWORK >= 5*N+2*N*N.
4.2. if JOBV = 'J' the minimal requirement is
LWORK >= 4*N+N*N.
In both cases, the allocated CWORK can accommodate blocked runs of CGEQP3, CGEQRF, CGELQF, CUNMQR, CUNMLQ.
If the call to CGEJSV is a workspace query (indicated by LWORK=-1 or LRWORK=-1), then on exit CWORK(1) contains the optimal and CWORK(2) contains the minimal length of CWORK for the job parameters used in the call.
RWORK π
RWORK is REAL array, dimension (MAX(7,LWORK)). On exit,
RWORK(1)= Determines the scaling factorSCALE = RWORK(2) / RWORK(1)such thatSCALE*SVA(1:N)are the computed singular values ofA. (See the description ofSVA().)RWORK(2)= See the description ofRWORK(1).RWORK(3)=SCONDAis an estimate for the condition number of column equilibratedA. (IfJOBA = 'E'or'G')SCONDAis an estimate ofSQRT(||(R^* * R)^(-1)||_1). It is computed usingCPOCON. It holds
N^(-1/4) * SCONDA <= ||R^(-1)||_2 <= N^(1/4) * SCONDA
where R is the triangular factor from the QRF of A.
However, ifRis truncated and the numerical rank is determined to be strictly smaller thanN,SCONDAis returned as-1, thus indicating that the smallest singular values might be lost. π
If full SVD is needed, the following two condition numbers are useful for the analysis of the algorithm. They are provided for a developer/implementer who is familiar with the details of the method.
RWORK(4)= an estimate of the scaled condition number of the triangular factor in the first QR factorization.RWORK(5)= an estimate of the scaled condition number of the triangular factor in the second QR factorization.
The following two parameters are computed if JOBT = 'T'. They are provided for a developer/implementer who is familiar with the details of the method.
RWORK(6)= the entropy ofA^* * A:: this is the Shannon entropy ofdiag(A^* * A) / Trace(A^* * A)taken as point in the probability simplex.RWORK(7)= the entropy ofA * A^*. (See the description ofRWORK(6).)
If the call to CGEJSV is a workspace query (indicated by LWORK=-1 or LRWORK=-1), then on exit RWORK(1) contains the required length of RWORK for the job parameters used in the call.
LRWORK π
LRWORK is INTEGER. Length of RWORK to confirm proper allocation of workspace. LRWORK depends on the job:
- If it's only the singular values you're asking for, i.e. if
LSAME(JOBU,'N') .AND. LSAME(JOBV,'N'), then:- If
LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G'), then:LRWORK = max( 7, 2 * M ). - Otherwise,
LRWORK = max( 7, N ).
- If it's singular values plus the right singular vectors, i.e. if
(LSAME(JOBV,'V').OR.LSAME(JOBV,'J')) .AND..NOT.(LSAME(JOBU,'U').OR.LSAME(JOBU,'F')), then:- If
LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G'), thenLRWORK = max( 7, 2 * M ). - Otherwise,
LRWORK = max( 7, N ).
- If
- If it's singular values plus the left singular vectors, i.e. if
(LSAME(JOBU,'U').OR.LSAME(JOBU,'F')) .AND..NOT.(LSAME(JOBV,'V').OR.LSAME(JOBV,'J')), then:- If
LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G'), thenLRWORK = max( 7, 2 * M ). - Otherwise,
LRWORK = max( 7, N ).
- If
- If it's singular values plus both the left and right singular vectors, i.e. if
(LSAME(JOBU,'U').OR.LSAME(JOBU,'F')) .AND.(LSAME(JOBV,'V').OR.LSAME(JOBV,'J')), then:- If
LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G'), thenLRWORK = max( 7, 2 * M ). - Otherwise,
LRWORK = max( 7, N ).
- If
- If
If, on entry, LRWORK = -1 or LWORK=-1, a workspace query is assumed and the length of RWORK is returned in RWORK(1).
Bestie that's a LOT of max( 7, β¦ ) and honestly? Respect. The pattern is giving "the minimum is always 7 and everything else is vibes." π
IWORK π
IWORK is an INTEGER array, of dimension at least 4, that further depends on the job:
- If only the singular values are requested then: If
( LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G') )then the length ofIWORKisN+M; otherwise the length ofIWORKisN. - If the singular values and the right singular vectors are requested then: If
( LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G') )then the length ofIWORKisN+M; otherwise the length ofIWORKisN. - If the singular values and the left singular vectors are requested then: If
( LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G') )then the length ofIWORKisN+M; otherwise the length ofIWORKisN. - If the singular values with both the left and the right singular vectors are requested, then:
- If
LSAME(JOBV,'J')the length ofIWORKis determined as follows: If( LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G') )then the length ofIWORKisN+M; otherwise the length ofIWORKisN. - If
LSAME(JOBV,'V')the length ofIWORKis determined as follows: If( LSAME(JOBT,'T') .OR. LSAME(JOBA,'F') .OR. LSAME(JOBA,'G') )then the length ofIWORKis2*N+M; otherwise the length ofIWORKis2*N.
- If
On exit, slay, here's the tea:
IWORK(1)= the numerical rank determined after the initial QR factorization with pivoting. See the descriptions ofJOBAandJOBR.IWORK(2)= the number of the computed nonzero singular valuesIWORK(3)= if nonzero, a warning message: IfIWORK(3) = 1then some of the column norms ofAwere denormalized floats. The requested high accuracy is not warranted by the data.IWORK(4)= 1 or -1. IfIWORK(4) = 1, then the procedure usedA^*to do the job as specified by the JOB parameters.
If the call to CGEJSV is a workspace query (indicated by LWORK = -1 and LRWORK = -1), then on exit IWORK(1) contains the required length of IWORK for the job parameters used in the call.
INFO π₯
INFO is INTEGER
< 0:ifINFO = -i, then the i-th argument had an illegal value.= 0:successful exit;> 0:CGEJSVdid not converge in the maximal allowed number of sweeps. The computed values may be inaccurate.
Not me catching the "may be inaccurate" at the end β that's the polite way of saying "girl, check your numbers." π
Author π«Ά
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.
Further Details: β¨
CGEJSV implements a preconditioned Jacobi SVD algorithm. It uses CGEQP3, CGEQRF, and CGELQF as preprocessors and preconditioners. Optionally, an additional row pivoting can be used as a preprocessor, which in some cases results in much higher accuracy. An example is matrix A with the structure A = D1 * C * D2, where D1, D2 are arbitrarily ill-conditioned diagonal matrices and C is well-conditioned matrix. In that case, complete pivoting in the first QR factorizations provides accuracy dependent on the condition number of C, and independent of D1, D2. Such higher accuracy is not completely understood theoretically, but it works well in practice. Further, if A can be written as A = B*D, with well-conditioned B and some diagonal D, then the high accuracy is guaranteed, both theoretically and in software, independent of D. For more details see [1], [2].
The computational range for the singular values can be the full range ( UNDERFLOW,OVERFLOW ), provided that the machine arithmetic and the BLAS & LAPACK routines called by CGEJSV are implemented to work in that range. If that is not the case, then the restriction for safe computation with the singular values in the range of normalized IEEE numbers is that the spectral condition number kappa(A)=sigma_max(A)/sigma_min(A) does not overflow. This code (CGEJSV) is best used in this restricted range, meaning that singular values of magnitude below ||A||_2 / SLAMCH('O') are returned as zeros. See JOBR for details on this.
Further, this implementation is somewhat slower than the one described in [1,2] due to replacement of some non-LAPACK components, and because the choice of some tuning parameters in the iterative part (CGESVJ) is left to the implementer on a particular machine.
The rank revealing QR factorization (in this code: CGEQP3) should be implemented as in [3]. We have a new version of CGEQP3 under development that is more robust than the current one in LAPACK, with a cleaner cut in rank deficient cases. It will be available in the SIGMA library [4].
If M is much larger than N, it is obvious that the initial QRF with column pivoting can be preprocessed by the QRF without pivoting. That well known trick is not used in CGEJSV because in some cases heavy row weighting can be treated with complete pivoting. The overhead in cases M much larger than N is then only due to pivoting, but the benefits in terms of accuracy have prevailed. The implementer/user can incorporate this extra QRF step easily. The implementer can also improve data movement (matrix transpose, matrix copy, matrix transposed copy) - this implementation of CGEJSV uses only the simplest, naive data movement.
Okay the way this whole section is just "we could make it faster but accuracy ate and that's that" β iconic behavior honestly. π
Contributor: πΈ
Zlatko Drmac (Zagreb, Croatia)
References: π
- [1] Z. Drmac and K. Veselic: New fast and accurate Jacobi SVD algorithm I. SIAM J. Matrix Anal. Appl. Vol. 35, No. 2 (2008), pp. 1322-1342. LAPACK Working note 169.
- [2] Z. Drmac and K. Veselic: New fast and accurate Jacobi SVD algorithm II. SIAM J. Matrix Anal. Appl. Vol. 35, No. 2 (2008), pp. 1343-1362. LAPACK Working note 170.
- [3] Z. Drmac and Z. Bujanovic: On the failure of rank-revealing QR factorization software - a case study. ACM Trans. Math. Softw. Vol. 35, No 2 (2008), pp. 1-28. LAPACK Working note 176.
- [4] Z. Drmac: SIGMA - mathematical software library for accurate SVD, PSV, QSVD, (H,K)-SVD computations. Department of Mathematics, University of Zagreb, 2008, 2016.
Bugs, examples and comments: π
Please report all bugs and send interesting examples and/or comments to drmac@math.hr. Thank you.
Not the author personally asking for your bugs like a group chat β we love a responsive king fr fr. π«Ά
subroutine cgesdd π¦
subroutine cgesdd (character JOBZ, integer M, integer N, complex, dimension(
lda, * ) A, integer LDA, real, dimension( * ) S, complex, dimension(
ldu, * ) U, integer LDU, complex, dimension( ldvt, * ) VT, integer LDVT,
complex, dimension( * ) WORK, integer LWORK, real, dimension( * ) RWORK,
integer, dimension( * ) IWORK, integer INFO)
CGESDD
Purpose: β
CGESDD computes the singular value decomposition (SVD) of a complex M-by-N matrix A, optionally computing the left and/or right singular vectors, by using divide-and-conquer method. The SVD is written
A = U * SIGMA * conjugate-transpose(V)
where SIGMA is an M-by-N matrix which is zero except for its min(m,n) diagonal elements, U is an M-by-M unitary matrix, and V is an N-by-N unitary matrix. The diagonal elements of SIGMA are the singular values of A; they are real and non-negative, and are returned in descending order. The first min(m,n) columns of U and V are the left and right singular vectors of A.
Note that the routine returns VT = V**H, not V.
The divide and conquer algorithm makes very mild assumptions about floating point arithmetic. It will work on machines with a guard digit in add/subtract, or on those binary machines without guard digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. It could conceivably fail on hexadecimal or decimal machines without guard digits, but we know of none.
She said "very mild assumptions" and then listed four Crays by name like a flex. The confidence?? Immaculate. π
Parameters π§
JOBZ
JOBZ is CHARACTER*1 β it picks what we compute for U and V**H. The options are:
'A'β allMcolumns ofUand allNrows ofV**Hare returned in the arraysUandVT;'S'β the firstmin(M,N)columns ofUand the firstmin(M,N)rows ofV**Hare returned in the arraysUandVT;'O'β ifM >= N, the firstNcolumns ofUare overwritten in the arrayAand all rows ofV**Hare returned in the arrayVT; otherwise, all columns ofUare returned in the arrayUand the firstMrows ofV**Hare overwritten in the arrayA;'N'β no columns ofUor rows ofV**Hare computed.
M is INTEGER β the number of rows of the input matrix A. M >= 0. π
N is INTEGER β the number of columns of the input matrix A. N >= 0. π
A is COMPLEX array, dimension (LDA,N). On entry, the M-by-N matrix A. On exit:
- if
JOBZ = 'O',Ais overwritten with the firstNcolumns ofU(the left singular vectors, stored columnwise) ifM >= N;Ais overwritten with the firstMrows ofV**H(the right singular vectors, stored rowwise) otherwise. - if
JOBZ .ne. 'O', the contents ofAare destroyed. π
LDA is INTEGER β the leading dimension of the array A. LDA >= max(1,M).
S is REAL array, dimension (min(M,N)) β the singular values of A, sorted so that S(i) >= S(i+1). β¨
U is COMPLEX array, dimension (LDU,UCOL). UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N; UCOL = min(M,N) if JOBZ = 'S'. If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M unitary matrix U; if JOBZ = 'S', U contains the first min(M,N) columns of U (the left singular vectors, stored columnwise); if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
LDU is INTEGER β the leading dimension of the array U. LDU >= 1; if JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.
VT is COMPLEX array, dimension (LDVT,N). If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the N-by-N unitary matrix V**H; if JOBZ = 'S', VT contains the first min(M,N) rows of V**H (the right singular vectors, stored rowwise); if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
LDVT is INTEGER β the leading dimension of the array VT. LDVT >= 1; if JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N; if JOBZ = 'S', LDVT >= min(M,N).
WORK is COMPLEX array, dimension (MAX(1,LWORK)). On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
LWORK is INTEGER β the dimension of the array WORK. LWORK >= 1. If LWORK = -1, a workspace query is assumed. The optimal size for the WORK array is calculated and stored in WORK(1), and no other work except argument checking is performed.
Let mx = max(M,N) and mn = min(M,N).
- If
JOBZ = 'N',LWORK >= 2*mn + mx. - If
JOBZ = 'O',LWORK >= 2*mn*mn + 2*mn + mx. - If
JOBZ = 'S',LWORK >= mn*mn + 3*mn. - If
JOBZ = 'A',LWORK >= mn*mn + 2*mn + mx.
These are not tight minimums in all cases; see comments inside code. For good performance, LWORK should generally be larger; a query is recommended. π«Ά
RWORK is REAL array, dimension (MAX(1,LRWORK)). Let mx = max(M,N) and mn = min(M,N).
- If
JOBZ = 'N',LRWORK >= 5*mn(LAPACK <= 3.6 needs7*mn); - else if
mx >> mn,LRWORK >= 5*mn*mn + 5*mn; - else
LRWORK >= max( 5*mn*mn + 5*mn, 2*mx*mn + 2*mn*mn + mn ).
IWORK is INTEGER array, dimension (8*min(M,N)).
INFO is INTEGER:
< 0: ifINFO = -i, thei-th argument had an illegal value.= -4: ifAhad aNANentry.> 0: The updating process ofSBDSDCdid not converge.= 0: successful exit.
β¨ Author β¨
- Univ. of Tennessee
- Univ. of California Berkeley
- Univ. of Colorado Denver
- NAG Ltd.
π Contributors π
Ming Gu and Huan Ren, Computer Science Division, University of California at Berkeley, USA.
π¦ subroutine cgesvd π¦
subroutine cgesvd (character JOBU, character JOBVT, integer M, integer N,
complex, dimension( lda, * ) A, integer LDA, real, dimension( * ) S,
complex, dimension( ldu, * ) U, integer LDU, complex, dimension( ldvt, *
) VT, integer LDVT, complex, dimension( * ) WORK, integer LWORK, real,
dimension( * ) RWORK, integer INFO)
CGESVD computes the singular value decomposition (SVD) for GE matrices. π
π Purpose π
CGESVD computes the singular value decomposition (SVD) of a complex M-by-N matrix A, optionally computing the left and/or right singular vectors. The SVD is written
A = U * SIGMA * conjugate-transpose(V)
where SIGMA is an M-by-N matrix which is zero except for its min(m,n) diagonal elements, U is an M-by-M unitary matrix, and V is an N-by-N unitary matrix. The diagonal elements of SIGMA are the singular values of A; they are real and non-negative, and are returned in descending order. The first min(m,n) columns of U and V are the left and right singular vectors of A.
Note that the routine returns V**H, not V. π«Ά
πΈ Parameters πΈ
JOBU is CHARACTER*1 β specifies options for computing all or part of the matrix U:
'A'β allMcolumns ofUare returned in arrayU:'S'β the firstmin(m,n)columns ofU(the left singular vectors) are returned in the arrayU;'O'β the firstmin(m,n)columns ofU(the left singular vectors) are overwritten on the arrayA;'N'β no columns ofU(no left singular vectors) are computed.
JOBVT is CHARACTER*1 β specifies options for computing all or part of the matrix V**H:
'A'β allNrows ofV**Hare returned in the arrayVT;'S'β the firstmin(m,n)rows ofV**H(the right singular vectors) are returned in the arrayVT;'O'β the firstmin(m,n)rows ofV**H(the right singular vectors) are overwritten on the arrayA;'N'β no rows ofV**H(no right singular vectors) are computed.
JOBVTandJOBUcannot both be'O'.
M is INTEGER β the number of rows of the input matrix A. M >= 0.
N is INTEGER β the number of columns of the input matrix A. N >= 0.
A is COMPLEX array, dimension (LDA,N). On entry, the M-by-N matrix A. On exit,
- if
JOBU = 'O',Ais overwritten with the firstmin(m,n)columns ofU(the left singular vectors, stored columnwise); - if
JOBVT = 'O',Ais overwritten with the firstmin(m,n)rows ofV**H(the right singular vectors, stored rowwise); - if
JOBU .ne. 'O'andJOBVT .ne. 'O', the contents ofAare destroyed. π
LDA is INTEGER β the leading dimension of the array A. LDA >= max(1,M).
S is REAL array, dimension (min(M,N)) β the singular values of A, sorted so that S(i) >= S(i+1).
U is COMPLEX array, dimension (LDU,UCOL) ((LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'). If JOBU = 'A', U contains the M-by-M unitary matrix U; if JOBU = 'S', U contains the first min(m,n) columns of U (the left singular vectors, stored columnwise); if JOBU = 'N' or 'O', U is not referenced.
LDU is INTEGER β the leading dimension of the array U. LDU >= 1; if JOBU = 'S' or 'A', LDU >= M.
VT is COMPLEX array, dimension (LDVT,N). If JOBVT = 'A', VT contains the N-by-N unitary matrix V**H; if JOBVT = 'S', VT contains the first min(m,n) rows of V**H (the right singular vectors, stored rowwise); if JOBVT = 'N' or 'O', VT is not referenced.
LDVT is INTEGER β the leading dimension of the array VT. LDVT >= 1; if JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
WORK is COMPLEX array, dimension (MAX(1,LWORK)). On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
LWORK is INTEGER β the dimension of the array WORK. LWORK >= MAX(1,2*MIN(M,N)+MAX(M,N)). For good performance, LWORK should generally be larger.
If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA.
RWORK is REAL array, dimension (5*min(M,N)). On exit, if INFO > 0, RWORK(1:MIN(M,N)-1) contains the unconverged superdiagonal elements of an upper bidiagonal matrix B whose diagonal is in S (not necessarily sorted). B satisfies A = U * B * VT, so it has the same singular values as A, and singular vectors related by U and VT.
INFO
INFOisINTEGERβ here's the tea β:= 0: successful exit. π< 0: ifINFO = -i, the i-th argument had an illegal value. π> 0: ifCBDSQRdid not converge,INFOspecifies how many superdiagonals of an intermediate bidiagonal formBdid not converge to zero. See the description ofRWORKabove for details. π
β¨ Author β¨
Shoutout to the legends who wrote this:
- Univ. of Tennessee
- Univ. of California Berkeley
- Univ. of Colorado Denver
- NAG Ltd.
π subroutine cgesvdq π
subroutine cgesvdq (character JOBA, character JOBP, character JOBR,
character JOBU, character JOBV, integer M, integer N, complex,
dimension( lda, * ) A, integer LDA, real, dimension( * ) S, complex,
dimension( ldu, * ) U, integer LDU, complex, dimension( ldv, * ) V,
integer LDV, integer NUMRANK, integer, dimension( * ) IWORK, integer
LIWORK, complex, dimension( * ) CWORK, integer LCWORK, real, dimension(
* ) RWORK, integer LRWORK, integer INFO)
CGESVDQ computes the singular value decomposition (SVD) with a QR-Preconditioned QR SVD Method for GE matrices. bestie, it's giving iconic. π
π« Purpose π«
CGESVDQ computes the singular value decomposition (SVD) of a complex M-by-N matrix A, where M >= N. The SVD of A is written as
[++] [xx] [x0] [xx]
A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx]
[++] [xx]
where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal matrix, and V is an N-by-N unitary matrix. The diagonal elements of SIGMA are the singular values of A. The columns of U and V are the left and the right singular vectors of A, respectively. no cap. β¨
π Parameters π
JOBAJOBAisCHARACTER*1. Specifies the level of accuracy in the computed SVD.= 'A': The requested accuracy corresponds to having the backward error bounded by|| delta A ||_F <= f(m,n) * EPS * || A ||_F, whereEPS = SLAMCH('Epsilon'). This authorisesCGESVDQto truncate the computed triangular factor in a rank revealing QR factorization whenever the truncated part is below the threshold of the order ofEPS * ||A||_F. This is aggressive truncation level. π₯= 'M': Similarly as with'A', but the truncation is more gentle: it is allowed only when there is a drop on the diagonal of the triangular factor in the QR factorization. This is medium truncation level. β¨= 'H': High accuracy requested. No numerical rank determination based on the rank revealing QR factorization is attempted. π= 'E': Same as'H', and in addition the condition number of column scaledAis estimated and returned inRWORK(1).N^(-1/4)*RWORK(1) <= ||pinv(A_scaled)||_2 <= N^(1/4)*RWORK(1). π«Ά
JOBPJOBPisCHARACTER*1.= 'P': The rows ofAare ordered in decreasing order with respect to||A(i,:)||_\infty. This enhances numerical accuracy at the cost of extra data movement. Recommended for numerical robustness. π= 'N': No row pivoting. π
JOBRJOBRisCHARACTER*1.= 'T': After the initial pivoted QR factorization,CGESVDis applied to the adjointR**Hof the computed triangular factorR. This involves some extra data movement (matrix transpositions). Useful for experiments, research and development. π§ͺ= 'N': The triangular factorRis given as input toCGESVD. This may be preferred as it involves less data movement. π
JOBUJOBUisCHARACTER*1.= 'A': AllMleft singular vectors are computed and returned in the matrixU. See the description ofU. π= 'S'or'U':N = min(M,N)left singular vectors are computed and returned in the matrixU. See the description ofU. β¨= 'R': Numerical rankNUMRANKis determined and onlyNUMRANKleft singular vectors are computed and returned in the matrixU. π= 'F': TheNleft singular vectors are returned in factored form as the product of theQfactor from the initial QR factorization and theNleft singular vectors of(R**H , 0)**H. If row pivoting is used, then the necessary information on the row pivoting is stored inIWORK(N+1:N+M-1). π§©= 'N': The left singular vectors are not computed. π«
JOBVJOBVisCHARACTER*1.= 'A', 'V': AllNright singular vectors are computed and returned in the matrixV. π= 'R': Numerical rankNUMRANKis determined and onlyNUMRANKright singular vectors are computed and returned in the matrixV. This option is allowed only ifJOBU = 'R'orJOBU = 'N'; otherwise it is illegal. β οΈ= 'N': The right singular vectors are not computed. π
MMisINTEGER. The number of rows of the input matrixA.M >= 0. πNNisINTEGER. The number of columns of the input matrixA.M >= N >= 0. πAAisCOMPLEXarray of dimensionsLDA x N. On entry, the input matrixA. On exit, ifJOBU .NE. 'N'orJOBV .NE. 'N', the lower triangle ofAcontains the Householder vectors as stored byCGEQP3. IfJOBU = 'F', these Householder vectors together withCWORK(1:N)can be used to restore theQfactors from the initial pivoted QR factorization ofA. See the description ofU. πLDALDAisINTEGER. The leading dimension of the arrayA.LDA >= max(1,M). πSSisREALarray of dimensionN. The singular values ofA, ordered so thatS(i) >= S(i+1). πUUisCOMPLEXarray, dimensionLDU x MifJOBU = 'A'; see the description ofLDU. In this case, on exit,Ucontains theMleft singular vectors.LDU x NifJOBU = 'S', 'U', 'R'; see the description ofLDU. In this case,Ucontains the leadingNor the leadingNUMRANKleft singular vectors.LDU x NifJOBU = 'F'; see the description ofLDU. In this caseUcontainsN x Nunitary matrix that can be used to form the left singular vectors.- If
JOBU = 'N',Uis not referenced. π»
LDULDUisINTEGER. The leading dimension of the arrayU.- If
JOBU = 'A', 'S', 'U', 'R',LDU >= max(1,M). - If
JOBU = 'F',LDU >= max(1,N). - Otherwise,
LDU >= 1. π
- If
VVisCOMPLEXarray, dimensionLDV x NifJOBV = 'A', 'V', 'R'or ifJOBA = 'E'.- If
JOBV = 'A', or'V',Vcontains theN-by-Nunitary matrixV**H; - If
JOBV = 'R',Vcontains the firstNUMRANKrows ofV**H(the right singular vectors, stored rowwise, of theNUMRANKlargest singular values). - If
JOBV = 'N'andJOBA = 'E',Vis used as a workspace. - If
JOBV = 'N', andJOBA.NE.'E',Vis not referenced. π«₯
LDVLDVisINTEGER. The leading dimension of the arrayV.- If
JOBV = 'A', 'V', 'R', orJOBA = 'E',LDV >= max(1,N). - Otherwise,
LDV >= 1. π
- If
NUMRANKNUMRANKisINTEGER.NUMRANKis the numerical rank first determined after the rank revealing QR factorization, following the strategy specified by the value ofJOBA. IfJOBV = 'R'andJOBU = 'R', onlyNUMRANKleading singular values and vectors are then requested in the call ofCGESVD. The final value ofNUMRANKmight be further reduced if some singular values are computed as zeros. π’IWORKIWORKisINTEGERarray, dimension(max(1, LIWORK)).- On exit,
IWORK(1:N)contains column pivoting permutation of the rank revealing QR factorization. - If
JOBP = 'P',IWORK(N+1:N+M-1)contains the indices of the sequence of row swaps used in row pivoting. These can be used to restore the left singular vectors in the caseJOBU = 'F'. - If
LIWORK,LCWORK, orLRWORK = -1, then on exit, ifINFO = 0,IWORK(1)returns the minimalLIWORK. π
- On exit,
LIWORKLIWORKisINTEGER. The dimension of the arrayIWORK.LIWORK >= N + M - 1, ifJOBP = 'P';LIWORK >= NifJOBP = 'N'.- If
LIWORK = -1, then a workspace query is assumed; the routine only calculates and returns the optimal and minimal sizes for theCWORK,IWORK, andRWORKarrays, and no error message related toLCWORKis issued byXERBLA. π
CWORKCWORKisCOMPLEXarray, dimension(max(2, LCWORK)), used as a workspace.- On exit, if, on entry,
LCWORK.NE.-1,CWORK(1:N)contains parameters needed to recover theQfactor from the QR factorization computed byCGEQP3. - If
LIWORK,LCWORK, orLRWORK = -1, then on exit, ifINFO = 0,CWORK(1)returns the optimalLCWORK, andCWORK(2)returns the minimalLCWORK. π οΈ
- On exit, if, on entry,
LCWORKLCWORKisINTEGER. The dimension of the arrayCWORK. It is determined as follows: LetLWQP3 = N+1,LWCON = 2*N, and let
LWUNQ = { MAX( N, 1 ), if JOBU = 'R', 'S', or 'U'
{ MAX( M, 1 ), if JOBU = 'A'
LWSVD = MAX( 3*N, 1 )
LWLQF = MAX( N/2, 1 ), LWSVD2 = MAX( 3*(N/2), 1 ), LWUNLQ = MAX( N, 1 ),
LWQRF = MAX( N/2, 1 ), LWUNQ2 = MAX( N, 1 )
Then the minimal value of LCWORK is:
= MAX( N + LWQP3, LWSVD ) if only the singular values are needed;
= MAX( N + LWQP3, LWCON, LWSVD ) if only the singular values are needed,
and a scaled condition estimate requested;
= N + MAX( LWQP3, LWSVD, LWUNQ ) if the singular values and the left
singular vectors are requested;
= N + MAX( LWQP3, LWCON, LWSVD, LWUNQ ) if the singular values and the left
singular vectors are requested, and also
a scaled condition estimate requested;
okay so this bit is all about the workspace size formulas β lowkey intimidating but honestly just vibes once you break it down π
= N + MAX( LWQP3, LWSVD ) if the singular values and the right
singular vectors are requested;
= N + MAX( LWQP3, LWCON, LWSVD ) if the singular values and the right
singular vectors are requested, and also
a scaled condition etimate requested;
= N + MAX( LWQP3, LWSVD, LWUNQ ) if the full SVD is requested with JOBV = 'R';
independent of JOBR;
= N + MAX( LWQP3, LWCON, LWSVD, LWUNQ ) if the full SVD is requested,
JOBV = 'R' and, also a scaled condition
estimate requested; independent of JOBR;
= MAX( N + MAX( LWQP3, LWSVD, LWUNQ ),
N + MAX( LWQP3, N/2+LWLQF, N/2+LWSVD2, N/2+LWUNLQ, LWUNQ) ) if the
full SVD is requested with JOBV = 'A' or 'V', and
JOBR ='N'
= MAX( N + MAX( LWQP3, LWCON, LWSVD, LWUNQ ),
N + MAX( LWQP3, LWCON, N/2+LWLQF, N/2+LWSVD2, N/2+LWUNLQ, LWUNQ ) )
if the full SVD is requested with JOBV = 'A' or 'V', and
JOBR ='N', and also a scaled condition number estimate
requested.
= MAX( N + MAX( LWQP3, LWSVD, LWUNQ ),
N + MAX( LWQP3, N/2+LWQRF, N/2+LWSVD2, N/2+LWUNQ2, LWUNQ ) ) if the
full SVD is requested with JOBV = 'A', 'V', and JOBR ='T'
= MAX( N + MAX( LWQP3, LWCON, LWSVD, LWUNQ ),
N + MAX( LWQP3, LWCON, N/2+LWQRF, N/2+LWSVD2, N/2+LWUNQ2, LWUNQ ) )
if the full SVD is requested with JOBV = 'A', 'V' and
JOBR ='T', and also a scaled condition number estimate
requested.
and then, the moment you've all been waiting for β the floor:
Finally, LCWORK must be at least two: LCWORK = MAX( 2, LCWORK ).
if LCWORK = -1, bestie, it's a workspace query β the routine is basically like "bestie I'm not doing the whole thing, I'm just gonna do the math and tell you what size arrays you need." It only calculates and returns the optimal and minimal sizes for the CWORK, IWORK, and RWORK arrays, and XERBLA won't yell at you about LCWORK at all. no cap. π
π RWORK π
RWORK is a REAL array, dimension (max(1, LRWORK)). On exit, here's the tea:
- If
JOBA = 'E', thenRWORK(1)contains an estimate of the condition number of column scaledA. IfA = C * DwhereDis diagonal andChas unit columns in the Euclidean norm, then, assuming full column rank:
N^(-1/4) * RWORK(1) <= ||pinv(C)||_2 <= N^(1/4) * RWORK(1).
Otherwise, RWORK(1) = -1.
RWORK(2)contains the number of singular values computed as exact zeros inCGESVDapplied to the upper triangular or trapezoidalR(from the initial QR factorization). In case of early exit (no call toCGESVD, such as in the case of zero matrix)RWORK(2) = -1.
and also β if LIWORK, LCWORK, or LRWORK = -1, then on exit, if INFO = 0, RWORK(1) returns the minimal LRWORK. cute, right? β¨
π¦ LRWORK π¦
LRWORK is INTEGER. It's the dimension of the array RWORK.
- If
JOBP ='P', thenLRWORK >= MAX(2, M, 5*N); - Otherwise,
LRWORK >= MAX(2, 5*N).
and if LRWORK = -1, again, workspace query mode β the routine only calculates and returns the optimal and minimal sizes for the CWORK, IWORK, and RWORK arrays, and no error message related to LCWORK is issued by XERBLA. (yes, it says LCWORK here too, we're just keeping it exactly as-is π)
πΈ INFO πΈ
INFO is INTEGER.
= 0: successful exit. slay. π< 0: ifINFO = -i, the i-th argument had an illegal value. rude.> 0: ifCBDSQRdid not converge,INFOspecifies how many superdiagonals of an intermediate bidiagonal formB(computed inCGESVD) did not converge to zero. not converging is not the vibe, bestie, pls look into it.
π Further Details: π
- The data movement (matrix transpose) is coded using simple nested DO-loops because BLAS and LAPACK do not provide corresponding subroutines. Those DO-loops are easily identified in this source code β by the
CONTINUEstatements labeled with11**. In an optimized version of this code, the nested DO loops should be replaced with calls to an optimized subroutine. - This code scales
Aby1/SQRT(M)if the largestABS(A(i,j))could cause column norm overflow. This is the minial precaution and it is left to the SVD routine (CGESVD) to do its own preemptive scaling if potential over- or underflows are detected. To avoid repeated scanning of the arrayA, an optimal implementation would do all necessary scaling before callingCGESVDand the scaling inCGESVDcan be switched off. - Other comments related to code optimization are given in comments in the code, enlosed in
[[double brackets]].
π Bugs, examples and comments π
Please report all bugs and send interesting examples and/or comments to drmac@math.hr. Thank you. (genuinely, they said thank you, that's so sweet π«Ά)
β References β
[1] Zlatko Drmac, Algorithm 977: A QR-Preconditioned QR SVD Method for Computing the SVD with High Accuracy. ACM Trans. Math. Softw. 44(1): 11:1-11:30 (2017)
SIGMA library, xGESVDQ section updated February 2016. Developed and coded by Zlatko Drmac, Department of Mathematics University of Zagreb, Croatia, drmac@math.hr.
π Contributors: π
Developed and coded by Zlatko Drmac, Department of Mathematics University of Zagreb, Croatia, drmac@math.hr.
π Author π
- Univ. of Tennessee
- Univ. of California Berkeley
- Univ. of Colorado Denver
- NAG Ltd.
π§ subroutine cgesvdx π§
subroutine cgesvdx (character JOBU, character JOBVT, character RANGE,
integer M, integer N, complex, dimension( lda, * ) A, integer LDA, real
VL, real VU, integer IL, integer IU, integer NS, real, dimension( * ) S,
complex, dimension( ldu, * ) U, integer LDU, complex, dimension( ldvt, *
) VT, integer LDVT, complex, dimension( * ) WORK, integer LWORK, real,
dimension( * ) RWORK, integer, dimension( * ) IWORK, integer INFO)
CGESVDX computes the singular value decomposition (SVD) for GE matrices. periodt. π
Purpose:
CGESVDX computes the singular value decomposition (SVD) of a complex M-by-N matrix A, optionally computing the left and/or right singular vectors. The SVD is written like this:
A = U * SIGMA * transpose(V)
where SIGMA is an M-by-N matrix which is zero except for its min(m,n) diagonal elements, U is an M-by-M unitary matrix, and V is an N-by-N unitary matrix. The diagonal elements of SIGMA are the singular values of A; they are real and non-negative, and are returned in descending order. The first min(m,n) columns of U and V are the left and right singular vectors of A.
CGESVDX uses an eigenvalue problem for obtaining the SVD, which allows for the computation of a subset of singular values and vectors. See SBDSVDX for details.
Note that the routine returnsV**T, notV. it's giving "I brought the transposed version, hope that's okay bestie" π
β¨ Parameters β¨
JOBUβJOBUisCHARACTER*1. Specifies options for computing all or part of the matrixU:= 'V': the firstmin(m,n)columns ofU(the left singular vectors) or as specified byRANGEare returned in the arrayU;= 'N': no columns ofU(no left singular vectors) are computed.
JOBVTβJOBVTisCHARACTER*1. Specifies options for computing all or part of the matrixV**T:= 'V': the firstmin(m,n)rows ofV**T(the right singular vectors) or as specified byRANGEare returned in the arrayVT;= 'N': no rows ofV**T(no right singular vectors) are computed.
RANGEβRANGEisCHARACTER*1:= 'A': all singular values will be found.= 'V': all singular values in the half-open interval(VL,VU]will be found.= 'I': theIL-th throughIU-th singular values will be found.
MβMis INTEGER. The number of rows of the input matrixA.M >= 0.NβNis INTEGER. The number of columns of the input matrixA.N >= 0.AβAis COMPLEX array, dimension(LDA,N). On entry, the M-by-N matrixA. On exit, the contents ofAare destroyed. bye bestie, she's gone πLDAβLDAis INTEGER. The leading dimension of the arrayA.LDA >= max(1,M).VLβVLis REAL. IfRANGE='V', the lower bound of the interval to be searched for singular values.VU > VL. Not referenced ifRANGE = 'A'or'I'.VUβVUis REAL. IfRANGE='V', the upper bound of the interval to be searched for singular values.VU > VL. Not referenced ifRANGE = 'A'or'I'.ILβILis INTEGER. IfRANGE='I', the index of the smallest singular value to be returned.1 <= IL <= IU <= min(M,N), ifmin(M,N) > 0. Not referenced ifRANGE = 'A'or'V'.IUβIUis INTEGER. IfRANGE='I', the index of the largest singular value to be returned.1 <= IL <= IU <= min(M,N), ifmin(M,N) > 0. Not referenced ifRANGE = 'A'or'V'.NSβNSis INTEGER. The total number of singular values found,0 <= NS <= min(M,N). IfRANGE = 'A',NS = min(M,N); ifRANGE = 'I',NS = IU-IL+1.SβSis REAL array, dimension(min(M,N)). The singular values ofA, sorted so thatS(i) >= S(i+1). descending order, the way it should be β¨UβUis COMPLEX array, dimension(LDU,UCOL). IfJOBU = 'V',Ucontains columns ofU(the left singular vectors, stored columnwise) as specified byRANGE; ifJOBU = 'N',Uis not referenced. Note: The user must ensure thatUCOL >= NS; ifRANGE = 'V', the exact value ofNSis not known in advance and an upper bound must be used.LDUβLDUis INTEGER. The leading dimension of the arrayU.LDU >= 1; ifJOBU = 'V',LDU >= M.VTβVTβ aCOMPLEXarray, dimension(LDVT,N). IfJOBVT = 'V', bestie,VTis holding the rows ofV**Tβ that's the right singular vectors, stored rowwise β exactly asRANGEtold it to. IfJOBVT = 'N', thenVTis literally not referenced, it's just vibing in the background, unbothered. π¦
Note: you β yes YOU β must make sure thatLDVT >= NS. And ifRANGE = 'V', the exact value ofNSis not known in advance, so you have to use an upper bound. No cap, plan ahead. π
LDVTβINTEGER. The leading dimension of the arrayVT. Rules:LDVT >= 1; and ifJOBVT = 'V', thenLDVT >= NS(see above, babes).WORKβCOMPLEXarray, dimension(MAX(1,LWORK)). On exit, ifINFO = 0,WORK(1)returns the optimalLWORK; β¨LWORKβINTEGER. The dimension of the arrayWORK. Here's the tea β on the minimums:LWORK >= MAX(1,MIN(M,N)*(MIN(M,N)+4))for the paths (see the comments inside the code, iykyk):PATH 1(M much larger than N)PATH 1t(N much larger than M)
LWORK >= MAX(1,MIN(M,N)*2+MAX(M,N))for the other paths.
For good performance, LWORK should generally be larger. Bigger is better, no notes. π
If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. Sneaky but iconic.
RWORKβREALarray, dimension(MAX(1,LRWORK)). AndLRWORK >= MIN(M,N)*(MIN(M,N)*2+15*MIN(M,N)). That's a lot of RWORK but okay, she's worth it. πΈIWORKβINTEGERarray, dimension(12*MIN(M,N)). IfINFO = 0, the firstNSelements ofIWORKare zero. IfINFO > 0, thenIWORKcontains the indices of the eigenvectors that failed to converge inSBDSVDX/SSTEVX. π (they tried their best)INFOβINTEGER, the vibe report:= 0: successful exit. slay! π< 0: ifINFO = -i, the i-th argument had an illegal value. π©> 0: ifINFO = i, then i eigenvectors failed to converge inSBDSVDX/SSTEVX. And ifINFO = N*2 + 1, an internal error occurred inSBDSVDX. π
β¨ Author β¨
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.
π subroutine cggsvd3 π
subroutine cggsvd3 (character JOBU, character JOBV, character JOBQ, integer
M, integer N, integer P, integer K, integer L, complex, dimension( lda,
* ) A, integer LDA, complex, dimension( ldb, * ) B, integer LDB, real,
dimension( * ) ALPHA, real, dimension( * ) BETA, complex, dimension(
ldu, * ) U, integer LDU, complex, dimension( ldv, * ) V, integer LDV,
complex, dimension( ldq, * ) Q, integer LDQ, complex, dimension( * )
WORK, integer LWORK, real, dimension( * ) RWORK, integer, dimension( * )
IWORK, integer INFO)
CGGSVD3 computes the singular value decomposition (SVD) for OTHER matrices. Yes, other matrices. She's versatile like that. π
π¦ Purpose:
CGGSVD3 computes the generalized singular value decomposition (GSVD) of an M-by-N complex matrix A and P-by-N complex matrix B:
U**H*A*Q = D1*( 0 R ), V**H*B*Q = D2*( 0 R )
where U, V and Q are unitary matrices.
Let K+L = the effective numerical rank of the matrix (A**H,B**H)**H, then R is a (K+L)-by-(K+L) nonsingular upper triangular matrix, D1 and D2 are M-by-(K+L) and P-by-(K+L) 'diagonal' matrices and of the following structures, respectively:
If M-K-L >= 0,
K L
D1 = K ( I 0 )
L ( 0 C )
M-K-L ( 0 0 )
K L
D2 = L ( 0 S )
P-L ( 0 0 )
N-K-L K L
( 0 R ) = K ( 0 R11 R12 )
L ( 0 0 R22 )
where
C = diag( ALPHA(K+1), ... , ALPHA(K+L) ),
S = diag( BETA(K+1), ... , BETA(K+L) ),
C**2 + S**2 = I.
R is stored in A(1:K+L,N-K-L+1:N) on exit. π
If M-K-L < 0,
K M-K K+L-M
D1 = K ( I 0 0 )
M-K ( 0 C 0 )
K M-K K+L-M
D2 = M-K ( 0 S 0 )
K+L-M ( 0 0 I )
P-L ( 0 0 0 )
N-K-L K M-K K+L-M
( 0 R ) = K ( 0 R11 R12 R13 )
M-K ( 0 0 R22 R23 )
K+L-M ( 0 0 0 R33 )
where
C = diag( ALPHA(K+1), ... , ALPHA(M) ),
S = diag( BETA(K+1), ... , BETA(M) ),
C**2 + S**2 = I.
(R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N), and R33 is stored in B(M-K+1:L,N+M-K-L+1:N) on exit.
( 0 R22 R23 )
The routine computes C, S, R, and optionally the unitary transformation matrices U, V and Q. Obsessed with her range honestly. π
In particular, if B is an N-by-N nonsingular matrix, then the GSVD of A and B implicitly gives the SVD of A*inv(B):
A*inv(B) = U*(D1*inv(D2))*V**H.
If ( A**H,B**H)**H has orthonormal columns, then the GSVD of A and B is also equal to the CS decomposition of A and B. Furthermore, the GSVD can be used to derive the solution of the eigenvalue problem:
A**H*A x = lambda* B**H*B x.
In some literature, the GSVD of A and B is presented in the form
U**H*A*X = ( 0 D1 ), V**H*B*X = ( 0 D2 )
where U and V are orthogonal and X is nonsingular, and D1 and D2 are ``diagonal''. The former GSVD form can be converted to the latter form by taking the nonsingular matrix X as
X = Q*( I 0 )
( 0 inv(R) )
β¨ Parameters β¨
JOBUβCHARACTER*1= 'U': Unitary matrix U is computed;= 'N': U is not computed.
JOBVβCHARACTER*1= 'V': Unitary matrix V is computed;= 'N': V is not computed.
JOBQβCHARACTER*1= 'Q': Unitary matrix Q is computed;= 'N': Q is not computed.
MβINTEGER. The number of rows of the matrix A.M >= 0.NβINTEGER. The number of columns of the matrices A and B.N >= 0.PβINTEGER. The number of rows of the matrix B.P >= 0.KβINTEGERLβINTEGER
On exit, K and L specify the dimension of the subblocks described in Purpose. K + L = effective numerical rank of (A**H,B**H)**H. π
AβCOMPLEXarray, dimension(LDA,N). On entry, the M-by-N matrix A. On exit, A contains the triangular matrix R, or part of R. See Purpose for details.LDAβINTEGER. The leading dimension of the array A.LDA >= max(1,M).BβCOMPLEXarray, dimension(LDB,N). On entry, the P-by-N matrix B. On exit, B contains part of the triangular matrix R ifM-K-L < 0. See Purpose for details.LDBβINTEGER. The leading dimension of the array B.LDB >= max(1,P).ALPHAβREALarray, dimension(N)BETAβREALarray, dimension(N)
On exit, ALPHA and BETA contain the generalized singular value pairs of A and B;
ALPHA(1:K) = 1,
BETA(1:K) = 0,
and if M-K-L >= 0,
ALPHA(K+1:K+L) = C,
BETA(K+1:K+L) = S,
or if M-K-L < 0,
ALPHA(K+1:M)=C, ALPHA(M+1:K+L)=0
BETA(K+1:M) =S, BETA(M+1:K+L) =1
and
ALPHA(K+L+1:N) = 0
BETA(K+L+1:N) = 0
UβCOMPLEXarray, dimension(LDU,M). IfJOBU = 'U', U contains the M-by-M unitary matrix U. IfJOBU = 'N', U is not referenced.LDUβINTEGER. The leading dimension of the array U.LDU >= max(1,M)ifJOBU = 'U';LDU >= 1otherwise.VβCOMPLEXarray, dimension(LDV,P). IfJOBV = 'V', V contains the P-by-P unitary matrix V. IfJOBV = 'N', V is not referenced.LDVβINTEGER. The leading dimension of the array V.LDV >= max(1,P)ifJOBV = 'V';LDV >= 1otherwise.QβCOMPLEXarray, dimension(LDQ,N). IfJOBQ = 'Q', Q contains the N-by-N unitary matrix Q. IfJOBQ = 'N', Q is not referenced.LDQβINTEGER. The leading dimension of the array Q.LDQ >= max(1,N)ifJOBQ = 'Q';LDQ >= 1otherwise.WORKβCOMPLEXarray, dimension(MAX(1,LWORK)). On exit, ifINFO = 0,WORK(1)returns the optimalLWORK. β¨LWORKβINTEGER. The dimension of the arrayWORK.
If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA.
RWORKβREALarray, dimension(2*N)IWORKβINTEGERarray, dimension(N). On exit,IWORKstores the sorting information. More precisely, the following loop will sortALPHA
for I = K+1, min(M,K+L)
swap ALPHA(I) and ALPHA(IWORK(I))
endfor
such that ALPHA(1) >= ALPHA(2) >= ... >= ALPHA(N). Sorted and gorgeous, she's giving organized. π
INFOβINTEGER= 0: successful exit.< 0: ifINFO = -i, the i-th argument had an illegal value.> 0: ifINFO = 1, the Jacobi-type procedure failed to converge. For further details, see subroutineCTGSJA. π
Internal Parameters:
TOLAβREALπTOLBβREALβ¨
TOLA and TOLB are the thresholds that decide the effective rank of (A**H,B**H)**H. Like, that's their whole job, bestie. π
Generally you set them to:
TOLA = MAX(M,N)*norm(A)*MACHEPS,
TOLB = MAX(P,N)*norm(B)*MACHEPS.
And lowkey important: the size of TOLA and TOLB may affect the size of backward errors of the decomposition. So don't just pick vibes, okay? π¦
πΈ Author πΈ
- Univ. of Tennessee
- Univ. of California Berkeley
- Univ. of Colorado Denver
- NAG Ltd.
π Contributors π
- Ming Gu and Huan Ren, Computer Science Division, University of California at Berkeley, USA
β Further Details β
CGGSVD3 replaces the deprecated subroutine CGGSVD. Yes babe, CGGSVD is giving β¨retiredβ¨ energy β it's deprecated, so like, move on, the glow-up is CGGSVD3. No cap. π
Okay so that's literally the whole page, and every single crumb of it was real. Not one fact skipped, not one option fumbled. We ate and left no crumbs. ππ
This lil masterpiece was generated automatically by Doxygen for LAPACK straight from the source code β so like, credit where credit's due π«Ά β and it's sitting pretty at Version 3.11.0, dated Sun Nov 27 2022. That's the vibe check, signed, sealed, slay. ππ§π
π¦ where this page comes from
- debian bookworm: liblapack-doc 3.11.0-2 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms