4
5
6
7
8
9
10 CHARACTER JOBZ, RANGE
11 INTEGER DOL, DOU, IL, INFO, IU,
12 $ LDZ, NZC, LIWORK, LWORK, M, N, ZOFFSET
13 REAL VL, VU
14
15
16
17 INTEGER ISUPPZ( * ), IWORK( * )
18 REAL D( * ), E( * ), W( * ), WORK( * )
19 REAL Z( LDZ, * )
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 REAL ZERO, ONE, FOUR, MINRGP
189 parameter( zero = 0.0e0, one = 1.0e0,
190 $ four = 4.0e0,
191 $ minrgp = 3.0e-3 )
192
193
194 LOGICAL ALLEIG, INDEIG, LQUERY, VALEIG, WANTZ, ZQUERY
195 INTEGER I, IIL, IINDBL, IINDW, IINDWK, IINFO, IINSPL,
196 $ IIU, INDE2, INDERR, INDGP, INDGRS, INDWRK,
197 $ ITMP, ITMP2, J, JJ, LIWMIN, LWMIN, NSPLIT,
198 $ NZCMIN
199 REAL BIGNUM, EPS, PIVMIN, RMAX, RMIN, RTOL1, RTOL2,
200 $ SAFMIN, SCALE, SMLNUM, THRESH, TMP, TNRM, WL,
201 $ WU
202
203
204 LOGICAL LSAME
205 REAL SLAMCH, SLANST
207
208
209 EXTERNAL scopy, slae2, slaev2, slarrc,
slarre2,
210 $ slarrv, slasrt, sscal, sswap
211
212
213 INTRINSIC max,
min, real, sqrt
214
215
216
217
218
219 wantz =
lsame( jobz,
'V' )
220 alleig =
lsame( range,
'A' )
221 valeig =
lsame( range,
'V' )
222 indeig =
lsame( range,
'I' )
223
224 lquery = ( ( lwork.EQ.-1 ).OR.( liwork.EQ.-1 ) )
225 zquery = ( nzc.EQ.-1 )
226
227
228
229
230 IF( wantz ) THEN
231 lwmin = 18*n
232 liwmin = 10*n
233 ELSE
234
235 lwmin = 12*n
236 liwmin = 8*n
237 ENDIF
238
239 wl = zero
240 wu = zero
241 iil = 0
242 iiu = 0
243
244 IF( valeig ) THEN
245
246
247
248 wl = vl
249 wu = vu
250 ELSEIF( indeig ) THEN
251
252 iil = il
253 iiu = iu
254 ENDIF
255
256 info = 0
257 IF( .NOT.( wantz .OR.
lsame( jobz,
'N' ) ) )
THEN
258 info = -1
259 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
260 info = -2
261 ELSE IF( n.LT.0 ) THEN
262 info = -3
263 ELSE IF( valeig .AND. n.GT.0 .AND. wu.LE.wl ) THEN
264 info = -7
265 ELSE IF( indeig .AND. ( iil.LT.1 .OR. iil.GT.n ) ) THEN
266 info = -8
267 ELSE IF( indeig .AND. ( iiu.LT.iil .OR. iiu.GT.n ) ) THEN
268 info = -9
269 ELSE IF( ldz.LT.1 .OR. ( wantz .AND. ldz.LT.n ) ) THEN
270 info = -13
271 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
272 info = -17
273 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
274 info = -19
275 END IF
276
277
278
279 safmin =
slamch(
'Safe minimum' )
280 eps =
slamch(
'Precision' )
281 smlnum = safmin / eps
282 bignum = one / smlnum
283 rmin = sqrt( smlnum )
284 rmax =
min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
285
286 IF( info.EQ.0 ) THEN
287 work( 1 ) = lwmin
288 iwork( 1 ) = liwmin
289
290 IF( wantz .AND. alleig ) THEN
291 nzcmin = n
292 iil = 1
293 iiu = n
294 ELSE IF( wantz .AND. valeig ) THEN
295 CALL slarrc( 'T', n, vl, vu, d, e, safmin,
296 $ nzcmin, itmp, itmp2, info )
297 iil = itmp+1
298 iiu = itmp2
299 ELSE IF( wantz .AND. indeig ) THEN
300 nzcmin = iiu-iil+1
301 ELSE
302
303 nzcmin = 0
304 ENDIF
305 IF( zquery .AND. info.EQ.0 ) THEN
306 z( 1,1 ) = nzcmin
307 ELSE IF( nzc.LT.nzcmin .AND. .NOT.zquery ) THEN
308 info = -14
309 END IF
310 END IF
311
312 IF ( wantz ) THEN
313 IF ( dol.LT.1 .OR. dol.GT.nzcmin ) THEN
314 info = -20
315 ENDIF
316 IF ( dou.LT.1 .OR. dou.GT.nzcmin .OR. dou.LT.dol) THEN
317 info = -21
318 ENDIF
319 ENDIF
320
321 IF( info.NE.0 ) THEN
322
323
324
325
326
327 RETURN
328 ELSE IF( lquery .OR. zquery ) THEN
329 RETURN
330 END IF
331
332
333
334 m = 0
335 IF( n.EQ.0 )
336 $ RETURN
337
338 IF( n.EQ.1 ) THEN
339 IF( alleig .OR. indeig ) THEN
340 m = 1
341 w( 1 ) = d( 1 )
342 ELSE
343 IF( wl.LT.d( 1 ) .AND. wu.GE.d( 1 ) ) THEN
344 m = 1
345 w( 1 ) = d( 1 )
346 END IF
347 END IF
348 IF( wantz )
349 $ z( 1, 1 ) = one
350 RETURN
351 END IF
352
353 indgrs = 1
354 inderr = 2*n + 1
355 indgp = 3*n + 1
356 inde2 = 5*n + 1
357 indwrk = 6*n + 1
358
359 iinspl = 1
360 iindbl = n + 1
361 iindw = 2*n + 1
362 iindwk = 3*n + 1
363
364
365
366 scale = one
367 tnrm = slanst( 'M', n, d, e )
368 IF( tnrm.GT.zero .AND. tnrm.LT.rmin ) THEN
369 scale = rmin / tnrm
370 ELSE IF( tnrm.GT.rmax ) THEN
371 scale = rmax / tnrm
372 END IF
373 IF( scale.NE.one ) THEN
374 CALL sscal( n, scale, d, 1 )
375 CALL sscal( n-1, scale, e, 1 )
376 tnrm = tnrm*scale
377 IF( valeig ) THEN
378
379
380 wl = wl*scale
381 wu = wu*scale
382 ENDIF
383 END IF
384
385
386
387
388
389
390
391
392
393 iinfo = -1
394
395 IF (iinfo.EQ.0) THEN
396 thresh = eps
397 ELSE
398 thresh = -eps
399 ENDIF
400
401
402 DO 5 j = 1, n-1
403 work( inde2+j-1 ) = e(j)**2
404 5 CONTINUE
405
406
407 IF( .NOT.wantz ) THEN
408
409 rtol1 = four * eps
410 rtol2 = four * eps
411 ELSE
412
413
414
415
416 rtol1 = sqrt(eps)
417 rtol2 =
max( sqrt(eps)*5.0e-3, four * eps )
418 ENDIF
419 CALL slarre2( range, n, wl, wu, iil, iiu, d, e,
420 $ work(inde2), rtol1, rtol2, thresh, nsplit,
421 $ iwork( iinspl ), m, dol, dou,
422 $ w, work( inderr ),
423 $ work( indgp ), iwork( iindbl ),
424 $ iwork( iindw ), work( indgrs ), pivmin,
425 $ work( indwrk ), iwork( iindwk ), iinfo )
426 IF( iinfo.NE.0 ) THEN
427 info = 100 + abs( iinfo )
428 RETURN
429 END IF
430
431
432
433
434
435 IF( wantz ) THEN
436
437
438
439
440 CALL slarrv( n, wl, wu, d, e,
441 $ pivmin, iwork( iinspl ), m,
442 $ dol, dou, minrgp, rtol1, rtol2,
443 $ w, work( inderr ), work( indgp ), iwork( iindbl ),
444 $ iwork( iindw ), work( indgrs ), z, ldz,
445 $ isuppz, work( indwrk ), iwork( iindwk ), iinfo )
446 IF( iinfo.NE.0 ) THEN
447 info = 200 + abs( iinfo )
448 RETURN
449 END IF
450 ELSE
451
452
453
454
455
456 DO 20 j = 1, m
457 itmp = iwork( iindbl+j-1 )
458 w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) )
459 20 CONTINUE
460 END IF
461
462
463
464
465
466 IF( scale.NE.one ) THEN
467 CALL sscal( m, one / scale, w, 1 )
468 END IF
469
470
471
472 IF ( wantz ) THEN
473 IF( dol.NE.1 .OR. dou.NE.m ) THEN
474 m = dou - dol +1
475 ENDIF
476 ENDIF
477
478
479
480
481 IF( nsplit.GT.1 ) THEN
482 IF( .NOT. wantz ) THEN
483 CALL slasrt( 'I', dou - dol +1, w(dol), iinfo )
484 IF( iinfo.NE.0 ) THEN
485 info = 3
486 RETURN
487 END IF
488 ELSE
489 DO 60 j = dol, dou - 1
490 i = 0
491 tmp = w( j )
492 DO 50 jj = j + 1, m
493 IF( w( jj ).LT.tmp ) THEN
494 i = jj
495 tmp = w( jj )
496 END IF
497 50 CONTINUE
498 IF( i.NE.0 ) THEN
499 w( i ) = w( j )
500 w( j ) = tmp
501 IF( wantz ) THEN
502 CALL sswap( n, z( 1, i-zoffset ),
503 $ 1, z( 1, j-zoffset ), 1 )
504 itmp = isuppz( 2*i-1 )
505 isuppz( 2*i-1 ) = isuppz( 2*j-1 )
506 isuppz( 2*j-1 ) = itmp
507 itmp = isuppz( 2*i )
508 isuppz( 2*i ) = isuppz( 2*j )
509 isuppz( 2*j ) = itmp
510 END IF
511 END IF
512 60 CONTINUE
513 END IF
514 ENDIF
515
516 work( 1 ) = lwmin
517 iwork( 1 ) = liwmin
518 RETURN
519
520
521
subroutine slarre2(range, n, vl, vu, il, iu, d, e, e2, rtol1, rtol2, spltol, nsplit, isplit, m, dol, dou, w, werr, wgap, iblock, indexw, gers, pivmin, work, iwork, info)