--- rpl/lapack/lapack/dgesvd.f 2010/01/26 15:22:45 1.1.1.1
+++ rpl/lapack/lapack/dgesvd.f 2012/07/31 11:06:35 1.11
@@ -1,10 +1,220 @@
- SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
- $ WORK, LWORK, INFO )
+*> \brief DGESVD computes the singular value decomposition (SVD) for GE matrices
*
-* -- LAPACK driver routine (version 3.2) --
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download DGESVD + dependencies
+*>
+*> [TGZ]
+*>
+*> [ZIP]
+*>
+*> [TXT]
+*> \endhtmlonly
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
+* WORK, LWORK, INFO )
+*
+* .. Scalar Arguments ..
+* CHARACTER JOBU, JOBVT
+* INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),
+* $ VT( LDVT, * ), WORK( * )
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DGESVD computes the singular value decomposition (SVD) of a real
+*> M-by-N matrix A, optionally computing the left and/or right singular
+*> vectors. The SVD is written
+*>
+*> A = U * SIGMA * transpose(V)
+*>
+*> where SIGMA is an M-by-N matrix which is zero except for its
+*> min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
+*> V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
+*> are the singular values of A; they are real and non-negative, and
+*> are returned in descending order. The first min(m,n) columns of
+*> U and V are the left and right singular vectors of A.
+*>
+*> Note that the routine returns V**T, not V.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] JOBU
+*> \verbatim
+*> JOBU is CHARACTER*1
+*> Specifies options for computing all or part of the matrix U:
+*> = 'A': all M columns of U are returned in array U:
+*> = 'S': the first min(m,n) columns of U (the left singular
+*> vectors) are returned in the array U;
+*> = 'O': the first min(m,n) columns of U (the left singular
+*> vectors) are overwritten on the array A;
+*> = 'N': no columns of U (no left singular vectors) are
+*> computed.
+*> \endverbatim
+*>
+*> \param[in] JOBVT
+*> \verbatim
+*> JOBVT is CHARACTER*1
+*> Specifies options for computing all or part of the matrix
+*> V**T:
+*> = 'A': all N rows of V**T are returned in the array VT;
+*> = 'S': the first min(m,n) rows of V**T (the right singular
+*> vectors) are returned in the array VT;
+*> = 'O': the first min(m,n) rows of V**T (the right singular
+*> vectors) are overwritten on the array A;
+*> = 'N': no rows of V**T (no right singular vectors) are
+*> computed.
+*>
+*> JOBVT and JOBU cannot both be 'O'.
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> The number of rows of the input matrix A. M >= 0.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> The number of columns of the input matrix A. N >= 0.
+*> \endverbatim
+*>
+*> \param[in,out] A
+*> \verbatim
+*> A is DOUBLE PRECISION array, dimension (LDA,N)
+*> On entry, the M-by-N matrix A.
+*> On exit,
+*> if JOBU = 'O', A is overwritten with the first min(m,n)
+*> columns of U (the left singular vectors,
+*> stored columnwise);
+*> if JOBVT = 'O', A is overwritten with the first min(m,n)
+*> rows of V**T (the right singular vectors,
+*> stored rowwise);
+*> if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A
+*> are destroyed.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> The leading dimension of the array A. LDA >= max(1,M).
+*> \endverbatim
+*>
+*> \param[out] S
+*> \verbatim
+*> S is DOUBLE PRECISION array, dimension (min(M,N))
+*> The singular values of A, sorted so that S(i) >= S(i+1).
+*> \endverbatim
+*>
+*> \param[out] U
+*> \verbatim
+*> U is DOUBLE PRECISION array, dimension (LDU,UCOL)
+*> (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
+*> If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
+*> if JOBU = 'S', U contains the first min(m,n) columns of U
+*> (the left singular vectors, stored columnwise);
+*> if JOBU = 'N' or 'O', U is not referenced.
+*> \endverbatim
+*>
+*> \param[in] LDU
+*> \verbatim
+*> LDU is INTEGER
+*> The leading dimension of the array U. LDU >= 1; if
+*> JOBU = 'S' or 'A', LDU >= M.
+*> \endverbatim
+*>
+*> \param[out] VT
+*> \verbatim
+*> VT is DOUBLE PRECISION array, dimension (LDVT,N)
+*> If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
+*> V**T;
+*> if JOBVT = 'S', VT contains the first min(m,n) rows of
+*> V**T (the right singular vectors, stored rowwise);
+*> if JOBVT = 'N' or 'O', VT is not referenced.
+*> \endverbatim
+*>
+*> \param[in] LDVT
+*> \verbatim
+*> LDVT is INTEGER
+*> The leading dimension of the array VT. LDVT >= 1; if
+*> JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
+*> if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
+*> superdiagonal elements of an upper bidiagonal matrix B
+*> whose diagonal is in S (not necessarily sorted). B
+*> satisfies A = U * B * VT, so it has the same singular values
+*> as A, and singular vectors related by U and VT.
+*> \endverbatim
+*>
+*> \param[in] LWORK
+*> \verbatim
+*> LWORK is INTEGER
+*> The dimension of the array WORK.
+*> LWORK >= MAX(1,5*MIN(M,N)) for the paths (see comments inside code):
+*> - PATH 1 (M much larger than N, JOBU='N')
+*> - PATH 1t (N much larger than M, JOBVT='N')
+*> LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)) for the other paths
+*> 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.
+*> \endverbatim
+*>
+*> \param[out] INFO
+*> \verbatim
+*> INFO is INTEGER
+*> = 0: successful exit.
+*> < 0: if INFO = -i, the i-th argument had an illegal value.
+*> > 0: if DBDSQR did not converge, INFO specifies how many
+*> superdiagonals of an intermediate bidiagonal form B
+*> did not converge to zero. See the description of WORK
+*> above for details.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date April 2012
+*
+*> \ingroup doubleGEsing
+*
+* =====================================================================
+ SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU,
+ $ VT, LDVT, WORK, LWORK, INFO )
+*
+* -- LAPACK driver routine (version 3.4.1) --
* -- LAPACK is a software package provided by Univ. of Tennessee, --
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
-* November 2006
+* April 2012
*
* .. Scalar Arguments ..
CHARACTER JOBU, JOBVT
@@ -15,122 +225,6 @@
$ VT( LDVT, * ), WORK( * )
* ..
*
-* Purpose
-* =======
-*
-* DGESVD computes the singular value decomposition (SVD) of a real
-* M-by-N matrix A, optionally computing the left and/or right singular
-* vectors. The SVD is written
-*
-* A = U * SIGMA * transpose(V)
-*
-* where SIGMA is an M-by-N matrix which is zero except for its
-* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
-* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
-* are the singular values of A; they are real and non-negative, and
-* are returned in descending order. The first min(m,n) columns of
-* U and V are the left and right singular vectors of A.
-*
-* Note that the routine returns V**T, not V.
-*
-* Arguments
-* =========
-*
-* JOBU (input) CHARACTER*1
-* Specifies options for computing all or part of the matrix U:
-* = 'A': all M columns of U are returned in array U:
-* = 'S': the first min(m,n) columns of U (the left singular
-* vectors) are returned in the array U;
-* = 'O': the first min(m,n) columns of U (the left singular
-* vectors) are overwritten on the array A;
-* = 'N': no columns of U (no left singular vectors) are
-* computed.
-*
-* JOBVT (input) CHARACTER*1
-* Specifies options for computing all or part of the matrix
-* V**T:
-* = 'A': all N rows of V**T are returned in the array VT;
-* = 'S': the first min(m,n) rows of V**T (the right singular
-* vectors) are returned in the array VT;
-* = 'O': the first min(m,n) rows of V**T (the right singular
-* vectors) are overwritten on the array A;
-* = 'N': no rows of V**T (no right singular vectors) are
-* computed.
-*
-* JOBVT and JOBU cannot both be 'O'.
-*
-* M (input) INTEGER
-* The number of rows of the input matrix A. M >= 0.
-*
-* N (input) INTEGER
-* The number of columns of the input matrix A. N >= 0.
-*
-* A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
-* On entry, the M-by-N matrix A.
-* On exit,
-* if JOBU = 'O', A is overwritten with the first min(m,n)
-* columns of U (the left singular vectors,
-* stored columnwise);
-* if JOBVT = 'O', A is overwritten with the first min(m,n)
-* rows of V**T (the right singular vectors,
-* stored rowwise);
-* if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A
-* are destroyed.
-*
-* LDA (input) INTEGER
-* The leading dimension of the array A. LDA >= max(1,M).
-*
-* S (output) DOUBLE PRECISION array, dimension (min(M,N))
-* The singular values of A, sorted so that S(i) >= S(i+1).
-*
-* U (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
-* (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
-* If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
-* if JOBU = 'S', U contains the first min(m,n) columns of U
-* (the left singular vectors, stored columnwise);
-* if JOBU = 'N' or 'O', U is not referenced.
-*
-* LDU (input) INTEGER
-* The leading dimension of the array U. LDU >= 1; if
-* JOBU = 'S' or 'A', LDU >= M.
-*
-* VT (output) DOUBLE PRECISION array, dimension (LDVT,N)
-* If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
-* V**T;
-* if JOBVT = 'S', VT contains the first min(m,n) rows of
-* V**T (the right singular vectors, stored rowwise);
-* if JOBVT = 'N' or 'O', VT is not referenced.
-*
-* LDVT (input) INTEGER
-* The leading dimension of the array VT. LDVT >= 1; if
-* JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
-*
-* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
-* On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
-* if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
-* superdiagonal elements of an upper bidiagonal matrix B
-* whose diagonal is in S (not necessarily sorted). B
-* satisfies A = U * B * VT, so it has the same singular values
-* as A, and singular vectors related by U and VT.
-*
-* LWORK (input) INTEGER
-* The dimension of the array WORK.
-* LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)).
-* 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: if DBDSQR did not converge, INFO specifies how many
-* superdiagonals of an intermediate bidiagonal form B
-* did not converge to zero. See the description of WORK
-* above for details.
-*
* =====================================================================
*
* .. Parameters ..
@@ -144,6 +238,9 @@
$ ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
$ MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
$ NRVT, WRKBL
+ INTEGER LWORK_DGEQRF, LWORK_DORGQR_N, LWORK_DORGQR_M,
+ $ LWORK_DGEBRD, LWORK_DORGBR_P, LWORK_DORGBR_Q,
+ $ LWORK_DGELQF, LWORK_DORGLQ_N, LWORK_DORGLQ_M
DOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM
* ..
* .. Local Arrays ..
@@ -215,31 +312,46 @@
*
MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
BDSPAC = 5*N
+* Compute space needed for DGEQRF
+ CALL DGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+ LWORK_DGEQRF=DUM(1)
+* Compute space needed for DORGQR
+ CALL DORGQR( M, N, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+ LWORK_DORGQR_N=DUM(1)
+ CALL DORGQR( M, M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+ LWORK_DORGQR_M=DUM(1)
+* Compute space needed for DGEBRD
+ CALL DGEBRD( N, N, A, LDA, S, DUM(1), DUM(1),
+ $ DUM(1), DUM(1), -1, IERR )
+ LWORK_DGEBRD=DUM(1)
+* Compute space needed for DORGBR P
+ CALL DORGBR( 'P', N, N, N, A, LDA, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_P=DUM(1)
+* Compute space needed for DORGBR Q
+ CALL DORGBR( 'Q', N, N, N, A, LDA, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_Q=DUM(1)
+*
IF( M.GE.MNTHR ) THEN
IF( WNTUN ) THEN
*
* Path 1 (M much larger than N, JOBU='N')
*
- MAXWRK = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,
- $ -1 )
- MAXWRK = MAX( MAXWRK, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
+ MAXWRK = N + LWORK_DGEQRF
+ MAXWRK = MAX( MAXWRK, 3*N+LWORK_DGEBRD )
IF( WNTVO .OR. WNTVAS )
- $ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+ $ MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_P )
MAXWRK = MAX( MAXWRK, BDSPAC )
MINWRK = MAX( 4*N, BDSPAC )
ELSE IF( WNTUO .AND. WNTVN ) THEN
*
* Path 2 (M much larger than N, JOBU='O', JOBVT='N')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
- $ N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -248,15 +360,11 @@
* Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
* 'A')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
- $ N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+( N-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -264,13 +372,10 @@
*
* Path 4 (M much larger than N, JOBU='S', JOBVT='N')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
- $ N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = N*N + WRKBL
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -278,15 +383,11 @@
*
* Path 5 (M much larger than N, JOBU='S', JOBVT='O')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
- $ N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+( N-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = 2*N*N + WRKBL
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -295,15 +396,11 @@
* Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
* 'A')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
- $ N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+( N-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = N*N + WRKBL
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -311,13 +408,10 @@
*
* Path 7 (M much larger than N, JOBU='A', JOBVT='N')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
- $ M, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_M )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = N*N + WRKBL
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -325,15 +419,11 @@
*
* Path 8 (M much larger than N, JOBU='A', JOBVT='O')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
- $ M, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+( N-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_M )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = 2*N*N + WRKBL
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -342,15 +432,11 @@
* Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
* 'A')
*
- WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
- WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
- $ M, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+2*N*
- $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
- WRKBL = MAX( WRKBL, 3*N+( N-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+ WRKBL = N + LWORK_DGEQRF
+ WRKBL = MAX( WRKBL, N+LWORK_DORGQR_M )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+ WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = N*N + WRKBL
MINWRK = MAX( 3*N+M, BDSPAC )
@@ -359,17 +445,25 @@
*
* Path 10 (M at least N, but not much larger)
*
- MAXWRK = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
- $ -1, -1 )
- IF( WNTUS .OR. WNTUO )
- $ MAXWRK = MAX( MAXWRK, 3*N+N*
- $ ILAENV( 1, 'DORGBR', 'Q', M, N, N, -1 ) )
- IF( WNTUA )
- $ MAXWRK = MAX( MAXWRK, 3*N+M*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, N, -1 ) )
- IF( .NOT.WNTVN )
- $ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+ CALL DGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+ $ DUM(1), DUM(1), -1, IERR )
+ LWORK_DGEBRD=DUM(1)
+ MAXWRK = 3*N + LWORK_DGEBRD
+ IF( WNTUS .OR. WNTUO ) THEN
+ CALL DORGBR( 'Q', M, N, N, A, LDA, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_Q=DUM(1)
+ MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_Q )
+ END IF
+ IF( WNTUA ) THEN
+ CALL DORGBR( 'Q', M, M, N, A, LDA, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_Q=DUM(1)
+ MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_Q )
+ END IF
+ IF( .NOT.WNTVN ) THEN
+ MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_P )
+ END IF
MAXWRK = MAX( MAXWRK, BDSPAC )
MINWRK = MAX( 3*N+M, BDSPAC )
END IF
@@ -379,31 +473,45 @@
*
MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
BDSPAC = 5*M
+* Compute space needed for DGELQF
+ CALL DGELQF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+ LWORK_DGELQF=DUM(1)
+* Compute space needed for DORGLQ
+ CALL DORGLQ( N, N, M, DUM(1), N, DUM(1), DUM(1), -1, IERR )
+ LWORK_DORGLQ_N=DUM(1)
+ CALL DORGLQ( M, N, M, A, LDA, DUM(1), DUM(1), -1, IERR )
+ LWORK_DORGLQ_M=DUM(1)
+* Compute space needed for DGEBRD
+ CALL DGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+ $ DUM(1), DUM(1), -1, IERR )
+ LWORK_DGEBRD=DUM(1)
+* Compute space needed for DORGBR P
+ CALL DORGBR( 'P', M, M, M, A, N, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_P=DUM(1)
+* Compute space needed for DORGBR Q
+ CALL DORGBR( 'Q', M, M, M, A, N, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_Q=DUM(1)
IF( N.GE.MNTHR ) THEN
IF( WNTVN ) THEN
*
* Path 1t(N much larger than M, JOBVT='N')
*
- MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
- $ -1 )
- MAXWRK = MAX( MAXWRK, 3*M+2*M*
- $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
+ MAXWRK = M + LWORK_DGELQF
+ MAXWRK = MAX( MAXWRK, 3*M+LWORK_DGEBRD )
IF( WNTUO .OR. WNTUAS )
- $ MAXWRK = MAX( MAXWRK, 3*M+M*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+ $ MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_Q )
MAXWRK = MAX( MAXWRK, BDSPAC )
MINWRK = MAX( 4*M, BDSPAC )
ELSE IF( WNTVO .AND. WNTUN ) THEN
*
* Path 2t(N much larger than M, JOBU='N', JOBVT='O')
*
- 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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -412,15 +520,11 @@
* Path 3t(N much larger than M, JOBU='S' or 'A',
* JOBVT='O')
*
- 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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
- WRKBL = MAX( WRKBL, 3*M+M*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -428,13 +532,10 @@
*
* Path 4t(N much larger than M, JOBU='N', JOBVT='S')
*
- 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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = M*M + WRKBL
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -442,15 +543,11 @@
*
* Path 5t(N much larger than M, JOBU='O', JOBVT='S')
*
- 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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
- WRKBL = MAX( WRKBL, 3*M+M*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = 2*M*M + WRKBL
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -459,15 +556,11 @@
* Path 6t(N much larger than M, JOBU='S' or 'A',
* JOBVT='S')
*
- 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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
- WRKBL = MAX( WRKBL, 3*M+M*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = M*M + WRKBL
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -475,13 +568,10 @@
*
* Path 7t(N much larger than M, JOBU='N', JOBVT='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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_N )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = M*M + WRKBL
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -489,15 +579,11 @@
*
* Path 8t(N much larger than M, JOBU='O', JOBVT='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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
- WRKBL = MAX( WRKBL, 3*M+M*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_N )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = 2*M*M + WRKBL
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -506,15 +592,11 @@
* Path 9t(N much larger than M, JOBU='S' or 'A',
* JOBVT='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-1 )*
- $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
- WRKBL = MAX( WRKBL, 3*M+M*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+ WRKBL = M + LWORK_DGELQF
+ WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_N )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+ WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
WRKBL = MAX( WRKBL, BDSPAC )
MAXWRK = M*M + WRKBL
MINWRK = MAX( 3*M+N, BDSPAC )
@@ -523,17 +605,26 @@
*
* Path 10t(N greater than M, but not much larger)
*
- MAXWRK = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
- $ -1, -1 )
- IF( WNTVS .OR. WNTVO )
- $ MAXWRK = MAX( MAXWRK, 3*M+M*
- $ ILAENV( 1, 'DORGBR', 'P', M, N, M, -1 ) )
- IF( WNTVA )
- $ MAXWRK = MAX( MAXWRK, 3*M+N*
- $ ILAENV( 1, 'DORGBR', 'P', N, N, M, -1 ) )
- IF( .NOT.WNTUN )
- $ MAXWRK = MAX( MAXWRK, 3*M+( M-1 )*
- $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+ CALL DGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+ $ DUM(1), DUM(1), -1, IERR )
+ LWORK_DGEBRD=DUM(1)
+ MAXWRK = 3*M + LWORK_DGEBRD
+ IF( WNTVS .OR. WNTVO ) THEN
+* Compute space needed for DORGBR P
+ CALL DORGBR( 'P', M, N, M, A, N, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_P=DUM(1)
+ MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_P )
+ END IF
+ IF( WNTVA ) THEN
+ CALL DORGBR( 'P', N, N, M, A, N, DUM(1),
+ $ DUM(1), -1, IERR )
+ LWORK_DORGBR_P=DUM(1)
+ MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_P )
+ END IF
+ IF( .NOT.WNTUN ) THEN
+ MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_Q )
+ END IF
MAXWRK = MAX( MAXWRK, BDSPAC )
MINWRK = MAX( 3*M+N, BDSPAC )
END IF