File:  [local] / rpl / lapack / lapack / dptrfs.f
Revision 1.19: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:39:05 2023 UTC (8 months, 3 weeks ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, rpl-4_1_34, HEAD
Première mise à jour de lapack et blas.

    1: *> \brief \b DPTRFS
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download DPTRFS + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dptrfs.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dptrfs.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dptrfs.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DPTRFS( N, NRHS, D, E, DF, EF, B, LDB, X, LDX, FERR,
   22: *                          BERR, WORK, INFO )
   23: *
   24: *       .. Scalar Arguments ..
   25: *       INTEGER            INFO, LDB, LDX, N, NRHS
   26: *       ..
   27: *       .. Array Arguments ..
   28: *       DOUBLE PRECISION   B( LDB, * ), BERR( * ), D( * ), DF( * ),
   29: *      $                   E( * ), EF( * ), FERR( * ), WORK( * ),
   30: *      $                   X( LDX, * )
   31: *       ..
   32: *
   33: *
   34: *> \par Purpose:
   35: *  =============
   36: *>
   37: *> \verbatim
   38: *>
   39: *> DPTRFS improves the computed solution to a system of linear
   40: *> equations when the coefficient matrix is symmetric positive definite
   41: *> and tridiagonal, and provides error bounds and backward error
   42: *> estimates for the solution.
   43: *> \endverbatim
   44: *
   45: *  Arguments:
   46: *  ==========
   47: *
   48: *> \param[in] N
   49: *> \verbatim
   50: *>          N is INTEGER
   51: *>          The order of the matrix A.  N >= 0.
   52: *> \endverbatim
   53: *>
   54: *> \param[in] NRHS
   55: *> \verbatim
   56: *>          NRHS is INTEGER
   57: *>          The number of right hand sides, i.e., the number of columns
   58: *>          of the matrix B.  NRHS >= 0.
   59: *> \endverbatim
   60: *>
   61: *> \param[in] D
   62: *> \verbatim
   63: *>          D is DOUBLE PRECISION array, dimension (N)
   64: *>          The n diagonal elements of the tridiagonal matrix A.
   65: *> \endverbatim
   66: *>
   67: *> \param[in] E
   68: *> \verbatim
   69: *>          E is DOUBLE PRECISION array, dimension (N-1)
   70: *>          The (n-1) subdiagonal elements of the tridiagonal matrix A.
   71: *> \endverbatim
   72: *>
   73: *> \param[in] DF
   74: *> \verbatim
   75: *>          DF is DOUBLE PRECISION array, dimension (N)
   76: *>          The n diagonal elements of the diagonal matrix D from the
   77: *>          factorization computed by DPTTRF.
   78: *> \endverbatim
   79: *>
   80: *> \param[in] EF
   81: *> \verbatim
   82: *>          EF is DOUBLE PRECISION array, dimension (N-1)
   83: *>          The (n-1) subdiagonal elements of the unit bidiagonal factor
   84: *>          L from the factorization computed by DPTTRF.
   85: *> \endverbatim
   86: *>
   87: *> \param[in] B
   88: *> \verbatim
   89: *>          B is DOUBLE PRECISION array, dimension (LDB,NRHS)
   90: *>          The right hand side matrix B.
   91: *> \endverbatim
   92: *>
   93: *> \param[in] LDB
   94: *> \verbatim
   95: *>          LDB is INTEGER
   96: *>          The leading dimension of the array B.  LDB >= max(1,N).
   97: *> \endverbatim
   98: *>
   99: *> \param[in,out] X
  100: *> \verbatim
  101: *>          X is DOUBLE PRECISION array, dimension (LDX,NRHS)
  102: *>          On entry, the solution matrix X, as computed by DPTTRS.
  103: *>          On exit, the improved solution matrix X.
  104: *> \endverbatim
  105: *>
  106: *> \param[in] LDX
  107: *> \verbatim
  108: *>          LDX is INTEGER
  109: *>          The leading dimension of the array X.  LDX >= max(1,N).
  110: *> \endverbatim
  111: *>
  112: *> \param[out] FERR
  113: *> \verbatim
  114: *>          FERR is DOUBLE PRECISION array, dimension (NRHS)
  115: *>          The forward error bound for each solution vector
  116: *>          X(j) (the j-th column of the solution matrix X).
  117: *>          If XTRUE is the true solution corresponding to X(j), FERR(j)
  118: *>          is an estimated upper bound for the magnitude of the largest
  119: *>          element in (X(j) - XTRUE) divided by the magnitude of the
  120: *>          largest element in X(j).
  121: *> \endverbatim
  122: *>
  123: *> \param[out] BERR
  124: *> \verbatim
  125: *>          BERR is DOUBLE PRECISION array, dimension (NRHS)
  126: *>          The componentwise relative backward error of each solution
  127: *>          vector X(j) (i.e., the smallest relative change in
  128: *>          any element of A or B that makes X(j) an exact solution).
  129: *> \endverbatim
  130: *>
  131: *> \param[out] WORK
  132: *> \verbatim
  133: *>          WORK is DOUBLE PRECISION array, dimension (2*N)
  134: *> \endverbatim
  135: *>
  136: *> \param[out] INFO
  137: *> \verbatim
  138: *>          INFO is INTEGER
  139: *>          = 0:  successful exit
  140: *>          < 0:  if INFO = -i, the i-th argument had an illegal value
  141: *> \endverbatim
  142: *
  143: *> \par Internal Parameters:
  144: *  =========================
  145: *>
  146: *> \verbatim
  147: *>  ITMAX is the maximum number of steps of iterative refinement.
  148: *> \endverbatim
  149: *
  150: *  Authors:
  151: *  ========
  152: *
  153: *> \author Univ. of Tennessee
  154: *> \author Univ. of California Berkeley
  155: *> \author Univ. of Colorado Denver
  156: *> \author NAG Ltd.
  157: *
  158: *> \ingroup doublePTcomputational
  159: *
  160: *  =====================================================================
  161:       SUBROUTINE DPTRFS( N, NRHS, D, E, DF, EF, B, LDB, X, LDX, FERR,
  162:      $                   BERR, WORK, INFO )
  163: *
  164: *  -- LAPACK computational routine --
  165: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  166: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  167: *
  168: *     .. Scalar Arguments ..
  169:       INTEGER            INFO, LDB, LDX, N, NRHS
  170: *     ..
  171: *     .. Array Arguments ..
  172:       DOUBLE PRECISION   B( LDB, * ), BERR( * ), D( * ), DF( * ),
  173:      $                   E( * ), EF( * ), FERR( * ), WORK( * ),
  174:      $                   X( LDX, * )
  175: *     ..
  176: *
  177: *  =====================================================================
  178: *
  179: *     .. Parameters ..
  180:       INTEGER            ITMAX
  181:       PARAMETER          ( ITMAX = 5 )
  182:       DOUBLE PRECISION   ZERO
  183:       PARAMETER          ( ZERO = 0.0D+0 )
  184:       DOUBLE PRECISION   ONE
  185:       PARAMETER          ( ONE = 1.0D+0 )
  186:       DOUBLE PRECISION   TWO
  187:       PARAMETER          ( TWO = 2.0D+0 )
  188:       DOUBLE PRECISION   THREE
  189:       PARAMETER          ( THREE = 3.0D+0 )
  190: *     ..
  191: *     .. Local Scalars ..
  192:       INTEGER            COUNT, I, IX, J, NZ
  193:       DOUBLE PRECISION   BI, CX, DX, EPS, EX, LSTRES, S, SAFE1, SAFE2,
  194:      $                   SAFMIN
  195: *     ..
  196: *     .. External Subroutines ..
  197:       EXTERNAL           DAXPY, DPTTRS, XERBLA
  198: *     ..
  199: *     .. Intrinsic Functions ..
  200:       INTRINSIC          ABS, MAX
  201: *     ..
  202: *     .. External Functions ..
  203:       INTEGER            IDAMAX
  204:       DOUBLE PRECISION   DLAMCH
  205:       EXTERNAL           IDAMAX, DLAMCH
  206: *     ..
  207: *     .. Executable Statements ..
  208: *
  209: *     Test the input parameters.
  210: *
  211:       INFO = 0
  212:       IF( N.LT.0 ) THEN
  213:          INFO = -1
  214:       ELSE IF( NRHS.LT.0 ) THEN
  215:          INFO = -2
  216:       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
  217:          INFO = -8
  218:       ELSE IF( LDX.LT.MAX( 1, N ) ) THEN
  219:          INFO = -10
  220:       END IF
  221:       IF( INFO.NE.0 ) THEN
  222:          CALL XERBLA( 'DPTRFS', -INFO )
  223:          RETURN
  224:       END IF
  225: *
  226: *     Quick return if possible
  227: *
  228:       IF( N.EQ.0 .OR. NRHS.EQ.0 ) THEN
  229:          DO 10 J = 1, NRHS
  230:             FERR( J ) = ZERO
  231:             BERR( J ) = ZERO
  232:    10    CONTINUE
  233:          RETURN
  234:       END IF
  235: *
  236: *     NZ = maximum number of nonzero elements in each row of A, plus 1
  237: *
  238:       NZ = 4
  239:       EPS = DLAMCH( 'Epsilon' )
  240:       SAFMIN = DLAMCH( 'Safe minimum' )
  241:       SAFE1 = NZ*SAFMIN
  242:       SAFE2 = SAFE1 / EPS
  243: *
  244: *     Do for each right hand side
  245: *
  246:       DO 90 J = 1, NRHS
  247: *
  248:          COUNT = 1
  249:          LSTRES = THREE
  250:    20    CONTINUE
  251: *
  252: *        Loop until stopping criterion is satisfied.
  253: *
  254: *        Compute residual R = B - A * X.  Also compute
  255: *        abs(A)*abs(x) + abs(b) for use in the backward error bound.
  256: *
  257:          IF( N.EQ.1 ) THEN
  258:             BI = B( 1, J )
  259:             DX = D( 1 )*X( 1, J )
  260:             WORK( N+1 ) = BI - DX
  261:             WORK( 1 ) = ABS( BI ) + ABS( DX )
  262:          ELSE
  263:             BI = B( 1, J )
  264:             DX = D( 1 )*X( 1, J )
  265:             EX = E( 1 )*X( 2, J )
  266:             WORK( N+1 ) = BI - DX - EX
  267:             WORK( 1 ) = ABS( BI ) + ABS( DX ) + ABS( EX )
  268:             DO 30 I = 2, N - 1
  269:                BI = B( I, J )
  270:                CX = E( I-1 )*X( I-1, J )
  271:                DX = D( I )*X( I, J )
  272:                EX = E( I )*X( I+1, J )
  273:                WORK( N+I ) = BI - CX - DX - EX
  274:                WORK( I ) = ABS( BI ) + ABS( CX ) + ABS( DX ) + ABS( EX )
  275:    30       CONTINUE
  276:             BI = B( N, J )
  277:             CX = E( N-1 )*X( N-1, J )
  278:             DX = D( N )*X( N, J )
  279:             WORK( N+N ) = BI - CX - DX
  280:             WORK( N ) = ABS( BI ) + ABS( CX ) + ABS( DX )
  281:          END IF
  282: *
  283: *        Compute componentwise relative backward error from formula
  284: *
  285: *        max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )
  286: *
  287: *        where abs(Z) is the componentwise absolute value of the matrix
  288: *        or vector Z.  If the i-th component of the denominator is less
  289: *        than SAFE2, then SAFE1 is added to the i-th components of the
  290: *        numerator and denominator before dividing.
  291: *
  292:          S = ZERO
  293:          DO 40 I = 1, N
  294:             IF( WORK( I ).GT.SAFE2 ) THEN
  295:                S = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )
  296:             ELSE
  297:                S = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /
  298:      $             ( WORK( I )+SAFE1 ) )
  299:             END IF
  300:    40    CONTINUE
  301:          BERR( J ) = S
  302: *
  303: *        Test stopping criterion. Continue iterating if
  304: *           1) The residual BERR(J) is larger than machine epsilon, and
  305: *           2) BERR(J) decreased by at least a factor of 2 during the
  306: *              last iteration, and
  307: *           3) At most ITMAX iterations tried.
  308: *
  309:          IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.
  310:      $       COUNT.LE.ITMAX ) THEN
  311: *
  312: *           Update solution and try again.
  313: *
  314:             CALL DPTTRS( N, 1, DF, EF, WORK( N+1 ), N, INFO )
  315:             CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )
  316:             LSTRES = BERR( J )
  317:             COUNT = COUNT + 1
  318:             GO TO 20
  319:          END IF
  320: *
  321: *        Bound error from formula
  322: *
  323: *        norm(X - XTRUE) / norm(X) .le. FERR =
  324: *        norm( abs(inv(A))*
  325: *           ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)
  326: *
  327: *        where
  328: *          norm(Z) is the magnitude of the largest component of Z
  329: *          inv(A) is the inverse of A
  330: *          abs(Z) is the componentwise absolute value of the matrix or
  331: *             vector Z
  332: *          NZ is the maximum number of nonzeros in any row of A, plus 1
  333: *          EPS is machine epsilon
  334: *
  335: *        The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))
  336: *        is incremented by SAFE1 if the i-th component of
  337: *        abs(A)*abs(X) + abs(B) is less than SAFE2.
  338: *
  339:          DO 50 I = 1, N
  340:             IF( WORK( I ).GT.SAFE2 ) THEN
  341:                WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )
  342:             ELSE
  343:                WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1
  344:             END IF
  345:    50    CONTINUE
  346:          IX = IDAMAX( N, WORK, 1 )
  347:          FERR( J ) = WORK( IX )
  348: *
  349: *        Estimate the norm of inv(A).
  350: *
  351: *        Solve M(A) * x = e, where M(A) = (m(i,j)) is given by
  352: *
  353: *           m(i,j) =  abs(A(i,j)), i = j,
  354: *           m(i,j) = -abs(A(i,j)), i .ne. j,
  355: *
  356: *        and e = [ 1, 1, ..., 1 ]**T.  Note M(A) = M(L)*D*M(L)**T.
  357: *
  358: *        Solve M(L) * x = e.
  359: *
  360:          WORK( 1 ) = ONE
  361:          DO 60 I = 2, N
  362:             WORK( I ) = ONE + WORK( I-1 )*ABS( EF( I-1 ) )
  363:    60    CONTINUE
  364: *
  365: *        Solve D * M(L)**T * x = b.
  366: *
  367:          WORK( N ) = WORK( N ) / DF( N )
  368:          DO 70 I = N - 1, 1, -1
  369:             WORK( I ) = WORK( I ) / DF( I ) + WORK( I+1 )*ABS( EF( I ) )
  370:    70    CONTINUE
  371: *
  372: *        Compute norm(inv(A)) = max(x(i)), 1<=i<=n.
  373: *
  374:          IX = IDAMAX( N, WORK, 1 )
  375:          FERR( J ) = FERR( J )*ABS( WORK( IX ) )
  376: *
  377: *        Normalize error.
  378: *
  379:          LSTRES = ZERO
  380:          DO 80 I = 1, N
  381:             LSTRES = MAX( LSTRES, ABS( X( I, J ) ) )
  382:    80    CONTINUE
  383:          IF( LSTRES.NE.ZERO )
  384:      $      FERR( J ) = FERR( J ) / LSTRES
  385: *
  386:    90 CONTINUE
  387: *
  388:       RETURN
  389: *
  390: *     End of DPTRFS
  391: *
  392:       END

CVSweb interface <joel.bertrand@systella.fr>