Annotation of rpl/lapack/lapack/ztrsyl3.f, revision 1.1
1.1 ! bertrand 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>