LAPACK 3.3.0

zlar1v.f

Go to the documentation of this file.
00001       SUBROUTINE ZLAR1V( N, B1, BN, LAMBDA, D, L, LD, LLD,
00002      $           PIVMIN, GAPTOL, Z, WANTNC, NEGCNT, ZTZ, MINGMA,
00003      $           R, ISUPPZ, NRMINV, RESID, RQCORR, WORK )
00004 *
00005 *  -- LAPACK auxiliary routine (version 3.2) --
00006 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00007 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00008 *     November 2006
00009 *
00010 *     .. Scalar Arguments ..
00011       LOGICAL            WANTNC
00012       INTEGER   B1, BN, N, NEGCNT, R
00013       DOUBLE PRECISION   GAPTOL, LAMBDA, MINGMA, NRMINV, PIVMIN, RESID,
00014      $                   RQCORR, ZTZ
00015 *     ..
00016 *     .. Array Arguments ..
00017       INTEGER            ISUPPZ( * )
00018       DOUBLE PRECISION   D( * ), L( * ), LD( * ), LLD( * ),
00019      $                  WORK( * )
00020       COMPLEX*16       Z( * )
00021 *     ..
00022 *
00023 *  Purpose
00024 *  =======
00025 *
00026 *  ZLAR1V computes the (scaled) r-th column of the inverse of
00027 *  the sumbmatrix in rows B1 through BN of the tridiagonal matrix
00028 *  L D L^T - sigma I. When sigma is close to an eigenvalue, the
00029 *  computed vector is an accurate eigenvector. Usually, r corresponds
00030 *  to the index where the eigenvector is largest in magnitude.
00031 *  The following steps accomplish this computation :
00032 *  (a) Stationary qd transform,  L D L^T - sigma I = L(+) D(+) L(+)^T,
00033 *  (b) Progressive qd transform, L D L^T - sigma I = U(-) D(-) U(-)^T,
00034 *  (c) Computation of the diagonal elements of the inverse of
00035 *      L D L^T - sigma I by combining the above transforms, and choosing
00036 *      r as the index where the diagonal of the inverse is (one of the)
00037 *      largest in magnitude.
00038 *  (d) Computation of the (scaled) r-th column of the inverse using the
00039 *      twisted factorization obtained by combining the top part of the
00040 *      the stationary and the bottom part of the progressive transform.
00041 *
00042 *  Arguments
00043 *  =========
00044 *
00045 *  N        (input) INTEGER
00046 *           The order of the matrix L D L^T.
00047 *
00048 *  B1       (input) INTEGER
00049 *           First index of the submatrix of L D L^T.
00050 *
00051 *  BN       (input) INTEGER
00052 *           Last index of the submatrix of L D L^T.
00053 *
00054 *  LAMBDA    (input) DOUBLE PRECISION
00055 *           The shift. In order to compute an accurate eigenvector,
00056 *           LAMBDA should be a good approximation to an eigenvalue
00057 *           of L D L^T.
00058 *
00059 *  L        (input) DOUBLE PRECISION array, dimension (N-1)
00060 *           The (n-1) subdiagonal elements of the unit bidiagonal matrix
00061 *           L, in elements 1 to N-1.
00062 *
00063 *  D        (input) DOUBLE PRECISION array, dimension (N)
00064 *           The n diagonal elements of the diagonal matrix D.
00065 *
00066 *  LD       (input) DOUBLE PRECISION array, dimension (N-1)
00067 *           The n-1 elements L(i)*D(i).
00068 *
00069 *  LLD      (input) DOUBLE PRECISION array, dimension (N-1)
00070 *           The n-1 elements L(i)*L(i)*D(i).
00071 *
00072 *  PIVMIN   (input) DOUBLE PRECISION
00073 *           The minimum pivot in the Sturm sequence.
00074 *
00075 *  GAPTOL   (input) DOUBLE PRECISION
00076 *           Tolerance that indicates when eigenvector entries are negligible
00077 *           w.r.t. their contribution to the residual.
00078 *
00079 *  Z        (input/output) COMPLEX*16       array, dimension (N)
00080 *           On input, all entries of Z must be set to 0.
00081 *           On output, Z contains the (scaled) r-th column of the
00082 *           inverse. The scaling is such that Z(R) equals 1.
00083 *
00084 *  WANTNC   (input) LOGICAL
00085 *           Specifies whether NEGCNT has to be computed.
00086 *
00087 *  NEGCNT   (output) INTEGER
00088 *           If WANTNC is .TRUE. then NEGCNT = the number of pivots < pivmin
00089 *           in the  matrix factorization L D L^T, and NEGCNT = -1 otherwise.
00090 *
00091 *  ZTZ      (output) DOUBLE PRECISION
00092 *           The square of the 2-norm of Z.
00093 *
00094 *  MINGMA   (output) DOUBLE PRECISION
00095 *           The reciprocal of the largest (in magnitude) diagonal
00096 *           element of the inverse of L D L^T - sigma I.
00097 *
00098 *  R        (input/output) INTEGER
00099 *           The twist index for the twisted factorization used to
00100 *           compute Z.
00101 *           On input, 0 <= R <= N. If R is input as 0, R is set to
00102 *           the index where (L D L^T - sigma I)^{-1} is largest
00103 *           in magnitude. If 1 <= R <= N, R is unchanged.
00104 *           On output, R contains the twist index used to compute Z.
00105 *           Ideally, R designates the position of the maximum entry in the
00106 *           eigenvector.
00107 *
00108 *  ISUPPZ   (output) INTEGER array, dimension (2)
00109 *           The support of the vector in Z, i.e., the vector Z is
00110 *           nonzero only in elements ISUPPZ(1) through ISUPPZ( 2 ).
00111 *
00112 *  NRMINV   (output) DOUBLE PRECISION
00113 *           NRMINV = 1/SQRT( ZTZ )
00114 *
00115 *  RESID    (output) DOUBLE PRECISION
00116 *           The residual of the FP vector.
00117 *           RESID = ABS( MINGMA )/SQRT( ZTZ )
00118 *
00119 *  RQCORR   (output) DOUBLE PRECISION
00120 *           The Rayleigh Quotient correction to LAMBDA.
00121 *           RQCORR = MINGMA*TMP
00122 *
00123 *  WORK     (workspace) DOUBLE PRECISION array, dimension (4*N)
00124 *
00125 *  Further Details
00126 *  ===============
00127 *
00128 *  Based on contributions by
00129 *     Beresford Parlett, University of California, Berkeley, USA
00130 *     Jim Demmel, University of California, Berkeley, USA
00131 *     Inderjit Dhillon, University of Texas, Austin, USA
00132 *     Osni Marques, LBNL/NERSC, USA
00133 *     Christof Voemel, University of California, Berkeley, USA
00134 *
00135 *  =====================================================================
00136 *
00137 *     .. Parameters ..
00138       DOUBLE PRECISION   ZERO, ONE
00139       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
00140       COMPLEX*16         CONE
00141       PARAMETER          ( CONE = ( 1.0D0, 0.0D0 ) )
00142 
00143 *     ..
00144 *     .. Local Scalars ..
00145       LOGICAL            SAWNAN1, SAWNAN2
00146       INTEGER            I, INDLPL, INDP, INDS, INDUMN, NEG1, NEG2, R1,
00147      $                   R2
00148       DOUBLE PRECISION   DMINUS, DPLUS, EPS, S, TMP
00149 *     ..
00150 *     .. External Functions ..
00151       LOGICAL DISNAN
00152       DOUBLE PRECISION   DLAMCH
00153       EXTERNAL           DISNAN, DLAMCH
00154 *     ..
00155 *     .. Intrinsic Functions ..
00156       INTRINSIC          ABS, DBLE
00157 *     ..
00158 *     .. Executable Statements ..
00159 *
00160       EPS = DLAMCH( 'Precision' )
00161 
00162 
00163       IF( R.EQ.0 ) THEN
00164          R1 = B1
00165          R2 = BN
00166       ELSE
00167          R1 = R
00168          R2 = R
00169       END IF
00170 
00171 *     Storage for LPLUS
00172       INDLPL = 0
00173 *     Storage for UMINUS
00174       INDUMN = N
00175       INDS = 2*N + 1
00176       INDP = 3*N + 1
00177 
00178       IF( B1.EQ.1 ) THEN
00179          WORK( INDS ) = ZERO
00180       ELSE
00181          WORK( INDS+B1-1 ) = LLD( B1-1 )
00182       END IF
00183 
00184 *
00185 *     Compute the stationary transform (using the differential form)
00186 *     until the index R2.
00187 *
00188       SAWNAN1 = .FALSE.
00189       NEG1 = 0
00190       S = WORK( INDS+B1-1 ) - LAMBDA
00191       DO 50 I = B1, R1 - 1
00192          DPLUS = D( I ) + S
00193          WORK( INDLPL+I ) = LD( I ) / DPLUS
00194          IF(DPLUS.LT.ZERO) NEG1 = NEG1 + 1
00195          WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
00196          S = WORK( INDS+I ) - LAMBDA
00197  50   CONTINUE
00198       SAWNAN1 = DISNAN( S )
00199       IF( SAWNAN1 ) GOTO 60
00200       DO 51 I = R1, R2 - 1
00201          DPLUS = D( I ) + S
00202          WORK( INDLPL+I ) = LD( I ) / DPLUS
00203          WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
00204          S = WORK( INDS+I ) - LAMBDA
00205  51   CONTINUE
00206       SAWNAN1 = DISNAN( S )
00207 *
00208  60   CONTINUE
00209       IF( SAWNAN1 ) THEN
00210 *        Runs a slower version of the above loop if a NaN is detected
00211          NEG1 = 0
00212          S = WORK( INDS+B1-1 ) - LAMBDA
00213          DO 70 I = B1, R1 - 1
00214             DPLUS = D( I ) + S
00215             IF(ABS(DPLUS).LT.PIVMIN) DPLUS = -PIVMIN
00216             WORK( INDLPL+I ) = LD( I ) / DPLUS
00217             IF(DPLUS.LT.ZERO) NEG1 = NEG1 + 1
00218             WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
00219             IF( WORK( INDLPL+I ).EQ.ZERO )
00220      $                      WORK( INDS+I ) = LLD( I )
00221             S = WORK( INDS+I ) - LAMBDA
00222  70      CONTINUE
00223          DO 71 I = R1, R2 - 1
00224             DPLUS = D( I ) + S
00225             IF(ABS(DPLUS).LT.PIVMIN) DPLUS = -PIVMIN
00226             WORK( INDLPL+I ) = LD( I ) / DPLUS
00227             WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
00228             IF( WORK( INDLPL+I ).EQ.ZERO )
00229      $                      WORK( INDS+I ) = LLD( I )
00230             S = WORK( INDS+I ) - LAMBDA
00231  71      CONTINUE
00232       END IF
00233 *
00234 *     Compute the progressive transform (using the differential form)
00235 *     until the index R1
00236 *
00237       SAWNAN2 = .FALSE.
00238       NEG2 = 0
00239       WORK( INDP+BN-1 ) = D( BN ) - LAMBDA
00240       DO 80 I = BN - 1, R1, -1
00241          DMINUS = LLD( I ) + WORK( INDP+I )
00242          TMP = D( I ) / DMINUS
00243          IF(DMINUS.LT.ZERO) NEG2 = NEG2 + 1
00244          WORK( INDUMN+I ) = L( I )*TMP
00245          WORK( INDP+I-1 ) = WORK( INDP+I )*TMP - LAMBDA
00246  80   CONTINUE
00247       TMP = WORK( INDP+R1-1 )
00248       SAWNAN2 = DISNAN( TMP )
00249 
00250       IF( SAWNAN2 ) THEN
00251 *        Runs a slower version of the above loop if a NaN is detected
00252          NEG2 = 0
00253          DO 100 I = BN-1, R1, -1
00254             DMINUS = LLD( I ) + WORK( INDP+I )
00255             IF(ABS(DMINUS).LT.PIVMIN) DMINUS = -PIVMIN
00256             TMP = D( I ) / DMINUS
00257             IF(DMINUS.LT.ZERO) NEG2 = NEG2 + 1
00258             WORK( INDUMN+I ) = L( I )*TMP
00259             WORK( INDP+I-1 ) = WORK( INDP+I )*TMP - LAMBDA
00260             IF( TMP.EQ.ZERO )
00261      $          WORK( INDP+I-1 ) = D( I ) - LAMBDA
00262  100     CONTINUE
00263       END IF
00264 *
00265 *     Find the index (from R1 to R2) of the largest (in magnitude)
00266 *     diagonal element of the inverse
00267 *
00268       MINGMA = WORK( INDS+R1-1 ) + WORK( INDP+R1-1 )
00269       IF( MINGMA.LT.ZERO ) NEG1 = NEG1 + 1
00270       IF( WANTNC ) THEN
00271          NEGCNT = NEG1 + NEG2
00272       ELSE
00273          NEGCNT = -1
00274       ENDIF
00275       IF( ABS(MINGMA).EQ.ZERO )
00276      $   MINGMA = EPS*WORK( INDS+R1-1 )
00277       R = R1
00278       DO 110 I = R1, R2 - 1
00279          TMP = WORK( INDS+I ) + WORK( INDP+I )
00280          IF( TMP.EQ.ZERO )
00281      $      TMP = EPS*WORK( INDS+I )
00282          IF( ABS( TMP ).LE.ABS( MINGMA ) ) THEN
00283             MINGMA = TMP
00284             R = I + 1
00285          END IF
00286  110  CONTINUE
00287 *
00288 *     Compute the FP vector: solve N^T v = e_r
00289 *
00290       ISUPPZ( 1 ) = B1
00291       ISUPPZ( 2 ) = BN
00292       Z( R ) = CONE
00293       ZTZ = ONE
00294 *
00295 *     Compute the FP vector upwards from R
00296 *
00297       IF( .NOT.SAWNAN1 .AND. .NOT.SAWNAN2 ) THEN
00298          DO 210 I = R-1, B1, -1
00299             Z( I ) = -( WORK( INDLPL+I )*Z( I+1 ) )
00300             IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
00301      $           THEN
00302                Z( I ) = ZERO
00303                ISUPPZ( 1 ) = I + 1
00304                GOTO 220
00305             ENDIF
00306             ZTZ = ZTZ + DBLE( Z( I )*Z( I ) )
00307  210     CONTINUE
00308  220     CONTINUE
00309       ELSE
00310 *        Run slower loop if NaN occurred.
00311          DO 230 I = R - 1, B1, -1
00312             IF( Z( I+1 ).EQ.ZERO ) THEN
00313                Z( I ) = -( LD( I+1 ) / LD( I ) )*Z( I+2 )
00314             ELSE
00315                Z( I ) = -( WORK( INDLPL+I )*Z( I+1 ) )
00316             END IF
00317             IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
00318      $           THEN
00319                Z( I ) = ZERO
00320                ISUPPZ( 1 ) = I + 1
00321                GO TO 240
00322             END IF
00323             ZTZ = ZTZ + DBLE( Z( I )*Z( I ) )
00324  230     CONTINUE
00325  240     CONTINUE
00326       ENDIF
00327 
00328 *     Compute the FP vector downwards from R in blocks of size BLKSIZ
00329       IF( .NOT.SAWNAN1 .AND. .NOT.SAWNAN2 ) THEN
00330          DO 250 I = R, BN-1
00331             Z( I+1 ) = -( WORK( INDUMN+I )*Z( I ) )
00332             IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
00333      $         THEN
00334                Z( I+1 ) = ZERO
00335                ISUPPZ( 2 ) = I
00336                GO TO 260
00337             END IF
00338             ZTZ = ZTZ + DBLE( Z( I+1 )*Z( I+1 ) )
00339  250     CONTINUE
00340  260     CONTINUE
00341       ELSE
00342 *        Run slower loop if NaN occurred.
00343          DO 270 I = R, BN - 1
00344             IF( Z( I ).EQ.ZERO ) THEN
00345                Z( I+1 ) = -( LD( I-1 ) / LD( I ) )*Z( I-1 )
00346             ELSE
00347                Z( I+1 ) = -( WORK( INDUMN+I )*Z( I ) )
00348             END IF
00349             IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
00350      $           THEN
00351                Z( I+1 ) = ZERO
00352                ISUPPZ( 2 ) = I
00353                GO TO 280
00354             END IF
00355             ZTZ = ZTZ + DBLE( Z( I+1 )*Z( I+1 ) )
00356  270     CONTINUE
00357  280     CONTINUE
00358       END IF
00359 *
00360 *     Compute quantities for convergence test
00361 *
00362       TMP = ONE / ZTZ
00363       NRMINV = SQRT( TMP )
00364       RESID = ABS( MINGMA )*NRMINV
00365       RQCORR = MINGMA*TMP
00366 *
00367 *
00368       RETURN
00369 *
00370 *     End of ZLAR1V
00371 *
00372       END
 All Files Functions