File:  [local] / rpl / lapack / lapack / zlalsd.f
Revision 1.21: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:39:29 2023 UTC (9 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, rpl-4_1_34, HEAD
Première mise à jour de lapack et blas.

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

CVSweb interface <joel.bertrand@systella.fr>