6
7
8
9
10
11
12 CHARACTER RANGE
13 INTEGER DOL, DOU, IL, INFO, IU, M, N, NSPLIT
14 DOUBLE PRECISION PIVMIN, RTOL1, RTOL2, SPLTOL, VL, VU
15
16
17 INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * ),
18 $ INDEXW( * )
19 DOUBLE PRECISION D( * ), E( * ), E2( * ), GERS( * ),
20 $ W( * ),WERR( * ), WGAP( * ), WORK( * )
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192 DOUBLE PRECISION FAC, FOUR, FOURTH, FUDGE, HALF, HNDRD,
193 $ MAXGROWTH, ONE, PERT, TWO, ZERO
194 parameter( zero = 0.0d0, one = 1.0d0,
195 $ two = 2.0d0, four=4.0d0,
196 $ hndrd = 100.0d0,
197 $ pert = 8.0d0,
198 $ half = one/two, fourth = one/four, fac= half,
199 $ maxgrowth = 64.0d0, fudge = 2.0d0 )
200 INTEGER MAXTRY
201 parameter( maxtry = 6 )
202
203
204 LOGICAL FORCEB, NOREP, RNDPRT, USEDQD
205 INTEGER CNT, CNT1, CNT2, I, IBEGIN, IDUM, IEND, IINFO,
206 $ IN, INDL, INDU, IRANGE, J, JBLK, MB, MM,
207 $ WBEGIN, WEND
208 DOUBLE PRECISION AVGAP, BSRTOL, CLWDTH, DMAX, DPIVOT, EABS,
209 $ EMAX, EOLD, EPS, GL, GU, ISLEFT, ISRGHT, RTL,
210 $ RTOL, S1, S2, SAFMIN, SGNDEF, SIGMA, SPDIAM,
211 $ TAU, TMP, TMP1
212
213
214
215
216 INTEGER ISEED( 4 )
217
218
219 LOGICAL LSAME
220 DOUBLE PRECISION DLAMCH
222
223
224
225 EXTERNAL dcopy, dlarnv, dlarra, dlarrb, dlarrc,
226 $ dlarrd, dlasq2
227
228
230
231
232
233
234
235 info = 0
236
237
238 rndprt = .true.
239
240
241
242 IF(
lsame( range,
'A' ) )
THEN
243 irange = 1
244 ELSE IF(
lsame( range,
'V' ) )
THEN
245 irange = 2
246 ELSE IF(
lsame( range,
'I' ) )
THEN
247 irange = 3
248 END IF
249
250 m = 0
251
252
255
256
257 rtl = sqrt(eps)
258 bsrtol = 1.0d-1
259
260
261 IF( n.EQ.1 ) THEN
262 IF( (irange.EQ.1).OR.
263 $ ((irange.EQ.2).AND.(d(1).GT.vl).AND.(d(1).LE.vu)).OR.
264 $ ((irange.EQ.3).AND.(il.EQ.1).AND.(iu.EQ.1)) ) THEN
265 m = 1
266 w(1) = d(1)
267
268 werr(1) = zero
269 wgap(1) = zero
270 iblock( 1 ) = 1
271 indexw( 1 ) = 1
272 gers(1) = d( 1 )
273 gers(2) = d( 1 )
274 ENDIF
275
276 e(1) = zero
277 RETURN
278 END IF
279
280
281
282
283
284 gl = d(1)
285 gu = d(1)
286 eold = zero
287 emax = zero
288 e(n) = zero
289 DO 5 i = 1,n
290 werr(i) = zero
291 wgap(i) = zero
292 eabs = abs( e(i) )
293 IF( eabs .GE. emax ) THEN
294 emax = eabs
295 END IF
296 tmp1 = eabs + eold
297 gers( 2*i-1) = d(i) - tmp1
298 gl =
min( gl, gers( 2*i - 1))
299 gers( 2*i ) = d(i) + tmp1
300 gu =
max( gu, gers(2*i) )
301 eold = eabs
302 5 CONTINUE
303
304 pivmin = safmin *
max( one, emax**2 )
305
306
307 spdiam = gu - gl
308
309
310 CALL dlarra( n, d, e, e2, spltol, spdiam,
311 $ nsplit, isplit, iinfo )
312
313
314 forceb = .false.
315
316 IF( (irange.EQ.1) .AND. (.NOT. forceb) ) THEN
317
318 vl = gl
319 vu = gu
320 ELSE
321
322
323
324
325
326
327 CALL dlarrd( range, 'B', n, vl, vu, il, iu, gers,
328 $ bsrtol, d, e, e2, pivmin, nsplit, isplit,
329 $ mm, w, werr, vl, vu, iblock, indexw,
330 $ work, iwork, iinfo )
331 IF( iinfo.NE.0 ) THEN
332 info = -1
333 RETURN
334 ENDIF
335
336 DO 14 i = mm+1,n
337 w( i ) = zero
338 werr( i ) = zero
339 iblock( i ) = 0
340 indexw( i ) = 0
341 14 CONTINUE
342 END IF
343
344
345
346
347 ibegin = 1
348 wbegin = 1
349 DO 170 jblk = 1, nsplit
350 iend = isplit( jblk )
351 in = iend - ibegin + 1
352
353
354 IF( in.EQ.1 ) THEN
355 IF( (irange.EQ.1).OR.( (irange.EQ.2).AND.
356 $ ( d( ibegin ).GT.vl ).AND.( d( ibegin ).LE.vu ) )
357 $ .OR. ( (irange.EQ.3).AND.(iblock(wbegin).EQ.jblk))
358 $ ) THEN
359 m = m + 1
360 w( m ) = d( ibegin )
361 werr(m) = zero
362
363
364 wgap(m) = zero
365 iblock( m ) = jblk
366 indexw( m ) = 1
367 wbegin = wbegin + 1
368 ENDIF
369
370 e( iend ) = zero
371 ibegin = iend + 1
372 GO TO 170
373 END IF
374
375
376
377
378 e( iend ) = zero
379
380
381 gl = d(ibegin)
382 gu = d(ibegin)
383 DO 15 i = ibegin , iend
384 gl =
min( gers( 2*i-1 ), gl )
385 gu =
max( gers( 2*i ), gu )
386 15 CONTINUE
387 spdiam = gu - gl
388
389 IF(.NOT. ((irange.EQ.1).AND.(.NOT.forceb)) ) THEN
390
391 mb = 0
392 DO 20 i = wbegin,mm
393 IF( iblock(i).EQ.jblk ) THEN
394 mb = mb+1
395 ELSE
396 GOTO 21
397 ENDIF
398 20 CONTINUE
399 21 CONTINUE
400
401 IF( mb.EQ.0) THEN
402
403
404 e( iend ) = zero
405 ibegin = iend + 1
406 GO TO 170
407 ELSE
408
409
410 usedqd = ( (mb .GT. fac*in) .AND. (.NOT.forceb) )
411 wend = wbegin + mb - 1
412
413
414
415 sigma = zero
416 DO 30 i = wbegin, wend - 1
417 wgap( i ) =
max( zero,
418 $ w(i+1)-werr(i+1) - (w(i)+werr(i)) )
419 30 CONTINUE
420 wgap( wend ) =
max( zero,
421 $ vu - sigma - (w( wend )+werr( wend )))
422
423 indl = indexw(wbegin)
424 indu = indexw( wend )
425 ENDIF
426 ELSE
427
428 mb = in
429 wend = wbegin + mb - 1
430 indl = 1
431 indu = in
432 ENDIF
433
434 IF( (wend.LT.dol).OR.(wbegin.GT.dou) ) THEN
435
436
437 ibegin = iend + 1
438 wbegin = wend + 1
439 m = m + indu - indl + 1
440 GO TO 170
441 END IF
442
443
444 CALL dlarrk( in, 1, gl, gu, d(ibegin),
445 $ e2(ibegin), pivmin, rtl, tmp, tmp1, iinfo )
446 IF( iinfo.NE.0 ) THEN
447 info = -1
448 RETURN
449 ENDIF
450 isleft =
max(gl, tmp - tmp1
451 $ - hndrd * eps* abs(tmp - tmp1))
452 CALL dlarrk( in, in, gl, gu, d(ibegin),
453 $ e2(ibegin), pivmin, rtl, tmp, tmp1, iinfo )
454 IF( iinfo.NE.0 ) THEN
455 info = -1
456 RETURN
457 ENDIF
458 isrght =
min(gu, tmp + tmp1
459 $ + hndrd * eps * abs(tmp + tmp1))
460 IF(( (irange.EQ.1) .AND. (.NOT. forceb) ).OR.usedqd) THEN
461
462
463 spdiam = isrght - isleft
464 ELSE
465
466
467 isleft =
max(gl, w(wbegin) - werr(wbegin)
468 $ - hndrd * eps*abs(w(wbegin)- werr(wbegin) ))
469 isrght =
min(gu,w(wend) + werr(wend)
470 $ + hndrd * eps * abs(w(wend)+ werr(wend)))
471 ENDIF
472
473
474
475
476
477
478
479
480
481
482 IF( ( irange.EQ.1 ) .AND. (.NOT.forceb) ) THEN
483
484 usedqd = .true.
485
486 indl = 1
487 indu = in
488
489 mb = in
490 wend = wbegin + mb - 1
491
492 s1 = isleft + fourth * spdiam
493 s2 = isrght - fourth * spdiam
494 ELSE
495
496
497
498 IF( usedqd ) THEN
499 s1 = isleft + fourth * spdiam
500 s2 = isrght - fourth * spdiam
501 ELSE
502 tmp =
min(isrght,vu) -
max(isleft,vl)
503 s1 =
max(isleft,vl) + fourth * tmp
504 s2 =
min(isrght,vu) - fourth * tmp
505 ENDIF
506 ENDIF
507
508
509 IF(mb.GT.1) THEN
510 CALL dlarrc( 'T', in, s1, s2, d(ibegin),
511 $ e(ibegin), pivmin, cnt, cnt1, cnt2, iinfo)
512 ENDIF
513
514 IF(mb.EQ.1) THEN
515 sigma = gl
516 sgndef = one
517 ELSEIF( cnt1 - indl .GE. indu - cnt2 ) THEN
518 IF( ( irange.EQ.1 ) .AND. (.NOT.forceb) ) THEN
519 sigma =
max(isleft,gl)
520 ELSEIF( usedqd ) THEN
521
522
523 sigma = isleft
524 ELSE
525
526
527 sigma =
max(isleft,vl)
528 ENDIF
529 sgndef = one
530 ELSE
531 IF( ( irange.EQ.1 ) .AND. (.NOT.forceb) ) THEN
532 sigma =
min(isrght,gu)
533 ELSEIF( usedqd ) THEN
534
535
536 sigma = isrght
537 ELSE
538
539
540 sigma =
min(isrght,vu)
541 ENDIF
542 sgndef = -one
543 ENDIF
544
545
546
547
548
549
550
551 IF( usedqd ) THEN
552 tau = spdiam*eps*n + two*pivmin
553 tau =
max(tau,eps*abs(sigma))
554 ELSE
555 IF(mb.GT.1) THEN
556 clwdth = w(wend) + werr(wend) - w(wbegin) - werr(wbegin)
557 avgap = abs(clwdth / dble(wend-wbegin))
558 IF( sgndef.EQ.one ) THEN
559 tau = half*
max(wgap(wbegin),avgap)
560 tau =
max(tau,werr(wbegin))
561 ELSE
562 tau = half*
max(wgap(wend-1),avgap)
563 tau =
max(tau,werr(wend))
564 ENDIF
565 ELSE
566 tau = werr(wbegin)
567 ENDIF
568 ENDIF
569
570 DO 80 idum = 1, maxtry
571
572
573
574 dpivot = d( ibegin ) - sigma
575 work( 1 ) = dpivot
576 dmax = abs( work(1) )
577 j = ibegin
578 DO 70 i = 1, in - 1
579 work( 2*in+i ) = one / work( i )
580 tmp = e( j )*work( 2*in+i )
581 work( in+i ) = tmp
582 dpivot = ( d( j+1 )-sigma ) - tmp*e( j )
583 work( i+1 ) = dpivot
584 dmax =
max( dmax, abs(dpivot) )
585 j = j + 1
586 70 CONTINUE
587
588 IF( dmax .GT. maxgrowth*spdiam ) THEN
589 norep = .true.
590 ELSE
591 norep = .false.
592 ENDIF
593 IF(norep) THEN
594
595
596
597 IF( idum.EQ.maxtry-1 ) THEN
598 IF( sgndef.EQ.one ) THEN
599
600 sigma =
601 $ gl - fudge*spdiam*eps*n - fudge*two*pivmin
602 ELSE
603 sigma =
604 $ gu + fudge*spdiam*eps*n + fudge*two*pivmin
605 END IF
606 ELSE
607 sigma = sigma - sgndef * tau
608 tau = two * tau
609 END IF
610 ELSE
611
612 GO TO 83
613 END IF
614 80 CONTINUE
615
616
617 info = 2
618 RETURN
619
620 83 CONTINUE
621
622
623
624 e( iend ) = sigma
625
626 CALL dcopy( in, work, 1, d( ibegin ), 1 )
627 CALL dcopy( in-1, work( in+1 ), 1, e( ibegin ), 1 )
628
629
630 IF(rndprt .AND. mb.GT.1 ) THEN
631
632
633
634
635
636 DO 122 i = 1, 4
637 iseed( i ) = 1
638 122 CONTINUE
639
640 CALL dlarnv(2, iseed, 2*in-1, work(1))
641 DO 125 i = 1,in-1
642 d(ibegin+i-1) = d(ibegin+i-1)*(one+eps*pert*work(i))
643 e(ibegin+i-1) = e(ibegin+i-1)*(one+eps*pert*work(in+i))
644 125 CONTINUE
645 d(iend) = d(iend)*(one+eps*four*work(in))
646
647 ENDIF
648
649
650
651
652
653
654
655 IF ( .NOT.usedqd ) THEN
656
657
658
659
660
661 DO 134 j=wbegin,wend
662 w(j) = w(j) - sigma
663 werr(j) = werr(j) + abs(w(j)) * eps
664 134 CONTINUE
665
666
667 DO 135 i = ibegin, iend-1
668 work( i ) = d( i ) * e( i )**2
669 135 CONTINUE
670
671 CALL dlarrb(in, d(ibegin), work(ibegin),
672 $ indl, indu, rtol1, rtol2, indl-1,
673 $ w(wbegin), wgap(wbegin), werr(wbegin),
674 $ work( 2*n+1 ), iwork, pivmin, spdiam,
675 $ in, iinfo )
676 IF( iinfo .NE. 0 ) THEN
677 info = -4
678 RETURN
679 END IF
680
681
682 wgap( wend ) =
max( zero,
683 $ ( vu-sigma ) - ( w( wend ) + werr( wend ) ) )
684 DO 138 i = indl, indu
685 m = m + 1
686 iblock(m) = jblk
687 indexw(m) = i
688 138 CONTINUE
689 ELSE
690
691
692
693
694
695
696
697
698
699
700
701 rtol = log(dble(in)) * four * eps
702 j = ibegin
703 DO 140 i = 1, in - 1
704 work( 2*i-1 ) = abs( d( j ) )
705 work( 2*i ) = e( j )*e( j )*work( 2*i-1 )
706 j = j + 1
707 140 CONTINUE
708 work( 2*in-1 ) = abs( d( iend ) )
709 work( 2*in ) = zero
710 CALL dlasq2( in, work, iinfo )
711 IF( iinfo .NE. 0 ) THEN
712
713
714
715 info = -5
716 RETURN
717 ELSE
718
719 DO 149 i = 1, in
720 IF( work( i ).LT.zero ) THEN
721 info = -6
722 RETURN
723 ENDIF
724 149 CONTINUE
725 END IF
726 IF( sgndef.GT.zero ) THEN
727 DO 150 i = indl, indu
728 m = m + 1
729 w( m ) = work( in-i+1 )
730 iblock( m ) = jblk
731 indexw( m ) = i
732 150 CONTINUE
733 ELSE
734 DO 160 i = indl, indu
735 m = m + 1
736 w( m ) = -work( i )
737 iblock( m ) = jblk
738 indexw( m ) = i
739 160 CONTINUE
740 END IF
741
742 DO 165 i = m - mb + 1, m
743
744 werr( i ) = rtol * abs( w(i) )
745 165 CONTINUE
746 DO 166 i = m - mb + 1, m - 1
747
748 wgap( i ) =
max( zero,
749 $ w(i+1)-werr(i+1) - (w(i)+werr(i)) )
750 166 CONTINUE
751 wgap( m ) =
max( zero,
752 $ ( vu-sigma ) - ( w( m ) + werr( m ) ) )
753 END IF
754
755 ibegin = iend + 1
756 wbegin = wend + 1
757 170 CONTINUE
758
759
760 RETURN
761
762
763