1 *> \brief \b ZLAR1V computes the (scaled) r-th column of the inverse of the submatrix in rows b1 through bn of the tridiagonal matrix LDLT - λI.
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download ZLAR1V + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zlar1v.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zlar1v.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlar1v.f">
21 * SUBROUTINE ZLAR1V( N, B1, BN, LAMBDA, D, L, LD, LLD,
22 * PIVMIN, GAPTOL, Z, WANTNC, NEGCNT, ZTZ, MINGMA,
23 * R, ISUPPZ, NRMINV, RESID, RQCORR, WORK )
25 * .. Scalar Arguments ..
27 * INTEGER B1, BN, N, NEGCNT, R
28 * DOUBLE PRECISION GAPTOL, LAMBDA, MINGMA, NRMINV, PIVMIN, RESID,
31 * .. Array Arguments ..
33 * DOUBLE PRECISION D( * ), L( * ), LD( * ), LLD( * ),
44 *> ZLAR1V computes the (scaled) r-th column of the inverse of
45 *> the sumbmatrix in rows B1 through BN of the tridiagonal matrix
46 *> L D L**T - sigma I. When sigma is close to an eigenvalue, the
47 *> computed vector is an accurate eigenvector. Usually, r corresponds
48 *> to the index where the eigenvector is largest in magnitude.
49 *> The following steps accomplish this computation :
50 *> (a) Stationary qd transform, L D L**T - sigma I = L(+) D(+) L(+)**T,
51 *> (b) Progressive qd transform, L D L**T - sigma I = U(-) D(-) U(-)**T,
52 *> (c) Computation of the diagonal elements of the inverse of
53 *> L D L**T - sigma I by combining the above transforms, and choosing
54 *> r as the index where the diagonal of the inverse is (one of the)
55 *> largest in magnitude.
56 *> (d) Computation of the (scaled) r-th column of the inverse using the
57 *> twisted factorization obtained by combining the top part of the
58 *> the stationary and the bottom part of the progressive transform.
67 *> The order of the matrix L D L**T.
73 *> First index of the submatrix of L D L**T.
79 *> Last index of the submatrix of L D L**T.
84 *> LAMBDA is DOUBLE PRECISION
85 *> The shift. In order to compute an accurate eigenvector,
86 *> LAMBDA should be a good approximation to an eigenvalue
92 *> L is DOUBLE PRECISION array, dimension (N-1)
93 *> The (n-1) subdiagonal elements of the unit bidiagonal matrix
94 *> L, in elements 1 to N-1.
99 *> D is DOUBLE PRECISION array, dimension (N)
100 *> The n diagonal elements of the diagonal matrix D.
105 *> LD is DOUBLE PRECISION array, dimension (N-1)
106 *> The n-1 elements L(i)*D(i).
111 *> LLD is DOUBLE PRECISION array, dimension (N-1)
112 *> The n-1 elements L(i)*L(i)*D(i).
117 *> PIVMIN is DOUBLE PRECISION
118 *> The minimum pivot in the Sturm sequence.
123 *> GAPTOL is DOUBLE PRECISION
124 *> Tolerance that indicates when eigenvector entries are negligible
125 *> w.r.t. their contribution to the residual.
130 *> Z is COMPLEX*16 array, dimension (N)
131 *> On input, all entries of Z must be set to 0.
132 *> On output, Z contains the (scaled) r-th column of the
133 *> inverse. The scaling is such that Z(R) equals 1.
139 *> Specifies whether NEGCNT has to be computed.
142 *> \param[out] NEGCNT
145 *> If WANTNC is .TRUE. then NEGCNT = the number of pivots < pivmin
146 *> in the matrix factorization L D L**T, and NEGCNT = -1 otherwise.
151 *> ZTZ is DOUBLE PRECISION
152 *> The square of the 2-norm of Z.
155 *> \param[out] MINGMA
157 *> MINGMA is DOUBLE PRECISION
158 *> The reciprocal of the largest (in magnitude) diagonal
159 *> element of the inverse of L D L**T - sigma I.
165 *> The twist index for the twisted factorization used to
167 *> On input, 0 <= R <= N. If R is input as 0, R is set to
168 *> the index where (L D L**T - sigma I)^{-1} is largest
169 *> in magnitude. If 1 <= R <= N, R is unchanged.
170 *> On output, R contains the twist index used to compute Z.
171 *> Ideally, R designates the position of the maximum entry in the
175 *> \param[out] ISUPPZ
177 *> ISUPPZ is INTEGER array, dimension (2)
178 *> The support of the vector in Z, i.e., the vector Z is
179 *> nonzero only in elements ISUPPZ(1) through ISUPPZ( 2 ).
182 *> \param[out] NRMINV
184 *> NRMINV is DOUBLE PRECISION
185 *> NRMINV = 1/SQRT( ZTZ )
190 *> RESID is DOUBLE PRECISION
191 *> The residual of the FP vector.
192 *> RESID = ABS( MINGMA )/SQRT( ZTZ )
195 *> \param[out] RQCORR
197 *> RQCORR is DOUBLE PRECISION
198 *> The Rayleigh Quotient correction to LAMBDA.
199 *> RQCORR = MINGMA*TMP
204 *> WORK is DOUBLE PRECISION array, dimension (4*N)
210 *> \author Univ. of Tennessee
211 *> \author Univ. of California Berkeley
212 *> \author Univ. of Colorado Denver
215 *> \date September 2012
217 *> \ingroup complex16OTHERauxiliary
219 *> \par Contributors:
222 *> Beresford Parlett, University of California, Berkeley, USA \n
223 *> Jim Demmel, University of California, Berkeley, USA \n
224 *> Inderjit Dhillon, University of Texas, Austin, USA \n
225 *> Osni Marques, LBNL/NERSC, USA \n
226 *> Christof Voemel, University of California, Berkeley, USA
228 * =====================================================================
229 SUBROUTINE ZLAR1V( N, B1, BN, LAMBDA, D, L, LD, LLD,
230 $ PIVMIN, GAPTOL, Z, WANTNC, NEGCNT, ZTZ, MINGMA,
231 $ R, ISUPPZ, NRMINV, RESID, RQCORR, WORK )
233 * -- LAPACK auxiliary routine (version 3.4.2) --
234 * -- LAPACK is a software package provided by Univ. of Tennessee, --
235 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
238 * .. Scalar Arguments ..
240 INTEGER B1, BN, N, NEGCNT, R
241 DOUBLE PRECISION GAPTOL, LAMBDA, MINGMA, NRMINV, PIVMIN, RESID,
244 * .. Array Arguments ..
246 DOUBLE PRECISION D( * ), L( * ), LD( * ), LLD( * ),
251 * =====================================================================
254 DOUBLE PRECISION ZERO, ONE
255 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
257 PARAMETER ( CONE = ( 1.0D0, 0.0D0 ) )
260 * .. Local Scalars ..
261 LOGICAL SAWNAN1, SAWNAN2
262 INTEGER I, INDLPL, INDP, INDS, INDUMN, NEG1, NEG2, R1,
264 DOUBLE PRECISION DMINUS, DPLUS, EPS, S, TMP
266 * .. External Functions ..
268 DOUBLE PRECISION DLAMCH
269 EXTERNAL DISNAN, DLAMCH
271 * .. Intrinsic Functions ..
274 * .. Executable Statements ..
276 EPS = DLAMCH( 'Precision' )
297 WORK( INDS+B1-1 ) = LLD( B1-1 )
301 * Compute the stationary transform (using the differential form)
302 * until the index R2.
306 S = WORK( INDS+B1-1 ) - LAMBDA
309 WORK( INDLPL+I ) = LD( I ) / DPLUS
310 IF(DPLUS.LT.ZERO) NEG1 = NEG1 + 1
311 WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
312 S = WORK( INDS+I ) - LAMBDA
314 SAWNAN1 = DISNAN( S )
315 IF( SAWNAN1 ) GOTO 60
318 WORK( INDLPL+I ) = LD( I ) / DPLUS
319 WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
320 S = WORK( INDS+I ) - LAMBDA
322 SAWNAN1 = DISNAN( S )
326 * Runs a slower version of the above loop if a NaN is detected
328 S = WORK( INDS+B1-1 ) - LAMBDA
331 IF(ABS(DPLUS).LT.PIVMIN) DPLUS = -PIVMIN
332 WORK( INDLPL+I ) = LD( I ) / DPLUS
333 IF(DPLUS.LT.ZERO) NEG1 = NEG1 + 1
334 WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
335 IF( WORK( INDLPL+I ).EQ.ZERO )
336 $ WORK( INDS+I ) = LLD( I )
337 S = WORK( INDS+I ) - LAMBDA
341 IF(ABS(DPLUS).LT.PIVMIN) DPLUS = -PIVMIN
342 WORK( INDLPL+I ) = LD( I ) / DPLUS
343 WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I )
344 IF( WORK( INDLPL+I ).EQ.ZERO )
345 $ WORK( INDS+I ) = LLD( I )
346 S = WORK( INDS+I ) - LAMBDA
350 * Compute the progressive transform (using the differential form)
355 WORK( INDP+BN-1 ) = D( BN ) - LAMBDA
356 DO 80 I = BN - 1, R1, -1
357 DMINUS = LLD( I ) + WORK( INDP+I )
358 TMP = D( I ) / DMINUS
359 IF(DMINUS.LT.ZERO) NEG2 = NEG2 + 1
360 WORK( INDUMN+I ) = L( I )*TMP
361 WORK( INDP+I-1 ) = WORK( INDP+I )*TMP - LAMBDA
363 TMP = WORK( INDP+R1-1 )
364 SAWNAN2 = DISNAN( TMP )
367 * Runs a slower version of the above loop if a NaN is detected
369 DO 100 I = BN-1, R1, -1
370 DMINUS = LLD( I ) + WORK( INDP+I )
371 IF(ABS(DMINUS).LT.PIVMIN) DMINUS = -PIVMIN
372 TMP = D( I ) / DMINUS
373 IF(DMINUS.LT.ZERO) NEG2 = NEG2 + 1
374 WORK( INDUMN+I ) = L( I )*TMP
375 WORK( INDP+I-1 ) = WORK( INDP+I )*TMP - LAMBDA
377 $ WORK( INDP+I-1 ) = D( I ) - LAMBDA
381 * Find the index (from R1 to R2) of the largest (in magnitude)
382 * diagonal element of the inverse
384 MINGMA = WORK( INDS+R1-1 ) + WORK( INDP+R1-1 )
385 IF( MINGMA.LT.ZERO ) NEG1 = NEG1 + 1
391 IF( ABS(MINGMA).EQ.ZERO )
392 $ MINGMA = EPS*WORK( INDS+R1-1 )
394 DO 110 I = R1, R2 - 1
395 TMP = WORK( INDS+I ) + WORK( INDP+I )
397 $ TMP = EPS*WORK( INDS+I )
398 IF( ABS( TMP ).LE.ABS( MINGMA ) ) THEN
404 * Compute the FP vector: solve N^T v = e_r
411 * Compute the FP vector upwards from R
413 IF( .NOT.SAWNAN1 .AND. .NOT.SAWNAN2 ) THEN
414 DO 210 I = R-1, B1, -1
415 Z( I ) = -( WORK( INDLPL+I )*Z( I+1 ) )
416 IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
422 ZTZ = ZTZ + DBLE( Z( I )*Z( I ) )
426 * Run slower loop if NaN occurred.
427 DO 230 I = R - 1, B1, -1
428 IF( Z( I+1 ).EQ.ZERO ) THEN
429 Z( I ) = -( LD( I+1 ) / LD( I ) )*Z( I+2 )
431 Z( I ) = -( WORK( INDLPL+I )*Z( I+1 ) )
433 IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
439 ZTZ = ZTZ + DBLE( Z( I )*Z( I ) )
444 * Compute the FP vector downwards from R in blocks of size BLKSIZ
445 IF( .NOT.SAWNAN1 .AND. .NOT.SAWNAN2 ) THEN
447 Z( I+1 ) = -( WORK( INDUMN+I )*Z( I ) )
448 IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
454 ZTZ = ZTZ + DBLE( Z( I+1 )*Z( I+1 ) )
458 * Run slower loop if NaN occurred.
460 IF( Z( I ).EQ.ZERO ) THEN
461 Z( I+1 ) = -( LD( I-1 ) / LD( I ) )*Z( I-1 )
463 Z( I+1 ) = -( WORK( INDUMN+I )*Z( I ) )
465 IF( (ABS(Z(I))+ABS(Z(I+1)))* ABS(LD(I)).LT.GAPTOL )
471 ZTZ = ZTZ + DBLE( Z( I+1 )*Z( I+1 ) )
476 * Compute quantities for convergence test
480 RESID = ABS( MINGMA )*NRMINV