📄 dgesdd.f
字号:
WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M, $ N, M, -1 ) ) WRKBL = MAX( WRKBL, 3*M+2*M* $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*M ) MAXWRK = WRKBL + M*M MINWRK = BDSPAC + M*M + 3*M ELSE IF( WNTQA ) THEN** Path 4t (N much larger than M, JOBZ='A')* WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N, $ N, M, -1 ) ) WRKBL = MAX( WRKBL, 3*M+2*M* $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*M ) MAXWRK = WRKBL + M*M MINWRK = BDSPAC + M*M + 3*M END IF ELSE** Path 5t (N greater than M, but not much larger)* WRKBL = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1, $ -1 ) IF( WNTQN ) THEN MAXWRK = MAX( WRKBL, BDSPAC+3*M ) MINWRK = 3*M + MAX( N, BDSPAC ) ELSE IF( WNTQO ) THEN WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) ) WRKBL = MAX( WRKBL, BDSPAC+3*M ) MAXWRK = WRKBL + M*N MINWRK = 3*M + MAX( N, M*M+BDSPAC ) ELSE IF( WNTQS ) THEN WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) ) MAXWRK = MAX( WRKBL, BDSPAC+3*M ) MINWRK = 3*M + MAX( N, BDSPAC ) ELSE IF( WNTQA ) THEN WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) ) WRKBL = MAX( WRKBL, 3*M+M* $ ILAENV( 1, 'DORMBR', 'PRT', N, N, M, -1 ) ) MAXWRK = MAX( WRKBL, BDSPAC+3*M ) MINWRK = 3*M + MAX( N, BDSPAC ) END IF END IF END IF WORK( 1 ) = MAXWRK END IF* IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN INFO = -12 END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'DGESDD', -INFO ) RETURN ELSE IF( LQUERY ) THEN RETURN END IF** Quick return if possible* IF( M.EQ.0 .OR. N.EQ.0 ) THEN IF( LWORK.GE.1 ) $ WORK( 1 ) = ONE RETURN END IF** Get machine constants* EPS = DLAMCH( 'P' ) SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS BIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]* ANRM = DLANGE( 'M', M, N, A, LDA, DUM ) ISCL = 0 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN ISCL = 1 OPS = OPS + DBLE( M*N ) CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR ) ELSE IF( ANRM.GT.BIGNUM ) THEN ISCL = 1 OPS = OPS + DBLE( M*N ) CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR ) END IF* IF( M.GE.N ) THEN** A has at least as many rows as columns. If A has sufficiently* more rows than columns, first reduce using the QR* decomposition (if sufficient workspace available)* IF( M.GE.MNTHR ) THEN* IF( WNTQN ) THEN** Path 1 (M much larger than N, JOBZ='N')* No singular vectors to be computed* ITAU = 1 NWORK = ITAU + N** Compute A=Q*R* (Workspace: need 2*N, prefer N+N*NB)* NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) OPS = OPS + DOPLA( 'DGEQRF', M, N, 0, 0, NB ) CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Zero out below R* CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA ) IE = 1 ITAUQ = IE + N ITAUP = ITAUQ + N NWORK = ITAUP + N** Bidiagonalize R in A* (Workspace: need 4*N, prefer 3*N+2*N*NB)* NB = ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) OPS = OPS + DOPLA( 'DGEBRD', N, N, 0, 0, NB ) CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ IERR ) NWORK = IE + N** Perform bidiagonal SVD, computing singular values only* (Workspace: need N+BDSPAC)* CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1, $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )* ELSE IF( WNTQO ) THEN** Path 2 (M much larger than N, JOBZ = 'O')* N left singular vectors to be overwritten on A and* N right singular vectors to be computed in VT* IR = 1** WORK(IR) is LDWRKR by N* IF( LWORK.GE.LDA*N+N*N+3*N+BDSPAC ) THEN LDWRKR = LDA ELSE LDWRKR = ( LWORK-N*N-3*N-BDSPAC ) / N END IF ITAU = IR + LDWRKR*N NWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) OPS = OPS + DOPLA( 'DGEQRF', M, N, 0, 0, NB ) CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Copy R to WORK(IR), zeroing out below it* CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR ) CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ), $ LDWRKR )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* NB = ILAENV( 1, 'DORGQR', ' ', M, N, N, -1 ) OPS = OPS + DOPLA( 'DORGQR', M, N, N, 0, NB ) CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), $ WORK( NWORK ), LWORK-NWORK+1, IERR ) IE = ITAU ITAUQ = IE + N ITAUP = ITAUQ + N NWORK = ITAUP + N** Bidiagonalize R in VT, copying result to WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)* NB = ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) OPS = OPS + DOPLA( 'DGEBRD', N, N, 0, 0, NB ) CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ), $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** WORK(IU) is N by N* IU = NWORK NWORK = IU + N*N** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in WORK(IU) and computing right* singular vectors of bidiagonal matrix in VT* (Workspace: need N+N*N+BDSPAC)* CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N, $ VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK, $ INFO )** Overwrite WORK(IU) by left singular vectors of R* and VT by right singular vectors of R* (Workspace: need 2*N*N+3*N, prefer 2*N*N+2*N+N*NB)* NB = ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'QLN', N, N, N, 0, NB ) CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR, $ WORK( ITAUQ ), WORK( IU ), N, WORK( NWORK ), $ LWORK-NWORK+1, IERR ) NB = ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'PRT', N, N, N, 0, NB ) CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR, $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Multiply Q in A by left singular vectors of R in* WORK(IU), storing result in WORK(IR) and copying to A* (Workspace: need 2*N*N, prefer N*N+M*N)* DO 10 I = 1, M, LDWRKR CHUNK = MIN( M-I+1, LDWRKR ) OPS = OPS + DOPBL3( 'DGEMM ', CHUNK, N, N ) CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ), $ LDA, WORK( IU ), N, ZERO, WORK( IR ), $ LDWRKR ) CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR, $ A( I, 1 ), LDA ) 10 CONTINUE* ELSE IF( WNTQS ) THEN** Path 3 (M much larger than N, JOBZ='S')* N left singular vectors to be computed in U and* N right singular vectors to be computed in VT* IR = 1** WORK(IR) is N by N* LDWRKR = N ITAU = IR + LDWRKR*N NWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) OPS = OPS + DOPLA( 'DGEQRF', M, N, 0, 0, NB ) CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Copy R to WORK(IR), zeroing out below it* CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR ) CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ), $ LDWRKR )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* NB = ILAENV( 1, 'DORGQR', ' ', M, N, N, -1 ) OPS = OPS + DOPLA( 'DORGQR', M, N, N, 0, NB ) CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), $ WORK( NWORK ), LWORK-NWORK+1, IERR ) IE = ITAU ITAUQ = IE + N ITAUP = ITAUQ + N NWORK = ITAUP + N** Bidiagonalize R in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)* NB = MAX( 1, ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) OPS = OPS + DOPLA( 'DGEBRD', N, N, 0, 0, NB ) CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ), $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Perform bidiagonal SVD, computing left singular vectors* of bidiagoal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need N+BDSPAC)* CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT, $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK, $ INFO )** Overwrite U by left singular vectors of R and VT* by right singular vectors of R* (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)* NB = ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'QLN', N, N, N, 0, NB ) CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR, $ WORK( ITAUQ ), U, LDU, WORK( NWORK ), $ LWORK-NWORK+1, IERR )* NB = ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'PRT', N, N, N, 0, NB ) CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR, $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Multiply Q in A by left singular vectors of R in* WORK(IR), storing result in U* (Workspace: need N*N)* CALL DLACPY( 'F', N, N, U, LDU, WORK( IR ), LDWRKR ) OPS = OPS + DOPBL3( 'DGEMM ', M, N, N ) CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, WORK( IR ), $ LDWRKR, ZERO, U, LDU )* ELSE IF( WNTQA ) THEN** Path 4 (M much larger than N, JOBZ='A')* M left singular vectors to be computed in U and* N right singular vectors to be computed in VT* IU = 1** WORK(IU) is N by N* LDWRKU = N ITAU = IU + LDWRKU*N NWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) OPS = OPS + DOPLA( 'DGEQRF', M, N, 0, 0, NB ) CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, IERR ) CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) NB = ILAENV( 1, 'DORGQR', ' ', M, M, N, -1 ) OPS = OPS + DOPLA( 'DORGQR', M, M, N, 0, NB ) CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ), $ WORK( NWORK ), LWORK-NWORK+1, IERR )** Produce R in A, zeroing out other entries* CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA ) IE = ITAU
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -