5
6
7
8
9
10
11 CHARACTER ORDER, RANGE
12 INTEGER DOL, DOU, IL, INFO, IU, M, N, NSPLIT
13 DOUBLE PRECISION PIVMIN, RELTOL, VL, VU, WL, WU
14
15
16 INTEGER IBLOCK( * ), INDEXW( * ),
17 $ ISPLIT( * ), IWORK( * )
18 DOUBLE PRECISION D( * ), E( * ), E2( * ),
19 $ GERS( * ), W( * ), WERR( * ), WORK( * )
20
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
193
194
195
196
197
198
199
200
201
202
203
204
205 DOUBLE PRECISION ZERO, ONE, TWO, HALF, FUDGE
206 parameter( zero = 0.0d0, one = 1.0d0,
207 $ two = 2.0d0, half = one/two,
208 $ fudge = 10.0d0 )
209
210
211
212 LOGICAL NCNVRG, TOOFEW
213 INTEGER I, IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,
214 $ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX,
215 $ ITMP1, ITMP2, IW, IWOFF, J, JBLK, JDISC, JE,
216 $ JEE, NB, NWL, NWU
217 DOUBLE PRECISION ATOLI, EPS, GL, GU, RTOLI, SPDIAM, TMP1, TMP2,
218 $ TNORM, UFLOW, WKILL, WLU, WUL
219
220
221
222 INTEGER IDUMMA( 1 )
223
224
225 LOGICAL LSAME
226 INTEGER ILAENV
227 DOUBLE PRECISION DLAMCH
229
230
231 EXTERNAL dlaebz
232
233
234 INTRINSIC abs, int, log,
max,
min, sqrt
235
236
237
238 info = 0
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 ELSE
249 irange = 0
250 END IF
251
252
253
254 IF(
lsame( order,
'B' ) )
THEN
255 iorder = 2
256 ELSE IF(
lsame( order,
'E' ) )
THEN
257 iorder = 1
258 ELSE
259 iorder = 0
260 END IF
261
262
263
264 IF( irange.LE.0 ) THEN
265 info = -1
266 ELSE IF( iorder.LE.0 ) THEN
267 info = -2
268 ELSE IF( n.LT.0 ) THEN
269 info = -3
270 ELSE IF( irange.EQ.2 ) THEN
271 IF( vl.GE.vu )
272 $ info = -5
273 ELSE IF( irange.EQ.3 .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
274 $ THEN
275 info = -6
276 ELSE IF( irange.EQ.3 .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
277 $ THEN
278 info = -7
279 END IF
280
281 IF( info.NE.0 ) THEN
282 RETURN
283 END IF
284
285
286 info = 0
287 ncnvrg = .false.
288 toofew = .false.
289
290
291 m = 0
292 IF( n.EQ.0 ) RETURN
293
294
295 IF( irange.EQ.3 .AND. il.EQ.1 .AND. iu.EQ.n ) irange = 1
296
297
300
301
302
303
304 IF( n.EQ.1 ) THEN
305 IF( (irange.EQ.1).OR.
306 $ ((irange.EQ.2).AND.(d(1).GT.vl).AND.(d(1).LE.vu)).OR.
307 $ ((irange.EQ.3).AND.(il.EQ.1).AND.(iu.EQ.1)) ) THEN
308 m = 1
309 w(1) = d(1)
310
311 werr(1) = zero
312 iblock( 1 ) = 1
313 indexw( 1 ) = 1
314 ENDIF
315 RETURN
316 END IF
317
318
319
320 nb = ilaenv( 1, 'DSTEBZ', ' ', n, -1, -1, -1 )
321 IF( nb.LE.1 ) nb = 0
322
323
324 gl = d(1)
325 gu = d(1)
326 DO 5 i = 1,n
327 gl =
min( gl, gers( 2*i - 1))
328 gu =
max( gu, gers(2*i) )
329 5 CONTINUE
330
331 tnorm =
max( abs( gl ), abs( gu ) )
332 gl = gl - fudge*tnorm*eps*n - fudge*two*pivmin
333 gu = gu + fudge*tnorm*eps*n + fudge*two*pivmin
334 spdiam = gu - gl
335
336
337
338 rtoli = reltol
339 atoli = fudge*two*uflow + fudge*two*pivmin
340
341 IF( irange.EQ.3 ) THEN
342
343
344
345
346 itmax = int( ( log( tnorm+pivmin )-log( pivmin ) ) /
347 $ log( two ) ) + 2
348 work( n+1 ) = gl
349 work( n+2 ) = gl
350 work( n+3 ) = gu
351 work( n+4 ) = gu
352 work( n+5 ) = gl
353 work( n+6 ) = gu
354 iwork( 1 ) = -1
355 iwork( 2 ) = -1
356 iwork( 3 ) = n + 1
357 iwork( 4 ) = n + 1
358 iwork( 5 ) = il - 1
359 iwork( 6 ) = iu
360
361 CALL dlaebz( 3, itmax, n, 2, 2, nb, atoli, rtoli, pivmin,
362 $ d, e, e2, iwork( 5 ), work( n+1 ), work( n+5 ), iout,
363 $ iwork, w, iblock, iinfo )
364 IF( iinfo .NE. 0 ) THEN
365 info = iinfo
366 RETURN
367 END IF
368
369 IF( iwork( 6 ).EQ.iu ) THEN
370 wl = work( n+1 )
371 wlu = work( n+3 )
372 nwl = iwork( 1 )
373 wu = work( n+4 )
374 wul = work( n+2 )
375 nwu = iwork( 4 )
376 ELSE
377 wl = work( n+2 )
378 wlu = work( n+4 )
379 nwl = iwork( 2 )
380 wu = work( n+3 )
381 wul = work( n+1 )
382 nwu = iwork( 3 )
383 END IF
384
385
386 IF( nwl.LT.0 .OR. nwl.GE.n .OR. nwu.LT.1 .OR. nwu.GT.n ) THEN
387 info = 4
388 RETURN
389 END IF
390
391 ELSEIF( irange.EQ.2 ) THEN
392 wl = vl
393 wu = vu
394
395 ELSEIF( irange.EQ.1 ) THEN
396 wl = gl
397 wu = gu
398 ENDIF
399
400
401
402
403
404
405 m = 0
406 iend = 0
407 info = 0
408 nwl = 0
409 nwu = 0
410
411 DO 70 jblk = 1, nsplit
412 ioff = iend
413 ibegin = ioff + 1
414 iend = isplit( jblk )
415 in = iend - ioff
416
417 IF( irange.EQ.1 ) THEN
418 IF( (iend.LT.dol).OR.(ibegin.GT.dou) ) THEN
419
420
421 nwu = nwu + in
422 DO 30 j = 1, in
423 m = m + 1
424 iblock( m ) = jblk
425 30 CONTINUE
426 GO TO 70
427 END IF
428 END IF
429
430 IF( in.EQ.1 ) THEN
431
432 IF( wl.GE.d( ibegin )-pivmin )
433 $ nwl = nwl + 1
434 IF( wu.GE.d( ibegin )-pivmin )
435 $ nwu = nwu + 1
436 IF( irange.EQ.1 .OR. ( wl.LT.d( ibegin )-pivmin .AND. wu.GE.
437 $ d( ibegin )-pivmin ) ) THEN
438 m = m + 1
439 w( m ) = d( ibegin )
440 werr(m) = zero
441
442
443 iblock( m ) = jblk
444 indexw( m ) = 1
445 END IF
446 ELSE
447
448
449
450 gu = d( ibegin )
451 gl = d( ibegin )
452 tmp1 = zero
453
454 DO 40 j = ibegin, iend
455 gl =
min( gl, gers( 2*j - 1))
456 gu =
max( gu, gers(2*j) )
457 40 CONTINUE
458 spdiam = gu - gl
459 gl = gl - fudge*tnorm*eps*in - fudge*pivmin
460 gu = gu + fudge*tnorm*eps*in + fudge*pivmin
461
462 IF( irange.GT.1 ) THEN
463 IF( gu.LT.wl ) THEN
464
465 nwl = nwl + in
466 nwu = nwu + in
467 GO TO 70
468 END IF
469
472 IF( gl.GE.gu )
473 $ GO TO 70
474 END IF
475
476
477 work( n+1 ) = gl
478 work( n+in+1 ) = gu
479 CALL dlaebz( 1, 0, in, in, 1, nb, atoli, rtoli, pivmin,
480 $ d( ibegin ), e( ibegin ), e2( ibegin ),
481 $ idumma, work( n+1 ), work( n+2*in+1 ), im,
482 $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
483 IF( iinfo .NE. 0 ) THEN
484 info = iinfo
485 RETURN
486 END IF
487
488 nwl = nwl + iwork( 1 )
489 nwu = nwu + iwork( in+1 )
490 iwoff = m - iwork( 1 )
491
492
493 itmax = int( ( log( gu-gl+pivmin )-log( pivmin ) ) /
494 $ log( two ) ) + 2
495 CALL dlaebz( 2, itmax, in, in, 1, nb, atoli, rtoli, pivmin,
496 $ d( ibegin ), e( ibegin ), e2( ibegin ),
497 $ idumma, work( n+1 ), work( n+2*in+1 ), iout,
498 $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
499 IF( iinfo .NE. 0 ) THEN
500 info = iinfo
501 RETURN
502 END IF
503
504
505
506
507 DO 60 j = 1, iout
508
509 tmp1 = half*( work( j+n )+work( j+in+n ) )
510
511 tmp2 = half*abs( work( j+n )-work( j+in+n ) )
512 IF( j.GT.iout-iinfo ) THEN
513
514 ncnvrg = .true.
515 ib = -jblk
516 ELSE
517 ib = jblk
518 END IF
519 DO 50 je = iwork( j ) + 1 + iwoff,
520 $ iwork( j+in ) + iwoff
521 w( je ) = tmp1
522 werr( je ) = tmp2
523 indexw( je ) = je - iwoff
524 iblock( je ) = ib
525 50 CONTINUE
526 60 CONTINUE
527
528 m = m + im
529 END IF
530 70 CONTINUE
531
532
533
534 IF( irange.EQ.3 ) THEN
535 idiscl = il - 1 - nwl
536 idiscu = nwu - iu
537
538 IF( idiscl.GT.0 ) THEN
539 im = 0
540 DO 80 je = 1, m
541
542
543 IF( w( je ).LE.wlu .AND. idiscl.GT.0 ) THEN
544 idiscl = idiscl - 1
545 ELSE
546 im = im + 1
547 w( im ) = w( je )
548 werr( im ) = werr( je )
549 indexw( im ) = indexw( je )
550 iblock( im ) = iblock( je )
551 END IF
552 80 CONTINUE
553 m = im
554 END IF
555 IF( idiscu.GT.0 ) THEN
556
557
558 im=m+1
559 DO 81 je = m, 1, -1
560 IF( w( je ).GE.wul .AND. idiscu.GT.0 ) THEN
561 idiscu = idiscu - 1
562 ELSE
563 im = im - 1
564 w( im ) = w( je )
565 werr( im ) = werr( je )
566 indexw( im ) = indexw( je )
567 iblock( im ) = iblock( je )
568 END IF
569 81 CONTINUE
570 jee = 0
571 DO 82 je = im, m
572 jee = jee + 1
573 w( jee ) = w( je )
574 werr( jee ) = werr( je )
575 indexw( jee ) = indexw( je )
576 iblock( jee ) = iblock( je )
577 82 CONTINUE
578 m = m-im+1
579 END IF
580
581 IF( idiscl.GT.0 .OR. idiscu.GT.0 ) THEN
582
583
584
585
586
587
588 IF( idiscl.GT.0 ) THEN
589 wkill = wu
590 DO 100 jdisc = 1, idiscl
591 iw = 0
592 DO 90 je = 1, m
593 IF( iblock( je ).NE.0 .AND.
594 $ ( w( je ).LT.wkill .OR. iw.EQ.0 ) ) THEN
595 iw = je
596 wkill = w( je )
597 END IF
598 90 CONTINUE
599 iblock( iw ) = 0
600 100 CONTINUE
601 END IF
602 IF( idiscu.GT.0 ) THEN
603 wkill = wl
604 DO 120 jdisc = 1, idiscu
605 iw = 0
606 DO 110 je = 1, m
607 IF( iblock( je ).NE.0 .AND.
608 $ ( w( je ).GE.wkill .OR. iw.EQ.0 ) ) THEN
609 iw = je
610 wkill = w( je )
611 END IF
612 110 CONTINUE
613 iblock( iw ) = 0
614 120 CONTINUE
615 END IF
616
617 im = 0
618 DO 130 je = 1, m
619 IF( iblock( je ).NE.0 ) THEN
620 im = im + 1
621 w( im ) = w( je )
622 werr( im ) = werr( je )
623 indexw( im ) = indexw( je )
624 iblock( im ) = iblock( je )
625 END IF
626 130 CONTINUE
627 m = im
628 END IF
629 IF( idiscl.LT.0 .OR. idiscu.LT.0 ) THEN
630 toofew = .true.
631 END IF
632 END IF
633
634 IF(( irange.EQ.1 .AND. m.NE.n ).OR.
635 $ ( irange.EQ.3 .AND. m.NE.iu-il+1 ) ) THEN
636 toofew = .true.
637 END IF
638
639
640
641
642
643 IF( iorder.EQ.1 .AND. nsplit.GT.1 ) THEN
644 DO 150 je = 1, m - 1
645 ie = 0
646 tmp1 = w( je )
647 DO 140 j = je + 1, m
648 IF( w( j ).LT.tmp1 ) THEN
649 ie = j
650 tmp1 = w( j )
651 END IF
652 140 CONTINUE
653 IF( ie.NE.0 ) THEN
654 tmp2 = werr( ie )
655 itmp1 = iblock( ie )
656 itmp2 = indexw( ie )
657 w( ie ) = w( je )
658 werr( ie ) = werr( je )
659 iblock( ie ) = iblock( je )
660 indexw( ie ) = indexw( je )
661 w( je ) = tmp1
662 werr( je ) = tmp2
663 iblock( je ) = itmp1
664 indexw( je ) = itmp2
665 END IF
666 150 CONTINUE
667 END IF
668
669 info = 0
670 IF( ncnvrg )
671 $ info = info + 1
672 IF( toofew )
673 $ info = info + 2
674 RETURN
675
676
677