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

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

CVSweb interface <joel.bertrand@systella.fr>