File:  [local] / rpl / lapack / lapack / dpstrf.f
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Sat Aug 7 13:21:06 2010 UTC (13 years, 9 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Ajout des nouveaux fichiers pour Lapack 3.2.2.

    1:       SUBROUTINE DPSTRF( UPLO, N, A, LDA, PIV, RANK, TOL, WORK, INFO )
    2: *
    3: *  -- LAPACK routine (version 3.2.2) --
    4: *     Craig Lucas, University of Manchester / NAG Ltd.
    5: *     October, 2008  
    6: *
    7: *     .. Scalar Arguments ..
    8:       DOUBLE PRECISION   TOL
    9:       INTEGER            INFO, LDA, N, RANK
   10:       CHARACTER          UPLO
   11: *     ..
   12: *     .. Array Arguments ..
   13:       DOUBLE PRECISION   A( LDA, * ), WORK( 2*N )
   14:       INTEGER            PIV( N )
   15: *     ..
   16: *
   17: *  Purpose
   18: *  =======
   19: *
   20: *  DPSTRF computes the Cholesky factorization with complete
   21: *  pivoting of a real symmetric positive semidefinite matrix A.
   22: *
   23: *  The factorization has the form
   24: *     P' * A * P = U' * U ,  if UPLO = 'U',
   25: *     P' * A * P = L  * L',  if UPLO = 'L',
   26: *  where U is an upper triangular matrix and L is lower triangular, and
   27: *  P is stored as vector PIV.
   28: *
   29: *  This algorithm does not attempt to check that A is positive
   30: *  semidefinite. This version of the algorithm calls level 3 BLAS.
   31: *
   32: *  Arguments
   33: *  =========
   34: *
   35: *  UPLO    (input) CHARACTER*1
   36: *          Specifies whether the upper or lower triangular part of the
   37: *          symmetric matrix A is stored.
   38: *          = 'U':  Upper triangular
   39: *          = 'L':  Lower triangular
   40: *
   41: *  N       (input) INTEGER
   42: *          The order of the matrix A.  N >= 0.
   43: *
   44: *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
   45: *          On entry, the symmetric matrix A.  If UPLO = 'U', the leading
   46: *          n by n upper triangular part of A contains the upper
   47: *          triangular part of the matrix A, and the strictly lower
   48: *          triangular part of A is not referenced.  If UPLO = 'L', the
   49: *          leading n by n lower triangular part of A contains the lower
   50: *          triangular part of the matrix A, and the strictly upper
   51: *          triangular part of A is not referenced.
   52: *
   53: *          On exit, if INFO = 0, the factor U or L from the Cholesky
   54: *          factorization as above.
   55: *
   56: *  LDA     (input) INTEGER
   57: *          The leading dimension of the array A.  LDA >= max(1,N).
   58: *
   59: *  PIV     (output) INTEGER array, dimension (N)
   60: *          PIV is such that the nonzero entries are P( PIV(K), K ) = 1.
   61: *
   62: *  RANK    (output) INTEGER
   63: *          The rank of A given by the number of steps the algorithm
   64: *          completed.
   65: *
   66: *  TOL     (input) DOUBLE PRECISION
   67: *          User defined tolerance. If TOL < 0, then N*U*MAX( A(K,K) )
   68: *          will be used. The algorithm terminates at the (K-1)st step
   69: *          if the pivot <= TOL.
   70: *
   71: *  WORK    (workspace) DOUBLE PRECISION array, dimension (2*N)
   72: *          Work space.
   73: *
   74: *  INFO    (output) INTEGER
   75: *          < 0: If INFO = -K, the K-th argument had an illegal value,
   76: *          = 0: algorithm completed successfully, and
   77: *          > 0: the matrix A is either rank deficient with computed rank
   78: *               as returned in RANK, or is indefinite.  See Section 7 of
   79: *               LAPACK Working Note #161 for further information.
   80: *
   81: *  =====================================================================
   82: *
   83: *     .. Parameters ..
   84:       DOUBLE PRECISION   ONE, ZERO
   85:       PARAMETER          ( ONE = 1.0D+0, ZERO = 0.0D+0 )
   86: *     ..
   87: *     .. Local Scalars ..
   88:       DOUBLE PRECISION   AJJ, DSTOP, DTEMP
   89:       INTEGER            I, ITEMP, J, JB, K, NB, PVT
   90:       LOGICAL            UPPER
   91: *     ..
   92: *     .. External Functions ..
   93:       DOUBLE PRECISION   DLAMCH
   94:       INTEGER            ILAENV
   95:       LOGICAL            LSAME, DISNAN
   96:       EXTERNAL           DLAMCH, ILAENV, LSAME, DISNAN
   97: *     ..
   98: *     .. External Subroutines ..
   99:       EXTERNAL           DGEMV, DPSTF2, DSCAL, DSWAP, DSYRK, XERBLA
  100: *     ..
  101: *     .. Intrinsic Functions ..
  102:       INTRINSIC          MAX, MIN, SQRT, MAXLOC
  103: *     ..
  104: *     .. Executable Statements ..
  105: *
  106: *     Test the input parameters.
  107: *
  108:       INFO = 0
  109:       UPPER = LSAME( UPLO, 'U' )
  110:       IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
  111:          INFO = -1
  112:       ELSE IF( N.LT.0 ) THEN
  113:          INFO = -2
  114:       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
  115:          INFO = -4
  116:       END IF
  117:       IF( INFO.NE.0 ) THEN
  118:          CALL XERBLA( 'DPSTRF', -INFO )
  119:          RETURN
  120:       END IF
  121: *
  122: *     Quick return if possible
  123: *
  124:       IF( N.EQ.0 )
  125:      $   RETURN
  126: *
  127: *     Get block size
  128: *
  129:       NB = ILAENV( 1, 'DPOTRF', UPLO, N, -1, -1, -1 )
  130:       IF( NB.LE.1 .OR. NB.GE.N ) THEN
  131: *
  132: *        Use unblocked code
  133: *
  134:          CALL DPSTF2( UPLO, N, A( 1, 1 ), LDA, PIV, RANK, TOL, WORK,
  135:      $                INFO )
  136:          GO TO 200
  137: *
  138:       ELSE
  139: *
  140: *     Initialize PIV
  141: *
  142:          DO 100 I = 1, N
  143:             PIV( I ) = I
  144:   100    CONTINUE
  145: *
  146: *     Compute stopping value
  147: *
  148:          PVT = 1
  149:          AJJ = A( PVT, PVT )
  150:          DO I = 2, N
  151:             IF( A( I, I ).GT.AJJ ) THEN
  152:                PVT = I
  153:                AJJ = A( PVT, PVT )
  154:             END IF
  155:          END DO
  156:          IF( AJJ.EQ.ZERO.OR.DISNAN( AJJ ) ) THEN
  157:             RANK = 0
  158:             INFO = 1
  159:             GO TO 200
  160:          END IF
  161: *
  162: *     Compute stopping value if not supplied
  163: *
  164:          IF( TOL.LT.ZERO ) THEN
  165:             DSTOP = N * DLAMCH( 'Epsilon' ) * AJJ
  166:          ELSE
  167:             DSTOP = TOL
  168:          END IF
  169: *
  170: *
  171:          IF( UPPER ) THEN
  172: *
  173: *           Compute the Cholesky factorization P' * A * P = U' * U
  174: *
  175:             DO 140 K = 1, N, NB
  176: *
  177: *              Account for last block not being NB wide
  178: *
  179:                JB = MIN( NB, N-K+1 )
  180: *
  181: *              Set relevant part of first half of WORK to zero,
  182: *              holds dot products
  183: *
  184:                DO 110 I = K, N
  185:                   WORK( I ) = 0
  186:   110          CONTINUE
  187: *
  188:                DO 130 J = K, K + JB - 1
  189: *
  190: *              Find pivot, test for exit, else swap rows and columns
  191: *              Update dot products, compute possible pivots which are
  192: *              stored in the second half of WORK
  193: *
  194:                   DO 120 I = J, N
  195: *
  196:                      IF( J.GT.K ) THEN
  197:                         WORK( I ) = WORK( I ) + A( J-1, I )**2
  198:                      END IF
  199:                      WORK( N+I ) = A( I, I ) - WORK( I )
  200: *
  201:   120             CONTINUE
  202: *
  203:                   IF( J.GT.1 ) THEN
  204:                      ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 )
  205:                      PVT = ITEMP + J - 1
  206:                      AJJ = WORK( N+PVT )
  207:                      IF( AJJ.LE.DSTOP.OR.DISNAN( AJJ ) ) THEN
  208:                         A( J, J ) = AJJ
  209:                         GO TO 190
  210:                      END IF
  211:                   END IF
  212: *
  213:                   IF( J.NE.PVT ) THEN
  214: *
  215: *                    Pivot OK, so can now swap pivot rows and columns
  216: *
  217:                      A( PVT, PVT ) = A( J, J )
  218:                      CALL DSWAP( J-1, A( 1, J ), 1, A( 1, PVT ), 1 )
  219:                      IF( PVT.LT.N )
  220:      $                  CALL DSWAP( N-PVT, A( J, PVT+1 ), LDA,
  221:      $                              A( PVT, PVT+1 ), LDA )
  222:                      CALL DSWAP( PVT-J-1, A( J, J+1 ), LDA,
  223:      $                           A( J+1, PVT ), 1 )
  224: *
  225: *                    Swap dot products and PIV
  226: *
  227:                      DTEMP = WORK( J )
  228:                      WORK( J ) = WORK( PVT )
  229:                      WORK( PVT ) = DTEMP
  230:                      ITEMP = PIV( PVT )
  231:                      PIV( PVT ) = PIV( J )
  232:                      PIV( J ) = ITEMP
  233:                   END IF
  234: *
  235:                   AJJ = SQRT( AJJ )
  236:                   A( J, J ) = AJJ
  237: *
  238: *                 Compute elements J+1:N of row J.
  239: *
  240:                   IF( J.LT.N ) THEN
  241:                      CALL DGEMV( 'Trans', J-K, N-J, -ONE, A( K, J+1 ),
  242:      $                           LDA, A( K, J ), 1, ONE, A( J, J+1 ),
  243:      $                           LDA )
  244:                      CALL DSCAL( N-J, ONE / AJJ, A( J, J+1 ), LDA )
  245:                   END IF
  246: *
  247:   130          CONTINUE
  248: *
  249: *              Update trailing matrix, J already incremented
  250: *
  251:                IF( K+JB.LE.N ) THEN
  252:                   CALL DSYRK( 'Upper', 'Trans', N-J+1, JB, -ONE,
  253:      $                        A( K, J ), LDA, ONE, A( J, J ), LDA )
  254:                END IF
  255: *
  256:   140       CONTINUE
  257: *
  258:          ELSE
  259: *
  260: *        Compute the Cholesky factorization P' * A * P = L * L'
  261: *
  262:             DO 180 K = 1, N, NB
  263: *
  264: *              Account for last block not being NB wide
  265: *
  266:                JB = MIN( NB, N-K+1 )
  267: *
  268: *              Set relevant part of first half of WORK to zero,
  269: *              holds dot products
  270: *
  271:                DO 150 I = K, N
  272:                   WORK( I ) = 0
  273:   150          CONTINUE
  274: *
  275:                DO 170 J = K, K + JB - 1
  276: *
  277: *              Find pivot, test for exit, else swap rows and columns
  278: *              Update dot products, compute possible pivots which are
  279: *              stored in the second half of WORK
  280: *
  281:                   DO 160 I = J, N
  282: *
  283:                      IF( J.GT.K ) THEN
  284:                         WORK( I ) = WORK( I ) + A( I, J-1 )**2
  285:                      END IF
  286:                      WORK( N+I ) = A( I, I ) - WORK( I )
  287: *
  288:   160             CONTINUE
  289: *
  290:                   IF( J.GT.1 ) THEN
  291:                      ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 )
  292:                      PVT = ITEMP + J - 1
  293:                      AJJ = WORK( N+PVT )
  294:                      IF( AJJ.LE.DSTOP.OR.DISNAN( AJJ ) ) THEN
  295:                         A( J, J ) = AJJ
  296:                         GO TO 190
  297:                      END IF
  298:                   END IF
  299: *
  300:                   IF( J.NE.PVT ) THEN
  301: *
  302: *                    Pivot OK, so can now swap pivot rows and columns
  303: *
  304:                      A( PVT, PVT ) = A( J, J )
  305:                      CALL DSWAP( J-1, A( J, 1 ), LDA, A( PVT, 1 ), LDA )
  306:                      IF( PVT.LT.N )
  307:      $                  CALL DSWAP( N-PVT, A( PVT+1, J ), 1,
  308:      $                              A( PVT+1, PVT ), 1 )
  309:                      CALL DSWAP( PVT-J-1, A( J+1, J ), 1, A( PVT, J+1 ),
  310:      $                           LDA )
  311: *
  312: *                    Swap dot products and PIV
  313: *
  314:                      DTEMP = WORK( J )
  315:                      WORK( J ) = WORK( PVT )
  316:                      WORK( PVT ) = DTEMP
  317:                      ITEMP = PIV( PVT )
  318:                      PIV( PVT ) = PIV( J )
  319:                      PIV( J ) = ITEMP
  320:                   END IF
  321: *
  322:                   AJJ = SQRT( AJJ )
  323:                   A( J, J ) = AJJ
  324: *
  325: *                 Compute elements J+1:N of column J.
  326: *
  327:                   IF( J.LT.N ) THEN
  328:                      CALL DGEMV( 'No Trans', N-J, J-K, -ONE,
  329:      $                           A( J+1, K ), LDA, A( J, K ), LDA, ONE,
  330:      $                           A( J+1, J ), 1 )
  331:                      CALL DSCAL( N-J, ONE / AJJ, A( J+1, J ), 1 )
  332:                   END IF
  333: *
  334:   170          CONTINUE
  335: *
  336: *              Update trailing matrix, J already incremented
  337: *
  338:                IF( K+JB.LE.N ) THEN
  339:                   CALL DSYRK( 'Lower', 'No Trans', N-J+1, JB, -ONE,
  340:      $                        A( J, K ), LDA, ONE, A( J, J ), LDA )
  341:                END IF
  342: *
  343:   180       CONTINUE
  344: *
  345:          END IF
  346:       END IF
  347: *
  348: *     Ran to completion, A has full rank
  349: *
  350:       RANK = N
  351: *
  352:       GO TO 200
  353:   190 CONTINUE
  354: *
  355: *     Rank is the number of steps completed.  Set INFO = 1 to signal
  356: *     that the factorization cannot be used to solve a system.
  357: *
  358:       RANK = J - 1
  359:       INFO = 1
  360: *
  361:   200 CONTINUE
  362:       RETURN
  363: *
  364: *     End of DPSTRF
  365: *
  366:       END

CVSweb interface <joel.bertrand@systella.fr>