File:  [local] / rpl / lapack / lapack / dsytrf_rk.f
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:39:11 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 DSYTRF_RK computes the factorization of a real symmetric indefinite matrix using the bounded Bunch-Kaufman (rook) diagonal pivoting method (BLAS3 blocked algorithm).
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download DSYTRF_RK + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dsytrf_rk.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dsytrf_rk.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytrf_rk.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DSYTRF_RK( UPLO, N, A, LDA, E, IPIV, WORK, LWORK,
   22: *                             INFO )
   23: *
   24: *       .. Scalar Arguments ..
   25: *       CHARACTER          UPLO
   26: *       INTEGER            INFO, LDA, LWORK, N
   27: *       ..
   28: *       .. Array Arguments ..
   29: *       INTEGER            IPIV( * )
   30: *       DOUBLE PRECISION   A( LDA, * ), E ( * ), WORK( * )
   31: *       ..
   32: *
   33: *
   34: *> \par Purpose:
   35: *  =============
   36: *>
   37: *> \verbatim
   38: *> DSYTRF_RK computes the factorization of a real symmetric matrix A
   39: *> using the bounded Bunch-Kaufman (rook) diagonal pivoting method:
   40: *>
   41: *>    A = P*U*D*(U**T)*(P**T) or A = P*L*D*(L**T)*(P**T),
   42: *>
   43: *> where U (or L) is unit upper (or lower) triangular matrix,
   44: *> U**T (or L**T) is the transpose of U (or L), P is a permutation
   45: *> matrix, P**T is the transpose of P, and D is symmetric and block
   46: *> diagonal with 1-by-1 and 2-by-2 diagonal blocks.
   47: *>
   48: *> This is the blocked version of the algorithm, calling Level 3 BLAS.
   49: *> For more information see Further Details section.
   50: *> \endverbatim
   51: *
   52: *  Arguments:
   53: *  ==========
   54: *
   55: *> \param[in] UPLO
   56: *> \verbatim
   57: *>          UPLO is CHARACTER*1
   58: *>          Specifies whether the upper or lower triangular part of the
   59: *>          symmetric matrix A is stored:
   60: *>          = 'U':  Upper triangular
   61: *>          = 'L':  Lower triangular
   62: *> \endverbatim
   63: *>
   64: *> \param[in] N
   65: *> \verbatim
   66: *>          N is INTEGER
   67: *>          The order of the matrix A.  N >= 0.
   68: *> \endverbatim
   69: *>
   70: *> \param[in,out] A
   71: *> \verbatim
   72: *>          A is DOUBLE PRECISION array, dimension (LDA,N)
   73: *>          On entry, the symmetric matrix A.
   74: *>            If UPLO = 'U': the leading N-by-N upper triangular part
   75: *>            of A contains the upper triangular part of the matrix A,
   76: *>            and the strictly lower triangular part of A is not
   77: *>            referenced.
   78: *>
   79: *>            If UPLO = 'L': the leading N-by-N lower triangular part
   80: *>            of A contains the lower triangular part of the matrix A,
   81: *>            and the strictly upper triangular part of A is not
   82: *>            referenced.
   83: *>
   84: *>          On exit, contains:
   85: *>            a) ONLY diagonal elements of the symmetric block diagonal
   86: *>               matrix D on the diagonal of A, i.e. D(k,k) = A(k,k);
   87: *>               (superdiagonal (or subdiagonal) elements of D
   88: *>                are stored on exit in array E), and
   89: *>            b) If UPLO = 'U': factor U in the superdiagonal part of A.
   90: *>               If UPLO = 'L': factor L in the subdiagonal part of A.
   91: *> \endverbatim
   92: *>
   93: *> \param[in] LDA
   94: *> \verbatim
   95: *>          LDA is INTEGER
   96: *>          The leading dimension of the array A.  LDA >= max(1,N).
   97: *> \endverbatim
   98: *>
   99: *> \param[out] E
  100: *> \verbatim
  101: *>          E is DOUBLE PRECISION array, dimension (N)
  102: *>          On exit, contains the superdiagonal (or subdiagonal)
  103: *>          elements of the symmetric block diagonal matrix D
  104: *>          with 1-by-1 or 2-by-2 diagonal blocks, where
  105: *>          If UPLO = 'U': E(i) = D(i-1,i), i=2:N, E(1) is set to 0;
  106: *>          If UPLO = 'L': E(i) = D(i+1,i), i=1:N-1, E(N) is set to 0.
  107: *>
  108: *>          NOTE: For 1-by-1 diagonal block D(k), where
  109: *>          1 <= k <= N, the element E(k) is set to 0 in both
  110: *>          UPLO = 'U' or UPLO = 'L' cases.
  111: *> \endverbatim
  112: *>
  113: *> \param[out] IPIV
  114: *> \verbatim
  115: *>          IPIV is INTEGER array, dimension (N)
  116: *>          IPIV describes the permutation matrix P in the factorization
  117: *>          of matrix A as follows. The absolute value of IPIV(k)
  118: *>          represents the index of row and column that were
  119: *>          interchanged with the k-th row and column. The value of UPLO
  120: *>          describes the order in which the interchanges were applied.
  121: *>          Also, the sign of IPIV represents the block structure of
  122: *>          the symmetric block diagonal matrix D with 1-by-1 or 2-by-2
  123: *>          diagonal blocks which correspond to 1 or 2 interchanges
  124: *>          at each factorization step. For more info see Further
  125: *>          Details section.
  126: *>
  127: *>          If UPLO = 'U',
  128: *>          ( in factorization order, k decreases from N to 1 ):
  129: *>            a) A single positive entry IPIV(k) > 0 means:
  130: *>               D(k,k) is a 1-by-1 diagonal block.
  131: *>               If IPIV(k) != k, rows and columns k and IPIV(k) were
  132: *>               interchanged in the matrix A(1:N,1:N);
  133: *>               If IPIV(k) = k, no interchange occurred.
  134: *>
  135: *>            b) A pair of consecutive negative entries
  136: *>               IPIV(k) < 0 and IPIV(k-1) < 0 means:
  137: *>               D(k-1:k,k-1:k) is a 2-by-2 diagonal block.
  138: *>               (NOTE: negative entries in IPIV appear ONLY in pairs).
  139: *>               1) If -IPIV(k) != k, rows and columns
  140: *>                  k and -IPIV(k) were interchanged
  141: *>                  in the matrix A(1:N,1:N).
  142: *>                  If -IPIV(k) = k, no interchange occurred.
  143: *>               2) If -IPIV(k-1) != k-1, rows and columns
  144: *>                  k-1 and -IPIV(k-1) were interchanged
  145: *>                  in the matrix A(1:N,1:N).
  146: *>                  If -IPIV(k-1) = k-1, no interchange occurred.
  147: *>
  148: *>            c) In both cases a) and b), always ABS( IPIV(k) ) <= k.
  149: *>
  150: *>            d) NOTE: Any entry IPIV(k) is always NONZERO on output.
  151: *>
  152: *>          If UPLO = 'L',
  153: *>          ( in factorization order, k increases from 1 to N ):
  154: *>            a) A single positive entry IPIV(k) > 0 means:
  155: *>               D(k,k) is a 1-by-1 diagonal block.
  156: *>               If IPIV(k) != k, rows and columns k and IPIV(k) were
  157: *>               interchanged in the matrix A(1:N,1:N).
  158: *>               If IPIV(k) = k, no interchange occurred.
  159: *>
  160: *>            b) A pair of consecutive negative entries
  161: *>               IPIV(k) < 0 and IPIV(k+1) < 0 means:
  162: *>               D(k:k+1,k:k+1) is a 2-by-2 diagonal block.
  163: *>               (NOTE: negative entries in IPIV appear ONLY in pairs).
  164: *>               1) If -IPIV(k) != k, rows and columns
  165: *>                  k and -IPIV(k) were interchanged
  166: *>                  in the matrix A(1:N,1:N).
  167: *>                  If -IPIV(k) = k, no interchange occurred.
  168: *>               2) If -IPIV(k+1) != k+1, rows and columns
  169: *>                  k-1 and -IPIV(k-1) were interchanged
  170: *>                  in the matrix A(1:N,1:N).
  171: *>                  If -IPIV(k+1) = k+1, no interchange occurred.
  172: *>
  173: *>            c) In both cases a) and b), always ABS( IPIV(k) ) >= k.
  174: *>
  175: *>            d) NOTE: Any entry IPIV(k) is always NONZERO on output.
  176: *> \endverbatim
  177: *>
  178: *> \param[out] WORK
  179: *> \verbatim
  180: *>          WORK is DOUBLE PRECISION array, dimension ( MAX(1,LWORK) ).
  181: *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  182: *> \endverbatim
  183: *>
  184: *> \param[in] LWORK
  185: *> \verbatim
  186: *>          LWORK is INTEGER
  187: *>          The length of WORK.  LWORK >=1.  For best performance
  188: *>          LWORK >= N*NB, where NB is the block size returned
  189: *>          by ILAENV.
  190: *>
  191: *>          If LWORK = -1, then a workspace query is assumed;
  192: *>          the routine only calculates the optimal size of the WORK
  193: *>          array, returns this value as the first entry of the WORK
  194: *>          array, and no error message related to LWORK is issued
  195: *>          by XERBLA.
  196: *> \endverbatim
  197: *>
  198: *> \param[out] INFO
  199: *> \verbatim
  200: *>          INFO is INTEGER
  201: *>          = 0: successful exit
  202: *>
  203: *>          < 0: If INFO = -k, the k-th argument had an illegal value
  204: *>
  205: *>          > 0: If INFO = k, the matrix A is singular, because:
  206: *>                 If UPLO = 'U': column k in the upper
  207: *>                 triangular part of A contains all zeros.
  208: *>                 If UPLO = 'L': column k in the lower
  209: *>                 triangular part of A contains all zeros.
  210: *>
  211: *>               Therefore D(k,k) is exactly zero, and superdiagonal
  212: *>               elements of column k of U (or subdiagonal elements of
  213: *>               column k of L ) are all zeros. The factorization has
  214: *>               been completed, but the block diagonal matrix D is
  215: *>               exactly singular, and division by zero will occur if
  216: *>               it is used to solve a system of equations.
  217: *>
  218: *>               NOTE: INFO only stores the first occurrence of
  219: *>               a singularity, any subsequent occurrence of singularity
  220: *>               is not stored in INFO even though the factorization
  221: *>               always completes.
  222: *> \endverbatim
  223: *
  224: *  Authors:
  225: *  ========
  226: *
  227: *> \author Univ. of Tennessee
  228: *> \author Univ. of California Berkeley
  229: *> \author Univ. of Colorado Denver
  230: *> \author NAG Ltd.
  231: *
  232: *> \ingroup doubleSYcomputational
  233: *
  234: *> \par Further Details:
  235: *  =====================
  236: *>
  237: *> \verbatim
  238: *> TODO: put correct description
  239: *> \endverbatim
  240: *
  241: *> \par Contributors:
  242: *  ==================
  243: *>
  244: *> \verbatim
  245: *>
  246: *>  December 2016,  Igor Kozachenko,
  247: *>                  Computer Science Division,
  248: *>                  University of California, Berkeley
  249: *>
  250: *>  September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
  251: *>                  School of Mathematics,
  252: *>                  University of Manchester
  253: *>
  254: *> \endverbatim
  255: *
  256: *  =====================================================================
  257:       SUBROUTINE DSYTRF_RK( UPLO, N, A, LDA, E, IPIV, WORK, LWORK,
  258:      $                      INFO )
  259: *
  260: *  -- LAPACK computational routine --
  261: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  262: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  263: *
  264: *     .. Scalar Arguments ..
  265:       CHARACTER          UPLO
  266:       INTEGER            INFO, LDA, LWORK, N
  267: *     ..
  268: *     .. Array Arguments ..
  269:       INTEGER            IPIV( * )
  270:       DOUBLE PRECISION   A( LDA, * ), E( * ), WORK( * )
  271: *     ..
  272: *
  273: *  =====================================================================
  274: *
  275: *     .. Local Scalars ..
  276:       LOGICAL            LQUERY, UPPER
  277:       INTEGER            I, IINFO, IP, IWS, K, KB, LDWORK, LWKOPT,
  278:      $                   NB, NBMIN
  279: *     ..
  280: *     .. External Functions ..
  281:       LOGICAL            LSAME
  282:       INTEGER            ILAENV
  283:       EXTERNAL           LSAME, ILAENV
  284: *     ..
  285: *     .. External Subroutines ..
  286:       EXTERNAL           DLASYF_RK, DSYTF2_RK, DSWAP, XERBLA
  287: *     ..
  288: *     .. Intrinsic Functions ..
  289:       INTRINSIC          ABS, MAX
  290: *     ..
  291: *     .. Executable Statements ..
  292: *
  293: *     Test the input parameters.
  294: *
  295:       INFO = 0
  296:       UPPER = LSAME( UPLO, 'U' )
  297:       LQUERY = ( LWORK.EQ.-1 )
  298:       IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
  299:          INFO = -1
  300:       ELSE IF( N.LT.0 ) THEN
  301:          INFO = -2
  302:       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
  303:          INFO = -4
  304:       ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THEN
  305:          INFO = -8
  306:       END IF
  307: *
  308:       IF( INFO.EQ.0 ) THEN
  309: *
  310: *        Determine the block size
  311: *
  312:          NB = ILAENV( 1, 'DSYTRF_RK', UPLO, N, -1, -1, -1 )
  313:          LWKOPT = N*NB
  314:          WORK( 1 ) = LWKOPT
  315:       END IF
  316: *
  317:       IF( INFO.NE.0 ) THEN
  318:          CALL XERBLA( 'DSYTRF_RK', -INFO )
  319:          RETURN
  320:       ELSE IF( LQUERY ) THEN
  321:          RETURN
  322:       END IF
  323: *
  324:       NBMIN = 2
  325:       LDWORK = N
  326:       IF( NB.GT.1 .AND. NB.LT.N ) THEN
  327:          IWS = LDWORK*NB
  328:          IF( LWORK.LT.IWS ) THEN
  329:             NB = MAX( LWORK / LDWORK, 1 )
  330:             NBMIN = MAX( 2, ILAENV( 2, 'DSYTRF_RK',
  331:      $                              UPLO, N, -1, -1, -1 ) )
  332:          END IF
  333:       ELSE
  334:          IWS = 1
  335:       END IF
  336:       IF( NB.LT.NBMIN )
  337:      $   NB = N
  338: *
  339:       IF( UPPER ) THEN
  340: *
  341: *        Factorize A as U*D*U**T using the upper triangle of A
  342: *
  343: *        K is the main loop index, decreasing from N to 1 in steps of
  344: *        KB, where KB is the number of columns factorized by DLASYF_RK;
  345: *        KB is either NB or NB-1, or K for the last block
  346: *
  347:          K = N
  348:    10    CONTINUE
  349: *
  350: *        If K < 1, exit from loop
  351: *
  352:          IF( K.LT.1 )
  353:      $      GO TO 15
  354: *
  355:          IF( K.GT.NB ) THEN
  356: *
  357: *           Factorize columns k-kb+1:k of A and use blocked code to
  358: *           update columns 1:k-kb
  359: *
  360:             CALL DLASYF_RK( UPLO, K, NB, KB, A, LDA, E,
  361:      $                      IPIV, WORK, LDWORK, IINFO )
  362:          ELSE
  363: *
  364: *           Use unblocked code to factorize columns 1:k of A
  365: *
  366:             CALL DSYTF2_RK( UPLO, K, A, LDA, E, IPIV, IINFO )
  367:             KB = K
  368:          END IF
  369: *
  370: *        Set INFO on the first occurrence of a zero pivot
  371: *
  372:          IF( INFO.EQ.0 .AND. IINFO.GT.0 )
  373:      $      INFO = IINFO
  374: *
  375: *        No need to adjust IPIV
  376: *
  377: *
  378: *        Apply permutations to the leading panel 1:k-1
  379: *
  380: *        Read IPIV from the last block factored, i.e.
  381: *        indices  k-kb+1:k and apply row permutations to the
  382: *        last k+1 colunms k+1:N after that block
  383: *        (We can do the simple loop over IPIV with decrement -1,
  384: *        since the ABS value of IPIV( I ) represents the row index
  385: *        of the interchange with row i in both 1x1 and 2x2 pivot cases)
  386: *
  387:          IF( K.LT.N ) THEN
  388:             DO I = K, ( K - KB + 1 ), -1
  389:                IP = ABS( IPIV( I ) )
  390:                IF( IP.NE.I ) THEN
  391:                   CALL DSWAP( N-K, A( I, K+1 ), LDA,
  392:      $                        A( IP, K+1 ), LDA )
  393:                END IF
  394:             END DO
  395:          END IF
  396: *
  397: *        Decrease K and return to the start of the main loop
  398: *
  399:          K = K - KB
  400:          GO TO 10
  401: *
  402: *        This label is the exit from main loop over K decreasing
  403: *        from N to 1 in steps of KB
  404: *
  405:    15    CONTINUE
  406: *
  407:       ELSE
  408: *
  409: *        Factorize A as L*D*L**T using the lower triangle of A
  410: *
  411: *        K is the main loop index, increasing from 1 to N in steps of
  412: *        KB, where KB is the number of columns factorized by DLASYF_RK;
  413: *        KB is either NB or NB-1, or N-K+1 for the last block
  414: *
  415:          K = 1
  416:    20    CONTINUE
  417: *
  418: *        If K > N, exit from loop
  419: *
  420:          IF( K.GT.N )
  421:      $      GO TO 35
  422: *
  423:          IF( K.LE.N-NB ) THEN
  424: *
  425: *           Factorize columns k:k+kb-1 of A and use blocked code to
  426: *           update columns k+kb:n
  427: *
  428:             CALL DLASYF_RK( UPLO, N-K+1, NB, KB, A( K, K ), LDA, E( K ),
  429:      $                        IPIV( K ), WORK, LDWORK, IINFO )
  430: 
  431: 
  432:          ELSE
  433: *
  434: *           Use unblocked code to factorize columns k:n of A
  435: *
  436:             CALL DSYTF2_RK( UPLO, N-K+1, A( K, K ), LDA, E( K ),
  437:      $                      IPIV( K ), IINFO )
  438:             KB = N - K + 1
  439: *
  440:          END IF
  441: *
  442: *        Set INFO on the first occurrence of a zero pivot
  443: *
  444:          IF( INFO.EQ.0 .AND. IINFO.GT.0 )
  445:      $      INFO = IINFO + K - 1
  446: *
  447: *        Adjust IPIV
  448: *
  449:          DO I = K, K + KB - 1
  450:             IF( IPIV( I ).GT.0 ) THEN
  451:                IPIV( I ) = IPIV( I ) + K - 1
  452:             ELSE
  453:                IPIV( I ) = IPIV( I ) - K + 1
  454:             END IF
  455:          END DO
  456: *
  457: *        Apply permutations to the leading panel 1:k-1
  458: *
  459: *        Read IPIV from the last block factored, i.e.
  460: *        indices  k:k+kb-1 and apply row permutations to the
  461: *        first k-1 colunms 1:k-1 before that block
  462: *        (We can do the simple loop over IPIV with increment 1,
  463: *        since the ABS value of IPIV( I ) represents the row index
  464: *        of the interchange with row i in both 1x1 and 2x2 pivot cases)
  465: *
  466:          IF( K.GT.1 ) THEN
  467:             DO I = K, ( K + KB - 1 ), 1
  468:                IP = ABS( IPIV( I ) )
  469:                IF( IP.NE.I ) THEN
  470:                   CALL DSWAP( K-1, A( I, 1 ), LDA,
  471:      $                        A( IP, 1 ), LDA )
  472:                END IF
  473:             END DO
  474:          END IF
  475: *
  476: *        Increase K and return to the start of the main loop
  477: *
  478:          K = K + KB
  479:          GO TO 20
  480: *
  481: *        This label is the exit from main loop over K increasing
  482: *        from 1 to N in steps of KB
  483: *
  484:    35    CONTINUE
  485: *
  486: *     End Lower
  487: *
  488:       END IF
  489: *
  490:       WORK( 1 ) = LWKOPT
  491:       RETURN
  492: *
  493: *     End of DSYTRF_RK
  494: *
  495:       END

CVSweb interface <joel.bertrand@systella.fr>