141
142
143
144
145
146
147 REAL TOL
148 INTEGER INFO, LDA, N, RANK
149 CHARACTER UPLO
150
151
152 REAL A( LDA, * ), WORK( 2*N )
153 INTEGER PIV( N )
154
155
156
157
158
159 REAL ONE, ZERO
160 parameter( one = 1.0e+0, zero = 0.0e+0 )
161
162
163 REAL AJJ, SSTOP, STEMP
164 INTEGER I, ITEMP, J, JB, K, NB, PVT
165 LOGICAL UPPER
166
167
168 REAL SLAMCH
169 INTEGER ILAENV
170 LOGICAL LSAME, SISNAN
172
173
175
176
177 INTRINSIC max, min, sqrt, maxloc
178
179
180
181
182
183 info = 0
184 upper =
lsame( uplo,
'U' )
185 IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
186 info = -1
187 ELSE IF( n.LT.0 ) THEN
188 info = -2
189 ELSE IF( lda.LT.max( 1, n ) ) THEN
190 info = -4
191 END IF
192 IF( info.NE.0 ) THEN
193 CALL xerbla(
'SPSTRF', -info )
194 RETURN
195 END IF
196
197
198
199 IF( n.EQ.0 )
200 $ RETURN
201
202
203
204 nb =
ilaenv( 1,
'SPOTRF', uplo, n, -1, -1, -1 )
205 IF( nb.LE.1 .OR. nb.GE.n ) THEN
206
207
208
209 CALL spstf2( uplo, n, a( 1, 1 ), lda, piv, rank, tol, work,
210 $ info )
211 GO TO 200
212
213 ELSE
214
215
216
217 DO 100 i = 1, n
218 piv( i ) = i
219 100 CONTINUE
220
221
222
223 pvt = 1
224 ajj = a( pvt, pvt )
225 DO i = 2, n
226 IF( a( i, i ).GT.ajj ) THEN
227 pvt = i
228 ajj = a( pvt, pvt )
229 END IF
230 END DO
231 IF( ajj.LE.zero.OR.
sisnan( ajj ) )
THEN
232 rank = 0
233 info = 1
234 GO TO 200
235 END IF
236
237
238
239 IF( tol.LT.zero ) THEN
240 sstop = n *
slamch(
'Epsilon' ) * ajj
241 ELSE
242 sstop = tol
243 END IF
244
245
246 IF( upper ) THEN
247
248
249
250 DO 140 k = 1, n, nb
251
252
253
254 jb = min( nb, n-k+1 )
255
256
257
258
259 DO 110 i = k, n
260 work( i ) = 0
261 110 CONTINUE
262
263 DO 130 j = k, k + jb - 1
264
265
266
267
268
269 DO 120 i = j, n
270
271 IF( j.GT.k ) THEN
272 work( i ) = work( i ) + a( j-1, i )**2
273 END IF
274 work( n+i ) = a( i, i ) - work( i )
275
276 120 CONTINUE
277
278 IF( j.GT.1 ) THEN
279 itemp = maxloc( work( (n+j):(2*n) ), 1 )
280 pvt = itemp + j - 1
281 ajj = work( n+pvt )
282 IF( ajj.LE.sstop.OR.
sisnan( ajj ) )
THEN
283 a( j, j ) = ajj
284 GO TO 190
285 END IF
286 END IF
287
288 IF( j.NE.pvt ) THEN
289
290
291
292 a( pvt, pvt ) = a( j, j )
293 CALL sswap( j-1, a( 1, j ), 1, a( 1, pvt ), 1 )
294 IF( pvt.LT.n )
295 $
CALL sswap( n-pvt, a( j, pvt+1 ), lda,
296 $ a( pvt, pvt+1 ), lda )
297 CALL sswap( pvt-j-1, a( j, j+1 ), lda,
298 $ a( j+1, pvt ), 1 )
299
300
301
302 stemp = work( j )
303 work( j ) = work( pvt )
304 work( pvt ) = stemp
305 itemp = piv( pvt )
306 piv( pvt ) = piv( j )
307 piv( j ) = itemp
308 END IF
309
310 ajj = sqrt( ajj )
311 a( j, j ) = ajj
312
313
314
315 IF( j.LT.n ) THEN
316 CALL sgemv(
'Trans', j-k, n-j, -one, a( k, j+1 ),
317 $ lda, a( k, j ), 1, one, a( j, j+1 ),
318 $ lda )
319 CALL sscal( n-j, one / ajj, a( j, j+1 ), lda )
320 END IF
321
322 130 CONTINUE
323
324
325
326 IF( k+jb.LE.n ) THEN
327 CALL ssyrk(
'Upper',
'Trans', n-j+1, jb, -one,
328 $ a( k, j ), lda, one, a( j, j ), lda )
329 END IF
330
331 140 CONTINUE
332
333 ELSE
334
335
336
337 DO 180 k = 1, n, nb
338
339
340
341 jb = min( nb, n-k+1 )
342
343
344
345
346 DO 150 i = k, n
347 work( i ) = 0
348 150 CONTINUE
349
350 DO 170 j = k, k + jb - 1
351
352
353
354
355
356 DO 160 i = j, n
357
358 IF( j.GT.k ) THEN
359 work( i ) = work( i ) + a( i, j-1 )**2
360 END IF
361 work( n+i ) = a( i, i ) - work( i )
362
363 160 CONTINUE
364
365 IF( j.GT.1 ) THEN
366 itemp = maxloc( work( (n+j):(2*n) ), 1 )
367 pvt = itemp + j - 1
368 ajj = work( n+pvt )
369 IF( ajj.LE.sstop.OR.
sisnan( ajj ) )
THEN
370 a( j, j ) = ajj
371 GO TO 190
372 END IF
373 END IF
374
375 IF( j.NE.pvt ) THEN
376
377
378
379 a( pvt, pvt ) = a( j, j )
380 CALL sswap( j-1, a( j, 1 ), lda, a( pvt, 1 ), lda )
381 IF( pvt.LT.n )
382 $
CALL sswap( n-pvt, a( pvt+1, j ), 1,
383 $ a( pvt+1, pvt ), 1 )
384 CALL sswap( pvt-j-1, a( j+1, j ), 1, a( pvt, j+1 ),
385 $ lda )
386
387
388
389 stemp = work( j )
390 work( j ) = work( pvt )
391 work( pvt ) = stemp
392 itemp = piv( pvt )
393 piv( pvt ) = piv( j )
394 piv( j ) = itemp
395 END IF
396
397 ajj = sqrt( ajj )
398 a( j, j ) = ajj
399
400
401
402 IF( j.LT.n ) THEN
403 CALL sgemv(
'No Trans', n-j, j-k, -one,
404 $ a( j+1, k ), lda, a( j, k ), lda, one,
405 $ a( j+1, j ), 1 )
406 CALL sscal( n-j, one / ajj, a( j+1, j ), 1 )
407 END IF
408
409 170 CONTINUE
410
411
412
413 IF( k+jb.LE.n ) THEN
414 CALL ssyrk(
'Lower',
'No Trans', n-j+1, jb, -one,
415 $ a( j, k ), lda, one, a( j, j ), lda )
416 END IF
417
418 180 CONTINUE
419
420 END IF
421 END IF
422
423
424
425 rank = n
426
427 GO TO 200
428 190 CONTINUE
429
430
431
432
433 rank = j - 1
434 info = 1
435
436 200 CONTINUE
437 RETURN
438
439
440
subroutine xerbla(srname, info)
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
subroutine ssyrk(uplo, trans, n, k, alpha, a, lda, beta, c, ldc)
SSYRK
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
logical function sisnan(sin)
SISNAN tests input for NaN.
real function slamch(cmach)
SLAMCH
logical function lsame(ca, cb)
LSAME
subroutine spstf2(uplo, n, a, lda, piv, rank, tol, work, info)
SPSTF2 computes the Cholesky factorization with complete pivoting of a real symmetric positive semide...
subroutine sscal(n, sa, sx, incx)
SSCAL
subroutine sswap(n, sx, incx, sy, incy)
SSWAP