File:  [local] / rpl / lapack / lapack / zhbgst.f
Revision 1.3: download - view: text, annotated - select for diffs - revision graph
Fri Aug 6 15:28:54 2010 UTC (13 years, 9 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Cohérence

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

CVSweb interface <joel.bertrand@systella.fr>