Annotation of rpl/lapack/lapack/zlalsd.f, revision 1.1
1.1 ! bertrand 1: SUBROUTINE ZLALSD( UPLO, SMLSIZ, N, NRHS, D, E, B, LDB, RCOND,
! 2: $ RANK, WORK, RWORK, IWORK, INFO )
! 3: *
! 4: * -- LAPACK routine (version 3.2) --
! 5: * -- LAPACK is a software package provided by Univ. of Tennessee, --
! 6: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! 7: * November 2006
! 8: *
! 9: * .. Scalar Arguments ..
! 10: CHARACTER UPLO
! 11: INTEGER INFO, LDB, N, NRHS, RANK, SMLSIZ
! 12: DOUBLE PRECISION RCOND
! 13: * ..
! 14: * .. Array Arguments ..
! 15: INTEGER IWORK( * )
! 16: DOUBLE PRECISION D( * ), E( * ), RWORK( * )
! 17: COMPLEX*16 B( LDB, * ), WORK( * )
! 18: * ..
! 19: *
! 20: * Purpose
! 21: * =======
! 22: *
! 23: * ZLALSD uses the singular value decomposition of A to solve the least
! 24: * squares problem of finding X to minimize the Euclidean norm of each
! 25: * column of A*X-B, where A is N-by-N upper bidiagonal, and X and B
! 26: * are N-by-NRHS. The solution X overwrites B.
! 27: *
! 28: * The singular values of A smaller than RCOND times the largest
! 29: * singular value are treated as zero in solving the least squares
! 30: * problem; in this case a minimum norm solution is returned.
! 31: * The actual singular values are returned in D in ascending order.
! 32: *
! 33: * This code makes very mild assumptions about floating point
! 34: * arithmetic. It will work on machines with a guard digit in
! 35: * add/subtract, or on those binary machines without guard digits
! 36: * which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2.
! 37: * It could conceivably fail on hexadecimal or decimal machines
! 38: * without guard digits, but we know of none.
! 39: *
! 40: * Arguments
! 41: * =========
! 42: *
! 43: * UPLO (input) CHARACTER*1
! 44: * = 'U': D and E define an upper bidiagonal matrix.
! 45: * = 'L': D and E define a lower bidiagonal matrix.
! 46: *
! 47: * SMLSIZ (input) INTEGER
! 48: * The maximum size of the subproblems at the bottom of the
! 49: * computation tree.
! 50: *
! 51: * N (input) INTEGER
! 52: * The dimension of the bidiagonal matrix. N >= 0.
! 53: *
! 54: * NRHS (input) INTEGER
! 55: * The number of columns of B. NRHS must be at least 1.
! 56: *
! 57: * D (input/output) DOUBLE PRECISION array, dimension (N)
! 58: * On entry D contains the main diagonal of the bidiagonal
! 59: * matrix. On exit, if INFO = 0, D contains its singular values.
! 60: *
! 61: * E (input/output) DOUBLE PRECISION array, dimension (N-1)
! 62: * Contains the super-diagonal entries of the bidiagonal matrix.
! 63: * On exit, E has been destroyed.
! 64: *
! 65: * B (input/output) COMPLEX*16 array, dimension (LDB,NRHS)
! 66: * On input, B contains the right hand sides of the least
! 67: * squares problem. On output, B contains the solution X.
! 68: *
! 69: * LDB (input) INTEGER
! 70: * The leading dimension of B in the calling subprogram.
! 71: * LDB must be at least max(1,N).
! 72: *
! 73: * RCOND (input) DOUBLE PRECISION
! 74: * The singular values of A less than or equal to RCOND times
! 75: * the largest singular value are treated as zero in solving
! 76: * the least squares problem. If RCOND is negative,
! 77: * machine precision is used instead.
! 78: * For example, if diag(S)*X=B were the least squares problem,
! 79: * where diag(S) is a diagonal matrix of singular values, the
! 80: * solution would be X(i) = B(i) / S(i) if S(i) is greater than
! 81: * RCOND*max(S), and X(i) = 0 if S(i) is less than or equal to
! 82: * RCOND*max(S).
! 83: *
! 84: * RANK (output) INTEGER
! 85: * The number of singular values of A greater than RCOND times
! 86: * the largest singular value.
! 87: *
! 88: * WORK (workspace) COMPLEX*16 array, dimension at least
! 89: * (N * NRHS).
! 90: *
! 91: * RWORK (workspace) DOUBLE PRECISION array, dimension at least
! 92: * (9*N + 2*N*SMLSIZ + 8*N*NLVL + 3*SMLSIZ*NRHS + (SMLSIZ+1)**2),
! 93: * where
! 94: * NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 )
! 95: *
! 96: * IWORK (workspace) INTEGER array, dimension at least
! 97: * (3*N*NLVL + 11*N).
! 98: *
! 99: * INFO (output) INTEGER
! 100: * = 0: successful exit.
! 101: * < 0: if INFO = -i, the i-th argument had an illegal value.
! 102: * > 0: The algorithm failed to compute an singular value while
! 103: * working on the submatrix lying in rows and columns
! 104: * INFO/(N+1) through MOD(INFO,N+1).
! 105: *
! 106: * Further Details
! 107: * ===============
! 108: *
! 109: * Based on contributions by
! 110: * Ming Gu and Ren-Cang Li, Computer Science Division, University of
! 111: * California at Berkeley, USA
! 112: * Osni Marques, LBNL/NERSC, USA
! 113: *
! 114: * =====================================================================
! 115: *
! 116: * .. Parameters ..
! 117: DOUBLE PRECISION ZERO, ONE, TWO
! 118: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )
! 119: COMPLEX*16 CZERO
! 120: PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ) )
! 121: * ..
! 122: * .. Local Scalars ..
! 123: INTEGER BX, BXST, C, DIFL, DIFR, GIVCOL, GIVNUM,
! 124: $ GIVPTR, I, ICMPQ1, ICMPQ2, IRWB, IRWIB, IRWRB,
! 125: $ IRWU, IRWVT, IRWWRK, IWK, J, JCOL, JIMAG,
! 126: $ JREAL, JROW, K, NLVL, NM1, NRWORK, NSIZE, NSUB,
! 127: $ PERM, POLES, S, SIZEI, SMLSZP, SQRE, ST, ST1,
! 128: $ U, VT, Z
! 129: DOUBLE PRECISION CS, EPS, ORGNRM, RCND, R, SN, TOL
! 130: * ..
! 131: * .. External Functions ..
! 132: INTEGER IDAMAX
! 133: DOUBLE PRECISION DLAMCH, DLANST
! 134: EXTERNAL IDAMAX, DLAMCH, DLANST
! 135: * ..
! 136: * .. External Subroutines ..
! 137: EXTERNAL DGEMM, DLARTG, DLASCL, DLASDA, DLASDQ, DLASET,
! 138: $ DLASRT, XERBLA, ZCOPY, ZDROT, ZLACPY, ZLALSA,
! 139: $ ZLASCL, ZLASET
! 140: * ..
! 141: * .. Intrinsic Functions ..
! 142: INTRINSIC ABS, DBLE, DCMPLX, DIMAG, INT, LOG, SIGN
! 143: * ..
! 144: * .. Executable Statements ..
! 145: *
! 146: * Test the input parameters.
! 147: *
! 148: INFO = 0
! 149: *
! 150: IF( N.LT.0 ) THEN
! 151: INFO = -3
! 152: ELSE IF( NRHS.LT.1 ) THEN
! 153: INFO = -4
! 154: ELSE IF( ( LDB.LT.1 ) .OR. ( LDB.LT.N ) ) THEN
! 155: INFO = -8
! 156: END IF
! 157: IF( INFO.NE.0 ) THEN
! 158: CALL XERBLA( 'ZLALSD', -INFO )
! 159: RETURN
! 160: END IF
! 161: *
! 162: EPS = DLAMCH( 'Epsilon' )
! 163: *
! 164: * Set up the tolerance.
! 165: *
! 166: IF( ( RCOND.LE.ZERO ) .OR. ( RCOND.GE.ONE ) ) THEN
! 167: RCND = EPS
! 168: ELSE
! 169: RCND = RCOND
! 170: END IF
! 171: *
! 172: RANK = 0
! 173: *
! 174: * Quick return if possible.
! 175: *
! 176: IF( N.EQ.0 ) THEN
! 177: RETURN
! 178: ELSE IF( N.EQ.1 ) THEN
! 179: IF( D( 1 ).EQ.ZERO ) THEN
! 180: CALL ZLASET( 'A', 1, NRHS, CZERO, CZERO, B, LDB )
! 181: ELSE
! 182: RANK = 1
! 183: CALL ZLASCL( 'G', 0, 0, D( 1 ), ONE, 1, NRHS, B, LDB, INFO )
! 184: D( 1 ) = ABS( D( 1 ) )
! 185: END IF
! 186: RETURN
! 187: END IF
! 188: *
! 189: * Rotate the matrix if it is lower bidiagonal.
! 190: *
! 191: IF( UPLO.EQ.'L' ) THEN
! 192: DO 10 I = 1, N - 1
! 193: CALL DLARTG( D( I ), E( I ), CS, SN, R )
! 194: D( I ) = R
! 195: E( I ) = SN*D( I+1 )
! 196: D( I+1 ) = CS*D( I+1 )
! 197: IF( NRHS.EQ.1 ) THEN
! 198: CALL ZDROT( 1, B( I, 1 ), 1, B( I+1, 1 ), 1, CS, SN )
! 199: ELSE
! 200: RWORK( I*2-1 ) = CS
! 201: RWORK( I*2 ) = SN
! 202: END IF
! 203: 10 CONTINUE
! 204: IF( NRHS.GT.1 ) THEN
! 205: DO 30 I = 1, NRHS
! 206: DO 20 J = 1, N - 1
! 207: CS = RWORK( J*2-1 )
! 208: SN = RWORK( J*2 )
! 209: CALL ZDROT( 1, B( J, I ), 1, B( J+1, I ), 1, CS, SN )
! 210: 20 CONTINUE
! 211: 30 CONTINUE
! 212: END IF
! 213: END IF
! 214: *
! 215: * Scale.
! 216: *
! 217: NM1 = N - 1
! 218: ORGNRM = DLANST( 'M', N, D, E )
! 219: IF( ORGNRM.EQ.ZERO ) THEN
! 220: CALL ZLASET( 'A', N, NRHS, CZERO, CZERO, B, LDB )
! 221: RETURN
! 222: END IF
! 223: *
! 224: CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, 1, D, N, INFO )
! 225: CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, NM1, 1, E, NM1, INFO )
! 226: *
! 227: * If N is smaller than the minimum divide size SMLSIZ, then solve
! 228: * the problem with another solver.
! 229: *
! 230: IF( N.LE.SMLSIZ ) THEN
! 231: IRWU = 1
! 232: IRWVT = IRWU + N*N
! 233: IRWWRK = IRWVT + N*N
! 234: IRWRB = IRWWRK
! 235: IRWIB = IRWRB + N*NRHS
! 236: IRWB = IRWIB + N*NRHS
! 237: CALL DLASET( 'A', N, N, ZERO, ONE, RWORK( IRWU ), N )
! 238: CALL DLASET( 'A', N, N, ZERO, ONE, RWORK( IRWVT ), N )
! 239: CALL DLASDQ( 'U', 0, N, N, N, 0, D, E, RWORK( IRWVT ), N,
! 240: $ RWORK( IRWU ), N, RWORK( IRWWRK ), 1,
! 241: $ RWORK( IRWWRK ), INFO )
! 242: IF( INFO.NE.0 ) THEN
! 243: RETURN
! 244: END IF
! 245: *
! 246: * In the real version, B is passed to DLASDQ and multiplied
! 247: * internally by Q'. Here B is complex and that product is
! 248: * computed below in two steps (real and imaginary parts).
! 249: *
! 250: J = IRWB - 1
! 251: DO 50 JCOL = 1, NRHS
! 252: DO 40 JROW = 1, N
! 253: J = J + 1
! 254: RWORK( J ) = DBLE( B( JROW, JCOL ) )
! 255: 40 CONTINUE
! 256: 50 CONTINUE
! 257: CALL DGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWU ), N,
! 258: $ RWORK( IRWB ), N, ZERO, RWORK( IRWRB ), N )
! 259: J = IRWB - 1
! 260: DO 70 JCOL = 1, NRHS
! 261: DO 60 JROW = 1, N
! 262: J = J + 1
! 263: RWORK( J ) = DIMAG( B( JROW, JCOL ) )
! 264: 60 CONTINUE
! 265: 70 CONTINUE
! 266: CALL DGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWU ), N,
! 267: $ RWORK( IRWB ), N, ZERO, RWORK( IRWIB ), N )
! 268: JREAL = IRWRB - 1
! 269: JIMAG = IRWIB - 1
! 270: DO 90 JCOL = 1, NRHS
! 271: DO 80 JROW = 1, N
! 272: JREAL = JREAL + 1
! 273: JIMAG = JIMAG + 1
! 274: B( JROW, JCOL ) = DCMPLX( RWORK( JREAL ),
! 275: $ RWORK( JIMAG ) )
! 276: 80 CONTINUE
! 277: 90 CONTINUE
! 278: *
! 279: TOL = RCND*ABS( D( IDAMAX( N, D, 1 ) ) )
! 280: DO 100 I = 1, N
! 281: IF( D( I ).LE.TOL ) THEN
! 282: CALL ZLASET( 'A', 1, NRHS, CZERO, CZERO, B( I, 1 ), LDB )
! 283: ELSE
! 284: CALL ZLASCL( 'G', 0, 0, D( I ), ONE, 1, NRHS, B( I, 1 ),
! 285: $ LDB, INFO )
! 286: RANK = RANK + 1
! 287: END IF
! 288: 100 CONTINUE
! 289: *
! 290: * Since B is complex, the following call to DGEMM is performed
! 291: * in two steps (real and imaginary parts). That is for V * B
! 292: * (in the real version of the code V' is stored in WORK).
! 293: *
! 294: * CALL DGEMM( 'T', 'N', N, NRHS, N, ONE, WORK, N, B, LDB, ZERO,
! 295: * $ WORK( NWORK ), N )
! 296: *
! 297: J = IRWB - 1
! 298: DO 120 JCOL = 1, NRHS
! 299: DO 110 JROW = 1, N
! 300: J = J + 1
! 301: RWORK( J ) = DBLE( B( JROW, JCOL ) )
! 302: 110 CONTINUE
! 303: 120 CONTINUE
! 304: CALL DGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWVT ), N,
! 305: $ RWORK( IRWB ), N, ZERO, RWORK( IRWRB ), N )
! 306: J = IRWB - 1
! 307: DO 140 JCOL = 1, NRHS
! 308: DO 130 JROW = 1, N
! 309: J = J + 1
! 310: RWORK( J ) = DIMAG( B( JROW, JCOL ) )
! 311: 130 CONTINUE
! 312: 140 CONTINUE
! 313: CALL DGEMM( 'T', 'N', N, NRHS, N, ONE, RWORK( IRWVT ), N,
! 314: $ RWORK( IRWB ), N, ZERO, RWORK( IRWIB ), N )
! 315: JREAL = IRWRB - 1
! 316: JIMAG = IRWIB - 1
! 317: DO 160 JCOL = 1, NRHS
! 318: DO 150 JROW = 1, N
! 319: JREAL = JREAL + 1
! 320: JIMAG = JIMAG + 1
! 321: B( JROW, JCOL ) = DCMPLX( RWORK( JREAL ),
! 322: $ RWORK( JIMAG ) )
! 323: 150 CONTINUE
! 324: 160 CONTINUE
! 325: *
! 326: * Unscale.
! 327: *
! 328: CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
! 329: CALL DLASRT( 'D', N, D, INFO )
! 330: CALL ZLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
! 331: *
! 332: RETURN
! 333: END IF
! 334: *
! 335: * Book-keeping and setting up some constants.
! 336: *
! 337: NLVL = INT( LOG( DBLE( N ) / DBLE( SMLSIZ+1 ) ) / LOG( TWO ) ) + 1
! 338: *
! 339: SMLSZP = SMLSIZ + 1
! 340: *
! 341: U = 1
! 342: VT = 1 + SMLSIZ*N
! 343: DIFL = VT + SMLSZP*N
! 344: DIFR = DIFL + NLVL*N
! 345: Z = DIFR + NLVL*N*2
! 346: C = Z + NLVL*N
! 347: S = C + N
! 348: POLES = S + N
! 349: GIVNUM = POLES + 2*NLVL*N
! 350: NRWORK = GIVNUM + 2*NLVL*N
! 351: BX = 1
! 352: *
! 353: IRWRB = NRWORK
! 354: IRWIB = IRWRB + SMLSIZ*NRHS
! 355: IRWB = IRWIB + SMLSIZ*NRHS
! 356: *
! 357: SIZEI = 1 + N
! 358: K = SIZEI + N
! 359: GIVPTR = K + N
! 360: PERM = GIVPTR + N
! 361: GIVCOL = PERM + NLVL*N
! 362: IWK = GIVCOL + NLVL*N*2
! 363: *
! 364: ST = 1
! 365: SQRE = 0
! 366: ICMPQ1 = 1
! 367: ICMPQ2 = 0
! 368: NSUB = 0
! 369: *
! 370: DO 170 I = 1, N
! 371: IF( ABS( D( I ) ).LT.EPS ) THEN
! 372: D( I ) = SIGN( EPS, D( I ) )
! 373: END IF
! 374: 170 CONTINUE
! 375: *
! 376: DO 240 I = 1, NM1
! 377: IF( ( ABS( E( I ) ).LT.EPS ) .OR. ( I.EQ.NM1 ) ) THEN
! 378: NSUB = NSUB + 1
! 379: IWORK( NSUB ) = ST
! 380: *
! 381: * Subproblem found. First determine its size and then
! 382: * apply divide and conquer on it.
! 383: *
! 384: IF( I.LT.NM1 ) THEN
! 385: *
! 386: * A subproblem with E(I) small for I < NM1.
! 387: *
! 388: NSIZE = I - ST + 1
! 389: IWORK( SIZEI+NSUB-1 ) = NSIZE
! 390: ELSE IF( ABS( E( I ) ).GE.EPS ) THEN
! 391: *
! 392: * A subproblem with E(NM1) not too small but I = NM1.
! 393: *
! 394: NSIZE = N - ST + 1
! 395: IWORK( SIZEI+NSUB-1 ) = NSIZE
! 396: ELSE
! 397: *
! 398: * A subproblem with E(NM1) small. This implies an
! 399: * 1-by-1 subproblem at D(N), which is not solved
! 400: * explicitly.
! 401: *
! 402: NSIZE = I - ST + 1
! 403: IWORK( SIZEI+NSUB-1 ) = NSIZE
! 404: NSUB = NSUB + 1
! 405: IWORK( NSUB ) = N
! 406: IWORK( SIZEI+NSUB-1 ) = 1
! 407: CALL ZCOPY( NRHS, B( N, 1 ), LDB, WORK( BX+NM1 ), N )
! 408: END IF
! 409: ST1 = ST - 1
! 410: IF( NSIZE.EQ.1 ) THEN
! 411: *
! 412: * This is a 1-by-1 subproblem and is not solved
! 413: * explicitly.
! 414: *
! 415: CALL ZCOPY( NRHS, B( ST, 1 ), LDB, WORK( BX+ST1 ), N )
! 416: ELSE IF( NSIZE.LE.SMLSIZ ) THEN
! 417: *
! 418: * This is a small subproblem and is solved by DLASDQ.
! 419: *
! 420: CALL DLASET( 'A', NSIZE, NSIZE, ZERO, ONE,
! 421: $ RWORK( VT+ST1 ), N )
! 422: CALL DLASET( 'A', NSIZE, NSIZE, ZERO, ONE,
! 423: $ RWORK( U+ST1 ), N )
! 424: CALL DLASDQ( 'U', 0, NSIZE, NSIZE, NSIZE, 0, D( ST ),
! 425: $ E( ST ), RWORK( VT+ST1 ), N, RWORK( U+ST1 ),
! 426: $ N, RWORK( NRWORK ), 1, RWORK( NRWORK ),
! 427: $ INFO )
! 428: IF( INFO.NE.0 ) THEN
! 429: RETURN
! 430: END IF
! 431: *
! 432: * In the real version, B is passed to DLASDQ and multiplied
! 433: * internally by Q'. Here B is complex and that product is
! 434: * computed below in two steps (real and imaginary parts).
! 435: *
! 436: J = IRWB - 1
! 437: DO 190 JCOL = 1, NRHS
! 438: DO 180 JROW = ST, ST + NSIZE - 1
! 439: J = J + 1
! 440: RWORK( J ) = DBLE( B( JROW, JCOL ) )
! 441: 180 CONTINUE
! 442: 190 CONTINUE
! 443: CALL DGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
! 444: $ RWORK( U+ST1 ), N, RWORK( IRWB ), NSIZE,
! 445: $ ZERO, RWORK( IRWRB ), NSIZE )
! 446: J = IRWB - 1
! 447: DO 210 JCOL = 1, NRHS
! 448: DO 200 JROW = ST, ST + NSIZE - 1
! 449: J = J + 1
! 450: RWORK( J ) = DIMAG( B( JROW, JCOL ) )
! 451: 200 CONTINUE
! 452: 210 CONTINUE
! 453: CALL DGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
! 454: $ RWORK( U+ST1 ), N, RWORK( IRWB ), NSIZE,
! 455: $ ZERO, RWORK( IRWIB ), NSIZE )
! 456: JREAL = IRWRB - 1
! 457: JIMAG = IRWIB - 1
! 458: DO 230 JCOL = 1, NRHS
! 459: DO 220 JROW = ST, ST + NSIZE - 1
! 460: JREAL = JREAL + 1
! 461: JIMAG = JIMAG + 1
! 462: B( JROW, JCOL ) = DCMPLX( RWORK( JREAL ),
! 463: $ RWORK( JIMAG ) )
! 464: 220 CONTINUE
! 465: 230 CONTINUE
! 466: *
! 467: CALL ZLACPY( 'A', NSIZE, NRHS, B( ST, 1 ), LDB,
! 468: $ WORK( BX+ST1 ), N )
! 469: ELSE
! 470: *
! 471: * A large problem. Solve it using divide and conquer.
! 472: *
! 473: CALL DLASDA( ICMPQ1, SMLSIZ, NSIZE, SQRE, D( ST ),
! 474: $ E( ST ), RWORK( U+ST1 ), N, RWORK( VT+ST1 ),
! 475: $ IWORK( K+ST1 ), RWORK( DIFL+ST1 ),
! 476: $ RWORK( DIFR+ST1 ), RWORK( Z+ST1 ),
! 477: $ RWORK( POLES+ST1 ), IWORK( GIVPTR+ST1 ),
! 478: $ IWORK( GIVCOL+ST1 ), N, IWORK( PERM+ST1 ),
! 479: $ RWORK( GIVNUM+ST1 ), RWORK( C+ST1 ),
! 480: $ RWORK( S+ST1 ), RWORK( NRWORK ),
! 481: $ IWORK( IWK ), INFO )
! 482: IF( INFO.NE.0 ) THEN
! 483: RETURN
! 484: END IF
! 485: BXST = BX + ST1
! 486: CALL ZLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, B( ST, 1 ),
! 487: $ LDB, WORK( BXST ), N, RWORK( U+ST1 ), N,
! 488: $ RWORK( VT+ST1 ), IWORK( K+ST1 ),
! 489: $ RWORK( DIFL+ST1 ), RWORK( DIFR+ST1 ),
! 490: $ RWORK( Z+ST1 ), RWORK( POLES+ST1 ),
! 491: $ IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
! 492: $ IWORK( PERM+ST1 ), RWORK( GIVNUM+ST1 ),
! 493: $ RWORK( C+ST1 ), RWORK( S+ST1 ),
! 494: $ RWORK( NRWORK ), IWORK( IWK ), INFO )
! 495: IF( INFO.NE.0 ) THEN
! 496: RETURN
! 497: END IF
! 498: END IF
! 499: ST = I + 1
! 500: END IF
! 501: 240 CONTINUE
! 502: *
! 503: * Apply the singular values and treat the tiny ones as zero.
! 504: *
! 505: TOL = RCND*ABS( D( IDAMAX( N, D, 1 ) ) )
! 506: *
! 507: DO 250 I = 1, N
! 508: *
! 509: * Some of the elements in D can be negative because 1-by-1
! 510: * subproblems were not solved explicitly.
! 511: *
! 512: IF( ABS( D( I ) ).LE.TOL ) THEN
! 513: CALL ZLASET( 'A', 1, NRHS, CZERO, CZERO, WORK( BX+I-1 ), N )
! 514: ELSE
! 515: RANK = RANK + 1
! 516: CALL ZLASCL( 'G', 0, 0, D( I ), ONE, 1, NRHS,
! 517: $ WORK( BX+I-1 ), N, INFO )
! 518: END IF
! 519: D( I ) = ABS( D( I ) )
! 520: 250 CONTINUE
! 521: *
! 522: * Now apply back the right singular vectors.
! 523: *
! 524: ICMPQ2 = 1
! 525: DO 320 I = 1, NSUB
! 526: ST = IWORK( I )
! 527: ST1 = ST - 1
! 528: NSIZE = IWORK( SIZEI+I-1 )
! 529: BXST = BX + ST1
! 530: IF( NSIZE.EQ.1 ) THEN
! 531: CALL ZCOPY( NRHS, WORK( BXST ), N, B( ST, 1 ), LDB )
! 532: ELSE IF( NSIZE.LE.SMLSIZ ) THEN
! 533: *
! 534: * Since B and BX are complex, the following call to DGEMM
! 535: * is performed in two steps (real and imaginary parts).
! 536: *
! 537: * CALL DGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
! 538: * $ RWORK( VT+ST1 ), N, RWORK( BXST ), N, ZERO,
! 539: * $ B( ST, 1 ), LDB )
! 540: *
! 541: J = BXST - N - 1
! 542: JREAL = IRWB - 1
! 543: DO 270 JCOL = 1, NRHS
! 544: J = J + N
! 545: DO 260 JROW = 1, NSIZE
! 546: JREAL = JREAL + 1
! 547: RWORK( JREAL ) = DBLE( WORK( J+JROW ) )
! 548: 260 CONTINUE
! 549: 270 CONTINUE
! 550: CALL DGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
! 551: $ RWORK( VT+ST1 ), N, RWORK( IRWB ), NSIZE, ZERO,
! 552: $ RWORK( IRWRB ), NSIZE )
! 553: J = BXST - N - 1
! 554: JIMAG = IRWB - 1
! 555: DO 290 JCOL = 1, NRHS
! 556: J = J + N
! 557: DO 280 JROW = 1, NSIZE
! 558: JIMAG = JIMAG + 1
! 559: RWORK( JIMAG ) = DIMAG( WORK( J+JROW ) )
! 560: 280 CONTINUE
! 561: 290 CONTINUE
! 562: CALL DGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
! 563: $ RWORK( VT+ST1 ), N, RWORK( IRWB ), NSIZE, ZERO,
! 564: $ RWORK( IRWIB ), NSIZE )
! 565: JREAL = IRWRB - 1
! 566: JIMAG = IRWIB - 1
! 567: DO 310 JCOL = 1, NRHS
! 568: DO 300 JROW = ST, ST + NSIZE - 1
! 569: JREAL = JREAL + 1
! 570: JIMAG = JIMAG + 1
! 571: B( JROW, JCOL ) = DCMPLX( RWORK( JREAL ),
! 572: $ RWORK( JIMAG ) )
! 573: 300 CONTINUE
! 574: 310 CONTINUE
! 575: ELSE
! 576: CALL ZLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, WORK( BXST ), N,
! 577: $ B( ST, 1 ), LDB, RWORK( U+ST1 ), N,
! 578: $ RWORK( VT+ST1 ), IWORK( K+ST1 ),
! 579: $ RWORK( DIFL+ST1 ), RWORK( DIFR+ST1 ),
! 580: $ RWORK( Z+ST1 ), RWORK( POLES+ST1 ),
! 581: $ IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
! 582: $ IWORK( PERM+ST1 ), RWORK( GIVNUM+ST1 ),
! 583: $ RWORK( C+ST1 ), RWORK( S+ST1 ),
! 584: $ RWORK( NRWORK ), IWORK( IWK ), INFO )
! 585: IF( INFO.NE.0 ) THEN
! 586: RETURN
! 587: END IF
! 588: END IF
! 589: 320 CONTINUE
! 590: *
! 591: * Unscale and sort the singular values.
! 592: *
! 593: CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
! 594: CALL DLASRT( 'D', N, D, INFO )
! 595: CALL ZLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
! 596: *
! 597: RETURN
! 598: *
! 599: * End of ZLALSD
! 600: *
! 601: END
CVSweb interface <joel.bertrand@systella.fr>