1 SUBROUTINE pzlattrs( 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
12 DOUBLE PRECISION SCALE
15 INTEGER DESCA( * ), DESCX( * )
16 DOUBLE PRECISION CNORM( * )
17 COMPLEX*16 A( * ), X( * )
255 DOUBLE PRECISION ZERO, HALF, ONE, TWO
256 parameter( zero = 0.0d+0, half = 0.5d+0, one = 1.0d+0,
258 COMPLEX*16 CZERO, CONE
259 parameter( czero = ( 0.0d+0, 0.0d+0 ),
260 $ cone = ( 1.0d+0, 0.0d+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 DOUBLE PRECISION BIGNUM, GROW, REC, SMLNUM, TJJ, TMAX, TSCAL,
275 COMPLEX*16 CSUMJ, TJJS, USCAL, XJTMP, ZDUM
280 DOUBLE PRECISION PDLAMCH
282 EXTERNAL lsame, idamax, pdlamch, zladiv
285 EXTERNAL blacs_gridinfo, dgsum2d, dscal,
infog2l,
287 $ pzdotc, pzdotu, pzdscal,
pzlaset, pzscal,
288 $ pztrsv, zgebr2d, zgebs2d
291 INTRINSIC abs, dble, dcmplx, dconjg, dimag,
max,
min
294 DOUBLE PRECISION CABS1, CABS2
297 cabs1( zdum ) = abs( dble( zdum ) ) + abs( dimag( zdum ) )
298 cabs2( zdum ) = abs( dble( zdum ) / 2.d0 ) +
299 $ abs( dimag( zdum ) / 2.d0 )
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,
'PZLATTRS', -info )
346 smlnum = pdlamch( contxt,
'Safe minimum' )
347 bignum = one / smlnum
348 CALL pdlabad( contxt, smlnum, bignum )
349 smlnum = smlnum / pdlamch( contxt,
'Precision' )
350 bignum = one / smlnum
354 IF( lsame( normin,
'N' ) )
THEN
364 CALL pdzasum( j-1, cnorm( j ), a, ia, ja+j-1, desca, 1 )
371 CALL pdzasum( n-j, cnorm( j ), a, ia+j, ja+j-1, desca,
376 CALL dgsum2d( contxt,
'Row',
' ', n, 1, cnorm, 1, -1, -1 )
382 imax = idamax( n, cnorm, 1 )
384 IF( tmax.LE.bignum*half )
THEN
387 tscal = half / ( smlnum*tmax )
388 CALL dscal( n, tscal, cnorm, 1 )
395 CALL pzamax( n, zdum, imax, x, ix, jx, descx, 1 )
397 CALL dgsum2d( 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 zgebs2d( contxt,
'All',
' ', 1, 1, tjjs, 1 )
442 CALL zgebr2d( 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 zgebs2d( contxt,
'All',
' ', 1, 1, tjjs, 1 )
540 CALL zgebr2d( 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 pztrsv( uplo, trans, diag, n, a, ia, ja, desca, x, ix, jx,
593 IF( xmax.GT.bignum*half )
THEN
598 scale = ( bignum*half ) / xmax
599 CALL pzdscal( n, scale, x, ix, jx, descx, 1 )
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 zgebs2d( contxt,
'All',
' ', 1, 1, xjtmp, 1 )
620 CALL zgebr2d( 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 zgebs2d( contxt,
'All',
' ', 1, 1, tjjs, 1 )
632 CALL zgebr2d( 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 pzdscal( n, rec, x, ix, jx, descx, 1 )
659 xjtmp = zladiv( xjtmp, tjjs )
661 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
665 ELSE IF( tjj.GT.zero )
THEN
669 IF( xj.GT.tjj*bignum )
THEN
674 rec = ( tjj*bignum ) / xj
675 IF( cnorm( j ).GT.one )
THEN
680 rec = rec / cnorm( j )
682 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
689 xjtmp = zladiv( xjtmp, tjjs )
691 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
700 CALL pzlaset(
' ', n, 1, czero, czero, x, ix, jx,
702 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
718 IF( cnorm( j ).GT.( bignum-xmax )*rec )
THEN
723 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
727 ELSE IF( xj*cnorm( j ).GT.( bignum-xmax ) )
THEN
731 CALL pzdscal( n, half, x, ix, jx, descx, 1 )
743 CALL pzaxpy( j-1, zdum, a, ia, ja+j-1, desca, 1, x,
745 CALL pzamax( j-1, zdum, imax, x, ix, jx, descx, 1 )
747 CALL dgsum2d( contxt,
'Row',
' ', 1, 1, xmax, 1,
757 CALL pzaxpy( n-j, zdum, a, ia+j, ja+j-1, desca, 1,
758 $ x, ix+j, jx, descx, 1 )
759 CALL pzamax( n-j, zdum, i, x, ix+j, jx, descx, 1 )
761 CALL dgsum2d( contxt,
'Row',
' ', 1, 1, xmax, 1,
767 ELSE IF( lsame( trans,
'T' ) )
THEN
771 DO 120 j = jfirst, jlast, jinc
777 CALL infog2l( ix+j-1, jx, descx, nprow, npcol, myrow,
778 $ mycol, irowx, icolx, itmp1x, itmp2x )
779 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
THEN
781 CALL zgebs2d( contxt,
'All',
' ', 1, 1, xjtmp, 1 )
783 CALL zgebr2d( contxt,
'All',
' ', 1, 1, xjtmp, 1,
787 uscal = dcmplx( tscal )
788 rec = one /
max( xmax, one )
789 IF( cnorm( j ).GT.( bignum-xj )*rec )
THEN
796 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
797 $ myrow, mycol, irow, icol, itmp1,
799 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
801 tjjs = a( ( icol-1 )*lda+irow )*tscal
802 CALL zgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
805 CALL zgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
812 IF( tjj.GT.one )
THEN
816 rec =
min( one, rec*tjj )
817 uscal = zladiv( uscal, tjjs )
819 IF( rec.LT.one )
THEN
820 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
828 IF( uscal.EQ.cone )
THEN
834 CALL pzdotu( j-1, csumj, a, ia, ja+j-1, desca, 1,
835 $ x, ix, jx, descx, 1 )
836 ELSE IF( j.LT.n )
THEN
837 CALL pzdotu( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
838 $ x, ix+j, jx, descx, 1 )
840 IF( mycol.EQ.itmp2x )
THEN
841 CALL zgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
843 CALL zgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
855 zdum = dconjg( uscal )
856 CALL pzscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
857 CALL pzdotu( j-1, csumj, a, ia, ja+j-1, desca, 1,
858 $ x, ix, jx, descx, 1 )
859 zdum = zladiv( zdum, uscal )
860 CALL pzscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
861 ELSE IF( j.LT.n )
THEN
865 zdum = dconjg( uscal )
866 CALL pzscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
867 CALL pzdotu( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
868 $ x, ix+j, jx, descx, 1 )
869 zdum = zladiv( zdum, uscal )
870 CALL pzscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
872 IF( mycol.EQ.itmp2x )
THEN
873 CALL zgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
875 CALL zgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
880 IF( uscal.EQ.dcmplx( tscal ) )
THEN
887 xjtmp = xjtmp - csumj
893 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
894 $ myrow, mycol, irow, icol, itmp1,
896 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
898 tjjs = a( ( icol-1 )*lda+irow )*tscal
899 CALL zgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
902 CALL zgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
914 IF( tjj.GT.smlnum )
THEN
918 IF( tjj.LT.one )
THEN
919 IF( xj.GT.tjj*bignum )
THEN
924 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
931 xjtmp = zladiv( xjtmp, tjjs )
932 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
936 ELSE IF( tjj.GT.zero )
THEN
940 IF( xj.GT.tjj*bignum )
THEN
944 rec = ( tjj*bignum ) / xj
945 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
951 xjtmp = zladiv( xjtmp, tjjs )
952 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
961 CALL pzlaset(
' ', n, 1, czero, czero, x, ix, jx,
963 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
978 xjtmp = zladiv( xjtmp, tjjs ) - csumj
979 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
984 xmax =
max( xmax, cabs1( xjtmp ) )
991 DO 140 j = jfirst, jlast, jinc
996 CALL infog2l( ix+j-1, jx, descx, nprow, npcol, myrow,
997 $ mycol, irowx, icolx, itmp1x, itmp2x )
998 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
THEN
1000 CALL zgebs2d( contxt,
'All',
' ', 1, 1, xjtmp, 1 )
1002 CALL zgebr2d( contxt,
'All',
' ', 1, 1, xjtmp, 1,
1007 rec = one /
max( xmax, one )
1008 IF( cnorm( j ).GT.( bignum-xj )*rec )
THEN
1015 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
1016 $ myrow, mycol, irow, icol, itmp1,
1018 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
1020 tjjs = dconjg( a( ( icol-1 )*lda+irow ) )*tscal
1021 CALL zgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
1024 CALL zgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
1031 IF( tjj.GT.one )
THEN
1035 rec =
min( one, rec*tjj )
1036 uscal = zladiv( uscal, tjjs )
1038 IF( rec.LT.one )
THEN
1039 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
1047 IF( uscal.EQ.cone )
THEN
1053 CALL pzdotc( j-1, csumj, a, ia, ja+j-1, desca, 1,
1054 $ x, ix, jx, descx, 1 )
1055 ELSE IF( j.LT.n )
THEN
1056 CALL pzdotc( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
1057 $ x, ix+j, jx, descx, 1 )
1059 IF( mycol.EQ.itmp2x )
THEN
1060 CALL zgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
1062 CALL zgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
1075 zdum = dconjg( uscal )
1076 CALL pzscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
1077 CALL pzdotc( j-1, csumj, a, ia, ja+j-1, desca, 1,
1078 $ x, ix, jx, descx, 1 )
1079 zdum = zladiv( cone, zdum )
1080 CALL pzscal( j-1, zdum, a, ia, ja+j-1, desca, 1 )
1081 ELSE IF( j.LT.n )
THEN
1086 zdum = dconjg( uscal )
1087 CALL pzscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
1088 CALL pzdotc( n-j, csumj, a, ia+j, ja+j-1, desca, 1,
1089 $ x, ix+j, jx, descx, 1 )
1090 zdum = zladiv( cone, zdum )
1091 CALL pzscal( n-j, zdum, a, ia+j, ja+j-1, desca, 1 )
1093 IF( mycol.EQ.itmp2x )
THEN
1094 CALL zgebs2d( contxt,
'Row',
' ', 1, 1, csumj, 1 )
1096 CALL zgebr2d( contxt,
'Row',
' ', 1, 1, csumj, 1,
1101 IF( uscal.EQ.dcmplx( tscal ) )
THEN
1108 xjtmp = xjtmp - csumj
1114 CALL infog2l( ia+j-1, ja+j-1, desca, nprow, npcol,
1115 $ myrow, mycol, irow, icol, itmp1,
1117 IF( ( myrow.EQ.itmp1 ) .AND. ( mycol.EQ.itmp2 ) )
1119 tjjs = dconjg( a( ( icol-1 )*lda+irow ) )*tscal
1120 CALL zgebs2d( contxt,
'All',
' ', 1, 1, tjjs,
1123 CALL zgebr2d( contxt,
'All',
' ', 1, 1, tjjs, 1,
1135 IF( tjj.GT.smlnum )
THEN
1139 IF( tjj.LT.one )
THEN
1140 IF( xj.GT.tjj*bignum )
THEN
1145 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
1152 xjtmp = zladiv( xjtmp, tjjs )
1153 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1154 $ x( irowx ) = xjtmp
1155 ELSE IF( tjj.GT.zero )
THEN
1159 IF( xj.GT.tjj*bignum )
THEN
1163 rec = ( tjj*bignum ) / xj
1164 CALL pzdscal( n, rec, x, ix, jx, descx, 1 )
1170 xjtmp = zladiv( xjtmp, tjjs )
1171 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1172 $ x( irowx ) = xjtmp
1178 CALL pzlaset(
' ', n, 1, czero, czero, x, ix, jx,
1180 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1193 xjtmp = zladiv( xjtmp, tjjs ) - csumj
1194 IF( ( myrow.EQ.itmp1x ) .AND. ( mycol.EQ.itmp2x ) )
1195 $ x( irowx ) = xjtmp
1197 xmax =
max( xmax, cabs1( xjtmp ) )
1200 scale = scale / tscal
1205 IF( tscal.NE.one )
THEN
1206 CALL dscal( n, one / tscal, cnorm, 1 )