1 SUBROUTINE pclattrs( UPLO, TRANS, DIAG, NORMIN, N, A, IA, JA,
2 $ DESCA, X, IX, JX, DESCX, SCALE, CNORM, INFO )
10 CHARACTER DIAG, NORMIN, TRANS, UPLO
11 INTEGER IA, INFO, IX, JA, JX, N
15 INTEGER DESCA( * ), DESCX( * )
17 COMPLEX A( * ), X( * )
255 REAL ZERO, HALF, ONE, TWO
256 parameter( zero = 0.0e+0, half = 0.5e+0, one = 1.0e+0,
259 parameter( czero = ( 0.0e+0, 0.0e+0 ),
260 $ cone = ( 1.0e+0, 0.0e+0 ) )
261 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
262 $ mb_, nb_, rsrc_, csrc_, lld_
263 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
264 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
265 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
268 LOGICAL NOTRAN, NOUNIT, UPPER
269 INTEGER CONTXT, CSRC, I, ICOL, ICOLX, IMAX, IROW,
270 $ irowx, itmp1, itmp1x, itmp2, itmp2x, j, jfirst,
271 $ jinc, jlast, lda, ldx, mb, mycol, myrow, nb,
273 REAL BIGNUM, GROW, REC, SMLNUM, TJJ, TMAX, TSCAL,
276 COMPLEX CSUMJ, TJJS, USCAL, XJTMP, ZDUM
282 EXTERNAL lsame, isamax, pslamch
285 EXTERNAL blacs_gridinfo, sgsum2d, sscal,
infog2l,
287 $ pcdotc, pcdotu, pcsscal,
pclaset, pcscal,
288 $ pctrsv, cgebr2d, cgebs2d, sladiv
297 cabs1( zdum ) = abs( real( zdum ) ) + abs( aimag( zdum ) )
298 cabs2( zdum ) = abs( real( zdum ) / 2.e0 ) +
299 $ abs( aimag( zdum ) / 2.e0 )
304 upper = lsame( uplo,
'U' )
305 notran = lsame( trans,
'N' )
306 nounit = lsame( diag,
'N' )
308 contxt = desca( ctxt_ )
309 rsrc = desca( rsrc_ )
310 csrc = desca( csrc_ )
318 IF( .NOT.upper .AND. .NOT.lsame( uplo,
'L' ) )
THEN
320 ELSE IF( .NOT.notran .AND. .NOT.lsame( trans,
'T' ) .AND. .NOT.
321 $ lsame( trans,
'C' ) )
THEN
323 ELSE IF( .NOT.nounit .AND. .NOT.lsame( diag,
'U' ) )
THEN
325 ELSE IF( .NOT.lsame( normin,
'Y' ) .AND. .NOT.
326 $ lsame( normin,
'N' ) )
THEN
328 ELSE IF( n.LT.0 )
THEN
332 CALL blacs_gridinfo( contxt, nprow, npcol, myrow, mycol )
335 CALL pxerbla( contxt,
'PCLATTRS', -info )
346 smlnum = pslamch( contxt,
'Safe minimum' )
347 bignum = one / smlnum
348 CALL pslabad( contxt, smlnum, bignum )
349 smlnum = smlnum / pslamch( contxt,
'Precision' )
350 bignum = one / smlnum
354 IF( lsame( normin,
'N' ) )
THEN
364 CALL pscasum( j-1, cnorm( j ), a, ia, ja+j-1, desca, 1 )
371 CALL pscasum( n-j, cnorm( j ), a, ia+j, ja+j-1, desca,
376 CALL sgsum2d( contxt,
'Row',
' ', n, 1, cnorm, 1, -1, -1 )
382 imax = isamax( n, cnorm, 1 )
384 IF( tmax.LE.bignum*half )
THEN
387 tscal = half / ( smlnum*tmax )
388 CALL sscal( n, tscal, cnorm, 1 )
395 CALL pcamax( n, zdum, imax, x, ix, jx, descx, 1 )
396 xmax( 1 ) = cabs2( zdum )
397 CALL sgsum2d( contxt,
'Row',
' ', 1, 1, xmax, 1, -1, -1 )
414 IF( tscal.NE.one )
THEN
426 grow = half /
max( xbnd, smlnum )
428 DO 30 j = jfirst, jlast, jinc
436 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol, myrow,
437 $ mycol, irow, icol, itmp1, itmp2 )
438 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
THEN
439 tjjs = a( ( icol-1 )*lda+irow )
440 CALL cgebs2d( contxt,
'All',
' ', 1, 1, tjjs, 1 )
442 CALL cgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
447 IF( tjj.GE.smlnum )
THEN
451 xbnd =
min( xbnd,
min( one, tjj )*grow )
459 IF( tjj+cnorm( j ).GE.smlnum )
THEN
463 grow = grow*( tjj / ( tjj+cnorm( j ) ) )
478 grow =
min( one, half /
max( xbnd, smlnum ) )
479 DO 40 j = jfirst, jlast, jinc
488 grow = grow*( one / ( one+cnorm( j ) ) )
507 IF( tscal.NE.one )
THEN
519 grow = half /
max( xbnd, smlnum )
521 DO 60 j = jfirst, jlast, jinc
530 xj = one + cnorm( j )
531 grow =
min( grow, xbnd / xj )
534 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol, myrow,
535 $ mycol, irow, icol, itmp1, itmp2 )
536 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
THEN
537 tjjs = a( ( icol-1 )*lda+irow )
538 CALL cgebs2d( contxt,
'All',
' ', 1, 1, tjjs, 1 )
540 CALL cgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
545 IF( tjj.GE.smlnum )
THEN
550 $ xbnd = xbnd*( tjj / xj )
558 grow =
min( grow, xbnd )
565 grow =
min( one, half /
max( xbnd, smlnum ) )
566 DO 70 j = jfirst, jlast, jinc
575 xj = one + cnorm( j )
582 IF( ( grow*tscal ).GT.smlnum )
THEN
587 CALL pctrsv( uplo, trans, diag, n, a, ia, ja, desca, x, ix, jx,
593 IF( xmax( 1 ).GT.bignum*half )
THEN
598 scale = ( bignum*half ) / xmax( 1 )
599 CALL pcsscal( n, scale, x, ix, jx, descx, 1 )
602 xmax( 1 ) = xmax( 1 )*two
609 DO 100 j = jfirst, jlast, jinc
614 CALL infog2l( ix+j-1, jx, descx, nprow, npcol, myrow,
615 $ mycol, irowx, icolx, itmp1x, itmp2x )
616 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
THEN
618 CALL cgebs2d( contxt,
'All',
' ', 1, 1, xjtmp, 1 )
620 CALL cgebr2d( contxt,
'All',
' ', 1, 1, xjtmp, 1,
626 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
627 $ myrow, mycol, irow, icol, itmp1, itmp2 )
628 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
THEN
629 tjjs = a( ( icol-1 )*lda+irow )*tscal
630 CALL cgebs2d( contxt,
'All',
' ', 1, 1, tjjs, 1 )
632 CALL cgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
641 IF( tjj.GT.smlnum )
THEN
645 IF( tjj.LT.one )
THEN
646 IF( xj.GT.tjj*bignum )
THEN
651 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
654 xmax( 1 ) = xmax( 1 )*rec
659 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
660 $ real( tjjs ), aimag( tjjs ), cr, ci )
661 xjtmp =
cmplx( cr, ci )
663 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
667 ELSE IF( tjj.GT.zero )
THEN
671 IF( xj.GT.tjj*bignum )
THEN
676 rec = ( tjj*bignum ) / xj
677 IF( cnorm( j ).GT.one )
THEN
682 rec = rec / cnorm( j )
684 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
687 xmax( 1 ) = xmax( 1 )*rec
691 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
692 $ real( tjjs ), aimag( tjjs ), cr, ci )
693 xjtmp =
cmplx( cr, ci )
695 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
704 CALL pclaset(
' ', n, 1, czero, czero, x, ix, jx,
706 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
722 IF( cnorm( j ).GT.( bignum-xmax( 1 ) )*rec )
THEN
727 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
731 ELSE IF( xj*cnorm( j ).GT.( bignum-xmax( 1 ) ) )
THEN
735 CALL pcsscal( n, half, x, ix, jx, descx, 1 )
747 CALL pcaxpy( j-1, zdum, a, ia, ja+j-1, desca, 1, x,
749 CALL pcamax( j-1, zdum, imax, x, ix, jx, descx, 1 )
750 xmax( 1 ) = cabs1( zdum )
751 CALL sgsum2d( contxt,
'Row',
' ', 1, 1, xmax, 1,
761 CALL pcaxpy( n-j, zdum, a, ia+j, ja+j-1, desca, 1,
762 $ x, ix+j, jx, descx, 1 )
763 CALL pcamax( n-j, zdum, i, x, ix+j, jx, descx, 1 )
764 xmax( 1 ) = cabs1( zdum )
765 CALL sgsum2d( contxt,
'Row',
' ', 1, 1, xmax, 1,
771 ELSE IF( lsame( trans,
'T' ) )
THEN
775 DO 120 j = jfirst, jlast, jinc
781 CALL infog2l( ix+j-1, jx, descx, nprow, npcol, myrow,
782 $ mycol, irowx, icolx, itmp1x, itmp2x )
783 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
THEN
785 CALL cgebs2d( contxt,
'All',
' ', 1, 1, xjtmp, 1 )
787 CALL cgebr2d( contxt,
'All',
' ', 1, 1, xjtmp, 1,
791 uscal =
cmplx( tscal )
792 rec = one /
max( xmax( 1 ), one )
793 IF( cnorm( j ).GT.( bignum-xj )*rec )
THEN
800 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
801 $ myrow, mycol, irow, icol, itmp1,
803 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
805 tjjs = a( ( icol-1 )*lda+irow )*tscal
806 CALL cgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
809 CALL cgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
816 IF( tjj.GT.one )
THEN
820 rec =
min( one, rec*tjj )
821 CALL sladiv( real( uscal ), aimag( uscal ),
822 $ real( tjjs ), aimag( tjjs ), cr, ci )
823 uscal =
cmplx( cr, ci )
825 IF( rec.LT.one )
THEN
826 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
829 xmax( 1 ) = xmax( 1 )*rec
834 IF( uscal.EQ.cone )
THEN
840 CALL pcdotu( j-1, csumj, a, ia, ja+j-1, desca, 1,
841 $ x, ix, jx, descx, 1 )
842 ELSE IF( j.LT.n )
THEN
843 CALL pcdotu( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
844 $ x, ix+j, jx, descx, 1 )
846 IF( mycol.EQ.itmp2x )
THEN
847 CALL cgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
849 CALL cgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
861 zdum = conjg( uscal )
862 CALL pcscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
863 CALL pcdotu( j-1, csumj, a, ia, ja+j-1, desca, 1,
864 $ x, ix, jx, descx, 1 )
865 CALL sladiv( real( zdum ), aimag( zdum ),
866 $ real( uscal ), aimag( uscal ), cr, ci)
867 zdum =
cmplx( cr, ci )
868 CALL pcscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
869 ELSE IF( j.LT.n )
THEN
873 zdum = conjg( uscal )
874 CALL pcscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
875 CALL pcdotu( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
876 $ x, ix+j, jx, descx, 1 )
877 CALL sladiv( real( zdum ), aimag( zdum ),
878 $ real( uscal ), aimag( uscal ), cr, ci)
879 zdum =
cmplx( cr, ci )
880 CALL pcscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
882 IF( mycol.EQ.itmp2x )
THEN
883 CALL cgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
885 CALL cgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
890 IF( uscal.EQ.
cmplx( tscal ) )
THEN
897 xjtmp = xjtmp - csumj
903 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
904 $ myrow, mycol, irow, icol, itmp1,
906 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
908 tjjs = a( ( icol-1 )*lda+irow )*tscal
909 CALL cgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
912 CALL cgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
924 IF( tjj.GT.smlnum )
THEN
928 IF( tjj.LT.one )
THEN
929 IF( xj.GT.tjj*bignum )
THEN
934 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
937 xmax( 1 ) = xmax( 1 )*rec
941 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
942 $ real( tjjs ), aimag( tjjs ), cr, ci )
943 xjtmp =
cmplx( cr, ci )
944 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
948 ELSE IF( tjj.GT.zero )
THEN
952 IF( xj.GT.tjj*bignum )
THEN
956 rec = ( tjj*bignum ) / xj
957 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
960 xmax( 1 ) = xmax( 1 )*rec
963 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
964 $ real( tjjs ), aimag( tjjs ), cr, ci )
965 xjtmp =
cmplx( cr, ci )
966 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
975 CALL pclaset(
' ', n, 1, czero, czero, x, ix, jx,
977 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
992 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
993 $ real( tjjs ), aimag( tjjs ), cr, ci )
994 xjtmp =
cmplx( cr, ci )
995 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1000 xmax( 1 ) =
max( xmax( 1 ), cabs1( xjtmp ) )
1007 DO 140 j = jfirst, jlast, jinc
1012 CALL infog2l( ix+j-1, jx, descx, nprow, npcol, myrow,
1013 $ mycol, irowx, icolx, itmp1x, itmp2x )
1014 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
THEN
1016 CALL cgebs2d( contxt,
'All',
' ', 1, 1, xjtmp, 1 )
1018 CALL cgebr2d( contxt,
'All',
' ', 1, 1, xjtmp, 1,
1023 rec = one /
max( xmax( 1 ), one )
1024 IF( cnorm( j ).GT.( bignum-xj )*rec )
THEN
1031 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
1032 $ myrow, mycol, irow, icol, itmp1,
1034 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
1036 tjjs = conjg( a( ( icol-1 )*lda+irow ) )*tscal
1037 CALL cgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
1040 CALL cgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
1047 IF( tjj.GT.one )
THEN
1051 rec =
min( one, rec*tjj )
1052 CALL sladiv( real( uscal ), aimag( uscal ),
1053 $ real( tjjs ), aimag( tjjs ), cr, ci )
1054 uscal =
cmplx( cr, ci )
1056 IF( rec.LT.one )
THEN
1057 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
1060 xmax( 1 ) = xmax( 1 )*rec
1065 IF( uscal.EQ.cone )
THEN
1071 CALL pcdotc( j-1, csumj, a, ia, ja+j-1, desca, 1,
1072 $ x, ix, jx, descx, 1 )
1073 ELSE IF( j.LT.n )
THEN
1074 CALL pcdotc( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
1075 $ x, ix+j, jx, descx, 1 )
1077 IF( mycol.EQ.itmp2x )
THEN
1078 CALL cgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
1080 CALL cgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
1093 zdum = conjg( uscal )
1094 CALL pcscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
1095 CALL pcdotc( j-1, csumj, a, ia, ja+j-1, desca, 1,
1096 $ x, ix, jx, descx, 1 )
1097 CALL sladiv( one, zero,
1098 $ real( zdum ), aimag( zdum ), cr, ci )
1099 zdum =
cmplx( cr, ci )
1100 CALL pcscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
1101 ELSE IF( j.LT.n )
THEN
1106 zdum = conjg( uscal )
1107 CALL pcscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
1108 CALL pcdotc( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
1109 $ x, ix+j, jx, descx, 1 )
1110 CALL sladiv( one, zero,
1111 $ real( zdum ), aimag( zdum ), cr, ci )
1112 zdum =
cmplx( cr, ci )
1113 CALL pcscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
1115 IF( mycol.EQ.itmp2x )
THEN
1116 CALL cgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
1118 CALL cgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
1123 IF( uscal.EQ.
cmplx( tscal ) )
THEN
1130 xjtmp = xjtmp - csumj
1136 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
1137 $ myrow, mycol, irow, icol, itmp1,
1139 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
1141 tjjs = conjg( a( ( icol-1 )*lda+irow ) )*tscal
1142 CALL cgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
1145 CALL cgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
1157 IF( tjj.GT.smlnum )
THEN
1161 IF( tjj.LT.one )
THEN
1162 IF( xj.GT.tjj*bignum )
THEN
1167 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
1170 xmax( 1 ) = xmax( 1 )*rec
1174 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
1175 $ real( tjjs ), aimag( tjjs ), cr, ci )
1176 xjtmp =
cmplx( cr, ci )
1177 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1178 $ x( irowx ) = xjtmp
1179 ELSE IF( tjj.GT.zero )
THEN
1183 IF( xj.GT.tjj*bignum )
THEN
1187 rec = ( tjj*bignum ) / xj
1188 CALL pcsscal( n, rec, x, ix, jx, descx, 1 )
1191 xmax( 1 ) = xmax( 1 )*rec
1194 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
1195 $ real( tjjs ), aimag( tjjs ), cr, ci )
1196 xjtmp =
cmplx( cr, ci )
1197 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1198 $ x( irowx ) = xjtmp
1204 CALL pclaset(
' ', n, 1, czero, czero, x, ix, jx,
1206 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1219 CALL sladiv( real( xjtmp ), aimag( xjtmp ),
1220 $ real( tjjs ), aimag( tjjs ), cr, ci )
1221 xjtmp =
cmplx( cr, ci )
1222 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1223 $ x( irowx ) = xjtmp
1225 xmax( 1 ) =
max( xmax( 1 ), cabs1( xjtmp ) )
1228 scale = scale / tscal
1233 IF( tscal.NE.one )
THEN
1234 CALL sscal( n, one / tscal, cnorm, 1 )