File:  [local] / rpl / lapack / lapack / dsbgst.f
Revision 1.17: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:39:05 2023 UTC (9 months, 1 week ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, rpl-4_1_34, HEAD
Première mise à jour de lapack et blas.

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

CVSweb interface <joel.bertrand@systella.fr>