📄 cgelsd.f
字号:
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' ) SMLNUM = SFMIN / EPS BIGNUM = ONE / SMLNUM CALL SLABAD( SMLNUM, BIGNUM )** Scale A if max entry outside range [SMLNUM,BIGNUM].* ANRM = CLANGE( 'M', M, N, A, LDA, RWORK ) IASCL = 0 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM* CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO ) IASCL = 1 ELSE IF( ANRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM.* CALL CLASCL( '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 CLASET( 'F', MAX( M, N ), NRHS, CZERO, CZERO, B, LDB ) CALL SLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 ) RANK = 0 GO TO 10 END IF** Scale B if max entry outside range [SMLNUM,BIGNUM].* BNRM = CLANGE( 'M', M, NRHS, B, LDB, RWORK ) IBSCL = 0 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM.* CALL CLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO ) IBSCL = 1 ELSE IF( BNRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM.* CALL CLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO ) IBSCL = 2 END IF** If M < N make sure B(M+1:N,:) = 0* IF( M.LT.N ) $ CALL CLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB )** 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 NWORK = ITAU + N** Compute A=Q*R.* (RWorkspace: need N)* (CWorkspace: need N, prefer N*NB)* CALL CGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, INFO )** Multiply B by transpose(Q).* (RWorkspace: need N)* (CWorkspace: need NRHS, prefer NRHS*NB)* CALL CUNMQR( 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAU ), B, $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Zero out below R.* IF( N.GT.1 ) THEN CALL CLASET( 'L', N-1, N-1, CZERO, CZERO, A( 2, 1 ), $ LDA ) END IF END IF* ITAUQ = 1 ITAUP = ITAUQ + N NWORK = ITAUP + N IE = 1 NRWORK = IE + N** Bidiagonalize R in A.* (RWorkspace: need N)* (CWorkspace: need 2*N+MM, prefer 2*N+(MM+N)*NB)* CALL CGEBRD( MM, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ INFO )** Multiply B by transpose of left bidiagonalizing vectors of R.* (CWorkspace: need 2*N+NRHS, prefer 2*N+NRHS*NB)* CALL CUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, WORK( ITAUQ ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.* CALL CLALSD( 'U', SMLSIZ, N, NRHS, S, RWORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ), $ IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF** Multiply B by right bidiagonalizing vectors of R.* CALL CUNMBR( 'P', 'L', 'N', N, NRHS, N, A, LDA, WORK( ITAUP ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )* ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+ $ MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN** Path 2a - underdetermined, with many more columns than rows* and sufficient workspace for an efficient algorithm.* LDWORK = M IF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ), $ M*LDA+M+M*NRHS ) )LDWORK = LDA ITAU = 1 NWORK = M + 1** Compute A=L*Q.* (CWorkspace: need 2*M, prefer M+M*NB)* CALL CGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, INFO ) IL = NWORK** Copy L to WORK(IL), zeroing out above its diagonal.* CALL CLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK ) CALL CLASET( 'U', M-1, M-1, CZERO, CZERO, WORK( IL+LDWORK ), $ LDWORK ) ITAUQ = IL + LDWORK*M ITAUP = ITAUQ + M NWORK = ITAUP + M IE = 1 NRWORK = IE + M** Bidiagonalize L in WORK(IL).* (RWorkspace: need M)* (CWorkspace: need M*M+4*M, prefer M*M+4*M+2*M*NB)* CALL CGEBRD( M, M, WORK( IL ), LDWORK, S, RWORK( IE ), $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ), $ LWORK-NWORK+1, INFO )** Multiply B by transpose of left bidiagonalizing vectors of L.* (CWorkspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)* CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, M, WORK( IL ), LDWORK, $ WORK( ITAUQ ), B, LDB, WORK( NWORK ), $ LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.* CALL CLALSD( 'U', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ), $ IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF** Multiply B by right bidiagonalizing vectors of L.* CALL CUNMBR( 'P', 'L', 'N', M, NRHS, M, WORK( IL ), LDWORK, $ WORK( ITAUP ), B, LDB, WORK( NWORK ), $ LWORK-NWORK+1, INFO )** Zero out below first M rows of B.* CALL CLASET( 'F', N-M, NRHS, CZERO, CZERO, B( M+1, 1 ), LDB ) NWORK = ITAU + M** Multiply transpose(Q) by B.* (CWorkspace: need NRHS, prefer NRHS*NB)* CALL CUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, WORK( ITAU ), B, $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )* ELSE** Path 2 - remaining underdetermined cases.* ITAUQ = 1 ITAUP = ITAUQ + M NWORK = ITAUP + M IE = 1 NRWORK = IE + M** Bidiagonalize A.* (RWorkspace: need M)* (CWorkspace: need 2*M+N, prefer 2*M+(M+N)*NB)* CALL CGEBRD( M, N, A, LDA, S, RWORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ INFO )** Multiply B by transpose of left bidiagonalizing vectors.* (CWorkspace: need 2*M+NRHS, prefer 2*M+NRHS*NB)* CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, WORK( ITAUQ ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.* CALL CLALSD( 'L', SMLSIZ, M, NRHS, S, RWORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), RWORK( NRWORK ), $ IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF** Multiply B by right bidiagonalizing vectors of A.* CALL CUNMBR( 'P', 'L', 'N', N, NRHS, M, A, LDA, WORK( ITAUP ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )* END IF** Undo scaling.* IF( IASCL.EQ.1 ) THEN CALL CLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO ) CALL SLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN, $ INFO ) ELSE IF( IASCL.EQ.2 ) THEN CALL CLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO ) CALL SLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN, $ INFO ) END IF IF( IBSCL.EQ.1 ) THEN CALL CLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO ) ELSE IF( IBSCL.EQ.2 ) THEN CALL CLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO ) END IF* 10 CONTINUE WORK( 1 ) = CMPLX( MAXWRK, 0 ) RETURN** End of CGELSD* END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -