5
6
7
8
9
10
11
12 INTEGER INFO, LDZ, M, N
13 DOUBLE PRECISION ORFAC
14
15
16 INTEGER IBLOCK( * ), IFAIL( * ), ISPLIT( * ),
17 $ IWORK( * )
18 DOUBLE PRECISION D( * ), E( * ), W( * ), ( * ), Z( LDZ, * )
19
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 DOUBLE PRECISION ZERO, ONE, TEN, ODM1
114 parameter( zero = 0.0d+0, one = 1.0d+0, ten = 1.0d+1,
115 $ odm1 = 1.0d-1 )
116 INTEGER MAXITS
117
118
119
120 INTEGER B1, BLKSIZ, BN, GPIND, I, IINFO, INDRV1,
121 $ INDRV2, INDRV3, INDRV4, INDRV5, ITS, J, J1,
122 $ JBLK, JMAX, NBLK, NRMCHK
123 DOUBLE PRECISION EPS, EPS1, NRM, ONENRM, ORTOL, PERTOL, SCL,
124 $ SEP, STPCRT, TOL, XJ, XJM, ZTR
125
126
127 INTEGER ISEED( 4 )
128
129
130 INTEGER IDAMAX
131 DOUBLE PRECISION DASUM, DDOT, DLAMCH, DNRM2
133
134
137
138
139 INTRINSIC abs,
max, sqrt
140
141
142
143
144
145 info = 0
146 DO 10 i = 1, m
147 ifail( i ) = 0
148 10 CONTINUE
149
150 IF( n.LT.0 ) THEN
151 info = -1
152 ELSE IF( m.LT.0 .OR. m.GT.n ) THEN
153 info = -4
154 ELSE IF( orfac.LT.zero ) THEN
155 info = -8
156 ELSE IF( ldz.LT.
max( 1, n ) )
THEN
157 info = -10
158 ELSE
159 DO 20 j = 2, m
160 IF( iblock( j ).LT.iblock( j-1 ) ) THEN
161 info = -6
162 GO TO 30
163 END IF
164 IF( iblock( j ).EQ.iblock( j-1 ) .AND. w( j ).LT.w( j-1 ) )
165 $ THEN
166 info = -5
167 GO TO 30
168 END IF
169 20 CONTINUE
170 30 CONTINUE
171 END IF
172
173 IF( info.NE.0 ) THEN
174 CALL xerbla(
'DSTEIN2', -info )
175 RETURN
176 END IF
177
178
179
180 IF( n.EQ.0 .OR. m.EQ.0 ) THEN
181 RETURN
182 ELSE IF( n.EQ.1 ) THEN
183 z( 1, 1 ) = one
184 RETURN
185 END IF
186
187
188
189 eps =
dlamch(
'Precision' )
190
191
192
193 DO 40 i = 1, 4
194 iseed( i ) = 1
195 40 CONTINUE
196
197
198
199 indrv1 = 0
200 indrv2 = indrv1 + n
201 indrv3 = indrv2 + n
202 indrv4 = indrv3 + n
203 indrv5 = indrv4 + n
204
205
206
207 j1 = 1
208 DO 160 nblk = 1, iblock( m )
209
210
211
212 IF( nblk.EQ.1 ) THEN
213 b1 = 1
214 ELSE
215 b1 = isplit( nblk-1 ) + 1
216 END IF
217 bn = isplit( nblk )
218 blksiz = bn - b1 + 1
219 IF( blksiz.EQ.1 )
220 $ GO TO 60
221 gpind = j1
222
223
224
225 onenrm = abs( d( b1 ) ) + abs( e( b1 ) )
226 onenrm =
max( onenrm, abs( d( bn ) )+abs( e( bn-1 ) ) )
227 DO 50 i = b1 + 1, bn - 1
228 onenrm =
max( onenrm, abs( d( i ) )+abs( e( i-1 ) )+
229 $ abs( e( i ) ) )
230 50 CONTINUE
231 ortol = orfac*onenrm
232
233 stpcrt = sqrt( odm1 / blksiz )
234
235
236
237 60 CONTINUE
238 jblk = 0
239 DO 150 j = j1, m
240 IF( iblock( j ).NE.nblk ) THEN
241 j1 = j
242 GO TO 160
243 END IF
244 jblk = jblk + 1
245 xj = w( j )
246
247
248
249 IF( blksiz.EQ.1 ) THEN
250 work( indrv1+1 ) = one
251 GO TO 120
252 END IF
253
254
255
256
257 IF( jblk.GT.1 ) THEN
258 eps1 = abs( eps*xj )
259 pertol = ten*eps1
260 sep = xj - xjm
261 IF( sep.LT.pertol )
262 $ xj = xjm + pertol
263 END IF
264
265 its = 0
266 nrmchk = 0
267
268
269
270 CALL dlarnv( 2, iseed, blksiz, work( indrv1+1 ) )
271
272
273
274 CALL dcopy( blksiz, d( b1 ), 1, work( indrv4+1 ), 1 )
275 CALL dcopy( blksiz-1, e( b1 ), 1, work( indrv2+2 ), 1 )
276 CALL dcopy( blksiz-1, e( b1 ), 1, work( indrv3+1 ), 1 )
277
278
279
280 tol = zero
281 CALL dlagtf( blksiz, work( indrv4+1 ), xj, work( indrv2+2 ),
282 $ work( indrv3
283 $ iinfo )
284
285
286
287 70 CONTINUE
288 its = its + 1
289 IF( its.GT.maxits )
290 $ GO TO 100
291
292
293
294 scl = blksiz*onenrm*
max( eps,
295 $ abs( work( indrv4+blksiz ) ) ) /
296 $
dasum( blksiz, work( indrv1+1 ), 1 )
297 CALL dscal( blksiz, scl, work( indrv1+1 ), 1 )
298
299
300
301 CALL dlagts( -1, blksiz, work( indrv4+1 ), work( indrv2+2 ),
302 $ work( indrv3+1 ), work( indrv5+1 ), iwork,
303 $ work( indrv1+1 ), tol, iinfo )
304
305
306
307
308 IF( jblk.EQ.1 )
309 $ GO TO 90
310 IF( abs( xj-xjm ).GT.ortol )
311 $ gpind = j
312
313 IF( gpind.NE.j ) THEN
314 DO 80 i = gpind, j - 1
315 ztr = -
ddot( blksiz, work( indrv1+1 ), 1, z( b1, i ),
316 $ 1 )
317 CALL daxpy( blksiz, ztr, z( b1
318 $ work( indrv1+1 ), 1 )
319 80 CONTINUE
320 END IF
321
322
323
324 90 CONTINUE
325 jmax =
idamax( blksiz, work( indrv1+1 ), 1 )
326 nrm = abs( work( indrv1+jmax ) )
327
328
329
330
331 IF( nrm.LT.stpcrt )
332 $ GO TO 70
333 nrmchk = nrmchk + 1
334 IF( nrmchk.LT.extra+1
335 $ GO TO 70
336
337 GO TO 110
338
339
340
341
342 100 CONTINUE
343 info = info + 1
344 ifail( info ) = j
345
346
347
348 110 CONTINUE
349 scl = one /
dnrm2( blksiz, work( indrv1+1 ), 1 )
350 jmax =
idamax( blksiz, work( indrv1+1 ), 1 )
351 IF( work( indrv1+jmax ).LT.zero )
352 $ scl = -scl
353 CALL dscal( blksiz, scl, work( indrv1+1 ), 1 )
354 120 CONTINUE
355 DO 130 i = 1, n
356 z( i, j ) = zero
357 130 CONTINUE
358 DO 140 i = 1, blksiz
359 z( b1+i-1, j ) = work( indrv1+i )
360 140 CONTINUE
361
362
363
364
365 xjm = xj
366
367 150 CONTINUE
368 160 CONTINUE
369
370 RETURN
371
372
373
subroutine dlarnv(idist, iseed, n, x)
DLARNV returns a vector of random numbers from a uniform or normal distribution.
subroutine dlagts(job, n, a, b, c, d, in, y, tol, info)
DLAGTS solves the system of equations (T-λI)x = y or (T-λI)Tx = y,where T is a general tridiagonal ma...
subroutine dlagtf(n, a, lambda, b, c, tol, d, in, info)
DLAGTF computes an LU factorization of a matrix T-λI, where T is a general tridiagonal matrix,...
subroutine xerbla(srname, info)
XERBLA
integer function idamax(n, dx, incx)
IDAMAX
subroutine dscal(n, da, dx, incx)
DSCAL
double precision function ddot(n, dx, incx, dy, incy)
DDOT
double precision function dasum(n, dx, incx)
DASUM
subroutine daxpy(n, da, dx, incx, dy, incy)
DAXPY
subroutine dcopy(n, dx, incx, dy, incy)
DCOPY
real(wp) function dnrm2(n, x, incx)
DNRM2
double precision function dlamch(cmach)
DLAMCH