1      SUBROUTINE pzgerfs( TRANS, N, NRHS, A, IA, JA, DESCA, AF, IAF,
 
    2     $                    JAF, DESCAF, IPIV, B, IB, JB, DESCB, X, IX,
 
    3     $                    JX, DESCX, FERR, BERR, WORK, LWORK, RWORK,
 
   13      INTEGER            IA, IAF, IB, IX, INFO, JA, JAF, JB, JX,
 
   14     $                   LRWORK, LWORK, N, NRHS
 
   17      INTEGER            DESCA( * ), DESCAF( * ), DESCB( * ),
 
   18     $                   DESCX( * ),  IPIV( * )
 
   19      DOUBLE PRECISION   BERR( * ), FERR( * ), RWORK( * )
 
   20      COMPLEX*16         A( * ), AF( * ), B( * ), WORK( * ), X( * )
 
  260      INTEGER            BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
 
  261     $                   LLD_, MB_, M_, NB_, N_, RSRC_
 
  262      PARAMETER          ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
 
  263     $                     ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
 
  264     $                     rsrc_ = 7, csrc_ = 8, lld_ = 9 )
 
  266      PARAMETER          ( ITMAX = 5 )
 
  267      double precision   zero, rone, two, three
 
  268      parameter( zero = 0.0d+0, rone = 1.0d+0, two = 2.0d+0,
 
  271      parameter( one = ( 1.0d+0, 0.0d+0 ) )
 
  274      LOGICAL            LQUERY, NOTRAN
 
  275      CHARACTER          TRANSN, TRANST
 
  276      INTEGER            COUNT, IACOL, IAFCOL, IAFROW, IAROW, IXBCOL,
 
  277     $                   ixbrow, ixcol, ixrow, icoffa, icoffaf, icoffb,
 
  278     $                   icoffx, ictxt, icurcol, idum, ii, iixb, iiw,
 
  279     $                   ioffxb, ipb, ipr, ipv, iroffa, iroffaf, iroffb,
 
  280     $                   iroffx, iw, j, jbrhs, jj, jjfbe, jjxb, jn, jw,
 
  281     $                   k, kase, ldxb, lrwmin, lwmin, mycol, myrhs,
 
  282     $                   myrow, np, np0, npcol, npmod, nprow, nz
 
  283      DOUBLE PRECISION   EPS, EST, LSTRES, S, SAFE1, SAFE2, SAFMIN
 
  287      INTEGER            DESCW( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
 
  291      INTEGER            ICEIL, INDXG2P, NUMROC
 
  292      DOUBLE PRECISION   PDLAMCH
 
  293      EXTERNAL           iceil, indxg2p, lsame, numroc, pdlamch
 
  302      INTRINSIC          abs, dble, dcmplx, dimag, ichar, 
max, 
min, mod
 
  305      DOUBLE PRECISION   CABS1
 
  308      cabs1( zdum ) = abs( dble( zdum ) ) + abs( dimag( zdum ) )
 
  314      ictxt = desca( ctxt_ )
 
  315      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
 
  319      notran = lsame( trans, 
'N' )
 
  322      IF( nprow.EQ.-1 ) 
THEN 
  325         CALL chk1mat( n, 2, n, 2, ia, ja, desca, 7, info )
 
  326         CALL chk1mat( n, 2, n, 2, iaf, jaf, descaf, 11, info )
 
  327         CALL chk1mat( n, 2, nrhs, 3, ib, jb, descb, 16, info )
 
  328         CALL chk1mat( n, 2, nrhs, 3, ix, jx, descx, 20, info )
 
  330            iroffa = mod( ia-1, desca( mb_ ) )
 
  331            icoffa = mod( ja-1, desca( nb_ ) )
 
  332            iroffaf = mod( iaf-1, descaf( mb_ ) )
 
  333            icoffaf = mod( jaf-1, descaf( nb_ ) )
 
  334            iroffb = mod( ib-1, descb( mb_ ) )
 
  335            icoffb = mod( jb-1, descb( nb_ ) )
 
  336            iroffx = mod( ix-1, descx( mb_ ) )
 
  337            icoffx = mod( jx-1, descx( nb_ ) )
 
  338            iarow = indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
 
  340            iafcol = indxg2p( jaf, descaf( nb_ ), mycol,
 
  341     $                        descaf( csrc_ ), npcol )
 
  342            iafrow = indxg2p( iaf, descaf( mb_ ), myrow,
 
  343     $                        descaf( rsrc_ ), nprow )
 
  344            iacol = indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
 
  346            CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol,
 
  347     $                    iixb, jjxb, ixbrow, ixbcol )
 
  348            ixrow = indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
 
  350            ixcol = indxg2p( jx, descx( nb_ ), mycol, descx( csrc_ ),
 
  352            npmod = numroc( n+iroffa, desca( mb_ ), myrow, iarow,
 
  356            work( 1 ) = dcmplx( dble( lwmin ) )
 
  357            rwork( 1 ) = dble( lrwmin )
 
  358            lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
 
  360            IF( ( .NOT.notran ) .AND. ( .NOT.lsame( trans, 
'T' ) ) .AND.
 
  361     $          ( .NOT.lsame( trans, 
'C' ) ) ) 
THEN 
  363            ELSE IF( n.LT.0 ) 
THEN 
  365            ELSE IF( nrhs.LT.0 ) 
THEN 
  367            ELSE IF( iroffa.NE.0 ) 
THEN 
  369            ELSE IF( icoffa.NE.0 ) 
THEN 
  371            ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) 
THEN 
  372               info = -( 700 + nb_ )
 
  373            ELSE IF( desca( mb_ ).NE.descaf( mb_ ) ) 
THEN 
  374               info = -( 1100 + mb_ )
 
  375            ELSE IF( iroffaf.NE.0 .OR. iarow.NE.iafrow ) 
THEN 
  377            ELSE IF( desca( nb_ ).NE.descaf( nb_ ) ) 
THEN 
  378               info = -( 1100 + nb_ )
 
  379            ELSE IF( icoffaf.NE.0 .OR. iacol.NE.iafcol ) 
THEN 
  381            ELSE IF( ictxt.NE.descaf( ctxt_ ) ) 
THEN 
  382               info = -( 1100 + ctxt_ )
 
  383            ELSE IF( iroffa.NE.iroffb .OR. iarow.NE.ixbrow ) 
THEN 
  385            ELSE IF( desca( mb_ ).NE.descb( mb_ ) ) 
THEN 
  386               info = -( 1600 + mb_ )
 
  387            ELSE IF( ictxt.NE.descb( ctxt_ ) ) 
THEN 
  388               info = -( 1600 + ctxt_ )
 
  389            ELSE IF( descb( mb_ ).NE.descx( mb_ ) ) 
THEN 
  390               info = -( 2000 + mb_ )
 
  391            ELSE IF( iroffx.NE.0 .OR. ixbrow.NE.ixrow ) 
THEN 
  393            ELSE IF( descb( nb_ ).NE.descx( nb_ ) ) 
THEN 
  394               info = -( 2000 + nb_ )
 
  395            ELSE IF( icoffb.NE.icoffx .OR. ixbcol.NE.ixcol ) 
THEN 
  397            ELSE IF( ictxt.NE.descx( ctxt_ ) ) 
THEN 
  398               info = -( 2000 + ctxt_ )
 
  399            ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) 
THEN 
  401            ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery ) 
THEN 
  407            idum1( 1 ) = ichar( 
'N' )
 
  408         ELSE IF( lsame( trans, 
'T' ) ) 
THEN 
  409            idum1( 1 ) = ichar( 
'T' )
 
  411            idum1( 1 ) = ichar( 
'C' )
 
  418         IF( lwork.EQ.-1 ) 
THEN 
  424         IF( lrwork.EQ.-1 ) 
THEN 
  430         CALL pchk2mat( n, 2, n, 2, ia, ja, desca, 7, n, 2, n, 2, iaf,
 
  431     $                  jaf, descaf, 11, 5, idum1, idum2, info )
 
  432         CALL pchk2mat( n, 2, nrhs, 3, ib, jb, descb, 16, n, 2, nrhs, 3,
 
  433     $                  ix, jx, descx, 20, 5, idum1, idum2, info )
 
  436         CALL pxerbla( ictxt, 
'PZGERFS', -info )
 
  438      ELSE IF( lquery ) 
THEN 
  443      myrhs = numroc( jb+nrhs-1, descb( nb_ ), mycol, descb( csrc_ ),
 
  448      IF( n.LE.1 .OR. nrhs.EQ.0 ) 
THEN 
  449         DO 10 jj = jjfbe, myrhs
 
  464      np0 = numroc( n+iroffb, descb( mb_ ), myrow, ixbrow, nprow )
 
  465      CALL descset( descw, n+iroffb, 1, desca( mb_ ), 1, ixbrow, ixbcol,
 
  466     $              ictxt, 
max( 1, np0 ) )
 
  470      IF( myrow.EQ.ixbrow ) 
THEN 
  480      ioffxb = ( jjxb-1 )*ldxb
 
  485      eps = pdlamch( ictxt, 
'Epsilon' )
 
  486      safmin = pdlamch( ictxt, 
'Safe minimum' )
 
  489      jn = 
min( iceil( jb, descb( nb_ ) ) * descb( nb_ ), jb+nrhs-1 )
 
  494      DO 100 k = 0, jbrhs-1
 
  506         CALL pzcopy( n, b, ib, jb+k, descb, 1, work( ipr ), iw, jw,
 
  508         CALL pzgemv( trans, n, n, -one, a, ia, ja, desca, x, ix,
 
  509     $                jx+k, descx, 1, one, work( ipr ), iw, jw,
 
  522         IF( mycol.EQ.ixbcol ) 
THEN 
  524               DO 30 ii = iixb, iixb + np - 1
 
  525                  rwork( iiw+ii-iixb ) = cabs1( b( ii+ioffxb ) )
 
  530         CALL pzagemv( trans, n, n, rone, a, ia, ja, desca, x, ix, jx+k,
 
  531     $                 descx, 1, rone, rwork( ipb ), iw, jw, descw, 1 )
 
  534         IF( mycol.EQ.ixbcol ) 
THEN 
  536               DO 40 ii = iiw-1, iiw+np-2
 
  537                  IF( rwork( ipb+ii ).GT.safe2 ) 
THEN 
  538                     s = 
max( s, cabs1( work( ipr+ii ) ) /
 
  541                     s = 
max( s, ( cabs1( work( ipr+ii ) )+safe1 ) /
 
  542     $                           ( rwork( ipb+ii )+safe1 ) )
 
  548         CALL dgamx2d( ictxt, 
'All', 
' ', 1, 1, s, 1, idum, idum, 1,
 
  550         IF( mycol.EQ.ixbcol )
 
  560         IF( s.GT.eps .AND. two*s.LE.lstres .AND. count.LE.itmax ) 
THEN 
  564            CALL pzgetrs( trans, n, 1, af, iaf, jaf, descaf, ipiv,
 
  565     $                    work( ipr ), iw, jw, descw, info )
 
  566            CALL pzaxpy( n, one, work( ipr ), iw, jw, descw, 1, x, ix,
 
  599         IF( mycol.EQ.ixbcol ) 
THEN 
  601               DO 50 ii = iiw-1, iiw+np-2
 
  602                  IF( rwork( ipb+ii ).GT.safe2 ) 
THEN 
  603                     rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
 
  604     $                                 nz*eps*rwork( ipb+ii )
 
  606                     rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
 
  607     $                                 nz*eps*rwork( ipb+ii ) + safe1
 
  615         IF( mycol.EQ.ixbcol ) 
THEN 
  616            CALL zgebs2d( ictxt, 
'Rowwise', 
' ', np, 1, work( ipr ),
 
  619            CALL zgebr2d( ictxt, 
'Rowwise', 
' ', np, 1, work( ipr ),
 
  620     $                    descw( lld_ ), myrow, ixbcol )
 
  622         descw( csrc_ ) = mycol
 
  623         CALL pzlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
 
  624     $                 iw, jw, descw, est, kase )
 
  625         descw( csrc_ ) = ixbcol
 
  632               CALL pzgetrs( transt, n, 1, af, iaf, jaf, descaf,
 
  633     $                       ipiv, work( ipr ), iw, jw, descw, info )
 
  635               IF( mycol.EQ.ixbcol ) 
THEN 
  637                     DO 70 ii = iiw-1, iiw+np-2
 
  638                        work( ipr+ii ) = rwork( ipb+ii )*work( ipr+ii )
 
  646               IF( mycol.EQ.ixbcol ) 
THEN 
  648                     DO 80 ii = iiw-1, iiw+np-2
 
  649                        work( ipr+ii ) = rwork( ipb+ii )*work( ipr+ii )
 
  654               CALL pzgetrs( transn, n, 1, af, iaf, jaf, descaf,
 
  655     $                       ipiv, work( ipr ), iw, jw, descw, info )
 
  663         IF( mycol.EQ.ixbcol ) 
THEN 
  665               DO 90 ii = iixb, iixb+np-1
 
  666                  lstres = 
max( lstres, cabs1( x( ioffxb+ii ) ) )
 
  669            CALL dgamx2d( ictxt, 
'Column', 
' ', 1, 1, lstres, 1, idum,
 
  670     $                    idum, 1, -1, mycol )
 
  672     $         ferr( jjfbe ) = est / lstres
 
  676            ioffxb = ioffxb + ldxb
 
  682      icurcol = mod( ixbcol+1, npcol )
 
  686      DO 200 j = jn+1, jb+nrhs-1, descb( nb_ )
 
  687         jbrhs = 
min( jb+nrhs-j, descb( nb_ ) )
 
  688         descw( csrc_ ) = icurcol
 
  690         DO 190 k = 0, jbrhs-1
 
  702            CALL pzcopy( n, b, ib, j+k, descb, 1, work( ipr ), iw, jw,
 
  704            CALL pzgemv( trans, n, n, -one, a, ia, ja, desca, x,
 
  705     $                   ix, j+k, descx, 1, one, work( ipr ), iw, jw,
 
  719            IF( mycol.EQ.icurcol ) 
THEN 
  721                  DO 120 ii = iixb, iixb+np-1
 
  722                     rwork( iiw+ii-iixb ) = cabs1( b( ii+ioffxb ) )
 
  727            CALL pzagemv( trans, n, n, rone, a, ia, ja, desca, x, ix,
 
  728     $                    j+k, descx, 1, rone, rwork( ipb ), iw, jw,
 
  732            IF( mycol.EQ.icurcol ) 
THEN 
  734                  DO 130 ii = iiw-1, iiw+np-2
 
  735                     IF( rwork( ipb+ii ).GT.safe2 ) 
THEN 
  736                        s = 
max( s, cabs1( work( ipr+ii ) ) /
 
  739                        s = 
max( s, ( cabs1( work( ipr+ii ) )+safe1 ) /
 
  740     $                              ( rwork( ipb+ii )+safe1 ) )
 
  746            CALL dgamx2d( ictxt, 
'All', 
' ', 1, 1, s, 1, idum, idum, 1,
 
  748            IF( mycol.EQ.icurcol )
 
  758            IF( s.GT.eps .AND. two*s.LE.lstres .AND.
 
  759     $          count.LE.itmax ) 
THEN 
  763               CALL pzgetrs( trans, n, 1, af, iaf, jaf, descaf, ipiv,
 
  764     $                       work( ipr ), iw, jw, descw, info )
 
  765               CALL pzaxpy( n, one, work( ipr ), iw, jw, descw, 1, x,
 
  766     $                      ix, j+k, descx, 1 )
 
  798            IF( mycol.EQ.icurcol ) 
THEN 
  800                  DO 140 ii = iiw-1, iiw+np-2
 
  801                     IF( rwork( ipb+ii ).GT.safe2 ) 
THEN 
  802                        rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
 
  803     $                                    nz*eps*rwork( ipb+ii )
 
  805                        rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
 
  806     $                                    nz*eps*rwork( ipb+ii ) + safe1
 
  814            IF( mycol.EQ.icurcol ) 
THEN 
  815               CALL zgebs2d( ictxt, 
'Rowwise', 
' ', np, 1, work( ipr ),
 
  818               CALL zgebr2d( ictxt, 
'Rowwise', 
' ', np, 1, work( ipr ),
 
  819     $                       descw( lld_ ), myrow, icurcol )
 
  821            descw( csrc_ ) = mycol
 
  822            CALL pzlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
 
  823     $                    iw, jw, descw, est, kase )
 
  824            descw( csrc_ ) = icurcol
 
  831                  CALL pzgetrs( transt, n, 1, af, iaf, jaf, descaf,
 
  832     $                          ipiv, work( ipr ), iw, jw, descw, info )
 
  834                  IF( mycol.EQ.icurcol ) 
THEN 
  836                        DO 160 ii = iiw-1, iiw+np-2
 
  837                           work( ipr+ii ) = rwork( ipb+ii )*
 
  846                  IF( mycol.EQ.icurcol ) 
THEN 
  848                        DO 170 ii = iiw-1, iiw+np-2
 
  849                           work( ipr+ii ) = rwork( ipb+ii )*
 
  855                  CALL pzgetrs( transn, n, 1, af, iaf, jaf, descaf,
 
  856     $                          ipiv, work( ipr ), iw, jw, descw,
 
  865            IF( mycol.EQ.icurcol ) 
THEN 
  867                  DO 180 ii = iixb, iixb+np-1
 
  868                     lstres = 
max( lstres, cabs1( x( ioffxb+ii ) ) )
 
  871               CALL dgamx2d( ictxt, 
'Column', 
' ', 1, 1, lstres,
 
  872     $                       1, idum, idum, 1, -1, mycol )
 
  874     $            ferr( jjfbe ) = est / lstres
 
  878               ioffxb = ioffxb + ldxb
 
  884         icurcol = mod( icurcol+1, npcol )
 
  888      work( 1 ) = dcmplx( dble( lwmin ) )
 
  889      rwork( 1 ) = dble( lrwmin )