Annotation of rpl/lapack/lapack/dlasd6.f, revision 1.11

1.11    ! bertrand    1: *> \brief \b DLASD6
        !             2: *
        !             3: *  =========== DOCUMENTATION ===========
        !             4: *
        !             5: * Online html documentation available at 
        !             6: *            http://www.netlib.org/lapack/explore-html/ 
        !             7: *
        !             8: *> \htmlonly
        !             9: *> Download DLASD6 + dependencies 
        !            10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlasd6.f"> 
        !            11: *> [TGZ]</a> 
        !            12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlasd6.f"> 
        !            13: *> [ZIP]</a> 
        !            14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlasd6.f"> 
        !            15: *> [TXT]</a>
        !            16: *> \endhtmlonly 
        !            17: *
        !            18: *  Definition:
        !            19: *  ===========
        !            20: *
        !            21: *       SUBROUTINE DLASD6( ICOMPQ, NL, NR, SQRE, D, VF, VL, ALPHA, BETA,
        !            22: *                          IDXQ, PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM,
        !            23: *                          LDGNUM, POLES, DIFL, DIFR, Z, K, C, S, WORK,
        !            24: *                          IWORK, INFO )
        !            25: * 
        !            26: *       .. Scalar Arguments ..
        !            27: *       INTEGER            GIVPTR, ICOMPQ, INFO, K, LDGCOL, LDGNUM, NL,
        !            28: *      $                   NR, SQRE
        !            29: *       DOUBLE PRECISION   ALPHA, BETA, C, S
        !            30: *       ..
        !            31: *       .. Array Arguments ..
        !            32: *       INTEGER            GIVCOL( LDGCOL, * ), IDXQ( * ), IWORK( * ),
        !            33: *      $                   PERM( * )
        !            34: *       DOUBLE PRECISION   D( * ), DIFL( * ), DIFR( * ),
        !            35: *      $                   GIVNUM( LDGNUM, * ), POLES( LDGNUM, * ),
        !            36: *      $                   VF( * ), VL( * ), WORK( * ), Z( * )
        !            37: *       ..
        !            38: *  
        !            39: *
        !            40: *> \par Purpose:
        !            41: *  =============
        !            42: *>
        !            43: *> \verbatim
        !            44: *>
        !            45: *> DLASD6 computes the SVD of an updated upper bidiagonal matrix B
        !            46: *> obtained by merging two smaller ones by appending a row. This
        !            47: *> routine is used only for the problem which requires all singular
        !            48: *> values and optionally singular vector matrices in factored form.
        !            49: *> B is an N-by-M matrix with N = NL + NR + 1 and M = N + SQRE.
        !            50: *> A related subroutine, DLASD1, handles the case in which all singular
        !            51: *> values and singular vectors of the bidiagonal matrix are desired.
        !            52: *>
        !            53: *> DLASD6 computes the SVD as follows:
        !            54: *>
        !            55: *>               ( D1(in)    0    0       0 )
        !            56: *>   B = U(in) * (   Z1**T   a   Z2**T    b ) * VT(in)
        !            57: *>               (   0       0   D2(in)   0 )
        !            58: *>
        !            59: *>     = U(out) * ( D(out) 0) * VT(out)
        !            60: *>
        !            61: *> where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M
        !            62: *> with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros
        !            63: *> elsewhere; and the entry b is empty if SQRE = 0.
        !            64: *>
        !            65: *> The singular values of B can be computed using D1, D2, the first
        !            66: *> components of all the right singular vectors of the lower block, and
        !            67: *> the last components of all the right singular vectors of the upper
        !            68: *> block. These components are stored and updated in VF and VL,
        !            69: *> respectively, in DLASD6. Hence U and VT are not explicitly
        !            70: *> referenced.
        !            71: *>
        !            72: *> The singular values are stored in D. The algorithm consists of two
        !            73: *> stages:
        !            74: *>
        !            75: *>       The first stage consists of deflating the size of the problem
        !            76: *>       when there are multiple singular values or if there is a zero
        !            77: *>       in the Z vector. For each such occurence the dimension of the
        !            78: *>       secular equation problem is reduced by one. This stage is
        !            79: *>       performed by the routine DLASD7.
        !            80: *>
        !            81: *>       The second stage consists of calculating the updated
        !            82: *>       singular values. This is done by finding the roots of the
        !            83: *>       secular equation via the routine DLASD4 (as called by DLASD8).
        !            84: *>       This routine also updates VF and VL and computes the distances
        !            85: *>       between the updated singular values and the old singular
        !            86: *>       values.
        !            87: *>
        !            88: *> DLASD6 is called from DLASDA.
        !            89: *> \endverbatim
        !            90: *
        !            91: *  Arguments:
        !            92: *  ==========
        !            93: *
        !            94: *> \param[in] ICOMPQ
        !            95: *> \verbatim
        !            96: *>          ICOMPQ is INTEGER
        !            97: *>         Specifies whether singular vectors are to be computed in
        !            98: *>         factored form:
        !            99: *>         = 0: Compute singular values only.
        !           100: *>         = 1: Compute singular vectors in factored form as well.
        !           101: *> \endverbatim
        !           102: *>
        !           103: *> \param[in] NL
        !           104: *> \verbatim
        !           105: *>          NL is INTEGER
        !           106: *>         The row dimension of the upper block.  NL >= 1.
        !           107: *> \endverbatim
        !           108: *>
        !           109: *> \param[in] NR
        !           110: *> \verbatim
        !           111: *>          NR is INTEGER
        !           112: *>         The row dimension of the lower block.  NR >= 1.
        !           113: *> \endverbatim
        !           114: *>
        !           115: *> \param[in] SQRE
        !           116: *> \verbatim
        !           117: *>          SQRE is INTEGER
        !           118: *>         = 0: the lower block is an NR-by-NR square matrix.
        !           119: *>         = 1: the lower block is an NR-by-(NR+1) rectangular matrix.
        !           120: *>
        !           121: *>         The bidiagonal matrix has row dimension N = NL + NR + 1,
        !           122: *>         and column dimension M = N + SQRE.
        !           123: *> \endverbatim
        !           124: *>
        !           125: *> \param[in,out] D
        !           126: *> \verbatim
        !           127: *>          D is DOUBLE PRECISION array, dimension ( NL+NR+1 ).
        !           128: *>         On entry D(1:NL,1:NL) contains the singular values of the
        !           129: *>         upper block, and D(NL+2:N) contains the singular values
        !           130: *>         of the lower block. On exit D(1:N) contains the singular
        !           131: *>         values of the modified matrix.
        !           132: *> \endverbatim
        !           133: *>
        !           134: *> \param[in,out] VF
        !           135: *> \verbatim
        !           136: *>          VF is DOUBLE PRECISION array, dimension ( M )
        !           137: *>         On entry, VF(1:NL+1) contains the first components of all
        !           138: *>         right singular vectors of the upper block; and VF(NL+2:M)
        !           139: *>         contains the first components of all right singular vectors
        !           140: *>         of the lower block. On exit, VF contains the first components
        !           141: *>         of all right singular vectors of the bidiagonal matrix.
        !           142: *> \endverbatim
        !           143: *>
        !           144: *> \param[in,out] VL
        !           145: *> \verbatim
        !           146: *>          VL is DOUBLE PRECISION array, dimension ( M )
        !           147: *>         On entry, VL(1:NL+1) contains the  last components of all
        !           148: *>         right singular vectors of the upper block; and VL(NL+2:M)
        !           149: *>         contains the last components of all right singular vectors of
        !           150: *>         the lower block. On exit, VL contains the last components of
        !           151: *>         all right singular vectors of the bidiagonal matrix.
        !           152: *> \endverbatim
        !           153: *>
        !           154: *> \param[in,out] ALPHA
        !           155: *> \verbatim
        !           156: *>          ALPHA is DOUBLE PRECISION
        !           157: *>         Contains the diagonal element associated with the added row.
        !           158: *> \endverbatim
        !           159: *>
        !           160: *> \param[in,out] BETA
        !           161: *> \verbatim
        !           162: *>          BETA is DOUBLE PRECISION
        !           163: *>         Contains the off-diagonal element associated with the added
        !           164: *>         row.
        !           165: *> \endverbatim
        !           166: *>
        !           167: *> \param[out] IDXQ
        !           168: *> \verbatim
        !           169: *>          IDXQ is INTEGER array, dimension ( N )
        !           170: *>         This contains the permutation which will reintegrate the
        !           171: *>         subproblem just solved back into sorted order, i.e.
        !           172: *>         D( IDXQ( I = 1, N ) ) will be in ascending order.
        !           173: *> \endverbatim
        !           174: *>
        !           175: *> \param[out] PERM
        !           176: *> \verbatim
        !           177: *>          PERM is INTEGER array, dimension ( N )
        !           178: *>         The permutations (from deflation and sorting) to be applied
        !           179: *>         to each block. Not referenced if ICOMPQ = 0.
        !           180: *> \endverbatim
        !           181: *>
        !           182: *> \param[out] GIVPTR
        !           183: *> \verbatim
        !           184: *>          GIVPTR is INTEGER
        !           185: *>         The number of Givens rotations which took place in this
        !           186: *>         subproblem. Not referenced if ICOMPQ = 0.
        !           187: *> \endverbatim
        !           188: *>
        !           189: *> \param[out] GIVCOL
        !           190: *> \verbatim
        !           191: *>          GIVCOL is INTEGER array, dimension ( LDGCOL, 2 )
        !           192: *>         Each pair of numbers indicates a pair of columns to take place
        !           193: *>         in a Givens rotation. Not referenced if ICOMPQ = 0.
        !           194: *> \endverbatim
        !           195: *>
        !           196: *> \param[in] LDGCOL
        !           197: *> \verbatim
        !           198: *>          LDGCOL is INTEGER
        !           199: *>         leading dimension of GIVCOL, must be at least N.
        !           200: *> \endverbatim
        !           201: *>
        !           202: *> \param[out] GIVNUM
        !           203: *> \verbatim
        !           204: *>          GIVNUM is DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
        !           205: *>         Each number indicates the C or S value to be used in the
        !           206: *>         corresponding Givens rotation. Not referenced if ICOMPQ = 0.
        !           207: *> \endverbatim
        !           208: *>
        !           209: *> \param[in] LDGNUM
        !           210: *> \verbatim
        !           211: *>          LDGNUM is INTEGER
        !           212: *>         The leading dimension of GIVNUM and POLES, must be at least N.
        !           213: *> \endverbatim
        !           214: *>
        !           215: *> \param[out] POLES
        !           216: *> \verbatim
        !           217: *>          POLES is DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
        !           218: *>         On exit, POLES(1,*) is an array containing the new singular
        !           219: *>         values obtained from solving the secular equation, and
        !           220: *>         POLES(2,*) is an array containing the poles in the secular
        !           221: *>         equation. Not referenced if ICOMPQ = 0.
        !           222: *> \endverbatim
        !           223: *>
        !           224: *> \param[out] DIFL
        !           225: *> \verbatim
        !           226: *>          DIFL is DOUBLE PRECISION array, dimension ( N )
        !           227: *>         On exit, DIFL(I) is the distance between I-th updated
        !           228: *>         (undeflated) singular value and the I-th (undeflated) old
        !           229: *>         singular value.
        !           230: *> \endverbatim
        !           231: *>
        !           232: *> \param[out] DIFR
        !           233: *> \verbatim
        !           234: *>          DIFR is DOUBLE PRECISION array,
        !           235: *>                  dimension ( LDGNUM, 2 ) if ICOMPQ = 1 and
        !           236: *>                  dimension ( N ) if ICOMPQ = 0.
        !           237: *>         On exit, DIFR(I, 1) is the distance between I-th updated
        !           238: *>         (undeflated) singular value and the I+1-th (undeflated) old
        !           239: *>         singular value.
        !           240: *>
        !           241: *>         If ICOMPQ = 1, DIFR(1:K,2) is an array containing the
        !           242: *>         normalizing factors for the right singular vector matrix.
        !           243: *>
        !           244: *>         See DLASD8 for details on DIFL and DIFR.
        !           245: *> \endverbatim
        !           246: *>
        !           247: *> \param[out] Z
        !           248: *> \verbatim
        !           249: *>          Z is DOUBLE PRECISION array, dimension ( M )
        !           250: *>         The first elements of this array contain the components
        !           251: *>         of the deflation-adjusted updating row vector.
        !           252: *> \endverbatim
        !           253: *>
        !           254: *> \param[out] K
        !           255: *> \verbatim
        !           256: *>          K is INTEGER
        !           257: *>         Contains the dimension of the non-deflated matrix,
        !           258: *>         This is the order of the related secular equation. 1 <= K <=N.
        !           259: *> \endverbatim
        !           260: *>
        !           261: *> \param[out] C
        !           262: *> \verbatim
        !           263: *>          C is DOUBLE PRECISION
        !           264: *>         C contains garbage if SQRE =0 and the C-value of a Givens
        !           265: *>         rotation related to the right null space if SQRE = 1.
        !           266: *> \endverbatim
        !           267: *>
        !           268: *> \param[out] S
        !           269: *> \verbatim
        !           270: *>          S is DOUBLE PRECISION
        !           271: *>         S contains garbage if SQRE =0 and the S-value of a Givens
        !           272: *>         rotation related to the right null space if SQRE = 1.
        !           273: *> \endverbatim
        !           274: *>
        !           275: *> \param[out] WORK
        !           276: *> \verbatim
        !           277: *>          WORK is DOUBLE PRECISION array, dimension ( 4 * M )
        !           278: *> \endverbatim
        !           279: *>
        !           280: *> \param[out] IWORK
        !           281: *> \verbatim
        !           282: *>          IWORK is INTEGER array, dimension ( 3 * N )
        !           283: *> \endverbatim
        !           284: *>
        !           285: *> \param[out] INFO
        !           286: *> \verbatim
        !           287: *>          INFO is INTEGER
        !           288: *>          = 0:  successful exit.
        !           289: *>          < 0:  if INFO = -i, the i-th argument had an illegal value.
        !           290: *>          > 0:  if INFO = 1, a singular value did not converge
        !           291: *> \endverbatim
        !           292: *
        !           293: *  Authors:
        !           294: *  ========
        !           295: *
        !           296: *> \author Univ. of Tennessee 
        !           297: *> \author Univ. of California Berkeley 
        !           298: *> \author Univ. of Colorado Denver 
        !           299: *> \author NAG Ltd. 
        !           300: *
        !           301: *> \date November 2011
        !           302: *
        !           303: *> \ingroup auxOTHERauxiliary
        !           304: *
        !           305: *> \par Contributors:
        !           306: *  ==================
        !           307: *>
        !           308: *>     Ming Gu and Huan Ren, Computer Science Division, University of
        !           309: *>     California at Berkeley, USA
        !           310: *>
        !           311: *  =====================================================================
1.1       bertrand  312:       SUBROUTINE DLASD6( ICOMPQ, NL, NR, SQRE, D, VF, VL, ALPHA, BETA,
                    313:      $                   IDXQ, PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM,
                    314:      $                   LDGNUM, POLES, DIFL, DIFR, Z, K, C, S, WORK,
                    315:      $                   IWORK, INFO )
                    316: *
1.11    ! bertrand  317: *  -- LAPACK auxiliary routine (version 3.4.0) --
1.1       bertrand  318: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
                    319: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.11    ! bertrand  320: *     November 2011
1.1       bertrand  321: *
                    322: *     .. Scalar Arguments ..
                    323:       INTEGER            GIVPTR, ICOMPQ, INFO, K, LDGCOL, LDGNUM, NL,
                    324:      $                   NR, SQRE
                    325:       DOUBLE PRECISION   ALPHA, BETA, C, S
                    326: *     ..
                    327: *     .. Array Arguments ..
                    328:       INTEGER            GIVCOL( LDGCOL, * ), IDXQ( * ), IWORK( * ),
                    329:      $                   PERM( * )
                    330:       DOUBLE PRECISION   D( * ), DIFL( * ), DIFR( * ),
                    331:      $                   GIVNUM( LDGNUM, * ), POLES( LDGNUM, * ),
                    332:      $                   VF( * ), VL( * ), WORK( * ), Z( * )
                    333: *     ..
                    334: *
                    335: *  =====================================================================
                    336: *
                    337: *     .. Parameters ..
                    338:       DOUBLE PRECISION   ONE, ZERO
                    339:       PARAMETER          ( ONE = 1.0D+0, ZERO = 0.0D+0 )
                    340: *     ..
                    341: *     .. Local Scalars ..
                    342:       INTEGER            I, IDX, IDXC, IDXP, ISIGMA, IVFW, IVLW, IW, M,
                    343:      $                   N, N1, N2
                    344:       DOUBLE PRECISION   ORGNRM
                    345: *     ..
                    346: *     .. External Subroutines ..
                    347:       EXTERNAL           DCOPY, DLAMRG, DLASCL, DLASD7, DLASD8, XERBLA
                    348: *     ..
                    349: *     .. Intrinsic Functions ..
                    350:       INTRINSIC          ABS, MAX
                    351: *     ..
                    352: *     .. Executable Statements ..
                    353: *
                    354: *     Test the input parameters.
                    355: *
                    356:       INFO = 0
                    357:       N = NL + NR + 1
                    358:       M = N + SQRE
                    359: *
                    360:       IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THEN
                    361:          INFO = -1
                    362:       ELSE IF( NL.LT.1 ) THEN
                    363:          INFO = -2
                    364:       ELSE IF( NR.LT.1 ) THEN
                    365:          INFO = -3
                    366:       ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THEN
                    367:          INFO = -4
                    368:       ELSE IF( LDGCOL.LT.N ) THEN
                    369:          INFO = -14
                    370:       ELSE IF( LDGNUM.LT.N ) THEN
                    371:          INFO = -16
                    372:       END IF
                    373:       IF( INFO.NE.0 ) THEN
                    374:          CALL XERBLA( 'DLASD6', -INFO )
                    375:          RETURN
                    376:       END IF
                    377: *
                    378: *     The following values are for bookkeeping purposes only.  They are
                    379: *     integer pointers which indicate the portion of the workspace
                    380: *     used by a particular array in DLASD7 and DLASD8.
                    381: *
                    382:       ISIGMA = 1
                    383:       IW = ISIGMA + N
                    384:       IVFW = IW + M
                    385:       IVLW = IVFW + M
                    386: *
                    387:       IDX = 1
                    388:       IDXC = IDX + N
                    389:       IDXP = IDXC + N
                    390: *
                    391: *     Scale.
                    392: *
                    393:       ORGNRM = MAX( ABS( ALPHA ), ABS( BETA ) )
                    394:       D( NL+1 ) = ZERO
                    395:       DO 10 I = 1, N
                    396:          IF( ABS( D( I ) ).GT.ORGNRM ) THEN
                    397:             ORGNRM = ABS( D( I ) )
                    398:          END IF
                    399:    10 CONTINUE
                    400:       CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, 1, D, N, INFO )
                    401:       ALPHA = ALPHA / ORGNRM
                    402:       BETA = BETA / ORGNRM
                    403: *
                    404: *     Sort and Deflate singular values.
                    405: *
                    406:       CALL DLASD7( ICOMPQ, NL, NR, SQRE, K, D, Z, WORK( IW ), VF,
                    407:      $             WORK( IVFW ), VL, WORK( IVLW ), ALPHA, BETA,
                    408:      $             WORK( ISIGMA ), IWORK( IDX ), IWORK( IDXP ), IDXQ,
                    409:      $             PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM, C, S,
                    410:      $             INFO )
                    411: *
                    412: *     Solve Secular Equation, compute DIFL, DIFR, and update VF, VL.
                    413: *
                    414:       CALL DLASD8( ICOMPQ, K, D, Z, VF, VL, DIFL, DIFR, LDGNUM,
                    415:      $             WORK( ISIGMA ), WORK( IW ), INFO )
                    416: *
1.8       bertrand  417: *     Handle error returned
                    418: *
                    419:       IF( INFO.NE.0 ) THEN
                    420:          CALL XERBLA( 'DLASD8', -INFO )
                    421:          RETURN
                    422:       END IF
                    423: *
1.1       bertrand  424: *     Save the poles if ICOMPQ = 1.
                    425: *
                    426:       IF( ICOMPQ.EQ.1 ) THEN
                    427:          CALL DCOPY( K, D, 1, POLES( 1, 1 ), 1 )
                    428:          CALL DCOPY( K, WORK( ISIGMA ), 1, POLES( 1, 2 ), 1 )
                    429:       END IF
                    430: *
                    431: *     Unscale.
                    432: *
                    433:       CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
                    434: *
                    435: *     Prepare the IDXQ sorting permutation.
                    436: *
                    437:       N1 = K
                    438:       N2 = N - K
                    439:       CALL DLAMRG( N1, N2, D, 1, -1, IDXQ )
                    440: *
                    441:       RETURN
                    442: *
                    443: *     End of DLASD6
                    444: *
                    445:       END

CVSweb interface <joel.bertrand@systella.fr>