File:  [local] / rpl / lapack / lapack / dlals0.f
Revision 1.19: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:38:54 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 DLALS0 applies back multiplying factors in solving the least squares problem using divide and conquer SVD approach. Used by sgelsd.
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download DLALS0 + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlals0.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlals0.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlals0.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DLALS0( ICOMPQ, NL, NR, SQRE, NRHS, B, LDB, BX, LDBX,
   22: *                          PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM,
   23: *                          POLES, DIFL, DIFR, Z, K, C, S, WORK, INFO )
   24: *
   25: *       .. Scalar Arguments ..
   26: *       INTEGER            GIVPTR, ICOMPQ, INFO, K, LDB, LDBX, LDGCOL,
   27: *      $                   LDGNUM, NL, NR, NRHS, SQRE
   28: *       DOUBLE PRECISION   C, S
   29: *       ..
   30: *       .. Array Arguments ..
   31: *       INTEGER            GIVCOL( LDGCOL, * ), PERM( * )
   32: *       DOUBLE PRECISION   B( LDB, * ), BX( LDBX, * ), DIFL( * ),
   33: *      $                   DIFR( LDGNUM, * ), GIVNUM( LDGNUM, * ),
   34: *      $                   POLES( LDGNUM, * ), WORK( * ), Z( * )
   35: *       ..
   36: *
   37: *
   38: *> \par Purpose:
   39: *  =============
   40: *>
   41: *> \verbatim
   42: *>
   43: *> DLALS0 applies back the multiplying factors of either the left or the
   44: *> right singular vector matrix of a diagonal matrix appended by a row
   45: *> to the right hand side matrix B in solving the least squares problem
   46: *> using the divide-and-conquer SVD approach.
   47: *>
   48: *> For the left singular vector matrix, three types of orthogonal
   49: *> matrices are involved:
   50: *>
   51: *> (1L) Givens rotations: the number of such rotations is GIVPTR; the
   52: *>      pairs of columns/rows they were applied to are stored in GIVCOL;
   53: *>      and the C- and S-values of these rotations are stored in GIVNUM.
   54: *>
   55: *> (2L) Permutation. The (NL+1)-st row of B is to be moved to the first
   56: *>      row, and for J=2:N, PERM(J)-th row of B is to be moved to the
   57: *>      J-th row.
   58: *>
   59: *> (3L) The left singular vector matrix of the remaining matrix.
   60: *>
   61: *> For the right singular vector matrix, four types of orthogonal
   62: *> matrices are involved:
   63: *>
   64: *> (1R) The right singular vector matrix of the remaining matrix.
   65: *>
   66: *> (2R) If SQRE = 1, one extra Givens rotation to generate the right
   67: *>      null space.
   68: *>
   69: *> (3R) The inverse transformation of (2L).
   70: *>
   71: *> (4R) The inverse transformation of (1L).
   72: *> \endverbatim
   73: *
   74: *  Arguments:
   75: *  ==========
   76: *
   77: *> \param[in] ICOMPQ
   78: *> \verbatim
   79: *>          ICOMPQ is INTEGER
   80: *>         Specifies whether singular vectors are to be computed in
   81: *>         factored form:
   82: *>         = 0: Left singular vector matrix.
   83: *>         = 1: Right singular vector matrix.
   84: *> \endverbatim
   85: *>
   86: *> \param[in] NL
   87: *> \verbatim
   88: *>          NL is INTEGER
   89: *>         The row dimension of the upper block. NL >= 1.
   90: *> \endverbatim
   91: *>
   92: *> \param[in] NR
   93: *> \verbatim
   94: *>          NR is INTEGER
   95: *>         The row dimension of the lower block. NR >= 1.
   96: *> \endverbatim
   97: *>
   98: *> \param[in] SQRE
   99: *> \verbatim
  100: *>          SQRE is INTEGER
  101: *>         = 0: the lower block is an NR-by-NR square matrix.
  102: *>         = 1: the lower block is an NR-by-(NR+1) rectangular matrix.
  103: *>
  104: *>         The bidiagonal matrix has row dimension N = NL + NR + 1,
  105: *>         and column dimension M = N + SQRE.
  106: *> \endverbatim
  107: *>
  108: *> \param[in] NRHS
  109: *> \verbatim
  110: *>          NRHS is INTEGER
  111: *>         The number of columns of B and BX. NRHS must be at least 1.
  112: *> \endverbatim
  113: *>
  114: *> \param[in,out] B
  115: *> \verbatim
  116: *>          B is DOUBLE PRECISION array, dimension ( LDB, NRHS )
  117: *>         On input, B contains the right hand sides of the least
  118: *>         squares problem in rows 1 through M. On output, B contains
  119: *>         the solution X in rows 1 through N.
  120: *> \endverbatim
  121: *>
  122: *> \param[in] LDB
  123: *> \verbatim
  124: *>          LDB is INTEGER
  125: *>         The leading dimension of B. LDB must be at least
  126: *>         max(1,MAX( M, N ) ).
  127: *> \endverbatim
  128: *>
  129: *> \param[out] BX
  130: *> \verbatim
  131: *>          BX is DOUBLE PRECISION array, dimension ( LDBX, NRHS )
  132: *> \endverbatim
  133: *>
  134: *> \param[in] LDBX
  135: *> \verbatim
  136: *>          LDBX is INTEGER
  137: *>         The leading dimension of BX.
  138: *> \endverbatim
  139: *>
  140: *> \param[in] PERM
  141: *> \verbatim
  142: *>          PERM is INTEGER array, dimension ( N )
  143: *>         The permutations (from deflation and sorting) applied
  144: *>         to the two blocks.
  145: *> \endverbatim
  146: *>
  147: *> \param[in] GIVPTR
  148: *> \verbatim
  149: *>          GIVPTR is INTEGER
  150: *>         The number of Givens rotations which took place in this
  151: *>         subproblem.
  152: *> \endverbatim
  153: *>
  154: *> \param[in] GIVCOL
  155: *> \verbatim
  156: *>          GIVCOL is INTEGER array, dimension ( LDGCOL, 2 )
  157: *>         Each pair of numbers indicates a pair of rows/columns
  158: *>         involved in a Givens rotation.
  159: *> \endverbatim
  160: *>
  161: *> \param[in] LDGCOL
  162: *> \verbatim
  163: *>          LDGCOL is INTEGER
  164: *>         The leading dimension of GIVCOL, must be at least N.
  165: *> \endverbatim
  166: *>
  167: *> \param[in] GIVNUM
  168: *> \verbatim
  169: *>          GIVNUM is DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
  170: *>         Each number indicates the C or S value used in the
  171: *>         corresponding Givens rotation.
  172: *> \endverbatim
  173: *>
  174: *> \param[in] LDGNUM
  175: *> \verbatim
  176: *>          LDGNUM is INTEGER
  177: *>         The leading dimension of arrays DIFR, POLES and
  178: *>         GIVNUM, must be at least K.
  179: *> \endverbatim
  180: *>
  181: *> \param[in] POLES
  182: *> \verbatim
  183: *>          POLES is DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
  184: *>         On entry, POLES(1:K, 1) contains the new singular
  185: *>         values obtained from solving the secular equation, and
  186: *>         POLES(1:K, 2) is an array containing the poles in the secular
  187: *>         equation.
  188: *> \endverbatim
  189: *>
  190: *> \param[in] DIFL
  191: *> \verbatim
  192: *>          DIFL is DOUBLE PRECISION array, dimension ( K ).
  193: *>         On entry, DIFL(I) is the distance between I-th updated
  194: *>         (undeflated) singular value and the I-th (undeflated) old
  195: *>         singular value.
  196: *> \endverbatim
  197: *>
  198: *> \param[in] DIFR
  199: *> \verbatim
  200: *>          DIFR is DOUBLE PRECISION array, dimension ( LDGNUM, 2 ).
  201: *>         On entry, DIFR(I, 1) contains the distances between I-th
  202: *>         updated (undeflated) singular value and the I+1-th
  203: *>         (undeflated) old singular value. And DIFR(I, 2) is the
  204: *>         normalizing factor for the I-th right singular vector.
  205: *> \endverbatim
  206: *>
  207: *> \param[in] Z
  208: *> \verbatim
  209: *>          Z is DOUBLE PRECISION array, dimension ( K )
  210: *>         Contain the components of the deflation-adjusted updating row
  211: *>         vector.
  212: *> \endverbatim
  213: *>
  214: *> \param[in] K
  215: *> \verbatim
  216: *>          K is INTEGER
  217: *>         Contains the dimension of the non-deflated matrix,
  218: *>         This is the order of the related secular equation. 1 <= K <=N.
  219: *> \endverbatim
  220: *>
  221: *> \param[in] C
  222: *> \verbatim
  223: *>          C is DOUBLE PRECISION
  224: *>         C contains garbage if SQRE =0 and the C-value of a Givens
  225: *>         rotation related to the right null space if SQRE = 1.
  226: *> \endverbatim
  227: *>
  228: *> \param[in] S
  229: *> \verbatim
  230: *>          S is DOUBLE PRECISION
  231: *>         S contains garbage if SQRE =0 and the S-value of a Givens
  232: *>         rotation related to the right null space if SQRE = 1.
  233: *> \endverbatim
  234: *>
  235: *> \param[out] WORK
  236: *> \verbatim
  237: *>          WORK is DOUBLE PRECISION array, dimension ( K )
  238: *> \endverbatim
  239: *>
  240: *> \param[out] INFO
  241: *> \verbatim
  242: *>          INFO is INTEGER
  243: *>          = 0:  successful exit.
  244: *>          < 0:  if INFO = -i, the i-th argument had an illegal value.
  245: *> \endverbatim
  246: *
  247: *  Authors:
  248: *  ========
  249: *
  250: *> \author Univ. of Tennessee
  251: *> \author Univ. of California Berkeley
  252: *> \author Univ. of Colorado Denver
  253: *> \author NAG Ltd.
  254: *
  255: *> \ingroup doubleOTHERcomputational
  256: *
  257: *> \par Contributors:
  258: *  ==================
  259: *>
  260: *>     Ming Gu and Ren-Cang Li, Computer Science Division, University of
  261: *>       California at Berkeley, USA \n
  262: *>     Osni Marques, LBNL/NERSC, USA \n
  263: *
  264: *  =====================================================================
  265:       SUBROUTINE DLALS0( ICOMPQ, NL, NR, SQRE, NRHS, B, LDB, BX, LDBX,
  266:      $                   PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM,
  267:      $                   POLES, DIFL, DIFR, Z, K, C, S, WORK, INFO )
  268: *
  269: *  -- LAPACK computational routine --
  270: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  271: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  272: *
  273: *     .. Scalar Arguments ..
  274:       INTEGER            GIVPTR, ICOMPQ, INFO, K, LDB, LDBX, LDGCOL,
  275:      $                   LDGNUM, NL, NR, NRHS, SQRE
  276:       DOUBLE PRECISION   C, S
  277: *     ..
  278: *     .. Array Arguments ..
  279:       INTEGER            GIVCOL( LDGCOL, * ), PERM( * )
  280:       DOUBLE PRECISION   B( LDB, * ), BX( LDBX, * ), DIFL( * ),
  281:      $                   DIFR( LDGNUM, * ), GIVNUM( LDGNUM, * ),
  282:      $                   POLES( LDGNUM, * ), WORK( * ), Z( * )
  283: *     ..
  284: *
  285: *  =====================================================================
  286: *
  287: *     .. Parameters ..
  288:       DOUBLE PRECISION   ONE, ZERO, NEGONE
  289:       PARAMETER          ( ONE = 1.0D0, ZERO = 0.0D0, NEGONE = -1.0D0 )
  290: *     ..
  291: *     .. Local Scalars ..
  292:       INTEGER            I, J, M, N, NLP1
  293:       DOUBLE PRECISION   DIFLJ, DIFRJ, DJ, DSIGJ, DSIGJP, TEMP
  294: *     ..
  295: *     .. External Subroutines ..
  296:       EXTERNAL           DCOPY, DGEMV, DLACPY, DLASCL, DROT, DSCAL,
  297:      $                   XERBLA
  298: *     ..
  299: *     .. External Functions ..
  300:       DOUBLE PRECISION   DLAMC3, DNRM2
  301:       EXTERNAL           DLAMC3, DNRM2
  302: *     ..
  303: *     .. Intrinsic Functions ..
  304:       INTRINSIC          MAX
  305: *     ..
  306: *     .. Executable Statements ..
  307: *
  308: *     Test the input parameters.
  309: *
  310:       INFO = 0
  311:       N = NL + NR + 1
  312: *
  313:       IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THEN
  314:          INFO = -1
  315:       ELSE IF( NL.LT.1 ) THEN
  316:          INFO = -2
  317:       ELSE IF( NR.LT.1 ) THEN
  318:          INFO = -3
  319:       ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THEN
  320:          INFO = -4
  321:       ELSE IF( NRHS.LT.1 ) THEN
  322:          INFO = -5
  323:       ELSE IF( LDB.LT.N ) THEN
  324:          INFO = -7
  325:       ELSE IF( LDBX.LT.N ) THEN
  326:          INFO = -9
  327:       ELSE IF( GIVPTR.LT.0 ) THEN
  328:          INFO = -11
  329:       ELSE IF( LDGCOL.LT.N ) THEN
  330:          INFO = -13
  331:       ELSE IF( LDGNUM.LT.N ) THEN
  332:          INFO = -15
  333:       ELSE IF( K.LT.1 ) THEN
  334:          INFO = -20
  335:       END IF
  336:       IF( INFO.NE.0 ) THEN
  337:          CALL XERBLA( 'DLALS0', -INFO )
  338:          RETURN
  339:       END IF
  340: *
  341:       M = N + SQRE
  342:       NLP1 = NL + 1
  343: *
  344:       IF( ICOMPQ.EQ.0 ) THEN
  345: *
  346: *        Apply back orthogonal transformations from the left.
  347: *
  348: *        Step (1L): apply back the Givens rotations performed.
  349: *
  350:          DO 10 I = 1, GIVPTR
  351:             CALL DROT( NRHS, B( GIVCOL( I, 2 ), 1 ), LDB,
  352:      $                 B( GIVCOL( I, 1 ), 1 ), LDB, GIVNUM( I, 2 ),
  353:      $                 GIVNUM( I, 1 ) )
  354:    10    CONTINUE
  355: *
  356: *        Step (2L): permute rows of B.
  357: *
  358:          CALL DCOPY( NRHS, B( NLP1, 1 ), LDB, BX( 1, 1 ), LDBX )
  359:          DO 20 I = 2, N
  360:             CALL DCOPY( NRHS, B( PERM( I ), 1 ), LDB, BX( I, 1 ), LDBX )
  361:    20    CONTINUE
  362: *
  363: *        Step (3L): apply the inverse of the left singular vector
  364: *        matrix to BX.
  365: *
  366:          IF( K.EQ.1 ) THEN
  367:             CALL DCOPY( NRHS, BX, LDBX, B, LDB )
  368:             IF( Z( 1 ).LT.ZERO ) THEN
  369:                CALL DSCAL( NRHS, NEGONE, B, LDB )
  370:             END IF
  371:          ELSE
  372:             DO 50 J = 1, K
  373:                DIFLJ = DIFL( J )
  374:                DJ = POLES( J, 1 )
  375:                DSIGJ = -POLES( J, 2 )
  376:                IF( J.LT.K ) THEN
  377:                   DIFRJ = -DIFR( J, 1 )
  378:                   DSIGJP = -POLES( J+1, 2 )
  379:                END IF
  380:                IF( ( Z( J ).EQ.ZERO ) .OR. ( POLES( J, 2 ).EQ.ZERO ) )
  381:      $              THEN
  382:                   WORK( J ) = ZERO
  383:                ELSE
  384:                   WORK( J ) = -POLES( J, 2 )*Z( J ) / DIFLJ /
  385:      $                        ( POLES( J, 2 )+DJ )
  386:                END IF
  387:                DO 30 I = 1, J - 1
  388:                   IF( ( Z( I ).EQ.ZERO ) .OR.
  389:      $                ( POLES( I, 2 ).EQ.ZERO ) ) THEN
  390:                      WORK( I ) = ZERO
  391:                   ELSE
  392:                      WORK( I ) = POLES( I, 2 )*Z( I ) /
  393:      $                           ( DLAMC3( POLES( I, 2 ), DSIGJ )-
  394:      $                           DIFLJ ) / ( POLES( I, 2 )+DJ )
  395:                   END IF
  396:    30          CONTINUE
  397:                DO 40 I = J + 1, K
  398:                   IF( ( Z( I ).EQ.ZERO ) .OR.
  399:      $                ( POLES( I, 2 ).EQ.ZERO ) ) THEN
  400:                      WORK( I ) = ZERO
  401:                   ELSE
  402:                      WORK( I ) = POLES( I, 2 )*Z( I ) /
  403:      $                           ( DLAMC3( POLES( I, 2 ), DSIGJP )+
  404:      $                           DIFRJ ) / ( POLES( I, 2 )+DJ )
  405:                   END IF
  406:    40          CONTINUE
  407:                WORK( 1 ) = NEGONE
  408:                TEMP = DNRM2( K, WORK, 1 )
  409:                CALL DGEMV( 'T', K, NRHS, ONE, BX, LDBX, WORK, 1, ZERO,
  410:      $                     B( J, 1 ), LDB )
  411:                CALL DLASCL( 'G', 0, 0, TEMP, ONE, 1, NRHS, B( J, 1 ),
  412:      $                      LDB, INFO )
  413:    50       CONTINUE
  414:          END IF
  415: *
  416: *        Move the deflated rows of BX to B also.
  417: *
  418:          IF( K.LT.MAX( M, N ) )
  419:      $      CALL DLACPY( 'A', N-K, NRHS, BX( K+1, 1 ), LDBX,
  420:      $                   B( K+1, 1 ), LDB )
  421:       ELSE
  422: *
  423: *        Apply back the right orthogonal transformations.
  424: *
  425: *        Step (1R): apply back the new right singular vector matrix
  426: *        to B.
  427: *
  428:          IF( K.EQ.1 ) THEN
  429:             CALL DCOPY( NRHS, B, LDB, BX, LDBX )
  430:          ELSE
  431:             DO 80 J = 1, K
  432:                DSIGJ = POLES( J, 2 )
  433:                IF( Z( J ).EQ.ZERO ) THEN
  434:                   WORK( J ) = ZERO
  435:                ELSE
  436:                   WORK( J ) = -Z( J ) / DIFL( J ) /
  437:      $                        ( DSIGJ+POLES( J, 1 ) ) / DIFR( J, 2 )
  438:                END IF
  439:                DO 60 I = 1, J - 1
  440:                   IF( Z( J ).EQ.ZERO ) THEN
  441:                      WORK( I ) = ZERO
  442:                   ELSE
  443:                      WORK( I ) = Z( J ) / ( DLAMC3( DSIGJ, -POLES( I+1,
  444:      $                           2 ) )-DIFR( I, 1 ) ) /
  445:      $                           ( DSIGJ+POLES( I, 1 ) ) / DIFR( I, 2 )
  446:                   END IF
  447:    60          CONTINUE
  448:                DO 70 I = J + 1, K
  449:                   IF( Z( J ).EQ.ZERO ) THEN
  450:                      WORK( I ) = ZERO
  451:                   ELSE
  452:                      WORK( I ) = Z( J ) / ( DLAMC3( DSIGJ, -POLES( I,
  453:      $                           2 ) )-DIFL( I ) ) /
  454:      $                           ( DSIGJ+POLES( I, 1 ) ) / DIFR( I, 2 )
  455:                   END IF
  456:    70          CONTINUE
  457:                CALL DGEMV( 'T', K, NRHS, ONE, B, LDB, WORK, 1, ZERO,
  458:      $                     BX( J, 1 ), LDBX )
  459:    80       CONTINUE
  460:          END IF
  461: *
  462: *        Step (2R): if SQRE = 1, apply back the rotation that is
  463: *        related to the right null space of the subproblem.
  464: *
  465:          IF( SQRE.EQ.1 ) THEN
  466:             CALL DCOPY( NRHS, B( M, 1 ), LDB, BX( M, 1 ), LDBX )
  467:             CALL DROT( NRHS, BX( 1, 1 ), LDBX, BX( M, 1 ), LDBX, C, S )
  468:          END IF
  469:          IF( K.LT.MAX( M, N ) )
  470:      $      CALL DLACPY( 'A', N-K, NRHS, B( K+1, 1 ), LDB, BX( K+1, 1 ),
  471:      $                   LDBX )
  472: *
  473: *        Step (3R): permute rows of B.
  474: *
  475:          CALL DCOPY( NRHS, BX( 1, 1 ), LDBX, B( NLP1, 1 ), LDB )
  476:          IF( SQRE.EQ.1 ) THEN
  477:             CALL DCOPY( NRHS, BX( M, 1 ), LDBX, B( M, 1 ), LDB )
  478:          END IF
  479:          DO 90 I = 2, N
  480:             CALL DCOPY( NRHS, BX( I, 1 ), LDBX, B( PERM( I ), 1 ), LDB )
  481:    90    CONTINUE
  482: *
  483: *        Step (4R): apply back the Givens rotations performed.
  484: *
  485:          DO 100 I = GIVPTR, 1, -1
  486:             CALL DROT( NRHS, B( GIVCOL( I, 2 ), 1 ), LDB,
  487:      $                 B( GIVCOL( I, 1 ), 1 ), LDB, GIVNUM( I, 2 ),
  488:      $                 -GIVNUM( I, 1 ) )
  489:   100    CONTINUE
  490:       END IF
  491: *
  492:       RETURN
  493: *
  494: *     End of DLALS0
  495: *
  496:       END

CVSweb interface <joel.bertrand@systella.fr>