LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ dlarrb()

subroutine dlarrb ( integer n,
double precision, dimension( * ) d,
double precision, dimension( * ) lld,
integer ifirst,
integer ilast,
double precision rtol1,
double precision rtol2,
integer offset,
double precision, dimension( * ) w,
double precision, dimension( * ) wgap,
double precision, dimension( * ) werr,
double precision, dimension( * ) work,
integer, dimension( * ) iwork,
double precision pivmin,
double precision spdiam,
integer twist,
integer info )

DLARRB provides limited bisection to locate eigenvalues for more accuracy.

Download DLARRB + dependencies [TGZ] [ZIP] [TXT]

Purpose:
!>
!> Given the relatively robust representation(RRR) L D L^T, DLARRB
!> does  bisection to refine the eigenvalues of L D L^T,
!> W( IFIRST-OFFSET ) through W( ILAST-OFFSET ), to more accuracy. Initial
!> guesses for these eigenvalues are input in W, the corresponding estimate
!> of the error in these guesses and their gaps are input in WERR
!> and WGAP, respectively. During bisection, intervals
!> [left, right] are maintained by storing their mid-points and
!> semi-widths in the arrays W and WERR respectively.
!> 
Parameters
[in]N
!>          N is INTEGER
!>          The order of the matrix.
!> 
[in]D
!>          D is DOUBLE PRECISION array, dimension (N)
!>          The N diagonal elements of the diagonal matrix D.
!> 
[in]LLD
!>          LLD is DOUBLE PRECISION array, dimension (N-1)
!>          The (N-1) elements L(i)*L(i)*D(i).
!> 
[in]IFIRST
!>          IFIRST is INTEGER
!>          The index of the first eigenvalue to be computed.
!> 
[in]ILAST
!>          ILAST is INTEGER
!>          The index of the last eigenvalue to be computed.
!> 
[in]RTOL1
!>          RTOL1 is DOUBLE PRECISION
!> 
[in]RTOL2
!>          RTOL2 is DOUBLE PRECISION
!>          Tolerance for the convergence of the bisection intervals.
!>          An interval [LEFT,RIGHT] has converged if
!>          RIGHT-LEFT < MAX( RTOL1*GAP, RTOL2*MAX(|LEFT|,|RIGHT|) )
!>          where GAP is the (estimated) distance to the nearest
!>          eigenvalue.
!> 
[in]OFFSET
!>          OFFSET is INTEGER
!>          Offset for the arrays W, WGAP and WERR, i.e., the IFIRST-OFFSET
!>          through ILAST-OFFSET elements of these arrays are to be used.
!> 
[in,out]W
!>          W is DOUBLE PRECISION array, dimension (N)
!>          On input, W( IFIRST-OFFSET ) through W( ILAST-OFFSET ) are
!>          estimates of the eigenvalues of L D L^T indexed IFIRST through
!>          ILAST.
!>          On output, these estimates are refined.
!> 
[in,out]WGAP
!>          WGAP is DOUBLE PRECISION array, dimension (N-1)
!>          On input, the (estimated) gaps between consecutive
!>          eigenvalues of L D L^T, i.e., WGAP(I-OFFSET) is the gap between
!>          eigenvalues I and I+1. Note that if IFIRST = ILAST
!>          then WGAP(IFIRST-OFFSET) must be set to ZERO.
!>          On output, these gaps are refined.
!> 
[in,out]WERR
!>          WERR is DOUBLE PRECISION array, dimension (N)
!>          On input, WERR( IFIRST-OFFSET ) through WERR( ILAST-OFFSET ) are
!>          the errors in the estimates of the corresponding elements in W.
!>          On output, these errors are refined.
!> 
[out]WORK
!>          WORK is DOUBLE PRECISION array, dimension (2*N)
!>          Workspace.
!> 
[out]IWORK
!>          IWORK is INTEGER array, dimension (2*N)
!>          Workspace.
!> 
[in]PIVMIN
!>          PIVMIN is DOUBLE PRECISION
!>          The minimum pivot in the Sturm sequence.
!> 
[in]SPDIAM
!>          SPDIAM is DOUBLE PRECISION
!>          The spectral diameter of the matrix.
!> 
[in]TWIST
!>          TWIST is INTEGER
!>          The twist index for the twisted factorization that is used
!>          for the negcount.
!>          TWIST = N: Compute negcount from L D L^T - LAMBDA I = L+ D+ L+^T
!>          TWIST = 1: Compute negcount from L D L^T - LAMBDA I = U- D- U-^T
!>          TWIST = R: Compute negcount from L D L^T - LAMBDA I = N(r) D(r) N(r)
!> 
[out]INFO
!>          INFO is INTEGER
!>          Error flag.
!> 
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.
Contributors:
Beresford Parlett, University of California, Berkeley, USA
Jim Demmel, University of California, Berkeley, USA
Inderjit Dhillon, University of Texas, Austin, USA
Osni Marques, LBNL/NERSC, USA
Christof Voemel, University of California, Berkeley, USA

Definition at line 191 of file dlarrb.f.

194*
195* -- LAPACK auxiliary routine --
196* -- LAPACK is a software package provided by Univ. of Tennessee, --
197* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
198*
199* .. Scalar Arguments ..
200 INTEGER IFIRST, ILAST, INFO, N, OFFSET, TWIST
201 DOUBLE PRECISION PIVMIN, RTOL1, RTOL2, SPDIAM
202* ..
203* .. Array Arguments ..
204 INTEGER IWORK( * )
205 DOUBLE PRECISION D( * ), LLD( * ), W( * ),
206 $ WERR( * ), WGAP( * ), WORK( * )
207* ..
208*
209* =====================================================================
210*
211* .. Parameters ..
212 DOUBLE PRECISION ZERO, TWO, HALF
213 parameter( zero = 0.0d0, two = 2.0d0,
214 $ half = 0.5d0 )
215 INTEGER MAXITR
216* ..
217* .. Local Scalars ..
218 INTEGER I, I1, II, IP, ITER, K, NEGCNT, NEXT, NINT,
219 $ OLNINT, PREV, R
220 DOUBLE PRECISION BACK, CVRGD, GAP, LEFT, LGAP, MID, MNWDTH,
221 $ RGAP, RIGHT, TMP, WIDTH
222* ..
223* .. External Functions ..
224 INTEGER DLANEG
225 EXTERNAL dlaneg
226*
227* ..
228* .. Intrinsic Functions ..
229 INTRINSIC abs, max, min
230* ..
231* .. Executable Statements ..
232*
233 info = 0
234*
235* Quick return if possible
236*
237 IF( n.LE.0 ) THEN
238 RETURN
239 END IF
240*
241 maxitr = int( ( log( spdiam+pivmin )-log( pivmin ) ) /
242 $ log( two ) ) + 2
243 mnwdth = two * pivmin
244*
245 r = twist
246 IF((r.LT.1).OR.(r.GT.n)) r = n
247*
248* Initialize unconverged intervals in [ WORK(2*I-1), WORK(2*I) ].
249* The Sturm Count, Count( WORK(2*I-1) ) is arranged to be I-1, while
250* Count( WORK(2*I) ) is stored in IWORK( 2*I ). The integer IWORK( 2*I-1 )
251* for an unconverged interval is set to the index of the next unconverged
252* interval, and is -1 or 0 for a converged interval. Thus a linked
253* list of unconverged intervals is set up.
254*
255 i1 = ifirst
256* The number of unconverged intervals
257 nint = 0
258* The last unconverged interval found
259 prev = 0
260
261 rgap = wgap( i1-offset )
262 DO 75 i = i1, ilast
263 k = 2*i
264 ii = i - offset
265 left = w( ii ) - werr( ii )
266 right = w( ii ) + werr( ii )
267 lgap = rgap
268 rgap = wgap( ii )
269 gap = min( lgap, rgap )
270
271* Make sure that [LEFT,RIGHT] contains the desired eigenvalue
272* Compute negcount from dstqds facto L+D+L+^T = L D L^T - LEFT
273*
274* Do while( NEGCNT(LEFT).GT.I-1 )
275*
276 back = werr( ii )
277 20 CONTINUE
278 negcnt = dlaneg( n, d, lld, left, pivmin, r )
279 IF( negcnt.GT.i-1 ) THEN
280 left = left - back
281 back = two*back
282 GO TO 20
283 END IF
284*
285* Do while( NEGCNT(RIGHT).LT.I )
286* Compute negcount from dstqds facto L+D+L+^T = L D L^T - RIGHT
287*
288 back = werr( ii )
289 50 CONTINUE
290
291 negcnt = dlaneg( n, d, lld, right, pivmin, r )
292 IF( negcnt.LT.i ) THEN
293 right = right + back
294 back = two*back
295 GO TO 50
296 END IF
297 width = half*abs( left - right )
298 tmp = max( abs( left ), abs( right ) )
299 cvrgd = max(rtol1*gap,rtol2*tmp)
300 IF( width.LE.cvrgd .OR. width.LE.mnwdth ) THEN
301* This interval has already converged and does not need refinement.
302* (Note that the gaps might change through refining the
303* eigenvalues, however, they can only get bigger.)
304* Remove it from the list.
305 iwork( k-1 ) = -1
306* Make sure that I1 always points to the first unconverged interval
307 IF((i.EQ.i1).AND.(i.LT.ilast)) i1 = i + 1
308 IF((prev.GE.i1).AND.(i.LE.ilast)) iwork( 2*prev-1 ) = i + 1
309 ELSE
310* unconverged interval found
311 prev = i
312 nint = nint + 1
313 iwork( k-1 ) = i + 1
314 iwork( k ) = negcnt
315 END IF
316 work( k-1 ) = left
317 work( k ) = right
318 75 CONTINUE
319
320*
321* Do while( NINT.GT.0 ), i.e. there are still unconverged intervals
322* and while (ITER.LT.MAXITR)
323*
324 iter = 0
325 80 CONTINUE
326 prev = i1 - 1
327 i = i1
328 olnint = nint
329
330 DO 100 ip = 1, olnint
331 k = 2*i
332 ii = i - offset
333 rgap = wgap( ii )
334 lgap = rgap
335 IF(ii.GT.1) lgap = wgap( ii-1 )
336 gap = min( lgap, rgap )
337 next = iwork( k-1 )
338 left = work( k-1 )
339 right = work( k )
340 mid = half*( left + right )
341
342* semiwidth of interval
343 width = right - mid
344 tmp = max( abs( left ), abs( right ) )
345 cvrgd = max(rtol1*gap,rtol2*tmp)
346 IF( ( width.LE.cvrgd ) .OR. ( width.LE.mnwdth ).OR.
347 $ ( iter.EQ.maxitr ) )THEN
348* reduce number of unconverged intervals
349 nint = nint - 1
350* Mark interval as converged.
351 iwork( k-1 ) = 0
352 IF( i1.EQ.i ) THEN
353 i1 = next
354 ELSE
355* Prev holds the last unconverged interval previously examined
356 IF(prev.GE.i1) iwork( 2*prev-1 ) = next
357 END IF
358 i = next
359 GO TO 100
360 END IF
361 prev = i
362*
363* Perform one bisection step
364*
365 negcnt = dlaneg( n, d, lld, mid, pivmin, r )
366 IF( negcnt.LE.i-1 ) THEN
367 work( k-1 ) = mid
368 ELSE
369 work( k ) = mid
370 END IF
371 i = next
372 100 CONTINUE
373 iter = iter + 1
374* do another loop if there are still unconverged intervals
375* However, in the last iteration, all intervals are accepted
376* since this is the best we can do.
377 IF( ( nint.GT.0 ).AND.(iter.LE.maxitr) ) GO TO 80
378*
379*
380* At this point, all the intervals have converged
381 DO 110 i = ifirst, ilast
382 k = 2*i
383 ii = i - offset
384* All intervals marked by '0' have been refined.
385 IF( iwork( k-1 ).EQ.0 ) THEN
386 w( ii ) = half*( work( k-1 )+work( k ) )
387 werr( ii ) = work( k ) - w( ii )
388 END IF
389 110 CONTINUE
390*
391 DO 111 i = ifirst+1, ilast
392 k = 2*i
393 ii = i - offset
394 wgap( ii-1 ) = max( zero,
395 $ w(ii) - werr(ii) - w( ii-1 ) - werr( ii-1 ))
396 111 CONTINUE
397
398 RETURN
399*
400* End of DLARRB
401*
integer function dlaneg(n, d, lld, sigma, pivmin, r)
DLANEG computes the Sturm count.
Definition dlaneg.f:116
Here is the caller graph for this function: