File:  [local] / rpl / lapack / lapack / zhetf2_rook.f
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Sat Jun 17 11:06:48 2017 UTC (6 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_27, rpl-4_1_26, HEAD
Cohérence.

    1: *> \brief \b ZHETF2_ROOK computes the factorization of a complex Hermitian indefinite matrix using the bounded Bunch-Kaufman ("rook") diagonal pivoting method (unblocked algorithm).
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download ZHETF2_ROOK + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zhetf2_rook.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zhetf2_rook.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetf2_rook.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE ZHETF2_ROOK( UPLO, N, A, LDA, IPIV, INFO )
   22: *
   23: *       .. Scalar Arguments ..
   24: *       CHARACTER          UPLO
   25: *       INTEGER            INFO, LDA, N
   26: *       ..
   27: *       .. Array Arguments ..
   28: *       INTEGER            IPIV( * )
   29: *       COMPLEX*16            A( LDA, * )
   30: *       ..
   31: *
   32: *
   33: *> \par Purpose:
   34: *  =============
   35: *>
   36: *> \verbatim
   37: *>
   38: *> ZHETF2_ROOK computes the factorization of a complex Hermitian matrix A
   39: *> using the bounded Bunch-Kaufman ("rook") diagonal pivoting method:
   40: *>
   41: *>    A = U*D*U**H  or  A = L*D*L**H
   42: *>
   43: *> where U (or L) is a product of permutation and unit upper (lower)
   44: *> triangular matrices, U**H is the conjugate transpose of U, and D is
   45: *> Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks.
   46: *>
   47: *> This is the unblocked version of the algorithm, calling Level 2 BLAS.
   48: *> \endverbatim
   49: *
   50: *  Arguments:
   51: *  ==========
   52: *
   53: *> \param[in] UPLO
   54: *> \verbatim
   55: *>          UPLO is CHARACTER*1
   56: *>          Specifies whether the upper or lower triangular part of the
   57: *>          Hermitian matrix A is stored:
   58: *>          = 'U':  Upper triangular
   59: *>          = 'L':  Lower triangular
   60: *> \endverbatim
   61: *>
   62: *> \param[in] N
   63: *> \verbatim
   64: *>          N is INTEGER
   65: *>          The order of the matrix A.  N >= 0.
   66: *> \endverbatim
   67: *>
   68: *> \param[in,out] A
   69: *> \verbatim
   70: *>          A is COMPLEX*16 array, dimension (LDA,N)
   71: *>          On entry, the Hermitian matrix A.  If UPLO = 'U', the leading
   72: *>          n-by-n upper triangular part of A contains the upper
   73: *>          triangular part of the matrix A, and the strictly lower
   74: *>          triangular part of A is not referenced.  If UPLO = 'L', the
   75: *>          leading n-by-n lower triangular part of A contains the lower
   76: *>          triangular part of the matrix A, and the strictly upper
   77: *>          triangular part of A is not referenced.
   78: *>
   79: *>          On exit, the block diagonal matrix D and the multipliers used
   80: *>          to obtain the factor U or L (see below for further details).
   81: *> \endverbatim
   82: *>
   83: *> \param[in] LDA
   84: *> \verbatim
   85: *>          LDA is INTEGER
   86: *>          The leading dimension of the array A.  LDA >= max(1,N).
   87: *> \endverbatim
   88: *>
   89: *> \param[out] IPIV
   90: *> \verbatim
   91: *>          IPIV is INTEGER array, dimension (N)
   92: *>          Details of the interchanges and the block structure of D.
   93: *>
   94: *>          If UPLO = 'U':
   95: *>             If IPIV(k) > 0, then rows and columns k and IPIV(k) were
   96: *>             interchanged and D(k,k) is a 1-by-1 diagonal block.
   97: *>
   98: *>             If IPIV(k) < 0 and IPIV(k-1) < 0, then rows and
   99: *>             columns k and -IPIV(k) were interchanged and rows and
  100: *>             columns k-1 and -IPIV(k-1) were inerchaged,
  101: *>             D(k-1:k,k-1:k) is a 2-by-2 diagonal block.
  102: *>
  103: *>          If UPLO = 'L':
  104: *>             If IPIV(k) > 0, then rows and columns k and IPIV(k)
  105: *>             were interchanged and D(k,k) is a 1-by-1 diagonal block.
  106: *>
  107: *>             If IPIV(k) < 0 and IPIV(k+1) < 0, then rows and
  108: *>             columns k and -IPIV(k) were interchanged and rows and
  109: *>             columns k+1 and -IPIV(k+1) were inerchaged,
  110: *>             D(k:k+1,k:k+1) is a 2-by-2 diagonal block.
  111: *> \endverbatim
  112: *>
  113: *> \param[out] INFO
  114: *> \verbatim
  115: *>          INFO is INTEGER
  116: *>          = 0: successful exit
  117: *>          < 0: if INFO = -k, the k-th argument had an illegal value
  118: *>          > 0: if INFO = k, D(k,k) is exactly zero.  The factorization
  119: *>               has been completed, but the block diagonal matrix D is
  120: *>               exactly singular, and division by zero will occur if it
  121: *>               is used to solve a system of equations.
  122: *> \endverbatim
  123: *
  124: *  Authors:
  125: *  ========
  126: *
  127: *> \author Univ. of Tennessee
  128: *> \author Univ. of California Berkeley
  129: *> \author Univ. of Colorado Denver
  130: *> \author NAG Ltd.
  131: *
  132: *> \date November 2013
  133: *
  134: *> \ingroup complex16HEcomputational
  135: *
  136: *> \par Further Details:
  137: *  =====================
  138: *>
  139: *> \verbatim
  140: *>
  141: *>  If UPLO = 'U', then A = U*D*U**H, where
  142: *>     U = P(n)*U(n)* ... *P(k)U(k)* ...,
  143: *>  i.e., U is a product of terms P(k)*U(k), where k decreases from n to
  144: *>  1 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
  145: *>  and 2-by-2 diagonal blocks D(k).  P(k) is a permutation matrix as
  146: *>  defined by IPIV(k), and U(k) is a unit upper triangular matrix, such
  147: *>  that if the diagonal block D(k) is of order s (s = 1 or 2), then
  148: *>
  149: *>             (   I    v    0   )   k-s
  150: *>     U(k) =  (   0    I    0   )   s
  151: *>             (   0    0    I   )   n-k
  152: *>                k-s   s   n-k
  153: *>
  154: *>  If s = 1, D(k) overwrites A(k,k), and v overwrites A(1:k-1,k).
  155: *>  If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k),
  156: *>  and A(k,k), and v overwrites A(1:k-2,k-1:k).
  157: *>
  158: *>  If UPLO = 'L', then A = L*D*L**H, where
  159: *>     L = P(1)*L(1)* ... *P(k)*L(k)* ...,
  160: *>  i.e., L is a product of terms P(k)*L(k), where k increases from 1 to
  161: *>  n in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
  162: *>  and 2-by-2 diagonal blocks D(k).  P(k) is a permutation matrix as
  163: *>  defined by IPIV(k), and L(k) is a unit lower triangular matrix, such
  164: *>  that if the diagonal block D(k) is of order s (s = 1 or 2), then
  165: *>
  166: *>             (   I    0     0   )  k-1
  167: *>     L(k) =  (   0    I     0   )  s
  168: *>             (   0    v     I   )  n-k-s+1
  169: *>                k-1   s  n-k-s+1
  170: *>
  171: *>  If s = 1, D(k) overwrites A(k,k), and v overwrites A(k+1:n,k).
  172: *>  If s = 2, the lower triangle of D(k) overwrites A(k,k), A(k+1,k),
  173: *>  and A(k+1,k+1), and v overwrites A(k+2:n,k:k+1).
  174: *> \endverbatim
  175: *
  176: *> \par Contributors:
  177: *  ==================
  178: *>
  179: *> \verbatim
  180: *>
  181: *>  November 2013,  Igor Kozachenko,
  182: *>                  Computer Science Division,
  183: *>                  University of California, Berkeley
  184: *>
  185: *>  September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
  186: *>                  School of Mathematics,
  187: *>                  University of Manchester
  188: *>
  189: *>  01-01-96 - Based on modifications by
  190: *>    J. Lewis, Boeing Computer Services Company
  191: *>    A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA
  192: *> \endverbatim
  193: *
  194: *  =====================================================================
  195:       SUBROUTINE ZHETF2_ROOK( UPLO, N, A, LDA, IPIV, INFO )
  196: *
  197: *  -- LAPACK computational routine (version 3.5.0) --
  198: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  199: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  200: *     November 2013
  201: *
  202: *     .. Scalar Arguments ..
  203:       CHARACTER          UPLO
  204:       INTEGER            INFO, LDA, N
  205: *     ..
  206: *     .. Array Arguments ..
  207:       INTEGER            IPIV( * )
  208:       COMPLEX*16         A( LDA, * )
  209: *     ..
  210: *
  211: *  ======================================================================
  212: *
  213: *     .. Parameters ..
  214:       DOUBLE PRECISION   ZERO, ONE
  215:       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
  216:       DOUBLE PRECISION   EIGHT, SEVTEN
  217:       PARAMETER          ( EIGHT = 8.0D+0, SEVTEN = 17.0D+0 )
  218: *     ..
  219: *     .. Local Scalars ..
  220:       LOGICAL            DONE, UPPER
  221:       INTEGER            I, II, IMAX, ITEMP, J, JMAX, K, KK, KP, KSTEP,
  222:      $                   P
  223:       DOUBLE PRECISION   ABSAKK, ALPHA, COLMAX, D, D11, D22, R1, DTEMP,
  224:      $                   ROWMAX, TT, SFMIN
  225:       COMPLEX*16         D12, D21, T, WK, WKM1, WKP1, Z
  226: *     ..
  227: *     .. External Functions ..
  228: *
  229:       LOGICAL            LSAME
  230:       INTEGER            IZAMAX
  231:       DOUBLE PRECISION   DLAMCH, DLAPY2
  232:       EXTERNAL           LSAME, IZAMAX, DLAMCH, DLAPY2
  233: *     ..
  234: *     .. External Subroutines ..
  235:       EXTERNAL           XERBLA, ZDSCAL, ZHER, ZSWAP
  236: *     ..
  237: *     .. Intrinsic Functions ..
  238:       INTRINSIC          ABS, DBLE, DCMPLX, DCONJG, DIMAG, MAX, SQRT
  239: *     ..
  240: *     .. Statement Functions ..
  241:       DOUBLE PRECISION   CABS1
  242: *     ..
  243: *     .. Statement Function definitions ..
  244:       CABS1( Z ) = ABS( DBLE( Z ) ) + ABS( DIMAG( Z ) )
  245: *     ..
  246: *     .. Executable Statements ..
  247: *
  248: *     Test the input parameters.
  249: *
  250:       INFO = 0
  251:       UPPER = LSAME( UPLO, 'U' )
  252:       IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
  253:          INFO = -1
  254:       ELSE IF( N.LT.0 ) THEN
  255:          INFO = -2
  256:       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
  257:          INFO = -4
  258:       END IF
  259:       IF( INFO.NE.0 ) THEN
  260:          CALL XERBLA( 'ZHETF2_ROOK', -INFO )
  261:          RETURN
  262:       END IF
  263: *
  264: *     Initialize ALPHA for use in choosing pivot block size.
  265: *
  266:       ALPHA = ( ONE+SQRT( SEVTEN ) ) / EIGHT
  267: *
  268: *     Compute machine safe minimum
  269: *
  270:       SFMIN = DLAMCH( 'S' )
  271: *
  272:       IF( UPPER ) THEN
  273: *
  274: *        Factorize A as U*D*U**H using the upper triangle of A
  275: *
  276: *        K is the main loop index, decreasing from N to 1 in steps of
  277: *        1 or 2
  278: *
  279:          K = N
  280:    10    CONTINUE
  281: *
  282: *        If K < 1, exit from loop
  283: *
  284:          IF( K.LT.1 )
  285:      $      GO TO 70
  286:          KSTEP = 1
  287:          P = K
  288: *
  289: *        Determine rows and columns to be interchanged and whether
  290: *        a 1-by-1 or 2-by-2 pivot block will be used
  291: *
  292:          ABSAKK = ABS( DBLE( A( K, K ) ) )
  293: *
  294: *        IMAX is the row-index of the largest off-diagonal element in
  295: *        column K, and COLMAX is its absolute value.
  296: *        Determine both COLMAX and IMAX.
  297: *
  298:          IF( K.GT.1 ) THEN
  299:             IMAX = IZAMAX( K-1, A( 1, K ), 1 )
  300:             COLMAX = CABS1( A( IMAX, K ) )
  301:          ELSE
  302:             COLMAX = ZERO
  303:          END IF
  304: *
  305:          IF( ( MAX( ABSAKK, COLMAX ).EQ.ZERO ) ) THEN
  306: *
  307: *           Column K is zero or underflow: set INFO and continue
  308: *
  309:             IF( INFO.EQ.0 )
  310:      $         INFO = K
  311:             KP = K
  312:             A( K, K ) = DBLE( A( K, K ) )
  313:          ELSE
  314: *
  315: *           ============================================================
  316: *
  317: *           BEGIN pivot search
  318: *
  319: *           Case(1)
  320: *           Equivalent to testing for ABSAKK.GE.ALPHA*COLMAX
  321: *           (used to handle NaN and Inf)
  322: *
  323:             IF( .NOT.( ABSAKK.LT.ALPHA*COLMAX ) ) THEN
  324: *
  325: *              no interchange, use 1-by-1 pivot block
  326: *
  327:                KP = K
  328: *
  329:             ELSE
  330: *
  331:                DONE = .FALSE.
  332: *
  333: *              Loop until pivot found
  334: *
  335:    12          CONTINUE
  336: *
  337: *                 BEGIN pivot search loop body
  338: *
  339: *
  340: *                 JMAX is the column-index of the largest off-diagonal
  341: *                 element in row IMAX, and ROWMAX is its absolute value.
  342: *                 Determine both ROWMAX and JMAX.
  343: *
  344:                   IF( IMAX.NE.K ) THEN
  345:                      JMAX = IMAX + IZAMAX( K-IMAX, A( IMAX, IMAX+1 ),
  346:      $                                     LDA )
  347:                      ROWMAX = CABS1( A( IMAX, JMAX ) )
  348:                   ELSE
  349:                      ROWMAX = ZERO
  350:                   END IF
  351: *
  352:                   IF( IMAX.GT.1 ) THEN
  353:                      ITEMP = IZAMAX( IMAX-1, A( 1, IMAX ), 1 )
  354:                      DTEMP = CABS1( A( ITEMP, IMAX ) )
  355:                      IF( DTEMP.GT.ROWMAX ) THEN
  356:                         ROWMAX = DTEMP
  357:                         JMAX = ITEMP
  358:                      END IF
  359:                   END IF
  360: *
  361: *                 Case(2)
  362: *                 Equivalent to testing for
  363: *                 ABS( REAL( W( IMAX,KW-1 ) ) ).GE.ALPHA*ROWMAX
  364: *                 (used to handle NaN and Inf)
  365: *
  366:                   IF( .NOT.( ABS( DBLE( A( IMAX, IMAX ) ) )
  367:      $                       .LT.ALPHA*ROWMAX ) ) THEN
  368: *
  369: *                    interchange rows and columns K and IMAX,
  370: *                    use 1-by-1 pivot block
  371: *
  372:                      KP = IMAX
  373:                      DONE = .TRUE.
  374: *
  375: *                 Case(3)
  376: *                 Equivalent to testing for ROWMAX.EQ.COLMAX,
  377: *                 (used to handle NaN and Inf)
  378: *
  379:                   ELSE IF( ( P.EQ.JMAX ) .OR. ( ROWMAX.LE.COLMAX ) )
  380:      $            THEN
  381: *
  382: *                    interchange rows and columns K-1 and IMAX,
  383: *                    use 2-by-2 pivot block
  384: *
  385:                      KP = IMAX
  386:                      KSTEP = 2
  387:                      DONE = .TRUE.
  388: *
  389: *                 Case(4)
  390:                   ELSE
  391: *
  392: *                    Pivot not found: set params and repeat
  393: *
  394:                      P = IMAX
  395:                      COLMAX = ROWMAX
  396:                      IMAX = JMAX
  397:                   END IF
  398: *
  399: *                 END pivot search loop body
  400: *
  401:                IF( .NOT.DONE ) GOTO 12
  402: *
  403:             END IF
  404: *
  405: *           END pivot search
  406: *
  407: *           ============================================================
  408: *
  409: *           KK is the column of A where pivoting step stopped
  410: *
  411:             KK = K - KSTEP + 1
  412: *
  413: *           For only a 2x2 pivot, interchange rows and columns K and P
  414: *           in the leading submatrix A(1:k,1:k)
  415: *
  416:             IF( ( KSTEP.EQ.2 ) .AND. ( P.NE.K ) ) THEN
  417: *              (1) Swap columnar parts
  418:                IF( P.GT.1 )
  419:      $            CALL ZSWAP( P-1, A( 1, K ), 1, A( 1, P ), 1 )
  420: *              (2) Swap and conjugate middle parts
  421:                DO 14 J = P + 1, K - 1
  422:                   T = DCONJG( A( J, K ) )
  423:                   A( J, K ) = DCONJG( A( P, J ) )
  424:                   A( P, J ) = T
  425:    14          CONTINUE
  426: *              (3) Swap and conjugate corner elements at row-col interserction
  427:                A( P, K ) = DCONJG( A( P, K ) )
  428: *              (4) Swap diagonal elements at row-col intersection
  429:                R1 = DBLE( A( K, K ) )
  430:                A( K, K ) = DBLE( A( P, P ) )
  431:                A( P, P ) = R1
  432:             END IF
  433: *
  434: *           For both 1x1 and 2x2 pivots, interchange rows and
  435: *           columns KK and KP in the leading submatrix A(1:k,1:k)
  436: *
  437:             IF( KP.NE.KK ) THEN
  438: *              (1) Swap columnar parts
  439:                IF( KP.GT.1 )
  440:      $            CALL ZSWAP( KP-1, A( 1, KK ), 1, A( 1, KP ), 1 )
  441: *              (2) Swap and conjugate middle parts
  442:                DO 15 J = KP + 1, KK - 1
  443:                   T = DCONJG( A( J, KK ) )
  444:                   A( J, KK ) = DCONJG( A( KP, J ) )
  445:                   A( KP, J ) = T
  446:    15          CONTINUE
  447: *              (3) Swap and conjugate corner elements at row-col interserction
  448:                A( KP, KK ) = DCONJG( A( KP, KK ) )
  449: *              (4) Swap diagonal elements at row-col intersection
  450:                R1 = DBLE( A( KK, KK ) )
  451:                A( KK, KK ) = DBLE( A( KP, KP ) )
  452:                A( KP, KP ) = R1
  453: *
  454:                IF( KSTEP.EQ.2 ) THEN
  455: *                 (*) Make sure that diagonal element of pivot is real
  456:                   A( K, K ) = DBLE( A( K, K ) )
  457: *                 (5) Swap row elements
  458:                   T = A( K-1, K )
  459:                   A( K-1, K ) = A( KP, K )
  460:                   A( KP, K ) = T
  461:                END IF
  462:             ELSE
  463: *              (*) Make sure that diagonal element of pivot is real
  464:                A( K, K ) = DBLE( A( K, K ) )
  465:                IF( KSTEP.EQ.2 )
  466:      $            A( K-1, K-1 ) = DBLE( A( K-1, K-1 ) )
  467:             END IF
  468: *
  469: *           Update the leading submatrix
  470: *
  471:             IF( KSTEP.EQ.1 ) THEN
  472: *
  473: *              1-by-1 pivot block D(k): column k now holds
  474: *
  475: *              W(k) = U(k)*D(k)
  476: *
  477: *              where U(k) is the k-th column of U
  478: *
  479:                IF( K.GT.1 ) THEN
  480: *
  481: *                 Perform a rank-1 update of A(1:k-1,1:k-1) and
  482: *                 store U(k) in column k
  483: *
  484:                   IF( ABS( DBLE( A( K, K ) ) ).GE.SFMIN ) THEN
  485: *
  486: *                    Perform a rank-1 update of A(1:k-1,1:k-1) as
  487: *                    A := A - U(k)*D(k)*U(k)**T
  488: *                       = A - W(k)*1/D(k)*W(k)**T
  489: *
  490:                      D11 = ONE / DBLE( A( K, K ) )
  491:                      CALL ZHER( UPLO, K-1, -D11, A( 1, K ), 1, A, LDA )
  492: *
  493: *                    Store U(k) in column k
  494: *
  495:                      CALL ZDSCAL( K-1, D11, A( 1, K ), 1 )
  496:                   ELSE
  497: *
  498: *                    Store L(k) in column K
  499: *
  500:                      D11 = DBLE( A( K, K ) )
  501:                      DO 16 II = 1, K - 1
  502:                         A( II, K ) = A( II, K ) / D11
  503:    16                CONTINUE
  504: *
  505: *                    Perform a rank-1 update of A(k+1:n,k+1:n) as
  506: *                    A := A - U(k)*D(k)*U(k)**T
  507: *                       = A - W(k)*(1/D(k))*W(k)**T
  508: *                       = A - (W(k)/D(k))*(D(k))*(W(k)/D(K))**T
  509: *
  510:                      CALL ZHER( UPLO, K-1, -D11, A( 1, K ), 1, A, LDA )
  511:                   END IF
  512:                END IF
  513: *
  514:             ELSE
  515: *
  516: *              2-by-2 pivot block D(k): columns k and k-1 now hold
  517: *
  518: *              ( W(k-1) W(k) ) = ( U(k-1) U(k) )*D(k)
  519: *
  520: *              where U(k) and U(k-1) are the k-th and (k-1)-th columns
  521: *              of U
  522: *
  523: *              Perform a rank-2 update of A(1:k-2,1:k-2) as
  524: *
  525: *              A := A - ( U(k-1) U(k) )*D(k)*( U(k-1) U(k) )**T
  526: *                 = A - ( ( A(k-1)A(k) )*inv(D(k)) ) * ( A(k-1)A(k) )**T
  527: *
  528: *              and store L(k) and L(k+1) in columns k and k+1
  529: *
  530:                IF( K.GT.2 ) THEN
  531: *                 D = |A12|
  532:                   D = DLAPY2( DBLE( A( K-1, K ) ),
  533:      $                DIMAG( A( K-1, K ) ) )
  534:                   D11 = A( K, K ) / D
  535:                   D22 = A( K-1, K-1 ) / D
  536:                   D12 = A( K-1, K ) / D
  537:                   TT = ONE / ( D11*D22-ONE )
  538: *
  539:                   DO 30 J = K - 2, 1, -1
  540: *
  541: *                    Compute  D21 * ( W(k)W(k+1) ) * inv(D(k)) for row J
  542: *
  543:                      WKM1 = TT*( D11*A( J, K-1 )-DCONJG( D12 )*
  544:      $                      A( J, K ) )
  545:                      WK = TT*( D22*A( J, K )-D12*A( J, K-1 ) )
  546: *
  547: *                    Perform a rank-2 update of A(1:k-2,1:k-2)
  548: *
  549:                      DO 20 I = J, 1, -1
  550:                         A( I, J ) = A( I, J ) -
  551:      $                              ( A( I, K ) / D )*DCONJG( WK ) -
  552:      $                              ( A( I, K-1 ) / D )*DCONJG( WKM1 )
  553:    20                CONTINUE
  554: *
  555: *                    Store U(k) and U(k-1) in cols k and k-1 for row J
  556: *
  557:                      A( J, K ) = WK / D
  558:                      A( J, K-1 ) = WKM1 / D
  559: *                    (*) Make sure that diagonal element of pivot is real
  560:                      A( J, J ) = DCMPLX( DBLE( A( J, J ) ), ZERO )
  561: *
  562:    30             CONTINUE
  563: *
  564:                END IF
  565: *
  566:             END IF
  567: *
  568:          END IF
  569: *
  570: *        Store details of the interchanges in IPIV
  571: *
  572:          IF( KSTEP.EQ.1 ) THEN
  573:             IPIV( K ) = KP
  574:          ELSE
  575:             IPIV( K ) = -P
  576:             IPIV( K-1 ) = -KP
  577:          END IF
  578: *
  579: *        Decrease K and return to the start of the main loop
  580: *
  581:          K = K - KSTEP
  582:          GO TO 10
  583: *
  584:       ELSE
  585: *
  586: *        Factorize A as L*D*L**H using the lower triangle of A
  587: *
  588: *        K is the main loop index, increasing from 1 to N in steps of
  589: *        1 or 2
  590: *
  591:          K = 1
  592:    40    CONTINUE
  593: *
  594: *        If K > N, exit from loop
  595: *
  596:          IF( K.GT.N )
  597:      $      GO TO 70
  598:          KSTEP = 1
  599:          P = K
  600: *
  601: *        Determine rows and columns to be interchanged and whether
  602: *        a 1-by-1 or 2-by-2 pivot block will be used
  603: *
  604:          ABSAKK = ABS( DBLE( A( K, K ) ) )
  605: *
  606: *        IMAX is the row-index of the largest off-diagonal element in
  607: *        column K, and COLMAX is its absolute value.
  608: *        Determine both COLMAX and IMAX.
  609: *
  610:          IF( K.LT.N ) THEN
  611:             IMAX = K + IZAMAX( N-K, A( K+1, K ), 1 )
  612:             COLMAX = CABS1( A( IMAX, K ) )
  613:          ELSE
  614:             COLMAX = ZERO
  615:          END IF
  616: *
  617:          IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
  618: *
  619: *           Column K is zero or underflow: set INFO and continue
  620: *
  621:             IF( INFO.EQ.0 )
  622:      $         INFO = K
  623:             KP = K
  624:             A( K, K ) = DBLE( A( K, K ) )
  625:          ELSE
  626: *
  627: *           ============================================================
  628: *
  629: *           BEGIN pivot search
  630: *
  631: *           Case(1)
  632: *           Equivalent to testing for ABSAKK.GE.ALPHA*COLMAX
  633: *           (used to handle NaN and Inf)
  634: *
  635:             IF( .NOT.( ABSAKK.LT.ALPHA*COLMAX ) ) THEN
  636: *
  637: *              no interchange, use 1-by-1 pivot block
  638: *
  639:                KP = K
  640: *
  641:             ELSE
  642: *
  643:                DONE = .FALSE.
  644: *
  645: *              Loop until pivot found
  646: *
  647:    42          CONTINUE
  648: *
  649: *                 BEGIN pivot search loop body
  650: *
  651: *
  652: *                 JMAX is the column-index of the largest off-diagonal
  653: *                 element in row IMAX, and ROWMAX is its absolute value.
  654: *                 Determine both ROWMAX and JMAX.
  655: *
  656:                   IF( IMAX.NE.K ) THEN
  657:                      JMAX = K - 1 + IZAMAX( IMAX-K, A( IMAX, K ), LDA )
  658:                      ROWMAX = CABS1( A( IMAX, JMAX ) )
  659:                   ELSE
  660:                      ROWMAX = ZERO
  661:                   END IF
  662: *
  663:                   IF( IMAX.LT.N ) THEN
  664:                      ITEMP = IMAX + IZAMAX( N-IMAX, A( IMAX+1, IMAX ),
  665:      $                                     1 )
  666:                      DTEMP = CABS1( A( ITEMP, IMAX ) )
  667:                      IF( DTEMP.GT.ROWMAX ) THEN
  668:                         ROWMAX = DTEMP
  669:                         JMAX = ITEMP
  670:                      END IF
  671:                   END IF
  672: *
  673: *                 Case(2)
  674: *                 Equivalent to testing for
  675: *                 ABS( REAL( W( IMAX,KW-1 ) ) ).GE.ALPHA*ROWMAX
  676: *                 (used to handle NaN and Inf)
  677: *
  678:                   IF( .NOT.( ABS( DBLE( A( IMAX, IMAX ) ) )
  679:      $                       .LT.ALPHA*ROWMAX ) ) THEN
  680: *
  681: *                    interchange rows and columns K and IMAX,
  682: *                    use 1-by-1 pivot block
  683: *
  684:                      KP = IMAX
  685:                      DONE = .TRUE.
  686: *
  687: *                 Case(3)
  688: *                 Equivalent to testing for ROWMAX.EQ.COLMAX,
  689: *                 (used to handle NaN and Inf)
  690: *
  691:                   ELSE IF( ( P.EQ.JMAX ) .OR. ( ROWMAX.LE.COLMAX ) )
  692:      $            THEN
  693: *
  694: *                    interchange rows and columns K+1 and IMAX,
  695: *                    use 2-by-2 pivot block
  696: *
  697:                      KP = IMAX
  698:                      KSTEP = 2
  699:                      DONE = .TRUE.
  700: *
  701: *                 Case(4)
  702:                   ELSE
  703: *
  704: *                    Pivot not found: set params and repeat
  705: *
  706:                      P = IMAX
  707:                      COLMAX = ROWMAX
  708:                      IMAX = JMAX
  709:                   END IF
  710: *
  711: *
  712: *                 END pivot search loop body
  713: *
  714:                IF( .NOT.DONE ) GOTO 42
  715: *
  716:             END IF
  717: *
  718: *           END pivot search
  719: *
  720: *           ============================================================
  721: *
  722: *           KK is the column of A where pivoting step stopped
  723: *
  724:             KK = K + KSTEP - 1
  725: *
  726: *           For only a 2x2 pivot, interchange rows and columns K and P
  727: *           in the trailing submatrix A(k:n,k:n)
  728: *
  729:             IF( ( KSTEP.EQ.2 ) .AND. ( P.NE.K ) ) THEN
  730: *              (1) Swap columnar parts
  731:                IF( P.LT.N )
  732:      $            CALL ZSWAP( N-P, A( P+1, K ), 1, A( P+1, P ), 1 )
  733: *              (2) Swap and conjugate middle parts
  734:                DO 44 J = K + 1, P - 1
  735:                   T = DCONJG( A( J, K ) )
  736:                   A( J, K ) = DCONJG( A( P, J ) )
  737:                   A( P, J ) = T
  738:    44          CONTINUE
  739: *              (3) Swap and conjugate corner elements at row-col interserction
  740:                A( P, K ) = DCONJG( A( P, K ) )
  741: *              (4) Swap diagonal elements at row-col intersection
  742:                R1 = DBLE( A( K, K ) )
  743:                A( K, K ) = DBLE( A( P, P ) )
  744:                A( P, P ) = R1
  745:             END IF
  746: *
  747: *           For both 1x1 and 2x2 pivots, interchange rows and
  748: *           columns KK and KP in the trailing submatrix A(k:n,k:n)
  749: *
  750:             IF( KP.NE.KK ) THEN
  751: *              (1) Swap columnar parts
  752:                IF( KP.LT.N )
  753:      $            CALL ZSWAP( N-KP, A( KP+1, KK ), 1, A( KP+1, KP ), 1 )
  754: *              (2) Swap and conjugate middle parts
  755:                DO 45 J = KK + 1, KP - 1
  756:                   T = DCONJG( A( J, KK ) )
  757:                   A( J, KK ) = DCONJG( A( KP, J ) )
  758:                   A( KP, J ) = T
  759:    45          CONTINUE
  760: *              (3) Swap and conjugate corner elements at row-col interserction
  761:                A( KP, KK ) = DCONJG( A( KP, KK ) )
  762: *              (4) Swap diagonal elements at row-col intersection
  763:                R1 = DBLE( A( KK, KK ) )
  764:                A( KK, KK ) = DBLE( A( KP, KP ) )
  765:                A( KP, KP ) = R1
  766: *
  767:                IF( KSTEP.EQ.2 ) THEN
  768: *                 (*) Make sure that diagonal element of pivot is real
  769:                   A( K, K ) = DBLE( A( K, K ) )
  770: *                 (5) Swap row elements
  771:                   T = A( K+1, K )
  772:                   A( K+1, K ) = A( KP, K )
  773:                   A( KP, K ) = T
  774:                END IF
  775:             ELSE
  776: *              (*) Make sure that diagonal element of pivot is real
  777:                A( K, K ) = DBLE( A( K, K ) )
  778:                IF( KSTEP.EQ.2 )
  779:      $            A( K+1, K+1 ) = DBLE( A( K+1, K+1 ) )
  780:             END IF
  781: *
  782: *           Update the trailing submatrix
  783: *
  784:             IF( KSTEP.EQ.1 ) THEN
  785: *
  786: *              1-by-1 pivot block D(k): column k of A now holds
  787: *
  788: *              W(k) = L(k)*D(k),
  789: *
  790: *              where L(k) is the k-th column of L
  791: *
  792:                IF( K.LT.N ) THEN
  793: *
  794: *                 Perform a rank-1 update of A(k+1:n,k+1:n) and
  795: *                 store L(k) in column k
  796: *
  797: *                 Handle division by a small number
  798: *
  799:                   IF( ABS( DBLE( A( K, K ) ) ).GE.SFMIN ) THEN
  800: *
  801: *                    Perform a rank-1 update of A(k+1:n,k+1:n) as
  802: *                    A := A - L(k)*D(k)*L(k)**T
  803: *                       = A - W(k)*(1/D(k))*W(k)**T
  804: *
  805:                      D11 = ONE / DBLE( A( K, K ) )
  806:                      CALL ZHER( UPLO, N-K, -D11, A( K+1, K ), 1,
  807:      $                          A( K+1, K+1 ), LDA )
  808: *
  809: *                    Store L(k) in column k
  810: *
  811:                      CALL ZDSCAL( N-K, D11, A( K+1, K ), 1 )
  812:                   ELSE
  813: *
  814: *                    Store L(k) in column k
  815: *
  816:                      D11 = DBLE( A( K, K ) )
  817:                      DO 46 II = K + 1, N
  818:                         A( II, K ) = A( II, K ) / D11
  819:    46                CONTINUE
  820: *
  821: *                    Perform a rank-1 update of A(k+1:n,k+1:n) as
  822: *                    A := A - L(k)*D(k)*L(k)**T
  823: *                       = A - W(k)*(1/D(k))*W(k)**T
  824: *                       = A - (W(k)/D(k))*(D(k))*(W(k)/D(K))**T
  825: *
  826:                      CALL ZHER( UPLO, N-K, -D11, A( K+1, K ), 1,
  827:      $                          A( K+1, K+1 ), LDA )
  828:                   END IF
  829:                END IF
  830: *
  831:             ELSE
  832: *
  833: *              2-by-2 pivot block D(k): columns k and k+1 now hold
  834: *
  835: *              ( W(k) W(k+1) ) = ( L(k) L(k+1) )*D(k)
  836: *
  837: *              where L(k) and L(k+1) are the k-th and (k+1)-th columns
  838: *              of L
  839: *
  840: *
  841: *              Perform a rank-2 update of A(k+2:n,k+2:n) as
  842: *
  843: *              A := A - ( L(k) L(k+1) ) * D(k) * ( L(k) L(k+1) )**T
  844: *                 = A - ( ( A(k)A(k+1) )*inv(D(k) ) * ( A(k)A(k+1) )**T
  845: *
  846: *              and store L(k) and L(k+1) in columns k and k+1
  847: *
  848:                IF( K.LT.N-1 ) THEN
  849: *                 D = |A21|
  850:                   D = DLAPY2( DBLE( A( K+1, K ) ),
  851:      $                DIMAG( A( K+1, K ) ) )
  852:                   D11 = DBLE( A( K+1, K+1 ) ) / D
  853:                   D22 = DBLE( A( K, K ) ) / D
  854:                   D21 = A( K+1, K ) / D
  855:                   TT = ONE / ( D11*D22-ONE )
  856: *
  857:                   DO 60 J = K + 2, N
  858: *
  859: *                    Compute  D21 * ( W(k)W(k+1) ) * inv(D(k)) for row J
  860: *
  861:                      WK = TT*( D11*A( J, K )-D21*A( J, K+1 ) )
  862:                      WKP1 = TT*( D22*A( J, K+1 )-DCONJG( D21 )*
  863:      $                      A( J, K ) )
  864: *
  865: *                    Perform a rank-2 update of A(k+2:n,k+2:n)
  866: *
  867:                      DO 50 I = J, N
  868:                         A( I, J ) = A( I, J ) -
  869:      $                              ( A( I, K ) / D )*DCONJG( WK ) -
  870:      $                              ( A( I, K+1 ) / D )*DCONJG( WKP1 )
  871:    50                CONTINUE
  872: *
  873: *                    Store L(k) and L(k+1) in cols k and k+1 for row J
  874: *
  875:                      A( J, K ) = WK / D
  876:                      A( J, K+1 ) = WKP1 / D
  877: *                    (*) Make sure that diagonal element of pivot is real
  878:                      A( J, J ) = DCMPLX( DBLE( A( J, J ) ), ZERO )
  879: *
  880:    60             CONTINUE
  881: *
  882:                END IF
  883: *
  884:             END IF
  885: *
  886:          END IF
  887: *
  888: *        Store details of the interchanges in IPIV
  889: *
  890:          IF( KSTEP.EQ.1 ) THEN
  891:             IPIV( K ) = KP
  892:          ELSE
  893:             IPIV( K ) = -P
  894:             IPIV( K+1 ) = -KP
  895:          END IF
  896: *
  897: *        Increase K and return to the start of the main loop
  898: *
  899:          K = K + KSTEP
  900:          GO TO 40
  901: *
  902:       END IF
  903: *
  904:    70 CONTINUE
  905: *
  906:       RETURN
  907: *
  908: *     End of ZHETF2_ROOK
  909: *
  910:       END

CVSweb interface <joel.bertrand@systella.fr>