LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
clar1v.f
Go to the documentation of this file.
1*> \brief \b CLAR1V computes the (scaled) r-th column of the inverse of the submatrix in rows b1 through bn of the tridiagonal matrix LDLT - λI.
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download CLAR1V + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/clar1v.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/clar1v.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clar1v.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE CLAR1V( N, B1, BN, LAMBDA, D, L, LD, LLD,
20* PIVMIN, GAPTOL, Z, WANTNC, NEGCNT, ZTZ, MINGMA,
21* R, ISUPPZ, NRMINV, RESID, RQCORR, WORK )
22*
23* .. Scalar Arguments ..
24* LOGICAL WANTNC
25* INTEGER B1, BN, N, NEGCNT, R
26* REAL GAPTOL, LAMBDA, MINGMA, NRMINV, PIVMIN, RESID,
27* $ RQCORR, ZTZ
28* ..
29* .. Array Arguments ..
30* INTEGER ISUPPZ( * )
31* REAL D( * ), L( * ), LD( * ), LLD( * ),
32* $ WORK( * )
33* COMPLEX Z( * )
34* ..
35*
36*
37*> \par Purpose:
38* =============
39*>
40*> \verbatim
41*>
42*> CLAR1V computes the (scaled) r-th column of the inverse of
43*> the sumbmatrix in rows B1 through BN of the tridiagonal matrix
44*> L D L**T - sigma I. When sigma is close to an eigenvalue, the
45*> computed vector is an accurate eigenvector. Usually, r corresponds
46*> to the index where the eigenvector is largest in magnitude.
47*> The following steps accomplish this computation :
48*> (a) Stationary qd transform, L D L**T - sigma I = L(+) D(+) L(+)**T,
49*> (b) Progressive qd transform, L D L**T - sigma I = U(-) D(-) U(-)**T,
50*> (c) Computation of the diagonal elements of the inverse of
51*> L D L**T - sigma I by combining the above transforms, and choosing
52*> r as the index where the diagonal of the inverse is (one of the)
53*> largest in magnitude.
54*> (d) Computation of the (scaled) r-th column of the inverse using the
55*> twisted factorization obtained by combining the top part of the
56*> the stationary and the bottom part of the progressive transform.
57*> \endverbatim
58*
59* Arguments:
60* ==========
61*
62*> \param[in] N
63*> \verbatim
64*> N is INTEGER
65*> The order of the matrix L D L**T.
66*> \endverbatim
67*>
68*> \param[in] B1
69*> \verbatim
70*> B1 is INTEGER
71*> First index of the submatrix of L D L**T.
72*> \endverbatim
73*>
74*> \param[in] BN
75*> \verbatim
76*> BN is INTEGER
77*> Last index of the submatrix of L D L**T.
78*> \endverbatim
79*>
80*> \param[in] LAMBDA
81*> \verbatim
82*> LAMBDA is REAL
83*> The shift. In order to compute an accurate eigenvector,
84*> LAMBDA should be a good approximation to an eigenvalue
85*> of L D L**T.
86*> \endverbatim
87*>
88*> \param[in] L
89*> \verbatim
90*> L is REAL array, dimension (N-1)
91*> The (n-1) subdiagonal elements of the unit bidiagonal matrix
92*> L, in elements 1 to N-1.
93*> \endverbatim
94*>
95*> \param[in] D
96*> \verbatim
97*> D is REAL array, dimension (N)
98*> The n diagonal elements of the diagonal matrix D.
99*> \endverbatim
100*>
101*> \param[in] LD
102*> \verbatim
103*> LD is REAL array, dimension (N-1)
104*> The n-1 elements L(i)*D(i).
105*> \endverbatim
106*>
107*> \param[in] LLD
108*> \verbatim
109*> LLD is REAL array, dimension (N-1)
110*> The n-1 elements L(i)*L(i)*D(i).
111*> \endverbatim
112*>
113*> \param[in] PIVMIN
114*> \verbatim
115*> PIVMIN is REAL
116*> The minimum pivot in the Sturm sequence.
117*> \endverbatim
118*>
119*> \param[in] GAPTOL
120*> \verbatim
121*> GAPTOL is REAL
122*> Tolerance that indicates when eigenvector entries are negligible
123*> w.r.t. their contribution to the residual.
124*> \endverbatim
125*>
126*> \param[in,out] Z
127*> \verbatim
128*> Z is COMPLEX array, dimension (N)
129*> On input, all entries of Z must be set to 0.
130*> On output, Z contains the (scaled) r-th column of the
131*> inverse. The scaling is such that Z(R) equals 1.
132*> \endverbatim
133*>
134*> \param[in] WANTNC
135*> \verbatim
136*> WANTNC is LOGICAL
137*> Specifies whether NEGCNT has to be computed.
138*> \endverbatim
139*>
140*> \param[out] NEGCNT
141*> \verbatim
142*> NEGCNT is INTEGER
143*> If WANTNC is .TRUE. then NEGCNT = the number of pivots < pivmin
144*> in the matrix factorization L D L**T, and NEGCNT = -1 otherwise.
145*> \endverbatim
146*>
147*> \param[out] ZTZ
148*> \verbatim
149*> ZTZ is REAL
150*> The square of the 2-norm of Z.
151*> \endverbatim
152*>
153*> \param[out] MINGMA
154*> \verbatim
155*> MINGMA is REAL
156*> The reciprocal of the largest (in magnitude) diagonal
157*> element of the inverse of L D L**T - sigma I.
158*> \endverbatim
159*>
160*> \param[in,out] R
161*> \verbatim
162*> R is INTEGER
163*> The twist index for the twisted factorization used to
164*> compute Z.
165*> On input, 0 <= R <= N. If R is input as 0, R is set to
166*> the index where (L D L**T - sigma I)^{-1} is largest
167*> in magnitude. If 1 <= R <= N, R is unchanged.
168*> On output, R contains the twist index used to compute Z.
169*> Ideally, R designates the position of the maximum entry in the
170*> eigenvector.
171*> \endverbatim
172*>
173*> \param[out] ISUPPZ
174*> \verbatim
175*> ISUPPZ is INTEGER array, dimension (2)
176*> The support of the vector in Z, i.e., the vector Z is
177*> nonzero only in elements ISUPPZ(1) through ISUPPZ( 2 ).
178*> \endverbatim
179*>
180*> \param[out] NRMINV
181*> \verbatim
182*> NRMINV is REAL
183*> NRMINV = 1/SQRT( ZTZ )
184*> \endverbatim
185*>
186*> \param[out] RESID
187*> \verbatim
188*> RESID is REAL
189*> The residual of the FP vector.
190*> RESID = ABS( MINGMA )/SQRT( ZTZ )
191*> \endverbatim
192*>
193*> \param[out] RQCORR
194*> \verbatim
195*> RQCORR is REAL
196*> The Rayleigh Quotient correction to LAMBDA.
197*> RQCORR = MINGMA*TMP
198*> \endverbatim
199*>
200*> \param[out] WORK
201*> \verbatim
202*> WORK is REAL array, dimension (4*N)
203*> \endverbatim
204*
205* Authors:
206* ========
207*
208*> \author Univ. of Tennessee
209*> \author Univ. of California Berkeley
210*> \author Univ. of Colorado Denver
211*> \author NAG Ltd.
212*
213*> \ingroup lar1v
214*
215*> \par Contributors:
216* ==================
217*>
218*> Beresford Parlett, University of California, Berkeley, USA \n
219*> Jim Demmel, University of California, Berkeley, USA \n
220*> Inderjit Dhillon, University of Texas, Austin, USA \n
221*> Osni Marques, LBNL/NERSC, USA \n
222*> Christof Voemel, University of California, Berkeley, USA
223*
224* =====================================================================
225 SUBROUTINE clar1v( N, B1, BN, LAMBDA, D, L, LD, LLD,
226 $ PIVMIN, GAPTOL, Z, WANTNC, NEGCNT, ZTZ, MINGMA,
227 $ R, ISUPPZ, NRMINV, RESID, RQCORR, WORK )
228*
229* -- LAPACK auxiliary routine --
230* -- LAPACK is a software package provided by Univ. of Tennessee, --
231* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
232*
233* .. Scalar Arguments ..
234 LOGICAL WANTNC
235 INTEGER B1, BN, N, NEGCNT, R
236 REAL GAPTOL, LAMBDA, MINGMA, NRMINV, PIVMIN, RESID,
237 $ rqcorr, ztz
238* ..
239* .. Array Arguments ..
240 INTEGER ISUPPZ( * )
241 REAL D( * ), L( * ), LD( * ), LLD( * ),
242 $ work( * )
243 COMPLEX Z( * )
244* ..
245*
246* =====================================================================
247*
248* .. Parameters ..
249 REAL ZERO, ONE
250 PARAMETER ( ZERO = 0.0e0, one = 1.0e0 )
251 COMPLEX CONE
252 parameter( cone = ( 1.0e0, 0.0e0 ) )
253
254* ..
255* .. Local Scalars ..
256 LOGICAL SAWNAN1, SAWNAN2
257 INTEGER I, INDLPL, INDP, INDS, INDUMN, NEG1, NEG2, R1,
258 $ r2
259 REAL DMINUS, DPLUS, EPS, S, TMP
260* ..
261* .. External Functions ..
262 LOGICAL SISNAN
263 REAL SLAMCH
264 EXTERNAL sisnan, slamch
265* ..
266* .. Intrinsic Functions ..
267 INTRINSIC abs, real
268* ..
269* .. Executable Statements ..
270*
271 eps = slamch( 'Precision' )
272
273
274 IF( r.EQ.0 ) THEN
275 r1 = b1
276 r2 = bn
277 ELSE
278 r1 = r
279 r2 = r
280 END IF
281
282* Storage for LPLUS
283 indlpl = 0
284* Storage for UMINUS
285 indumn = n
286 inds = 2*n + 1
287 indp = 3*n + 1
288
289 IF( b1.EQ.1 ) THEN
290 work( inds ) = zero
291 ELSE
292 work( inds+b1-1 ) = lld( b1-1 )
293 END IF
294
295*
296* Compute the stationary transform (using the differential form)
297* until the index R2.
298*
299 sawnan1 = .false.
300 neg1 = 0
301 s = work( inds+b1-1 ) - lambda
302 DO 50 i = b1, r1 - 1
303 dplus = d( i ) + s
304 work( indlpl+i ) = ld( i ) / dplus
305 IF(dplus.LT.zero) neg1 = neg1 + 1
306 work( inds+i ) = s*work( indlpl+i )*l( i )
307 s = work( inds+i ) - lambda
308 50 CONTINUE
309 sawnan1 = sisnan( s )
310 IF( sawnan1 ) GOTO 60
311 DO 51 i = r1, r2 - 1
312 dplus = d( i ) + s
313 work( indlpl+i ) = ld( i ) / dplus
314 work( inds+i ) = s*work( indlpl+i )*l( i )
315 s = work( inds+i ) - lambda
316 51 CONTINUE
317 sawnan1 = sisnan( s )
318*
319 60 CONTINUE
320 IF( sawnan1 ) THEN
321* Runs a slower version of the above loop if a NaN is detected
322 neg1 = 0
323 s = work( inds+b1-1 ) - lambda
324 DO 70 i = b1, r1 - 1
325 dplus = d( i ) + s
326 IF(abs(dplus).LT.pivmin) dplus = -pivmin
327 work( indlpl+i ) = ld( i ) / dplus
328 IF(dplus.LT.zero) neg1 = neg1 + 1
329 work( inds+i ) = s*work( indlpl+i )*l( i )
330 IF( work( indlpl+i ).EQ.zero )
331 $ work( inds+i ) = lld( i )
332 s = work( inds+i ) - lambda
333 70 CONTINUE
334 DO 71 i = r1, r2 - 1
335 dplus = d( i ) + s
336 IF(abs(dplus).LT.pivmin) dplus = -pivmin
337 work( indlpl+i ) = ld( i ) / dplus
338 work( inds+i ) = s*work( indlpl+i )*l( i )
339 IF( work( indlpl+i ).EQ.zero )
340 $ work( inds+i ) = lld( i )
341 s = work( inds+i ) - lambda
342 71 CONTINUE
343 END IF
344*
345* Compute the progressive transform (using the differential form)
346* until the index R1
347*
348 sawnan2 = .false.
349 neg2 = 0
350 work( indp+bn-1 ) = d( bn ) - lambda
351 DO 80 i = bn - 1, r1, -1
352 dminus = lld( i ) + work( indp+i )
353 tmp = d( i ) / dminus
354 IF(dminus.LT.zero) neg2 = neg2 + 1
355 work( indumn+i ) = l( i )*tmp
356 work( indp+i-1 ) = work( indp+i )*tmp - lambda
357 80 CONTINUE
358 tmp = work( indp+r1-1 )
359 sawnan2 = sisnan( tmp )
360
361 IF( sawnan2 ) THEN
362* Runs a slower version of the above loop if a NaN is detected
363 neg2 = 0
364 DO 100 i = bn-1, r1, -1
365 dminus = lld( i ) + work( indp+i )
366 IF(abs(dminus).LT.pivmin) dminus = -pivmin
367 tmp = d( i ) / dminus
368 IF(dminus.LT.zero) neg2 = neg2 + 1
369 work( indumn+i ) = l( i )*tmp
370 work( indp+i-1 ) = work( indp+i )*tmp - lambda
371 IF( tmp.EQ.zero )
372 $ work( indp+i-1 ) = d( i ) - lambda
373 100 CONTINUE
374 END IF
375*
376* Find the index (from R1 to R2) of the largest (in magnitude)
377* diagonal element of the inverse
378*
379 mingma = work( inds+r1-1 ) + work( indp+r1-1 )
380 IF( mingma.LT.zero ) neg1 = neg1 + 1
381 IF( wantnc ) THEN
382 negcnt = neg1 + neg2
383 ELSE
384 negcnt = -1
385 ENDIF
386 IF( abs(mingma).EQ.zero )
387 $ mingma = eps*work( inds+r1-1 )
388 r = r1
389 DO 110 i = r1, r2 - 1
390 tmp = work( inds+i ) + work( indp+i )
391 IF( tmp.EQ.zero )
392 $ tmp = eps*work( inds+i )
393 IF( abs( tmp ).LE.abs( mingma ) ) THEN
394 mingma = tmp
395 r = i + 1
396 END IF
397 110 CONTINUE
398*
399* Compute the FP vector: solve N^T v = e_r
400*
401 isuppz( 1 ) = b1
402 isuppz( 2 ) = bn
403 z( r ) = cone
404 ztz = one
405*
406* Compute the FP vector upwards from R
407*
408 IF( .NOT.sawnan1 .AND. .NOT.sawnan2 ) THEN
409 DO 210 i = r-1, b1, -1
410 z( i ) = -( work( indlpl+i )*z( i+1 ) )
411 IF( (abs(z(i))+abs(z(i+1)))* abs(ld(i)).LT.gaptol )
412 $ THEN
413 z( i ) = zero
414 isuppz( 1 ) = i + 1
415 GOTO 220
416 ENDIF
417 ztz = ztz + real( z( i )*z( i ) )
418 210 CONTINUE
419 220 CONTINUE
420 ELSE
421* Run slower loop if NaN occurred.
422 DO 230 i = r - 1, b1, -1
423 IF( z( i+1 ).EQ.zero ) THEN
424 z( i ) = -( ld( i+1 ) / ld( i ) )*z( i+2 )
425 ELSE
426 z( i ) = -( work( indlpl+i )*z( i+1 ) )
427 END IF
428 IF( (abs(z(i))+abs(z(i+1)))* abs(ld(i)).LT.gaptol )
429 $ THEN
430 z( i ) = zero
431 isuppz( 1 ) = i + 1
432 GO TO 240
433 END IF
434 ztz = ztz + real( z( i )*z( i ) )
435 230 CONTINUE
436 240 CONTINUE
437 ENDIF
438
439* Compute the FP vector downwards from R in blocks of size BLKSIZ
440 IF( .NOT.sawnan1 .AND. .NOT.sawnan2 ) THEN
441 DO 250 i = r, bn-1
442 z( i+1 ) = -( work( indumn+i )*z( i ) )
443 IF( (abs(z(i))+abs(z(i+1)))* abs(ld(i)).LT.gaptol )
444 $ THEN
445 z( i+1 ) = zero
446 isuppz( 2 ) = i
447 GO TO 260
448 END IF
449 ztz = ztz + real( z( i+1 )*z( i+1 ) )
450 250 CONTINUE
451 260 CONTINUE
452 ELSE
453* Run slower loop if NaN occurred.
454 DO 270 i = r, bn - 1
455 IF( z( i ).EQ.zero ) THEN
456 z( i+1 ) = -( ld( i-1 ) / ld( i ) )*z( i-1 )
457 ELSE
458 z( i+1 ) = -( work( indumn+i )*z( i ) )
459 END IF
460 IF( (abs(z(i))+abs(z(i+1)))* abs(ld(i)).LT.gaptol )
461 $ THEN
462 z( i+1 ) = zero
463 isuppz( 2 ) = i
464 GO TO 280
465 END IF
466 ztz = ztz + real( z( i+1 )*z( i+1 ) )
467 270 CONTINUE
468 280 CONTINUE
469 END IF
470*
471* Compute quantities for convergence test
472*
473 tmp = one / ztz
474 nrminv = sqrt( tmp )
475 resid = abs( mingma )*nrminv
476 rqcorr = mingma*tmp
477*
478*
479 RETURN
480*
481* End of CLAR1V
482*
483 END
subroutine clar1v(n, b1, bn, lambda, d, l, ld, lld, pivmin, gaptol, z, wantnc, negcnt, ztz, mingma, r, isuppz, nrminv, resid, rqcorr, work)
CLAR1V computes the (scaled) r-th column of the inverse of the submatrix in rows b1 through bn of the...
Definition clar1v.f:228