1       SUBROUTINE ZHBTRD( VECT, UPLO, N, KD, AB, LDAB, D, E, Q, LDQ,
  2      $                   WORK, INFO )
  3 *
  4 *  -- LAPACK routine (version 3.2) --
  5 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  6 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  7 *     November 2006
  8 *
  9 *     .. Scalar Arguments ..
 10       CHARACTER          UPLO, VECT
 11       INTEGER            INFO, KD, LDAB, LDQ, N
 12 *     ..
 13 *     .. Array Arguments ..
 14       DOUBLE PRECISION   D( * ), E( * )
 15       COMPLEX*16         AB( LDAB, * ), Q( LDQ, * ), WORK( * )
 16 *     ..
 17 *
 18 *  Purpose
 19 *  =======
 20 *
 21 *  ZHBTRD reduces a complex Hermitian band matrix A to real symmetric
 22 *  tridiagonal form T by a unitary similarity transformation:
 23 *  Q**H * A * Q = T.
 24 *
 25 *  Arguments
 26 *  =========
 27 *
 28 *  VECT    (input) CHARACTER*1
 29 *          = 'N':  do not form Q;
 30 *          = 'V':  form Q;
 31 *          = 'U':  update a matrix X, by forming X*Q.
 32 *
 33 *  UPLO    (input) CHARACTER*1
 34 *          = 'U':  Upper triangle of A is stored;
 35 *          = 'L':  Lower triangle of A is stored.
 36 *
 37 *  N       (input) INTEGER
 38 *          The order of the matrix A.  N >= 0.
 39 *
 40 *  KD      (input) INTEGER
 41 *          The number of superdiagonals of the matrix A if UPLO = 'U',
 42 *          or the number of subdiagonals if UPLO = 'L'.  KD >= 0.
 43 *
 44 *  AB      (input/output) COMPLEX*16 array, dimension (LDAB,N)
 45 *          On entry, the upper or lower triangle of the Hermitian band
 46 *          matrix A, stored in the first KD+1 rows of the array.  The
 47 *          j-th column of A is stored in the j-th column of the array AB
 48 *          as follows:
 49 *          if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
 50 *          if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).
 51 *          On exit, the diagonal elements of AB are overwritten by the
 52 *          diagonal elements of the tridiagonal matrix T; if KD > 0, the
 53 *          elements on the first superdiagonal (if UPLO = 'U') or the
 54 *          first subdiagonal (if UPLO = 'L') are overwritten by the
 55 *          off-diagonal elements of T; the rest of AB is overwritten by
 56 *          values generated during the reduction.
 57 *
 58 *  LDAB    (input) INTEGER
 59 *          The leading dimension of the array AB.  LDAB >= KD+1.
 60 *
 61 *  D       (output) DOUBLE PRECISION array, dimension (N)
 62 *          The diagonal elements of the tridiagonal matrix T.
 63 *
 64 *  E       (output) DOUBLE PRECISION array, dimension (N-1)
 65 *          The off-diagonal elements of the tridiagonal matrix T:
 66 *          E(i) = T(i,i+1) if UPLO = 'U'; E(i) = T(i+1,i) if UPLO = 'L'.
 67 *
 68 *  Q       (input/output) COMPLEX*16 array, dimension (LDQ,N)
 69 *          On entry, if VECT = 'U', then Q must contain an N-by-N
 70 *          matrix X; if VECT = 'N' or 'V', then Q need not be set.
 71 *
 72 *          On exit:
 73 *          if VECT = 'V', Q contains the N-by-N unitary matrix Q;
 74 *          if VECT = 'U', Q contains the product X*Q;
 75 *          if VECT = 'N', the array Q is not referenced.
 76 *
 77 *  LDQ     (input) INTEGER
 78 *          The leading dimension of the array Q.
 79 *          LDQ >= 1, and LDQ >= N if VECT = 'V' or 'U'.
 80 *
 81 *  WORK    (workspace) COMPLEX*16 array, dimension (N)
 82 *
 83 *  INFO    (output) INTEGER
 84 *          = 0:  successful exit
 85 *          < 0:  if INFO = -i, the i-th argument had an illegal value
 86 *
 87 *  Further Details
 88 *  ===============
 89 *
 90 *  Modified by Linda Kaufman, Bell Labs.
 91 *
 92 *  =====================================================================
 93 *
 94 *     .. Parameters ..
 95       DOUBLE PRECISION   ZERO
 96       PARAMETER          ( ZERO = 0.0D+0 )
 97       COMPLEX*16         CZERO, CONE
 98       PARAMETER          ( CZERO = ( 0.0D+00.0D+0 ),
 99      $                   CONE = ( 1.0D+00.0D+0 ) )
