File:  [local] / rpl / lapack / lapack / zhegvd.f
Revision 1.19: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:39:23 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 ZHEGVD
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download ZHEGVD + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zhegvd.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zhegvd.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhegvd.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE ZHEGVD( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK,
   22: *                          LWORK, RWORK, LRWORK, IWORK, LIWORK, INFO )
   23: *
   24: *       .. Scalar Arguments ..
   25: *       CHARACTER          JOBZ, UPLO
   26: *       INTEGER            INFO, ITYPE, LDA, LDB, LIWORK, LRWORK, LWORK, N
   27: *       ..
   28: *       .. Array Arguments ..
   29: *       INTEGER            IWORK( * )
   30: *       DOUBLE PRECISION   RWORK( * ), W( * )
   31: *       COMPLEX*16         A( LDA, * ), B( LDB, * ), WORK( * )
   32: *       ..
   33: *
   34: *
   35: *> \par Purpose:
   36: *  =============
   37: *>
   38: *> \verbatim
   39: *>
   40: *> ZHEGVD computes all the eigenvalues, and optionally, the eigenvectors
   41: *> of a complex generalized Hermitian-definite eigenproblem, of the form
   42: *> A*x=(lambda)*B*x,  A*Bx=(lambda)*x,  or B*A*x=(lambda)*x.  Here A and
   43: *> B are assumed to be Hermitian and B is also positive definite.
   44: *> If eigenvectors are desired, it uses a divide and conquer algorithm.
   45: *>
   46: *> The divide and conquer algorithm makes very mild assumptions about
   47: *> floating point arithmetic. It will work on machines with a guard
   48: *> digit in add/subtract, or on those binary machines without guard
   49: *> digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
   50: *> Cray-2. It could conceivably fail on hexadecimal or decimal machines
   51: *> without guard digits, but we know of none.
   52: *> \endverbatim
   53: *
   54: *  Arguments:
   55: *  ==========
   56: *
   57: *> \param[in] ITYPE
   58: *> \verbatim
   59: *>          ITYPE is INTEGER
   60: *>          Specifies the problem type to be solved:
   61: *>          = 1:  A*x = (lambda)*B*x
   62: *>          = 2:  A*B*x = (lambda)*x
   63: *>          = 3:  B*A*x = (lambda)*x
   64: *> \endverbatim
   65: *>
   66: *> \param[in] JOBZ
   67: *> \verbatim
   68: *>          JOBZ is CHARACTER*1
   69: *>          = 'N':  Compute eigenvalues only;
   70: *>          = 'V':  Compute eigenvalues and eigenvectors.
   71: *> \endverbatim
   72: *>
   73: *> \param[in] UPLO
   74: *> \verbatim
   75: *>          UPLO is CHARACTER*1
   76: *>          = 'U':  Upper triangles of A and B are stored;
   77: *>          = 'L':  Lower triangles of A and B are stored.
   78: *> \endverbatim
   79: *>
   80: *> \param[in] N
   81: *> \verbatim
   82: *>          N is INTEGER
   83: *>          The order of the matrices A and B.  N >= 0.
   84: *> \endverbatim
   85: *>
   86: *> \param[in,out] A
   87: *> \verbatim
   88: *>          A is COMPLEX*16 array, dimension (LDA, N)
   89: *>          On entry, the Hermitian matrix A.  If UPLO = 'U', the
   90: *>          leading N-by-N upper triangular part of A contains the
   91: *>          upper triangular part of the matrix A.  If UPLO = 'L',
   92: *>          the leading N-by-N lower triangular part of A contains
   93: *>          the lower triangular part of the matrix A.
   94: *>
   95: *>          On exit, if JOBZ = 'V', then if INFO = 0, A contains the
   96: *>          matrix Z of eigenvectors.  The eigenvectors are normalized
   97: *>          as follows:
   98: *>          if ITYPE = 1 or 2, Z**H*B*Z = I;
   99: *>          if ITYPE = 3, Z**H*inv(B)*Z = I.
  100: *>          If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
  101: *>          or the lower triangle (if UPLO='L') of A, including the
  102: *>          diagonal, is destroyed.
  103: *> \endverbatim
  104: *>
  105: *> \param[in] LDA
  106: *> \verbatim
  107: *>          LDA is INTEGER
  108: *>          The leading dimension of the array A.  LDA >= max(1,N).
  109: *> \endverbatim
  110: *>
  111: *> \param[in,out] B
  112: *> \verbatim
  113: *>          B is COMPLEX*16 array, dimension (LDB, N)
  114: *>          On entry, the Hermitian matrix B.  If UPLO = 'U', the
  115: *>          leading N-by-N upper triangular part of B contains the
  116: *>          upper triangular part of the matrix B.  If UPLO = 'L',
  117: *>          the leading N-by-N lower triangular part of B contains
  118: *>          the lower triangular part of the matrix B.
  119: *>
  120: *>          On exit, if INFO <= N, the part of B containing the matrix is
  121: *>          overwritten by the triangular factor U or L from the Cholesky
  122: *>          factorization B = U**H*U or B = L*L**H.
  123: *> \endverbatim
  124: *>
  125: *> \param[in] LDB
  126: *> \verbatim
  127: *>          LDB is INTEGER
  128: *>          The leading dimension of the array B.  LDB >= max(1,N).
  129: *> \endverbatim
  130: *>
  131: *> \param[out] W
  132: *> \verbatim
  133: *>          W is DOUBLE PRECISION array, dimension (N)
  134: *>          If INFO = 0, the eigenvalues in ascending order.
  135: *> \endverbatim
  136: *>
  137: *> \param[out] WORK
  138: *> \verbatim
  139: *>          WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
  140: *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  141: *> \endverbatim
  142: *>
  143: *> \param[in] LWORK
  144: *> \verbatim
  145: *>          LWORK is INTEGER
  146: *>          The length of the array WORK.
  147: *>          If N <= 1,                LWORK >= 1.
  148: *>          If JOBZ  = 'N' and N > 1, LWORK >= N + 1.
  149: *>          If JOBZ  = 'V' and N > 1, LWORK >= 2*N + N**2.
  150: *>
  151: *>          If LWORK = -1, then a workspace query is assumed; the routine
  152: *>          only calculates the optimal sizes of the WORK, RWORK and
  153: *>          IWORK arrays, returns these values as the first entries of
  154: *>          the WORK, RWORK and IWORK arrays, and no error message
  155: *>          related to LWORK or LRWORK or LIWORK is issued by XERBLA.
  156: *> \endverbatim
  157: *>
  158: *> \param[out] RWORK
  159: *> \verbatim
  160: *>          RWORK is DOUBLE PRECISION array, dimension (MAX(1,LRWORK))
  161: *>          On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
  162: *> \endverbatim
  163: *>
  164: *> \param[in] LRWORK
  165: *> \verbatim
  166: *>          LRWORK is INTEGER
  167: *>          The dimension of the array RWORK.
  168: *>          If N <= 1,                LRWORK >= 1.
  169: *>          If JOBZ  = 'N' and N > 1, LRWORK >= N.
  170: *>          If JOBZ  = 'V' and N > 1, LRWORK >= 1 + 5*N + 2*N**2.
  171: *>
  172: *>          If LRWORK = -1, then a workspace query is assumed; the
  173: *>          routine only calculates the optimal sizes of the WORK, RWORK
  174: *>          and IWORK arrays, returns these values as the first entries
  175: *>          of the WORK, RWORK and IWORK arrays, and no error message
  176: *>          related to LWORK or LRWORK or LIWORK is issued by XERBLA.
  177: *> \endverbatim
  178: *>
  179: *> \param[out] IWORK
  180: *> \verbatim
  181: *>          IWORK is INTEGER array, dimension (MAX(1,LIWORK))
  182: *>          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
  183: *> \endverbatim
  184: *>
  185: *> \param[in] LIWORK
  186: *> \verbatim
  187: *>          LIWORK is INTEGER
  188: *>          The dimension of the array IWORK.
  189: *>          If N <= 1,                LIWORK >= 1.
  190: *>          If JOBZ  = 'N' and N > 1, LIWORK >= 1.
  191: *>          If JOBZ  = 'V' and N > 1, LIWORK >= 3 + 5*N.
  192: *>
  193: *>          If LIWORK = -1, then a workspace query is assumed; the
  194: *>          routine only calculates the optimal sizes of the WORK, RWORK
  195: *>          and IWORK arrays, returns these values as the first entries
  196: *>          of the WORK, RWORK and IWORK arrays, and no error message
  197: *>          related to LWORK or LRWORK or LIWORK is issued by XERBLA.
  198: *> \endverbatim
  199: *>
  200: *> \param[out] INFO
  201: *> \verbatim
  202: *>          INFO is INTEGER
  203: *>          = 0:  successful exit
  204: *>          < 0:  if INFO = -i, the i-th argument had an illegal value
  205: *>          > 0:  ZPOTRF or ZHEEVD returned an error code:
  206: *>             <= N:  if INFO = i and JOBZ = 'N', then the algorithm
  207: *>                    failed to converge; i off-diagonal elements of an
  208: *>                    intermediate tridiagonal form did not converge to
  209: *>                    zero;
  210: *>                    if INFO = i and JOBZ = 'V', then the algorithm
  211: *>                    failed to compute an eigenvalue while working on
  212: *>                    the submatrix lying in rows and columns INFO/(N+1)
  213: *>                    through mod(INFO,N+1);
  214: *>             > N:   if INFO = N + i, for 1 <= i <= N, then the leading
  215: *>                    minor of order i of B is not positive definite.
  216: *>                    The factorization of B could not be completed and
  217: *>                    no eigenvalues or eigenvectors were computed.
  218: *> \endverbatim
  219: *
  220: *  Authors:
  221: *  ========
  222: *
  223: *> \author Univ. of Tennessee
  224: *> \author Univ. of California Berkeley
  225: *> \author Univ. of Colorado Denver
  226: *> \author NAG Ltd.
  227: *
  228: *> \ingroup complex16HEeigen
  229: *
  230: *> \par Further Details:
  231: *  =====================
  232: *>
  233: *> \verbatim
  234: *>
  235: *>  Modified so that no backsubstitution is performed if ZHEEVD fails to
  236: *>  converge (NEIG in old code could be greater than N causing out of
  237: *>  bounds reference to A - reported by Ralf Meyer).  Also corrected the
  238: *>  description of INFO and the test on ITYPE. Sven, 16 Feb 05.
  239: *> \endverbatim
  240: *
  241: *> \par Contributors:
  242: *  ==================
  243: *>
  244: *>     Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA
  245: *>
  246: *  =====================================================================
  247:       SUBROUTINE ZHEGVD( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK,
  248:      $                   LWORK, RWORK, LRWORK, IWORK, LIWORK, INFO )
  249: *
  250: *  -- LAPACK driver routine --
  251: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  252: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  253: *
  254: *     .. Scalar Arguments ..
  255:       CHARACTER          JOBZ, UPLO
  256:       INTEGER            INFO, ITYPE, LDA, LDB, LIWORK, LRWORK, LWORK, N
  257: *     ..
  258: *     .. Array Arguments ..
  259:       INTEGER            IWORK( * )
  260:       DOUBLE PRECISION   RWORK( * ), W( * )
  261:       COMPLEX*16         A( LDA, * ), B( LDB, * ), WORK( * )
  262: *     ..
  263: *
  264: *  =====================================================================
  265: *
  266: *     .. Parameters ..
  267:       COMPLEX*16         CONE
  268:       PARAMETER          ( CONE = ( 1.0D+0, 0.0D+0 ) )
  269: *     ..
  270: *     .. Local Scalars ..
  271:       LOGICAL            LQUERY, UPPER, WANTZ
  272:       CHARACTER          TRANS
  273:       INTEGER            LIOPT, LIWMIN, LOPT, LROPT, LRWMIN, LWMIN
  274: *     ..
  275: *     .. External Functions ..
  276:       LOGICAL            LSAME
  277:       EXTERNAL           LSAME
  278: *     ..
  279: *     .. External Subroutines ..
  280:       EXTERNAL           XERBLA, ZHEEVD, ZHEGST, ZPOTRF, ZTRMM, ZTRSM
  281: *     ..
  282: *     .. Intrinsic Functions ..
  283:       INTRINSIC          DBLE, MAX
  284: *     ..
  285: *     .. Executable Statements ..
  286: *
  287: *     Test the input parameters.
  288: *
  289:       WANTZ = LSAME( JOBZ, 'V' )
  290:       UPPER = LSAME( UPLO, 'U' )
  291:       LQUERY = ( LWORK.EQ.-1 .OR. LRWORK.EQ.-1 .OR. LIWORK.EQ.-1 )
  292: *
  293:       INFO = 0
  294:       IF( N.LE.1 ) THEN
  295:          LWMIN = 1
  296:          LRWMIN = 1
  297:          LIWMIN = 1
  298:       ELSE IF( WANTZ ) THEN
  299:          LWMIN = 2*N + N*N
  300:          LRWMIN = 1 + 5*N + 2*N*N
  301:          LIWMIN = 3 + 5*N
  302:       ELSE
  303:          LWMIN = N + 1
  304:          LRWMIN = N
  305:          LIWMIN = 1
  306:       END IF
  307:       LOPT = LWMIN
  308:       LROPT = LRWMIN
  309:       LIOPT = LIWMIN
  310:       IF( ITYPE.LT.1 .OR. ITYPE.GT.3 ) THEN
  311:          INFO = -1
  312:       ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
  313:          INFO = -2
  314:       ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THEN
  315:          INFO = -3
  316:       ELSE IF( N.LT.0 ) THEN
  317:          INFO = -4
  318:       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
  319:          INFO = -6
  320:       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
  321:          INFO = -8
  322:       END IF
  323: *
  324:       IF( INFO.EQ.0 ) THEN
  325:          WORK( 1 ) = LOPT
  326:          RWORK( 1 ) = LROPT
  327:          IWORK( 1 ) = LIOPT
  328: *
  329:          IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
  330:             INFO = -11
  331:          ELSE IF( LRWORK.LT.LRWMIN .AND. .NOT.LQUERY ) THEN
  332:             INFO = -13
  333:          ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
  334:             INFO = -15
  335:          END IF
  336:       END IF
  337: *
  338:       IF( INFO.NE.0 ) THEN
  339:          CALL XERBLA( 'ZHEGVD', -INFO )
  340:          RETURN
  341:       ELSE IF( LQUERY ) THEN
  342:          RETURN
  343:       END IF
  344: *
  345: *     Quick return if possible
  346: *
  347:       IF( N.EQ.0 )
  348:      $   RETURN
  349: *
  350: *     Form a Cholesky factorization of B.
  351: *
  352:       CALL ZPOTRF( UPLO, N, B, LDB, INFO )
  353:       IF( INFO.NE.0 ) THEN
  354:          INFO = N + INFO
  355:          RETURN
  356:       END IF
  357: *
  358: *     Transform problem to standard eigenvalue problem and solve.
  359: *
  360:       CALL ZHEGST( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )
  361:       CALL ZHEEVD( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, RWORK, LRWORK,
  362:      $             IWORK, LIWORK, INFO )
  363:       LOPT = INT( MAX( DBLE( LOPT ), DBLE( WORK( 1 ) ) ) )
  364:       LROPT = INT( MAX( DBLE( LROPT ), DBLE( RWORK( 1 ) ) ) )
  365:       LIOPT = INT( MAX( DBLE( LIOPT ), DBLE( IWORK( 1 ) ) ) )
  366: *
  367:       IF( WANTZ .AND. INFO.EQ.0 ) THEN
  368: *
  369: *        Backtransform eigenvectors to the original problem.
  370: *
  371:          IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN
  372: *
  373: *           For A*x=(lambda)*B*x and A*B*x=(lambda)*x;
  374: *           backtransform eigenvectors: x = inv(L)**H *y or inv(U)*y
  375: *
  376:             IF( UPPER ) THEN
  377:                TRANS = 'N'
  378:             ELSE
  379:                TRANS = 'C'
  380:             END IF
  381: *
  382:             CALL ZTRSM( 'Left', UPLO, TRANS, 'Non-unit', N, N, CONE,
  383:      $                  B, LDB, A, LDA )
  384: *
  385:          ELSE IF( ITYPE.EQ.3 ) THEN
  386: *
  387: *           For B*A*x=(lambda)*x;
  388: *           backtransform eigenvectors: x = L*y or U**H *y
  389: *
  390:             IF( UPPER ) THEN
  391:                TRANS = 'C'
  392:             ELSE
  393:                TRANS = 'N'
  394:             END IF
  395: *
  396:             CALL ZTRMM( 'Left', UPLO, TRANS, 'Non-unit', N, N, CONE,
  397:      $                  B, LDB, A, LDA )
  398:          END IF
  399:       END IF
  400: *
  401:       WORK( 1 ) = LOPT
  402:       RWORK( 1 ) = LROPT
  403:       IWORK( 1 ) = LIOPT
  404: *
  405:       RETURN
  406: *
  407: *     End of ZHEGVD
  408: *
  409:       END

CVSweb interface <joel.bertrand@systella.fr>