4
5
6
7
8
9 IMPLICIT NONE
10
11
12 INTEGER IFIRST, ILAST, INFO, N, OFFSET, TWIST
13 REAL LGPVMN, LGSPDM, PIVMIN,
14 $ RTOL1, RTOL2
15
16
17 INTEGER IWORK( * )
18 REAL D( * ), LLD( * ), W( * ),
19 $ WERR( * ), WGAP( * ), 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 REAL ZERO, TWO, HALF
119 parameter( zero = 0.0e0, two = 2.0e0,
120 $ half = 0.5e0 )
121 INTEGER MAXITR
122
123
124 INTEGER I, I1, II, INDLLD, IP, ITER, J, K, NEGCNT,
125 $ NEXT, NINT, OLNINT, PREV, R
126 REAL BACK, CVRGD, GAP, LEFT, LGAP, MID, MNWDTH,
127 $ RGAP, RIGHT, SAVGAP, TMP, WIDTH
128 LOGICAL PARANOID
129
130
131 LOGICAL SISNAN
132 REAL SLAMCH
133 INTEGER SLANEG2A
136
137
138
140
141
142
143 info = 0
144
145
146
147
148 paranoid = .true.
149
150 maxitr = int( ( lgspdm - lgpvmn ) / log( two ) ) + 2
151 mnwdth = two * pivmin
152
153 r = twist
154
155 indlld = 2*n
156 DO 5 j = 1, n-1
157 i=2*j
158 work(indlld+i-1) = d(j)
159 work(indlld+i) = lld(j)
160 5 CONTINUE
161 work(indlld+2*n-1) = d(n)
162
163 IF((r.LT.1).OR.(r.GT.n)) r = n
164
165
166
167
168
169
170
171
172 i1 = ifirst
173
174 nint = 0
175
176 prev = 0
177
178 rgap = wgap( i1-offset )
179 DO 75 i = i1, ilast
180 k = 2*i
181 ii = i - offset
182 left = w( ii ) - werr( ii )
183 right = w( ii ) + werr( ii )
184 lgap = rgap
185 rgap = wgap( ii )
186 gap =
min( lgap, rgap )
187
188 IF((abs(left).LE.16*pivmin).OR.(abs(right).LE.16*pivmin))
189 $ THEN
190 info = -1
191 RETURN
192 ENDIF
193
194 IF( paranoid ) THEN
195
196
197
198
199
200 back = werr( ii )
201 20 CONTINUE
202 negcnt =
slaneg2a( n, work(indlld+1), left, pivmin, r )
203 IF( negcnt.GT.i-1 ) THEN
204 left = left - back
205 back = two*back
206 GO TO 20
207 END IF
208
209
210
211
212 back = werr( ii )
213 50 CONTINUE
214 negcnt =
slaneg2a( n, work(indlld+1),right, pivmin, r )
215
216 IF( negcnt.LT.i ) THEN
217 right = right + back
218 back = two*back
219 GO TO 50
220 END IF
221 ENDIF
222
223 width = half*abs( left - right )
224 tmp =
max( abs( left ), abs( right ) )
225 cvrgd =
max(rtol1*gap,rtol2*tmp)
226 IF( width.LE.cvrgd .OR. width.LE.mnwdth ) THEN
227
228
229
230
231 iwork( k-1 ) = -1
232
233 IF((i.EQ.i1).AND.(i.LT.ilast)) i1 = i + 1
234 IF((prev.GE.i1).AND.(i.LE.ilast)) iwork( 2*prev-1 ) = i + 1
235 ELSE
236
237 prev = i
238 nint = nint + 1
239 iwork( k-1 ) = i + 1
240 iwork( k ) = negcnt
241 END IF
242 work( k-1 ) = left
243 work( k ) = right
244 75 CONTINUE
245
246
247
248
249
250 iter = 0
251 80 CONTINUE
252 prev = i1 - 1
253 i = i1
254 olnint = nint
255
256 DO 100 ip = 1, olnint
257 k = 2*i
258 ii = i - offset
259 rgap = wgap( ii )
260 lgap = rgap
261 IF(ii.GT.1) lgap = wgap( ii-1 )
262 gap =
min( lgap, rgap )
263 next = iwork( k-1 )
264 left = work( k-1 )
265 right = work( k )
266 mid = half*( left + right )
267
268 width = right - mid
269 tmp =
max( abs( left ), abs( right ) )
270 cvrgd =
max(rtol1*gap,rtol2*tmp)
271 IF( ( width.LE.cvrgd ) .OR. ( width.LE.mnwdth ).OR.
272 $ ( iter.EQ.maxitr ) )THEN
273
274 nint = nint - 1
275
276 iwork( k-1 ) = 0
277 IF( i1.EQ.i ) THEN
278 i1 = next
279 ELSE
280
281 IF(prev.GE.i1) iwork( 2*prev-1 ) = next
282 END IF
283 i = next
284 GO TO 100
285 END IF
286 prev = i
287
288
289
290 negcnt =
slaneg2a( n, work(indlld+1), mid, pivmin, r )
291 IF( negcnt.LE.i-1 ) THEN
292 work( k-1 ) = mid
293 ELSE
294 work( k ) = mid
295 END IF
296 i = next
297 100 CONTINUE
298 iter = iter + 1
299
300
301
302 IF( ( nint.GT.0 ).AND.(iter.LE.maxitr) ) GO TO 80
303
304
305
306
307
308 savgap = wgap( ilast-offset )
309
310 left = work( 2*ifirst-1 )
311 DO 110 i = ifirst, ilast
312 k = 2*i
313 ii = i - offset
314
315 right = work( k )
316
317 IF( iwork( k-1 ).EQ.0 ) THEN
318 w( ii ) = half*( left+right )
319 werr( ii ) = right - w( ii )
320 END IF
321
322 left = work( k +1 )
323 wgap( ii ) =
max( zero, left - right )
324 110 CONTINUE
325
326 wgap( ilast-offset ) = savgap
327
328 RETURN
329
330
331
integer function slaneg2a(n, dlld, sigma, pivmin, r)