107
108
109
110
111
112
113 CHARACTER UPLO
114 INTEGER INFO, N
115
116
117 INTEGER IPIV( * )
118 REAL AP( * ), WORK( * )
119
120
121
122
123
124 REAL ONE, ZERO
125 parameter( one = 1.0e+0, zero = 0.0e+0 )
126
127
128 LOGICAL UPPER
129 INTEGER J, K, KC, KCNEXT, KP, KPC, KSTEP, KX, NPP
130 REAL AK, AKKP1, AKP1, D, T, TEMP
131
132
133 LOGICAL LSAME
134 REAL SDOT
136
137
139
140
141 INTRINSIC abs
142
143
144
145
146
147 info = 0
148 upper =
lsame( uplo,
'U' )
149 IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
150 info = -1
151 ELSE IF( n.LT.0 ) THEN
152 info = -2
153 END IF
154 IF( info.NE.0 ) THEN
155 CALL xerbla(
'SSPTRI', -info )
156 RETURN
157 END IF
158
159
160
161 IF( n.EQ.0 )
162 $ RETURN
163
164
165
166 IF( upper ) THEN
167
168
169
170 kp = n*( n+1 ) / 2
171 DO 10 info = n, 1, -1
172 IF( ipiv( info ).GT.0 .AND. ap( kp ).EQ.zero )
173 $ RETURN
174 kp = kp - info
175 10 CONTINUE
176 ELSE
177
178
179
180 kp = 1
181 DO 20 info = 1, n
182 IF( ipiv( info ).GT.0 .AND. ap( kp ).EQ.zero )
183 $ RETURN
184 kp = kp + n - info + 1
185 20 CONTINUE
186 END IF
187 info = 0
188
189 IF( upper ) THEN
190
191
192
193
194
195
196 k = 1
197 kc = 1
198 30 CONTINUE
199
200
201
202 IF( k.GT.n )
203 $ GO TO 50
204
205 kcnext = kc + k
206 IF( ipiv( k ).GT.0 ) THEN
207
208
209
210
211
212 ap( kc+k-1 ) = one / ap( kc+k-1 )
213
214
215
216 IF( k.GT.1 ) THEN
217 CALL scopy( k-1, ap( kc ), 1, work, 1 )
218 CALL sspmv( uplo, k-1, -one, ap, work, 1, zero,
219 $ ap( kc ),
220 $ 1 )
221 ap( kc+k-1 ) = ap( kc+k-1 ) -
222 $
sdot( k-1, work, 1, ap( kc ), 1 )
223 END IF
224 kstep = 1
225 ELSE
226
227
228
229
230
231 t = abs( ap( kcnext+k-1 ) )
232 ak = ap( kc+k-1 ) / t
233 akp1 = ap( kcnext+k ) / t
234 akkp1 = ap( kcnext+k-1 ) / t
235 d = t*( ak*akp1-one )
236 ap( kc+k-1 ) = akp1 / d
237 ap( kcnext+k ) = ak / d
238 ap( kcnext+k-1 ) = -akkp1 / d
239
240
241
242 IF( k.GT.1 ) THEN
243 CALL scopy( k-1, ap( kc ), 1, work, 1 )
244 CALL sspmv( uplo, k-1, -one, ap, work, 1, zero,
245 $ ap( kc ),
246 $ 1 )
247 ap( kc+k-1 ) = ap( kc+k-1 ) -
248 $
sdot( k-1, work, 1, ap( kc ), 1 )
249 ap( kcnext+k-1 ) = ap( kcnext+k-1 ) -
250 $
sdot( k-1, ap( kc ), 1,
251 $ ap( kcnext ),
252 $ 1 )
253 CALL scopy( k-1, ap( kcnext ), 1, work, 1 )
254 CALL sspmv( uplo, k-1, -one, ap, work, 1, zero,
255 $ ap( kcnext ), 1 )
256 ap( kcnext+k ) = ap( kcnext+k ) -
257 $
sdot( k-1, work, 1, ap( kcnext ), 1 )
258 END IF
259 kstep = 2
260 kcnext = kcnext + k + 1
261 END IF
262
263 kp = abs( ipiv( k ) )
264 IF( kp.NE.k ) THEN
265
266
267
268
269 kpc = ( kp-1 )*kp / 2 + 1
270 CALL sswap( kp-1, ap( kc ), 1, ap( kpc ), 1 )
271 kx = kpc + kp - 1
272 DO 40 j = kp + 1, k - 1
273 kx = kx + j - 1
274 temp = ap( kc+j-1 )
275 ap( kc+j-1 ) = ap( kx )
276 ap( kx ) = temp
277 40 CONTINUE
278 temp = ap( kc+k-1 )
279 ap( kc+k-1 ) = ap( kpc+kp-1 )
280 ap( kpc+kp-1 ) = temp
281 IF( kstep.EQ.2 ) THEN
282 temp = ap( kc+k+k-1 )
283 ap( kc+k+k-1 ) = ap( kc+k+kp-1 )
284 ap( kc+k+kp-1 ) = temp
285 END IF
286 END IF
287
288 k = k + kstep
289 kc = kcnext
290 GO TO 30
291 50 CONTINUE
292
293 ELSE
294
295
296
297
298
299
300 npp = n*( n+1 ) / 2
301 k = n
302 kc = npp
303 60 CONTINUE
304
305
306
307 IF( k.LT.1 )
308 $ GO TO 80
309
310 kcnext = kc - ( n-k+2 )
311 IF( ipiv( k ).GT.0 ) THEN
312
313
314
315
316
317 ap( kc ) = one / ap( kc )
318
319
320
321 IF( k.LT.n ) THEN
322 CALL scopy( n-k, ap( kc+1 ), 1, work, 1 )
323 CALL sspmv( uplo, n-k, -one, ap( kc+n-k+1 ), work, 1,
324 $ zero, ap( kc+1 ), 1 )
325 ap( kc ) = ap( kc ) -
sdot( n-k, work, 1, ap( kc+1 ),
326 $ 1 )
327 END IF
328 kstep = 1
329 ELSE
330
331
332
333
334
335 t = abs( ap( kcnext+1 ) )
336 ak = ap( kcnext ) / t
337 akp1 = ap( kc ) / t
338 akkp1 = ap( kcnext+1 ) / t
339 d = t*( ak*akp1-one )
340 ap( kcnext ) = akp1 / d
341 ap( kc ) = ak / d
342 ap( kcnext+1 ) = -akkp1 / d
343
344
345
346 IF( k.LT.n ) THEN
347 CALL scopy( n-k, ap( kc+1 ), 1, work, 1 )
348 CALL sspmv( uplo, n-k, -one, ap( kc+( n-k+1 ) ), work,
349 $ 1,
350 $ zero, ap( kc+1 ), 1 )
351 ap( kc ) = ap( kc ) -
sdot( n-k, work, 1, ap( kc+1 ),
352 $ 1 )
353 ap( kcnext+1 ) = ap( kcnext+1 ) -
354 $
sdot( n-k, ap( kc+1 ), 1,
355 $ ap( kcnext+2 ), 1 )
356 CALL scopy( n-k, ap( kcnext+2 ), 1, work, 1 )
357 CALL sspmv( uplo, n-k, -one, ap( kc+( n-k+1 ) ), work,
358 $ 1,
359 $ zero, ap( kcnext+2 ), 1 )
360 ap( kcnext ) = ap( kcnext ) -
361 $
sdot( n-k, work, 1, ap( kcnext+2 ), 1 )
362 END IF
363 kstep = 2
364 kcnext = kcnext - ( n-k+3 )
365 END IF
366
367 kp = abs( ipiv( k ) )
368 IF( kp.NE.k ) THEN
369
370
371
372
373 kpc = npp - ( n-kp+1 )*( n-kp+2 ) / 2 + 1
374 IF( kp.LT.n )
375 $
CALL sswap( n-kp, ap( kc+kp-k+1 ), 1, ap( kpc+1 ), 1 )
376 kx = kc + kp - k
377 DO 70 j = k + 1, kp - 1
378 kx = kx + n - j + 1
379 temp = ap( kc+j-k )
380 ap( kc+j-k ) = ap( kx )
381 ap( kx ) = temp
382 70 CONTINUE
383 temp = ap( kc )
384 ap( kc ) = ap( kpc )
385 ap( kpc ) = temp
386 IF( kstep.EQ.2 ) THEN
387 temp = ap( kc-n+k-1 )
388 ap( kc-n+k-1 ) = ap( kc-n+kp-1 )
389 ap( kc-n+kp-1 ) = temp
390 END IF
391 END IF
392
393 k = k - kstep
394 kc = kcnext
395 GO TO 60
396 80 CONTINUE
397 END IF
398
399 RETURN
400
401
402
subroutine xerbla(srname, info)
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
real function sdot(n, sx, incx, sy, incy)
SDOT
subroutine sspmv(uplo, n, alpha, ap, x, incx, beta, y, incy)
SSPMV
logical function lsame(ca, cb)
LSAME
subroutine sswap(n, sx, incx, sy, incy)
SSWAP