📄 dgesdd.f
字号:
ITAUQ = IE + N ITAUP = ITAUQ + N NWORK = ITAUP + N** Bidiagonalize R in A* (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, A, LDA, S, WORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ IERR )** 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 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, A, LDA, $ WORK( ITAUQ ), WORK( IU ), LDWRKU, $ 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, A, LDA, $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Multiply Q in U by left singular vectors of R in* WORK(IU), storing result in A* (Workspace: need N*N)* OPS = OPS + DOPBL3( 'DGEMM ', M, N, N ) CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, WORK( IU ), $ LDWRKU, ZERO, A, LDA )** Copy left singular vectors of A from A to U* CALL DLACPY( 'F', M, N, A, LDA, U, LDU )* END IF* ELSE** M .LT. MNTHR** Path 5 (M at least N, but not much larger)* Reduce to bidiagonal form without QR decomposition* IE = 1 ITAUQ = IE + N ITAUP = ITAUQ + N NWORK = ITAUP + N** Bidiagonalize A* (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)* NB = MAX( 1, ILAENV( 1, 'DGEBRD', ' ', M, N, -1, -1 ) ) OPS = OPS + DOPLA( 'DGEBRD', M, N, 0, 0, NB ) CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ IERR ) IF( WNTQN ) THEN** Perform bidiagonal SVD, only computing singular values* (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 IU = NWORK IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN** WORK( IU ) is M by N* LDWRKU = M NWORK = IU + LDWRKU*N CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IU ), $ LDWRKU ) ELSE** WORK( IU ) is N by N* LDWRKU = N NWORK = IU + LDWRKU*N** WORK(IR) is LDWRKR by N* IR = NWORK LDWRKR = ( LWORK-N*N-3*N ) / N END IF NWORK = IU + LDWRKU*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 ), $ LDWRKU, VT, LDVT, DUM, IDUM, WORK( NWORK ), $ IWORK, INFO )** Overwrite VT by right singular vectors of A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* 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, A, LDA, $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ), $ LWORK-NWORK+1, IERR )* IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN** Overwrite WORK(IU) by left singular vectors of A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* NB = ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'QLN', M, N, N, 0, NB ) CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA, $ WORK( ITAUQ ), WORK( IU ), LDWRKU, $ WORK( NWORK ), LWORK-NWORK+1, IERR )** Copy left singular vectors of A from WORK(IU) to A* CALL DLACPY( 'F', M, N, WORK( IU ), LDWRKU, A, LDA ) ELSE** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)* NB = ILAENV( 1, 'DORGBR', 'Q', M, N, N, -1 ) OPS = OPS + DOPLA2( 'DORGBR', 'Q', M, N, N, 0, NB ) CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ), $ WORK( NWORK ), LWORK-NWORK+1, IERR )** Multiply Q in A by left singular vectors of* bidiagonal matrix in WORK(IU), storing result in* WORK(IR) and copying to A* (Workspace: need 2*N*N, prefer N*N+M*N)* DO 20 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 ), LDWRKU, ZERO, $ WORK( IR ), LDWRKR ) CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR, $ A( I, 1 ), LDA ) 20 CONTINUE END IF* ELSE IF( WNTQS ) THEN** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need N+BDSPAC)* CALL DLASET( 'F', M, N, ZERO, ZERO, U, LDU ) 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 A and VT* by right singular vectors of A* (Workspace: need 3*N, prefer 2*N+N*NB)* NB = ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'QLN', M, N, N, 0, NB ) CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA, $ 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, A, LDA, $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ), $ LWORK-NWORK+1, IERR ) ELSE IF( WNTQA ) THEN** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need N+BDSPAC)* CALL DLASET( 'F', M, M, ZERO, ZERO, U, LDU ) CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT, $ LDVT, DUM, IDUM, WORK( NWORK ), IWORK, $ INFO )** Set the right corner of U to identity matrix* CALL DLASET( 'F', M-N, M-N, ZERO, ONE, U( N+1, N+1 ), $ LDU )** Overwrite U by left singular vectors of A and VT* by right singular vectors of A* (Workspace: need N*N+2*N+M, prefer N*N+2*N+M*NB)* NB = ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'QLN', M, M, N, 0, NB ) CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA, $ WORK( ITAUQ ), U, LDU, WORK( NWORK ), $ LWORK-NWORK+1, IERR ) NB = ILAENV( 1, 'DORMBR', 'PRT', N, N, M, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'PRT', N, N, M, 0, NB ) CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA, $ WORK( ITAUP ), VT, LDVT, WORK( NWORK ), $ LWORK-NWORK+1, IERR ) END IF* END IF* ELSE** A has more columns than rows. If A has sufficiently more* columns than rows, first reduce using the LQ decomposition (if* sufficient workspace available)* IF( N.GE.MNTHR ) THEN* IF( WNTQN ) THEN** Path 1t (N much larger than M, JOBZ='N')* No singular vectors to be computed* ITAU = 1 NWORK = ITAU + M** Compute A=L*Q* (Workspace: need 2*M, prefer M+M*NB)* NB = ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) OPS = OPS + DOPLA( 'DGELQF', M, N, 0, 0, NB ) CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Zero out above L* CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA ) IE = 1 ITAUQ = IE + M ITAUP = ITAUQ + M NWORK = ITAUP + M** Bidiagonalize L in A* (Workspace: need 4*M, prefer 3*M+2*M*NB)* NB = ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) OPS = OPS + DOPLA( 'DGEBRD', M, M, 0, 0, NB ) CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ IERR ) NWORK = IE + M** Perform bidiagonal SVD, computing singular values only* (Workspace: need M+BDSPAC)* CALL DBDSDC( 'U', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1, $ DUM, IDUM, WORK( NWORK ), IWORK, INFO )* ELSE IF( WNTQO ) THEN** Path 2t (N much larger than M, JOBZ='O')* M right singular vectors to be overwritten on A and* M left singular vectors to be computed in U* IVT = 1** IVT is M by M* IL = IVT + M*M IF( LWORK.GE.M*N+M*M+3*M+BDSPAC ) THEN** WORK(IL) is M by N* LDWRKL = M CHUNK = N ELSE LDWRKL = M CHUNK = ( LWORK-M*M ) / M END IF ITAU = IL + LDWRKL*M NWORK = ITAU + M** Compute A=L*Q* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)* NB = ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) OPS = OPS + DOPLA( 'DGELQF', M, N, 0, 0, NB ) CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Copy L to WORK(IL), zeroing about above it* CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL ) CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, $ WORK( IL+LDWRKL ), LDWRKL )** Generate Q in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)* NB = ILAENV( 1, 'DORGLQ', ' ', M, N, M, -1 ) OPS = OPS + DOPLA( 'DORGLQ', M, N, M, 0, NB ) CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ), $ WORK( NWORK ), LWORK-NWORK+1, IERR ) IE = ITAU ITAUQ = IE + M ITAUP = ITAUQ + M NWORK = ITAUP + M** Bidiagonalize L in WORK(IL)* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)* NB = ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) OPS = OPS + DOPLA( 'DGEBRD', M, M, 0, 0, NB ) CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ), $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ), $ LWORK-NWORK+1, IERR )** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U, and computing right singular* vectors of bidiagonal matrix in WORK(IVT)* (Workspace: need M+M*M+BDSPAC)* CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU, $ WORK( IVT ), M, DUM, IDUM, WORK( NWORK ), $ IWORK, INFO )** Overwrite U by left singular vectors of L and WORK(IVT)* by right singular vectors of L* (Workspace: need 2*M*M+3*M, prefer 2*M*M+2*M+M*NB)* NB = ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'QLN', M, M, M, 0, NB ) CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL, $ WORK( ITAUQ ), U, LDU, WORK( NWORK ), $ LWORK-NWORK+1, IERR ) NB = ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) OPS = OPS + DOPLA2( 'DORMBR', 'PRT', M, M, M, 0, NB ) CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL, $ WORK( ITAUP ), WORK( IVT ), M, $ WORK( NWORK ), LWORK-NWORK+1, IERR )** Multiply right singular vectors of L in WORK(IVT) by Q* in A, storing result in WORK(IL) and copying to A* (Workspace: need 2*M*M, prefer M*M+M*N)* DO 30 I = 1, N, CHUNK BLK = MIN( N-I+1, CHUNK ) OPS = OPS + DOPBL3( 'DGEMM ', M, BLK, M ) CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ), M, $ A( 1, I ), LDA, ZERO, WORK( IL ), LDWRKL ) CALL DLACPY( 'F', M, BLK, WORK( IL ), LDWRKL, $ A( 1, I ), LDA ) 30 CONTINUE*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -