File:  [local] / rpl / lapack / lapack / zlaqz2.f
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:55:31 2023 UTC (9 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, rpl-4_1_34, HEAD
Ajout de fichiers de lapack 3.11

    1: *> \brief \b ZLAQZ2
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download ZLAQZ2 + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ZLAQZ2.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ZLAQZ2.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ZLAQZ2.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *      SUBROUTINE ZLAQZ2( ILSCHUR, ILQ, ILZ, N, ILO, IHI, NW, A, LDA, B,
   22: *     $    LDB, Q, LDQ, Z, LDZ, NS, ND, ALPHA, BETA, QC, LDQC, ZC, LDZC,
   23: *     $    WORK, LWORK, RWORK, REC, INFO )
   24: *      IMPLICIT NONE
   25: *
   26: *      Arguments
   27: *      LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
   28: *      INTEGER, INTENT( IN ) :: N, ILO, IHI, NW, LDA, LDB, LDQ, LDZ,
   29: *     $    LDQC, LDZC, LWORK, REC
   30: *
   31: *      COMPLEX*16, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ), Q( LDQ,
   32: *     $    * ), Z( LDZ, * ), ALPHA( * ), BETA( * )
   33: *      INTEGER, INTENT( OUT ) :: NS, ND, INFO
   34: *      COMPLEX*16 :: QC( LDQC, * ), ZC( LDZC, * ), WORK( * )
   35: *      DOUBLE PRECISION :: RWORK( * )
   36: *       ..
   37: *
   38: *
   39: *> \par Purpose:
   40: *  =============
   41: *>
   42: *> \verbatim
   43: *>
   44: *> ZLAQZ2 performs AED
   45: *> \endverbatim
   46: *
   47: *  Arguments:
   48: *  ==========
   49: *
   50: *> \param[in] ILSCHUR
   51: *> \verbatim
   52: *>          ILSCHUR is LOGICAL
   53: *>              Determines whether or not to update the full Schur form
   54: *> \endverbatim
   55: *> \param[in] ILQ
   56: *> \verbatim
   57: *>          ILQ is LOGICAL
   58: *>              Determines whether or not to update the matrix Q
   59: *> \endverbatim
   60: *>
   61: *> \param[in] ILZ
   62: *> \verbatim
   63: *>          ILZ is LOGICAL
   64: *>              Determines whether or not to update the matrix Z
   65: *> \endverbatim
   66: *>
   67: *> \param[in] N
   68: *> \verbatim
   69: *>          N is INTEGER
   70: *>          The order of the matrices A, B, Q, and Z.  N >= 0.
   71: *> \endverbatim
   72: *>
   73: *> \param[in] ILO
   74: *> \verbatim
   75: *>          ILO is INTEGER
   76: *> \endverbatim
   77: *>
   78: *> \param[in] IHI
   79: *> \verbatim
   80: *>          IHI is INTEGER
   81: *>          ILO and IHI mark the rows and columns of (A,B) which
   82: *>          are to be normalized
   83: *> \endverbatim
   84: *>
   85: *> \param[in] NW
   86: *> \verbatim
   87: *>          NW is INTEGER
   88: *>          The desired size of the deflation window.
   89: *> \endverbatim
   90: *>
   91: *> \param[in,out] A
   92: *> \verbatim
   93: *>          A is COMPLEX*16 array, dimension (LDA, N)
   94: *> \endverbatim
   95: *>
   96: *> \param[in] LDA
   97: *> \verbatim
   98: *>          LDA is INTEGER
   99: *>          The leading dimension of the array A.  LDA >= max( 1, N ).
  100: *> \endverbatim
  101: *>
  102: *> \param[in,out] B
  103: *> \verbatim
  104: *>          B is COMPLEX*16 array, dimension (LDB, N)
  105: *> \endverbatim
  106: *>
  107: *> \param[in] LDB
  108: *> \verbatim
  109: *>          LDB is INTEGER
  110: *>          The leading dimension of the array B.  LDB >= max( 1, N ).
  111: *> \endverbatim
  112: *>
  113: *> \param[in,out] Q
  114: *> \verbatim
  115: *>          Q is COMPLEX*16 array, dimension (LDQ, N)
  116: *> \endverbatim
  117: *>
  118: *> \param[in] LDQ
  119: *> \verbatim
  120: *>          LDQ is INTEGER
  121: *> \endverbatim
  122: *>
  123: *> \param[in,out] Z
  124: *> \verbatim
  125: *>          Z is COMPLEX*16 array, dimension (LDZ, N)
  126: *> \endverbatim
  127: *>
  128: *> \param[in] LDZ
  129: *> \verbatim
  130: *>          LDZ is INTEGER
  131: *> \endverbatim
  132: *>
  133: *> \param[out] NS
  134: *> \verbatim
  135: *>          NS is INTEGER
  136: *>          The number of unconverged eigenvalues available to
  137: *>          use as shifts.
  138: *> \endverbatim
  139: *>
  140: *> \param[out] ND
  141: *> \verbatim
  142: *>          ND is INTEGER
  143: *>          The number of converged eigenvalues found.
  144: *> \endverbatim
  145: *>
  146: *> \param[out] ALPHA
  147: *> \verbatim
  148: *>          ALPHA is COMPLEX*16 array, dimension (N)
  149: *>          Each scalar alpha defining an eigenvalue
  150: *>          of GNEP.
  151: *> \endverbatim
  152: *>
  153: *> \param[out] BETA
  154: *> \verbatim
  155: *>          BETA is COMPLEX*16 array, dimension (N)
  156: *>          The scalars beta that define the eigenvalues of GNEP.
  157: *>          Together, the quantities alpha = ALPHA(j) and
  158: *>          beta = BETA(j) represent the j-th eigenvalue of the matrix
  159: *>          pair (A,B), in one of the forms lambda = alpha/beta or
  160: *>          mu = beta/alpha.  Since either lambda or mu may overflow,
  161: *>          they should not, in general, be computed.
  162: *> \endverbatim
  163: *>
  164: *> \param[in,out] QC
  165: *> \verbatim
  166: *>          QC is COMPLEX*16 array, dimension (LDQC, NW)
  167: *> \endverbatim
  168: *>
  169: *> \param[in] LDQC
  170: *> \verbatim
  171: *>          LDQC is INTEGER
  172: *> \endverbatim
  173: *>
  174: *> \param[in,out] ZC
  175: *> \verbatim
  176: *>          ZC is COMPLEX*16 array, dimension (LDZC, NW)
  177: *> \endverbatim
  178: *>
  179: *> \param[in] LDZC
  180: *> \verbatim
  181: *>          LDZ is INTEGER
  182: *> \endverbatim
  183: *>
  184: *> \param[out] WORK
  185: *> \verbatim
  186: *>          WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
  187: *>          On exit, if INFO >= 0, WORK(1) returns the optimal LWORK.
  188: *> \endverbatim
  189: *>
  190: *> \param[in] LWORK
  191: *> \verbatim
  192: *>          LWORK is INTEGER
  193: *>          The dimension of the array WORK.  LWORK >= max(1,N).
  194: *>
  195: *>          If LWORK = -1, then a workspace query is assumed; the routine
  196: *>          only calculates the optimal size of the WORK array, returns
  197: *>          this value as the first entry of the WORK array, and no error
  198: *>          message related to LWORK is issued by XERBLA.
  199: *> \endverbatim
  200: *>
  201: *> \param[out] RWORK
  202: *> \verbatim
  203: *>          RWORK is DOUBLE PRECISION array, dimension (N)
  204: *> \endverbatim
  205: *>
  206: *> \param[in] REC
  207: *> \verbatim
  208: *>          REC is INTEGER
  209: *>             REC indicates the current recursion level. Should be set
  210: *>             to 0 on first call.
  211: *> \endverbatim
  212: *>
  213: *> \param[out] INFO
  214: *> \verbatim
  215: *>          INFO is INTEGER
  216: *>          = 0: successful exit
  217: *>          < 0: if INFO = -i, the i-th argument had an illegal value
  218: *> \endverbatim
  219: *
  220: *  Authors:
  221: *  ========
  222: *
  223: *> \author Thijs Steel, KU Leuven
  224: *
  225: *> \date May 2020
  226: *
  227: *> \ingroup complex16GEcomputational
  228: *>
  229: *  =====================================================================
  230:       RECURSIVE SUBROUTINE ZLAQZ2( ILSCHUR, ILQ, ILZ, N, ILO, IHI, NW,
  231:      $                             A, LDA, B, LDB, Q, LDQ, Z, LDZ, NS,
  232:      $                             ND, ALPHA, BETA, QC, LDQC, ZC, LDZC,
  233:      $                             WORK, LWORK, RWORK, REC, INFO )
  234:       IMPLICIT NONE
  235: 
  236: *     Arguments
  237:       LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
  238:       INTEGER, INTENT( IN ) :: N, ILO, IHI, NW, LDA, LDB, LDQ, LDZ,
  239:      $         LDQC, LDZC, LWORK, REC
  240: 
  241:       COMPLEX*16, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ), Q( LDQ,
  242:      $   * ), Z( LDZ, * ), ALPHA( * ), BETA( * )
  243:       INTEGER, INTENT( OUT ) :: NS, ND, INFO
  244:       COMPLEX*16 :: QC( LDQC, * ), ZC( LDZC, * ), WORK( * )
  245:       DOUBLE PRECISION :: RWORK( * )
  246: 
  247: *     Parameters
  248:       COMPLEX*16         CZERO, CONE
  249:       PARAMETER          ( CZERO = ( 0.0D+0, 0.0D+0 ), CONE = ( 1.0D+0,
  250:      $                     0.0D+0 ) )
  251:       DOUBLE PRECISION :: ZERO, ONE, HALF
  252:       PARAMETER( ZERO = 0.0D0, ONE = 1.0D0, HALF = 0.5D0 )
  253: 
  254: *     Local Scalars
  255:       INTEGER :: JW, KWTOP, KWBOT, ISTOPM, ISTARTM, K, K2, ZTGEXC_INFO,
  256:      $           IFST, ILST, LWORKREQ, QZ_SMALL_INFO
  257:       DOUBLE PRECISION ::SMLNUM, ULP, SAFMIN, SAFMAX, C1, TEMPR
  258:       COMPLEX*16 :: S, S1, TEMP
  259: 
  260: *     External Functions
  261:       EXTERNAL :: XERBLA, ZLAQZ0, ZLAQZ1, DLABAD, ZLACPY, ZLASET, ZGEMM,
  262:      $            ZTGEXC, ZLARTG, ZROT
  263:       DOUBLE PRECISION, EXTERNAL :: DLAMCH
  264: 
  265:       INFO = 0
  266: 
  267: *     Set up deflation window
  268:       JW = MIN( NW, IHI-ILO+1 )
  269:       KWTOP = IHI-JW+1
  270:       IF ( KWTOP .EQ. ILO ) THEN
  271:          S = CZERO
  272:       ELSE
  273:          S = A( KWTOP, KWTOP-1 )
  274:       END IF
  275: 
  276: *     Determine required workspace
  277:       IFST = 1
  278:       ILST = JW
  279:       CALL ZLAQZ0( 'S', 'V', 'V', JW, 1, JW, A( KWTOP, KWTOP ), LDA,
  280:      $             B( KWTOP, KWTOP ), LDB, ALPHA, BETA, QC, LDQC, ZC,
  281:      $             LDZC, WORK, -1, RWORK, REC+1, QZ_SMALL_INFO )
  282:       LWORKREQ = INT( WORK( 1 ) )+2*JW**2
  283:       LWORKREQ = MAX( LWORKREQ, N*NW, 2*NW**2+N )
  284:       IF ( LWORK .EQ.-1 ) THEN
  285: *        workspace query, quick return
  286:          WORK( 1 ) = LWORKREQ
  287:          RETURN
  288:       ELSE IF ( LWORK .LT. LWORKREQ ) THEN
  289:          INFO = -26
  290:       END IF
  291: 
  292:       IF( INFO.NE.0 ) THEN
  293:          CALL XERBLA( 'ZLAQZ2', -INFO )
  294:          RETURN
  295:       END IF
  296: 
  297: *     Get machine constants
  298:       SAFMIN = DLAMCH( 'SAFE MINIMUM' )
  299:       SAFMAX = ONE/SAFMIN
  300:       CALL DLABAD( SAFMIN, SAFMAX )
  301:       ULP = DLAMCH( 'PRECISION' )
  302:       SMLNUM = SAFMIN*( DBLE( N )/ULP )
  303: 
  304:       IF ( IHI .EQ. KWTOP ) THEN
  305: *        1 by 1 deflation window, just try a regular deflation
  306:          ALPHA( KWTOP ) = A( KWTOP, KWTOP )
  307:          BETA( KWTOP ) = B( KWTOP, KWTOP )
  308:          NS = 1
  309:          ND = 0
  310:          IF ( ABS( S ) .LE. MAX( SMLNUM, ULP*ABS( A( KWTOP,
  311:      $      KWTOP ) ) ) ) THEN
  312:             NS = 0
  313:             ND = 1
  314:             IF ( KWTOP .GT. ILO ) THEN
  315:                A( KWTOP, KWTOP-1 ) = CZERO
  316:             END IF
  317:          END IF
  318:       END IF
  319: 
  320: 
  321: *     Store window in case of convergence failure
  322:       CALL ZLACPY( 'ALL', JW, JW, A( KWTOP, KWTOP ), LDA, WORK, JW )
  323:       CALL ZLACPY( 'ALL', JW, JW, B( KWTOP, KWTOP ), LDB, WORK( JW**2+
  324:      $             1 ), JW )
  325: 
  326: *     Transform window to real schur form
  327:       CALL ZLASET( 'FULL', JW, JW, CZERO, CONE, QC, LDQC )
  328:       CALL ZLASET( 'FULL', JW, JW, CZERO, CONE, ZC, LDZC )
  329:       CALL ZLAQZ0( 'S', 'V', 'V', JW, 1, JW, A( KWTOP, KWTOP ), LDA,
  330:      $             B( KWTOP, KWTOP ), LDB, ALPHA, BETA, QC, LDQC, ZC,
  331:      $             LDZC, WORK( 2*JW**2+1 ), LWORK-2*JW**2, RWORK,
  332:      $             REC+1, QZ_SMALL_INFO )
  333: 
  334:       IF( QZ_SMALL_INFO .NE. 0 ) THEN
  335: *        Convergence failure, restore the window and exit
  336:          ND = 0
  337:          NS = JW-QZ_SMALL_INFO
  338:          CALL ZLACPY( 'ALL', JW, JW, WORK, JW, A( KWTOP, KWTOP ), LDA )
  339:          CALL ZLACPY( 'ALL', JW, JW, WORK( JW**2+1 ), JW, B( KWTOP,
  340:      $                KWTOP ), LDB )
  341:          RETURN
  342:       END IF
  343: 
  344: *     Deflation detection loop
  345:       IF ( KWTOP .EQ. ILO .OR. S .EQ. CZERO ) THEN
  346:          KWBOT = KWTOP-1
  347:       ELSE
  348:          KWBOT = IHI
  349:          K = 1
  350:          K2 = 1
  351:          DO WHILE ( K .LE. JW )
  352: *              Try to deflate eigenvalue
  353:                TEMPR = ABS( A( KWBOT, KWBOT ) )
  354:                IF( TEMPR .EQ. ZERO ) THEN
  355:                   TEMPR = ABS( S )
  356:                END IF
  357:                IF ( ( ABS( S*QC( 1, KWBOT-KWTOP+1 ) ) ) .LE. MAX( ULP*
  358:      $            TEMPR, SMLNUM ) ) THEN
  359: *                 Deflatable
  360:                   KWBOT = KWBOT-1
  361:                ELSE
  362: *                 Not deflatable, move out of the way
  363:                   IFST = KWBOT-KWTOP+1
  364:                   ILST = K2
  365:                   CALL ZTGEXC( .TRUE., .TRUE., JW, A( KWTOP, KWTOP ),
  366:      $                         LDA, B( KWTOP, KWTOP ), LDB, QC, LDQC,
  367:      $                         ZC, LDZC, IFST, ILST, ZTGEXC_INFO )
  368:                   K2 = K2+1
  369:                END IF
  370: 
  371:                K = K+1
  372:          END DO
  373:       END IF
  374: 
  375: *     Store eigenvalues
  376:       ND = IHI-KWBOT
  377:       NS = JW-ND
  378:       K = KWTOP
  379:       DO WHILE ( K .LE. IHI )
  380:          ALPHA( K ) = A( K, K )
  381:          BETA( K ) = B( K, K )
  382:          K = K+1
  383:       END DO
  384: 
  385:       IF ( KWTOP .NE. ILO .AND. S .NE. CZERO ) THEN
  386: *        Reflect spike back, this will create optimally packed bulges
  387:          A( KWTOP:KWBOT, KWTOP-1 ) = A( KWTOP, KWTOP-1 ) *DCONJG( QC( 1,
  388:      $      1:JW-ND ) )
  389:          DO K = KWBOT-1, KWTOP, -1
  390:             CALL ZLARTG( A( K, KWTOP-1 ), A( K+1, KWTOP-1 ), C1, S1,
  391:      $                   TEMP )
  392:             A( K, KWTOP-1 ) = TEMP
  393:             A( K+1, KWTOP-1 ) = CZERO
  394:             K2 = MAX( KWTOP, K-1 )
  395:             CALL ZROT( IHI-K2+1, A( K, K2 ), LDA, A( K+1, K2 ), LDA, C1,
  396:      $                 S1 )
  397:             CALL ZROT( IHI-( K-1 )+1, B( K, K-1 ), LDB, B( K+1, K-1 ),
  398:      $                 LDB, C1, S1 )
  399:             CALL ZROT( JW, QC( 1, K-KWTOP+1 ), 1, QC( 1, K+1-KWTOP+1 ),
  400:      $                 1, C1, DCONJG( S1 ) )
  401:          END DO
  402: 
  403: *        Chase bulges down
  404:          ISTARTM = KWTOP
  405:          ISTOPM = IHI
  406:          K = KWBOT-1
  407:          DO WHILE ( K .GE. KWTOP )
  408: 
  409: *           Move bulge down and remove it
  410:             DO K2 = K, KWBOT-1
  411:                CALL ZLAQZ1( .TRUE., .TRUE., K2, KWTOP, KWTOP+JW-1,
  412:      $                      KWBOT, A, LDA, B, LDB, JW, KWTOP, QC, LDQC,
  413:      $                      JW, KWTOP, ZC, LDZC )
  414:             END DO
  415: 
  416:             K = K-1
  417:          END DO
  418: 
  419:       END IF
  420: 
  421: *     Apply Qc and Zc to rest of the matrix
  422:       IF ( ILSCHUR ) THEN
  423:          ISTARTM = 1
  424:          ISTOPM = N
  425:       ELSE
  426:          ISTARTM = ILO
  427:          ISTOPM = IHI
  428:       END IF
  429: 
  430:       IF ( ISTOPM-IHI > 0 ) THEN
  431:          CALL ZGEMM( 'C', 'N', JW, ISTOPM-IHI, JW, CONE, QC, LDQC,
  432:      $               A( KWTOP, IHI+1 ), LDA, CZERO, WORK, JW )
  433:          CALL ZLACPY( 'ALL', JW, ISTOPM-IHI, WORK, JW, A( KWTOP,
  434:      $                IHI+1 ), LDA )
  435:          CALL ZGEMM( 'C', 'N', JW, ISTOPM-IHI, JW, CONE, QC, LDQC,
  436:      $               B( KWTOP, IHI+1 ), LDB, CZERO, WORK, JW )
  437:          CALL ZLACPY( 'ALL', JW, ISTOPM-IHI, WORK, JW, B( KWTOP,
  438:      $                IHI+1 ), LDB )
  439:       END IF
  440:       IF ( ILQ ) THEN
  441:          CALL ZGEMM( 'N', 'N', N, JW, JW, CONE, Q( 1, KWTOP ), LDQ, QC,
  442:      $               LDQC, CZERO, WORK, N )
  443:          CALL ZLACPY( 'ALL', N, JW, WORK, N, Q( 1, KWTOP ), LDQ )
  444:       END IF
  445: 
  446:       IF ( KWTOP-1-ISTARTM+1 > 0 ) THEN
  447:          CALL ZGEMM( 'N', 'N', KWTOP-ISTARTM, JW, JW, CONE, A( ISTARTM,
  448:      $               KWTOP ), LDA, ZC, LDZC, CZERO, WORK,
  449:      $               KWTOP-ISTARTM )
  450:         CALL ZLACPY( 'ALL', KWTOP-ISTARTM, JW, WORK, KWTOP-ISTARTM,
  451:      $               A( ISTARTM, KWTOP ), LDA )
  452:          CALL ZGEMM( 'N', 'N', KWTOP-ISTARTM, JW, JW, CONE, B( ISTARTM,
  453:      $               KWTOP ), LDB, ZC, LDZC, CZERO, WORK,
  454:      $               KWTOP-ISTARTM )
  455:         CALL ZLACPY( 'ALL', KWTOP-ISTARTM, JW, WORK, KWTOP-ISTARTM,
  456:      $               B( ISTARTM, KWTOP ), LDB )
  457:       END IF
  458:       IF ( ILZ ) THEN
  459:          CALL ZGEMM( 'N', 'N', N, JW, JW, CONE, Z( 1, KWTOP ), LDZ, ZC,
  460:      $               LDZC, CZERO, WORK, N )
  461:          CALL ZLACPY( 'ALL', N, JW, WORK, N, Z( 1, KWTOP ), LDZ )
  462:       END IF
  463: 
  464:       END SUBROUTINE

CVSweb interface <joel.bertrand@systella.fr>