175
176
177
178
179
180
181 CHARACTER UPLO
182 INTEGER INFO, KB, LDA, LDW, N, NB
183
184
185 INTEGER IPIV( * )
186 REAL A( LDA, * ), W( LDW, * )
187
188
189
190
191
192 REAL ZERO, ONE
193 parameter( zero = 0.0e+0, one = 1.0e+0 )
194 REAL EIGHT, SEVTEN
195 parameter( eight = 8.0e+0, sevten = 17.0e+0 )
196
197
198 INTEGER IMAX, J, JJ, JMAX, JP, K, KK, KKW, KP,
199 $ KSTEP, KW
200 REAL ABSAKK, ALPHA, COLMAX, D11, D21, D22, R1,
201 $ ROWMAX, T
202
203
204 LOGICAL LSAME
205 INTEGER ISAMAX
207
208
210
211
212 INTRINSIC abs, max, min, sqrt
213
214
215
216 info = 0
217
218
219
220 alpha = ( one+sqrt( sevten ) ) / eight
221
222 IF(
lsame( uplo,
'U' ) )
THEN
223
224
225
226
227
228
229
230
231
232 k = n
233 10 CONTINUE
234 kw = nb + k - n
235
236
237
238 IF( ( k.LE.n-nb+1 .AND. nb.LT.n ) .OR. k.LT.1 )
239 $ GO TO 30
240
241
242
243 CALL scopy( k, a( 1, k ), 1, w( 1, kw ), 1 )
244 IF( k.LT.n )
245 $
CALL sgemv(
'No transpose', k, n-k, -one, a( 1, k+1 ),
246 $ lda,
247 $ w( k, kw+1 ), ldw, one, w( 1, kw ), 1 )
248
249 kstep = 1
250
251
252
253
254 absakk = abs( w( k, kw ) )
255
256
257
258
259
260 IF( k.GT.1 ) THEN
261 imax =
isamax( k-1, w( 1, kw ), 1 )
262 colmax = abs( w( imax, kw ) )
263 ELSE
264 colmax = zero
265 END IF
266
267 IF( max( absakk, colmax ).EQ.zero ) THEN
268
269
270
271 IF( info.EQ.0 )
272 $ info = k
273 kp = k
274 ELSE
275 IF( absakk.GE.alpha*colmax ) THEN
276
277
278
279 kp = k
280 ELSE
281
282
283
284 CALL scopy( imax, a( 1, imax ), 1, w( 1, kw-1 ), 1 )
285 CALL scopy( k-imax, a( imax, imax+1 ), lda,
286 $ w( imax+1, kw-1 ), 1 )
287 IF( k.LT.n )
288 $
CALL sgemv(
'No transpose', k, n-k, -one, a( 1,
289 $ k+1 ),
290 $ lda, w( imax, kw+1 ), ldw, one,
291 $ w( 1, kw-1 ), 1 )
292
293
294
295
296 jmax = imax +
isamax( k-imax, w( imax+1, kw-1 ), 1 )
297 rowmax = abs( w( jmax, kw-1 ) )
298 IF( imax.GT.1 ) THEN
299 jmax =
isamax( imax-1, w( 1, kw-1 ), 1 )
300 rowmax = max( rowmax, abs( w( jmax, kw-1 ) ) )
301 END IF
302
303 IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
304
305
306
307 kp = k
308 ELSE IF( abs( w( imax, kw-1 ) ).GE.alpha*rowmax ) THEN
309
310
311
312
313 kp = imax
314
315
316
317 CALL scopy( k, w( 1, kw-1 ), 1, w( 1, kw ), 1 )
318 ELSE
319
320
321
322
323 kp = imax
324 kstep = 2
325 END IF
326 END IF
327
328
329
330
331
332 kk = k - kstep + 1
333
334
335
336 kkw = nb + kk - n
337
338
339
340
341 IF( kp.NE.kk ) THEN
342
343
344
345
346
347
348 a( kp, kp ) = a( kk, kk )
349 CALL scopy( kk-1-kp, a( kp+1, kk ), 1, a( kp, kp+1 ),
350 $ lda )
351 IF( kp.GT.1 )
352 $
CALL scopy( kp-1, a( 1, kk ), 1, a( 1, kp ), 1 )
353
354
355
356
357
358
359 IF( k.LT.n )
360 $
CALL sswap( n-k, a( kk, k+1 ), lda, a( kp, k+1 ),
361 $ lda )
362 CALL sswap( n-kk+1, w( kk, kkw ), ldw, w( kp, kkw ),
363 $ ldw )
364 END IF
365
366 IF( kstep.EQ.1 ) THEN
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381 CALL scopy( k, w( 1, kw ), 1, a( 1, k ), 1 )
382 r1 = one / a( k, k )
383 CALL sscal( k-1, r1, a( 1, k ), 1 )
384
385 ELSE
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402 IF( k.GT.2 ) THEN
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429 d21 = w( k-1, kw )
430 d11 = w( k, kw ) / d21
431 d22 = w( k-1, kw-1 ) / d21
432 t = one / ( d11*d22-one )
433 d21 = t / d21
434
435
436
437
438
439 DO 20 j = 1, k - 2
440 a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) )
441 a( j, k ) = d21*( d22*w( j, kw )-w( j, kw-1 ) )
442 20 CONTINUE
443 END IF
444
445
446
447 a( k-1, k-1 ) = w( k-1, kw-1 )
448 a( k-1, k ) = w( k-1, kw )
449 a( k, k ) = w( k, kw )
450
451 END IF
452
453 END IF
454
455
456
457 IF( kstep.EQ.1 ) THEN
458 ipiv( k ) = kp
459 ELSE
460 ipiv( k ) = -kp
461 ipiv( k-1 ) = -kp
462 END IF
463
464
465
466 k = k - kstep
467 GO TO 10
468
469 30 CONTINUE
470
471
472
473
474
475 CALL sgemmtr(
'Upper',
'No transpose',
'Transpose', k, n-k,
476 $ -one, a( 1, k+1 ), lda, w( 1, kw+1 ), ldw,
477 $ one, a( 1, 1 ), lda )
478
479
480
481
482 j = k + 1
483 60 CONTINUE
484
485
486
487
488
489 jj = j
490 jp = ipiv( j )
491 IF( jp.LT.0 ) THEN
492 jp = -jp
493
494 j = j + 1
495 END IF
496
497
498 j = j + 1
499 IF( jp.NE.jj .AND. j.LE.n )
500 $
CALL sswap( n-j+1, a( jp, j ), lda, a( jj, j ), lda )
501 IF( j.LT.n )
502 $ GO TO 60
503
504
505
506 kb = n - k
507
508 ELSE
509
510
511
512
513
514
515
516 k = 1
517 70 CONTINUE
518
519
520
521 IF( ( k.GE.nb .AND. nb.LT.n ) .OR. k.GT.n )
522 $ GO TO 90
523
524
525
526 CALL scopy( n-k+1, a( k, k ), 1, w( k, k ), 1 )
527 CALL sgemv(
'No transpose', n-k+1, k-1, -one, a( k, 1 ),
528 $ lda,
529 $ w( k, 1 ), ldw, one, w( k, k ), 1 )
530
531 kstep = 1
532
533
534
535
536 absakk = abs( w( k, k ) )
537
538
539
540
541
542 IF( k.LT.n ) THEN
543 imax = k +
isamax( n-k, w( k+1, k ), 1 )
544 colmax = abs( w( imax, k ) )
545 ELSE
546 colmax = zero
547 END IF
548
549 IF( max( absakk, colmax ).EQ.zero ) THEN
550
551
552
553 IF( info.EQ.0 )
554 $ info = k
555 kp = k
556 ELSE
557 IF( absakk.GE.alpha*colmax ) THEN
558
559
560
561 kp = k
562 ELSE
563
564
565
566 CALL scopy( imax-k, a( imax, k ), lda, w( k, k+1 ),
567 $ 1 )
568 CALL scopy( n-imax+1, a( imax, imax ), 1, w( imax,
569 $ k+1 ),
570 $ 1 )
571 CALL sgemv(
'No transpose', n-k+1, k-1, -one, a( k,
572 $ 1 ),
573 $ lda, w( imax, 1 ), ldw, one, w( k, k+1 ), 1 )
574
575
576
577
578 jmax = k - 1 +
isamax( imax-k, w( k, k+1 ), 1 )
579 rowmax = abs( w( jmax, k+1 ) )
580 IF( imax.LT.n ) THEN
581 jmax = imax +
isamax( n-imax, w( imax+1, k+1 ), 1 )
582 rowmax = max( rowmax, abs( w( jmax, k+1 ) ) )
583 END IF
584
585 IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
586
587
588
589 kp = k
590 ELSE IF( abs( w( imax, k+1 ) ).GE.alpha*rowmax ) THEN
591
592
593
594
595 kp = imax
596
597
598
599 CALL scopy( n-k+1, w( k, k+1 ), 1, w( k, k ), 1 )
600 ELSE
601
602
603
604
605 kp = imax
606 kstep = 2
607 END IF
608 END IF
609
610
611
612
613
614 kk = k + kstep - 1
615
616
617
618
619 IF( kp.NE.kk ) THEN
620
621
622
623
624
625
626 a( kp, kp ) = a( kk, kk )
627 CALL scopy( kp-kk-1, a( kk+1, kk ), 1, a( kp, kk+1 ),
628 $ lda )
629 IF( kp.LT.n )
630 $
CALL scopy( n-kp, a( kp+1, kk ), 1, a( kp+1, kp ),
631 $ 1 )
632
633
634
635
636
637
638 IF( k.GT.1 )
639 $
CALL sswap( k-1, a( kk, 1 ), lda, a( kp, 1 ), lda )
640 CALL sswap( kk, w( kk, 1 ), ldw, w( kp, 1 ), ldw )
641 END IF
642
643 IF( kstep.EQ.1 ) THEN
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658 CALL scopy( n-k+1, w( k, k ), 1, a( k, k ), 1 )
659 IF( k.LT.n ) THEN
660 r1 = one / a( k, k )
661 CALL sscal( n-k, r1, a( k+1, k ), 1 )
662 END IF
663
664 ELSE
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681 IF( k.LT.n-1 ) THEN
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708 d21 = w( k+1, k )
709 d11 = w( k+1, k+1 ) / d21
710 d22 = w( k, k ) / d21
711 t = one / ( d11*d22-one )
712 d21 = t / d21
713
714
715
716
717
718 DO 80 j = k + 2, n
719 a( j, k ) = d21*( d11*w( j, k )-w( j, k+1 ) )
720 a( j, k+1 ) = d21*( d22*w( j, k+1 )-w( j, k ) )
721 80 CONTINUE
722 END IF
723
724
725
726 a( k, k ) = w( k, k )
727 a( k+1, k ) = w( k+1, k )
728 a( k+1, k+1 ) = w( k+1, k+1 )
729
730 END IF
731
732 END IF
733
734
735
736 IF( kstep.EQ.1 ) THEN
737 ipiv( k ) = kp
738 ELSE
739 ipiv( k ) = -kp
740 ipiv( k+1 ) = -kp
741 END IF
742
743
744
745 k = k + kstep
746 GO TO 70
747
748 90 CONTINUE
749
750
751
752
753
754 CALL sgemmtr(
'Lower',
'No transpose',
'Transpose', n-k+1,
755 $ k-1, -one, a( k, 1 ), lda, w( k, 1 ), ldw,
756 $ one, a( k, k ), lda )
757
758
759
760
761 j = k - 1
762 120 CONTINUE
763
764
765
766
767
768 jj = j
769 jp = ipiv( j )
770 IF( jp.LT.0 ) THEN
771 jp = -jp
772
773 j = j - 1
774 END IF
775
776
777 j = j - 1
778 IF( jp.NE.jj .AND. j.GE.1 )
779 $
CALL sswap( j, a( jp, 1 ), lda, a( jj, 1 ), lda )
780 IF( j.GT.1 )
781 $ GO TO 120
782
783
784
785 kb = k - 1
786
787 END IF
788 RETURN
789
790
791
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
subroutine sgemmtr(uplo, transa, transb, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMMTR
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
integer function isamax(n, sx, incx)
ISAMAX
logical function lsame(ca, cb)
LSAME
subroutine sscal(n, sa, sx, incx)
SSCAL
subroutine sswap(n, sx, incx, sy, incy)
SSWAP