📄 dgelsd.f
字号:
CALL XERBLA( 'DGELSD', -INFO ) RETURN ELSE IF( LQUERY ) THEN GO TO 10 END IF** Quick return if possible.* IF( M.EQ.0 .OR. N.EQ.0 ) THEN RANK = 0 RETURN END IF** Get machine parameters.* EPS = DLAMCH( 'P' ) SFMIN = DLAMCH( 'S' ) SMLNUM = SFMIN / EPS BIGNUM = ONE / SMLNUM CALL DLABAD( SMLNUM, BIGNUM )** Scale A if max entry outside range [SMLNUM,BIGNUM].* ANRM = DLANGE( 'M', M, N, A, LDA, WORK ) IASCL = 0 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM.* CALL DLASCL( '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 DLASCL( '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 DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB ) CALL DLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 ) RANK = 0 GO TO 10 END IF** Scale B if max entry outside range [SMLNUM,BIGNUM].* BNRM = DLANGE( 'M', M, NRHS, B, LDB, WORK ) IBSCL = 0 IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM.* CALL DLASCL( '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 DLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO ) IBSCL = 2 END IF** If M < N make sure certain entries of B are zero.* IF( M.LT.N ) $ CALL DLASET( 'F', N-M, NRHS, ZERO, ZERO, 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.* (Workspace: need 2*N, prefer N+N*NB)* CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ), $ LWORK-NWORK+1, INFO )** Multiply B by transpose(Q).* (Workspace: need N+NRHS, prefer N+NRHS*NB)* CALL DORMQR( 'L', 'T', 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 DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA ) END IF END IF* IE = 1 ITAUQ = IE + N ITAUP = ITAUQ + N NWORK = ITAUP + N** Bidiagonalize R in A.* (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB)* CALL DGEBRD( MM, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ INFO )** Multiply B by transpose of left bidiagonalizing vectors of R.* (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB)* CALL DORMBR( 'Q', 'L', 'T', MM, NRHS, N, A, LDA, WORK( ITAUQ ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.* CALL DLALSD( 'U', SMLSIZ, N, NRHS, S, WORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF** Multiply B by right bidiagonalizing vectors of R.* CALL DORMBR( '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.* (Workspace: need 2*M, prefer M+M*NB)* CALL DGELQF( 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 DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK ) CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, WORK( IL+LDWORK ), $ LDWORK ) IE = IL + LDWORK*M ITAUQ = IE + M ITAUP = ITAUQ + M NWORK = ITAUP + M** Bidiagonalize L in WORK(IL).* (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB)* CALL DGEBRD( M, M, WORK( IL ), LDWORK, S, WORK( IE ), $ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ), $ LWORK-NWORK+1, INFO )** Multiply B by transpose of left bidiagonalizing vectors of L.* (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)* CALL DORMBR( 'Q', 'L', 'T', M, NRHS, M, WORK( IL ), LDWORK, $ WORK( ITAUQ ), B, LDB, WORK( NWORK ), $ LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.* CALL DLALSD( 'U', SMLSIZ, M, NRHS, S, WORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF** Multiply B by right bidiagonalizing vectors of L.* CALL DORMBR( '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 DLASET( 'F', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB ) NWORK = ITAU + M** Multiply transpose(Q) by B.* (Workspace: need M+NRHS, prefer M+NRHS*NB)* CALL DORMLQ( 'L', 'T', N, NRHS, M, A, LDA, WORK( ITAU ), B, $ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )* ELSE** Path 2 - remaining underdetermined cases.* IE = 1 ITAUQ = IE + M ITAUP = ITAUQ + M NWORK = ITAUP + M** Bidiagonalize A.* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)* CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), $ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1, $ INFO )** Multiply B by transpose of left bidiagonalizing vectors.* (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB)* CALL DORMBR( 'Q', 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAUQ ), $ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.* CALL DLALSD( 'L', SMLSIZ, M, NRHS, S, WORK( IE ), B, LDB, $ RCOND, RANK, WORK( NWORK ), IWORK, INFO ) IF( INFO.NE.0 ) THEN GO TO 10 END IF** Multiply B by right bidiagonalizing vectors of A.* CALL DORMBR( '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 DLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO ) CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN, $ INFO ) ELSE IF( IASCL.EQ.2 ) THEN CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO ) CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN, $ INFO ) END IF IF( IBSCL.EQ.1 ) THEN CALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO ) ELSE IF( IBSCL.EQ.2 ) THEN CALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO ) END IF* 10 CONTINUE WORK( 1 ) = MAXWRK RETURN** End of DGELSD* END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -