Annotation of rpl/lapack/lapack/dsbgst.f, revision 1.9

1.8       bertrand    1: *> \brief \b DSBGST
                      2: *
                      3: *  =========== DOCUMENTATION ===========
                      4: *
                      5: * Online html documentation available at 
                      6: *            http://www.netlib.org/lapack/explore-html/ 
                      7: *
                      8: *> \htmlonly
                      9: *> Download DSBGST + dependencies 
                     10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dsbgst.f"> 
                     11: *> [TGZ]</a> 
                     12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dsbgst.f"> 
                     13: *> [ZIP]</a> 
                     14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbgst.f"> 
                     15: *> [TXT]</a>
                     16: *> \endhtmlonly 
                     17: *
                     18: *  Definition:
                     19: *  ===========
                     20: *
                     21: *       SUBROUTINE DSBGST( VECT, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, X,
                     22: *                          LDX, WORK, INFO )
                     23: * 
                     24: *       .. Scalar Arguments ..
                     25: *       CHARACTER          UPLO, VECT
                     26: *       INTEGER            INFO, KA, KB, LDAB, LDBB, LDX, N
                     27: *       ..
                     28: *       .. Array Arguments ..
                     29: *       DOUBLE PRECISION   AB( LDAB, * ), BB( LDBB, * ), WORK( * ),
                     30: *      $                   X( LDX, * )
                     31: *       ..
                     32: *  
                     33: *
                     34: *> \par Purpose:
                     35: *  =============
                     36: *>
                     37: *> \verbatim
                     38: *>
                     39: *> DSBGST reduces a real symmetric-definite banded generalized
                     40: *> eigenproblem  A*x = lambda*B*x  to standard form  C*y = lambda*y,
                     41: *> such that C has the same bandwidth as A.
                     42: *>
                     43: *> B must have been previously factorized as S**T*S by DPBSTF, using a
                     44: *> split Cholesky factorization. A is overwritten by C = X**T*A*X, where
                     45: *> X = S**(-1)*Q and Q is an orthogonal matrix chosen to preserve the
                     46: *> bandwidth of A.
                     47: *> \endverbatim
                     48: *
                     49: *  Arguments:
                     50: *  ==========
                     51: *
                     52: *> \param[in] VECT
                     53: *> \verbatim
                     54: *>          VECT is CHARACTER*1
                     55: *>          = 'N':  do not form the transformation matrix X;
                     56: *>          = 'V':  form X.
                     57: *> \endverbatim
                     58: *>
                     59: *> \param[in] UPLO
                     60: *> \verbatim
                     61: *>          UPLO is CHARACTER*1
                     62: *>          = 'U':  Upper triangle of A is stored;
                     63: *>          = 'L':  Lower triangle of A is stored.
                     64: *> \endverbatim
                     65: *>
                     66: *> \param[in] N
                     67: *> \verbatim
                     68: *>          N is INTEGER
                     69: *>          The order of the matrices A and B.  N >= 0.
                     70: *> \endverbatim
                     71: *>
                     72: *> \param[in] KA
                     73: *> \verbatim
                     74: *>          KA is INTEGER
                     75: *>          The number of superdiagonals of the matrix A if UPLO = 'U',
                     76: *>          or the number of subdiagonals if UPLO = 'L'.  KA >= 0.
                     77: *> \endverbatim
                     78: *>
                     79: *> \param[in] KB
                     80: *> \verbatim
                     81: *>          KB is INTEGER
                     82: *>          The number of superdiagonals of the matrix B if UPLO = 'U',
                     83: *>          or the number of subdiagonals if UPLO = 'L'.  KA >= KB >= 0.
                     84: *> \endverbatim
                     85: *>
                     86: *> \param[in,out] AB
                     87: *> \verbatim
                     88: *>          AB is DOUBLE PRECISION array, dimension (LDAB,N)
                     89: *>          On entry, the upper or lower triangle of the symmetric band
                     90: *>          matrix A, stored in the first ka+1 rows of the array.  The
                     91: *>          j-th column of A is stored in the j-th column of the array AB
                     92: *>          as follows:
                     93: *>          if UPLO = 'U', AB(ka+1+i-j,j) = A(i,j) for max(1,j-ka)<=i<=j;
                     94: *>          if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+ka).
                     95: *>
                     96: *>          On exit, the transformed matrix X**T*A*X, stored in the same
                     97: *>          format as A.
                     98: *> \endverbatim
                     99: *>
                    100: *> \param[in] LDAB
                    101: *> \verbatim
                    102: *>          LDAB is INTEGER
                    103: *>          The leading dimension of the array AB.  LDAB >= KA+1.
                    104: *> \endverbatim
                    105: *>
                    106: *> \param[in] BB
                    107: *> \verbatim
                    108: *>          BB is DOUBLE PRECISION array, dimension (LDBB,N)
                    109: *>          The banded factor S from the split Cholesky factorization of
                    110: *>          B, as returned by DPBSTF, stored in the first KB+1 rows of
                    111: *>          the array.
                    112: *> \endverbatim
                    113: *>
                    114: *> \param[in] LDBB
                    115: *> \verbatim
                    116: *>          LDBB is INTEGER
                    117: *>          The leading dimension of the array BB.  LDBB >= KB+1.
                    118: *> \endverbatim
                    119: *>
                    120: *> \param[out] X
                    121: *> \verbatim
                    122: *>          X is DOUBLE PRECISION array, dimension (LDX,N)
                    123: *>          If VECT = 'V', the n-by-n matrix X.
                    124: *>          If VECT = 'N', the array X is not referenced.
                    125: *> \endverbatim
                    126: *>
                    127: *> \param[in] LDX
                    128: *> \verbatim
                    129: *>          LDX is INTEGER
                    130: *>          The leading dimension of the array X.
                    131: *>          LDX >= max(1,N) if VECT = 'V'; LDX >= 1 otherwise.
                    132: *> \endverbatim
                    133: *>
                    134: *> \param[out] WORK
                    135: *> \verbatim
                    136: *>          WORK is DOUBLE PRECISION array, dimension (2*N)
                    137: *> \endverbatim
                    138: *>
                    139: *> \param[out] INFO
                    140: *> \verbatim
                    141: *>          INFO is INTEGER
                    142: *>          = 0:  successful exit
                    143: *>          < 0:  if INFO = -i, the i-th argument had an illegal value.
                    144: *> \endverbatim
                    145: *
                    146: *  Authors:
                    147: *  ========
                    148: *
                    149: *> \author Univ. of Tennessee 
                    150: *> \author Univ. of California Berkeley 
                    151: *> \author Univ. of Colorado Denver 
                    152: *> \author NAG Ltd. 
                    153: *
                    154: *> \date November 2011
                    155: *
                    156: *> \ingroup doubleOTHERcomputational
                    157: *
                    158: *  =====================================================================
1.1       bertrand  159:       SUBROUTINE DSBGST( VECT, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, X,
                    160:      $                   LDX, WORK, INFO )
                    161: *
1.8       bertrand  162: *  -- LAPACK computational routine (version 3.4.0) --
1.1       bertrand  163: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
                    164: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.8       bertrand  165: *     November 2011
1.1       bertrand  166: *
                    167: *     .. Scalar Arguments ..
                    168:       CHARACTER          UPLO, VECT
                    169:       INTEGER            INFO, KA, KB, LDAB, LDBB, LDX, N
                    170: *     ..
                    171: *     .. Array Arguments ..
                    172:       DOUBLE PRECISION   AB( LDAB, * ), BB( LDBB, * ), WORK( * ),
                    173:      $                   X( LDX, * )
                    174: *     ..
                    175: *
                    176: *  =====================================================================
                    177: *
                    178: *     .. Parameters ..
                    179:       DOUBLE PRECISION   ZERO, ONE
                    180:       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
                    181: *     ..
                    182: *     .. Local Scalars ..
                    183:       LOGICAL            UPDATE, UPPER, WANTX
                    184:       INTEGER            I, I0, I1, I2, INCA, J, J1, J1T, J2, J2T, K,
                    185:      $                   KA1, KB1, KBT, L, M, NR, NRT, NX
                    186:       DOUBLE PRECISION   BII, RA, RA1, T
                    187: *     ..
                    188: *     .. External Functions ..
                    189:       LOGICAL            LSAME
                    190:       EXTERNAL           LSAME
                    191: *     ..
                    192: *     .. External Subroutines ..
                    193:       EXTERNAL           DGER, DLAR2V, DLARGV, DLARTG, DLARTV, DLASET,
                    194:      $                   DROT, DSCAL, XERBLA
                    195: *     ..
                    196: *     .. Intrinsic Functions ..
                    197:       INTRINSIC          MAX, MIN
                    198: *     ..
                    199: *     .. Executable Statements ..
                    200: *
                    201: *     Test the input parameters
                    202: *
                    203:       WANTX = LSAME( VECT, 'V' )
                    204:       UPPER = LSAME( UPLO, 'U' )
                    205:       KA1 = KA + 1
                    206:       KB1 = KB + 1
                    207:       INFO = 0
                    208:       IF( .NOT.WANTX .AND. .NOT.LSAME( VECT, 'N' ) ) THEN
                    209:          INFO = -1
                    210:       ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
                    211:          INFO = -2
                    212:       ELSE IF( N.LT.0 ) THEN
                    213:          INFO = -3
                    214:       ELSE IF( KA.LT.0 ) THEN
                    215:          INFO = -4
                    216:       ELSE IF( KB.LT.0 .OR. KB.GT.KA ) THEN
                    217:          INFO = -5
                    218:       ELSE IF( LDAB.LT.KA+1 ) THEN
                    219:          INFO = -7
                    220:       ELSE IF( LDBB.LT.KB+1 ) THEN
                    221:          INFO = -9
                    222:       ELSE IF( LDX.LT.1 .OR. WANTX .AND. LDX.LT.MAX( 1, N ) ) THEN
                    223:          INFO = -11
                    224:       END IF
                    225:       IF( INFO.NE.0 ) THEN
                    226:          CALL XERBLA( 'DSBGST', -INFO )
                    227:          RETURN
                    228:       END IF
                    229: *
                    230: *     Quick return if possible
                    231: *
                    232:       IF( N.EQ.0 )
                    233:      $   RETURN
                    234: *
                    235:       INCA = LDAB*KA1
                    236: *
                    237: *     Initialize X to the unit matrix, if needed
                    238: *
                    239:       IF( WANTX )
                    240:      $   CALL DLASET( 'Full', N, N, ZERO, ONE, X, LDX )
                    241: *
                    242: *     Set M to the splitting point m. It must be the same value as is
                    243: *     used in DPBSTF. The chosen value allows the arrays WORK and RWORK
                    244: *     to be of dimension (N).
                    245: *
                    246:       M = ( N+KB ) / 2
                    247: *
                    248: *     The routine works in two phases, corresponding to the two halves
                    249: *     of the split Cholesky factorization of B as S**T*S where
                    250: *
                    251: *     S = ( U    )
                    252: *         ( M  L )
                    253: *
                    254: *     with U upper triangular of order m, and L lower triangular of
                    255: *     order n-m. S has the same bandwidth as B.
                    256: *
                    257: *     S is treated as a product of elementary matrices:
                    258: *
                    259: *     S = S(m)*S(m-1)*...*S(2)*S(1)*S(m+1)*S(m+2)*...*S(n-1)*S(n)
                    260: *
                    261: *     where S(i) is determined by the i-th row of S.
                    262: *
                    263: *     In phase 1, the index i takes the values n, n-1, ... , m+1;
                    264: *     in phase 2, it takes the values 1, 2, ... , m.
                    265: *
                    266: *     For each value of i, the current matrix A is updated by forming
                    267: *     inv(S(i))**T*A*inv(S(i)). This creates a triangular bulge outside
                    268: *     the band of A. The bulge is then pushed down toward the bottom of
                    269: *     A in phase 1, and up toward the top of A in phase 2, by applying
                    270: *     plane rotations.
                    271: *
                    272: *     There are kb*(kb+1)/2 elements in the bulge, but at most 2*kb-1
                    273: *     of them are linearly independent, so annihilating a bulge requires
                    274: *     only 2*kb-1 plane rotations. The rotations are divided into a 1st
                    275: *     set of kb-1 rotations, and a 2nd set of kb rotations.
                    276: *
                    277: *     Wherever possible, rotations are generated and applied in vector
                    278: *     operations of length NR between the indices J1 and J2 (sometimes
                    279: *     replaced by modified values NRT, J1T or J2T).
                    280: *
                    281: *     The cosines and sines of the rotations are stored in the array
                    282: *     WORK. The cosines of the 1st set of rotations are stored in
                    283: *     elements n+2:n+m-kb-1 and the sines of the 1st set in elements
                    284: *     2:m-kb-1; the cosines of the 2nd set are stored in elements
                    285: *     n+m-kb+1:2*n and the sines of the second set in elements m-kb+1:n.
                    286: *
                    287: *     The bulges are not formed explicitly; nonzero elements outside the
                    288: *     band are created only when they are required for generating new
                    289: *     rotations; they are stored in the array WORK, in positions where
                    290: *     they are later overwritten by the sines of the rotations which
                    291: *     annihilate them.
                    292: *
                    293: *     **************************** Phase 1 *****************************
                    294: *
                    295: *     The logical structure of this phase is:
                    296: *
                    297: *     UPDATE = .TRUE.
                    298: *     DO I = N, M + 1, -1
                    299: *        use S(i) to update A and create a new bulge
                    300: *        apply rotations to push all bulges KA positions downward
                    301: *     END DO
                    302: *     UPDATE = .FALSE.
                    303: *     DO I = M + KA + 1, N - 1
                    304: *        apply rotations to push all bulges KA positions downward
                    305: *     END DO
                    306: *
                    307: *     To avoid duplicating code, the two loops are merged.
                    308: *
                    309:       UPDATE = .TRUE.
                    310:       I = N + 1
                    311:    10 CONTINUE
                    312:       IF( UPDATE ) THEN
                    313:          I = I - 1
                    314:          KBT = MIN( KB, I-1 )
                    315:          I0 = I - 1
                    316:          I1 = MIN( N, I+KA )
                    317:          I2 = I - KBT + KA1
                    318:          IF( I.LT.M+1 ) THEN
                    319:             UPDATE = .FALSE.
                    320:             I = I + 1
                    321:             I0 = M
                    322:             IF( KA.EQ.0 )
                    323:      $         GO TO 480
                    324:             GO TO 10
                    325:          END IF
                    326:       ELSE
                    327:          I = I + KA
                    328:          IF( I.GT.N-1 )
                    329:      $      GO TO 480
                    330:       END IF
                    331: *
                    332:       IF( UPPER ) THEN
                    333: *
                    334: *        Transform A, working with the upper triangle
                    335: *
                    336:          IF( UPDATE ) THEN
                    337: *
                    338: *           Form  inv(S(i))**T * A * inv(S(i))
                    339: *
                    340:             BII = BB( KB1, I )
                    341:             DO 20 J = I, I1
                    342:                AB( I-J+KA1, J ) = AB( I-J+KA1, J ) / BII
                    343:    20       CONTINUE
                    344:             DO 30 J = MAX( 1, I-KA ), I
                    345:                AB( J-I+KA1, I ) = AB( J-I+KA1, I ) / BII
                    346:    30       CONTINUE
                    347:             DO 60 K = I - KBT, I - 1
                    348:                DO 40 J = I - KBT, K
                    349:                   AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -
                    350:      $                               BB( J-I+KB1, I )*AB( K-I+KA1, I ) -
                    351:      $                               BB( K-I+KB1, I )*AB( J-I+KA1, I ) +
                    352:      $                               AB( KA1, I )*BB( J-I+KB1, I )*
                    353:      $                               BB( K-I+KB1, I )
                    354:    40          CONTINUE
                    355:                DO 50 J = MAX( 1, I-KA ), I - KBT - 1
                    356:                   AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -
                    357:      $                               BB( K-I+KB1, I )*AB( J-I+KA1, I )
                    358:    50          CONTINUE
                    359:    60       CONTINUE
                    360:             DO 80 J = I, I1
                    361:                DO 70 K = MAX( J-KA, I-KBT ), I - 1
                    362:                   AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -
                    363:      $                               BB( K-I+KB1, I )*AB( I-J+KA1, J )
                    364:    70          CONTINUE
                    365:    80       CONTINUE
                    366: *
                    367:             IF( WANTX ) THEN
                    368: *
                    369: *              post-multiply X by inv(S(i))
                    370: *
                    371:                CALL DSCAL( N-M, ONE / BII, X( M+1, I ), 1 )
                    372:                IF( KBT.GT.0 )
                    373:      $            CALL DGER( N-M, KBT, -ONE, X( M+1, I ), 1,
                    374:      $                       BB( KB1-KBT, I ), 1, X( M+1, I-KBT ), LDX )
                    375:             END IF
                    376: *
                    377: *           store a(i,i1) in RA1 for use in next loop over K
                    378: *
                    379:             RA1 = AB( I-I1+KA1, I1 )
                    380:          END IF
                    381: *
                    382: *        Generate and apply vectors of rotations to chase all the
                    383: *        existing bulges KA positions down toward the bottom of the
                    384: *        band
                    385: *
                    386:          DO 130 K = 1, KB - 1
                    387:             IF( UPDATE ) THEN
                    388: *
                    389: *              Determine the rotations which would annihilate the bulge
                    390: *              which has in theory just been created
                    391: *
                    392:                IF( I-K+KA.LT.N .AND. I-K.GT.1 ) THEN
                    393: *
                    394: *                 generate rotation to annihilate a(i,i-k+ka+1)
                    395: *
                    396:                   CALL DLARTG( AB( K+1, I-K+KA ), RA1,
                    397:      $                         WORK( N+I-K+KA-M ), WORK( I-K+KA-M ),
                    398:      $                         RA )
                    399: *
                    400: *                 create nonzero element a(i-k,i-k+ka+1) outside the
                    401: *                 band and store it in WORK(i-k)
                    402: *
                    403:                   T = -BB( KB1-K, I )*RA1
                    404:                   WORK( I-K ) = WORK( N+I-K+KA-M )*T -
                    405:      $                          WORK( I-K+KA-M )*AB( 1, I-K+KA )
                    406:                   AB( 1, I-K+KA ) = WORK( I-K+KA-M )*T +
                    407:      $                              WORK( N+I-K+KA-M )*AB( 1, I-K+KA )
                    408:                   RA1 = RA
                    409:                END IF
                    410:             END IF
                    411:             J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
                    412:             NR = ( N-J2+KA ) / KA1
                    413:             J1 = J2 + ( NR-1 )*KA1
                    414:             IF( UPDATE ) THEN
                    415:                J2T = MAX( J2, I+2*KA-K+1 )
                    416:             ELSE
                    417:                J2T = J2
                    418:             END IF
                    419:             NRT = ( N-J2T+KA ) / KA1
                    420:             DO 90 J = J2T, J1, KA1
                    421: *
                    422: *              create nonzero element a(j-ka,j+1) outside the band
                    423: *              and store it in WORK(j-m)
                    424: *
                    425:                WORK( J-M ) = WORK( J-M )*AB( 1, J+1 )
                    426:                AB( 1, J+1 ) = WORK( N+J-M )*AB( 1, J+1 )
                    427:    90       CONTINUE
                    428: *
                    429: *           generate rotations in 1st set to annihilate elements which
                    430: *           have been created outside the band
                    431: *
                    432:             IF( NRT.GT.0 )
                    433:      $         CALL DLARGV( NRT, AB( 1, J2T ), INCA, WORK( J2T-M ), KA1,
                    434:      $                      WORK( N+J2T-M ), KA1 )
                    435:             IF( NR.GT.0 ) THEN
                    436: *
                    437: *              apply rotations in 1st set from the right
                    438: *
                    439:                DO 100 L = 1, KA - 1
                    440:                   CALL DLARTV( NR, AB( KA1-L, J2 ), INCA,
                    441:      $                         AB( KA-L, J2+1 ), INCA, WORK( N+J2-M ),
                    442:      $                         WORK( J2-M ), KA1 )
                    443:   100          CONTINUE
                    444: *
                    445: *              apply rotations in 1st set from both sides to diagonal
                    446: *              blocks
                    447: *
                    448:                CALL DLAR2V( NR, AB( KA1, J2 ), AB( KA1, J2+1 ),
                    449:      $                      AB( KA, J2+1 ), INCA, WORK( N+J2-M ),
                    450:      $                      WORK( J2-M ), KA1 )
                    451: *
                    452:             END IF
                    453: *
                    454: *           start applying rotations in 1st set from the left
                    455: *
                    456:             DO 110 L = KA - 1, KB - K + 1, -1
                    457:                NRT = ( N-J2+L ) / KA1
                    458:                IF( NRT.GT.0 )
                    459:      $            CALL DLARTV( NRT, AB( L, J2+KA1-L ), INCA,
                    460:      $                         AB( L+1, J2+KA1-L ), INCA,
                    461:      $                         WORK( N+J2-M ), WORK( J2-M ), KA1 )
                    462:   110       CONTINUE
                    463: *
                    464:             IF( WANTX ) THEN
                    465: *
                    466: *              post-multiply X by product of rotations in 1st set
                    467: *
                    468:                DO 120 J = J2, J1, KA1
                    469:                   CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
                    470:      $                       WORK( N+J-M ), WORK( J-M ) )
                    471:   120          CONTINUE
                    472:             END IF
                    473:   130    CONTINUE
                    474: *
                    475:          IF( UPDATE ) THEN
                    476:             IF( I2.LE.N .AND. KBT.GT.0 ) THEN
                    477: *
                    478: *              create nonzero element a(i-kbt,i-kbt+ka+1) outside the
                    479: *              band and store it in WORK(i-kbt)
                    480: *
                    481:                WORK( I-KBT ) = -BB( KB1-KBT, I )*RA1
                    482:             END IF
                    483:          END IF
                    484: *
                    485:          DO 170 K = KB, 1, -1
                    486:             IF( UPDATE ) THEN
                    487:                J2 = I - K - 1 + MAX( 2, K-I0+1 )*KA1
                    488:             ELSE
                    489:                J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
                    490:             END IF
                    491: *
                    492: *           finish applying rotations in 2nd set from the left
                    493: *
                    494:             DO 140 L = KB - K, 1, -1
                    495:                NRT = ( N-J2+KA+L ) / KA1
                    496:                IF( NRT.GT.0 )
                    497:      $            CALL DLARTV( NRT, AB( L, J2-L+1 ), INCA,
                    498:      $                         AB( L+1, J2-L+1 ), INCA, WORK( N+J2-KA ),
                    499:      $                         WORK( J2-KA ), KA1 )
                    500:   140       CONTINUE
                    501:             NR = ( N-J2+KA ) / KA1
                    502:             J1 = J2 + ( NR-1 )*KA1
                    503:             DO 150 J = J1, J2, -KA1
                    504:                WORK( J ) = WORK( J-KA )
                    505:                WORK( N+J ) = WORK( N+J-KA )
                    506:   150       CONTINUE
                    507:             DO 160 J = J2, J1, KA1
                    508: *
                    509: *              create nonzero element a(j-ka,j+1) outside the band
                    510: *              and store it in WORK(j)
                    511: *
                    512:                WORK( J ) = WORK( J )*AB( 1, J+1 )
                    513:                AB( 1, J+1 ) = WORK( N+J )*AB( 1, J+1 )
                    514:   160       CONTINUE
                    515:             IF( UPDATE ) THEN
                    516:                IF( I-K.LT.N-KA .AND. K.LE.KBT )
                    517:      $            WORK( I-K+KA ) = WORK( I-K )
                    518:             END IF
                    519:   170    CONTINUE
                    520: *
                    521:          DO 210 K = KB, 1, -1
                    522:             J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
                    523:             NR = ( N-J2+KA ) / KA1
                    524:             J1 = J2 + ( NR-1 )*KA1
                    525:             IF( NR.GT.0 ) THEN
                    526: *
                    527: *              generate rotations in 2nd set to annihilate elements
                    528: *              which have been created outside the band
                    529: *
                    530:                CALL DLARGV( NR, AB( 1, J2 ), INCA, WORK( J2 ), KA1,
                    531:      $                      WORK( N+J2 ), KA1 )
                    532: *
                    533: *              apply rotations in 2nd set from the right
                    534: *
                    535:                DO 180 L = 1, KA - 1
                    536:                   CALL DLARTV( NR, AB( KA1-L, J2 ), INCA,
                    537:      $                         AB( KA-L, J2+1 ), INCA, WORK( N+J2 ),
                    538:      $                         WORK( J2 ), KA1 )
                    539:   180          CONTINUE
                    540: *
                    541: *              apply rotations in 2nd set from both sides to diagonal
                    542: *              blocks
                    543: *
                    544:                CALL DLAR2V( NR, AB( KA1, J2 ), AB( KA1, J2+1 ),
                    545:      $                      AB( KA, J2+1 ), INCA, WORK( N+J2 ),
                    546:      $                      WORK( J2 ), KA1 )
                    547: *
                    548:             END IF
                    549: *
                    550: *           start applying rotations in 2nd set from the left
                    551: *
                    552:             DO 190 L = KA - 1, KB - K + 1, -1
                    553:                NRT = ( N-J2+L ) / KA1
                    554:                IF( NRT.GT.0 )
                    555:      $            CALL DLARTV( NRT, AB( L, J2+KA1-L ), INCA,
                    556:      $                         AB( L+1, J2+KA1-L ), INCA, WORK( N+J2 ),
                    557:      $                         WORK( J2 ), KA1 )
                    558:   190       CONTINUE
                    559: *
                    560:             IF( WANTX ) THEN
                    561: *
                    562: *              post-multiply X by product of rotations in 2nd set
                    563: *
                    564:                DO 200 J = J2, J1, KA1
                    565:                   CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
                    566:      $                       WORK( N+J ), WORK( J ) )
                    567:   200          CONTINUE
                    568:             END IF
                    569:   210    CONTINUE
                    570: *
                    571:          DO 230 K = 1, KB - 1
                    572:             J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
                    573: *
                    574: *           finish applying rotations in 1st set from the left
                    575: *
                    576:             DO 220 L = KB - K, 1, -1
                    577:                NRT = ( N-J2+L ) / KA1
                    578:                IF( NRT.GT.0 )
                    579:      $            CALL DLARTV( NRT, AB( L, J2+KA1-L ), INCA,
                    580:      $                         AB( L+1, J2+KA1-L ), INCA,
                    581:      $                         WORK( N+J2-M ), WORK( J2-M ), KA1 )
                    582:   220       CONTINUE
                    583:   230    CONTINUE
                    584: *
                    585:          IF( KB.GT.1 ) THEN
                    586:             DO 240 J = N - 1, I - KB + 2*KA + 1, -1
                    587:                WORK( N+J-M ) = WORK( N+J-KA-M )
                    588:                WORK( J-M ) = WORK( J-KA-M )
                    589:   240       CONTINUE
                    590:          END IF
                    591: *
                    592:       ELSE
                    593: *
                    594: *        Transform A, working with the lower triangle
                    595: *
                    596:          IF( UPDATE ) THEN
                    597: *
                    598: *           Form  inv(S(i))**T * A * inv(S(i))
                    599: *
                    600:             BII = BB( 1, I )
                    601:             DO 250 J = I, I1
                    602:                AB( J-I+1, I ) = AB( J-I+1, I ) / BII
                    603:   250       CONTINUE
                    604:             DO 260 J = MAX( 1, I-KA ), I
                    605:                AB( I-J+1, J ) = AB( I-J+1, J ) / BII
                    606:   260       CONTINUE
                    607:             DO 290 K = I - KBT, I - 1
                    608:                DO 270 J = I - KBT, K
                    609:                   AB( K-J+1, J ) = AB( K-J+1, J ) -
                    610:      $                             BB( I-J+1, J )*AB( I-K+1, K ) -
                    611:      $                             BB( I-K+1, K )*AB( I-J+1, J ) +
                    612:      $                             AB( 1, I )*BB( I-J+1, J )*
                    613:      $                             BB( I-K+1, K )
                    614:   270          CONTINUE
                    615:                DO 280 J = MAX( 1, I-KA ), I - KBT - 1
                    616:                   AB( K-J+1, J ) = AB( K-J+1, J ) -
                    617:      $                             BB( I-K+1, K )*AB( I-J+1, J )
                    618:   280          CONTINUE
                    619:   290       CONTINUE
                    620:             DO 310 J = I, I1
                    621:                DO 300 K = MAX( J-KA, I-KBT ), I - 1
                    622:                   AB( J-K+1, K ) = AB( J-K+1, K ) -
                    623:      $                             BB( I-K+1, K )*AB( J-I+1, I )
                    624:   300          CONTINUE
                    625:   310       CONTINUE
                    626: *
                    627:             IF( WANTX ) THEN
                    628: *
                    629: *              post-multiply X by inv(S(i))
                    630: *
                    631:                CALL DSCAL( N-M, ONE / BII, X( M+1, I ), 1 )
                    632:                IF( KBT.GT.0 )
                    633:      $            CALL DGER( N-M, KBT, -ONE, X( M+1, I ), 1,
                    634:      $                       BB( KBT+1, I-KBT ), LDBB-1,
                    635:      $                       X( M+1, I-KBT ), LDX )
                    636:             END IF
                    637: *
                    638: *           store a(i1,i) in RA1 for use in next loop over K
                    639: *
                    640:             RA1 = AB( I1-I+1, I )
                    641:          END IF
                    642: *
                    643: *        Generate and apply vectors of rotations to chase all the
                    644: *        existing bulges KA positions down toward the bottom of the
                    645: *        band
                    646: *
                    647:          DO 360 K = 1, KB - 1
                    648:             IF( UPDATE ) THEN
                    649: *
                    650: *              Determine the rotations which would annihilate the bulge
                    651: *              which has in theory just been created
                    652: *
                    653:                IF( I-K+KA.LT.N .AND. I-K.GT.1 ) THEN
                    654: *
                    655: *                 generate rotation to annihilate a(i-k+ka+1,i)
                    656: *
                    657:                   CALL DLARTG( AB( KA1-K, I ), RA1, WORK( N+I-K+KA-M ),
                    658:      $                         WORK( I-K+KA-M ), RA )
                    659: *
                    660: *                 create nonzero element a(i-k+ka+1,i-k) outside the
                    661: *                 band and store it in WORK(i-k)
                    662: *
                    663:                   T = -BB( K+1, I-K )*RA1
                    664:                   WORK( I-K ) = WORK( N+I-K+KA-M )*T -
                    665:      $                          WORK( I-K+KA-M )*AB( KA1, I-K )
                    666:                   AB( KA1, I-K ) = WORK( I-K+KA-M )*T +
                    667:      $                             WORK( N+I-K+KA-M )*AB( KA1, I-K )
                    668:                   RA1 = RA
                    669:                END IF
                    670:             END IF
                    671:             J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
                    672:             NR = ( N-J2+KA ) / KA1
                    673:             J1 = J2 + ( NR-1 )*KA1
                    674:             IF( UPDATE ) THEN
                    675:                J2T = MAX( J2, I+2*KA-K+1 )
                    676:             ELSE
                    677:                J2T = J2
                    678:             END IF
                    679:             NRT = ( N-J2T+KA ) / KA1
                    680:             DO 320 J = J2T, J1, KA1
                    681: *
                    682: *              create nonzero element a(j+1,j-ka) outside the band
                    683: *              and store it in WORK(j-m)
                    684: *
                    685:                WORK( J-M ) = WORK( J-M )*AB( KA1, J-KA+1 )
                    686:                AB( KA1, J-KA+1 ) = WORK( N+J-M )*AB( KA1, J-KA+1 )
                    687:   320       CONTINUE
                    688: *
                    689: *           generate rotations in 1st set to annihilate elements which
                    690: *           have been created outside the band
                    691: *
                    692:             IF( NRT.GT.0 )
                    693:      $         CALL DLARGV( NRT, AB( KA1, J2T-KA ), INCA, WORK( J2T-M ),
                    694:      $                      KA1, WORK( N+J2T-M ), KA1 )
                    695:             IF( NR.GT.0 ) THEN
                    696: *
                    697: *              apply rotations in 1st set from the left
                    698: *
                    699:                DO 330 L = 1, KA - 1
                    700:                   CALL DLARTV( NR, AB( L+1, J2-L ), INCA,
                    701:      $                         AB( L+2, J2-L ), INCA, WORK( N+J2-M ),
                    702:      $                         WORK( J2-M ), KA1 )
                    703:   330          CONTINUE
                    704: *
                    705: *              apply rotations in 1st set from both sides to diagonal
                    706: *              blocks
                    707: *
                    708:                CALL DLAR2V( NR, AB( 1, J2 ), AB( 1, J2+1 ), AB( 2, J2 ),
                    709:      $                      INCA, WORK( N+J2-M ), WORK( J2-M ), KA1 )
                    710: *
                    711:             END IF
                    712: *
                    713: *           start applying rotations in 1st set from the right
                    714: *
                    715:             DO 340 L = KA - 1, KB - K + 1, -1
                    716:                NRT = ( N-J2+L ) / KA1
                    717:                IF( NRT.GT.0 )
                    718:      $            CALL DLARTV( NRT, AB( KA1-L+1, J2 ), INCA,
                    719:      $                         AB( KA1-L, J2+1 ), INCA, WORK( N+J2-M ),
                    720:      $                         WORK( J2-M ), KA1 )
                    721:   340       CONTINUE
                    722: *
                    723:             IF( WANTX ) THEN
                    724: *
                    725: *              post-multiply X by product of rotations in 1st set
                    726: *
                    727:                DO 350 J = J2, J1, KA1
                    728:                   CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
                    729:      $                       WORK( N+J-M ), WORK( J-M ) )
                    730:   350          CONTINUE
                    731:             END IF
                    732:   360    CONTINUE
                    733: *
                    734:          IF( UPDATE ) THEN
                    735:             IF( I2.LE.N .AND. KBT.GT.0 ) THEN
                    736: *
                    737: *              create nonzero element a(i-kbt+ka+1,i-kbt) outside the
                    738: *              band and store it in WORK(i-kbt)
                    739: *
                    740:                WORK( I-KBT ) = -BB( KBT+1, I-KBT )*RA1
                    741:             END IF
                    742:          END IF
                    743: *
                    744:          DO 400 K = KB, 1, -1
                    745:             IF( UPDATE ) THEN
                    746:                J2 = I - K - 1 + MAX( 2, K-I0+1 )*KA1
                    747:             ELSE
                    748:                J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
                    749:             END IF
                    750: *
                    751: *           finish applying rotations in 2nd set from the right
                    752: *
                    753:             DO 370 L = KB - K, 1, -1
                    754:                NRT = ( N-J2+KA+L ) / KA1
                    755:                IF( NRT.GT.0 )
                    756:      $            CALL DLARTV( NRT, AB( KA1-L+1, J2-KA ), INCA,
                    757:      $                         AB( KA1-L, J2-KA+1 ), INCA,
                    758:      $                         WORK( N+J2-KA ), WORK( J2-KA ), KA1 )
                    759:   370       CONTINUE
                    760:             NR = ( N-J2+KA ) / KA1
                    761:             J1 = J2 + ( NR-1 )*KA1
                    762:             DO 380 J = J1, J2, -KA1
                    763:                WORK( J ) = WORK( J-KA )
                    764:                WORK( N+J ) = WORK( N+J-KA )
                    765:   380       CONTINUE
                    766:             DO 390 J = J2, J1, KA1
                    767: *
                    768: *              create nonzero element a(j+1,j-ka) outside the band
                    769: *              and store it in WORK(j)
                    770: *
                    771:                WORK( J ) = WORK( J )*AB( KA1, J-KA+1 )
                    772:                AB( KA1, J-KA+1 ) = WORK( N+J )*AB( KA1, J-KA+1 )
                    773:   390       CONTINUE
                    774:             IF( UPDATE ) THEN
                    775:                IF( I-K.LT.N-KA .AND. K.LE.KBT )
                    776:      $            WORK( I-K+KA ) = WORK( I-K )
                    777:             END IF
                    778:   400    CONTINUE
                    779: *
                    780:          DO 440 K = KB, 1, -1
                    781:             J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
                    782:             NR = ( N-J2+KA ) / KA1
                    783:             J1 = J2 + ( NR-1 )*KA1
                    784:             IF( NR.GT.0 ) THEN
                    785: *
                    786: *              generate rotations in 2nd set to annihilate elements
                    787: *              which have been created outside the band
                    788: *
                    789:                CALL DLARGV( NR, AB( KA1, J2-KA ), INCA, WORK( J2 ), KA1,
                    790:      $                      WORK( N+J2 ), KA1 )
                    791: *
                    792: *              apply rotations in 2nd set from the left
                    793: *
                    794:                DO 410 L = 1, KA - 1
                    795:                   CALL DLARTV( NR, AB( L+1, J2-L ), INCA,
                    796:      $                         AB( L+2, J2-L ), INCA, WORK( N+J2 ),
                    797:      $                         WORK( J2 ), KA1 )
                    798:   410          CONTINUE
                    799: *
                    800: *              apply rotations in 2nd set from both sides to diagonal
                    801: *              blocks
                    802: *
                    803:                CALL DLAR2V( NR, AB( 1, J2 ), AB( 1, J2+1 ), AB( 2, J2 ),
                    804:      $                      INCA, WORK( N+J2 ), WORK( J2 ), KA1 )
                    805: *
                    806:             END IF
                    807: *
                    808: *           start applying rotations in 2nd set from the right
                    809: *
                    810:             DO 420 L = KA - 1, KB - K + 1, -1
                    811:                NRT = ( N-J2+L ) / KA1
                    812:                IF( NRT.GT.0 )
                    813:      $            CALL DLARTV( NRT, AB( KA1-L+1, J2 ), INCA,
                    814:      $                         AB( KA1-L, J2+1 ), INCA, WORK( N+J2 ),
                    815:      $                         WORK( J2 ), KA1 )
                    816:   420       CONTINUE
                    817: *
                    818:             IF( WANTX ) THEN
                    819: *
                    820: *              post-multiply X by product of rotations in 2nd set
                    821: *
                    822:                DO 430 J = J2, J1, KA1
                    823:                   CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
                    824:      $                       WORK( N+J ), WORK( J ) )
                    825:   430          CONTINUE
                    826:             END IF
                    827:   440    CONTINUE
                    828: *
                    829:          DO 460 K = 1, KB - 1
                    830:             J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
                    831: *
                    832: *           finish applying rotations in 1st set from the right
                    833: *
                    834:             DO 450 L = KB - K, 1, -1
                    835:                NRT = ( N-J2+L ) / KA1
                    836:                IF( NRT.GT.0 )
                    837:      $            CALL DLARTV( NRT, AB( KA1-L+1, J2 ), INCA,
                    838:      $                         AB( KA1-L, J2+1 ), INCA, WORK( N+J2-M ),
                    839:      $                         WORK( J2-M ), KA1 )
                    840:   450       CONTINUE
                    841:   460    CONTINUE
                    842: *
                    843:          IF( KB.GT.1 ) THEN
                    844:             DO 470 J = N - 1, I - KB + 2*KA + 1, -1
                    845:                WORK( N+J-M ) = WORK( N+J-KA-M )
                    846:                WORK( J-M ) = WORK( J-KA-M )
                    847:   470       CONTINUE
                    848:          END IF
                    849: *
                    850:       END IF
                    851: *
                    852:       GO TO 10
                    853: *
                    854:   480 CONTINUE
                    855: *
                    856: *     **************************** Phase 2 *****************************
                    857: *
                    858: *     The logical structure of this phase is:
                    859: *
                    860: *     UPDATE = .TRUE.
                    861: *     DO I = 1, M
                    862: *        use S(i) to update A and create a new bulge
                    863: *        apply rotations to push all bulges KA positions upward
                    864: *     END DO
                    865: *     UPDATE = .FALSE.
                    866: *     DO I = M - KA - 1, 2, -1
                    867: *        apply rotations to push all bulges KA positions upward
                    868: *     END DO
                    869: *
                    870: *     To avoid duplicating code, the two loops are merged.
                    871: *
                    872:       UPDATE = .TRUE.
                    873:       I = 0
                    874:   490 CONTINUE
                    875:       IF( UPDATE ) THEN
                    876:          I = I + 1
                    877:          KBT = MIN( KB, M-I )
                    878:          I0 = I + 1
                    879:          I1 = MAX( 1, I-KA )
                    880:          I2 = I + KBT - KA1
                    881:          IF( I.GT.M ) THEN
                    882:             UPDATE = .FALSE.
                    883:             I = I - 1
                    884:             I0 = M + 1
                    885:             IF( KA.EQ.0 )
                    886:      $         RETURN
                    887:             GO TO 490
                    888:          END IF
                    889:       ELSE
                    890:          I = I - KA
                    891:          IF( I.LT.2 )
                    892:      $      RETURN
                    893:       END IF
                    894: *
                    895:       IF( I.LT.M-KBT ) THEN
                    896:          NX = M
                    897:       ELSE
                    898:          NX = N
                    899:       END IF
                    900: *
                    901:       IF( UPPER ) THEN
                    902: *
                    903: *        Transform A, working with the upper triangle
                    904: *
                    905:          IF( UPDATE ) THEN
                    906: *
                    907: *           Form  inv(S(i))**T * A * inv(S(i))
                    908: *
                    909:             BII = BB( KB1, I )
                    910:             DO 500 J = I1, I
                    911:                AB( J-I+KA1, I ) = AB( J-I+KA1, I ) / BII
                    912:   500       CONTINUE
                    913:             DO 510 J = I, MIN( N, I+KA )
                    914:                AB( I-J+KA1, J ) = AB( I-J+KA1, J ) / BII
                    915:   510       CONTINUE
                    916:             DO 540 K = I + 1, I + KBT
                    917:                DO 520 J = K, I + KBT
                    918:                   AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -
                    919:      $                               BB( I-J+KB1, J )*AB( I-K+KA1, K ) -
                    920:      $                               BB( I-K+KB1, K )*AB( I-J+KA1, J ) +
                    921:      $                               AB( KA1, I )*BB( I-J+KB1, J )*
                    922:      $                               BB( I-K+KB1, K )
                    923:   520          CONTINUE
                    924:                DO 530 J = I + KBT + 1, MIN( N, I+KA )
                    925:                   AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -
                    926:      $                               BB( I-K+KB1, K )*AB( I-J+KA1, J )
                    927:   530          CONTINUE
                    928:   540       CONTINUE
                    929:             DO 560 J = I1, I
                    930:                DO 550 K = I + 1, MIN( J+KA, I+KBT )
                    931:                   AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -
                    932:      $                               BB( I-K+KB1, K )*AB( J-I+KA1, I )
                    933:   550          CONTINUE
                    934:   560       CONTINUE
                    935: *
                    936:             IF( WANTX ) THEN
                    937: *
                    938: *              post-multiply X by inv(S(i))
                    939: *
                    940:                CALL DSCAL( NX, ONE / BII, X( 1, I ), 1 )
                    941:                IF( KBT.GT.0 )
                    942:      $            CALL DGER( NX, KBT, -ONE, X( 1, I ), 1, BB( KB, I+1 ),
                    943:      $                       LDBB-1, X( 1, I+1 ), LDX )
                    944:             END IF
                    945: *
                    946: *           store a(i1,i) in RA1 for use in next loop over K
                    947: *
                    948:             RA1 = AB( I1-I+KA1, I )
                    949:          END IF
                    950: *
                    951: *        Generate and apply vectors of rotations to chase all the
                    952: *        existing bulges KA positions up toward the top of the band
                    953: *
                    954:          DO 610 K = 1, KB - 1
                    955:             IF( UPDATE ) THEN
                    956: *
                    957: *              Determine the rotations which would annihilate the bulge
                    958: *              which has in theory just been created
                    959: *
                    960:                IF( I+K-KA1.GT.0 .AND. I+K.LT.M ) THEN
                    961: *
                    962: *                 generate rotation to annihilate a(i+k-ka-1,i)
                    963: *
                    964:                   CALL DLARTG( AB( K+1, I ), RA1, WORK( N+I+K-KA ),
                    965:      $                         WORK( I+K-KA ), RA )
                    966: *
                    967: *                 create nonzero element a(i+k-ka-1,i+k) outside the
                    968: *                 band and store it in WORK(m-kb+i+k)
                    969: *
                    970:                   T = -BB( KB1-K, I+K )*RA1
                    971:                   WORK( M-KB+I+K ) = WORK( N+I+K-KA )*T -
                    972:      $                               WORK( I+K-KA )*AB( 1, I+K )
                    973:                   AB( 1, I+K ) = WORK( I+K-KA )*T +
                    974:      $                           WORK( N+I+K-KA )*AB( 1, I+K )
                    975:                   RA1 = RA
                    976:                END IF
                    977:             END IF
                    978:             J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
                    979:             NR = ( J2+KA-1 ) / KA1
                    980:             J1 = J2 - ( NR-1 )*KA1
                    981:             IF( UPDATE ) THEN
                    982:                J2T = MIN( J2, I-2*KA+K-1 )
                    983:             ELSE
                    984:                J2T = J2
                    985:             END IF
                    986:             NRT = ( J2T+KA-1 ) / KA1
                    987:             DO 570 J = J1, J2T, KA1
                    988: *
                    989: *              create nonzero element a(j-1,j+ka) outside the band
                    990: *              and store it in WORK(j)
                    991: *
                    992:                WORK( J ) = WORK( J )*AB( 1, J+KA-1 )
                    993:                AB( 1, J+KA-1 ) = WORK( N+J )*AB( 1, J+KA-1 )
                    994:   570       CONTINUE
                    995: *
                    996: *           generate rotations in 1st set to annihilate elements which
                    997: *           have been created outside the band
                    998: *
                    999:             IF( NRT.GT.0 )
                   1000:      $         CALL DLARGV( NRT, AB( 1, J1+KA ), INCA, WORK( J1 ), KA1,
                   1001:      $                      WORK( N+J1 ), KA1 )
                   1002:             IF( NR.GT.0 ) THEN
                   1003: *
                   1004: *              apply rotations in 1st set from the left
                   1005: *
                   1006:                DO 580 L = 1, KA - 1
                   1007:                   CALL DLARTV( NR, AB( KA1-L, J1+L ), INCA,
                   1008:      $                         AB( KA-L, J1+L ), INCA, WORK( N+J1 ),
                   1009:      $                         WORK( J1 ), KA1 )
                   1010:   580          CONTINUE
                   1011: *
                   1012: *              apply rotations in 1st set from both sides to diagonal
                   1013: *              blocks
                   1014: *
                   1015:                CALL DLAR2V( NR, AB( KA1, J1 ), AB( KA1, J1-1 ),
                   1016:      $                      AB( KA, J1 ), INCA, WORK( N+J1 ),
                   1017:      $                      WORK( J1 ), KA1 )
                   1018: *
                   1019:             END IF
                   1020: *
                   1021: *           start applying rotations in 1st set from the right
                   1022: *
                   1023:             DO 590 L = KA - 1, KB - K + 1, -1
                   1024:                NRT = ( J2+L-1 ) / KA1
                   1025:                J1T = J2 - ( NRT-1 )*KA1
                   1026:                IF( NRT.GT.0 )
                   1027:      $            CALL DLARTV( NRT, AB( L, J1T ), INCA,
                   1028:      $                         AB( L+1, J1T-1 ), INCA, WORK( N+J1T ),
                   1029:      $                         WORK( J1T ), KA1 )
                   1030:   590       CONTINUE
                   1031: *
                   1032:             IF( WANTX ) THEN
                   1033: *
                   1034: *              post-multiply X by product of rotations in 1st set
                   1035: *
                   1036:                DO 600 J = J1, J2, KA1
                   1037:                   CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
                   1038:      $                       WORK( N+J ), WORK( J ) )
                   1039:   600          CONTINUE
                   1040:             END IF
                   1041:   610    CONTINUE
                   1042: *
                   1043:          IF( UPDATE ) THEN
                   1044:             IF( I2.GT.0 .AND. KBT.GT.0 ) THEN
                   1045: *
                   1046: *              create nonzero element a(i+kbt-ka-1,i+kbt) outside the
                   1047: *              band and store it in WORK(m-kb+i+kbt)
                   1048: *
                   1049:                WORK( M-KB+I+KBT ) = -BB( KB1-KBT, I+KBT )*RA1
                   1050:             END IF
                   1051:          END IF
                   1052: *
                   1053:          DO 650 K = KB, 1, -1
                   1054:             IF( UPDATE ) THEN
                   1055:                J2 = I + K + 1 - MAX( 2, K+I0-M )*KA1
                   1056:             ELSE
                   1057:                J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
                   1058:             END IF
                   1059: *
                   1060: *           finish applying rotations in 2nd set from the right
                   1061: *
                   1062:             DO 620 L = KB - K, 1, -1
                   1063:                NRT = ( J2+KA+L-1 ) / KA1
                   1064:                J1T = J2 - ( NRT-1 )*KA1
                   1065:                IF( NRT.GT.0 )
                   1066:      $            CALL DLARTV( NRT, AB( L, J1T+KA ), INCA,
                   1067:      $                         AB( L+1, J1T+KA-1 ), INCA,
                   1068:      $                         WORK( N+M-KB+J1T+KA ),
                   1069:      $                         WORK( M-KB+J1T+KA ), KA1 )
                   1070:   620       CONTINUE
                   1071:             NR = ( J2+KA-1 ) / KA1
                   1072:             J1 = J2 - ( NR-1 )*KA1
                   1073:             DO 630 J = J1, J2, KA1
                   1074:                WORK( M-KB+J ) = WORK( M-KB+J+KA )
                   1075:                WORK( N+M-KB+J ) = WORK( N+M-KB+J+KA )
                   1076:   630       CONTINUE
                   1077:             DO 640 J = J1, J2, KA1
                   1078: *
                   1079: *              create nonzero element a(j-1,j+ka) outside the band
                   1080: *              and store it in WORK(m-kb+j)
                   1081: *
                   1082:                WORK( M-KB+J ) = WORK( M-KB+J )*AB( 1, J+KA-1 )
                   1083:                AB( 1, J+KA-1 ) = WORK( N+M-KB+J )*AB( 1, J+KA-1 )
                   1084:   640       CONTINUE
                   1085:             IF( UPDATE ) THEN
                   1086:                IF( I+K.GT.KA1 .AND. K.LE.KBT )
                   1087:      $            WORK( M-KB+I+K-KA ) = WORK( M-KB+I+K )
                   1088:             END IF
                   1089:   650    CONTINUE
                   1090: *
                   1091:          DO 690 K = KB, 1, -1
                   1092:             J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
                   1093:             NR = ( J2+KA-1 ) / KA1
                   1094:             J1 = J2 - ( NR-1 )*KA1
                   1095:             IF( NR.GT.0 ) THEN
                   1096: *
                   1097: *              generate rotations in 2nd set to annihilate elements
                   1098: *              which have been created outside the band
                   1099: *
                   1100:                CALL DLARGV( NR, AB( 1, J1+KA ), INCA, WORK( M-KB+J1 ),
                   1101:      $                      KA1, WORK( N+M-KB+J1 ), KA1 )
                   1102: *
                   1103: *              apply rotations in 2nd set from the left
                   1104: *
                   1105:                DO 660 L = 1, KA - 1
                   1106:                   CALL DLARTV( NR, AB( KA1-L, J1+L ), INCA,
                   1107:      $                         AB( KA-L, J1+L ), INCA,
                   1108:      $                         WORK( N+M-KB+J1 ), WORK( M-KB+J1 ), KA1 )
                   1109:   660          CONTINUE
                   1110: *
                   1111: *              apply rotations in 2nd set from both sides to diagonal
                   1112: *              blocks
                   1113: *
                   1114:                CALL DLAR2V( NR, AB( KA1, J1 ), AB( KA1, J1-1 ),
                   1115:      $                      AB( KA, J1 ), INCA, WORK( N+M-KB+J1 ),
                   1116:      $                      WORK( M-KB+J1 ), KA1 )
                   1117: *
                   1118:             END IF
                   1119: *
                   1120: *           start applying rotations in 2nd set from the right
                   1121: *
                   1122:             DO 670 L = KA - 1, KB - K + 1, -1
                   1123:                NRT = ( J2+L-1 ) / KA1
                   1124:                J1T = J2 - ( NRT-1 )*KA1
                   1125:                IF( NRT.GT.0 )
                   1126:      $            CALL DLARTV( NRT, AB( L, J1T ), INCA,
                   1127:      $                         AB( L+1, J1T-1 ), INCA,
                   1128:      $                         WORK( N+M-KB+J1T ), WORK( M-KB+J1T ),
                   1129:      $                         KA1 )
                   1130:   670       CONTINUE
                   1131: *
                   1132:             IF( WANTX ) THEN
                   1133: *
                   1134: *              post-multiply X by product of rotations in 2nd set
                   1135: *
                   1136:                DO 680 J = J1, J2, KA1
                   1137:                   CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
                   1138:      $                       WORK( N+M-KB+J ), WORK( M-KB+J ) )
                   1139:   680          CONTINUE
                   1140:             END IF
                   1141:   690    CONTINUE
                   1142: *
                   1143:          DO 710 K = 1, KB - 1
                   1144:             J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
                   1145: *
                   1146: *           finish applying rotations in 1st set from the right
                   1147: *
                   1148:             DO 700 L = KB - K, 1, -1
                   1149:                NRT = ( J2+L-1 ) / KA1
                   1150:                J1T = J2 - ( NRT-1 )*KA1
                   1151:                IF( NRT.GT.0 )
                   1152:      $            CALL DLARTV( NRT, AB( L, J1T ), INCA,
                   1153:      $                         AB( L+1, J1T-1 ), INCA, WORK( N+J1T ),
                   1154:      $                         WORK( J1T ), KA1 )
                   1155:   700       CONTINUE
                   1156:   710    CONTINUE
                   1157: *
                   1158:          IF( KB.GT.1 ) THEN
                   1159:             DO 720 J = 2, MIN( I+KB, M ) - 2*KA - 1
                   1160:                WORK( N+J ) = WORK( N+J+KA )
                   1161:                WORK( J ) = WORK( J+KA )
                   1162:   720       CONTINUE
                   1163:          END IF
                   1164: *
                   1165:       ELSE
                   1166: *
                   1167: *        Transform A, working with the lower triangle
                   1168: *
                   1169:          IF( UPDATE ) THEN
                   1170: *
                   1171: *           Form  inv(S(i))**T * A * inv(S(i))
                   1172: *
                   1173:             BII = BB( 1, I )
                   1174:             DO 730 J = I1, I
                   1175:                AB( I-J+1, J ) = AB( I-J+1, J ) / BII
                   1176:   730       CONTINUE
                   1177:             DO 740 J = I, MIN( N, I+KA )
                   1178:                AB( J-I+1, I ) = AB( J-I+1, I ) / BII
                   1179:   740       CONTINUE
                   1180:             DO 770 K = I + 1, I + KBT
                   1181:                DO 750 J = K, I + KBT
                   1182:                   AB( J-K+1, K ) = AB( J-K+1, K ) -
                   1183:      $                             BB( J-I+1, I )*AB( K-I+1, I ) -
                   1184:      $                             BB( K-I+1, I )*AB( J-I+1, I ) +
                   1185:      $                             AB( 1, I )*BB( J-I+1, I )*
                   1186:      $                             BB( K-I+1, I )
                   1187:   750          CONTINUE
                   1188:                DO 760 J = I + KBT + 1, MIN( N, I+KA )
                   1189:                   AB( J-K+1, K ) = AB( J-K+1, K ) -
                   1190:      $                             BB( K-I+1, I )*AB( J-I+1, I )
                   1191:   760          CONTINUE
                   1192:   770       CONTINUE
                   1193:             DO 790 J = I1, I
                   1194:                DO 780 K = I + 1, MIN( J+KA, I+KBT )
                   1195:                   AB( K-J+1, J ) = AB( K-J+1, J ) -
                   1196:      $                             BB( K-I+1, I )*AB( I-J+1, J )
                   1197:   780          CONTINUE
                   1198:   790       CONTINUE
                   1199: *
                   1200:             IF( WANTX ) THEN
                   1201: *
                   1202: *              post-multiply X by inv(S(i))
                   1203: *
                   1204:                CALL DSCAL( NX, ONE / BII, X( 1, I ), 1 )
                   1205:                IF( KBT.GT.0 )
                   1206:      $            CALL DGER( NX, KBT, -ONE, X( 1, I ), 1, BB( 2, I ), 1,
                   1207:      $                       X( 1, I+1 ), LDX )
                   1208:             END IF
                   1209: *
                   1210: *           store a(i,i1) in RA1 for use in next loop over K
                   1211: *
                   1212:             RA1 = AB( I-I1+1, I1 )
                   1213:          END IF
                   1214: *
                   1215: *        Generate and apply vectors of rotations to chase all the
                   1216: *        existing bulges KA positions up toward the top of the band
                   1217: *
                   1218:          DO 840 K = 1, KB - 1
                   1219:             IF( UPDATE ) THEN
                   1220: *
                   1221: *              Determine the rotations which would annihilate the bulge
                   1222: *              which has in theory just been created
                   1223: *
                   1224:                IF( I+K-KA1.GT.0 .AND. I+K.LT.M ) THEN
                   1225: *
                   1226: *                 generate rotation to annihilate a(i,i+k-ka-1)
                   1227: *
                   1228:                   CALL DLARTG( AB( KA1-K, I+K-KA ), RA1,
                   1229:      $                         WORK( N+I+K-KA ), WORK( I+K-KA ), RA )
                   1230: *
                   1231: *                 create nonzero element a(i+k,i+k-ka-1) outside the
                   1232: *                 band and store it in WORK(m-kb+i+k)
                   1233: *
                   1234:                   T = -BB( K+1, I )*RA1
                   1235:                   WORK( M-KB+I+K ) = WORK( N+I+K-KA )*T -
                   1236:      $                               WORK( I+K-KA )*AB( KA1, I+K-KA )
                   1237:                   AB( KA1, I+K-KA ) = WORK( I+K-KA )*T +
                   1238:      $                                WORK( N+I+K-KA )*AB( KA1, I+K-KA )
                   1239:                   RA1 = RA
                   1240:                END IF
                   1241:             END IF
                   1242:             J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
                   1243:             NR = ( J2+KA-1 ) / KA1
                   1244:             J1 = J2 - ( NR-1 )*KA1
                   1245:             IF( UPDATE ) THEN
                   1246:                J2T = MIN( J2, I-2*KA+K-1 )
                   1247:             ELSE
                   1248:                J2T = J2
                   1249:             END IF
                   1250:             NRT = ( J2T+KA-1 ) / KA1
                   1251:             DO 800 J = J1, J2T, KA1
                   1252: *
                   1253: *              create nonzero element a(j+ka,j-1) outside the band
                   1254: *              and store it in WORK(j)
                   1255: *
                   1256:                WORK( J ) = WORK( J )*AB( KA1, J-1 )
                   1257:                AB( KA1, J-1 ) = WORK( N+J )*AB( KA1, J-1 )
                   1258:   800       CONTINUE
                   1259: *
                   1260: *           generate rotations in 1st set to annihilate elements which
                   1261: *           have been created outside the band
                   1262: *
                   1263:             IF( NRT.GT.0 )
                   1264:      $         CALL DLARGV( NRT, AB( KA1, J1 ), INCA, WORK( J1 ), KA1,
                   1265:      $                      WORK( N+J1 ), KA1 )
                   1266:             IF( NR.GT.0 ) THEN
                   1267: *
                   1268: *              apply rotations in 1st set from the right
                   1269: *
                   1270:                DO 810 L = 1, KA - 1
                   1271:                   CALL DLARTV( NR, AB( L+1, J1 ), INCA, AB( L+2, J1-1 ),
                   1272:      $                         INCA, WORK( N+J1 ), WORK( J1 ), KA1 )
                   1273:   810          CONTINUE
                   1274: *
                   1275: *              apply rotations in 1st set from both sides to diagonal
                   1276: *              blocks
                   1277: *
                   1278:                CALL DLAR2V( NR, AB( 1, J1 ), AB( 1, J1-1 ),
                   1279:      $                      AB( 2, J1-1 ), INCA, WORK( N+J1 ),
                   1280:      $                      WORK( J1 ), KA1 )
                   1281: *
                   1282:             END IF
                   1283: *
                   1284: *           start applying rotations in 1st set from the left
                   1285: *
                   1286:             DO 820 L = KA - 1, KB - K + 1, -1
                   1287:                NRT = ( J2+L-1 ) / KA1
                   1288:                J1T = J2 - ( NRT-1 )*KA1
                   1289:                IF( NRT.GT.0 )
                   1290:      $            CALL DLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,
                   1291:      $                         AB( KA1-L, J1T-KA1+L ), INCA,
                   1292:      $                         WORK( N+J1T ), WORK( J1T ), KA1 )
                   1293:   820       CONTINUE
                   1294: *
                   1295:             IF( WANTX ) THEN
                   1296: *
                   1297: *              post-multiply X by product of rotations in 1st set
                   1298: *
                   1299:                DO 830 J = J1, J2, KA1
                   1300:                   CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
                   1301:      $                       WORK( N+J ), WORK( J ) )
                   1302:   830          CONTINUE
                   1303:             END IF
                   1304:   840    CONTINUE
                   1305: *
                   1306:          IF( UPDATE ) THEN
                   1307:             IF( I2.GT.0 .AND. KBT.GT.0 ) THEN
                   1308: *
                   1309: *              create nonzero element a(i+kbt,i+kbt-ka-1) outside the
                   1310: *              band and store it in WORK(m-kb+i+kbt)
                   1311: *
                   1312:                WORK( M-KB+I+KBT ) = -BB( KBT+1, I )*RA1
                   1313:             END IF
                   1314:          END IF
                   1315: *
                   1316:          DO 880 K = KB, 1, -1
                   1317:             IF( UPDATE ) THEN
                   1318:                J2 = I + K + 1 - MAX( 2, K+I0-M )*KA1
                   1319:             ELSE
                   1320:                J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
                   1321:             END IF
                   1322: *
                   1323: *           finish applying rotations in 2nd set from the left
                   1324: *
                   1325:             DO 850 L = KB - K, 1, -1
                   1326:                NRT = ( J2+KA+L-1 ) / KA1
                   1327:                J1T = J2 - ( NRT-1 )*KA1
                   1328:                IF( NRT.GT.0 )
                   1329:      $            CALL DLARTV( NRT, AB( KA1-L+1, J1T+L-1 ), INCA,
                   1330:      $                         AB( KA1-L, J1T+L-1 ), INCA,
                   1331:      $                         WORK( N+M-KB+J1T+KA ),
                   1332:      $                         WORK( M-KB+J1T+KA ), KA1 )
                   1333:   850       CONTINUE
                   1334:             NR = ( J2+KA-1 ) / KA1
                   1335:             J1 = J2 - ( NR-1 )*KA1
                   1336:             DO 860 J = J1, J2, KA1
                   1337:                WORK( M-KB+J ) = WORK( M-KB+J+KA )
                   1338:                WORK( N+M-KB+J ) = WORK( N+M-KB+J+KA )
                   1339:   860       CONTINUE
                   1340:             DO 870 J = J1, J2, KA1
                   1341: *
                   1342: *              create nonzero element a(j+ka,j-1) outside the band
                   1343: *              and store it in WORK(m-kb+j)
                   1344: *
                   1345:                WORK( M-KB+J ) = WORK( M-KB+J )*AB( KA1, J-1 )
                   1346:                AB( KA1, J-1 ) = WORK( N+M-KB+J )*AB( KA1, J-1 )
                   1347:   870       CONTINUE
                   1348:             IF( UPDATE ) THEN
                   1349:                IF( I+K.GT.KA1 .AND. K.LE.KBT )
                   1350:      $            WORK( M-KB+I+K-KA ) = WORK( M-KB+I+K )
                   1351:             END IF
                   1352:   880    CONTINUE
                   1353: *
                   1354:          DO 920 K = KB, 1, -1
                   1355:             J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
                   1356:             NR = ( J2+KA-1 ) / KA1
                   1357:             J1 = J2 - ( NR-1 )*KA1
                   1358:             IF( NR.GT.0 ) THEN
                   1359: *
                   1360: *              generate rotations in 2nd set to annihilate elements
                   1361: *              which have been created outside the band
                   1362: *
                   1363:                CALL DLARGV( NR, AB( KA1, J1 ), INCA, WORK( M-KB+J1 ),
                   1364:      $                      KA1, WORK( N+M-KB+J1 ), KA1 )
                   1365: *
                   1366: *              apply rotations in 2nd set from the right
                   1367: *
                   1368:                DO 890 L = 1, KA - 1
                   1369:                   CALL DLARTV( NR, AB( L+1, J1 ), INCA, AB( L+2, J1-1 ),
                   1370:      $                         INCA, WORK( N+M-KB+J1 ), WORK( M-KB+J1 ),
                   1371:      $                         KA1 )
                   1372:   890          CONTINUE
                   1373: *
                   1374: *              apply rotations in 2nd set from both sides to diagonal
                   1375: *              blocks
                   1376: *
                   1377:                CALL DLAR2V( NR, AB( 1, J1 ), AB( 1, J1-1 ),
                   1378:      $                      AB( 2, J1-1 ), INCA, WORK( N+M-KB+J1 ),
                   1379:      $                      WORK( M-KB+J1 ), KA1 )
                   1380: *
                   1381:             END IF
                   1382: *
                   1383: *           start applying rotations in 2nd set from the left
                   1384: *
                   1385:             DO 900 L = KA - 1, KB - K + 1, -1
                   1386:                NRT = ( J2+L-1 ) / KA1
                   1387:                J1T = J2 - ( NRT-1 )*KA1
                   1388:                IF( NRT.GT.0 )
                   1389:      $            CALL DLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,
                   1390:      $                         AB( KA1-L, J1T-KA1+L ), INCA,
                   1391:      $                         WORK( N+M-KB+J1T ), WORK( M-KB+J1T ),
                   1392:      $                         KA1 )
                   1393:   900       CONTINUE
                   1394: *
                   1395:             IF( WANTX ) THEN
                   1396: *
                   1397: *              post-multiply X by product of rotations in 2nd set
                   1398: *
                   1399:                DO 910 J = J1, J2, KA1
                   1400:                   CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
                   1401:      $                       WORK( N+M-KB+J ), WORK( M-KB+J ) )
                   1402:   910          CONTINUE
                   1403:             END IF
                   1404:   920    CONTINUE
                   1405: *
                   1406:          DO 940 K = 1, KB - 1
                   1407:             J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
                   1408: *
                   1409: *           finish applying rotations in 1st set from the left
                   1410: *
                   1411:             DO 930 L = KB - K, 1, -1
                   1412:                NRT = ( J2+L-1 ) / KA1
                   1413:                J1T = J2 - ( NRT-1 )*KA1
                   1414:                IF( NRT.GT.0 )
                   1415:      $            CALL DLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,
                   1416:      $                         AB( KA1-L, J1T-KA1+L ), INCA,
                   1417:      $                         WORK( N+J1T ), WORK( J1T ), KA1 )
                   1418:   930       CONTINUE
                   1419:   940    CONTINUE
                   1420: *
                   1421:          IF( KB.GT.1 ) THEN
                   1422:             DO 950 J = 2, MIN( I+KB, M ) - 2*KA - 1
                   1423:                WORK( N+J ) = WORK( N+J+KA )
                   1424:                WORK( J ) = WORK( J+KA )
                   1425:   950       CONTINUE
                   1426:          END IF
                   1427: *
                   1428:       END IF
                   1429: *
                   1430:       GO TO 490
                   1431: *
                   1432: *     End of DSBGST
                   1433: *
                   1434:       END

CVSweb interface <joel.bertrand@systella.fr>