LAPACK 3.3.0

zhbtrd.f

Go to the documentation of this file.
00001       SUBROUTINE ZHBTRD( VECT, UPLO, N, KD, AB, LDAB, D, E, Q, LDQ,
00002      $                   WORK, INFO )
00003 *
00004 *  -- LAPACK routine (version 3.2) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *     November 2006
00008 *
00009 *     .. Scalar Arguments ..
00010       CHARACTER          UPLO, VECT
00011       INTEGER            INFO, KD, LDAB, LDQ, N
00012 *     ..
00013 *     .. Array Arguments ..
00014       DOUBLE PRECISION   D( * ), E( * )
00015       COMPLEX*16         AB( LDAB, * ), Q( LDQ, * ), WORK( * )
00016 *     ..
00017 *
00018 *  Purpose
00019 *  =======
00020 *
00021 *  ZHBTRD reduces a complex Hermitian band matrix A to real symmetric
00022 *  tridiagonal form T by a unitary similarity transformation:
00023 *  Q**H * A * Q = T.
00024 *
00025 *  Arguments
00026 *  =========
00027 *
00028 *  VECT    (input) CHARACTER*1
00029 *          = 'N':  do not form Q;
00030 *          = 'V':  form Q;
00031 *          = 'U':  update a matrix X, by forming X*Q.
00032 *
00033 *  UPLO    (input) CHARACTER*1
00034 *          = 'U':  Upper triangle of A is stored;
00035 *          = 'L':  Lower triangle of A is stored.
00036 *
00037 *  N       (input) INTEGER
00038 *          The order of the matrix A.  N >= 0.
00039 *
00040 *  KD      (input) INTEGER
00041 *          The number of superdiagonals of the matrix A if UPLO = 'U',
00042 *          or the number of subdiagonals if UPLO = 'L'.  KD >= 0.
00043 *
00044 *  AB      (input/output) COMPLEX*16 array, dimension (LDAB,N)
00045 *          On entry, the upper or lower triangle of the Hermitian band
00046 *          matrix A, stored in the first KD+1 rows of the array.  The
00047 *          j-th column of A is stored in the j-th column of the array AB
00048 *          as follows:
00049 *          if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
00050 *          if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).
00051 *          On exit, the diagonal elements of AB are overwritten by the
00052 *          diagonal elements of the tridiagonal matrix T; if KD > 0, the
00053 *          elements on the first superdiagonal (if UPLO = 'U') or the
00054 *          first subdiagonal (if UPLO = 'L') are overwritten by the
00055 *          off-diagonal elements of T; the rest of AB is overwritten by
00056 *          values generated during the reduction.
00057 *
00058 *  LDAB    (input) INTEGER
00059 *          The leading dimension of the array AB.  LDAB >= KD+1.
00060 *
00061 *  D       (output) DOUBLE PRECISION array, dimension (N)
00062 *          The diagonal elements of the tridiagonal matrix T.
00063 *
00064 *  E       (output) DOUBLE PRECISION array, dimension (N-1)
00065 *          The off-diagonal elements of the tridiagonal matrix T:
00066 *          E(i) = T(i,i+1) if UPLO = 'U'; E(i) = T(i+1,i) if UPLO = 'L'.
00067 *
00068 *  Q       (input/output) COMPLEX*16 array, dimension (LDQ,N)
00069 *          On entry, if VECT = 'U', then Q must contain an N-by-N
00070 *          matrix X; if VECT = 'N' or 'V', then Q need not be set.
00071 *
00072 *          On exit:
00073 *          if VECT = 'V', Q contains the N-by-N unitary matrix Q;
00074 *          if VECT = 'U', Q contains the product X*Q;
00075 *          if VECT = 'N', the array Q is not referenced.
00076 *
00077 *  LDQ     (input) INTEGER
00078 *          The leading dimension of the array Q.
00079 *          LDQ >= 1, and LDQ >= N if VECT = 'V' or 'U'.
00080 *
00081 *  WORK    (workspace) COMPLEX*16 array, dimension (N)
00082 *
00083 *  INFO    (output) INTEGER
00084 *          = 0:  successful exit
00085 *          < 0:  if INFO = -i, the i-th argument had an illegal value
00086 *
00087 *  Further Details
00088 *  ===============
00089 *
00090 *  Modified by Linda Kaufman, Bell Labs.
00091 *
00092 *  =====================================================================
00093 *
00094 *     .. Parameters ..
00095       DOUBLE PRECISION   ZERO
00096       PARAMETER          ( ZERO = 0.0D+0 )
00097       COMPLEX*16         CZERO, CONE
00098       PARAMETER          ( CZERO = ( 0.0D+0, 0.0D+0 ),
00099      $                   CONE = ( 1.0D+0, 0.0D+0 ) )
00100 *     ..
00101 *     .. Local Scalars ..
00102       LOGICAL            INITQ, UPPER, WANTQ
00103       INTEGER            I, I2, IBL, INCA, INCX, IQAEND, IQB, IQEND, J,
00104      $                   J1, J1END, J1INC, J2, JEND, JIN, JINC, K, KD1,
00105      $                   KDM1, KDN, L, LAST, LEND, NQ, NR, NRT
00106       DOUBLE PRECISION   ABST
00107       COMPLEX*16         T, TEMP
00108 *     ..
00109 *     .. External Subroutines ..
00110       EXTERNAL           XERBLA, ZLACGV, ZLAR2V, ZLARGV, ZLARTG, ZLARTV,
00111      $                   ZLASET, ZROT, ZSCAL
00112 *     ..
00113 *     .. Intrinsic Functions ..
00114       INTRINSIC          ABS, DBLE, DCONJG, MAX, MIN
00115 *     ..
00116 *     .. External Functions ..
00117       LOGICAL            LSAME
00118       EXTERNAL           LSAME
00119 *     ..
00120 *     .. Executable Statements ..
00121 *
00122 *     Test the input parameters
00123 *
00124       INITQ = LSAME( VECT, 'V' )
00125       WANTQ = INITQ .OR. LSAME( VECT, 'U' )
00126       UPPER = LSAME( UPLO, 'U' )
00127       KD1 = KD + 1
00128       KDM1 = KD - 1
00129       INCX = LDAB - 1
00130       IQEND = 1
00131 *
00132       INFO = 0
00133       IF( .NOT.WANTQ .AND. .NOT.LSAME( VECT, 'N' ) ) THEN
00134          INFO = -1
00135       ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
00136          INFO = -2
00137       ELSE IF( N.LT.0 ) THEN
00138          INFO = -3
00139       ELSE IF( KD.LT.0 ) THEN
00140          INFO = -4
00141       ELSE IF( LDAB.LT.KD1 ) THEN
00142          INFO = -6
00143       ELSE IF( LDQ.LT.MAX( 1, N ) .AND. WANTQ ) THEN
00144          INFO = -10
00145       END IF
00146       IF( INFO.NE.0 ) THEN
00147          CALL XERBLA( 'ZHBTRD', -INFO )
00148          RETURN
00149       END IF
00150 *
00151 *     Quick return if possible
00152 *
00153       IF( N.EQ.0 )
00154      $   RETURN
00155 *
00156 *     Initialize Q to the unit matrix, if needed
00157 *
00158       IF( INITQ )
00159      $   CALL ZLASET( 'Full', N, N, CZERO, CONE, Q, LDQ )
00160 *
00161 *     Wherever possible, plane rotations are generated and applied in
00162 *     vector operations of length NR over the index set J1:J2:KD1.
00163 *
00164 *     The real cosines and complex sines of the plane rotations are
00165 *     stored in the arrays D and WORK.
00166 *
00167       INCA = KD1*LDAB
00168       KDN = MIN( N-1, KD )
00169       IF( UPPER ) THEN
00170 *
00171          IF( KD.GT.1 ) THEN
00172 *
00173 *           Reduce to complex Hermitian tridiagonal form, working with
00174 *           the upper triangle
00175 *
00176             NR = 0
00177             J1 = KDN + 2
00178             J2 = 1
00179 *
00180             AB( KD1, 1 ) = DBLE( AB( KD1, 1 ) )
00181             DO 90 I = 1, N - 2
00182 *
00183 *              Reduce i-th row of matrix to tridiagonal form
00184 *
00185                DO 80 K = KDN + 1, 2, -1
00186                   J1 = J1 + KDN
00187                   J2 = J2 + KDN
00188 *
00189                   IF( NR.GT.0 ) THEN
00190 *
00191 *                    generate plane rotations to annihilate nonzero
00192 *                    elements which have been created outside the band
00193 *
00194                      CALL ZLARGV( NR, AB( 1, J1-1 ), INCA, WORK( J1 ),
00195      $                            KD1, D( J1 ), KD1 )
00196 *
00197 *                    apply rotations from the right
00198 *
00199 *
00200 *                    Dependent on the the number of diagonals either
00201 *                    ZLARTV or ZROT is used
00202 *
00203                      IF( NR.GE.2*KD-1 ) THEN
00204                         DO 10 L = 1, KD - 1
00205                            CALL ZLARTV( NR, AB( L+1, J1-1 ), INCA,
00206      $                                  AB( L, J1 ), INCA, D( J1 ),
00207      $                                  WORK( J1 ), KD1 )
00208    10                   CONTINUE
00209 *
00210                      ELSE
00211                         JEND = J1 + ( NR-1 )*KD1
00212                         DO 20 JINC = J1, JEND, KD1
00213                            CALL ZROT( KDM1, AB( 2, JINC-1 ), 1,
00214      $                                AB( 1, JINC ), 1, D( JINC ),
00215      $                                WORK( JINC ) )
00216    20                   CONTINUE
00217                      END IF
00218                   END IF
00219 *
00220 *
00221                   IF( K.GT.2 ) THEN
00222                      IF( K.LE.N-I+1 ) THEN
00223 *
00224 *                       generate plane rotation to annihilate a(i,i+k-1)
00225 *                       within the band
00226 *
00227                         CALL ZLARTG( AB( KD-K+3, I+K-2 ),
00228      $                               AB( KD-K+2, I+K-1 ), D( I+K-1 ),
00229      $                               WORK( I+K-1 ), TEMP )
00230                         AB( KD-K+3, I+K-2 ) = TEMP
00231 *
00232 *                       apply rotation from the right
00233 *
00234                         CALL ZROT( K-3, AB( KD-K+4, I+K-2 ), 1,
00235      $                             AB( KD-K+3, I+K-1 ), 1, D( I+K-1 ),
00236      $                             WORK( I+K-1 ) )
00237                      END IF
00238                      NR = NR + 1
00239                      J1 = J1 - KDN - 1
00240                   END IF
00241 *
00242 *                 apply plane rotations from both sides to diagonal
00243 *                 blocks
00244 *
00245                   IF( NR.GT.0 )
00246      $               CALL ZLAR2V( NR, AB( KD1, J1-1 ), AB( KD1, J1 ),
00247      $                            AB( KD, J1 ), INCA, D( J1 ),
00248      $                            WORK( J1 ), KD1 )
00249 *
00250 *                 apply plane rotations from the left
00251 *
00252                   IF( NR.GT.0 ) THEN
00253                      CALL ZLACGV( NR, WORK( J1 ), KD1 )
00254                      IF( 2*KD-1.LT.NR ) THEN
00255 *
00256 *                    Dependent on the the number of diagonals either
00257 *                    ZLARTV or ZROT is used
00258 *
00259                         DO 30 L = 1, KD - 1
00260                            IF( J2+L.GT.N ) THEN
00261                               NRT = NR - 1
00262                            ELSE
00263                               NRT = NR
00264                            END IF
00265                            IF( NRT.GT.0 )
00266      $                        CALL ZLARTV( NRT, AB( KD-L, J1+L ), INCA,
00267      $                                     AB( KD-L+1, J1+L ), INCA,
00268      $                                     D( J1 ), WORK( J1 ), KD1 )
00269    30                   CONTINUE
00270                      ELSE
00271                         J1END = J1 + KD1*( NR-2 )
00272                         IF( J1END.GE.J1 ) THEN
00273                            DO 40 JIN = J1, J1END, KD1
00274                               CALL ZROT( KD-1, AB( KD-1, JIN+1 ), INCX,
00275      $                                   AB( KD, JIN+1 ), INCX,
00276      $                                   D( JIN ), WORK( JIN ) )
00277    40                      CONTINUE
00278                         END IF
00279                         LEND = MIN( KDM1, N-J2 )
00280                         LAST = J1END + KD1
00281                         IF( LEND.GT.0 )
00282      $                     CALL ZROT( LEND, AB( KD-1, LAST+1 ), INCX,
00283      $                                AB( KD, LAST+1 ), INCX, D( LAST ),
00284      $                                WORK( LAST ) )
00285                      END IF
00286                   END IF
00287 *
00288                   IF( WANTQ ) THEN
00289 *
00290 *                    accumulate product of plane rotations in Q
00291 *
00292                      IF( INITQ ) THEN
00293 *
00294 *                 take advantage of the fact that Q was
00295 *                 initially the Identity matrix
00296 *
00297                         IQEND = MAX( IQEND, J2 )
00298                         I2 = MAX( 0, K-3 )
00299                         IQAEND = 1 + I*KD
00300                         IF( K.EQ.2 )
00301      $                     IQAEND = IQAEND + KD
00302                         IQAEND = MIN( IQAEND, IQEND )
00303                         DO 50 J = J1, J2, KD1
00304                            IBL = I - I2 / KDM1
00305                            I2 = I2 + 1
00306                            IQB = MAX( 1, J-IBL )
00307                            NQ = 1 + IQAEND - IQB
00308                            IQAEND = MIN( IQAEND+KD, IQEND )
00309                            CALL ZROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
00310      $                                1, D( J ), DCONJG( WORK( J ) ) )
00311    50                   CONTINUE
00312                      ELSE
00313 *
00314                         DO 60 J = J1, J2, KD1
00315                            CALL ZROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
00316      $                                D( J ), DCONJG( WORK( J ) ) )
00317    60                   CONTINUE
00318                      END IF
00319 *
00320                   END IF
00321 *
00322                   IF( J2+KDN.GT.N ) THEN
00323 *
00324 *                    adjust J2 to keep within the bounds of the matrix
00325 *
00326                      NR = NR - 1
00327                      J2 = J2 - KDN - 1
00328                   END IF
00329 *
00330                   DO 70 J = J1, J2, KD1
00331 *
00332 *                    create nonzero element a(j-1,j+kd) outside the band
00333 *                    and store it in WORK
00334 *
00335                      WORK( J+KD ) = WORK( J )*AB( 1, J+KD )
00336                      AB( 1, J+KD ) = D( J )*AB( 1, J+KD )
00337    70             CONTINUE
00338    80          CONTINUE
00339    90       CONTINUE
00340          END IF
00341 *
00342          IF( KD.GT.0 ) THEN
00343 *
00344 *           make off-diagonal elements real and copy them to E
00345 *
00346             DO 100 I = 1, N - 1
00347                T = AB( KD, I+1 )
00348                ABST = ABS( T )
00349                AB( KD, I+1 ) = ABST
00350                E( I ) = ABST
00351                IF( ABST.NE.ZERO ) THEN
00352                   T = T / ABST
00353                ELSE
00354                   T = CONE
00355                END IF
00356                IF( I.LT.N-1 )
00357      $            AB( KD, I+2 ) = AB( KD, I+2 )*T
00358                IF( WANTQ ) THEN
00359                   CALL ZSCAL( N, DCONJG( T ), Q( 1, I+1 ), 1 )
00360                END IF
00361   100       CONTINUE
00362          ELSE
00363 *
00364 *           set E to zero if original matrix was diagonal
00365 *
00366             DO 110 I = 1, N - 1
00367                E( I ) = ZERO
00368   110       CONTINUE
00369          END IF
00370 *
00371 *        copy diagonal elements to D
00372 *
00373          DO 120 I = 1, N
00374             D( I ) = AB( KD1, I )
00375   120    CONTINUE
00376 *
00377       ELSE
00378 *
00379          IF( KD.GT.1 ) THEN
00380 *
00381 *           Reduce to complex Hermitian tridiagonal form, working with
00382 *           the lower triangle
00383 *
00384             NR = 0
00385             J1 = KDN + 2
00386             J2 = 1
00387 *
00388             AB( 1, 1 ) = DBLE( AB( 1, 1 ) )
00389             DO 210 I = 1, N - 2
00390 *
00391 *              Reduce i-th column of matrix to tridiagonal form
00392 *
00393                DO 200 K = KDN + 1, 2, -1
00394                   J1 = J1 + KDN
00395                   J2 = J2 + KDN
00396 *
00397                   IF( NR.GT.0 ) THEN
00398 *
00399 *                    generate plane rotations to annihilate nonzero
00400 *                    elements which have been created outside the band
00401 *
00402                      CALL ZLARGV( NR, AB( KD1, J1-KD1 ), INCA,
00403      $                            WORK( J1 ), KD1, D( J1 ), KD1 )
00404 *
00405 *                    apply plane rotations from one side
00406 *
00407 *
00408 *                    Dependent on the the number of diagonals either
00409 *                    ZLARTV or ZROT is used
00410 *
00411                      IF( NR.GT.2*KD-1 ) THEN
00412                         DO 130 L = 1, KD - 1
00413                            CALL ZLARTV( NR, AB( KD1-L, J1-KD1+L ), INCA,
00414      $                                  AB( KD1-L+1, J1-KD1+L ), INCA,
00415      $                                  D( J1 ), WORK( J1 ), KD1 )
00416   130                   CONTINUE
00417                      ELSE
00418                         JEND = J1 + KD1*( NR-1 )
00419                         DO 140 JINC = J1, JEND, KD1
00420                            CALL ZROT( KDM1, AB( KD, JINC-KD ), INCX,
00421      $                                AB( KD1, JINC-KD ), INCX,
00422      $                                D( JINC ), WORK( JINC ) )
00423   140                   CONTINUE
00424                      END IF
00425 *
00426                   END IF
00427 *
00428                   IF( K.GT.2 ) THEN
00429                      IF( K.LE.N-I+1 ) THEN
00430 *
00431 *                       generate plane rotation to annihilate a(i+k-1,i)
00432 *                       within the band
00433 *
00434                         CALL ZLARTG( AB( K-1, I ), AB( K, I ),
00435      $                               D( I+K-1 ), WORK( I+K-1 ), TEMP )
00436                         AB( K-1, I ) = TEMP
00437 *
00438 *                       apply rotation from the left
00439 *
00440                         CALL ZROT( K-3, AB( K-2, I+1 ), LDAB-1,
00441      $                             AB( K-1, I+1 ), LDAB-1, D( I+K-1 ),
00442      $                             WORK( I+K-1 ) )
00443                      END IF
00444                      NR = NR + 1
00445                      J1 = J1 - KDN - 1
00446                   END IF
00447 *
00448 *                 apply plane rotations from both sides to diagonal
00449 *                 blocks
00450 *
00451                   IF( NR.GT.0 )
00452      $               CALL ZLAR2V( NR, AB( 1, J1-1 ), AB( 1, J1 ),
00453      $                            AB( 2, J1-1 ), INCA, D( J1 ),
00454      $                            WORK( J1 ), KD1 )
00455 *
00456 *                 apply plane rotations from the right
00457 *
00458 *
00459 *                    Dependent on the the number of diagonals either
00460 *                    ZLARTV or ZROT is used
00461 *
00462                   IF( NR.GT.0 ) THEN
00463                      CALL ZLACGV( NR, WORK( J1 ), KD1 )
00464                      IF( NR.GT.2*KD-1 ) THEN
00465                         DO 150 L = 1, KD - 1
00466                            IF( J2+L.GT.N ) THEN
00467                               NRT = NR - 1
00468                            ELSE
00469                               NRT = NR
00470                            END IF
00471                            IF( NRT.GT.0 )
00472      $                        CALL ZLARTV( NRT, AB( L+2, J1-1 ), INCA,
00473      $                                     AB( L+1, J1 ), INCA, D( J1 ),
00474      $                                     WORK( J1 ), KD1 )
00475   150                   CONTINUE
00476                      ELSE
00477                         J1END = J1 + KD1*( NR-2 )
00478                         IF( J1END.GE.J1 ) THEN
00479                            DO 160 J1INC = J1, J1END, KD1
00480                               CALL ZROT( KDM1, AB( 3, J1INC-1 ), 1,
00481      $                                   AB( 2, J1INC ), 1, D( J1INC ),
00482      $                                   WORK( J1INC ) )
00483   160                      CONTINUE
00484                         END IF
00485                         LEND = MIN( KDM1, N-J2 )
00486                         LAST = J1END + KD1
00487                         IF( LEND.GT.0 )
00488      $                     CALL ZROT( LEND, AB( 3, LAST-1 ), 1,
00489      $                                AB( 2, LAST ), 1, D( LAST ),
00490      $                                WORK( LAST ) )
00491                      END IF
00492                   END IF
00493 *
00494 *
00495 *
00496                   IF( WANTQ ) THEN
00497 *
00498 *                    accumulate product of plane rotations in Q
00499 *
00500                      IF( INITQ ) THEN
00501 *
00502 *                 take advantage of the fact that Q was
00503 *                 initially the Identity matrix
00504 *
00505                         IQEND = MAX( IQEND, J2 )
00506                         I2 = MAX( 0, K-3 )
00507                         IQAEND = 1 + I*KD
00508                         IF( K.EQ.2 )
00509      $                     IQAEND = IQAEND + KD
00510                         IQAEND = MIN( IQAEND, IQEND )
00511                         DO 170 J = J1, J2, KD1
00512                            IBL = I - I2 / KDM1
00513                            I2 = I2 + 1
00514                            IQB = MAX( 1, J-IBL )
00515                            NQ = 1 + IQAEND - IQB
00516                            IQAEND = MIN( IQAEND+KD, IQEND )
00517                            CALL ZROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
00518      $                                1, D( J ), WORK( J ) )
00519   170                   CONTINUE
00520                      ELSE
00521 *
00522                         DO 180 J = J1, J2, KD1
00523                            CALL ZROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
00524      $                                D( J ), WORK( J ) )
00525   180                   CONTINUE
00526                      END IF
00527                   END IF
00528 *
00529                   IF( J2+KDN.GT.N ) THEN
00530 *
00531 *                    adjust J2 to keep within the bounds of the matrix
00532 *
00533                      NR = NR - 1
00534                      J2 = J2 - KDN - 1
00535                   END IF
00536 *
00537                   DO 190 J = J1, J2, KD1
00538 *
00539 *                    create nonzero element a(j+kd,j-1) outside the
00540 *                    band and store it in WORK
00541 *
00542                      WORK( J+KD ) = WORK( J )*AB( KD1, J )
00543                      AB( KD1, J ) = D( J )*AB( KD1, J )
00544   190             CONTINUE
00545   200          CONTINUE
00546   210       CONTINUE
00547          END IF
00548 *
00549          IF( KD.GT.0 ) THEN
00550 *
00551 *           make off-diagonal elements real and copy them to E
00552 *
00553             DO 220 I = 1, N - 1
00554                T = AB( 2, I )
00555                ABST = ABS( T )
00556                AB( 2, I ) = ABST
00557                E( I ) = ABST
00558                IF( ABST.NE.ZERO ) THEN
00559                   T = T / ABST
00560                ELSE
00561                   T = CONE
00562                END IF
00563                IF( I.LT.N-1 )
00564      $            AB( 2, I+1 ) = AB( 2, I+1 )*T
00565                IF( WANTQ ) THEN
00566                   CALL ZSCAL( N, T, Q( 1, I+1 ), 1 )
00567                END IF
00568   220       CONTINUE
00569          ELSE
00570 *
00571 *           set E to zero if original matrix was diagonal
00572 *
00573             DO 230 I = 1, N - 1
00574                E( I ) = ZERO
00575   230       CONTINUE
00576          END IF
00577 *
00578 *        copy diagonal elements to D
00579 *
00580          DO 240 I = 1, N
00581             D( I ) = AB( 1, I )
00582   240    CONTINUE
00583       END IF
00584 *
00585       RETURN
00586 *
00587 *     End of ZHBTRD
00588 *
00589       END
 All Files Functions