File:  [local] / rpl / lapack / lapack / dsbgst.f
Revision 1.6: download - view: text, annotated - select for diffs - revision graph
Fri Aug 13 21:03:56 2010 UTC (13 years, 9 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_0_19, rpl-4_0_18, HEAD
Patches pour OS/2

    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>