File:  [local] / rpl / lapack / lapack / dlasdq.f
Revision 1.20: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:38:59 2023 UTC (8 months, 3 weeks 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 DLASDQ computes the SVD of a real bidiagonal matrix with diagonal d and off-diagonal e. Used by sbdsdc.
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download DLASDQ + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlasdq.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlasdq.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlasdq.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DLASDQ( UPLO, SQRE, N, NCVT, NRU, NCC, D, E, VT, LDVT,
   22: *                          U, LDU, C, LDC, WORK, INFO )
   23: *
   24: *       .. Scalar Arguments ..
   25: *       CHARACTER          UPLO
   26: *       INTEGER            INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU, SQRE
   27: *       ..
   28: *       .. Array Arguments ..
   29: *       DOUBLE PRECISION   C( LDC, * ), D( * ), E( * ), U( LDU, * ),
   30: *      $                   VT( LDVT, * ), WORK( * )
   31: *       ..
   32: *
   33: *
   34: *> \par Purpose:
   35: *  =============
   36: *>
   37: *> \verbatim
   38: *>
   39: *> DLASDQ computes the singular value decomposition (SVD) of a real
   40: *> (upper or lower) bidiagonal matrix with diagonal D and offdiagonal
   41: *> E, accumulating the transformations if desired. Letting B denote
   42: *> the input bidiagonal matrix, the algorithm computes orthogonal
   43: *> matrices Q and P such that B = Q * S * P**T (P**T denotes the transpose
   44: *> of P). The singular values S are overwritten on D.
   45: *>
   46: *> The input matrix U  is changed to U  * Q  if desired.
   47: *> The input matrix VT is changed to P**T * VT if desired.
   48: *> The input matrix C  is changed to Q**T * C  if desired.
   49: *>
   50: *> See "Computing  Small Singular Values of Bidiagonal Matrices With
   51: *> Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,
   52: *> LAPACK Working Note #3, for a detailed description of the algorithm.
   53: *> \endverbatim
   54: *
   55: *  Arguments:
   56: *  ==========
   57: *
   58: *> \param[in] UPLO
   59: *> \verbatim
   60: *>          UPLO is CHARACTER*1
   61: *>        On entry, UPLO specifies whether the input bidiagonal matrix
   62: *>        is upper or lower bidiagonal, and whether it is square are
   63: *>        not.
   64: *>           UPLO = 'U' or 'u'   B is upper bidiagonal.
   65: *>           UPLO = 'L' or 'l'   B is lower bidiagonal.
   66: *> \endverbatim
   67: *>
   68: *> \param[in] SQRE
   69: *> \verbatim
   70: *>          SQRE is INTEGER
   71: *>        = 0: then the input matrix is N-by-N.
   72: *>        = 1: then the input matrix is N-by-(N+1) if UPLU = 'U' and
   73: *>             (N+1)-by-N if UPLU = 'L'.
   74: *>
   75: *>        The bidiagonal matrix has
   76: *>        N = NL + NR + 1 rows and
   77: *>        M = N + SQRE >= N columns.
   78: *> \endverbatim
   79: *>
   80: *> \param[in] N
   81: *> \verbatim
   82: *>          N is INTEGER
   83: *>        On entry, N specifies the number of rows and columns
   84: *>        in the matrix. N must be at least 0.
   85: *> \endverbatim
   86: *>
   87: *> \param[in] NCVT
   88: *> \verbatim
   89: *>          NCVT is INTEGER
   90: *>        On entry, NCVT specifies the number of columns of
   91: *>        the matrix VT. NCVT must be at least 0.
   92: *> \endverbatim
   93: *>
   94: *> \param[in] NRU
   95: *> \verbatim
   96: *>          NRU is INTEGER
   97: *>        On entry, NRU specifies the number of rows of
   98: *>        the matrix U. NRU must be at least 0.
   99: *> \endverbatim
  100: *>
  101: *> \param[in] NCC
  102: *> \verbatim
  103: *>          NCC is INTEGER
  104: *>        On entry, NCC specifies the number of columns of
  105: *>        the matrix C. NCC must be at least 0.
  106: *> \endverbatim
  107: *>
  108: *> \param[in,out] D
  109: *> \verbatim
  110: *>          D is DOUBLE PRECISION array, dimension (N)
  111: *>        On entry, D contains the diagonal entries of the
  112: *>        bidiagonal matrix whose SVD is desired. On normal exit,
  113: *>        D contains the singular values in ascending order.
  114: *> \endverbatim
  115: *>
  116: *> \param[in,out] E
  117: *> \verbatim
  118: *>          E is DOUBLE PRECISION array.
  119: *>        dimension is (N-1) if SQRE = 0 and N if SQRE = 1.
  120: *>        On entry, the entries of E contain the offdiagonal entries
  121: *>        of the bidiagonal matrix whose SVD is desired. On normal
  122: *>        exit, E will contain 0. If the algorithm does not converge,
  123: *>        D and E will contain the diagonal and superdiagonal entries
  124: *>        of a bidiagonal matrix orthogonally equivalent to the one
  125: *>        given as input.
  126: *> \endverbatim
  127: *>
  128: *> \param[in,out] VT
  129: *> \verbatim
  130: *>          VT is DOUBLE PRECISION array, dimension (LDVT, NCVT)
  131: *>        On entry, contains a matrix which on exit has been
  132: *>        premultiplied by P**T, dimension N-by-NCVT if SQRE = 0
  133: *>        and (N+1)-by-NCVT if SQRE = 1 (not referenced if NCVT=0).
  134: *> \endverbatim
  135: *>
  136: *> \param[in] LDVT
  137: *> \verbatim
  138: *>          LDVT is INTEGER
  139: *>        On entry, LDVT specifies the leading dimension of VT as
  140: *>        declared in the calling (sub) program. LDVT must be at
  141: *>        least 1. If NCVT is nonzero LDVT must also be at least N.
  142: *> \endverbatim
  143: *>
  144: *> \param[in,out] U
  145: *> \verbatim
  146: *>          U is DOUBLE PRECISION array, dimension (LDU, N)
  147: *>        On entry, contains a  matrix which on exit has been
  148: *>        postmultiplied by Q, dimension NRU-by-N if SQRE = 0
  149: *>        and NRU-by-(N+1) if SQRE = 1 (not referenced if NRU=0).
  150: *> \endverbatim
  151: *>
  152: *> \param[in] LDU
  153: *> \verbatim
  154: *>          LDU is INTEGER
  155: *>        On entry, LDU  specifies the leading dimension of U as
  156: *>        declared in the calling (sub) program. LDU must be at
  157: *>        least max( 1, NRU ) .
  158: *> \endverbatim
  159: *>
  160: *> \param[in,out] C
  161: *> \verbatim
  162: *>          C is DOUBLE PRECISION array, dimension (LDC, NCC)
  163: *>        On entry, contains an N-by-NCC matrix which on exit
  164: *>        has been premultiplied by Q**T  dimension N-by-NCC if SQRE = 0
  165: *>        and (N+1)-by-NCC if SQRE = 1 (not referenced if NCC=0).
  166: *> \endverbatim
  167: *>
  168: *> \param[in] LDC
  169: *> \verbatim
  170: *>          LDC is INTEGER
  171: *>        On entry, LDC  specifies the leading dimension of C as
  172: *>        declared in the calling (sub) program. LDC must be at
  173: *>        least 1. If NCC is nonzero, LDC must also be at least N.
  174: *> \endverbatim
  175: *>
  176: *> \param[out] WORK
  177: *> \verbatim
  178: *>          WORK is DOUBLE PRECISION array, dimension (4*N)
  179: *>        Workspace. Only referenced if one of NCVT, NRU, or NCC is
  180: *>        nonzero, and if N is at least 2.
  181: *> \endverbatim
  182: *>
  183: *> \param[out] INFO
  184: *> \verbatim
  185: *>          INFO is INTEGER
  186: *>        On exit, a value of 0 indicates a successful exit.
  187: *>        If INFO < 0, argument number -INFO is illegal.
  188: *>        If INFO > 0, the algorithm did not converge, and INFO
  189: *>        specifies how many superdiagonals did not converge.
  190: *> \endverbatim
  191: *
  192: *  Authors:
  193: *  ========
  194: *
  195: *> \author Univ. of Tennessee
  196: *> \author Univ. of California Berkeley
  197: *> \author Univ. of Colorado Denver
  198: *> \author NAG Ltd.
  199: *
  200: *> \ingroup OTHERauxiliary
  201: *
  202: *> \par Contributors:
  203: *  ==================
  204: *>
  205: *>     Ming Gu and Huan Ren, Computer Science Division, University of
  206: *>     California at Berkeley, USA
  207: *>
  208: *  =====================================================================
  209:       SUBROUTINE DLASDQ( UPLO, SQRE, N, NCVT, NRU, NCC, D, E, VT, LDVT,
  210:      $                   U, LDU, C, LDC, WORK, INFO )
  211: *
  212: *  -- LAPACK auxiliary routine --
  213: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  214: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  215: *
  216: *     .. Scalar Arguments ..
  217:       CHARACTER          UPLO
  218:       INTEGER            INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU, SQRE
  219: *     ..
  220: *     .. Array Arguments ..
  221:       DOUBLE PRECISION   C( LDC, * ), D( * ), E( * ), U( LDU, * ),
  222:      $                   VT( LDVT, * ), WORK( * )
  223: *     ..
  224: *
  225: *  =====================================================================
  226: *
  227: *     .. Parameters ..
  228:       DOUBLE PRECISION   ZERO
  229:       PARAMETER          ( ZERO = 0.0D+0 )
  230: *     ..
  231: *     .. Local Scalars ..
  232:       LOGICAL            ROTATE
  233:       INTEGER            I, ISUB, IUPLO, J, NP1, SQRE1
  234:       DOUBLE PRECISION   CS, R, SMIN, SN
  235: *     ..
  236: *     .. External Subroutines ..
  237:       EXTERNAL           DBDSQR, DLARTG, DLASR, DSWAP, XERBLA
  238: *     ..
  239: *     .. External Functions ..
  240:       LOGICAL            LSAME
  241:       EXTERNAL           LSAME
  242: *     ..
  243: *     .. Intrinsic Functions ..
  244:       INTRINSIC          MAX
  245: *     ..
  246: *     .. Executable Statements ..
  247: *
  248: *     Test the input parameters.
  249: *
  250:       INFO = 0
  251:       IUPLO = 0
  252:       IF( LSAME( UPLO, 'U' ) )
  253:      $   IUPLO = 1
  254:       IF( LSAME( UPLO, 'L' ) )
  255:      $   IUPLO = 2
  256:       IF( IUPLO.EQ.0 ) THEN
  257:          INFO = -1
  258:       ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THEN
  259:          INFO = -2
  260:       ELSE IF( N.LT.0 ) THEN
  261:          INFO = -3
  262:       ELSE IF( NCVT.LT.0 ) THEN
  263:          INFO = -4
  264:       ELSE IF( NRU.LT.0 ) THEN
  265:          INFO = -5
  266:       ELSE IF( NCC.LT.0 ) THEN
  267:          INFO = -6
  268:       ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR.
  269:      $         ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THEN
  270:          INFO = -10
  271:       ELSE IF( LDU.LT.MAX( 1, NRU ) ) THEN
  272:          INFO = -12
  273:       ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR.
  274:      $         ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THEN
  275:          INFO = -14
  276:       END IF
  277:       IF( INFO.NE.0 ) THEN
  278:          CALL XERBLA( 'DLASDQ', -INFO )
  279:          RETURN
  280:       END IF
  281:       IF( N.EQ.0 )
  282:      $   RETURN
  283: *
  284: *     ROTATE is true if any singular vectors desired, false otherwise
  285: *
  286:       ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 )
  287:       NP1 = N + 1
  288:       SQRE1 = SQRE
  289: *
  290: *     If matrix non-square upper bidiagonal, rotate to be lower
  291: *     bidiagonal.  The rotations are on the right.
  292: *
  293:       IF( ( IUPLO.EQ.1 ) .AND. ( SQRE1.EQ.1 ) ) THEN
  294:          DO 10 I = 1, N - 1
  295:             CALL DLARTG( D( I ), E( I ), CS, SN, R )
  296:             D( I ) = R
  297:             E( I ) = SN*D( I+1 )
  298:             D( I+1 ) = CS*D( I+1 )
  299:             IF( ROTATE ) THEN
  300:                WORK( I ) = CS
  301:                WORK( N+I ) = SN
  302:             END IF
  303:    10    CONTINUE
  304:          CALL DLARTG( D( N ), E( N ), CS, SN, R )
  305:          D( N ) = R
  306:          E( N ) = ZERO
  307:          IF( ROTATE ) THEN
  308:             WORK( N ) = CS
  309:             WORK( N+N ) = SN
  310:          END IF
  311:          IUPLO = 2
  312:          SQRE1 = 0
  313: *
  314: *        Update singular vectors if desired.
  315: *
  316:          IF( NCVT.GT.0 )
  317:      $      CALL DLASR( 'L', 'V', 'F', NP1, NCVT, WORK( 1 ),
  318:      $                  WORK( NP1 ), VT, LDVT )
  319:       END IF
  320: *
  321: *     If matrix lower bidiagonal, rotate to be upper bidiagonal
  322: *     by applying Givens rotations on the left.
  323: *
  324:       IF( IUPLO.EQ.2 ) THEN
  325:          DO 20 I = 1, N - 1
  326:             CALL DLARTG( D( I ), E( I ), CS, SN, R )
  327:             D( I ) = R
  328:             E( I ) = SN*D( I+1 )
  329:             D( I+1 ) = CS*D( I+1 )
  330:             IF( ROTATE ) THEN
  331:                WORK( I ) = CS
  332:                WORK( N+I ) = SN
  333:             END IF
  334:    20    CONTINUE
  335: *
  336: *        If matrix (N+1)-by-N lower bidiagonal, one additional
  337: *        rotation is needed.
  338: *
  339:          IF( SQRE1.EQ.1 ) THEN
  340:             CALL DLARTG( D( N ), E( N ), CS, SN, R )
  341:             D( N ) = R
  342:             IF( ROTATE ) THEN
  343:                WORK( N ) = CS
  344:                WORK( N+N ) = SN
  345:             END IF
  346:          END IF
  347: *
  348: *        Update singular vectors if desired.
  349: *
  350:          IF( NRU.GT.0 ) THEN
  351:             IF( SQRE1.EQ.0 ) THEN
  352:                CALL DLASR( 'R', 'V', 'F', NRU, N, WORK( 1 ),
  353:      $                     WORK( NP1 ), U, LDU )
  354:             ELSE
  355:                CALL DLASR( 'R', 'V', 'F', NRU, NP1, WORK( 1 ),
  356:      $                     WORK( NP1 ), U, LDU )
  357:             END IF
  358:          END IF
  359:          IF( NCC.GT.0 ) THEN
  360:             IF( SQRE1.EQ.0 ) THEN
  361:                CALL DLASR( 'L', 'V', 'F', N, NCC, WORK( 1 ),
  362:      $                     WORK( NP1 ), C, LDC )
  363:             ELSE
  364:                CALL DLASR( 'L', 'V', 'F', NP1, NCC, WORK( 1 ),
  365:      $                     WORK( NP1 ), C, LDC )
  366:             END IF
  367:          END IF
  368:       END IF
  369: *
  370: *     Call DBDSQR to compute the SVD of the reduced real
  371: *     N-by-N upper bidiagonal matrix.
  372: *
  373:       CALL DBDSQR( 'U', N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C,
  374:      $             LDC, WORK, INFO )
  375: *
  376: *     Sort the singular values into ascending order (insertion sort on
  377: *     singular values, but only one transposition per singular vector)
  378: *
  379:       DO 40 I = 1, N
  380: *
  381: *        Scan for smallest D(I).
  382: *
  383:          ISUB = I
  384:          SMIN = D( I )
  385:          DO 30 J = I + 1, N
  386:             IF( D( J ).LT.SMIN ) THEN
  387:                ISUB = J
  388:                SMIN = D( J )
  389:             END IF
  390:    30    CONTINUE
  391:          IF( ISUB.NE.I ) THEN
  392: *
  393: *           Swap singular values and vectors.
  394: *
  395:             D( ISUB ) = D( I )
  396:             D( I ) = SMIN
  397:             IF( NCVT.GT.0 )
  398:      $         CALL DSWAP( NCVT, VT( ISUB, 1 ), LDVT, VT( I, 1 ), LDVT )
  399:             IF( NRU.GT.0 )
  400:      $         CALL DSWAP( NRU, U( 1, ISUB ), 1, U( 1, I ), 1 )
  401:             IF( NCC.GT.0 )
  402:      $         CALL DSWAP( NCC, C( ISUB, 1 ), LDC, C( I, 1 ), LDC )
  403:          END IF
  404:    40 CONTINUE
  405: *
  406:       RETURN
  407: *
  408: *     End of DLASDQ
  409: *
  410:       END

CVSweb interface <joel.bertrand@systella.fr>