Annotation of rpl/lapack/lapack/dgesvdx.f, revision 1.1
1.1 ! bertrand 1: *> \brief <b> DGESVDX computes the singular value decomposition (SVD) for GE matrices</b>
! 2: *
! 3: * =========== DOCUMENTATION ===========
! 4: *
! 5: * Online html documentation available at
! 6: * http://www.netlib.org/lapack/explore-html/
! 7: *
! 8: *> \htmlonly
! 9: *> Download DGESVDX + dependencies
! 10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgesvdx.f">
! 11: *> [TGZ]</a>
! 12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgesvdx.f">
! 13: *> [ZIP]</a>
! 14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesvdx.f">
! 15: *> [TXT]</a>
! 16: *> \endhtmlonly
! 17: *
! 18: * Definition:
! 19: * ===========
! 20: *
! 21: * SUBROUTINE DGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
! 22: * $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
! 23: * $ LWORK, IWORK, INFO )
! 24: *
! 25: *
! 26: * .. Scalar Arguments ..
! 27: * CHARACTER JOBU, JOBVT, RANGE
! 28: * INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
! 29: * DOUBLE PRECISION VL, VU
! 30: * ..
! 31: * .. Array Arguments ..
! 32: * INTEGER IWORK( * )
! 33: * DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),
! 34: * $ VT( LDVT, * ), WORK( * )
! 35: * ..
! 36: *
! 37: *
! 38: *> \par Purpose:
! 39: * =============
! 40: *>
! 41: *> \verbatim
! 42: *>
! 43: *> DGESVDX computes the singular value decomposition (SVD) of a real
! 44: *> M-by-N matrix A, optionally computing the left and/or right singular
! 45: *> vectors. The SVD is written
! 46: *>
! 47: *> A = U * SIGMA * transpose(V)
! 48: *>
! 49: *> where SIGMA is an M-by-N matrix which is zero except for its
! 50: *> min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
! 51: *> V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
! 52: *> are the singular values of A; they are real and non-negative, and
! 53: *> are returned in descending order. The first min(m,n) columns of
! 54: *> U and V are the left and right singular vectors of A.
! 55: *>
! 56: *> DGESVDX uses an eigenvalue problem for obtaining the SVD, which
! 57: *> allows for the computation of a subset of singular values and
! 58: *> vectors. See DBDSVDX for details.
! 59: *>
! 60: *> Note that the routine returns V**T, not V.
! 61: *> \endverbatim
! 62: *
! 63: * Arguments:
! 64: * ==========
! 65: *
! 66: *> \param[in] JOBU
! 67: *> \verbatim
! 68: *> JOBU is CHARACTER*1
! 69: *> Specifies options for computing all or part of the matrix U:
! 70: *> = 'V': the first min(m,n) columns of U (the left singular
! 71: *> vectors) or as specified by RANGE are returned in
! 72: *> the array U;
! 73: *> = 'N': no columns of U (no left singular vectors) are
! 74: *> computed.
! 75: *> \endverbatim
! 76: *>
! 77: *> \param[in] JOBVT
! 78: *> \verbatim
! 79: *> JOBVT is CHARACTER*1
! 80: *> Specifies options for computing all or part of the matrix
! 81: *> V**T:
! 82: *> = 'V': the first min(m,n) rows of V**T (the right singular
! 83: *> vectors) or as specified by RANGE are returned in
! 84: *> the array VT;
! 85: *> = 'N': no rows of V**T (no right singular vectors) are
! 86: *> computed.
! 87: *> \endverbatim
! 88: *>
! 89: *> \param[in] RANGE
! 90: *> \verbatim
! 91: *> RANGE is CHARACTER*1
! 92: *> = 'A': all singular values will be found.
! 93: *> = 'V': all singular values in the half-open interval (VL,VU]
! 94: *> will be found.
! 95: *> = 'I': the IL-th through IU-th singular values will be found.
! 96: *> \endverbatim
! 97: *>
! 98: *> \param[in] M
! 99: *> \verbatim
! 100: *> M is INTEGER
! 101: *> The number of rows of the input matrix A. M >= 0.
! 102: *> \endverbatim
! 103: *>
! 104: *> \param[in] N
! 105: *> \verbatim
! 106: *> N is INTEGER
! 107: *> The number of columns of the input matrix A. N >= 0.
! 108: *> \endverbatim
! 109: *>
! 110: *> \param[in,out] A
! 111: *> \verbatim
! 112: *> A is DOUBLE PRECISION array, dimension (LDA,N)
! 113: *> On entry, the M-by-N matrix A.
! 114: *> On exit, the contents of A are destroyed.
! 115: *> \endverbatim
! 116: *>
! 117: *> \param[in] LDA
! 118: *> \verbatim
! 119: *> LDA is INTEGER
! 120: *> The leading dimension of the array A. LDA >= max(1,M).
! 121: *> \endverbatim
! 122: *>
! 123: *> \param[in] VL
! 124: *> \verbatim
! 125: *> VL is DOUBLE PRECISION
! 126: *> VL >=0.
! 127: *> \endverbatim
! 128: *>
! 129: *> \param[in] VU
! 130: *> \verbatim
! 131: *> VU is DOUBLE PRECISION
! 132: *> If RANGE='V', the lower and upper bounds of the interval to
! 133: *> be searched for singular values. VU > VL.
! 134: *> Not referenced if RANGE = 'A' or 'I'.
! 135: *> \endverbatim
! 136: *>
! 137: *> \param[in] IL
! 138: *> \verbatim
! 139: *> IL is INTEGER
! 140: *> \endverbatim
! 141: *>
! 142: *> \param[in] IU
! 143: *> \verbatim
! 144: *> IU is INTEGER
! 145: *> If RANGE='I', the indices (in ascending order) of the
! 146: *> smallest and largest singular values to be returned.
! 147: *> 1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
! 148: *> Not referenced if RANGE = 'A' or 'V'.
! 149: *> \endverbatim
! 150: *>
! 151: *> \param[out] NS
! 152: *> \verbatim
! 153: *> NS is INTEGER
! 154: *> The total number of singular values found,
! 155: *> 0 <= NS <= min(M,N).
! 156: *> If RANGE = 'A', NS = min(M,N); if RANGE = 'I', NS = IU-IL+1.
! 157: *> \endverbatim
! 158: *>
! 159: *> \param[out] S
! 160: *> \verbatim
! 161: *> S is DOUBLE PRECISION array, dimension (min(M,N))
! 162: *> The singular values of A, sorted so that S(i) >= S(i+1).
! 163: *> \endverbatim
! 164: *>
! 165: *> \param[out] U
! 166: *> \verbatim
! 167: *> U is DOUBLE PRECISION array, dimension (LDU,UCOL)
! 168: *> If JOBU = 'V', U contains columns of U (the left singular
! 169: *> vectors, stored columnwise) as specified by RANGE; if
! 170: *> JOBU = 'N', U is not referenced.
! 171: *> Note: The user must ensure that UCOL >= NS; if RANGE = 'V',
! 172: *> the exact value of NS is not known ILQFin advance and an upper
! 173: *> bound must be used.
! 174: *> \endverbatim
! 175: *>
! 176: *> \param[in] LDU
! 177: *> \verbatim
! 178: *> LDU is INTEGER
! 179: *> The leading dimension of the array U. LDU >= 1; if
! 180: *> JOBU = 'V', LDU >= M.
! 181: *> \endverbatim
! 182: *>
! 183: *> \param[out] VT
! 184: *> \verbatim
! 185: *> VT is DOUBLE PRECISION array, dimension (LDVT,N)
! 186: *> If JOBVT = 'V', VT contains the rows of V**T (the right singular
! 187: *> vectors, stored rowwise) as specified by RANGE; if JOBVT = 'N',
! 188: *> VT is not referenced.
! 189: *> Note: The user must ensure that LDVT >= NS; if RANGE = 'V',
! 190: *> the exact value of NS is not known in advance and an upper
! 191: *> bound must be used.
! 192: *> \endverbatim
! 193: *>
! 194: *> \param[in] LDVT
! 195: *> \verbatim
! 196: *> LDVT is INTEGER
! 197: *> The leading dimension of the array VT. LDVT >= 1; if
! 198: *> JOBVT = 'V', LDVT >= NS (see above).
! 199: *> \endverbatim
! 200: *>
! 201: *> \param[out] WORK
! 202: *> \verbatim
! 203: *> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
! 204: *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
! 205: *> \endverbatim
! 206: *>
! 207: *> \param[in] LWORK
! 208: *> \verbatim
! 209: *> LWORK is INTEGER
! 210: *> The dimension of the array WORK.
! 211: *> LWORK >= MAX(1,MIN(M,N)*(MIN(M,N)+4)) for the paths (see
! 212: *> comments inside the code):
! 213: *> - PATH 1 (M much larger than N)
! 214: *> - PATH 1t (N much larger than M)
! 215: *> LWORK >= MAX(1,MIN(M,N)*2+MAX(M,N)) for the other paths.
! 216: *> For good performance, LWORK should generally be larger.
! 217: *>
! 218: *> If LWORK = -1, then a workspace query is assumed; the routine
! 219: *> only calculates the optimal size of the WORK array, returns
! 220: *> this value as the first entry of the WORK array, and no error
! 221: *> message related to LWORK is issued by XERBLA.
! 222: *> \endverbatim
! 223: *>
! 224: *> \param[out] IWORK
! 225: *> \verbatim
! 226: *> IWORK is INTEGER array, dimension (12*MIN(M,N))
! 227: *> If INFO = 0, the first NS elements of IWORK are zero. If INFO > 0,
! 228: *> then IWORK contains the indices of the eigenvectors that failed
! 229: *> to converge in DBDSVDX/DSTEVX.
! 230: *> \endverbatim
! 231: *>
! 232: *> \param[out] INFO
! 233: *> \verbatim
! 234: *> INFO is INTEGER
! 235: *> = 0: successful exit
! 236: *> < 0: if INFO = -i, the i-th argument had an illegal value
! 237: *> > 0: if INFO = i, then i eigenvectors failed to converge
! 238: *> in DBDSVDX/DSTEVX.
! 239: *> if INFO = N*2 + 1, an internal error occurred in
! 240: *> DBDSVDX
! 241: *> \endverbatim
! 242: *
! 243: * Authors:
! 244: * ========
! 245: *
! 246: *> \author Univ. of Tennessee
! 247: *> \author Univ. of California Berkeley
! 248: *> \author Univ. of Colorado Denver
! 249: *> \author NAG Ltd.
! 250: *
! 251: *> \date November 2015
! 252: *
! 253: *> \ingroup doubleGEsing
! 254: *
! 255: * =====================================================================
! 256: SUBROUTINE DGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
! 257: $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
! 258: $ LWORK, IWORK, INFO )
! 259: *
! 260: * -- LAPACK driver routine (version 3.6.0) --
! 261: * -- LAPACK is a software package provided by Univ. of Tennessee, --
! 262: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! 263: * November 2015
! 264: *
! 265: * .. Scalar Arguments ..
! 266: CHARACTER JOBU, JOBVT, RANGE
! 267: INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
! 268: DOUBLE PRECISION VL, VU
! 269: * ..
! 270: * .. Array Arguments ..
! 271: INTEGER IWORK( * )
! 272: DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),
! 273: $ VT( LDVT, * ), WORK( * )
! 274: * ..
! 275: *
! 276: * =====================================================================
! 277: *
! 278: * .. Parameters ..
! 279: DOUBLE PRECISION ZERO, ONE
! 280: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
! 281: * ..
! 282: * .. Local Scalars ..
! 283: CHARACTER JOBZ, RNGTGK
! 284: LOGICAL ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
! 285: INTEGER I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
! 286: $ ITAU, ITAUP, ITAUQ, ITEMP, ITGKZ, IUTGK,
! 287: $ J, MAXWRK, MINMN, MINWRK, MNTHR
! 288: DOUBLE PRECISION ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
! 289: * ..
! 290: * .. Local Arrays ..
! 291: DOUBLE PRECISION DUM( 1 )
! 292: * ..
! 293: * .. External Subroutines ..
! 294: EXTERNAL DBDSVDX, DGEBRD, DGELQF, DGEQRF, DLACPY,
! 295: $ DLASCL, DLASET, DORMBR, DORMLQ, DORMQR,
! 296: $ DSCAL, XERBLA
! 297: * ..
! 298: * .. External Functions ..
! 299: LOGICAL LSAME
! 300: INTEGER ILAENV
! 301: DOUBLE PRECISION DLAMCH, DLANGE, DNRM2
! 302: EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE, DNRM2
! 303: * ..
! 304: * .. Intrinsic Functions ..
! 305: INTRINSIC MAX, MIN, SQRT
! 306: * ..
! 307: * .. Executable Statements ..
! 308: *
! 309: * Test the input arguments.
! 310: *
! 311: NS = 0
! 312: INFO = 0
! 313: ABSTOL = 2*DLAMCH('S')
! 314: LQUERY = ( LWORK.EQ.-1 )
! 315: MINMN = MIN( M, N )
! 316:
! 317: WANTU = LSAME( JOBU, 'V' )
! 318: WANTVT = LSAME( JOBVT, 'V' )
! 319: IF( WANTU .OR. WANTVT ) THEN
! 320: JOBZ = 'V'
! 321: ELSE
! 322: JOBZ = 'N'
! 323: END IF
! 324: ALLS = LSAME( RANGE, 'A' )
! 325: VALS = LSAME( RANGE, 'V' )
! 326: INDS = LSAME( RANGE, 'I' )
! 327: *
! 328: INFO = 0
! 329: IF( .NOT.LSAME( JOBU, 'V' ) .AND.
! 330: $ .NOT.LSAME( JOBU, 'N' ) ) THEN
! 331: INFO = -1
! 332: ELSE IF( .NOT.LSAME( JOBVT, 'V' ) .AND.
! 333: $ .NOT.LSAME( JOBVT, 'N' ) ) THEN
! 334: INFO = -2
! 335: ELSE IF( .NOT.( ALLS .OR. VALS .OR. INDS ) ) THEN
! 336: INFO = -3
! 337: ELSE IF( M.LT.0 ) THEN
! 338: INFO = -4
! 339: ELSE IF( N.LT.0 ) THEN
! 340: INFO = -5
! 341: ELSE IF( M.GT.LDA ) THEN
! 342: INFO = -7
! 343: ELSE IF( MINMN.GT.0 ) THEN
! 344: IF( VALS ) THEN
! 345: IF( VL.LT.ZERO ) THEN
! 346: INFO = -8
! 347: ELSE IF( VU.LE.VL ) THEN
! 348: INFO = -9
! 349: END IF
! 350: ELSE IF( INDS ) THEN
! 351: IF( IL.LT.1 .OR. IL.GT.MAX( 1, MINMN ) ) THEN
! 352: INFO = -10
! 353: ELSE IF( IU.LT.MIN( MINMN, IL ) .OR. IU.GT.MINMN ) THEN
! 354: INFO = -11
! 355: END IF
! 356: END IF
! 357: IF( INFO.EQ.0 ) THEN
! 358: IF( WANTU .AND. LDU.LT.M ) THEN
! 359: INFO = -15
! 360: ELSE IF( WANTVT .AND. LDVT.LT.MINMN ) THEN
! 361: INFO = -16
! 362: END IF
! 363: END IF
! 364: END IF
! 365: *
! 366: * Compute workspace
! 367: * (Note: Comments in the code beginning "Workspace:" describe the
! 368: * minimal amount of workspace needed at that point in the code,
! 369: * as well as the preferred amount for good performance.
! 370: * NB refers to the optimal block size for the immediately
! 371: * following subroutine, as returned by ILAENV.)
! 372: *
! 373: IF( INFO.EQ.0 ) THEN
! 374: MINWRK = 1
! 375: MAXWRK = 1
! 376: IF( MINMN.GT.0 ) THEN
! 377: IF( M.GE.N ) THEN
! 378: MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
! 379: IF( M.GE.MNTHR ) THEN
! 380: *
! 381: * Path 1 (M much larger than N)
! 382: *
! 383: MAXWRK = N*(N*2+16) +
! 384: $ N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
! 385: MAXWRK = MAX( MAXWRK, N*(N*2+20) + 2*N*
! 386: $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
! 387: MINWRK = N*(N*2+21)
! 388: ELSE
! 389: *
! 390: * Path 2 (M at least N, but not much larger)
! 391: *
! 392: MAXWRK = N*(N*2+19) + ( M+N )*
! 393: $ ILAENV( 1, 'DGEBRD', ' ', M, N, -1, -1 )
! 394: MINWRK = N*(N*2+20) + M
! 395: END IF
! 396: ELSE
! 397: MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
! 398: IF( N.GE.MNTHR ) THEN
! 399: *
! 400: * Path 1t (N much larger than M)
! 401: *
! 402: MAXWRK = M*(M*2+16) +
! 403: $ M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
! 404: MAXWRK = MAX( MAXWRK, M*(M*2+20) + 2*M*
! 405: $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
! 406: MINWRK = M*(M*2+21)
! 407: ELSE
! 408: *
! 409: * Path 2t (N greater than M, but not much larger)
! 410: *
! 411: MAXWRK = M*(M*2+19) + ( M+N )*
! 412: $ ILAENV( 1, 'DGEBRD', ' ', M, N, -1, -1 )
! 413: MINWRK = M*(M*2+20) + N
! 414: END IF
! 415: END IF
! 416: END IF
! 417: MAXWRK = MAX( MAXWRK, MINWRK )
! 418: WORK( 1 ) = DBLE( MAXWRK )
! 419: *
! 420: IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
! 421: INFO = -19
! 422: END IF
! 423: END IF
! 424: *
! 425: IF( INFO.NE.0 ) THEN
! 426: CALL XERBLA( 'DGESVDX', -INFO )
! 427: RETURN
! 428: ELSE IF( LQUERY ) THEN
! 429: RETURN
! 430: END IF
! 431: *
! 432: * Quick return if possible
! 433: *
! 434: IF( M.EQ.0 .OR. N.EQ.0 ) THEN
! 435: RETURN
! 436: END IF
! 437: *
! 438: * Set singular values indices accord to RANGE.
! 439: *
! 440: IF( ALLS ) THEN
! 441: RNGTGK = 'I'
! 442: ILTGK = 1
! 443: IUTGK = MIN( M, N )
! 444: ELSE IF( INDS ) THEN
! 445: RNGTGK = 'I'
! 446: ILTGK = IL
! 447: IUTGK = IU
! 448: ELSE
! 449: RNGTGK = 'V'
! 450: ILTGK = 0
! 451: IUTGK = 0
! 452: END IF
! 453: *
! 454: * Get machine constants
! 455: *
! 456: EPS = DLAMCH( 'P' )
! 457: SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS
! 458: BIGNUM = ONE / SMLNUM
! 459: *
! 460: * Scale A if max element outside range [SMLNUM,BIGNUM]
! 461: *
! 462: ANRM = DLANGE( 'M', M, N, A, LDA, DUM )
! 463: ISCL = 0
! 464: IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
! 465: ISCL = 1
! 466: CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
! 467: ELSE IF( ANRM.GT.BIGNUM ) THEN
! 468: ISCL = 1
! 469: CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
! 470: END IF
! 471: *
! 472: IF( M.GE.N ) THEN
! 473: *
! 474: * A has at least as many rows as columns. If A has sufficiently
! 475: * more rows than columns, first reduce A using the QR
! 476: * decomposition.
! 477: *
! 478: IF( M.GE.MNTHR ) THEN
! 479: *
! 480: * Path 1 (M much larger than N):
! 481: * A = Q * R = Q * ( QB * B * PB**T )
! 482: * = Q * ( QB * ( UB * S * VB**T ) * PB**T )
! 483: * U = Q * QB * UB; V**T = VB**T * PB**T
! 484: *
! 485: * Compute A=Q*R
! 486: * (Workspace: need 2*N, prefer N+N*NB)
! 487: *
! 488: ITAU = 1
! 489: ITEMP = ITAU + N
! 490: CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
! 491: $ LWORK-ITEMP+1, INFO )
! 492: *
! 493: * Copy R into WORK and bidiagonalize it:
! 494: * (Workspace: need N*N+5*N, prefer N*N+4*N+2*N*NB)
! 495: *
! 496: IQRF = ITEMP
! 497: ID = IQRF + N*N
! 498: IE = ID + N
! 499: ITAUQ = IE + N
! 500: ITAUP = ITAUQ + N
! 501: ITEMP = ITAUP + N
! 502: CALL DLACPY( 'U', N, N, A, LDA, WORK( IQRF ), N )
! 503: CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IQRF+1 ), N )
! 504: CALL DGEBRD( N, N, WORK( IQRF ), N, WORK( ID ), WORK( IE ),
! 505: $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
! 506: $ LWORK-ITEMP+1, INFO )
! 507: *
! 508: * Solve eigenvalue problem TGK*Z=Z*S.
! 509: * (Workspace: need 14*N + 2*N*(N+1))
! 510: *
! 511: ITGKZ = ITEMP
! 512: ITEMP = ITGKZ + N*(N*2+1)
! 513: CALL DBDSVDX( 'U', JOBZ, RNGTGK, N, WORK( ID ), WORK( IE ),
! 514: $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
! 515: $ N*2, WORK( ITEMP ), IWORK, INFO)
! 516: *
! 517: * If needed, compute left singular vectors.
! 518: *
! 519: IF( WANTU ) THEN
! 520: J = ITGKZ
! 521: DO I = 1, NS
! 522: CALL DCOPY( N, WORK( J ), 1, U( 1,I ), 1 )
! 523: J = J + N*2
! 524: END DO
! 525: CALL DLASET( 'A', M-N, N, ZERO, ZERO, U( N+1,1 ), LDU )
! 526: *
! 527: * Call DORMBR to compute QB*UB.
! 528: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
! 529: *
! 530: CALL DORMBR( 'Q', 'L', 'N', N, NS, N, WORK( IQRF ), N,
! 531: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
! 532: $ LWORK-ITEMP+1, INFO )
! 533: *
! 534: * Call DORMQR to compute Q*(QB*UB).
! 535: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
! 536: *
! 537: CALL DORMQR( 'L', 'N', M, NS, N, A, LDA,
! 538: $ WORK( ITAU ), U, LDU, WORK( ITEMP ),
! 539: $ LWORK-ITEMP+1, INFO )
! 540: END IF
! 541: *
! 542: * If needed, compute right singular vectors.
! 543: *
! 544: IF( WANTVT) THEN
! 545: J = ITGKZ + N
! 546: DO I = 1, NS
! 547: CALL DCOPY( N, WORK( J ), 1, VT( I,1 ), LDVT )
! 548: J = J + N*2
! 549: END DO
! 550: *
! 551: * Call DORMBR to compute VB**T * PB**T
! 552: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
! 553: *
! 554: CALL DORMBR( 'P', 'R', 'T', NS, N, N, WORK( IQRF ), N,
! 555: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
! 556: $ LWORK-ITEMP+1, INFO )
! 557: END IF
! 558: ELSE
! 559: *
! 560: * Path 2 (M at least N, but not much larger)
! 561: * Reduce A to bidiagonal form without QR decomposition
! 562: * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
! 563: * U = QB * UB; V**T = VB**T * PB**T
! 564: *
! 565: * Bidiagonalize A
! 566: * (Workspace: need 4*N+M, prefer 4*N+(M+N)*NB)
! 567: *
! 568: ID = 1
! 569: IE = ID + N
! 570: ITAUQ = IE + N
! 571: ITAUP = ITAUQ + N
! 572: ITEMP = ITAUP + N
! 573: CALL DGEBRD( M, N, A, LDA, WORK( ID ), WORK( IE ),
! 574: $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
! 575: $ LWORK-ITEMP+1, INFO )
! 576: *
! 577: * Solve eigenvalue problem TGK*Z=Z*S.
! 578: * (Workspace: need 14*N + 2*N*(N+1))
! 579: *
! 580: ITGKZ = ITEMP
! 581: ITEMP = ITGKZ + N*(N*2+1)
! 582: CALL DBDSVDX( 'U', JOBZ, RNGTGK, N, WORK( ID ), WORK( IE ),
! 583: $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
! 584: $ N*2, WORK( ITEMP ), IWORK, INFO)
! 585: *
! 586: * If needed, compute left singular vectors.
! 587: *
! 588: IF( WANTU ) THEN
! 589: J = ITGKZ
! 590: DO I = 1, NS
! 591: CALL DCOPY( N, WORK( J ), 1, U( 1,I ), 1 )
! 592: J = J + N*2
! 593: END DO
! 594: CALL DLASET( 'A', M-N, N, ZERO, ZERO, U( N+1,1 ), LDU )
! 595: *
! 596: * Call DORMBR to compute QB*UB.
! 597: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
! 598: *
! 599: CALL DORMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
! 600: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
! 601: $ LWORK-ITEMP+1, IERR )
! 602: END IF
! 603: *
! 604: * If needed, compute right singular vectors.
! 605: *
! 606: IF( WANTVT) THEN
! 607: J = ITGKZ + N
! 608: DO I = 1, NS
! 609: CALL DCOPY( N, WORK( J ), 1, VT( I,1 ), LDVT )
! 610: J = J + N*2
! 611: END DO
! 612: *
! 613: * Call DORMBR to compute VB**T * PB**T
! 614: * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
! 615: *
! 616: CALL DORMBR( 'P', 'R', 'T', NS, N, N, A, LDA,
! 617: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
! 618: $ LWORK-ITEMP+1, IERR )
! 619: END IF
! 620: END IF
! 621: ELSE
! 622: *
! 623: * A has more columns than rows. If A has sufficiently more
! 624: * columns than rows, first reduce A using the LQ decomposition.
! 625: *
! 626: IF( N.GE.MNTHR ) THEN
! 627: *
! 628: * Path 1t (N much larger than M):
! 629: * A = L * Q = ( QB * B * PB**T ) * Q
! 630: * = ( QB * ( UB * S * VB**T ) * PB**T ) * Q
! 631: * U = QB * UB ; V**T = VB**T * PB**T * Q
! 632: *
! 633: * Compute A=L*Q
! 634: * (Workspace: need 2*M, prefer M+M*NB)
! 635: *
! 636: ITAU = 1
! 637: ITEMP = ITAU + M
! 638: CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
! 639: $ LWORK-ITEMP+1, INFO )
! 640:
! 641: * Copy L into WORK and bidiagonalize it:
! 642: * (Workspace in WORK( ITEMP ): need M*M+5*N, prefer M*M+4*M+2*M*NB)
! 643: *
! 644: ILQF = ITEMP
! 645: ID = ILQF + M*M
! 646: IE = ID + M
! 647: ITAUQ = IE + M
! 648: ITAUP = ITAUQ + M
! 649: ITEMP = ITAUP + M
! 650: CALL DLACPY( 'L', M, M, A, LDA, WORK( ILQF ), M )
! 651: CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, WORK( ILQF+M ), M )
! 652: CALL DGEBRD( M, M, WORK( ILQF ), M, WORK( ID ), WORK( IE ),
! 653: $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
! 654: $ LWORK-ITEMP+1, INFO )
! 655: *
! 656: * Solve eigenvalue problem TGK*Z=Z*S.
! 657: * (Workspace: need 2*M*M+14*M)
! 658: *
! 659: ITGKZ = ITEMP
! 660: ITEMP = ITGKZ + M*(M*2+1)
! 661: CALL DBDSVDX( 'U', JOBZ, RNGTGK, M, WORK( ID ), WORK( IE ),
! 662: $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
! 663: $ M*2, WORK( ITEMP ), IWORK, INFO)
! 664: *
! 665: * If needed, compute left singular vectors.
! 666: *
! 667: IF( WANTU ) THEN
! 668: J = ITGKZ
! 669: DO I = 1, NS
! 670: CALL DCOPY( M, WORK( J ), 1, U( 1,I ), 1 )
! 671: J = J + M*2
! 672: END DO
! 673: *
! 674: * Call DORMBR to compute QB*UB.
! 675: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
! 676: *
! 677: CALL DORMBR( 'Q', 'L', 'N', M, NS, M, WORK( ILQF ), M,
! 678: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
! 679: $ LWORK-ITEMP+1, INFO )
! 680: END IF
! 681: *
! 682: * If needed, compute right singular vectors.
! 683: *
! 684: IF( WANTVT) THEN
! 685: J = ITGKZ + M
! 686: DO I = 1, NS
! 687: CALL DCOPY( M, WORK( J ), 1, VT( I,1 ), LDVT )
! 688: J = J + M*2
! 689: END DO
! 690: CALL DLASET( 'A', M, N-M, ZERO, ZERO, VT( 1,M+1 ), LDVT )
! 691: *
! 692: * Call DORMBR to compute (VB**T)*(PB**T)
! 693: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
! 694: *
! 695: CALL DORMBR( 'P', 'R', 'T', NS, M, M, WORK( ILQF ), M,
! 696: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
! 697: $ LWORK-ITEMP+1, INFO )
! 698: *
! 699: * Call DORMLQ to compute ((VB**T)*(PB**T))*Q.
! 700: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
! 701: *
! 702: CALL DORMLQ( 'R', 'N', NS, N, M, A, LDA,
! 703: $ WORK( ITAU ), VT, LDVT, WORK( ITEMP ),
! 704: $ LWORK-ITEMP+1, INFO )
! 705: END IF
! 706: ELSE
! 707: *
! 708: * Path 2t (N greater than M, but not much larger)
! 709: * Reduce to bidiagonal form without LQ decomposition
! 710: * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
! 711: * U = QB * UB; V**T = VB**T * PB**T
! 712: *
! 713: * Bidiagonalize A
! 714: * (Workspace: need 4*M+N, prefer 4*M+(M+N)*NB)
! 715: *
! 716: ID = 1
! 717: IE = ID + M
! 718: ITAUQ = IE + M
! 719: ITAUP = ITAUQ + M
! 720: ITEMP = ITAUP + M
! 721: CALL DGEBRD( M, N, A, LDA, WORK( ID ), WORK( IE ),
! 722: $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
! 723: $ LWORK-ITEMP+1, INFO )
! 724: *
! 725: * Solve eigenvalue problem TGK*Z=Z*S.
! 726: * (Workspace: need 2*M*M+14*M)
! 727: *
! 728: ITGKZ = ITEMP
! 729: ITEMP = ITGKZ + M*(M*2+1)
! 730: CALL DBDSVDX( 'L', JOBZ, RNGTGK, M, WORK( ID ), WORK( IE ),
! 731: $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
! 732: $ M*2, WORK( ITEMP ), IWORK, INFO)
! 733: *
! 734: * If needed, compute left singular vectors.
! 735: *
! 736: IF( WANTU ) THEN
! 737: J = ITGKZ
! 738: DO I = 1, NS
! 739: CALL DCOPY( M, WORK( J ), 1, U( 1,I ), 1 )
! 740: J = J + M*2
! 741: END DO
! 742: *
! 743: * Call DORMBR to compute QB*UB.
! 744: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
! 745: *
! 746: CALL DORMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
! 747: $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
! 748: $ LWORK-ITEMP+1, INFO )
! 749: END IF
! 750: *
! 751: * If needed, compute right singular vectors.
! 752: *
! 753: IF( WANTVT) THEN
! 754: J = ITGKZ + M
! 755: DO I = 1, NS
! 756: CALL DCOPY( M, WORK( J ), 1, VT( I,1 ), LDVT )
! 757: J = J + M*2
! 758: END DO
! 759: CALL DLASET( 'A', M, N-M, ZERO, ZERO, VT( 1,M+1 ), LDVT )
! 760: *
! 761: * Call DORMBR to compute VB**T * PB**T
! 762: * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
! 763: *
! 764: CALL DORMBR( 'P', 'R', 'T', NS, N, M, A, LDA,
! 765: $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
! 766: $ LWORK-ITEMP+1, INFO )
! 767: END IF
! 768: END IF
! 769: END IF
! 770: *
! 771: * Undo scaling if necessary
! 772: *
! 773: IF( ISCL.EQ.1 ) THEN
! 774: IF( ANRM.GT.BIGNUM )
! 775: $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1,
! 776: $ S, MINMN, INFO )
! 777: IF( ANRM.LT.SMLNUM )
! 778: $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1,
! 779: $ S, MINMN, INFO )
! 780: END IF
! 781: *
! 782: * Return optimal workspace in WORK(1)
! 783: *
! 784: WORK( 1 ) = DBLE( MAXWRK )
! 785: *
! 786: RETURN
! 787: *
! 788: * End of DGESVDX
! 789: *
! 790: END
CVSweb interface <joel.bertrand@systella.fr>