Routine: PDGESVX()  File: SRC\pdgesvx.f

 
 
# lines: 829
  # code: 829
  # comment: 0
  # blank:0
# Variables:99
# Callers:0
# Callings:9
# Words:438
# Keywords:286
 

 

..
     .. Array Arguments ..
     ..
  Purpose
  =======
  PDGESVX uses the LU factorization to compute the solution to a real
  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)  (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) DOUBLE PRECISION 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) DOUBLE PRECISION 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 PDGETRF.
          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
          PDGETRF; 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION
          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) DOUBLE PRECISION 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) DOUBLE PRECISION 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) DOUBLE PRECISION 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( PDGECON( LWORK ), PDGERFS( 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.
  IWORK   (local workspace/local output) INTEGER array,
                                                  dimension (LIWORK)
          On exit, IWORK(1) returns the minimal and optimal LIWORK.
  LIWORK  (local or global input) INTEGER
          The dimension of the array IWORK.
          LIWORK is local input and must be at least
          LIWORK = LOCr(N_A).
          If LIWORK = -1, then LIWORK 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 PDGESVX( 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 , IWORK , LIWORK , 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 , LIWORK ,
014       $LWORK , N , NRHS
015        DOUBLE PRECISION 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        DOUBLE PRECISION ONE , ZERO
022        PARAMETER( ONE = 1.0D + 0 , ZERO = 0.0D + 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       $LIWMIN , LWMIN , MYCOL , MYROW , NP , NPCOL , NPROW ,
034       $NQ , NQB , NRHSQ , RFSWRK
035        DOUBLE PRECISION 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       $DGEBR2D , DGEBS2D , DGAMN2D ,
044       $DGAMX2D , INFOG2L , PDCOPY , PDGECON ,
045       $PDGEEQU , PDGERFS , PDGETRF , PDGETRS ,
046       $PDLACPY , PDLAQGE , PXERBLA
047  *     ..
048  *     .. External Functions ..
049        LOGICAL LSAME
050        INTEGER ICEIL , ILCM , INDXG2P , NUMROC
051        DOUBLE PRECISION PDLAMCH , PDLANGE
052        EXTERNAL ICEIL , ILCM , INDXG2P , LSAME , NUMROC , PDLANGE ,
053       $PDLAMCH
054  *     ..
055  *     .. Intrinsic Functions ..
056        INTRINSIC DBLE , ICHAR , MAX , MIN , MOD
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 = PDLAMCH( 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                            WORK( 1 ) = DBLE( LWMIN )
131                            LIWMIN = NP
132                            IWORK( 1 ) = LIWMIN
133                            IF( .NOT.NOFACT .AND. .NOT.EQUIL .AND.
134       $                        .NOT.LSAME( FACT , 'F' ) ) THEN
135                                INFO = - 1
136                            ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS , 'T' ) .AND.
137       $                        .NOT. LSAME( TRANS , 'C' ) ) THEN
138                                INFO = - 2
139                            ELSE IF( IROFFA.NE.0 ) THEN
140                                INFO = - 6
141                            ELSE IF( ICOFFA.NE.0 .OR. IROFFA.NE.ICOFFA ) THEN
142                                INFO = - 7
143                            ELSE IF( DESCA( MB_ ).NE.DESCA( NB_ ) ) THEN
144                                INFO = - (800 + NB_)
145                            ELSE IF( IAFROW.NE.IAROW ) THEN
146                                INFO = - 10
147                            ELSE IF( IROFFAF.NE.0 ) THEN
148                                INFO = - 10
149                            ELSE IF( ICTXT.NE.DESCAF( CTXT_ ) ) THEN
150                                INFO = - (1200 + CTXT_)
151                            ELSE IF( LSAME( FACT , 'F' ) .AND. .NOT.
152       $( ROWEQU .OR. COLEQU .OR. LSAME( EQUED , 'N' ) ) ) THEN
153                                INFO = - 13
154                            ELSE
155                                IF( ROWEQU ) THEN
156                                    RCMIN = BIGNUM
157                                    RCMAX = ZERO
158                                    DO 10 J = IIA , IIA + NP - 1
159                                        RCMIN = MIN( RCMIN , R( J ) )
160                                        RCMAX = MAX( RCMAX , R( J ) )
161     10                             CONTINUE
162                                    CALL DGAMN2D( ICTXT , 'Columnwise' , ' ' , 1 , 1 , RCMIN ,
163       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
164                                    CALL DGAMX2D( ICTXT , 'Columnwise' , ' ' , 1 , 1 , RCMAX ,
165       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
166                                    IF( RCMIN.LE.ZERO ) THEN
167                                        INFO = - 14
168                                    ELSE IF( N.GT.0 ) THEN
169                                        ROWCND = MAX( RCMIN , SMLNUM ) /
170       $                                MIN( RCMAX , BIGNUM )
171                                    ELSE
172                                        ROWCND = ONE
173                                    END IF
174                                END IF
175                                IF( COLEQU .AND. INFO.EQ.0 ) THEN
176                                    RCMIN = BIGNUM
177                                    RCMAX = ZERO
178                                    DO 20 J = JJA , JJA + NQ - 1
179                                        RCMIN = MIN( RCMIN , C( J ) )
180                                        RCMAX = MAX( RCMAX , C( J ) )
181     20                             CONTINUE
182                                    CALL DGAMN2D( ICTXT , 'Rowwise' , ' ' , 1 , 1 , RCMIN ,
183       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
184                                    CALL DGAMX2D( ICTXT , 'Rowwise' , ' ' , 1 , 1 , RCMAX ,
185       $                            1 , IDUMM , IDUMM , - 1 , - 1 , MYCOL )
186                                    IF( RCMIN.LE.ZERO ) THEN
187                                        INFO = - 15
188                                    ELSE IF( N.GT.0 ) THEN
189                                        COLCND = MAX( RCMIN , SMLNUM ) /
190       $                                MIN( RCMAX , BIGNUM )
191                                    ELSE
192                                        COLCND = ONE
193                                    END IF
194                                END IF
195                            END IF
196                        END IF
197  
198                        WORK( 1 ) = DBLE( LWMIN )
199                        IWORK( 1 ) = LIWMIN
200                        LQUERY =( LWORK.EQ. - 1 .OR. LIWORK.EQ. - 1 )
201                        IF( INFO.EQ.0 ) THEN
202                            IF( IBROW.NE.IAROW ) THEN
203                                INFO = - 18
204                            ELSE IF( IXROW.NE.IBROW ) THEN
205                                INFO = - 22
206                            ELSE IF( DESCB( MB_ ).NE.DESCA( NB_ ) ) THEN
207                                INFO = - (2000 + NB_)
208                            ELSE IF( ICTXT.NE.DESCB( CTXT_ ) ) THEN
209                                INFO = - (2000 + CTXT_)
210                            ELSE IF( DESCX( MB_ ).NE.DESCA( NB_ ) ) THEN
211                                INFO = - (2400 + NB_)
212                            ELSE IF( ICTXT.NE.DESCX( CTXT_ ) ) THEN
213                                INFO = - (2400 + CTXT_)
214                            ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
215                                INFO = - 29
216                            ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
217                                INFO = - 31
218                            END IF
219                            IDUM1( 1 ) = ICHAR( FACT )
220                            IDUM2( 1 ) = 1
221                            IDUM1( 2 ) = ICHAR( TRANS )
222                            IDUM2( 2 ) = 2
223                            IF( LSAME( FACT , 'F' ) ) THEN
224                                IDUM1( 3 ) = ICHAR( EQUED )
225                                IDUM2( 3 ) = 14
226                                IF( LWORK.EQ. - 1 ) THEN
227                                    IDUM1( 4 ) = - 1
228                                ELSE
229                                    IDUM1( 4 ) = 1
230                                END IF
231                                IDUM2( 4 ) = 29
232                                IF( LIWORK.EQ. - 1 ) THEN
233                                    IDUM1( 5 ) = - 1
234                                ELSE
235                                    IDUM1( 5 ) = 1
236                                END IF
237                                IDUM2( 5 ) = 31
238                                CALL PCHK2MAT( N , 3 , N , 3 , IA , JA , DESCA , 8 , N , 3 ,
239       $                        NRHS , 4 , IB , JB , DESCB , 20 , 5 , IDUM1 ,
240       $                        IDUM2 , INFO )
241                            ELSE
242                                IF( LWORK.EQ. - 1 ) THEN
243                                    IDUM1( 3 ) = - 1
244                                ELSE
245                                    IDUM1( 3 ) = 1
246                                END IF
247                                IDUM2( 3 ) = 29
248                                IF( LIWORK.EQ. - 1 ) THEN
249                                    IDUM1( 4 ) = - 1
250                                ELSE
251                                    IDUM1( 4 ) = 1
252                                END IF
253                                IDUM2( 4 ) = 31
254                                CALL PCHK2MAT( N , 3 , N , 3 , IA , JA , DESCA , 8 , N , 3 ,
255       $                        NRHS , 4 , IB , JB , DESCB , 20 , 4 , IDUM1 ,
256       $                        IDUM2 , INFO )
257                            END IF
258                        END IF
259                    END IF
260  
261                    IF( INFO.NE.0 ) THEN
262                        CALL PXERBLA( ICTXT , 'PDGESVX' , - INFO )
263                        RETURN
264                    ELSE IF( LQUERY ) THEN
265                        RETURN
266                    END IF
267  
268                    IF( EQUIL ) THEN
269  
270  *                     Compute row and column scalings to equilibrate the matrix A.
271  
272                        CALL PDGEEQU ( N , N , A , IA , JA , DESCA , R , C , ROWCND , COLCND ,
273       $                AMAX , INFEQU )
274                        IF( INFEQU.EQ.0 ) THEN
275  
276  *                         Equilibrate the matrix.
277  
278                            CALL PDLAQGE ( N , N , A , IA , JA , DESCA , R , C , ROWCND , COLCND ,
279       $                    AMAX , EQUED )
280                            ROWEQU = LSAME( EQUED , 'R' ) .OR. LSAME( EQUED , 'B' )
281                            COLEQU = LSAME( EQUED , 'C' ) .OR. LSAME( EQUED , 'B' )
282                        END IF
283                    END IF
284  
285  *                 Scale the right - hand side.
286  
287                    CALL INFOG2L( IB , JB , DESCB , NPROW , NPCOL , MYROW , MYCOL , IIB ,
288       $            JJB , IBROW , IBCOL )
289                    NP = NUMROC( N + IROFFB , DESCB( MB_ ) , MYROW , IBROW , NPROW )
290                    NRHSQ = NUMROC( NRHS + ICOFFB , DESCB( NB_ ) , MYCOL , IBCOL , NPCOL )
291                    IF( MYROW.EQ.IBROW )
292       $                NP = NP - IROFFB
293                        IF( MYCOL.EQ.IBCOL )
294       $                    NRHSQ = NRHSQ - ICOFFB
295  
296                            IF( NOTRAN ) THEN
297                                IF( ROWEQU ) THEN
298                                    DO 40 J = JJB , JJB + NRHSQ - 1
299                                        DO 30 I = IIB , IIB + NP - 1
300                                            B( I + ( J - 1 )*DESCB( LLD_ ) ) = R( I )*
301       $                                    B( I + ( J - 1 )*DESCB( LLD_ ) )
302     30                                 CONTINUE
303     40                             CONTINUE
304                                END IF
305                            ELSE IF( COLEQU ) THEN
306  
307  *                             Transpose the Column scale factors
308  
309                                CALL DESCSET( CDESC , 1 , N + ICOFFA , 1 , DESCA( NB_ ) , MYROW ,
310       $                        IACOL , ICTXT , 1 )
311                                CALL PDCOPY( N , C , 1 , JA , CDESC , CDESC( LLD_ ) , WORK , IB , JB ,
312       $                        DESCB , 1 )
313                                IF( MYCOL.EQ.IBCOL ) THEN
314                                    CALL DGEBS2D( ICTXT , 'Rowwise' , ' ' , NP , 1 , WORK( IIB ) ,
315       $                            DESCB( LLD_ ) )
316                                ELSE
317                                    CALL DGEBR2D( ICTXT , 'Rowwise' , ' ' , NP , 1 , WORK( IIB ) ,
318       $                            DESCB( LLD_ ) , MYROW , IBCOL )
319                                END IF
320                                DO 60 J = JJB , JJB + NRHSQ - 1
321                                    DO 50 I = IIB , IIB + NP - 1
322                                        B( I + ( J - 1 )*DESCB( LLD_ ) ) = WORK( I )*
323       $                                B( I + ( J - 1 )*DESCB( LLD_ ) )
324     50                             CONTINUE
325     60                         CONTINUE
326                            END IF
327  
328                            IF( NOFACT.OR.EQUIL ) THEN
329  
330  *                             Compute the LU factorization of A.
331  
332                                CALL PDLACPY ( 'Full' , N , N , A , IA , JA , DESCA , AF , IAF , JAF ,
333       $                        DESCAF )
334                                CALL PDGETRF ( N , N , AF , IAF , JAF , DESCAF , IPIV , INFO )
335  
336  *                             Return if INFO is non - zero.
337  
338                                IF( INFO.NE.0 ) THEN
339                                    IF( INFO.GT.0 )
340       $                                RCOND = ZERO
341                                        RETURN
342                                    END IF
343                                END IF
344  
345  *                             Compute the norm of the matrix A.
346  
347                                IF( NOTRAN ) THEN
348                                    NORM = '1'
349                                ELSE
350                                    NORM = 'I'
351                                END IF
352                                ANORM = PDLANGE( NORM , N , N , A , IA , JA , DESCA , WORK )
353  
354  *                             Compute the reciprocal of the condition number of A.
355  
356                                CALL PDGECON ( NORM , N , AF , IAF , JAF , DESCAF , ANORM , RCOND , WORK ,
357       $                        LWORK , IWORK , LIWORK , INFO )
358  
359  *                             Return if the matrix is singular to working precision.
360  
361                                IF( RCOND.LT.PDLAMCH( ICTXT , 'Epsilon' ) ) THEN
362                                    INFO = IA + N
363                                    RETURN
364                                END IF
365  
366  *                             Compute the solution matrix X.
367  
368                                CALL PDLACPY ( 'Full' , N , NRHS , B , IB , JB , DESCB , X , IX , JX ,
369       $                        DESCX )
370                                CALL PDGETRS ( TRANS , N , NRHS , AF , IAF , JAF , DESCAF , IPIV , X , IX ,
371       $                        JX , DESCX , INFO )
372  
373  *                             Use iterative refinement to improve the computed solution and
374  *                             compute error bounds and backward error estimates for it.
375  
376                                CALL PDGERFS ( TRANS , N , NRHS , A , IA , JA , DESCA , AF , IAF , JAF ,
377       $                        DESCAF , IPIV , B , IB , JB , DESCB , X , IX , JX , DESCX ,
378       $                        FERR , BERR , WORK , LWORK , IWORK , LIWORK , INFO )
379  
380  *                             Transform the solution matrix X to a solution of the original
381  *                             system.
382  
383                                CALL INFOG2L( IX , JX , DESCX , NPROW , NPCOL , MYROW , MYCOL , IIX ,
384       $                        JJX , IXROW , IXCOL )
385                                NP = NUMROC( N + IROFFX , DESCX( MB_ ) , MYROW , IXROW , NPROW )
386                                NRHSQ = NUMROC( NRHS + ICOFFX , DESCX( NB_ ) , MYCOL , IXCOL , NPCOL )
387                                IF( MYROW.EQ.IBROW )
388       $                            NP = NP - IROFFX
389                                    IF( MYCOL.EQ.IBCOL )
390       $                                NRHSQ = NRHSQ - ICOFFX
391  
392                                        IF( NOTRAN ) THEN
393                                            IF( COLEQU ) THEN
394  
395  *                                             Transpose the column scaling factors
396  
397                                                CALL DESCSET( CDESC , 1 , N + ICOFFA , 1 , DESCA( NB_ ) , MYROW ,
398       $                                        IACOL , ICTXT , 1 )
399                                                CALL PDCOPY( N , C , 1 , JA , CDESC , CDESC( LLD_ ) , WORK , IX ,
400       $                                        JX , DESCX , 1 )
401                                                IF( MYCOL.EQ.IBCOL ) THEN
402                                                    CALL DGEBS2D( ICTXT , 'Rowwise' , ' ' , NP , 1 ,
403       $                                            WORK( IIX ) , DESCX( LLD_ ) )
404                                                ELSE
405                                                    CALL DGEBR2D( ICTXT , 'Rowwise' , ' ' , NP , 1 ,
406       $                                            WORK( IIX ) , DESCX( LLD_ ) , MYROW , 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_ ) ) = WORK( 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 ) = DBLE( LWMIN )
432                                        IWORK( 1 ) = LIWMIN
433  
434                                        RETURN
435  
436  *                                     End of PDGESVX
437  
438                                    END