6
7
8
9
10
11 IMPLICIT NONE
12
13
14 CHARACTER RANGE
15 INTEGER DOL, DOU, IL, INFO, IU, M, N, NSPLIT,
16 $ NEEDIL, NEEDIU
17 DOUBLE PRECISION MINRGP, PIVMIN, RTOL1, RTOL2, SPLTOL, VL, VU
18
19
20 INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * ),
21 $ INDEXW( * )
22 DOUBLE PRECISION D( * ), E( * ), E2( * ), GERS( * ),
23 $ SDIAM( * ), W( * ),WERR( * ),
24 $ WGAP( * ), WORK( * )
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 DOUBLE PRECISION FAC, FOUR, FOURTH, FUDGE, HALF, HNDRD,
209 $ MAXGROWTH, ONE, PERT, TWO, ZERO
210 parameter( zero = 0.0d0, one = 1.0d0,
211 $ two = 2.0d0, four=4.0d0,
212 $ hndrd = 100.0d0,
213 $ pert = 8.0d0,
214 $ half = one/two, fourth = one/four, fac= half,
215 $ maxgrowth = 64.0d0, fudge = 2.0d0 )
216 INTEGER MAXTRY
217 parameter( maxtry = 6 )
218
219
220 LOGICAL NOREP, RNDPRT, USEDQD
221 INTEGER CNT, CNT1, CNT2, I, IBEGIN, IDUM, IEND, IINFO,
222 $ IN, INDL, INDU, IRANGE, J, JBLK, MB, MM,
223 $ MYINDL, MYINDU, MYWBEG, MYWEND, WBEGIN, WEND
224 DOUBLE PRECISION AVGAP, BSRTOL, CLWDTH, DMAX, DPIVOT, EABS,
225 $ EMAX, EOLD, EPS, GL, GU, ISLEFT, ISRGHT,
226 $ LGPVMN, LGSPDM, RTL, S1, S2, SAFMIN, SGNDEF,
227 $ SIGMA, SPDIAM, TAU, TMP, TMP1, TMP2
228
229
230
231
232 INTEGER ISEED( 4 )
233
234
235 LOGICAL LSAME
236 DOUBLE PRECISION DLAMCH
238
239
240
241 EXTERNAL dcopy, dlarnv, dlarra,
dlarrb2,
243
244
246
247
248
249
250
251 info = 0
252
253
254 rndprt = .true.
255
256
257
258 IF(
lsame( range,
'A' ) )
THEN
259 irange = 1
260 ELSE IF(
lsame( range,
'V' ) )
THEN
261 irange = 2
262 ELSE IF(
lsame( range,
'I' ) )
THEN
263 irange = 3
264 END IF
265
266 m = 0
267
268
271
272
273 rtl = sqrt(eps)
274 bsrtol = 1.0d-1
275
276
277 IF( n.EQ.1 ) THEN
278 IF( (irange.EQ.1).OR.
279 $ ((irange.EQ.2).AND.(d(1).GT.vl).AND.(d(1).LE.vu)).OR.
280 $ ((irange.EQ.3).AND.(il.EQ.1).AND.(iu.EQ.1)) ) THEN
281 m = 1
282 w(1) = d(1)
283
284 werr(1) = zero
285 wgap(1) = zero
286 iblock( 1 ) = 1
287 indexw( 1 ) = 1
288 gers(1) = d( 1 )
289 gers(2) = d( 1 )
290 ENDIF
291
292 e(1) = zero
293 RETURN
294 END IF
295
296
297
298
299 DO 1 i =1,n
300 werr(i) = zero
301 1 CONTINUE
302 DO 2 i =1,n
303 wgap(i) = zero
304 2 CONTINUE
305
306
307
308 gl = d(1)
309 gu = d(1)
310 eold = zero
311 emax = zero
312 e(n) = zero
313 DO 5 i = 1,n
314 eabs = abs( e(i) )
315 IF( eabs .GE. emax ) THEN
316 emax = eabs
317 END IF
318 tmp = eabs + eold
319 eold = eabs
320 tmp1 = d(i) - tmp
321 tmp2 = d(i) + tmp
324 gers( 2*i-1) = tmp1
325 gers( 2*i ) = tmp2
326 5 CONTINUE
327
328 pivmin = safmin *
max( one, emax**2 )
329
330
331 spdiam = gu - gl
332
333
334 CALL dlarra( n, d, e, e2, spltol, spdiam,
335 $ nsplit, isplit, iinfo )
336
337 IF( irange.EQ.1 ) THEN
338
339 vl = gl
340 vu = gu
341 ENDIF
342
343
344
345
346
347
348
349 CALL dlarrd2( range,
'B', n, vl, vu, il, iu, gers,
350 $ bsrtol, d, e, e2, pivmin, nsplit, isplit,
351 $ mm, w, werr, vl, vu, iblock, indexw,
352 $ work, iwork, dol, dou, iinfo )
353 IF( iinfo.NE.0 ) THEN
354 info = -1
355 RETURN
356 ENDIF
357
358 DO 14 i = mm+1,n
359 w( i ) = zero
360 werr( i ) = zero
361 iblock( i ) = 0
362 indexw( i ) = 0
363 14 CONTINUE
364
365
366
367
368 ibegin = 1
369 wbegin = 1
370 DO 170 jblk = 1, nsplit
371 iend = isplit( jblk )
372 in = iend - ibegin + 1
373
374
375 IF( in.EQ.1 ) THEN
376 IF( (irange.EQ.1).OR.( (irange.EQ.2).AND.
377 $ ( d( ibegin ).GT.vl ).AND.( d( ibegin ).LE.vu ) )
378 $ .OR. ( (irange.EQ.3).AND.(iblock(wbegin).EQ.jblk))
379 $ ) THEN
380 m = m + 1
381 w( m ) = d( ibegin )
382 werr(m) = zero
383
384
385 wgap(m) = zero
386 iblock( m ) = jblk
387 indexw( m ) = 1
388 wbegin = wbegin + 1
389 ENDIF
390
391 e( iend ) = zero
392 ibegin = iend + 1
393 GO TO 170
394 END IF
395
396
397
398
399 e( iend ) = zero
400
401 IF( ( irange.EQ.1 ) .OR.
402 $ ((irange.EQ.3).AND.(il.EQ.1.AND.iu.EQ.n)) ) THEN
403
404 mb = in
405 wend = wbegin + mb - 1
406 indl = 1
407 indu = in
408 ELSE
409
410 mb = 0
411 DO 20 i = wbegin,mm
412 IF( iblock(i).EQ.jblk ) THEN
413 mb = mb+1
414 ELSE
415 GOTO 21
416 ENDIF
417 20 CONTINUE
418 21 CONTINUE
419
420 IF( mb.EQ.0) THEN
421
422
423 e( iend ) = zero
424 ibegin = iend + 1
425 GO TO 170
426 ENDIF
427
428 wend = wbegin + mb - 1
429
430 indl = indexw(wbegin)
431 indu = indexw( wend )
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 + mb
440 GO TO 170
441 END IF
442
443 IF(.NOT. ( irange.EQ.1 ) ) THEN
444
445
446
447
448
449
450
451
452 usedqd = ( mb .GT. fac*in )
453
454
455
456
457 sigma = zero
458 DO 30 i = wbegin, wend - 1
459 wgap( i ) =
max( zero,
460 $ w(i+1)-werr(i+1) - (w(i)+werr(i)) )
461 30 CONTINUE
462 wgap( wend ) =
max( zero,
463 $ vu - sigma - (w( wend )+werr( wend )))
464 ENDIF
465
466
467
468 gl = d(ibegin)
469 gu = d(ibegin)
470 DO 15 i = ibegin , iend
471 gl =
min( gers( 2*i-1 ), gl )
472 gu =
max( gers( 2*i ), gu )
473 15 CONTINUE
474 spdiam = gu - gl
475
476 sdiam(jblk) = spdiam
477
478
479 CALL dlarrk( in, 1, gl, gu, d(ibegin),
480 $ e2(ibegin), pivmin, rtl, tmp, tmp1, iinfo )
481 IF( iinfo.NE.0 ) THEN
482 info = -1
483 RETURN
484 ENDIF
485 isleft =
max(gl, tmp - tmp1
486 $ - hndrd * eps* abs(tmp - tmp1))
487 CALL dlarrk( in, in, gl, gu, d(ibegin),
488 $ e2(ibegin), pivmin, rtl, tmp, tmp1, iinfo )
489 IF( iinfo.NE.0 ) THEN
490 info = -1
491 RETURN
492 ENDIF
493 isrght =
min(gu, tmp + tmp1
494 $ + hndrd * eps * abs(tmp + tmp1))
495 IF( ( irange.EQ.1 ).OR.usedqd ) THEN
496
497
498 spdiam = isrght - isleft
499 ELSE
500
501
502 isleft =
max(gl, w(wbegin) - werr(wbegin)
503 $ - hndrd * eps*abs(w(wbegin)- werr(wbegin) ))
504 isrght =
min(gu,w(wend) + werr(wend)
505 $ + hndrd * eps * abs(w(wend)+ werr(wend)))
506 ENDIF
507
508
509
510
511
512
513 IF( irange.EQ.1 ) THEN
514
515 usedqd = .true.
516
517 indl = 1
518 indu = in
519
520 mb = in
521 wend = wbegin + mb - 1
522
523 s1 = isleft + fourth * spdiam
524 s2 = isrght - fourth * spdiam
525 ELSE
526
527
528
529 IF( usedqd ) THEN
530 s1 = isleft + fourth * spdiam
531 s2 = isrght - fourth * spdiam
532 ELSE
533 tmp =
min(isrght,vu) -
max(isleft,vl)
534 s1 =
max(isleft,vl) + fourth * tmp
535 s2 =
min(isrght,vu) - fourth * tmp
536 ENDIF
537 ENDIF
538
539
540 IF(mb.GT.2) THEN
541 CALL dlarrc( 'T', in, s1, s2, d(ibegin),
542 $ e(ibegin), pivmin, cnt, cnt1, cnt2, iinfo)
543 ENDIF
544
545 IF(mb.LE.2) THEN
546 sigma = gl
547 sgndef = one
548 ELSEIF( cnt1 - indl .GE. indu - cnt2 ) THEN
549 IF( irange.EQ.1 ) THEN
550 sigma =
max(isleft,gl)
551 ELSEIF( usedqd ) THEN
552
553 sigma = isleft
554 ELSE
555
556
557 sigma =
max(isleft,vl)
558 ENDIF
559 sgndef = one
560 ELSE
561 IF( irange.EQ.1 ) THEN
562 sigma =
min(isrght,gu)
563 ELSEIF( usedqd ) THEN
564
565
566 sigma = isrght
567 ELSE
568
569
570 sigma =
min(isrght,vu)
571 ENDIF
572 sgndef = -one
573 ENDIF
574
575
576
577
578
579
580
581 IF( usedqd ) THEN
582 tau = spdiam*eps*n + two*pivmin
583 tau =
max(tau,eps*abs(sigma))
584 ELSE
585 IF(mb.GT.1) THEN
586 clwdth = w(wend) + werr(wend) - w(wbegin) - werr(wbegin)
587 avgap = abs(clwdth / dble(wend-wbegin))
588 IF( sgndef.EQ.one ) THEN
589 tau = half*
max(wgap(wbegin),avgap)
590 tau =
max(tau,werr(wbegin))
591 ELSE
592 tau = half*
max(wgap(wend-1),avgap)
593 tau =
max(tau,werr(wend))
594 ENDIF
595 ELSE
596 tau = werr(wbegin)
597 ENDIF
598 ENDIF
599
600 DO 80 idum = 1, maxtry
601
602
603
604 dpivot = d( ibegin ) - sigma
605 work( 1 ) = dpivot
606 dmax = abs( work(1) )
607 j = ibegin
608 DO 70 i = 1, in - 1
609 work( 2*in+i ) = one / work( i )
610 tmp = e( j )*work( 2*in+i )
611 work( in+i ) = tmp
612 dpivot = ( d( j+1 )-sigma ) - tmp*e( j )
613 work( i+1 ) = dpivot
614 dmax =
max( dmax, abs(dpivot) )
615 j = j + 1
616 70 CONTINUE
617
618 IF( dmax .GT. maxgrowth*spdiam ) THEN
619 norep = .true.
620 ELSE
621 norep = .false.
622 ENDIF
623 IF(norep) THEN
624
625
626
627 IF( idum.EQ.maxtry-1 ) THEN
628 IF( sgndef.EQ.one ) THEN
629
630 sigma =
631 $ gl - fudge*spdiam*eps*n - fudge*two*pivmin
632 ELSE
633 sigma =
634 $ gu + fudge*spdiam*eps*n + fudge*two*pivmin
635 END IF
636 ELSE
637 sigma = sigma - sgndef * tau
638 tau = two * tau
639 END IF
640 ELSE
641
642 GO TO 83
643 END IF
644 80 CONTINUE
645
646
647 info = 2
648 RETURN
649
650 83 CONTINUE
651
652
653
654 e( iend ) = sigma
655
656 CALL dcopy( in, work, 1, d( ibegin ), 1 )
657 CALL dcopy( in-1, work( in+1 ), 1, e( ibegin ), 1 )
658
659
660 IF(rndprt .AND. mb.GT.1 ) THEN
661
662
663
664
665
666 DO 122 i = 1, 4
667 iseed( i ) = 1
668 122 CONTINUE
669
670 CALL dlarnv(2, iseed, 2*in-1, work(1))
671 DO 125 i = 1,in-1
672 d(ibegin+i-1) = d(ibegin+i-1)*(one+eps*pert*work(2*i-1))
673 e(ibegin+i-1) = e(ibegin+i-1)*(one+eps*pert*work(2*i))
674 125 CONTINUE
675 d(iend) = d(iend)*(one+eps*pert*work(2*in-1))
676
677 ENDIF
678
679
680
681
682 DO 134 j=wbegin,wend
683 w(j) = w(j) - sigma
684 werr(j) = werr(j) + abs(w(j)) * eps
685 134 CONTINUE
686
687
688 DO 135 i = ibegin, iend-1
689 work( i ) = d( i ) * e( i )**2
690 135 CONTINUE
691
692 indl = indexw( wbegin )
693 indu = indexw( wend )
694
695
696
697
698 needil =
min(needil,wbegin)
699 neediu =
max(neediu,wend)
700
701
702
703
704 mywbeg =
max(wbegin,dol)
705 mywend =
min(wend,dou)
706
707 IF(mywbeg.GT.wbegin) THEN
708
709
710
711
712
713 DO 136 i = wbegin, mywbeg-1
714 IF ( wgap(i).GE.minrgp*abs(w(i)) ) THEN
715 needil =
max(i+1,needil)
716 ENDIF
717 136 CONTINUE
718 ENDIF
719 IF(mywend.LT.wend) THEN
720
721
722
723 DO 137 i = mywend,wend-1
724 IF ( wgap(i).GE.minrgp*abs(w(i)) ) THEN
725 neediu =
min(i,neediu)
726 GOTO 138
727 ENDIF
728 137 CONTINUE
729 138 CONTINUE
730 ENDIF
731
732
733
734
735 myindl = indexw( mywbeg )
736 myindu = indexw( mywend )
737
738 lgpvmn = log( pivmin )
739 lgspdm = log( spdiam + pivmin )
740
741 CALL dlarrb2(in, d(ibegin), work(ibegin),
742 $ myindl, myindu, rtol1, rtol2, myindl-1,
743 $ w(mywbeg), wgap(mywbeg), werr(mywbeg),
744 $ work( 2*n+1 ), iwork, pivmin,
745 $ lgpvmn, lgspdm, in, iinfo )
746 IF( iinfo .NE. 0 ) THEN
747 info = -4
748 RETURN
749 END IF
750
751
752 wgap( wend ) =
max( zero,
753 $ ( vu-sigma ) - ( w( wend ) + werr( wend ) ) )
754 DO 140 i = indl, indu
755 m = m + 1
756 iblock(m) = jblk
757 indexw(m) = i
758 140 CONTINUE
759
760
761 ibegin = iend + 1
762 wbegin = wend + 1
763 170 CONTINUE
764
765 IF (m.LT.dou-dol+1) THEN
766 info = -9
767 ENDIF
768
769
770 RETURN
771
772
773
subroutine dlarrb2(n, d, lld, ifirst, ilast, rtol1, rtol2, offset, w, wgap, werr, work, iwork, pivmin, lgpvmn, lgspdm, twist, info)
subroutine dlarrd2(range, order, n, vl, vu, il, iu, gers, reltol, d, e, e2, pivmin, nsplit, isplit, m, w, werr, wl, wu, iblock, indexw, work, iwork, dol, dou, info)