📄 sgelss.f
字号:
SUBROUTINE SGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, $ WORK, LWORK, INFO )** -- LAPACK driver routine (instrumented to count ops, version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1999** .. Scalar Arguments .. INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK REAL RCOND* ..* .. Array Arguments .. REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )* ..* Common blocks to return operation counts and timings* .. Common blocks .. COMMON / LATIME / OPS, ITCNT COMMON / LSTIME / OPCNT, TIMNG* ..* .. Scalars in Common .. REAL ITCNT, OPS* ..* .. Arrays in Common .. REAL OPCNT( 6 ), TIMNG( 6 )* ..** Purpose* =======** SGELSS computes the minimum norm solution to a real linear least* squares problem:** Minimize 2-norm(| b - A*x |).** using the singular value decomposition (SVD) of A. A is an M-by-N* matrix which may be rank-deficient.** Several right hand side vectors b and solution vectors x can be* handled in a single call; they are stored as the columns of the* M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix* X.** The effective rank of A is determined by treating as zero those* singular values which are less than RCOND times the largest singular* value.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** A (input/output) REAL array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, the first min(m,n) rows of A are overwritten with* its right singular vectors, stored rowwise.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input/output) REAL array, dimension (LDB,NRHS)* On entry, the M-by-NRHS right hand side matrix B.* On exit, B is overwritten by the N-by-NRHS solution* matrix X. If m >= n and RANK = n, the residual* sum-of-squares for the solution in the i-th column is given* by the sum of squares of elements n+1:m in that column.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,max(M,N)).** S (output) REAL array, dimension (min(M,N))* The singular values of A in decreasing order.* The condition number of A in the 2-norm = S(1)/S(min(m,n)).** RCOND (input) REAL* RCOND is used to determine the effective rank of A.* Singular values S(i) <= RCOND*S(1) are treated as zero.* If RCOND < 0, machine precision is used instead.** RANK (output) INTEGER* The effective rank of A, i.e., the number of singular values* which are greater than RCOND*S(1).** WORK (workspace/output) REAL array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= 1, and also:* LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS )* 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.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: the algorithm for computing the SVD failed to converge;* if INFO = i, i off-diagonal elements of an intermediate* bidiagonal form did not converge to zero.** =====================================================================** .. Parameters .. REAL ZERO, ONE PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 )* ..* .. Local Scalars .. LOGICAL LQUERY INTEGER BDSPAC, BDSQR, BL, CHUNK, GEBRD, GELQF, GELSS, $ GEMM, GEMV, GEQRF, I, IASCL, IBSCL, IE, IL, $ ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN, $ MAXWRK, MINMN, MINWRK, MM, MNTHR, NB, $ ORGBR, ORMBR, ORMLQ, ORMQR REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR, $ T1, T2* ..* .. Local Arrays .. REAL VDUM( 1 )* ..* .. External Subroutines .. EXTERNAL SBDSQR, SCOPY, SGEBRD, SGELQF, SGEMM, SGEMV, $ SGEQRF, SLABAD, SLACPY, SLASCL, SLASET, SORGBR, $ SORMBR, SORMLQ, SORMQR, SRSCL, XERBLA* ..* .. External Functions .. INTEGER ILAENV REAL SECOND, SLAMCH, SLANGE, SOPBL2, $ SOPBL3, SOPLA, SOPLA2 EXTERNAL SECOND, SLAMCH, SLANGE, SOPBL2, $ SOPBL3, SOPLA, SOPLA2, ILAENV* ..* .. Intrinsic Functions .. INTRINSIC REAL, MAX, MIN* ..* .. Data statements .. DATA BDSQR / 5 /, GEBRD / 3 /, GELQF / 2 /, $ GELSS / 1 /, GEMM / 6 /, GEMV / 6 /, $ GEQRF / 2 /, ORGBR / 4 /, ORMBR / 4 /, $ ORMLQ / 6 /, ORMQR / 2 /* ..* .. Executable Statements ..** Test the input arguments* INFO = 0 MINMN = MIN( M, N ) MAXMN = MAX( M, N ) MNTHR = ILAENV( 6, 'SGELSS', ' ', M, N, NRHS, -1 ) LQUERY = ( LWORK.EQ.-1 ) IF( M.LT.0 ) THEN INFO = -1 ELSE IF( N.LT.0 ) THEN INFO = -2 ELSE IF( NRHS.LT.0 ) THEN INFO = -3 ELSE IF( LDA.LT.MAX( 1, M ) ) THEN INFO = -5 ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THEN INFO = -7 END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.)* MINWRK = 1 IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THEN MAXWRK = 0 MM = M IF( M.GE.N .AND. M.GE.MNTHR ) THEN** Path 1a - overdetermined, with many more rows than columns* MM = N MAXWRK = MAX( MAXWRK, N+N*ILAENV( 1, 'SGEQRF', ' ', M, N, $ -1, -1 ) ) MAXWRK = MAX( MAXWRK, N+NRHS* $ ILAENV( 1, 'SORMQR', 'LT', M, NRHS, N, -1 ) ) END IF IF( M.GE.N ) THEN** Path 1 - overdetermined or exactly determined** Compute workspace needed for SBDSQR* BDSPAC = MAX( 1, 5*N ) MAXWRK = MAX( MAXWRK, 3*N+( MM+N )* $ ILAENV( 1, 'SGEBRD', ' ', MM, N, -1, -1 ) ) MAXWRK = MAX( MAXWRK, 3*N+NRHS* $ ILAENV( 1, 'SORMBR', 'QLT', MM, NRHS, N, -1 ) ) MAXWRK = MAX( MAXWRK, 3*N+( N-1 )* $ ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) ) MAXWRK = MAX( MAXWRK, BDSPAC ) MAXWRK = MAX( MAXWRK, N*NRHS ) MINWRK = MAX( 3*N+MM, 3*N+NRHS, BDSPAC ) MAXWRK = MAX( MINWRK, MAXWRK ) END IF IF( N.GT.M ) THEN** Compute workspace needed for SBDSQR* BDSPAC = MAX( 1, 5*M ) MINWRK = MAX( 3*M+NRHS, 3*M+N, BDSPAC ) IF( N.GE.MNTHR ) THEN** Path 2a - underdetermined, with many more columns* than rows* MAXWRK = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 ) MAXWRK = MAX( MAXWRK, M*M+4*M+2*M* $ ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) ) MAXWRK = MAX( MAXWRK, M*M+4*M+NRHS* $ ILAENV( 1, 'SORMBR', 'QLT', M, NRHS, M, -1 ) ) MAXWRK = MAX( MAXWRK, M*M+4*M+( M-1 )* $ ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) ) MAXWRK = MAX( MAXWRK, M*M+M+BDSPAC ) IF( NRHS.GT.1 ) THEN MAXWRK = MAX( MAXWRK, M*M+M+M*NRHS ) ELSE MAXWRK = MAX( MAXWRK, M*M+2*M ) END IF MAXWRK = MAX( MAXWRK, M+NRHS* $ ILAENV( 1, 'SORMLQ', 'LT', N, NRHS, M, -1 ) ) ELSE** Path 2 - underdetermined* MAXWRK = 3*M + ( N+M )*ILAENV( 1, 'SGEBRD', ' ', M, N, $ -1, -1 ) MAXWRK = MAX( MAXWRK, 3*M+NRHS* $ ILAENV( 1, 'SORMBR', 'QLT', M, NRHS, M, -1 ) ) MAXWRK = MAX( MAXWRK, 3*M+M* $ ILAENV( 1, 'SORGBR', 'P', M, N, M, -1 ) ) MAXWRK = MAX( MAXWRK, BDSPAC ) MAXWRK = MAX( MAXWRK, N*NRHS ) END IF END IF MAXWRK = MAX( MINWRK, MAXWRK ) WORK( 1 ) = MAXWRK END IF* MINWRK = MAX( MINWRK, 1 ) IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) $ INFO = -12 IF( INFO.NE.0 ) THEN CALL XERBLA( 'SGELSS', -INFO ) RETURN ELSE IF( LQUERY ) THEN RETURN END IF** Quick return if possible* IF( M.EQ.0 .OR. N.EQ.0 ) THEN RANK = 0 RETURN END IF** Get machine parameters* EPS = SLAMCH( 'P' ) SFMIN = SLAMCH( 'S' ) OPCNT( GELSS ) = OPCNT( GELSS ) + REAL( 2 ) SMLNUM = SFMIN / EPS BIGNUM = ONE / SMLNUM CALL SLABAD( SMLNUM, BIGNUM )** Scale A if max element outside range [SMLNUM,BIGNUM]* ANRM = SLANGE( 'M', M, N, A, LDA, WORK ) IASCL = 0 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM* OPCNT( GELSS ) = OPCNT( GELSS ) + REAL( M*N ) CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO ) IASCL = 1 ELSE IF( ANRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM* OPCNT( GELSS ) = OPCNT( GELSS ) + REAL( M*N ) CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO ) IASCL = 2 ELSE IF( ANRM.EQ.ZERO ) THEN** Matrix all zero. Return zero solution.* CALL SLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB ) CALL SLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 ) RANK = 0 GO TO 70 END IF** Scale B if max element outside range [SMLNUM,BIGNUM]* BNRM = SLANGE( 'M', M, NRHS, B, LDB, WORK ) IBSCL = 0 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM* OPCNT( GELSS ) = OPCNT( GELSS ) + REAL( M*NRHS ) CALL SLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO ) IBSCL = 1 ELSE IF( BNRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM* OPCNT( GELSS ) = OPCNT( GELSS ) + REAL( M*NRHS ) CALL SLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO ) IBSCL = 2 END IF** Overdetermined case* IF( M.GE.N ) THEN** Path 1 - overdetermined or exactly determined* MM = M IF( M.GE.MNTHR ) THEN** Path 1a - overdetermined, with many more rows than columns* MM = N ITAU = 1 IWORK = ITAU + N** Compute A=Q*R* (Workspace: need 2*N, prefer N+N*NB)* NB = ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 ) OPCNT( GEQRF ) = OPCNT( GEQRF ) + $ SOPLA( 'SGEQRF', M, N, 0, 0, NB ) T1 = SECOND( ) CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ), $ LWORK-IWORK+1, INFO ) T2 = SECOND( ) TIMNG( GEQRF ) = TIMNG( GEQRF ) + ( T2-T1 )** Multiply B by transpose(Q)* (Workspace: need N+NRHS, prefer N+NRHS*NB)* NB = ILAENV( 1, 'SORMQR', 'LT', M, NRHS, N, -1 ) OPCNT( ORMQR ) = OPCNT( ORMQR ) + $ SOPLA( 'SORMQR', M, NRHS, N, 0, NB ) T1 = SECOND( ) CALL SORMQR( 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAU ), B, $ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO ) T2 = SECOND( ) TIMNG( ORMQR ) = TIMNG( ORMQR ) + ( T2-T1 )** Zero out below R* IF( N.GT.1 ) $ CALL SLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA ) END IF* IE = 1 ITAUQ = IE + N ITAUP = ITAUQ + N IWORK = ITAUP + N** Bidiagonalize R in A* (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB)* NB = ILAENV( 1, 'SGEBRD', ' ', MM, N, -1, -1 ) OPCNT( GEBRD ) = OPCNT( GEBRD ) + $ SOPLA( 'SGEBRD', MM, N, 0, 0, NB ) T1 = SECOND( ) CALL SGEBRD( MM, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1, $ INFO ) T2 = SECOND( ) TIMNG( GEBRD ) = TIMNG( GEBRD ) + ( T2-T1 )** Multiply B by transpose of left bidiagonalizing vectors of R* (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB)* NB = ILAENV( 1, 'SORMBR', 'QLT', MM, NRHS, N, -1 ) OPCNT( ORMBR ) = OPCNT( ORMBR ) + $ SOPLA2( 'SORMBR', 'QLT', MM, NRHS, N, 0, NB )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -