LAPACK 3.3.1 Linear Algebra PACKage

# cgerfs.f

Go to the documentation of this file.
```00001       SUBROUTINE CGERFS( TRANS, N, NRHS, A, LDA, AF, LDAF, IPIV, B, LDB,
00002      \$                   X, LDX, FERR, BERR, WORK, RWORK, INFO )
00003 *
00004 *  -- LAPACK routine (version 3.2) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *     November 2006
00008 *
00009 *     Modified to call CLACN2 in place of CLACON, 10 Feb 03, SJH.
00010 *
00011 *     .. Scalar Arguments ..
00012       CHARACTER          TRANS
00013       INTEGER            INFO, LDA, LDAF, LDB, LDX, N, NRHS
00014 *     ..
00015 *     .. Array Arguments ..
00016       INTEGER            IPIV( * )
00017       REAL               BERR( * ), FERR( * ), RWORK( * )
00018       COMPLEX            A( LDA, * ), AF( LDAF, * ), B( LDB, * ),
00019      \$                   WORK( * ), X( LDX, * )
00020 *     ..
00021 *
00022 *  Purpose
00023 *  =======
00024 *
00025 *  CGERFS improves the computed solution to a system of linear
00026 *  equations and provides error bounds and backward error estimates for
00027 *  the solution.
00028 *
00029 *  Arguments
00030 *  =========
00031 *
00032 *  TRANS   (input) CHARACTER*1
00033 *          Specifies the form of the system of equations:
00034 *          = 'N':  A * X = B     (No transpose)
00035 *          = 'T':  A**T * X = B  (Transpose)
00036 *          = 'C':  A**H * X = B  (Conjugate transpose)
00037 *
00038 *  N       (input) INTEGER
00039 *          The order of the matrix A.  N >= 0.
00040 *
00041 *  NRHS    (input) INTEGER
00042 *          The number of right hand sides, i.e., the number of columns
00043 *          of the matrices B and X.  NRHS >= 0.
00044 *
00045 *  A       (input) COMPLEX array, dimension (LDA,N)
00046 *          The original N-by-N matrix A.
00047 *
00048 *  LDA     (input) INTEGER
00049 *          The leading dimension of the array A.  LDA >= max(1,N).
00050 *
00051 *  AF      (input) COMPLEX array, dimension (LDAF,N)
00052 *          The factors L and U from the factorization A = P*L*U
00053 *          as computed by CGETRF.
00054 *
00055 *  LDAF    (input) INTEGER
00056 *          The leading dimension of the array AF.  LDAF >= max(1,N).
00057 *
00058 *  IPIV    (input) INTEGER array, dimension (N)
00059 *          The pivot indices from CGETRF; for 1<=i<=N, row i of the
00060 *          matrix was interchanged with row IPIV(i).
00061 *
00062 *  B       (input) COMPLEX array, dimension (LDB,NRHS)
00063 *          The right hand side matrix B.
00064 *
00065 *  LDB     (input) INTEGER
00066 *          The leading dimension of the array B.  LDB >= max(1,N).
00067 *
00068 *  X       (input/output) COMPLEX array, dimension (LDX,NRHS)
00069 *          On entry, the solution matrix X, as computed by CGETRS.
00070 *          On exit, the improved solution matrix X.
00071 *
00072 *  LDX     (input) INTEGER
00073 *          The leading dimension of the array X.  LDX >= max(1,N).
00074 *
00075 *  FERR    (output) REAL array, dimension (NRHS)
00076 *          The estimated forward error bound for each solution vector
00077 *          X(j) (the j-th column of the solution matrix X).
00078 *          If XTRUE is the true solution corresponding to X(j), FERR(j)
00079 *          is an estimated upper bound for the magnitude of the largest
00080 *          element in (X(j) - XTRUE) divided by the magnitude of the
00081 *          largest element in X(j).  The estimate is as reliable as
00082 *          the estimate for RCOND, and is almost always a slight
00083 *          overestimate of the true error.
00084 *
00085 *  BERR    (output) REAL array, dimension (NRHS)
00086 *          The componentwise relative backward error of each solution
00087 *          vector X(j) (i.e., the smallest relative change in
00088 *          any element of A or B that makes X(j) an exact solution).
00089 *
00090 *  WORK    (workspace) COMPLEX array, dimension (2*N)
00091 *
00092 *  RWORK   (workspace) REAL array, dimension (N)
00093 *
00094 *  INFO    (output) INTEGER
00095 *          = 0:  successful exit
00096 *          < 0:  if INFO = -i, the i-th argument had an illegal value
00097 *
00098 *  Internal Parameters
00099 *  ===================
00100 *
00101 *  ITMAX is the maximum number of steps of iterative refinement.
00102 *
00103 *  =====================================================================
00104 *
00105 *     .. Parameters ..
00106       INTEGER            ITMAX
00107       PARAMETER          ( ITMAX = 5 )
00108       REAL               ZERO
00109       PARAMETER          ( ZERO = 0.0E+0 )
00110       COMPLEX            ONE
00111       PARAMETER          ( ONE = ( 1.0E+0, 0.0E+0 ) )
00112       REAL               TWO
00113       PARAMETER          ( TWO = 2.0E+0 )
00114       REAL               THREE
00115       PARAMETER          ( THREE = 3.0E+0 )
00116 *     ..
00117 *     .. Local Scalars ..
00118       LOGICAL            NOTRAN
00119       CHARACTER          TRANSN, TRANST
00120       INTEGER            COUNT, I, J, K, KASE, NZ
00121       REAL               EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK
00122       COMPLEX            ZDUM
00123 *     ..
00124 *     .. Local Arrays ..
00125       INTEGER            ISAVE( 3 )
00126 *     ..
00127 *     .. External Functions ..
00128       LOGICAL            LSAME
00129       REAL               SLAMCH
00130       EXTERNAL           LSAME, SLAMCH
00131 *     ..
00132 *     .. External Subroutines ..
00133       EXTERNAL           CAXPY, CCOPY, CGEMV, CGETRS, CLACN2, XERBLA
00134 *     ..
00135 *     .. Intrinsic Functions ..
00136       INTRINSIC          ABS, AIMAG, MAX, REAL
00137 *     ..
00138 *     .. Statement Functions ..
00139       REAL               CABS1
00140 *     ..
00141 *     .. Statement Function definitions ..
00142       CABS1( ZDUM ) = ABS( REAL( ZDUM ) ) + ABS( AIMAG( ZDUM ) )
00143 *     ..
00144 *     .. Executable Statements ..
00145 *
00146 *     Test the input parameters.
00147 *
00148       INFO = 0
00149       NOTRAN = LSAME( TRANS, 'N' )
00150       IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.
00151      \$    LSAME( TRANS, 'C' ) ) THEN
00152          INFO = -1
00153       ELSE IF( N.LT.0 ) THEN
00154          INFO = -2
00155       ELSE IF( NRHS.LT.0 ) THEN
00156          INFO = -3
00157       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00158          INFO = -5
00159       ELSE IF( LDAF.LT.MAX( 1, N ) ) THEN
00160          INFO = -7
00161       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00162          INFO = -10
00163       ELSE IF( LDX.LT.MAX( 1, N ) ) THEN
00164          INFO = -12
00165       END IF
00166       IF( INFO.NE.0 ) THEN
00167          CALL XERBLA( 'CGERFS', -INFO )
00168          RETURN
00169       END IF
00170 *
00171 *     Quick return if possible
00172 *
00173       IF( N.EQ.0 .OR. NRHS.EQ.0 ) THEN
00174          DO 10 J = 1, NRHS
00175             FERR( J ) = ZERO
00176             BERR( J ) = ZERO
00177    10    CONTINUE
00178          RETURN
00179       END IF
00180 *
00181       IF( NOTRAN ) THEN
00182          TRANSN = 'N'
00183          TRANST = 'C'
00184       ELSE
00185          TRANSN = 'C'
00186          TRANST = 'N'
00187       END IF
00188 *
00189 *     NZ = maximum number of nonzero elements in each row of A, plus 1
00190 *
00191       NZ = N + 1
00192       EPS = SLAMCH( 'Epsilon' )
00193       SAFMIN = SLAMCH( 'Safe minimum' )
00194       SAFE1 = NZ*SAFMIN
00195       SAFE2 = SAFE1 / EPS
00196 *
00197 *     Do for each right hand side
00198 *
00199       DO 140 J = 1, NRHS
00200 *
00201          COUNT = 1
00202          LSTRES = THREE
00203    20    CONTINUE
00204 *
00205 *        Loop until stopping criterion is satisfied.
00206 *
00207 *        Compute residual R = B - op(A) * X,
00208 *        where op(A) = A, A**T, or A**H, depending on TRANS.
00209 *
00210          CALL CCOPY( N, B( 1, J ), 1, WORK, 1 )
00211          CALL CGEMV( TRANS, N, N, -ONE, A, LDA, X( 1, J ), 1, ONE, WORK,
00212      \$               1 )
00213 *
00214 *        Compute componentwise relative backward error from formula
00215 *
00216 *        max(i) ( abs(R(i)) / ( abs(op(A))*abs(X) + abs(B) )(i) )
00217 *
00218 *        where abs(Z) is the componentwise absolute value of the matrix
00219 *        or vector Z.  If the i-th component of the denominator is less
00220 *        than SAFE2, then SAFE1 is added to the i-th components of the
00221 *        numerator and denominator before dividing.
00222 *
00223          DO 30 I = 1, N
00224             RWORK( I ) = CABS1( B( I, J ) )
00225    30    CONTINUE
00226 *
00227 *        Compute abs(op(A))*abs(X) + abs(B).
00228 *
00229          IF( NOTRAN ) THEN
00230             DO 50 K = 1, N
00231                XK = CABS1( X( K, J ) )
00232                DO 40 I = 1, N
00233                   RWORK( I ) = RWORK( I ) + CABS1( A( I, K ) )*XK
00234    40          CONTINUE
00235    50       CONTINUE
00236          ELSE
00237             DO 70 K = 1, N
00238                S = ZERO
00239                DO 60 I = 1, N
00240                   S = S + CABS1( A( I, K ) )*CABS1( X( I, J ) )
00241    60          CONTINUE
00242                RWORK( K ) = RWORK( K ) + S
00243    70       CONTINUE
00244          END IF
00245          S = ZERO
00246          DO 80 I = 1, N
00247             IF( RWORK( I ).GT.SAFE2 ) THEN
00248                S = MAX( S, CABS1( WORK( I ) ) / RWORK( I ) )
00249             ELSE
00250                S = MAX( S, ( CABS1( WORK( I ) )+SAFE1 ) /
00251      \$             ( RWORK( I )+SAFE1 ) )
00252             END IF
00253    80    CONTINUE
00254          BERR( J ) = S
00255 *
00256 *        Test stopping criterion. Continue iterating if
00257 *           1) The residual BERR(J) is larger than machine epsilon, and
00258 *           2) BERR(J) decreased by at least a factor of 2 during the
00259 *              last iteration, and
00260 *           3) At most ITMAX iterations tried.
00261 *
00262          IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.
00263      \$       COUNT.LE.ITMAX ) THEN
00264 *
00265 *           Update solution and try again.
00266 *
00267             CALL CGETRS( TRANS, N, 1, AF, LDAF, IPIV, WORK, N, INFO )
00268             CALL CAXPY( N, ONE, WORK, 1, X( 1, J ), 1 )
00269             LSTRES = BERR( J )
00270             COUNT = COUNT + 1
00271             GO TO 20
00272          END IF
00273 *
00274 *        Bound error from formula
00275 *
00276 *        norm(X - XTRUE) / norm(X) .le. FERR =
00277 *        norm( abs(inv(op(A)))*
00278 *           ( abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) ))) / norm(X)
00279 *
00280 *        where
00281 *          norm(Z) is the magnitude of the largest component of Z
00282 *          inv(op(A)) is the inverse of op(A)
00283 *          abs(Z) is the componentwise absolute value of the matrix or
00284 *             vector Z
00285 *          NZ is the maximum number of nonzeros in any row of A, plus 1
00286 *          EPS is machine epsilon
00287 *
00288 *        The i-th component of abs(R)+NZ*EPS*(abs(op(A))*abs(X)+abs(B))
00289 *        is incremented by SAFE1 if the i-th component of
00290 *        abs(op(A))*abs(X) + abs(B) is less than SAFE2.
00291 *
00292 *        Use CLACN2 to estimate the infinity-norm of the matrix
00293 *           inv(op(A)) * diag(W),
00294 *        where W = abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) )))
00295 *
00296          DO 90 I = 1, N
00297             IF( RWORK( I ).GT.SAFE2 ) THEN
00298                RWORK( I ) = CABS1( WORK( I ) ) + NZ*EPS*RWORK( I )
00299             ELSE
00300                RWORK( I ) = CABS1( WORK( I ) ) + NZ*EPS*RWORK( I ) +
00301      \$                      SAFE1
00302             END IF
00303    90    CONTINUE
00304 *
00305          KASE = 0
00306   100    CONTINUE
00307          CALL CLACN2( N, WORK( N+1 ), WORK, FERR( J ), KASE, ISAVE )
00308          IF( KASE.NE.0 ) THEN
00309             IF( KASE.EQ.1 ) THEN
00310 *
00311 *              Multiply by diag(W)*inv(op(A)**H).
00312 *
00313                CALL CGETRS( TRANST, N, 1, AF, LDAF, IPIV, WORK, N,
00314      \$                      INFO )
00315                DO 110 I = 1, N
00316                   WORK( I ) = RWORK( I )*WORK( I )
00317   110          CONTINUE
00318             ELSE
00319 *
00320 *              Multiply by inv(op(A))*diag(W).
00321 *
00322                DO 120 I = 1, N
00323                   WORK( I ) = RWORK( I )*WORK( I )
00324   120          CONTINUE
00325                CALL CGETRS( TRANSN, N, 1, AF, LDAF, IPIV, WORK, N,
00326      \$                      INFO )
00327             END IF
00328             GO TO 100
00329          END IF
00330 *
00331 *        Normalize error.
00332 *
00333          LSTRES = ZERO
00334          DO 130 I = 1, N
00335             LSTRES = MAX( LSTRES, CABS1( X( I, J ) ) )
00336   130    CONTINUE
00337          IF( LSTRES.NE.ZERO )
00338      \$      FERR( J ) = FERR( J ) / LSTRES
00339 *
00340   140 CONTINUE
00341 *
00342       RETURN
00343 *
00344 *     End of CGERFS
00345 *
00346       END
```