Routine: PCGESVX()  File: SRC\pcgesvx.f

 
 
# lines: 830
  # code: 830
  # comment: 0
  # blank:0
# Variables:99
# Callers:0
# Callings:9
# Words:437
# Keywords:287
 

 

..
     .. Array Arguments ..
     ..
  Purpose
  =======
  PCGESVX uses the LU factorization to compute the solution to a
  complex system of linear equations
        A(IA:IA+N-1,JA:JA+N-1) * X = B(IB:IB+N-1,JB:JB+NRHS-1),
  where A(IA:IA+N-1,JA:JA+N-1) is an N-by-N matrix and X and
  B(IB:IB+N-1,JB:JB+NRHS-1) are N-by-NRHS matrices.
  Error bounds on the solution and a condition estimate are also
  provided.
  Notes
  =====
  Each global data object is described by an associated description
  vector.  This vector stores the information required to establish
  the mapping between an object element and its corresponding process
  and memory location.
  Let A be a generic term for any 2D block cyclicly distributed array.
  Such a global array has an associated description vector DESCA.
  In the following comments, the character _ should be read as
  "of the global array".
  NOTATION        STORED IN      EXPLANATION
  --------------- -------------- --------------------------------------
  DTYPE_A(global) DESCA( DTYPE_ )The descriptor type.  In this case,
                                 DTYPE_A = 1.
  CTXT_A (global) DESCA( CTXT_ ) The BLACS context handle, indicating
                                 the BLACS process grid A is distribu-
                                 ted over. The context itself is glo-
                                 bal, but the handle (the integer
                                 value) may vary.
  M_A    (global) DESCA( M_ )    The number of rows in the global
                                 array A.
  N_A    (global) DESCA( N_ )    The number of columns in the global
                                 array A.
  MB_A   (global) DESCA( MB_ )   The blocking factor used to distribute
                                 the rows of the array.
  NB_A   (global) DESCA( NB_ )   The blocking factor used to distribute
                                 the columns of the array.
  RSRC_A (global) DESCA( RSRC_ ) The process row over which the first
                                 row of the array A is distributed.
  CSRC_A (global) DESCA( CSRC_ ) The process column over which the
                                 first column of the array A is
                                 distributed.
  LLD_A  (local)  DESCA( LLD_ )  The leading dimension of the local
                                 array.  LLD_A >= MAX(1,LOCr(M_A)).
  Let K be the number of rows or columns of a distributed matrix,
  and assume that its process grid has dimension p x q.
  LOCr( K ) denotes the number of elements of K that a process
  would receive if K were distributed over the p processes of its
  process column.
  Similarly, LOCc( K ) denotes the number of elements of K that a
  process would receive if K were distributed over the q processes of
  its process row.
  The values of LOCr() and LOCc() may be determined via a call to the
  ScaLAPACK tool function, NUMROC:
          LOCr( M ) = NUMROC( M, MB_A, MYROW, RSRC_A, NPROW ),
          LOCc( N ) = NUMROC( N, NB_A, MYCOL, CSRC_A, NPCOL ).
  An upper bound for these quantities may be computed by:
          LOCr( M ) <= ceil( ceil(M/MB_A)/NPROW )*MB_A
          LOCc( N ) <= ceil( ceil(N/NB_A)/NPCOL )*NB_A
  Description
  ===========
  In the following description, A denotes A(IA:IA+N-1,JA:JA+N-1),
  B denotes B(IB:IB+N-1,JB:JB+NRHS-1) and X denotes
  X(IX:IX+N-1,JX:JX+NRHS-1).
  The following steps are performed:
  1. If FACT = 'E', real scaling factors are computed to equilibrate
     the system:
        TRANS = 'N':  diag(R)*A*diag(C)     *inv(diag(C))*X = diag(R)*B
        TRANS = 'T': (diag(R)*A*diag(C))**T *inv(diag(R))*X = diag(C)*B
        TRANS = 'C': (diag(R)*A*diag(C))**H *inv(diag(R))*X = diag(C)*B
     Whether or not the system will be equilibrated depends on the
     scaling of the matrix A, but if equilibration is used, A is
     overwritten by diag(R)*A*diag(C) and B by diag(R)*B (if TRANS='N')
     or diag(C)*B (if TRANS = 'T' or 'C').
  2. If FACT = 'N' or 'E', the LU decomposition is used to factor the
     matrix A (after equilibration if FACT = 'E') as
        A = P * L * U,
     where P is a permutation matrix, L is a unit lower triangular
     matrix, and U is upper triangular.
  3. The factored form of A is used to estimate the condition number
     of the matrix A.  If the reciprocal of the condition number is
     less than machine precision, steps 4-6 are skipped.
  4. The system of equations is solved for X using the factored form
     of A.
  5. Iterative refinement is applied to improve the computed solution
     matrix and calculate error bounds and backward error estimates
     for it.
  6. If FACT = 'E' and equilibration was used, the matrix X is
     premultiplied by diag(C) (if TRANS = 'N') or diag(R) (if
     TRANS = 'T' or 'C') so that it solves the original system
     before equilibration.
  Arguments
  =========
  FACT    (global input) CHARACTER
          Specifies whether or not the factored form of the matrix
          A(IA:IA+N-1,JA:JA+N-1) is supplied on entry, and if not,
          whether the matrix A(IA:IA+N-1,JA:JA+N-1) should be
          equilibrated before it is factored.
          = 'F':  On entry, AF(IAF:IAF+N-1,JAF:JAF+N-1) and IPIV con-
                  tain the factored form of A(IA:IA+N-1,JA:JA+N-1).
                  If EQUED is not 'N', the matrix
                  A(IA:IA+N-1,JA:JA+N-1) has been equilibrated with
                  scaling factors given by R and C.
                  A(IA:IA+N-1,JA:JA+N-1), AF(IAF:IAF+N-1,JAF:JAF+N-1),
                  and IPIV are not modified.
          = 'N':  The matrix A(IA:IA+N-1,JA:JA+N-1) will be copied to
                  AF(IAF:IAF+N-1,JAF:JAF+N-1) and factored.
          = 'E':  The matrix A(IA:IA+N-1,JA:JA+N-1) will be equili-
                  brated if necessary, then copied to
                  AF(IAF:IAF+N-1,JAF:JAF+N-1) and factored.
  TRANS   (global input) CHARACTER
          Specifies the form of the system of equations:
          = 'N':  A(IA:IA+N-1,JA:JA+N-1) * X(IX:IX+N-1,JX:JX+NRHS-1)
                = B(IB:IB+N-1,JB:JB+NRHS-1)     (No transpose)
          = 'T':  A(IA:IA+N-1,JA:JA+N-1)**T * X(IX:IX+N-1,JX:JX+NRHS-1)
                = B(IB:IB+N-1,JB:JB+NRHS-1)  (Transpose)
          = 'C':  A(IA:IA+N-1,JA:JA+N-1)**H * X(IX:IX+N-1,JX:JX+NRHS-1)
                = B(IB:IB+N-1,JB:JB+NRHS-1)  (Conjugate transpose)
  N       (global input) INTEGER
          The number of rows and columns to be operated on, i.e. the
          order of the distributed submatrix A(IA:IA+N-1,JA:JA+N-1).
          N >= 0.
  NRHS    (global input) INTEGER
          The number of right-hand sides, i.e., the number of columns
          of the distributed submatrices B(IB:IB+N-1,JB:JB+NRHS-1) and
          X(IX:IX+N-1,JX:JX+NRHS-1).  NRHS >= 0.
  A       (local input/local output) COMPLEX pointer into
          the local memory to an array of local dimension
          (LLD_A,LOCc(JA+N-1)).  On entry, the N-by-N matrix
          A(IA:IA+N-1,JA:JA+N-1).  If FACT = 'F' and EQUED is not 'N',
          then A(IA:IA+N-1,JA:JA+N-1) must have been equilibrated by
          the scaling factors in R and/or C.  A(IA:IA+N-1,JA:JA+N-1) is
          not modified if FACT = 'F' or  'N', or if FACT = 'E' and
          EQUED = 'N' on exit.
          On exit, if EQUED .ne. 'N', A(IA:IA+N-1,JA:JA+N-1) is scaled
          as follows:
          EQUED = 'R':  A(IA:IA+N-1,JA:JA+N-1) :=
                                      diag(R) * A(IA:IA+N-1,JA:JA+N-1)
          EQUED = 'C':  A(IA:IA+N-1,JA:JA+N-1) :=
                                      A(IA:IA+N-1,JA:JA+N-1) * diag(C)
          EQUED = 'B':  A(IA:IA+N-1,JA:JA+N-1) :=
                            diag(R) * A(IA:IA+N-1,JA:JA+N-1) * diag(C).
  IA      (global input) INTEGER
          The row index in the global array A indicating the first
          row of sub( A ).
  JA      (global input) INTEGER
          The column index in the global array A indicating the
          first column of sub( A ).
  DESCA   (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix A.
  AF      (local input or local output) COMPLEX pointer
          into the local memory to an array of local dimension
          (LLD_AF,LOCc(JA+N-1)).  If FACT = 'F', then
          AF(IAF:IAF+N-1,JAF:JAF+N-1) is an input argument and on
          entry contains the factors L and U from the factorization
          A(IA:IA+N-1,JA:JA+N-1) = P*L*U as computed by PCGETRF.
          If EQUED .ne. 'N', then AF is the factored form of the
          equilibrated matrix A(IA:IA+N-1,JA:JA+N-1).
          If FACT = 'N', then AF(IAF:IAF+N-1,JAF:JAF+N-1) is an output
          argument and on exit returns the factors L and U from the
          factorization A(IA:IA+N-1,JA:JA+N-1) = P*L*U of the original
          matrix A(IA:IA+N-1,JA:JA+N-1).
          If FACT = 'E', then AF(IAF:IAF+N-1,JAF:JAF+N-1) is an output
          argument and on exit returns the factors L and U from the
          factorization A(IA:IA+N-1,JA:JA+N-1) = P*L*U of the equili-
          brated matrix A(IA:IA+N-1,JA:JA+N-1) (see the description of
          A(IA:IA+N-1,JA:JA+N-1) for the form of the equilibrated
          matrix).
  IAF     (global input) INTEGER
          The row index in the global array AF indicating the first
          row of sub( AF ).
  JAF     (global input) INTEGER
          The column index in the global array AF indicating the
          first column of sub( AF ).
  DESCAF  (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix AF.
  IPIV    (local input or local output) INTEGER array, dimension
          LOCr(M_A)+MB_A. If FACT = 'F', then IPIV is an input argu-
          ment and on entry contains the pivot indices from the fac-
          torization A(IA:IA+N-1,JA:JA+N-1) = P*L*U as computed by
          PCGETRF; IPIV(i) -> The global row local row i was
          swapped with.  This array must be aligned with
          A( IA:IA+N-1, * ).
          If FACT = 'N', then IPIV is an output argument and on exit
          contains the pivot indices from the factorization
          A(IA:IA+N-1,JA:JA+N-1) = P*L*U of the original matrix
          A(IA:IA+N-1,JA:JA+N-1).
          If FACT = 'E', then IPIV is an output argument and on exit
          contains the pivot indices from the factorization
          A(IA:IA+N-1,JA:JA+N-1) = P*L*U of the equilibrated matrix
          A(IA:IA+N-1,JA:JA+N-1).
  EQUED   (global input or global output) CHARACTER
          Specifies the form of equilibration that was done.
          = 'N':  No equilibration (always true if FACT = 'N').
          = 'R':  Row equilibration, i.e., A(IA:IA+N-1,JA:JA+N-1) has
                  been premultiplied by diag(R).
          = 'C':  Column equilibration, i.e., A(IA:IA+N-1,JA:JA+N-1)
                  has been postmultiplied by diag(C).
          = 'B':  Both row and column equilibration, i.e.,
                  A(IA:IA+N-1,JA:JA+N-1) has been replaced by
                  diag(R) * A(IA:IA+N-1,JA:JA+N-1) * diag(C).
          EQUED is an input variable if FACT = 'F'; otherwise, it is an
          output variable.
  R       (local input or local output) REAL array,
                                                  dimension LOCr(M_A).
          The row scale factors for A(IA:IA+N-1,JA:JA+N-1).
          If EQUED = 'R' or 'B', A(IA:IA+N-1,JA:JA+N-1) is multiplied
          on the left by diag(R); if EQUED='N' or 'C', R is not acces-
          sed.  R is an input variable if FACT = 'F'; otherwise, R is
          an output variable.
          If FACT = 'F' and EQUED = 'R' or 'B', each element of R must
          be positive.
          R is replicated in every process column, and is aligned
          with the distributed matrix A.
  C       (local input or local output) REAL array,
                                                  dimension LOCc(N_A).
          The column scale factors for A(IA:IA+N-1,JA:JA+N-1).
          If EQUED = 'C' or 'B', A(IA:IA+N-1,JA:JA+N-1) is multiplied
          on the right by diag(C); if EQUED = 'N' or 'R', C is not
          accessed.  C is an input variable if FACT = 'F'; otherwise,
          C is an output variable.  If FACT = 'F' and EQUED = 'C' or
          'B', each element of C must be positive.
          C is replicated in every process row, and is aligned with
          the distributed matrix A.
  B       (local input/local output) COMPLEX pointer
          into the local memory to an array of local dimension
          (LLD_B,LOCc(JB+NRHS-1) ).  On entry, the N-by-NRHS right-hand
          side matrix B(IB:IB+N-1,JB:JB+NRHS-1). On exit, if
          EQUED = 'N', B(IB:IB+N-1,JB:JB+NRHS-1) is not modified; if
          TRANS = 'N' and EQUED = 'R' or 'B', B is overwritten by
          diag(R)*B(IB:IB+N-1,JB:JB+NRHS-1); if TRANS = 'T' or 'C'
          and EQUED = 'C' or 'B', B(IB:IB+N-1,JB:JB+NRHS-1) is over-
          written by diag(C)*B(IB:IB+N-1,JB:JB+NRHS-1).
  IB      (global input) INTEGER
          The row index in the global array B indicating the first
          row of sub( B ).
  JB      (global input) INTEGER
          The column index in the global array B indicating the
          first column of sub( B ).
  DESCB   (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix B.
  X       (local input/local output) COMPLEX pointer
          into the local memory to an array of local dimension
          (LLD_X, LOCc(JX+NRHS-1)).  If INFO = 0, the N-by-NRHS
          solution matrix X(IX:IX+N-1,JX:JX+NRHS-1) to the original
          system of equations.  Note that A(IA:IA+N-1,JA:JA+N-1) and
          B(IB:IB+N-1,JB:JB+NRHS-1) are modified on exit if
          EQUED .ne. 'N', and the solution to the equilibrated system
          is inv(diag(C))*X(IX:IX+N-1,JX:JX+NRHS-1) if TRANS = 'N'
          and EQUED = 'C' or 'B', or
          inv(diag(R))*X(IX:IX+N-1,JX:JX+NRHS-1) if TRANS = 'T' or 'C'
          and EQUED = 'R' or 'B'.
  IX      (global input) INTEGER
          The row index in the global array X indicating the first
          row of sub( X ).
  JX      (global input) INTEGER
          The column index in the global array X indicating the
          first column of sub( X ).
  DESCX   (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix X.
  RCOND   (global output) REAL
          The estimate of the reciprocal condition number of the matrix
          A(IA:IA+N-1,JA:JA+N-1) after equilibration (if done).  If
          RCOND is less than the machine precision (in particular, if
          RCOND = 0), the matrix is singular to working precision.
          This condition is indicated by a return code of INFO > 0.
  FERR    (local output) REAL array, dimension LOCc(N_B)
          The estimated forward error bounds for each solution vector
          X(j) (the j-th column of the solution matrix
          X(IX:IX+N-1,JX:JX+NRHS-1). If XTRUE is the true solution,
          FERR(j) bounds the magnitude of the largest entry in
          (X(j) - XTRUE) divided by the magnitude of the largest entry
          in X(j).  The estimate is as reliable as the estimate for
          RCOND, and is almost always a slight overestimate of the
          true error.  FERR is replicated in every process row, and is
          aligned with the matrices B and X.
  BERR    (local output) REAL array, dimension LOCc(N_B).
          The componentwise relative backward error of each solution
          vector X(j) (i.e., the smallest relative change in
          any entry of A(IA:IA+N-1,JA:JA+N-1) or
          B(IB:IB+N-1,JB:JB+NRHS-1) that makes X(j) an exact solution).
          BERR is replicated in every process row, and is aligned
          with the matrices B and X.
  WORK    (local workspace/local output) COMPLEX array,
                                                    dimension (LWORK)
          On exit, WORK(1) returns the minimal and optimal LWORK.
  LWORK   (local or global input) INTEGER
          The dimension of the array WORK.
          LWORK is local input and must be at least
          LWORK = MAX( PCGECON( LWORK ), PCGERFS( LWORK ) )
                  + LOCr( N_A ).
          If LWORK = -1, then LWORK is global input and a workspace
          query is assumed; the routine only calculates the minimum
          and optimal size for all work arrays. Each of these
          values is returned in the first entry of the corresponding
          work array, and no error message is issued by PXERBLA.
  RWORK   (local workspace/local output) REAL array,
                                                  dimension (LRWORK)
          On exit, RWORK(1) returns the minimal and optimal LRWORK.
  LRWORK  (local or global input) INTEGER
          The dimension of the array RWORK.
          LRWORK is local input and must be at least
          LRWORK = 2*LOCc(N_A).
          If LRWORK = -1, then LRWORK is global input and a workspace
          query is assumed; the routine only calculates the minimum
          and optimal size for all work arrays. Each of these
          values is returned in the first entry of the corresponding
          work array, and no error message is issued by PXERBLA.
  INFO    (global output) INTEGER
          = 0:  successful exit
          < 0:  if INFO = -i, the i-th argument had an illegal value
          > 0:  if INFO = i, and i is
                <= N:  U(IA+I-1,IA+I-1) is exactly zero.  The
                       factorization has been completed, but the
                       factor U is exactly singular, so the solution
                       and error bounds could not be computed.
                = N+1: RCOND is less than machine precision.  The
                       factorization has been completed, but the
                       matrix is singular to working precision, and
                       the solution and error bounds have not been
                       computed.
  =====================================================================
     .. Parameters ..

 
Display dynamic version Find AutoScroll Reload FontSize: - + Hide Comments Hide Blanks Frame FullScreen MailPrint

 
001        SUBROUTINE PCGESVX( FACT , TRANS , N , NRHS , A , IA , JA , DESCA , AF ,
002       $IAF , JAF , DESCAF , IPIV , EQUED , R , C , B , IB ,
003       $JB , DESCB , X , IX , JX , DESCX , RCOND , FERR ,
004       $BERR , WORK , LWORK , RWORK , LRWORK , INFO )
005  
006  *     -- ScaLAPACK routine(version 1.7) --
007  *     University of Tennessee , Knoxville , Oak Ridge National Laboratory ,
008  *     and University of California , Berkeley.
009  *     December 31 , 1998
010  
011  *     .. Scalar Arguments ..
012        CHARACTER EQUED , FACT , TRANS
013        INTEGER IA , IAF , IB , INFO , IX , JA , JAF , JB , JX , LRWORK ,
014       $LWORK , N , NRHS
015        REAL RCOND
016        INTEGER BLOCK_CYCLIC_2D , CSRC_ , CTXT_ , DLEN_ , DTYPE_ ,
017       $LLD_ , MB_ , M_ , NB_ , N_ , RSRC_
018        PARAMETER( BLOCK_CYCLIC_2D = 1 , DLEN_ = 9 , DTYPE_ = 1 ,
019       $CTXT_ = 2 , M_ = 3 , N_ = 4 , MB_ = 5 , NB_ = 6 ,
020       $RSRC_ = 7 , CSRC_ = 8 , LLD_ = 9 )
021        REAL ONE , ZERO
022        PARAMETER( ONE = 1.0E + 0 , ZERO = 0.0E + 0 )
023  *     ..
024  *     .. Local Scalars ..
025        LOGICAL COLEQU , EQUIL , LQUERY , NOFACT , NOTRAN , ROWEQU
026        CHARACTER NORM
027        INTEGER CONWRK , I , IACOL , IAROW , IAFROW , IBROW , IBCOL ,
028       $ICOFFA , ICOFFB , ICOFFX , ICTXT , IDUMM ,
029       $IIA , IIB , IIX ,
030       $INFEQU , IROFFA , IROFFAF , IROFFB ,
031       $IROFFX , IXCOL , IXROW , J , JJA , JJB , JJX ,
032       $LCM , LCMQ ,
033       $LRWMIN , LWMIN , MYCOL , MYROW , NP , NPCOL , NPROW ,
034       $NQ , NQB , NRHSQ , RFSWRK
035        REAL AMAX , ANORM , BIGNUM , COLCND , RCMAX , RCMIN ,
036       $ROWCND , SMLNUM
037  *     ..
038  *     .. Local Arrays ..
039        INTEGER CDESC( DLEN_ ) , IDUM1( 5 ) , IDUM2( 5 )
040  *     ..
041  *     .. External Subroutines ..
042        EXTERNAL BLACS_GRIDINFO , CHK1MAT , DESCSET , PCHK2MAT ,
043       $INFOG2L , PCGECON , PCGEEQU , PCGERFS ,
044       $PCGETRF , PCGETRS , PCLACPY ,
045       $PCLAQGE , PSCOPY , PXERBLA , SGEBR2D ,
046       $SGEBS2D , SGAMN2D , SGAMX2D
047  *     ..
048  *     .. External Functions ..
049        LOGICAL LSAME
050        INTEGER ICEIL , ILCM , INDXG2P , NUMROC
051        REAL PSLAMCH , PCLANGE
052        EXTERNAL ICEIL , ILCM , INDXG2P , LSAME , NUMROC , PCLANGE ,
053       $PSLAMCH
054  *     ..
055  *     .. Intrinsic Functions ..
056        INTRINSIC ICHAR , MAX , MIN , MOD , REAL
057  *     ..
058  *     .. Executable Statements ..
059  
060  *     Get grid parameters
061  
062        ICTXT = DESCA( CTXT_ )
063        CALL BLACS_GRIDINFO( ICTXT , NPROW , NPCOL , MYROW , MYCOL )
064  
065  *     Test the input parameters
066  
067        INFO = 0
068        IF( NPROW.EQ. - 1 ) THEN
069            INFO = - (800 + CTXT_)
070        ELSE
071            CALL CHK1MAT( N , 3 , N , 3 , IA , JA , DESCA , 8 , INFO )
072            IF( LSAME( FACT , 'F' ) )
073       $        CALL CHK1MAT( N , 3 , N , 3 , IAF , JAF , DESCAF , 12 , INFO )
074                CALL CHK1MAT( N , 3 , NRHS , 4 , IB , JB , DESCB , 20 , INFO )
075                CALL CHK1MAT( N , 3 , NRHS , 4 , IX , JX , DESCX , 24 , INFO )
076                NOFACT = LSAME( FACT , 'N' )
077                EQUIL = LSAME( FACT , 'E' )
078                NOTRAN = LSAME( TRANS , 'N' )
079                IF( NOFACT .OR. EQUIL ) THEN
080                    EQUED = 'N'
081                    ROWEQU = .FALSE.
082                    COLEQU = .FALSE.
083                ELSE
084                    ROWEQU = LSAME( EQUED , 'R' ) .OR. LSAME( EQUED , 'B' )
085                    COLEQU = LSAME( EQUED , 'C' ) .OR. LSAME( EQUED , 'B' )
086                    SMLNUM = PSLAMCH( ICTXT , 'Safe minimum' )
087                    BIGNUM = ONE / SMLNUM
088                END IF
089                IF( INFO.EQ.0 ) THEN
090                    IAROW = INDXG2P( IA , DESCA( MB_ ) , MYROW , DESCA( RSRC_ ) ,
091       $            NPROW )
092                    IAFROW = INDXG2P( IAF , DESCAF( MB_ ) , MYROW ,
093       $            DESCAF( RSRC_ ) , NPROW )
094                    IBROW = INDXG2P( IB , DESCB( MB_ ) , MYROW , DESCB( RSRC_ ) ,
095       $            NPROW )
096                    IXROW = INDXG2P( IX , DESCX( MB_ ) , MYROW , DESCX( RSRC_ ) ,
097       $            NPROW )
098                    IROFFA = MOD( IA - 1 , DESCA( MB_ ) )
099                    IROFFAF = MOD( IAF - 1 , DESCAF( MB_ ) )
100                    ICOFFA = MOD( JA - 1 , DESCA( NB_ ) )
101                    IROFFB = MOD( IB - 1 , DESCB( MB_ ) )
102                    ICOFFB = MOD( JB - 1 , DESCB( NB_ ) )
103                    IROFFX = MOD( IX - 1 , DESCX( MB_ ) )
104                    ICOFFX = MOD( JX - 1 , DESCX( NB_ ) )
105                    CALL INFOG2L( IA , JA , DESCA , NPROW , NPCOL , MYROW ,
106       $            MYCOL , IIA , JJA , IAROW , IACOL )
107                    NP = NUMROC( N + IROFFA , DESCA( MB_ ) , MYROW , IAROW ,
108       $            NPROW )
109                    IF( MYROW.EQ.IAROW )
110       $                NP = NP - IROFFA
111                        NQ = NUMROC( N + ICOFFA , DESCA( NB_ ) , MYCOL , IACOL ,
112       $                NPCOL )
113                        IF( MYCOL.EQ.IACOL )
114       $                    NQ = NQ - ICOFFA
115                            NQB = ICEIL( N + IROFFA , DESCA( NB_ )*NPCOL )
116                            LCM = ILCM( NPROW , NPCOL )
117                            LCMQ = LCM / NPCOL
118                            CONWRK = 2*NP + 2*NQ + MAX( 2 , MAX( DESCA( NB_ )*
119       $                    MAX( 1 , ICEIL( NPROW - 1 , NPCOL ) ) , NQ +
120       $                    DESCA( NB_ )*
121       $                    MAX( 1 , ICEIL( NPCOL - 1 , NPROW ) ) ) )
122                            RFSWRK = 3*NP
123                            IF( LSAME( TRANS , 'N' ) ) THEN
124                                RFSWRK = RFSWRK + NP + NQ +
125       $                        ICEIL( NQB , LCMQ )*DESCA( NB_ )
126                            ELSE IF( LSAME( TRANS , 'T' ).OR.LSAME( TRANS , 'C' ) ) THEN
127                                RFSWRK = RFSWRK + NP + NQ
128                            END IF
129                            LWMIN = MAX( CONWRK , RFSWRK )
130                            LRWMIN = MAX( 2*NQ , NP )
131                            RWORK( 1 ) = REAL( LRWMIN )
132                            IF( .NOT.NOFACT .AND. .NOT.EQUIL .AND.
133       $                        .NOT.LSAME( FACT , 'F' ) ) THEN
134                                INFO = - 1
135                            ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS , 'T' ) .AND.
136       $                        .NOT. LSAME( TRANS , 'C' ) ) THEN
137                                INFO = - 2
138                            ELSE IF( IROFFA.NE.0 ) THEN
139                                INFO = - 6
140                            ELSE IF( ICOFFA.NE.0 .OR. IROFFA.NE.ICOFFA ) THEN
141                                INFO = - 7
142                            ELSE IF( DESCA( MB_ ).NE.DESCA( NB_ ) ) THEN
143                                INFO = - (800 + NB_)
144                            ELSE IF( IAFROW.NE.IAROW ) THEN
145                                INFO = - 10
146                            ELSE IF( IROFFAF.NE.0 ) THEN
147                                INFO = - 10
148                            ELSE IF( ICTXT.NE.DESCAF( CTXT_ ) ) THEN
149                                INFO = - (1200 + CTXT_)
150                            ELSE IF( LSAME( FACT , 'F' ) .AND. .NOT.
151       $( ROWEQU .OR. COLEQU .OR. LSAME( EQUED , 'N' ) ) ) THEN
152                                INFO = - 13
153                            ELSE
154                                IF( ROWEQU ) THEN
155                                    RCMIN = BIGNUM
156                                    RCMAX = ZERO
157                                    DO 10 J = IIA , IIA + NP - 1
158                                        RCMIN = MIN( RCMIN , R( J ) )
159                                        RCMAX = MAX( RCMAX , R( J ) )
160     10                             CONTINUE
161                                    CALL SGAMN2D( ICTXT , 'Columnwise' , ' ' , 1 , 1 , RCMIN ,
162       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
163                                    CALL SGAMX2D( ICTXT , 'Columnwise' , ' ' , 1 , 1 , RCMAX ,
164       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
165                                    IF( RCMIN.LE.ZERO ) THEN
166                                        INFO = - 14
167                                    ELSE IF( N.GT.0 ) THEN
168                                        ROWCND = MAX( RCMIN , SMLNUM ) /
169       $                                MIN( RCMAX , BIGNUM )
170                                    ELSE
171                                        ROWCND = ONE
172                                    END IF
173                                END IF
174                                IF( COLEQU .AND. INFO.EQ.0 ) THEN
175                                    RCMIN = BIGNUM
176                                    RCMAX = ZERO
177                                    DO 20 J = JJA , JJA + NQ - 1
178                                        RCMIN = MIN( RCMIN , C( J ) )
179                                        RCMAX = MAX( RCMAX , C( J ) )
180     20                             CONTINUE
181                                    CALL SGAMN2D( ICTXT , 'Rowwise' , ' ' , 1 , 1 , RCMIN ,
182       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
183                                    CALL SGAMX2D( ICTXT , 'Rowwise' , ' ' , 1 , 1 , RCMAX ,
184       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
185                                    IF( RCMIN.LE.ZERO ) THEN
186                                        INFO = - 15
187                                    ELSE IF( N.GT.0 ) THEN
188                                        COLCND = MAX( RCMIN , SMLNUM ) /
189       $                                MIN( RCMAX , BIGNUM )
190                                    ELSE
191                                        COLCND = ONE
192                                    END IF
193                                END IF
194                            END IF
195                        END IF
196  
197                        WORK( 1 ) = REAL( LWMIN )
198                        RWORK( 1 ) = REAL( LRWMIN )
199                        LQUERY =( LWORK.EQ. - 1 .OR. LRWORK.EQ. - 1 )
200                        IF( INFO.EQ.0 ) THEN
201                            IF( IBROW.NE.IAROW ) THEN
202                                INFO = - 18
203                            ELSE IF( IXROW.NE.IBROW ) THEN
204                                INFO = - 22
205                            ELSE IF( DESCB( MB_ ).NE.DESCA( NB_ ) ) THEN
206                                INFO = - (2000 + NB_)
207                            ELSE IF( ICTXT.NE.DESCB( CTXT_ ) ) THEN
208                                INFO = - (2000 + CTXT_)
209                            ELSE IF( DESCX( MB_ ).NE.DESCA( NB_ ) ) THEN
210                                INFO = - (2400 + NB_)
211                            ELSE IF( ICTXT.NE.DESCX( CTXT_ ) ) THEN
212                                INFO = - (2400 + CTXT_)
213                            ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
214                                INFO = - 29
215                            ELSE IF( LRWORK.LT.LRWMIN .AND. .NOT.LQUERY ) THEN
216                                INFO = - 31
217                            END IF
218                            IDUM1( 1 ) = ICHAR( FACT )
219                            IDUM2( 1 ) = 1
220                            IDUM1( 2 ) = ICHAR( TRANS )
221                            IDUM2( 2 ) = 2
222                            IF( LSAME( FACT , 'F' ) ) THEN
223                                IDUM1( 3 ) = ICHAR( EQUED )
224                                IDUM2( 3 ) = 14
225                                IF( LWORK.EQ. - 1 ) THEN
226                                    IDUM1( 4 ) = - 1
227                                ELSE
228                                    IDUM1( 4 ) = 1
229                                END IF
230                                IDUM2( 4 ) = 29
231                                IF( LRWORK.EQ. - 1 ) THEN
232                                    IDUM1( 5 ) = - 1
233                                ELSE
234                                    IDUM1( 5 ) = 1
235                                END IF
236                                IDUM2( 5 ) = 31
237                                CALL PCHK2MAT( N , 3 , N , 3 , IA , JA , DESCA , 8 , N , 3 ,
238       $                        NRHS , 4 , IB , JB , DESCB , 20 , 5 , IDUM1 ,
239       $                        IDUM2 , INFO )
240                            ELSE
241                                IF( LWORK.EQ. - 1 ) THEN
242                                    IDUM1( 3 ) = - 1
243                                ELSE
244                                    IDUM1( 3 ) = 1
245                                END IF
246                                IDUM2( 3 ) = 29
247                                IF( LRWORK.EQ. - 1 ) THEN
248                                    IDUM1( 4 ) = - 1
249                                ELSE
250                                    IDUM1( 4 ) = 1
251                                END IF
252                                IDUM2( 4 ) = 31
253                                CALL PCHK2MAT( N , 3 , N , 3 , IA , JA , DESCA , 8 , N , 3 ,
254       $                        NRHS , 4 , IB , JB , DESCB , 20 , 4 , IDUM1 ,
255       $                        IDUM2 , INFO )
256                            END IF
257                        END IF
258                    END IF
259  
260                    IF( INFO.NE.0 ) THEN
261                        CALL PXERBLA( ICTXT , 'PCGESVX' , - INFO )
262                        RETURN
263                    ELSE IF( LQUERY ) THEN
264                        RETURN
265                    END IF
266  
267                    IF( EQUIL ) THEN
268  
269  *                     Compute row and column scalings to equilibrate the matrix A.
270  
271                        CALL PCGEEQU ( N , N , A , IA , JA , DESCA , R , C , ROWCND , COLCND ,
272       $                AMAX , INFEQU )
273                        IF( INFEQU.EQ.0 ) THEN
274  
275  *                         Equilibrate the matrix.
276  
277                            CALL PCLAQGE ( N , N , A , IA , JA , DESCA , R , C , ROWCND , COLCND ,
278       $                    AMAX , EQUED )
279                            ROWEQU = LSAME( EQUED , 'R' ) .OR. LSAME( EQUED , 'B' )
280                            COLEQU = LSAME( EQUED , 'C' ) .OR. LSAME( EQUED , 'B' )
281                        END IF
282                    END IF
283  
284  *                 Scale the right - hand side.
285  
286                    CALL INFOG2L( IB , JB , DESCB , NPROW , NPCOL , MYROW , MYCOL , IIB ,
287       $            JJB , IBROW , IBCOL )
288                    NP = NUMROC( N + IROFFB , DESCB( MB_ ) , MYROW , IBROW , NPROW )
289                    NRHSQ = NUMROC( NRHS + ICOFFB , DESCB( NB_ ) , MYCOL , IBCOL , NPCOL )
290                    IF( MYROW.EQ.IBROW )
291       $                NP = NP - IROFFB
292                        IF( MYCOL.EQ.IBCOL )
293       $                    NRHSQ = NRHSQ - ICOFFB
294  
295                            IF( NOTRAN ) THEN
296                                IF( ROWEQU ) THEN
297                                    DO 40 J = JJB , JJB + NRHSQ - 1
298                                        DO 30 I = IIB , IIB + NP - 1
299                                            B( I + ( J - 1 )*DESCB( LLD_ ) ) = R( I )*
300       $                                    B( I + ( J - 1 )*DESCB( LLD_ ) )
301     30                                 CONTINUE
302     40                             CONTINUE
303                                END IF
304                            ELSE IF( COLEQU ) THEN
305  
306  *                             Transpose the Column scale factors
307  
308                                CALL DESCSET( CDESC , 1 , N + ICOFFA , 1 , DESCA( NB_ ) , MYROW ,
309       $                        IACOL , ICTXT , 1 )
310                                CALL PSCOPY( N , C , 1 , JA , CDESC , CDESC( LLD_ ) , RWORK , IB , JB ,
311       $                        DESCB , 1 )
312                                IF( MYCOL.EQ.IBCOL ) THEN
313                                    CALL SGEBS2D( ICTXT , 'Rowwise' , ' ' , NP , 1 , RWORK( IIB ) ,
314       $                            DESCB( LLD_ ) )
315                                ELSE
316                                    CALL SGEBR2D( ICTXT , 'Rowwise' , ' ' , NP , 1 , RWORK( IIB ) ,
317       $                            DESCB( LLD_ ) , MYROW , IBCOL )
318                                END IF
319                                DO 60 J = JJB , JJB + NRHSQ - 1
320                                    DO 50 I = IIB , IIB + NP - 1
321                                        B( I + ( J - 1 )*DESCB( LLD_ ) ) = RWORK( I )*
322       $                                B( I + ( J - 1 )*DESCB( LLD_ ) )
323     50                             CONTINUE
324     60                         CONTINUE
325                            END IF
326  
327                            IF( NOFACT.OR.EQUIL ) THEN
328  
329  *                             Compute the LU factorization of A.
330  
331                                CALL PCLACPY ( 'Full' , N , N , A , IA , JA , DESCA , AF , IAF , JAF ,
332       $                        DESCAF )
333                                CALL PCGETRF ( N , N , AF , IAF , JAF , DESCAF , IPIV , INFO )
334  
335  *                             Return if INFO is non - zero.
336  
337                                IF( INFO.NE.0 ) THEN
338                                    IF( INFO.GT.0 )
339       $                                RCOND = ZERO
340                                        RETURN
341                                    END IF
342                                END IF
343  
344  *                             Compute the norm of the matrix A.
345  
346                                IF( NOTRAN ) THEN
347                                    NORM = '1'
348                                ELSE
349                                    NORM = 'I'
350                                END IF
351                                ANORM = PCLANGE( NORM , N , N , A , IA , JA , DESCA , RWORK )
352  
353  *                             Compute the reciprocal of the condition number of A.
354  
355                                CALL PCGECON ( NORM , N , AF , IAF , JAF , DESCAF , ANORM , RCOND , WORK ,
356       $                        LWORK , RWORK , LRWORK , INFO )
357  
358  *                             Return if the matrix is singular to working precision.
359  
360                                IF( RCOND.LT.PSLAMCH( ICTXT , 'Epsilon' ) ) THEN
361                                    INFO = IA + N
362                                    RETURN
363                                END IF
364  
365  *                             Compute the solution matrix X.
366  
367                                CALL PCLACPY ( 'Full' , N , NRHS , B , IB , JB , DESCB , X , IX , JX ,
368       $                        DESCX )
369                                CALL PCGETRS ( TRANS , N , NRHS , AF , IAF , JAF , DESCAF , IPIV , X , IX ,
370       $                        JX , DESCX , INFO )
371  
372  *                             Use iterative refinement to improve the computed solution and
373  *                             compute error bounds and backward error estimates for it.
374  
375                                CALL PCGERFS ( TRANS , N , NRHS , A , IA , JA , DESCA , AF , IAF , JAF ,
376       $                        DESCAF , IPIV , B , IB , JB , DESCB , X , IX , JX , DESCX ,
377       $                        FERR , BERR , WORK , LWORK , RWORK , LRWORK , INFO )
378  
379  *                             Transform the solution matrix X to a solution of the original
380  *                             system.
381  
382                                CALL INFOG2L( IX , JX , DESCX , NPROW , NPCOL , MYROW , MYCOL , IIX ,
383       $                        JJX , IXROW , IXCOL )
384                                NP = NUMROC( N + IROFFX , DESCX( MB_ ) , MYROW , IXROW , NPROW )
385                                NRHSQ = NUMROC( NRHS + ICOFFX , DESCX( NB_ ) , MYCOL , IXCOL , NPCOL )
386                                IF( MYROW.EQ.IBROW )
387       $                            NP = NP - IROFFX
388                                    IF( MYCOL.EQ.IBCOL )
389       $                                NRHSQ = NRHSQ - ICOFFX
390  
391                                        IF( NOTRAN ) THEN
392                                            IF( COLEQU ) THEN
393  
394  *                                             Transpose the column scaling factors
395  
396                                                CALL DESCSET( CDESC , 1 , N + ICOFFA , 1 , DESCA( NB_ ) , MYROW ,
397       $                                        IACOL , ICTXT , 1 )
398                                                CALL PSCOPY( N , C , 1 , JA , CDESC , CDESC( LLD_ ) , RWORK , IX ,
399       $                                        JX , DESCX , 1 )
400                                                IF( MYCOL.EQ.IBCOL ) THEN
401                                                    CALL SGEBS2D( ICTXT , 'Rowwise' , ' ' , NP , 1 ,
402       $                                            RWORK( IIX ) , DESCX( LLD_ ) )
403                                                ELSE
404                                                    CALL SGEBR2D( ICTXT , 'Rowwise' , ' ' , NP , 1 ,
405       $                                            RWORK( IIX ) , DESCX( LLD_ ) , MYROW ,
406       $                                            IBCOL )
407                                                END IF
408  
409                                                DO 80 J = JJX , JJX + NRHSQ - 1
410                                                    DO 70 I = IIX , IIX + NP - 1
411                                                        X( I + ( J - 1 )*DESCX( LLD_ ) ) = RWORK( I )*
412       $                                                X( I + ( J - 1 )*DESCX( LLD_ ) )
413     70                                             CONTINUE
414     80                                         CONTINUE
415                                                DO 90 J = JJX , JJX + NRHSQ - 1
416                                                    FERR( J ) = FERR( J ) / COLCND
417     90                                         CONTINUE
418                                            END IF
419                                        ELSE IF( ROWEQU ) THEN
420                                            DO 110 J = JJX , JJX + NRHSQ - 1
421                                                DO 100 I = IIX , IIX + NP - 1
422                                                    X( I + ( J - 1 )*DESCX( LLD_ ) ) = R( I )*
423       $                                            X( I + ( J - 1 )*DESCX( LLD_ ) )
424    100                                         CONTINUE
425    110                                     CONTINUE
426                                            DO 120 J = JJX , JJX + NRHSQ - 1
427                                                FERR( J ) = FERR( J ) / ROWCND
428    120                                     CONTINUE
429                                        END IF
430  
431                                        WORK( 1 ) = REAL( LWMIN )
432                                        RWORK( 1 ) = REAL( LRWMIN )
433  
434                                        RETURN
435  
436  *                                     End of PCGESVX
437  
438                                    END