LAPACK  3.4.2 LAPACK: Linear Algebra PACKage
dlarrf.f
Go to the documentation of this file.
1 *> \brief \b DLARRF finds a new relatively robust representation such that at least one of the eigenvalues is relatively isolated.
2 *
3 * =========== DOCUMENTATION ===========
4 *
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
7 *
8 *> \htmlonly
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarrf.f">
11 *> [TGZ]</a>
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarrf.f">
13 *> [ZIP]</a>
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarrf.f">
15 *> [TXT]</a>
16 *> \endhtmlonly
17 *
18 * Definition:
19 * ===========
20 *
21 * SUBROUTINE DLARRF( N, D, L, LD, CLSTRT, CLEND,
22 * W, WGAP, WERR,
23 * SPDIAM, CLGAPL, CLGAPR, PIVMIN, SIGMA,
24 * DPLUS, LPLUS, WORK, INFO )
25 *
26 * .. Scalar Arguments ..
27 * INTEGER CLSTRT, CLEND, INFO, N
28 * DOUBLE PRECISION CLGAPL, CLGAPR, PIVMIN, SIGMA, SPDIAM
29 * ..
30 * .. Array Arguments ..
31 * DOUBLE PRECISION D( * ), DPLUS( * ), L( * ), LD( * ),
32 * \$ LPLUS( * ), W( * ), WGAP( * ), WERR( * ), WORK( * )
33 * ..
34 *
35 *
36 *> \par Purpose:
37 * =============
38 *>
39 *> \verbatim
40 *>
41 *> Given the initial representation L D L^T and its cluster of close
42 *> eigenvalues (in a relative measure), W( CLSTRT ), W( CLSTRT+1 ), ...
43 *> W( CLEND ), DLARRF finds a new relatively robust representation
44 *> L D L^T - SIGMA I = L(+) D(+) L(+)^T such that at least one of the
45 *> eigenvalues of L(+) D(+) L(+)^T is relatively isolated.
46 *> \endverbatim
47 *
48 * Arguments:
49 * ==========
50 *
51 *> \param[in] N
52 *> \verbatim
53 *> N is INTEGER
54 *> The order of the matrix (subblock, if the matrix splitted).
55 *> \endverbatim
56 *>
57 *> \param[in] D
58 *> \verbatim
59 *> D is DOUBLE PRECISION array, dimension (N)
60 *> The N diagonal elements of the diagonal matrix D.
61 *> \endverbatim
62 *>
63 *> \param[in] L
64 *> \verbatim
65 *> L is DOUBLE PRECISION array, dimension (N-1)
66 *> The (N-1) subdiagonal elements of the unit bidiagonal
67 *> matrix L.
68 *> \endverbatim
69 *>
70 *> \param[in] LD
71 *> \verbatim
72 *> LD is DOUBLE PRECISION array, dimension (N-1)
73 *> The (N-1) elements L(i)*D(i).
74 *> \endverbatim
75 *>
76 *> \param[in] CLSTRT
77 *> \verbatim
78 *> CLSTRT is INTEGER
79 *> The index of the first eigenvalue in the cluster.
80 *> \endverbatim
81 *>
82 *> \param[in] CLEND
83 *> \verbatim
84 *> CLEND is INTEGER
85 *> The index of the last eigenvalue in the cluster.
86 *> \endverbatim
87 *>
88 *> \param[in] W
89 *> \verbatim
90 *> W is DOUBLE PRECISION array, dimension
91 *> dimension is >= (CLEND-CLSTRT+1)
92 *> The eigenvalue APPROXIMATIONS of L D L^T in ascending order.
93 *> W( CLSTRT ) through W( CLEND ) form the cluster of relatively
94 *> close eigenalues.
95 *> \endverbatim
96 *>
97 *> \param[in,out] WGAP
98 *> \verbatim
99 *> WGAP is DOUBLE PRECISION array, dimension
100 *> dimension is >= (CLEND-CLSTRT+1)
101 *> The separation from the right neighbor eigenvalue in W.
102 *> \endverbatim
103 *>
104 *> \param[in] WERR
105 *> \verbatim
106 *> WERR is DOUBLE PRECISION array, dimension
107 *> dimension is >= (CLEND-CLSTRT+1)
108 *> WERR contain the semiwidth of the uncertainty
109 *> interval of the corresponding eigenvalue APPROXIMATION in W
110 *> \endverbatim
111 *>
112 *> \param[in] SPDIAM
113 *> \verbatim
114 *> SPDIAM is DOUBLE PRECISION
115 *> estimate of the spectral diameter obtained from the
116 *> Gerschgorin intervals
117 *> \endverbatim
118 *>
119 *> \param[in] CLGAPL
120 *> \verbatim
121 *> CLGAPL is DOUBLE PRECISION
122 *> \endverbatim
123 *>
124 *> \param[in] CLGAPR
125 *> \verbatim
126 *> CLGAPR is DOUBLE PRECISION
127 *> absolute gap on each end of the cluster.
128 *> Set by the calling routine to protect against shifts too close
129 *> to eigenvalues outside the cluster.
130 *> \endverbatim
131 *>
132 *> \param[in] PIVMIN
133 *> \verbatim
134 *> PIVMIN is DOUBLE PRECISION
135 *> The minimum pivot allowed in the Sturm sequence.
136 *> \endverbatim
137 *>
138 *> \param[out] SIGMA
139 *> \verbatim
140 *> SIGMA is DOUBLE PRECISION
141 *> The shift used to form L(+) D(+) L(+)^T.
142 *> \endverbatim
143 *>
144 *> \param[out] DPLUS
145 *> \verbatim
146 *> DPLUS is DOUBLE PRECISION array, dimension (N)
147 *> The N diagonal elements of the diagonal matrix D(+).
148 *> \endverbatim
149 *>
150 *> \param[out] LPLUS
151 *> \verbatim
152 *> LPLUS is DOUBLE PRECISION array, dimension (N-1)
153 *> The first (N-1) elements of LPLUS contain the subdiagonal
154 *> elements of the unit bidiagonal matrix L(+).
155 *> \endverbatim
156 *>
157 *> \param[out] WORK
158 *> \verbatim
159 *> WORK is DOUBLE PRECISION array, dimension (2*N)
160 *> Workspace.
161 *> \endverbatim
162 *>
163 *> \param[out] INFO
164 *> \verbatim
165 *> INFO is INTEGER
166 *> Signals processing OK (=0) or failure (=1)
167 *> \endverbatim
168 *
169 * Authors:
170 * ========
171 *
172 *> \author Univ. of Tennessee
173 *> \author Univ. of California Berkeley
174 *> \author Univ. of Colorado Denver
175 *> \author NAG Ltd.
176 *
177 *> \date September 2012
178 *
179 *> \ingroup auxOTHERauxiliary
180 *
181 *> \par Contributors:
182 * ==================
183 *>
184 *> Beresford Parlett, University of California, Berkeley, USA \n
185 *> Jim Demmel, University of California, Berkeley, USA \n
186 *> Inderjit Dhillon, University of Texas, Austin, USA \n
187 *> Osni Marques, LBNL/NERSC, USA \n
188 *> Christof Voemel, University of California, Berkeley, USA
189 *
190 * =====================================================================
191  SUBROUTINE dlarrf( N, D, L, LD, CLSTRT, CLEND,
192  \$ w, wgap, werr,
193  \$ spdiam, clgapl, clgapr, pivmin, sigma,
194  \$ dplus, lplus, work, info )
195 *
196 * -- LAPACK auxiliary routine (version 3.4.2) --
197 * -- LAPACK is a software package provided by Univ. of Tennessee, --
198 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
199 * September 2012
200 *
201 * .. Scalar Arguments ..
202  INTEGER clstrt, clend, info, n
203  DOUBLE PRECISION clgapl, clgapr, pivmin, sigma, spdiam
204 * ..
205 * .. Array Arguments ..
206  DOUBLE PRECISION d( * ), dplus( * ), l( * ), ld( * ),
207  \$ lplus( * ), w( * ), wgap( * ), werr( * ), work( * )
208 * ..
209 *
210 * =====================================================================
211 *
212 * .. Parameters ..
213  DOUBLE PRECISION four, maxgrowth1, maxgrowth2, one, quart, two
214  parameter( one = 1.0d0, two = 2.0d0, four = 4.0d0,
215  \$ quart = 0.25d0,
216  \$ maxgrowth1 = 8.d0,
217  \$ maxgrowth2 = 8.d0 )
218 * ..
219 * .. Local Scalars ..
220  LOGICAL dorrr1, forcer, nofail, sawnan1, sawnan2, tryrrr1
221  INTEGER i, indx, ktry, ktrymax, sleft, sright, shift
222  parameter( ktrymax = 1, sleft = 1, sright = 2 )
223  DOUBLE PRECISION avgap, bestshift, clwdth, eps, fact, fail,
224  \$ fail2, growthbound, ldelta, ldmax, lsigma,
225  \$ max1, max2, mingap, oldp, prod, rdelta, rdmax,
226  \$ rrr1, rrr2, rsigma, s, smlgrowth, tmp, znm2
227 * ..
228 * .. External Functions ..
229  LOGICAL disnan
230  DOUBLE PRECISION dlamch
231  EXTERNAL disnan, dlamch
232 * ..
233 * .. External Subroutines ..
234  EXTERNAL dcopy
235 * ..
236 * .. Intrinsic Functions ..
237  INTRINSIC abs
238 * ..
239 * .. Executable Statements ..
240 *
241  info = 0
242  fact = dble(2**ktrymax)
243  eps = dlamch( 'Precision' )
244  shift = 0
245  forcer = .false.
246
247
248 * Note that we cannot guarantee that for any of the shifts tried,
249 * the factorization has a small or even moderate element growth.
250 * There could be Ritz values at both ends of the cluster and despite
251 * backing off, there are examples where all factorizations tried
252 * (in IEEE mode, allowing zero pivots & infinities) have INFINITE
253 * element growth.
254 * For this reason, we should use PIVMIN in this subroutine so that at
255 * least the L D L^T factorization exists. It can be checked afterwards
256 * whether the element growth caused bad residuals/orthogonality.
257
258 * Decide whether the code should accept the best among all
259 * representations despite large element growth or signal INFO=1
260  nofail = .true.
261 *
262
263 * Compute the average gap length of the cluster
264  clwdth = abs(w(clend)-w(clstrt)) + werr(clend) + werr(clstrt)
265  avgap = clwdth / dble(clend-clstrt)
266  mingap = min(clgapl, clgapr)
267 * Initial values for shifts to both ends of cluster
268  lsigma = min(w( clstrt ),w( clend )) - werr( clstrt )
269  rsigma = max(w( clstrt ),w( clend )) + werr( clend )
270
271 * Use a small fudge to make sure that we really shift to the outside
272  lsigma = lsigma - abs(lsigma)* four * eps
273  rsigma = rsigma + abs(rsigma)* four * eps
274
275 * Compute upper bounds for how much to back off the initial shifts
276  ldmax = quart * mingap + two * pivmin
277  rdmax = quart * mingap + two * pivmin
278
279  ldelta = max(avgap,wgap( clstrt ))/fact
280  rdelta = max(avgap,wgap( clend-1 ))/fact
281 *
282 * Initialize the record of the best representation found
283 *
284  s = dlamch( 'S' )
285  smlgrowth = one / s
286  fail = dble(n-1)*mingap/(spdiam*eps)
287  fail2 = dble(n-1)*mingap/(spdiam*sqrt(eps))
288  bestshift = lsigma
289 *
290 * while (KTRY <= KTRYMAX)
291  ktry = 0
292  growthbound = maxgrowth1*spdiam
293
294  5 continue
295  sawnan1 = .false.
296  sawnan2 = .false.
297 * Ensure that we do not back off too much of the initial shifts
298  ldelta = min(ldmax,ldelta)
299  rdelta = min(rdmax,rdelta)
300
301 * Compute the element growth when shifting to both ends of the cluster
302 * accept the shift if there is no element growth at one of the two ends
303
304 * Left end
305  s = -lsigma
306  dplus( 1 ) = d( 1 ) + s
307  IF(abs(dplus(1)).LT.pivmin) THEN
308  dplus(1) = -pivmin
309 * Need to set SAWNAN1 because refined RRR test should not be used
310 * in this case
311  sawnan1 = .true.
312  ENDIF
313  max1 = abs( dplus( 1 ) )
314  DO 6 i = 1, n - 1
315  lplus( i ) = ld( i ) / dplus( i )
316  s = s*lplus( i )*l( i ) - lsigma
317  dplus( i+1 ) = d( i+1 ) + s
318  IF(abs(dplus(i+1)).LT.pivmin) THEN
319  dplus(i+1) = -pivmin
320 * Need to set SAWNAN1 because refined RRR test should not be used
321 * in this case
322  sawnan1 = .true.
323  ENDIF
324  max1 = max( max1,abs(dplus(i+1)) )
325  6 continue
326  sawnan1 = sawnan1 .OR. disnan( max1 )
327
328  IF( forcer .OR.
329  \$ (max1.LE.growthbound .AND. .NOT.sawnan1 ) ) THEN
330  sigma = lsigma
331  shift = sleft
332  goto 100
333  ENDIF
334
335 * Right end
336  s = -rsigma
337  work( 1 ) = d( 1 ) + s
338  IF(abs(work(1)).LT.pivmin) THEN
339  work(1) = -pivmin
340 * Need to set SAWNAN2 because refined RRR test should not be used
341 * in this case
342  sawnan2 = .true.
343  ENDIF
344  max2 = abs( work( 1 ) )
345  DO 7 i = 1, n - 1
346  work( n+i ) = ld( i ) / work( i )
347  s = s*work( n+i )*l( i ) - rsigma
348  work( i+1 ) = d( i+1 ) + s
349  IF(abs(work(i+1)).LT.pivmin) THEN
350  work(i+1) = -pivmin
351 * Need to set SAWNAN2 because refined RRR test should not be used
352 * in this case
353  sawnan2 = .true.
354  ENDIF
355  max2 = max( max2,abs(work(i+1)) )
356  7 continue
357  sawnan2 = sawnan2 .OR. disnan( max2 )
358
359  IF( forcer .OR.
360  \$ (max2.LE.growthbound .AND. .NOT.sawnan2 ) ) THEN
361  sigma = rsigma
362  shift = sright
363  goto 100
364  ENDIF
365 * If we are at this point, both shifts led to too much element growth
366
367 * Record the better of the two shifts (provided it didn't lead to NaN)
368  IF(sawnan1.AND.sawnan2) THEN
369 * both MAX1 and MAX2 are NaN
370  goto 50
371  ELSE
372  IF( .NOT.sawnan1 ) THEN
373  indx = 1
374  IF(max1.LE.smlgrowth) THEN
375  smlgrowth = max1
376  bestshift = lsigma
377  ENDIF
378  ENDIF
379  IF( .NOT.sawnan2 ) THEN
380  IF(sawnan1 .OR. max2.LE.max1) indx = 2
381  IF(max2.LE.smlgrowth) THEN
382  smlgrowth = max2
383  bestshift = rsigma
384  ENDIF
385  ENDIF
386  ENDIF
387
388 * If we are here, both the left and the right shift led to
389 * element growth. If the element growth is moderate, then
390 * we may still accept the representation, if it passes a
391 * refined test for RRR. This test supposes that no NaN occurred.
392 * Moreover, we use the refined RRR test only for isolated clusters.
393  IF((clwdth.LT.mingap/dble(128)) .AND.
394  \$ (min(max1,max2).LT.fail2)
395  \$ .AND.(.NOT.sawnan1).AND.(.NOT.sawnan2)) THEN
396  dorrr1 = .true.
397  ELSE
398  dorrr1 = .false.
399  ENDIF
400  tryrrr1 = .true.
401  IF( tryrrr1 .AND. dorrr1 ) THEN
402  IF(indx.EQ.1) THEN
403  tmp = abs( dplus( n ) )
404  znm2 = one
405  prod = one
406  oldp = one
407  DO 15 i = n-1, 1, -1
408  IF( prod .LE. eps ) THEN
409  prod =
410  \$ ((dplus(i+1)*work(n+i+1))/(dplus(i)*work(n+i)))*oldp
411  ELSE
412  prod = prod*abs(work(n+i))
413  END IF
414  oldp = prod
415  znm2 = znm2 + prod**2
416  tmp = max( tmp, abs( dplus( i ) * prod ))
417  15 continue
418  rrr1 = tmp/( spdiam * sqrt( znm2 ) )
419  IF (rrr1.LE.maxgrowth2) THEN
420  sigma = lsigma
421  shift = sleft
422  goto 100
423  ENDIF
424  ELSE IF(indx.EQ.2) THEN
425  tmp = abs( work( n ) )
426  znm2 = one
427  prod = one
428  oldp = one
429  DO 16 i = n-1, 1, -1
430  IF( prod .LE. eps ) THEN
431  prod = ((work(i+1)*lplus(i+1))/(work(i)*lplus(i)))*oldp
432  ELSE
433  prod = prod*abs(lplus(i))
434  END IF
435  oldp = prod
436  znm2 = znm2 + prod**2
437  tmp = max( tmp, abs( work( i ) * prod ))
438  16 continue
439  rrr2 = tmp/( spdiam * sqrt( znm2 ) )
440  IF (rrr2.LE.maxgrowth2) THEN
441  sigma = rsigma
442  shift = sright
443  goto 100
444  ENDIF
445  END IF
446  ENDIF
447
448  50 continue
449
450  IF (ktry.LT.ktrymax) THEN
451 * If we are here, both shifts failed also the RRR test.
452 * Back off to the outside
453  lsigma = max( lsigma - ldelta,
454  \$ lsigma - ldmax)
455  rsigma = min( rsigma + rdelta,
456  \$ rsigma + rdmax )
457  ldelta = two * ldelta
458  rdelta = two * rdelta
459  ktry = ktry + 1
460  goto 5
461  ELSE
462 * None of the representations investigated satisfied our
463 * criteria. Take the best one we found.
464  IF((smlgrowth.LT.fail).OR.nofail) THEN
465  lsigma = bestshift
466  rsigma = bestshift
467  forcer = .true.
468  goto 5
469  ELSE
470  info = 1
471  return
472  ENDIF
473  END IF
474
475  100 continue
476  IF (shift.EQ.sleft) THEN
477  elseif(shift.EQ.sright) THEN
478 * store new L and D back into DPLUS, LPLUS
479  CALL dcopy( n, work, 1, dplus, 1 )
480  CALL dcopy( n-1, work(n+1), 1, lplus, 1 )
481  ENDIF
482
483  return
484 *
485 * End of DLARRF
486 *
487  END