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

CVSweb interface <joel.bertrand@systella.fr>