File:  [local] / rpl / lapack / lapack / ztrsyl3.f
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:55:32 2023 UTC (8 months, 3 weeks 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 ZTRSYL3
    2: *
    3: * Definition:
    4: * ===========
    5: *
    6: *
    7: *>  \par Purpose
    8: *  =============
    9: *>
   10: *> \verbatim
   11: *>
   12: *>  ZTRSYL3 solves the complex Sylvester matrix equation:
   13: *>
   14: *>     op(A)*X + X*op(B) = scale*C or
   15: *>     op(A)*X - X*op(B) = scale*C,
   16: *>
   17: *>  where op(A) = A or A**H, and  A and B are both upper triangular. A is
   18: *>  M-by-M and B is N-by-N; the right hand side C and the solution X are
   19: *>  M-by-N; and scale is an output scale factor, set <= 1 to avoid
   20: *>  overflow in X.
   21: *>
   22: *>  This is the block version of the algorithm.
   23: *> \endverbatim
   24: *
   25: *  Arguments
   26: *  =========
   27: *
   28: *> \param[in] TRANA
   29: *> \verbatim
   30: *>          TRANA is CHARACTER*1
   31: *>          Specifies the option op(A):
   32: *>          = 'N': op(A) = A    (No transpose)
   33: *>          = 'C': op(A) = A**H (Conjugate transpose)
   34: *> \endverbatim
   35: *>
   36: *> \param[in] TRANB
   37: *> \verbatim
   38: *>          TRANB is CHARACTER*1
   39: *>          Specifies the option op(B):
   40: *>          = 'N': op(B) = B    (No transpose)
   41: *>          = 'C': op(B) = B**H (Conjugate transpose)
   42: *> \endverbatim
   43: *>
   44: *> \param[in] ISGN
   45: *> \verbatim
   46: *>          ISGN is INTEGER
   47: *>          Specifies the sign in the equation:
   48: *>          = +1: solve op(A)*X + X*op(B) = scale*C
   49: *>          = -1: solve op(A)*X - X*op(B) = scale*C
   50: *> \endverbatim
   51: *>
   52: *> \param[in] M
   53: *> \verbatim
   54: *>          M is INTEGER
   55: *>          The order of the matrix A, and the number of rows in the
   56: *>          matrices X and C. M >= 0.
   57: *> \endverbatim
   58: *>
   59: *> \param[in] N
   60: *> \verbatim
   61: *>          N is INTEGER
   62: *>          The order of the matrix B, and the number of columns in the
   63: *>          matrices X and C. N >= 0.
   64: *> \endverbatim
   65: *>
   66: *> \param[in] A
   67: *> \verbatim
   68: *>          A is COMPLEX*16 array, dimension (LDA,M)
   69: *>          The upper triangular matrix A.
   70: *> \endverbatim
   71: *>
   72: *> \param[in] LDA
   73: *> \verbatim
   74: *>          LDA is INTEGER
   75: *>          The leading dimension of the array A. LDA >= max(1,M).
   76: *> \endverbatim
   77: *>
   78: *> \param[in] B
   79: *> \verbatim
   80: *>          B is COMPLEX*16 array, dimension (LDB,N)
   81: *>          The upper triangular matrix B.
   82: *> \endverbatim
   83: *>
   84: *> \param[in] LDB
   85: *> \verbatim
   86: *>          LDB is INTEGER
   87: *>          The leading dimension of the array B. LDB >= max(1,N).
   88: *> \endverbatim
   89: *>
   90: *> \param[in,out] C
   91: *> \verbatim
   92: *>          C is COMPLEX*16 array, dimension (LDC,N)
   93: *>          On entry, the M-by-N right hand side matrix C.
   94: *>          On exit, C is overwritten by the solution matrix X.
   95: *> \endverbatim
   96: *>
   97: *> \param[in] LDC
   98: *> \verbatim
   99: *>          LDC is INTEGER
  100: *>          The leading dimension of the array C. LDC >= max(1,M)
  101: *> \endverbatim
  102: *>
  103: *> \param[out] SCALE
  104: *> \verbatim
  105: *>          SCALE is DOUBLE PRECISION
  106: *>          The scale factor, scale, set <= 1 to avoid overflow in X.
  107: *> \endverbatim
  108: *>
  109: *> \param[out] SWORK
  110: *> \verbatim
  111: *>          SWORK is DOUBLE PRECISION array, dimension (MAX(2, ROWS),
  112: *>          MAX(1,COLS)).
  113: *>          On exit, if INFO = 0, SWORK(1) returns the optimal value ROWS
  114: *>          and SWORK(2) returns the optimal COLS.
  115: *> \endverbatim
  116: *>
  117: *> \param[in] LDSWORK
  118: *> \verbatim
  119: *>          LDSWORK is INTEGER
  120: *>          LDSWORK >= MAX(2,ROWS), where ROWS = ((M + NB - 1) / NB + 1)
  121: *>          and NB is the optimal block size.
  122: *>
  123: *>          If LDSWORK = -1, then a workspace query is assumed; the routine
  124: *>          only calculates the optimal dimensions of the SWORK matrix,
  125: *>          returns these values as the first and second entry of the SWORK
  126: *>          matrix, and no error message related LWORK is issued by XERBLA.
  127: *> \endverbatim
  128: *>
  129: *> \param[out] INFO
  130: *> \verbatim
  131: *>          INFO is INTEGER
  132: *>          = 0: successful exit
  133: *>          < 0: if INFO = -i, the i-th argument had an illegal value
  134: *>          = 1: A and B have common or very close eigenvalues; perturbed
  135: *>               values were used to solve the equation (but the matrices
  136: *>               A and B are unchanged).
  137: *> \endverbatim
  138: *
  139: *> \ingroup complex16SYcomputational
  140: *
  141: *  =====================================================================
  142: *  References:
  143: *   E. S. Quintana-Orti and R. A. Van De Geijn (2003). Formal derivation of
  144: *   algorithms: The triangular Sylvester equation, ACM Transactions
  145: *   on Mathematical Software (TOMS), volume 29, pages 218--243.
  146: *
  147: *   A. Schwarz and C. C. Kjelgaard Mikkelsen (2020). Robust Task-Parallel
  148: *   Solution of the Triangular Sylvester Equation. Lecture Notes in
  149: *   Computer Science, vol 12043, pages 82--92, Springer.
  150: *
  151: *  Contributor:
  152: *   Angelika Schwarz, Umea University, Sweden.
  153: *
  154: *  =====================================================================
  155:       SUBROUTINE ZTRSYL3( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB, C,
  156:      $                    LDC, SCALE, SWORK, LDSWORK, INFO )
  157:       IMPLICIT NONE
  158: *
  159: *     .. Scalar Arguments ..
  160:       CHARACTER          TRANA, TRANB
  161:       INTEGER            INFO, ISGN, LDA, LDB, LDC, LDSWORK, M, N
  162:       DOUBLE PRECISION   SCALE
  163: *     ..
  164: *     .. Array Arguments ..
  165:       COMPLEX*16         A( LDA, * ), B( LDB, * ), C( LDC, * )
  166:       DOUBLE PRECISION   SWORK( LDSWORK, * )
  167: *     ..
  168: *     .. Parameters ..
  169:       DOUBLE PRECISION   ZERO, ONE
  170:       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
  171:       COMPLEX*16         CONE
  172:       PARAMETER          ( CONE = ( 1.0D0, 0.0D0 ) )
  173: *     ..
  174: *     .. Local Scalars ..
  175:       LOGICAL            NOTRNA, NOTRNB, LQUERY
  176:       INTEGER            AWRK, BWRK, I, I1, I2, IINFO, J, J1, J2, JJ,
  177:      $                   K, K1, K2, L, L1, L2, LL, NBA, NB, NBB
  178:       DOUBLE PRECISION   ANRM, BIGNUM, BNRM, CNRM, SCAL, SCALOC,
  179:      $                   SCAMIN, SGN, XNRM, BUF, SMLNUM
  180:       COMPLEX*16         CSGN
  181: *     ..
  182: *     .. Local Arrays ..
  183:       DOUBLE PRECISION   WNRM( MAX( M, N ) )
  184: *     ..
  185: *     .. External Functions ..
  186:       LOGICAL            LSAME
  187:       INTEGER            ILAENV
  188:       DOUBLE PRECISION   DLAMCH, DLARMM, ZLANGE
  189:       EXTERNAL           DLAMCH, DLARMM, ILAENV, LSAME, ZLANGE
  190: *     ..
  191: *     .. External Subroutines ..
  192:       EXTERNAL           XERBLA, ZDSCAL, ZGEMM, ZLASCL, ZTRSYL
  193: *     ..
  194: *     .. Intrinsic Functions ..
  195:       INTRINSIC          ABS, DBLE, DIMAG, EXPONENT, MAX, MIN
  196: *     ..
  197: *     .. Executable Statements ..
  198: *
  199: *     Decode and Test input parameters
  200: *
  201:       NOTRNA = LSAME( TRANA, 'N' )
  202:       NOTRNB = LSAME( TRANB, 'N' )
  203: *
  204: *     Use the same block size for all matrices.
  205: *
  206:       NB = MAX( 8, ILAENV( 1, 'ZTRSYL', '', M, N, -1, -1) )
  207: *
  208: *     Compute number of blocks in A and B
  209: *
  210:       NBA = MAX( 1, (M + NB - 1) / NB )
  211:       NBB = MAX( 1, (N + NB - 1) / NB )
  212: *
  213: *     Compute workspace
  214: *
  215:       INFO = 0
  216:       LQUERY = ( LDSWORK.EQ.-1 )
  217:       IF( LQUERY ) THEN
  218:          LDSWORK = 2
  219:          SWORK(1,1) = MAX( NBA, NBB )
  220:          SWORK(2,1) = 2 * NBB + NBA
  221:       END IF
  222: *
  223: *     Test the input arguments
  224: *
  225:       IF( .NOT.NOTRNA .AND. .NOT. LSAME( TRANA, 'C' ) ) THEN
  226:          INFO = -1
  227:       ELSE IF( .NOT.NOTRNB .AND. .NOT. LSAME( TRANB, 'C' ) ) THEN
  228:          INFO = -2
  229:       ELSE IF( ISGN.NE.1 .AND. ISGN.NE.-1 ) THEN
  230:          INFO = -3
  231:       ELSE IF( M.LT.0 ) THEN
  232:          INFO = -4
  233:       ELSE IF( N.LT.0 ) THEN
  234:          INFO = -5
  235:       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
  236:          INFO = -7
  237:       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
  238:          INFO = -9
  239:       ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
  240:          INFO = -11
  241:       END IF
  242:       IF( INFO.NE.0 ) THEN
  243:          CALL XERBLA( 'ZTRSYL3', -INFO )
  244:          RETURN
  245:       ELSE IF( LQUERY ) THEN
  246:          RETURN
  247:       END IF
  248: *
  249: *     Quick return if possible
  250: *
  251:       SCALE = ONE
  252:       IF( M.EQ.0 .OR. N.EQ.0 )
  253:      $   RETURN
  254: *
  255: *     Use unblocked code for small problems or if insufficient
  256: *     workspace is provided
  257: *
  258:       IF( MIN( NBA, NBB ).EQ.1 .OR. LDSWORK.LT.MAX( NBA, NBB ) ) THEN
  259:         CALL ZTRSYL( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB,
  260:      $               C, LDC, SCALE, INFO )
  261:         RETURN
  262:       END IF
  263: *
  264: *     Set constants to control overflow
  265: *
  266:       SMLNUM = DLAMCH( 'S' )
  267:       BIGNUM = ONE / SMLNUM
  268: *
  269: *     Set local scaling factors.
  270: *
  271:       DO L = 1, NBB
  272:          DO K = 1, NBA
  273:             SWORK( K, L ) = ONE
  274:          END DO
  275:       END DO
  276: *
  277: *     Fallback scaling factor to prevent flushing of SWORK( K, L ) to zero.
  278: *     This scaling is to ensure compatibility with TRSYL and may get flushed.
  279: *
  280:       BUF = ONE
  281: *
  282: *      Compute upper bounds of blocks of A and B
  283: *
  284:       AWRK = NBB
  285:       DO K = 1, NBA
  286:          K1 = (K - 1) * NB + 1
  287:          K2 = MIN( K * NB, M ) + 1
  288:          DO L = K, NBA
  289:             L1 = (L - 1) * NB + 1
  290:             L2 = MIN( L * NB, M ) + 1
  291:             IF( NOTRNA ) THEN
  292:                SWORK( K, AWRK + L ) = ZLANGE( 'I', K2-K1, L2-L1,
  293:      $                                        A( K1, L1 ), LDA, WNRM )
  294:             ELSE
  295:                SWORK( L, AWRK + K ) = ZLANGE( '1', K2-K1, L2-L1,
  296:      $                                        A( K1, L1 ), LDA, WNRM )
  297:             END IF
  298:          END DO
  299:       END DO
  300:       BWRK = NBB + NBA
  301:       DO K = 1, NBB
  302:          K1 = (K - 1) * NB + 1
  303:          K2 = MIN( K * NB, N ) + 1
  304:          DO L = K, NBB
  305:             L1 = (L - 1) * NB + 1
  306:             L2 = MIN( L * NB, N ) + 1
  307:             IF( NOTRNB ) THEN
  308:                SWORK( K, BWRK + L ) = ZLANGE( 'I', K2-K1, L2-L1,
  309:      $                                        B( K1, L1 ), LDB, WNRM )
  310:             ELSE
  311:                SWORK( L, BWRK + K ) = ZLANGE( '1', K2-K1, L2-L1,
  312:      $                                        B( K1, L1 ), LDB, WNRM )
  313:             END IF
  314:          END DO
  315:       END DO
  316: *
  317:       SGN = DBLE( ISGN )
  318:       CSGN = DCMPLX( SGN, ZERO )
  319: *
  320:       IF( NOTRNA .AND. NOTRNB ) THEN
  321: *
  322: *        Solve    A*X + ISGN*X*B = scale*C.
  323: *
  324: *        The (K,L)th block of X is determined starting from
  325: *        bottom-left corner column by column by
  326: *
  327: *         A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
  328: *
  329: *        Where
  330: *                  M                         L-1
  331: *        R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(J,L)].
  332: *                I=K+1                       J=1
  333: *
  334: *        Start loop over block rows (index = K) and block columns (index = L)
  335: *
  336:          DO K = NBA, 1, -1
  337: *
  338: *           K1: row index of the first row in X( K, L )
  339: *           K2: row index of the first row in X( K+1, L )
  340: *           so the K2 - K1 is the column count of the block X( K, L )
  341: *
  342:             K1 = (K - 1) * NB + 1
  343:             K2 = MIN( K * NB, M ) + 1
  344:             DO L = 1, NBB
  345: *
  346: *              L1: column index of the first column in X( K, L )
  347: *              L2: column index of the first column in X( K, L + 1)
  348: *              so that L2 - L1 is the row count of the block X( K, L )
  349: *
  350:                L1 = (L - 1) * NB + 1
  351:                L2 = MIN( L * NB, N ) + 1
  352: *
  353:                CALL ZTRSYL( TRANA, TRANB, ISGN, K2-K1, L2-L1,
  354:      $                      A( K1, K1 ), LDA,
  355:      $                      B( L1, L1 ), LDB,
  356:      $                      C( K1, L1 ), LDC, SCALOC, IINFO )
  357:                INFO = MAX( INFO, IINFO )
  358: *
  359:                IF( SCALOC * SWORK( K, L ) .EQ. ZERO ) THEN
  360:                   IF( SCALOC .EQ. ZERO ) THEN
  361: *                    The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
  362: *                    is larger than the product of BIGNUM**2 and cannot be
  363: *                    represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
  364: *                    Mark the computation as pointless.
  365:                      BUF = ZERO
  366:                   ELSE
  367:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  368:                   END IF
  369:                   DO JJ = 1, NBB
  370:                      DO LL = 1, NBA
  371: *                       Bound by BIGNUM to not introduce Inf. The value
  372: *                       is irrelevant; corresponding entries of the
  373: *                       solution will be flushed in consistency scaling.
  374:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  375:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  376:                      END DO
  377:                   END DO
  378:                END IF
  379:                SWORK( K, L ) = SCALOC * SWORK( K, L )
  380:                XNRM = ZLANGE( 'I', K2-K1, L2-L1, C( K1, L1 ), LDC,
  381:      $                        WNRM )
  382: *
  383:                DO I = K - 1, 1, -1
  384: *
  385: *                 C( I, L ) := C( I, L ) - A( I, K ) * C( K, L )
  386: *
  387:                   I1 = (I - 1) * NB + 1
  388:                   I2 = MIN( I * NB, M ) + 1
  389: *
  390: *                 Compute scaling factor to survive the linear update
  391: *                 simulating consistent scaling.
  392: *
  393:                   CNRM = ZLANGE( 'I', I2-I1, L2-L1, C( I1, L1 ),
  394:      $                           LDC, WNRM )
  395:                   SCAMIN = MIN( SWORK( I, L ), SWORK( K, L ) )
  396:                   CNRM = CNRM * ( SCAMIN / SWORK( I, L ) )
  397:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
  398:                   ANRM = SWORK( I, AWRK + K )
  399:                   SCALOC = DLARMM( ANRM, XNRM, CNRM )
  400:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
  401: *                    Use second scaling factor to prevent flushing to zero.
  402:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  403:                      DO JJ = 1, NBB
  404:                         DO LL = 1, NBA
  405:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  406:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  407:                         END DO
  408:                      END DO
  409:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
  410:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
  411:                   END IF
  412:                   CNRM = CNRM * SCALOC
  413:                   XNRM = XNRM * SCALOC
  414: *
  415: *                 Simultaneously apply the robust update factor and the
  416: *                 consistency scaling factor to C( I, L ) and C( K, L ).
  417: *
  418:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
  419:                   IF( SCAL .NE. ONE ) THEN
  420:                       DO JJ = L1, L2-1
  421:                          CALL ZDSCAL( K2-K1, SCAL, C( K1, JJ ), 1)
  422:                       END DO
  423:                   ENDIF
  424: *
  425:                   SCAL = ( SCAMIN / SWORK( I, L ) ) * SCALOC
  426:                   IF( SCAL .NE. ONE ) THEN
  427:                       DO LL = L1, L2-1
  428:                          CALL ZDSCAL( I2-I1, SCAL, C( I1, LL ), 1)
  429:                       END DO
  430:                   ENDIF
  431: *
  432: *                 Record current scaling factor
  433: *
  434:                   SWORK( K, L ) = SCAMIN * SCALOC
  435:                   SWORK( I, L ) = SCAMIN * SCALOC
  436: *
  437:                   CALL ZGEMM( 'N', 'N', I2-I1, L2-L1, K2-K1, -CONE,
  438:      $                        A( I1, K1 ), LDA, C( K1, L1 ), LDC,
  439:      $                        CONE, C( I1, L1 ), LDC )
  440: *
  441:                END DO
  442: *
  443:                DO J = L + 1, NBB
  444: *
  445: *                 C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( L, J )
  446: *
  447:                   J1 = (J - 1) * NB + 1
  448:                   J2 = MIN( J * NB, N ) + 1
  449: *
  450: *                 Compute scaling factor to survive the linear update
  451: *                 simulating consistent scaling.
  452: *
  453:                   CNRM = ZLANGE( 'I', K2-K1, J2-J1, C( K1, J1 ),
  454:      $                           LDC, WNRM )
  455:                   SCAMIN = MIN( SWORK( K, J ), SWORK( K, L ) )
  456:                   CNRM = CNRM * ( SCAMIN / SWORK( K, J ) )
  457:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
  458:                   BNRM = SWORK(L, BWRK + J)
  459:                   SCALOC = DLARMM( BNRM, XNRM, CNRM )
  460:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
  461: *                    Use second scaling factor to prevent flushing to zero.
  462:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  463:                      DO JJ = 1, NBB
  464:                         DO LL = 1, NBA
  465:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  466:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  467:                         END DO
  468:                      END DO
  469:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
  470:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
  471:                   END IF
  472:                   CNRM = CNRM * SCALOC
  473:                   XNRM = XNRM * SCALOC
  474: *
  475: *                 Simultaneously apply the robust update factor and the
  476: *                 consistency scaling factor to C( K, J ) and C( K, L).
  477: *
  478:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
  479:                   IF( SCAL .NE. ONE ) THEN
  480:                      DO LL = L1, L2-1
  481:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, LL ), 1 )
  482:                      END DO
  483:                   ENDIF
  484: *
  485:                   SCAL = ( SCAMIN / SWORK( K, J ) ) * SCALOC
  486:                   IF( SCAL .NE. ONE ) THEN
  487:                       DO JJ = J1, J2-1
  488:                          CALL ZDSCAL( K2-K1, SCAL, C( K1, JJ ), 1 )
  489:                       END DO
  490:                   ENDIF
  491: *
  492: *                 Record current scaling factor
  493: *
  494:                   SWORK( K, L ) = SCAMIN * SCALOC
  495:                   SWORK( K, J ) = SCAMIN * SCALOC
  496: *
  497:                   CALL ZGEMM( 'N', 'N', K2-K1, J2-J1, L2-L1, -CSGN,
  498:      $                        C( K1, L1 ), LDC, B( L1, J1 ), LDB,
  499:      $                        CONE, C( K1, J1 ), LDC )
  500:                END DO
  501:             END DO
  502:          END DO
  503:       ELSE IF( .NOT.NOTRNA .AND. NOTRNB ) THEN
  504: *
  505: *        Solve    A**H *X + ISGN*X*B = scale*C.
  506: *
  507: *        The (K,L)th block of X is determined starting from
  508: *        upper-left corner column by column by
  509: *
  510: *          A(K,K)**H*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
  511: *
  512: *        Where
  513: *                   K-1                        L-1
  514: *          R(K,L) = SUM [A(I,K)**H*X(I,L)] +ISGN*SUM [X(K,J)*B(J,L)]
  515: *                   I=1                        J=1
  516: *
  517: *        Start loop over block rows (index = K) and block columns (index = L)
  518: *
  519:          DO K = 1, NBA
  520: *
  521: *           K1: row index of the first row in X( K, L )
  522: *           K2: row index of the first row in X( K+1, L )
  523: *           so the K2 - K1 is the column count of the block X( K, L )
  524: *
  525:             K1 = (K - 1) * NB + 1
  526:             K2 = MIN( K * NB, M ) + 1
  527:             DO L = 1, NBB
  528: *
  529: *              L1: column index of the first column in X( K, L )
  530: *              L2: column index of the first column in X( K, L + 1)
  531: *              so that L2 - L1 is the row count of the block X( K, L )
  532: *
  533:                L1 = (L - 1) * NB + 1
  534:                L2 = MIN( L * NB, N ) + 1
  535: *
  536:                CALL ZTRSYL( TRANA, TRANB, ISGN, K2-K1, L2-L1,
  537:      $                      A( K1, K1 ), LDA,
  538:      $                      B( L1, L1 ), LDB,
  539:      $                      C( K1, L1 ), LDC, SCALOC, IINFO )
  540:                INFO = MAX( INFO, IINFO )
  541: *
  542:                IF( SCALOC * SWORK( K, L ) .EQ. ZERO ) THEN
  543:                   IF( SCALOC .EQ. ZERO ) THEN
  544: *                    The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
  545: *                    is larger than the product of BIGNUM**2 and cannot be
  546: *                    represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
  547: *                    Mark the computation as pointless.
  548:                      BUF = ZERO
  549:                   ELSE
  550: *                    Use second scaling factor to prevent flushing to zero.
  551:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  552:                   END IF
  553:                   DO JJ = 1, NBB
  554:                      DO LL = 1, NBA
  555: *                       Bound by BIGNUM to not introduce Inf. The value
  556: *                       is irrelevant; corresponding entries of the
  557: *                       solution will be flushed in consistency scaling.
  558:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  559:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  560:                      END DO
  561:                   END DO
  562:                END IF
  563:                SWORK( K, L ) = SCALOC * SWORK( K, L )
  564:                XNRM = ZLANGE( 'I', K2-K1, L2-L1, C( K1, L1 ), LDC,
  565:      $                        WNRM )
  566: *
  567:                DO I = K + 1, NBA
  568: *
  569: *                 C( I, L ) := C( I, L ) - A( K, I )**H * C( K, L )
  570: *
  571:                   I1 = (I - 1) * NB + 1
  572:                   I2 = MIN( I * NB, M ) + 1
  573: *
  574: *                 Compute scaling factor to survive the linear update
  575: *                 simulating consistent scaling.
  576: *
  577:                   CNRM = ZLANGE( 'I', I2-I1, L2-L1, C( I1, L1 ),
  578:      $                           LDC, WNRM )
  579:                   SCAMIN = MIN( SWORK( I, L ), SWORK( K, L ) )
  580:                   CNRM = CNRM * ( SCAMIN / SWORK( I, L ) )
  581:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
  582:                   ANRM = SWORK( I, AWRK + K )
  583:                   SCALOC = DLARMM( ANRM, XNRM, CNRM )
  584:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
  585: *                    Use second scaling factor to prevent flushing to zero.
  586:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  587:                      DO JJ = 1, NBB
  588:                         DO LL = 1, NBA
  589:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  590:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  591:                         END DO
  592:                      END DO
  593:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
  594:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
  595:                   END IF
  596:                   CNRM = CNRM * SCALOC
  597:                   XNRM = XNRM * SCALOC
  598: *
  599: *                 Simultaneously apply the robust update factor and the
  600: *                 consistency scaling factor to to C( I, L ) and C( K, L).
  601: *
  602:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
  603:                   IF( SCAL .NE. ONE ) THEN
  604:                      DO LL = L1, L2-1
  605:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, LL ), 1 )
  606:                      END DO
  607:                   ENDIF
  608: *
  609:                   SCAL = ( SCAMIN / SWORK( I, L ) ) * SCALOC
  610:                   IF( SCAL .NE. ONE ) THEN
  611:                      DO LL = L1, L2-1
  612:                         CALL ZDSCAL( I2-I1, SCAL, C( I1, LL ), 1 )
  613:                      END DO
  614:                   ENDIF
  615: *
  616: *                 Record current scaling factor
  617: *
  618:                   SWORK( K, L ) = SCAMIN * SCALOC
  619:                   SWORK( I, L ) = SCAMIN * SCALOC
  620: *
  621:                   CALL ZGEMM( 'C', 'N', I2-I1, L2-L1, K2-K1, -CONE,
  622:      $                        A( K1, I1 ), LDA, C( K1, L1 ), LDC,
  623:      $                        CONE, C( I1, L1 ), LDC )
  624:                END DO
  625: *
  626:                DO J = L + 1, NBB
  627: *
  628: *                 C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( L, J )
  629: *
  630:                   J1 = (J - 1) * NB + 1
  631:                   J2 = MIN( J * NB, N ) + 1
  632: *
  633: *                 Compute scaling factor to survive the linear update
  634: *                 simulating consistent scaling.
  635: *
  636:                   CNRM = ZLANGE( 'I', K2-K1, J2-J1, C( K1, J1 ),
  637:      $                           LDC, WNRM )
  638:                   SCAMIN = MIN( SWORK( K, J ), SWORK( K, L ) )
  639:                   CNRM = CNRM * ( SCAMIN / SWORK( K, J ) )
  640:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
  641:                   BNRM = SWORK( L, BWRK + J )
  642:                   SCALOC = DLARMM( BNRM, XNRM, CNRM )
  643:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
  644: *                    Use second scaling factor to prevent flushing to zero.
  645:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  646:                      DO JJ = 1, NBB
  647:                         DO LL = 1, NBA
  648:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  649:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  650:                         END DO
  651:                      END DO
  652:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
  653:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
  654:                   END IF
  655:                   CNRM = CNRM * SCALOC
  656:                   XNRM = XNRM * SCALOC
  657: *
  658: *                 Simultaneously apply the robust update factor and the
  659: *                 consistency scaling factor to to C( K, J ) and C( K, L).
  660: *
  661:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
  662:                   IF( SCAL .NE. ONE ) THEN
  663:                       DO LL = L1, L2-1
  664:                          CALL ZDSCAL( K2-K1, SCAL, C( K1, LL ), 1 )
  665:                       END DO
  666:                   ENDIF
  667: *
  668:                   SCAL = ( SCAMIN / SWORK( K, J ) ) * SCALOC
  669:                   IF( SCAL .NE. ONE ) THEN
  670:                      DO JJ = J1, J2-1
  671:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, JJ ), 1 )
  672:                      END DO
  673:                   ENDIF
  674: *
  675: *                 Record current scaling factor
  676: *
  677:                   SWORK( K, L ) = SCAMIN * SCALOC
  678:                   SWORK( K, J ) = SCAMIN * SCALOC
  679: *
  680:                   CALL ZGEMM( 'N', 'N', K2-K1, J2-J1, L2-L1, -CSGN,
  681:      $                        C( K1, L1 ), LDC, B( L1, J1 ), LDB,
  682:      $                        CONE, C( K1, J1 ), LDC )
  683:                END DO
  684:             END DO
  685:          END DO
  686:       ELSE IF( .NOT.NOTRNA .AND. .NOT.NOTRNB ) THEN
  687: *
  688: *        Solve    A**H *X + ISGN*X*B**H = scale*C.
  689: *
  690: *        The (K,L)th block of X is determined starting from
  691: *        top-right corner column by column by
  692: *
  693: *           A(K,K)**H*X(K,L) + ISGN*X(K,L)*B(L,L)**H = C(K,L) - R(K,L)
  694: *
  695: *        Where
  696: *                     K-1                          N
  697: *            R(K,L) = SUM [A(I,K)**H*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)**H].
  698: *                     I=1                        J=L+1
  699: *
  700: *        Start loop over block rows (index = K) and block columns (index = L)
  701: *
  702:          DO K = 1, NBA
  703: *
  704: *           K1: row index of the first row in X( K, L )
  705: *           K2: row index of the first row in X( K+1, L )
  706: *           so the K2 - K1 is the column count of the block X( K, L )
  707: *
  708:             K1 = (K - 1) * NB + 1
  709:             K2 = MIN( K * NB, M ) + 1
  710:             DO L = NBB, 1, -1
  711: *
  712: *              L1: column index of the first column in X( K, L )
  713: *              L2: column index of the first column in X( K, L + 1)
  714: *              so that L2 - L1 is the row count of the block X( K, L )
  715: *
  716:                L1 = (L - 1) * NB + 1
  717:                L2 = MIN( L * NB, N ) + 1
  718: *
  719:                CALL ZTRSYL( TRANA, TRANB, ISGN, K2-K1, L2-L1,
  720:      $                      A( K1, K1 ), LDA,
  721:      $                      B( L1, L1 ), LDB,
  722:      $                      C( K1, L1 ), LDC, SCALOC, IINFO )
  723:                INFO = MAX( INFO, IINFO )
  724: *
  725:                IF( SCALOC * SWORK( K, L ) .EQ. ZERO ) THEN
  726:                   IF( SCALOC .EQ. ZERO ) THEN
  727: *                    The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
  728: *                    is larger than the product of BIGNUM**2 and cannot be
  729: *                    represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
  730: *                    Mark the computation as pointless.
  731:                      BUF = ZERO
  732:                   ELSE
  733: *                    Use second scaling factor to prevent flushing to zero.
  734:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  735:                   END IF
  736:                   DO JJ = 1, NBB
  737:                      DO LL = 1, NBA
  738: *                       Bound by BIGNUM to not introduce Inf. The value
  739: *                       is irrelevant; corresponding entries of the
  740: *                       solution will be flushed in consistency scaling.
  741:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  742:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  743:                      END DO
  744:                   END DO
  745:                END IF
  746:                SWORK( K, L ) = SCALOC * SWORK( K, L )
  747:                XNRM = ZLANGE( 'I', K2-K1, L2-L1, C( K1, L1 ), LDC,
  748:      $                        WNRM )
  749: *
  750:                DO I = K + 1, NBA
  751: *
  752: *                 C( I, L ) := C( I, L ) - A( K, I )**H * C( K, L )
  753: *
  754:                   I1 = (I - 1) * NB + 1
  755:                   I2 = MIN( I * NB, M ) + 1
  756: *
  757: *                 Compute scaling factor to survive the linear update
  758: *                 simulating consistent scaling.
  759: *
  760:                   CNRM = ZLANGE( 'I', I2-I1, L2-L1, C( I1, L1 ),
  761:      $                           LDC, WNRM )
  762:                   SCAMIN = MIN( SWORK( I, L ), SWORK( K, L ) )
  763:                   CNRM = CNRM * ( SCAMIN / SWORK( I, L ) )
  764:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
  765:                   ANRM = SWORK( I, AWRK + K )
  766:                   SCALOC = DLARMM( ANRM, XNRM, CNRM )
  767:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
  768: *                    Use second scaling factor to prevent flushing to zero.
  769:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  770:                      DO JJ = 1, NBB
  771:                         DO LL = 1, NBA
  772:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  773:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  774:                         END DO
  775:                      END DO
  776:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
  777:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
  778:                   END IF
  779:                   CNRM = CNRM * SCALOC
  780:                   XNRM = XNRM * SCALOC
  781: *
  782: *                 Simultaneously apply the robust update factor and the
  783: *                 consistency scaling factor to C( I, L ) and C( K, L).
  784: *
  785:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
  786:                   IF( SCAL .NE. ONE ) THEN
  787:                      DO LL = L1, L2-1
  788:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, LL ), 1 )
  789:                      END DO
  790:                   ENDIF
  791: *
  792:                   SCAL = ( SCAMIN / SWORK( I, L ) ) * SCALOC
  793:                   IF( SCAL .NE. ONE ) THEN
  794:                      DO LL = L1, L2-1
  795:                         CALL ZDSCAL( I2-I1, SCAL, C( I1, LL ), 1 )
  796:                      END DO
  797:                   ENDIF
  798: *
  799: *                 Record current scaling factor
  800: *
  801:                   SWORK( K, L ) = SCAMIN * SCALOC
  802:                   SWORK( I, L ) = SCAMIN * SCALOC
  803: *
  804:                   CALL ZGEMM( 'C', 'N', I2-I1, L2-L1, K2-K1, -CONE,
  805:      $                        A( K1, I1 ), LDA, C( K1, L1 ), LDC,
  806:      $                        CONE, C( I1, L1 ), LDC )
  807:                END DO
  808: *
  809:                DO J = 1, L - 1
  810: *
  811: *                 C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( J, L )**H
  812: *
  813:                   J1 = (J - 1) * NB + 1
  814:                   J2 = MIN( J * NB, N ) + 1
  815: *
  816: *                 Compute scaling factor to survive the linear update
  817: *                 simulating consistent scaling.
  818: *
  819:                   CNRM = ZLANGE( 'I', K2-K1, J2-J1, C( K1, J1 ),
  820:      $                           LDC, WNRM )
  821:                   SCAMIN = MIN( SWORK( K, J ), SWORK( K, L ) )
  822:                   CNRM = CNRM * ( SCAMIN / SWORK( K, J ) )
  823:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
  824:                   BNRM = SWORK( L, BWRK + J )
  825:                   SCALOC = DLARMM( BNRM, XNRM, CNRM )
  826:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
  827: *                    Use second scaling factor to prevent flushing to zero.
  828:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  829:                      DO JJ = 1, NBB
  830:                         DO LL = 1, NBA
  831:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  832:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  833:                         END DO
  834:                      END DO
  835:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
  836:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
  837:                   END IF
  838:                   CNRM = CNRM * SCALOC
  839:                   XNRM = XNRM * SCALOC
  840: *
  841: *                 Simultaneously apply the robust update factor and the
  842: *                 consistency scaling factor to C( K, J ) and C( K, L).
  843: *
  844:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
  845:                   IF( SCAL .NE. ONE ) THEN
  846:                      DO LL = L1, L2-1
  847:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, LL ), 1)
  848:                      END DO
  849:                   ENDIF
  850: *
  851:                   SCAL = ( SCAMIN / SWORK( K, J ) ) * SCALOC
  852:                   IF( SCAL .NE. ONE ) THEN
  853:                      DO JJ = J1, J2-1
  854:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, JJ ), 1 )
  855:                      END DO
  856:                   ENDIF
  857: *
  858: *                 Record current scaling factor
  859: *
  860:                   SWORK( K, L ) = SCAMIN * SCALOC
  861:                   SWORK( K, J ) = SCAMIN * SCALOC
  862: *
  863:                   CALL ZGEMM( 'N', 'C', K2-K1, J2-J1, L2-L1, -CSGN,
  864:      $                        C( K1, L1 ), LDC, B( J1, L1 ), LDB,
  865:      $                        CONE, C( K1, J1 ), LDC )
  866:                END DO
  867:             END DO
  868:          END DO
  869:       ELSE IF( NOTRNA .AND. .NOT.NOTRNB ) THEN
  870: *
  871: *        Solve    A*X + ISGN*X*B**H = scale*C.
  872: *
  873: *        The (K,L)th block of X is determined starting from
  874: *        bottom-right corner column by column by
  875: *
  876: *            A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L)**H = C(K,L) - R(K,L)
  877: *
  878: *        Where
  879: *                      M                          N
  880: *            R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)**H].
  881: *                    I=K+1                      J=L+1
  882: *
  883: *        Start loop over block rows (index = K) and block columns (index = L)
  884: *
  885:          DO K = NBA, 1, -1
  886: *
  887: *           K1: row index of the first row in X( K, L )
  888: *           K2: row index of the first row in X( K+1, L )
  889: *           so the K2 - K1 is the column count of the block X( K, L )
  890: *
  891:             K1 = (K - 1) * NB + 1
  892:             K2 = MIN( K * NB, M ) + 1
  893:             DO L = NBB, 1, -1
  894: *
  895: *              L1: column index of the first column in X( K, L )
  896: *              L2: column index of the first column in X( K, L + 1)
  897: *              so that L2 - L1 is the row count of the block X( K, L )
  898: *
  899:                L1 = (L - 1) * NB + 1
  900:                L2 = MIN( L * NB, N ) + 1
  901: *
  902:                CALL ZTRSYL( TRANA, TRANB, ISGN, K2-K1, L2-L1,
  903:      $                      A( K1, K1 ), LDA,
  904:      $                      B( L1, L1 ), LDB,
  905:      $                      C( K1, L1 ), LDC, SCALOC, IINFO )
  906:                INFO = MAX( INFO, IINFO )
  907: *
  908:                IF( SCALOC * SWORK( K, L ) .EQ. ZERO ) THEN
  909:                   IF( SCALOC .EQ. ZERO ) THEN
  910: *                    The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
  911: *                    is larger than the product of BIGNUM**2 and cannot be
  912: *                    represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
  913: *                    Mark the computation as pointless.
  914:                      BUF = ZERO
  915:                   ELSE
  916: *                    Use second scaling factor to prevent flushing to zero.
  917:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  918:                   END IF
  919:                   DO JJ = 1, NBB
  920:                      DO LL = 1, NBA
  921: *                       Bound by BIGNUM to not introduce Inf. The value
  922: *                       is irrelevant; corresponding entries of the
  923: *                       solution will be flushed in consistency scaling.
  924:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  925:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  926:                      END DO
  927:                   END DO
  928:                END IF
  929:                SWORK( K, L ) = SCALOC * SWORK( K, L )
  930:                XNRM = ZLANGE( 'I', K2-K1, L2-L1, C( K1, L1 ), LDC,
  931:      $                        WNRM )
  932: *
  933:                DO I = 1, K - 1
  934: *
  935: *                 C( I, L ) := C( I, L ) - A( I, K ) * C( K, L )
  936: *
  937:                   I1 = (I - 1) * NB + 1
  938:                   I2 = MIN( I * NB, M ) + 1
  939: *
  940: *                 Compute scaling factor to survive the linear update
  941: *                 simulating consistent scaling.
  942: *
  943:                   CNRM = ZLANGE( 'I', I2-I1, L2-L1, C( I1, L1 ),
  944:      $                           LDC, WNRM )
  945:                   SCAMIN = MIN( SWORK( I, L ), SWORK( K, L ) )
  946:                   CNRM = CNRM * ( SCAMIN / SWORK( I, L ) )
  947:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
  948:                   ANRM = SWORK( I, AWRK + K )
  949:                   SCALOC = DLARMM( ANRM, XNRM, CNRM )
  950:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
  951: *                    Use second scaling factor to prevent flushing to zero.
  952:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
  953:                      DO JJ = 1, NBB
  954:                         DO LL = 1, NBA
  955:                         SWORK( LL, JJ ) = MIN( BIGNUM,
  956:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
  957:                         END DO
  958:                      END DO
  959:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
  960:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
  961:                   END IF
  962:                   CNRM = CNRM * SCALOC
  963:                   XNRM = XNRM * SCALOC
  964: *
  965: *                 Simultaneously apply the robust update factor and the
  966: *                 consistency scaling factor to C( I, L ) and C( K, L).
  967: *
  968:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
  969:                   IF( SCAL .NE. ONE ) THEN
  970:                      DO LL = L1, L2-1
  971:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, LL ), 1 )
  972:                      END DO
  973:                   ENDIF
  974: *
  975:                   SCAL = ( SCAMIN / SWORK( I, L ) ) * SCALOC
  976:                   IF( SCAL .NE. ONE ) THEN
  977:                      DO LL = L1, L2-1
  978:                         CALL ZDSCAL( I2-I1, SCAL, C( I1, LL ), 1 )
  979:                      END DO
  980:                   ENDIF
  981: *
  982: *                 Record current scaling factor
  983: *
  984:                   SWORK( K, L ) = SCAMIN * SCALOC
  985:                   SWORK( I, L ) = SCAMIN * SCALOC
  986: *
  987:                   CALL ZGEMM( 'N', 'N', I2-I1, L2-L1, K2-K1, -CONE,
  988:      $                        A( I1, K1 ), LDA, C( K1, L1 ), LDC,
  989:      $                        CONE, C( I1, L1 ), LDC )
  990: *
  991:                END DO
  992: *
  993:                DO J = 1, L - 1
  994: *
  995: *                 C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( J, L )**H
  996: *
  997:                   J1 = (J - 1) * NB + 1
  998:                   J2 = MIN( J * NB, N ) + 1
  999: *
 1000: *                 Compute scaling factor to survive the linear update
 1001: *                 simulating consistent scaling.
 1002: *
 1003:                   CNRM = ZLANGE( 'I', K2-K1, J2-J1, C( K1, J1 ),
 1004:      $                           LDC, WNRM )
 1005:                   SCAMIN = MIN( SWORK( K, J ), SWORK( K, L ) )
 1006:                   CNRM = CNRM * ( SCAMIN / SWORK( K, J ) )
 1007:                   XNRM = XNRM * ( SCAMIN / SWORK( K, L ) )
 1008:                   BNRM = SWORK( L, BWRK + J )
 1009:                   SCALOC = DLARMM( BNRM, XNRM, CNRM )
 1010:                   IF( SCALOC * SCAMIN .EQ. ZERO ) THEN
 1011: *                    Use second scaling factor to prevent flushing to zero.
 1012:                      BUF = BUF*2.D0**EXPONENT( SCALOC )
 1013:                      DO JJ = 1, NBB
 1014:                         DO LL = 1, NBA
 1015:                         SWORK( LL, JJ ) = MIN( BIGNUM,
 1016:      $                     SWORK( LL, JJ ) / 2.D0**EXPONENT( SCALOC ) )
 1017:                         END DO
 1018:                      END DO
 1019:                      SCAMIN = SCAMIN / 2.D0**EXPONENT( SCALOC )
 1020:                      SCALOC = SCALOC / 2.D0**EXPONENT( SCALOC )
 1021:                   END IF
 1022:                   CNRM = CNRM * SCALOC
 1023:                   XNRM = XNRM * SCALOC
 1024: *
 1025: *                 Simultaneously apply the robust update factor and the
 1026: *                 consistency scaling factor to C( K, J ) and C( K, L).
 1027: *
 1028:                   SCAL = ( SCAMIN / SWORK( K, L ) ) * SCALOC
 1029:                   IF( SCAL .NE. ONE ) THEN
 1030:                      DO JJ = L1, L2-1
 1031:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, JJ ), 1 )
 1032:                      END DO
 1033:                   ENDIF
 1034: *
 1035:                   SCAL = ( SCAMIN / SWORK( K, J ) ) * SCALOC
 1036:                   IF( SCAL .NE. ONE ) THEN
 1037:                      DO JJ = J1, J2-1
 1038:                         CALL ZDSCAL( K2-K1, SCAL, C( K1, JJ ), 1 )
 1039:                      END DO
 1040:                   ENDIF
 1041: *
 1042: *                 Record current scaling factor
 1043: *
 1044:                   SWORK( K, L ) = SCAMIN * SCALOC
 1045:                   SWORK( K, J ) = SCAMIN * SCALOC
 1046: *
 1047:                   CALL ZGEMM( 'N', 'C', K2-K1, J2-J1, L2-L1, -CSGN,
 1048:      $                        C( K1, L1 ), LDC, B( J1, L1 ), LDB,
 1049:      $                        CONE, C( K1, J1 ), LDC )
 1050:                END DO
 1051:             END DO
 1052:          END DO
 1053: *
 1054:       END IF
 1055: *
 1056: *     Reduce local scaling factors
 1057: *
 1058:       SCALE = SWORK( 1, 1 )
 1059:       DO K = 1, NBA
 1060:          DO L = 1, NBB
 1061:             SCALE = MIN( SCALE, SWORK( K, L ) )
 1062:          END DO
 1063:       END DO
 1064:       IF( SCALE .EQ. ZERO ) THEN
 1065: *
 1066: *        The magnitude of the largest entry of the solution is larger
 1067: *        than the product of BIGNUM**2 and cannot be represented in the
 1068: *        form (1/SCALE)*X if SCALE is DOUBLE PRECISION. Set SCALE to
 1069: *        zero and give up.
 1070: *
 1071:          SWORK(1,1) = MAX( NBA, NBB )
 1072:          SWORK(2,1) = 2 * NBB + NBA
 1073:          RETURN
 1074:       END IF
 1075: *
 1076: *     Realize consistent scaling
 1077: *
 1078:       DO K = 1, NBA
 1079:          K1 = (K - 1) * NB + 1
 1080:          K2 = MIN( K * NB, M ) + 1
 1081:          DO L = 1, NBB
 1082:             L1 = (L - 1) * NB + 1
 1083:             L2 = MIN( L * NB, N ) + 1
 1084:             SCAL = SCALE / SWORK( K, L )
 1085:             IF( SCAL .NE. ONE ) THEN
 1086:                DO LL = L1, L2-1
 1087:                   CALL ZDSCAL( K2-K1, SCAL, C( K1, LL ), 1 )
 1088:                END DO
 1089:             ENDIF
 1090:          END DO
 1091:       END DO
 1092: *
 1093:       IF( BUF .NE. ONE .AND. BUF.GT.ZERO ) THEN
 1094: *
 1095: *        Decrease SCALE as much as possible.
 1096: *
 1097:          SCALOC = MIN( SCALE / SMLNUM, ONE / BUF )
 1098:          BUF = BUF * SCALOC
 1099:          SCALE = SCALE / SCALOC
 1100:       END IF
 1101: *
 1102:       IF( BUF.NE.ONE .AND. BUF.GT.ZERO ) THEN
 1103: *
 1104: *        In case of overly aggressive scaling during the computation,
 1105: *        flushing of the global scale factor may be prevented by
 1106: *        undoing some of the scaling. This step is to ensure that
 1107: *        this routine flushes only scale factors that TRSYL also
 1108: *        flushes and be usable as a drop-in replacement.
 1109: *
 1110: *        How much can the normwise largest entry be upscaled?
 1111: *
 1112:          SCAL = MAX( ABS( DBLE( C( 1, 1 ) ) ),
 1113:      $               ABS( DIMAG( C ( 1, 1 ) ) ) )
 1114:          DO K = 1, M
 1115:             DO L = 1, N
 1116:                SCAL = MAX( SCAL, ABS( DBLE ( C( K, L ) ) ),
 1117:      $                     ABS( DIMAG ( C( K, L ) ) ) )
 1118:             END DO
 1119:          END DO
 1120: *
 1121: *        Increase BUF as close to 1 as possible and apply scaling.
 1122: *
 1123:          SCALOC = MIN( BIGNUM / SCAL, ONE / BUF )
 1124:          BUF = BUF * SCALOC
 1125:          CALL ZLASCL( 'G', -1, -1, ONE, SCALOC, M, N, C, LDC, IINFO )
 1126:       END IF
 1127: *
 1128: *     Combine with buffer scaling factor. SCALE will be flushed if
 1129: *     BUF is less than one here.
 1130: *
 1131:       SCALE = SCALE * BUF
 1132: *
 1133: *     Restore workspace dimensions
 1134: *
 1135:       SWORK(1,1) = MAX( NBA, NBB )
 1136:       SWORK(2,1) = 2 * NBB + NBA
 1137: *
 1138:       RETURN
 1139: *
 1140: *     End of ZTRSYL3
 1141: *
 1142:       END

CVSweb interface <joel.bertrand@systella.fr>