100 *     ..
101 *     .. Local Scalars ..
102       LOGICAL            INITQ, UPPER, WANTQ
103       INTEGER            I, I2, IBL, INCA, INCX, IQAEND, IQB, IQEND, J,
104      $                   J1, J1END, J1INC, J2, JEND, JIN, JINC, K, KD1,
105      $                   KDM1, KDN, L, LAST, LEND, NQ, NR, NRT
106       DOUBLE PRECISION   ABST
107       COMPLEX*16         T, TEMP
108 *     ..
109 *     .. External Subroutines ..
110       EXTERNAL           XERBLA, ZLACGV, ZLAR2V, ZLARGV, ZLARTG, ZLARTV,
111      $                   ZLASET, ZROT, ZSCAL
112 *     ..
113 *     .. Intrinsic Functions ..
114       INTRINSIC          ABSDBLEDCONJGMAXMIN
115 *     ..
116 *     .. External Functions ..
117       LOGICAL            LSAME
118       EXTERNAL           LSAME
119 *     ..
120 *     .. Executable Statements ..
121 *
122 *     Test the input parameters
123 *
124       INITQ = LSAME( VECT, 'V' )
125       WANTQ = INITQ .OR. LSAME( VECT, 'U' )
126       UPPER = LSAME( UPLO, 'U' )
127       KD1 = KD + 1
128       KDM1 = KD - 1
129       INCX = LDAB - 1
130       IQEND = 1
131 *
132       INFO = 0
133       IF.NOT.WANTQ .AND. .NOT.LSAME( VECT, 'N' ) ) THEN
134          INFO = -1
135       ELSE IF.NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
136          INFO = -2
137       ELSE IF( N.LT.0 ) THEN
138          INFO = -3
139       ELSE IF( KD.LT.0 ) THEN
140          INFO = -4
141       ELSE IF( LDAB.LT.KD1 ) THEN
142          INFO = -6
143       ELSE IF( LDQ.LT.MAX1, N ) .AND. WANTQ ) THEN
144          INFO = -10
145       END IF
146       IF( INFO.NE.0 ) THEN
147          CALL XERBLA( 'ZHBTRD'-INFO )
148          RETURN
149       END IF
150 *
151 *     Quick return if possible
152 *
153       IF( N.EQ.0 )
154      $   RETURN
155 *
156 *     Initialize Q to the unit matrix, if needed
157 *
158       IF( INITQ )
159      $   CALL ZLASET( 'Full', N, N, CZERO, CONE, Q, LDQ )
160 *
161 *     Wherever possible, plane rotations are generated and applied in
162 *     vector operations of length NR over the index set J1:J2:KD1.
163 *
164 *     The real cosines and complex sines of the plane rotations are
165 *     stored in the arrays D and WORK.
166 *
167       INCA = KD1*LDAB
168       KDN = MIN( N-1, KD )
169       IF( UPPER ) THEN
170 *
171          IF( KD.GT.1 ) THEN
172 *
173 *           Reduce to complex Hermitian tridiagonal form, working with
174 *           the upper triangle
175 *
176             NR = 0
177             J1 = KDN + 2
178             J2 = 1
179 *
180             AB( KD1, 1 ) = DBLE( AB( KD1, 1 ) )
181             DO 90 I = 1, N - 2
182 *
183 *              Reduce i-th row of matrix to tridiagonal form
184 *
185                DO 80 K = KDN + 12-1
186                   J1 = J1 + KDN
187                   J2 = J2 + KDN
188 *
189                   IF( NR.GT.0 ) THEN
190 *
191 *                    generate plane rotations to annihilate nonzero
192 *                    elements which have been created outside the band
193 *
194                      CALL ZLARGV( NR, AB( 1, J1-1 ), INCA, WORK( J1 ),
195      $                            KD1, D( J1 ), KD1 )
196 *
197 *                    apply rotations from the right
198 *
199 *
200 *                    Dependent on the the number of diagonals either
201 *                    ZLARTV or ZROT is used
202 *
203                      IF( NR.GE.2*KD-1 ) THEN
204                         DO 10 L = 1, KD - 1
205                            CALL ZLARTV( NR, AB( L+1, J1-1 ), INCA,
206      $                                  AB( L, J1 ), INCA, D( J1 ),
207      $                                  WORK( J1 ), KD1 )
208    10                   CONTINUE
209 *
210                      ELSE
211                         JEND = J1 + ( NR-1 )*KD1
212                         DO 20 JINC = J1, JEND, KD1
213                            CALL ZROT( KDM1, AB( 2, JINC-1 ), 1,
214      $                                AB( 1, JINC ), 1, D( JINC ),
215      $                                WORK( JINC ) )
216    20                   CONTINUE
217                      END IF
218                   END IF
219 *
220 *
221                   IF( K.GT.2 ) THEN
222                      IF( K.LE.N-I+1 ) THEN
223 *
224 *                       generate plane rotation to annihilate a(i,i+k-1)
225 *                       within the band
226 *
227                         CALL ZLARTG( AB( KD-K+3, I+K-2 ),
228      $                               AB( KD-K+2, I+K-1 ), D( I+K-1 ),
229      $                               WORK( I+K-1 ), TEMP )
230                         AB( KD-K+3, I+K-2 ) = TEMP
231 *
232 *                       apply rotation from the right
233 *
234                         CALL ZROT( K-3, AB( KD-K+4, I+K-2 ), 1,
235      $                             AB( KD-K+3, I+K-1 ), 1, D( I+K-1 ),
236      $                             WORK( I+K-1 ) )
237                      END IF
238                      NR = NR + 1
239                      J1 = J1 - KDN - 1
240                   END IF
241 *
242 *                 apply plane rotations from both sides to diagonal
243 *                 blocks
244 *
245                   IF( NR.GT.0 )
246      $               CALL ZLAR2V( NR, AB( KD1, J1-1 ), AB( KD1, J1 ),
247      $                            AB( KD, J1 ), INCA, D( J1 ),
248      $                            WORK( J1 ), KD1 )
249 *
250 *                 apply plane rotations from the left
251 *
252                   IF( NR.GT.0 ) THEN
253                      CALL ZLACGV( NR, WORK( J1 ), KD1 )
254                      IF2*KD-1.LT.NR ) THEN
255 *
256 *                    Dependent on the the number of diagonals either
257 *                    ZLARTV or ZROT is used
258 *
259                         DO 30 L = 1, KD - 1
260                            IF( J2+L.GT.N ) THEN
261                               NRT = NR - 1
262                            ELSE
263                               NRT = NR
264                            END IF
265                            IF( NRT.GT.0 )
266      $                        CALL ZLARTV( NRT, AB( KD-L, J1+L ), INCA,
267      $                                     AB( KD-L+1, J1+L ), INCA,
268      $                                     D( J1 ), WORK( J1 ), KD1 )
269    30                   CONTINUE
270                      ELSE
271                         J1END = J1 + KD1*( NR-2 )
272                         IF( J1END.GE.J1 ) THEN
273                            DO 40 JIN = J1, J1END, KD1
274                               CALL ZROT( KD-1, AB( KD-1, JIN+1 ), INCX,
275      $                                   AB( KD, JIN+1 ), INCX,
276      $                                   D( JIN ), WORK( JIN ) )
277    40                      CONTINUE
278                         END IF
279                         LEND = MIN( KDM1, N-J2 )
280                         LAST = J1END + KD1
281                         IF( LEND.GT.0 )
282      $                     CALL ZROT( LEND, AB( KD-1, LAST+1 ), INCX,
283      $                                AB( KD, LAST+1 ), INCX, D( LAST ),
284      $                                WORK( LAST ) )
285                      END IF
286                   END IF
287 *
288                   IF( WANTQ ) THEN
289 *
290 *                    accumulate product of plane rotations in Q
291 *
292                      IF( INITQ ) THEN
293 *
294 *                 take advantage of the fact that Q was
295 *                 initially the Identity matrix
296 *
297                         IQEND = MAX( IQEND, J2 )
298                         I2 = MAX0, K-3 )
299                         IQAEND = 1 + I*KD
300                         IF( K.EQ.2 )
301      $                     IQAEND = IQAEND + KD
302                         IQAEND = MIN( IQAEND, IQEND )
303                         DO 50 J = J1, J2, KD1
304                            IBL = I - I2 / KDM1
305                            I2 = I2 + 1
306                            IQB = MAX1, J-IBL )
307                            NQ = 1 + IQAEND - IQB
308                            IQAEND = MIN( IQAEND+KD, IQEND )
309                            CALL ZROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
310      $                                1, D( J ), DCONJG( WORK( J ) ) )
311    50                   CONTINUE
312                      ELSE
313 *
314                         DO 60 J = J1, J2, KD1
315                            CALL ZROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
316      $                                D( J ), DCONJG( WORK( J ) ) )
317    60                   CONTINUE
318                      END IF
319 *
320                   END IF
321 *
322                   IF( J2+KDN.GT.N ) THEN
323 *
324 *                    adjust J2 to keep within the bounds of the matrix
325 *
326                      NR = NR - 1
327                      J2 = J2 - KDN - 1
328                   END IF
329 *
330                   DO 70 J = J1, J2, KD1
331 *
332 *                    create nonzero element a(j-1,j+kd) outside the band
333 *                    and store it in WORK
334 *
335                      WORK( J+KD ) = WORK( J )*AB( 1, J+KD )
336                      AB( 1, J+KD ) = D( J )*AB( 1, J+KD )
337    70             CONTINUE
338    80          CONTINUE
339    90       CONTINUE
340          END IF
341 *
342          IF( KD.GT.0 ) THEN
343 *
344 *           make off-diagonal elements real and copy them to E
345 *
346             DO 100 I = 1, N - 1
347                T = AB( KD, I+1 )
348                ABST = ABS( T )
349                AB( KD, I+1 ) = ABST
350                E( I ) = ABST
351                IF( ABST.NE.ZERO ) THEN
352                   T = T / ABST
353                ELSE
354                   T = CONE
355                END IF
356                IF( I.LT.N-1 )
357      $            AB( KD, I+2 ) = AB( KD, I+2 )*T
358                IF( WANTQ ) THEN
359                   CALL ZSCAL( N, DCONJG( T ), Q( 1, I+1 ), 1 )
360                END IF
361   100       CONTINUE
362          ELSE
363 *
364 *           set E to zero if original matrix was diagonal
365 *
366             DO 110 I = 1, N - 1
367                E( I ) = ZERO
368   110       CONTINUE
369          END IF
370 *
371 *        copy diagonal elements to D
372 *
373          DO 120 I = 1, N
374             D( I ) = AB( KD1, I )
375   120    CONTINUE
376 *
377       ELSE
378 *
379          IF( KD.GT.1 ) THEN
380 *
381 *           Reduce to complex Hermitian tridiagonal form, working with
382 *           the lower triangle
383 *
384             NR = 0
385             J1 = KDN + 2
386             J2 = 1
387 *
388             AB( 11 ) = DBLE( AB( 11 ) )
389             DO 210 I = 1, N - 2
390 *
391 *              Reduce i-th column of matrix to tridiagonal form
392 *
393                DO 200 K = KDN + 12-1
394                   J1 = J1 + KDN
395                   J2 = J2 + KDN
396 *
397                   IF( NR.GT.0 ) THEN
398 *
399 *                    generate plane rotations to annihilate nonzero
400 *                    elements which have been created outside the band
401 *
402                      CALL ZLARGV( NR, AB( KD1, J1-KD1 ), INCA,
403      $                            WORK( J1 ), KD1, D( J1 ), KD1 )
404 *
405 *                    apply plane rotations from one side
406 *
407 *
408 *                    Dependent on the the number of diagonals either
409 *                    ZLARTV or ZROT is used
410 *
411                      IF( NR.GT.2*KD-1 ) THEN
412                         DO 130 L = 1, KD - 1
413                            CALL ZLARTV( NR, AB( KD1-L, J1-KD1+L ), INCA,
414      $                                  AB( KD1-L+1, J1-KD1+L ), INCA,
415      $                                  D( J1 ), WORK( J1 ), KD1 )
416   130                   CONTINUE
417                      ELSE
418                         JEND = J1 + KD1*( NR-1 )
419                         DO 140 JINC = J1, JEND, KD1
420                            CALL ZROT( KDM1, AB( KD, JINC-KD ), INCX,
421      $                                AB( KD1, JINC-KD ), INCX,
422      $                                D( JINC ), WORK( JINC ) )
423   140                   CONTINUE
424                      END IF
425 *
426                   END IF
427 *
428                   IF( K.GT.2 ) THEN
429                      IF( K.LE.N-I+1 ) THEN
430 *
431 *                       generate plane rotation to annihilate a(i+k-1,i)
432 *                       within the band
433 *
434                         CALL ZLARTG( AB( K-1, I ), AB( K, I ),
435      $                               D( I+K-1 ), WORK( I+K-1 ), TEMP )
436                         AB( K-1, I ) = TEMP
437 *
438 *                       apply rotation from the left
439 *
440                         CALL ZROT( K-3, AB( K-2, I+1 ), LDAB-1,
441      $                             AB( K-1, I+1 ), LDAB-1, D( I+K-1 ),
442      $                             WORK( I+K-1 ) )
443                      END IF
444                      NR = NR + 1
445                      J1 = J1 - KDN - 1
446                   END IF
447 *
448 *                 apply plane rotations from both sides to diagonal
449 *                 blocks
450 *
451                   IF( NR.GT.0 )
452      $               CALL ZLAR2V( NR, AB( 1, J1-1 ), AB( 1, J1 ),
453      $                            AB( 2, J1-1 ), INCA, D( J1 ),
454      $                            WORK( J1 ), KD1 )
455 *
456 *                 apply plane rotations from the right
457 *
458 *
459 *                    Dependent on the the number of diagonals either
460 *                    ZLARTV or ZROT is used
461 *
462                   IF( NR.GT.0 ) THEN
463                      CALL ZLACGV( NR, WORK( J1 ), KD1 )
464                      IF( NR.GT.2*KD-1 ) THEN
465                         DO 150 L = 1, KD - 1
466                            IF( J2+L.GT.N ) THEN
467                               NRT = NR - 1
468                            ELSE
469                               NRT = NR
470                            END IF
471                            IF( NRT.GT.0 )
472      $                        CALL ZLARTV( NRT, AB( L+2, J1-1 ), INCA,
473      $                                     AB( L+1, J1 ), INCA, D( J1 ),
474      $                                     WORK( J1 ), KD1 )
475   150                   CONTINUE
476                      ELSE
477                         J1END = J1 + KD1*( NR-2 )
478                         IF( J1END.GE.J1 ) THEN
479                            DO 160 J1INC = J1, J1END, KD1
480                               CALL ZROT( KDM1, AB( 3, J1INC-1 ), 1,
481      $                                   AB( 2, J1INC ), 1, D( J1INC ),
482      $                                   WORK( J1INC ) )
483   160                      CONTINUE
484                         END IF
485                         LEND = MIN( KDM1, N-J2 )
486                         LAST = J1END + KD1
487                         IF( LEND.GT.0 )
488      $                     CALL ZROT( LEND, AB( 3, LAST-1 ), 1,
489      $                                AB( 2, LAST ), 1, D( LAST ),
490      $                                WORK( LAST ) )
491                      END IF
492                   END IF
493 *
494 *
495 *
496                   IF( WANTQ ) THEN
497 *
498 *                    accumulate product of plane rotations in Q
499 *
500                      IF( INITQ ) THEN
501 *
502 *                 take advantage of the fact that Q was
503 *                 initially the Identity matrix
504 *
505                         IQEND = MAX( IQEND, J2 )
506                         I2 = MAX0, K-3 )
507                         IQAEND = 1 + I*KD
508                         IF( K.EQ.2 )
509      $                     IQAEND = IQAEND + KD
510                         IQAEND = MIN( IQAEND, IQEND )
511                         DO 170 J = J1, J2, KD1
512                            IBL = I - I2 / KDM1
513                            I2 = I2 + 1
514                            IQB = MAX1, J-IBL )
515                            NQ = 1 + IQAEND - IQB
516                            IQAEND = MIN( IQAEND+KD, IQEND )
517                            CALL ZROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
518      $                                1, D( J ), WORK( J ) )
519   170                   CONTINUE
520                      ELSE
521 *
522                         DO 180 J = J1, J2, KD1
523                            CALL ZROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
524      $                                D( J ), WORK( J ) )
525   180                   CONTINUE
526                      END IF
527                   END IF
528 *
529                   IF( J2+KDN.GT.N ) THEN
530 *
531 *                    adjust J2 to keep within the bounds of the matrix
532 *
533                      NR = NR - 1
534                      J2 = J2 - KDN - 1
535                   END IF
536 *
537                   DO 190 J = J1, J2, KD1
538 *
539 *                    create nonzero element a(j+kd,j-1) outside the
540 *                    band and store it in WORK
541 *
542                      WORK( J+KD ) = WORK( J )*AB( KD1, J )
543                      AB( KD1, J ) = D( J )*AB( KD1, J )
544   190             CONTINUE
545   200          CONTINUE
546   210       CONTINUE
547          END IF
548 *
549          IF( KD.GT.0 ) THEN
550 *
551 *           make off-diagonal elements real and copy them to E
552 *
553             DO 220 I = 1, N - 1
554                T = AB( 2, I )
555                ABST = ABS( T )
556                AB( 2, I ) = ABST
557                E( I ) = ABST
558                IF( ABST.NE.ZERO ) THEN
559                   T = T / ABST
560                ELSE
561                   T = CONE
562                END IF
563                IF( I.LT.N-1 )
564      $            AB( 2, I+1 ) = AB( 2, I+1 )*T
565                IF( WANTQ ) THEN
566                   CALL ZSCAL( N, T, Q( 1, I+1 ), 1 )
567                END IF
568   220       CONTINUE
569          ELSE
570 *
571 *           set E to zero if original matrix was diagonal
572 *
573             DO 230 I = 1, N - 1
574                E( I ) = ZERO
575   230       CONTINUE
576          END IF
577 *
578 *        copy diagonal elements to D
579 *
580          DO 240 I = 1, N
581             D( I ) = AB( 1, I )
582   240    CONTINUE
583       END IF
584 *
585       RETURN
586 *
587 *     End of ZHBTRD
588 *
589       END