LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ ctrsyl3()

subroutine ctrsyl3 ( character trana,
character tranb,
integer isgn,
integer m,
integer n,
complex, dimension( lda, * ) a,
integer lda,
complex, dimension( ldb, * ) b,
integer ldb,
complex, dimension( ldc, * ) c,
integer ldc,
real scale,
real, dimension( ldswork, * ) swork,
integer ldswork,
integer info )

CTRSYL3

Purpose:
!>
!>  CTRSYL3 solves the complex Sylvester matrix equation:
!>
!>     op(A)*X + X*op(B) = scale*C or
!>     op(A)*X - X*op(B) = scale*C,
!>
!>  where op(A) = A or A**H, and  A and B are both upper triangular. A is
!>  M-by-M and B is N-by-N; the right hand side C and the solution X are
!>  M-by-N; and scale is an output scale factor, set <= 1 to avoid
!>  overflow in X.
!>
!>  This is the block version of the algorithm.
!> 
Parameters
[in]TRANA
!>          TRANA is CHARACTER*1
!>          Specifies the option op(A):
!>          = 'N': op(A) = A    (No transpose)
!>          = 'C': op(A) = A**H (Conjugate transpose)
!> 
[in]TRANB
!>          TRANB is CHARACTER*1
!>          Specifies the option op(B):
!>          = 'N': op(B) = B    (No transpose)
!>          = 'C': op(B) = B**H (Conjugate transpose)
!> 
[in]ISGN
!>          ISGN is INTEGER
!>          Specifies the sign in the equation:
!>          = +1: solve op(A)*X + X*op(B) = scale*C
!>          = -1: solve op(A)*X - X*op(B) = scale*C
!> 
[in]M
!>          M is INTEGER
!>          The order of the matrix A, and the number of rows in the
!>          matrices X and C. M >= 0.
!> 
[in]N
!>          N is INTEGER
!>          The order of the matrix B, and the number of columns in the
!>          matrices X and C. N >= 0.
!> 
[in]A
!>          A is COMPLEX array, dimension (LDA,M)
!>          The upper triangular matrix A.
!> 
[in]LDA
!>          LDA is INTEGER
!>          The leading dimension of the array A. LDA >= max(1,M).
!> 
[in]B
!>          B is COMPLEX array, dimension (LDB,N)
!>          The upper triangular matrix B.
!> 
[in]LDB
!>          LDB is INTEGER
!>          The leading dimension of the array B. LDB >= max(1,N).
!> 
[in,out]C
!>          C is COMPLEX array, dimension (LDC,N)
!>          On entry, the M-by-N right hand side matrix C.
!>          On exit, C is overwritten by the solution matrix X.
!> 
[in]LDC
!>          LDC is INTEGER
!>          The leading dimension of the array C. LDC >= max(1,M)
!> 
[out]SCALE
!>          SCALE is REAL
!>          The scale factor, scale, set <= 1 to avoid overflow in X.
!> 
[out]SWORK
!>          SWORK is REAL array, dimension (MAX(2, ROWS), MAX(1,COLS)).
!>          On exit, if INFO = 0, SWORK(1) returns the optimal value ROWS
!>          and SWORK(2) returns the optimal COLS.
!> 
[in]LDSWORK
!>          LDSWORK is INTEGER
!>          LDSWORK >= MAX(2,ROWS), where ROWS = ((M + NB - 1) / NB + 1)
!>          and NB is the optimal block size.
!>
!>          If LDSWORK = -1, then a workspace query is assumed; the routine
!>          only calculates the optimal dimensions of the SWORK matrix,
!>          returns these values as the first and second entry of the SWORK
!>          matrix, and no error message related LWORK is issued by XERBLA.
!> 
[out]INFO
!>          INFO is INTEGER
!>          = 0: successful exit
!>          < 0: if INFO = -i, the i-th argument had an illegal value
!>          = 1: A and B have common or very close eigenvalues; perturbed
!>               values were used to solve the equation (but the matrices
!>               A and B are unchanged).
!> 

Definition at line 167 of file ctrsyl3.f.

169 IMPLICIT NONE
170*
171* .. Scalar Arguments ..
172 CHARACTER TRANA, TRANB
173 INTEGER INFO, ISGN, LDA, LDB, LDC, LDSWORK, M, N
174 REAL SCALE
175* ..
176* .. Array Arguments ..
177 COMPLEX A( LDA, * ), B( LDB, * ), C( LDC, * )
178 REAL SWORK( LDSWORK, * )
179* ..
180* .. Parameters ..
181 REAL ZERO, ONE
182 parameter( zero = 0.0e+0, one = 1.0e+0 )
183 COMPLEX CONE
184 parameter( cone = ( 1.0e+0, 0.0e+0 ) )
185* ..
186* .. Local Scalars ..
187 LOGICAL NOTRNA, NOTRNB, LQUERY
188 INTEGER AWRK, BWRK, I, I1, I2, IINFO, J, J1, J2, JJ,
189 $ K, K1, K2, L, L1, L2, LL, NBA, NB, NBB
190 REAL ANRM, BIGNUM, BNRM, CNRM, SCAL, SCALOC,
191 $ SCAMIN, SGN, XNRM, BUF, SMLNUM
192 COMPLEX CSGN
193* ..
194* .. Local Arrays ..
195 REAL WNRM( MAX( M, N ) )
196* ..
197* .. External Functions ..
198 LOGICAL LSAME
199 INTEGER ILAENV
200 REAL CLANGE, SLAMCH, SLARMM
201 EXTERNAL clange, ilaenv, lsame, slamch,
202 $ slarmm
203* ..
204* .. External Subroutines ..
205 EXTERNAL csscal, cgemm, clascl, ctrsyl,
206 $ xerbla
207* ..
208* .. Intrinsic Functions ..
209 INTRINSIC abs, aimag, exponent, max, min, real
210* ..
211* .. Executable Statements ..
212*
213* Decode and Test input parameters
214*
215 notrna = lsame( trana, 'N' )
216 notrnb = lsame( tranb, 'N' )
217*
218* Use the same block size for all matrices.
219*
220 nb = max( 8, ilaenv( 1, 'CTRSYL', '', m, n, -1, -1) )
221*
222* Compute number of blocks in A and B
223*
224 nba = max( 1, (m + nb - 1) / nb )
225 nbb = max( 1, (n + nb - 1) / nb )
226*
227* Compute workspace
228*
229 info = 0
230 lquery = ( ldswork.EQ.-1 )
231 IF( lquery ) THEN
232 ldswork = 2
233 swork(1,1) = real( max( nba, nbb ) )
234 swork(2,1) = real( 2 * nbb + nba )
235 END IF
236*
237* Test the input arguments
238*
239 IF( .NOT.notrna .AND. .NOT. lsame( trana, 'C' ) ) THEN
240 info = -1
241 ELSE IF( .NOT.notrnb .AND. .NOT. lsame( tranb, 'C' ) ) THEN
242 info = -2
243 ELSE IF( isgn.NE.1 .AND. isgn.NE.-1 ) THEN
244 info = -3
245 ELSE IF( m.LT.0 ) THEN
246 info = -4
247 ELSE IF( n.LT.0 ) THEN
248 info = -5
249 ELSE IF( lda.LT.max( 1, m ) ) THEN
250 info = -7
251 ELSE IF( ldb.LT.max( 1, n ) ) THEN
252 info = -9
253 ELSE IF( ldc.LT.max( 1, m ) ) THEN
254 info = -11
255 END IF
256 IF( info.NE.0 ) THEN
257 CALL xerbla( 'CTRSYL3', -info )
258 RETURN
259 ELSE IF( lquery ) THEN
260 RETURN
261 END IF
262*
263* Quick return if possible
264*
265 scale = one
266 IF( m.EQ.0 .OR. n.EQ.0 )
267 $ RETURN
268*
269* Use unblocked code for small problems or if insufficient
270* workspace is provided
271*
272 IF( min( nba, nbb ).EQ.1 .OR. ldswork.LT.max( nba, nbb ) ) THEN
273 CALL ctrsyl( trana, tranb, isgn, m, n, a, lda, b, ldb,
274 $ c, ldc, scale, info )
275 RETURN
276 END IF
277*
278* Set constants to control overflow
279*
280 smlnum = slamch( 'S' )
281 bignum = one / smlnum
282*
283* Set local scaling factors.
284*
285 DO l = 1, nbb
286 DO k = 1, nba
287 swork( k, l ) = one
288 END DO
289 END DO
290*
291* Fallback scaling factor to prevent flushing of SWORK( K, L ) to zero.
292* This scaling is to ensure compatibility with TRSYL and may get flushed.
293*
294 buf = one
295*
296* Compute upper bounds of blocks of A and B
297*
298 awrk = nbb
299 DO k = 1, nba
300 k1 = (k - 1) * nb + 1
301 k2 = min( k * nb, m ) + 1
302 DO l = k, nba
303 l1 = (l - 1) * nb + 1
304 l2 = min( l * nb, m ) + 1
305 IF( notrna ) THEN
306 swork( k, awrk + l ) = clange( 'I', k2-k1, l2-l1,
307 $ a( k1, l1 ), lda, wnrm )
308 ELSE
309 swork( l, awrk + k ) = clange( '1', k2-k1, l2-l1,
310 $ a( k1, l1 ), lda, wnrm )
311 END IF
312 END DO
313 END DO
314 bwrk = nbb + nba
315 DO k = 1, nbb
316 k1 = (k - 1) * nb + 1
317 k2 = min( k * nb, n ) + 1
318 DO l = k, nbb
319 l1 = (l - 1) * nb + 1
320 l2 = min( l * nb, n ) + 1
321 IF( notrnb ) THEN
322 swork( k, bwrk + l ) = clange( 'I', k2-k1, l2-l1,
323 $ b( k1, l1 ), ldb, wnrm )
324 ELSE
325 swork( l, bwrk + k ) = clange( '1', k2-k1, l2-l1,
326 $ b( k1, l1 ), ldb, wnrm )
327 END IF
328 END DO
329 END DO
330*
331 sgn = real( isgn )
332 csgn = cmplx( sgn, zero )
333*
334 IF( notrna .AND. notrnb ) THEN
335*
336* Solve A*X + ISGN*X*B = scale*C.
337*
338* The (K,L)th block of X is determined starting from
339* bottom-left corner column by column by
340*
341* A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
342*
343* Where
344* M L-1
345* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(J,L)].
346* I=K+1 J=1
347*
348* Start loop over block rows (index = K) and block columns (index = L)
349*
350 DO k = nba, 1, -1
351*
352* K1: row index of the first row in X( K, L )
353* K2: row index of the first row in X( K+1, L )
354* so the K2 - K1 is the column count of the block X( K, L )
355*
356 k1 = (k - 1) * nb + 1
357 k2 = min( k * nb, m ) + 1
358 DO l = 1, nbb
359*
360* L1: column index of the first column in X( K, L )
361* L2: column index of the first column in X( K, L + 1)
362* so that L2 - L1 is the row count of the block X( K, L )
363*
364 l1 = (l - 1) * nb + 1
365 l2 = min( l * nb, n ) + 1
366*
367 CALL ctrsyl( trana, tranb, isgn, k2-k1, l2-l1,
368 $ a( k1, k1 ), lda,
369 $ b( l1, l1 ), ldb,
370 $ c( k1, l1 ), ldc, scaloc, iinfo )
371 info = max( info, iinfo )
372*
373 IF( scaloc * swork( k, l ) .EQ. zero ) THEN
374 IF( scaloc .EQ. zero ) THEN
375* The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
376* is larger than the product of BIGNUM**2 and cannot be
377* represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
378* Mark the computation as pointless.
379 buf = zero
380 ELSE
381* Use second scaling factor to prevent flushing to zero.
382 buf = buf*2.e0**exponent( scaloc )
383 END IF
384 DO jj = 1, nbb
385 DO ll = 1, nba
386* Bound by BIGNUM to not introduce Inf. The value
387* is irrelevant; corresponding entries of the
388* solution will be flushed in consistency scaling.
389 swork( ll, jj ) = min( bignum,
390 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
391 END DO
392 END DO
393 END IF
394 swork( k, l ) = scaloc * swork( k, l )
395 xnrm = clange( 'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
396 $ wnrm )
397*
398 DO i = k - 1, 1, -1
399*
400* C( I, L ) := C( I, L ) - A( I, K ) * C( K, L )
401*
402 i1 = (i - 1) * nb + 1
403 i2 = min( i * nb, m ) + 1
404*
405* Compute scaling factor to survive the linear update
406* simulating consistent scaling.
407*
408 cnrm = clange( 'I', i2-i1, l2-l1, c( i1, l1 ),
409 $ ldc, wnrm )
410 scamin = min( swork( i, l ), swork( k, l ) )
411 cnrm = cnrm * ( scamin / swork( i, l ) )
412 xnrm = xnrm * ( scamin / swork( k, l ) )
413 anrm = swork( i, awrk + k )
414 scaloc = slarmm( anrm, xnrm, cnrm )
415 IF( scaloc * scamin .EQ. zero ) THEN
416* Use second scaling factor to prevent flushing to zero.
417 buf = buf*2.e0**exponent( scaloc )
418 DO jj = 1, nbb
419 DO ll = 1, nba
420 swork( ll, jj ) = min( bignum,
421 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
422 END DO
423 END DO
424 scamin = scamin / 2.e0**exponent( scaloc )
425 scaloc = scaloc / 2.e0**exponent( scaloc )
426 END IF
427 cnrm = cnrm * scaloc
428 xnrm = xnrm * scaloc
429*
430* Simultaneously apply the robust update factor and the
431* consistency scaling factor to C( I, L ) and C( K, L ).
432*
433 scal = ( scamin / swork( k, l ) ) * scaloc
434 IF( scal.NE.one ) THEN
435 DO jj = l1, l2-1
436 CALL csscal( k2-k1, scal, c( k1, jj ), 1)
437 END DO
438 ENDIF
439*
440 scal = ( scamin / swork( i, l ) ) * scaloc
441 IF( scal.NE.one ) THEN
442 DO ll = l1, l2-1
443 CALL csscal( i2-i1, scal, c( i1, ll ), 1)
444 END DO
445 ENDIF
446*
447* Record current scaling factor
448*
449 swork( k, l ) = scamin * scaloc
450 swork( i, l ) = scamin * scaloc
451*
452 CALL cgemm( 'N', 'N', i2-i1, l2-l1, k2-k1, -cone,
453 $ a( i1, k1 ), lda, c( k1, l1 ), ldc,
454 $ cone, c( i1, l1 ), ldc )
455*
456 END DO
457*
458 DO j = l + 1, nbb
459*
460* C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( L, J )
461*
462 j1 = (j - 1) * nb + 1
463 j2 = min( j * nb, n ) + 1
464*
465* Compute scaling factor to survive the linear update
466* simulating consistent scaling.
467*
468 cnrm = clange( 'I', k2-k1, j2-j1, c( k1, j1 ),
469 $ ldc, wnrm )
470 scamin = min( swork( k, j ), swork( k, l ) )
471 cnrm = cnrm * ( scamin / swork( k, j ) )
472 xnrm = xnrm * ( scamin / swork( k, l ) )
473 bnrm = swork(l, bwrk + j)
474 scaloc = slarmm( bnrm, xnrm, cnrm )
475 IF( scaloc * scamin .EQ. zero ) THEN
476* Use second scaling factor to prevent flushing to zero.
477 buf = buf*2.e0**exponent( scaloc )
478 DO jj = 1, nbb
479 DO ll = 1, nba
480 swork( ll, jj ) = min( bignum,
481 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
482 END DO
483 END DO
484 scamin = scamin / 2.e0**exponent( scaloc )
485 scaloc = scaloc / 2.e0**exponent( scaloc )
486 END IF
487 cnrm = cnrm * scaloc
488 xnrm = xnrm * scaloc
489*
490* Simultaneously apply the robust update factor and the
491* consistency scaling factor to C( K, J ) and C( K, L).
492*
493 scal = ( scamin / swork( k, l ) ) * scaloc
494 IF( scal .NE. one ) THEN
495 DO ll = l1, l2-1
496 CALL csscal( k2-k1, scal, c( k1, ll ), 1 )
497 END DO
498 ENDIF
499*
500 scal = ( scamin / swork( k, j ) ) * scaloc
501 IF( scal .NE. one ) THEN
502 DO jj = j1, j2-1
503 CALL csscal( k2-k1, scal, c( k1, jj ), 1 )
504 END DO
505 ENDIF
506*
507* Record current scaling factor
508*
509 swork( k, l ) = scamin * scaloc
510 swork( k, j ) = scamin * scaloc
511*
512 CALL cgemm( 'N', 'N', k2-k1, j2-j1, l2-l1, -csgn,
513 $ c( k1, l1 ), ldc, b( l1, j1 ), ldb,
514 $ cone, c( k1, j1 ), ldc )
515 END DO
516 END DO
517 END DO
518 ELSE IF( .NOT.notrna .AND. notrnb ) THEN
519*
520* Solve A**H *X + ISGN*X*B = scale*C.
521*
522* The (K,L)th block of X is determined starting from
523* upper-left corner column by column by
524*
525* A(K,K)**H*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
526*
527* Where
528* K-1 L-1
529* R(K,L) = SUM [A(I,K)**H*X(I,L)] +ISGN*SUM [X(K,J)*B(J,L)]
530* I=1 J=1
531*
532* Start loop over block rows (index = K) and block columns (index = L)
533*
534 DO k = 1, nba
535*
536* K1: row index of the first row in X( K, L )
537* K2: row index of the first row in X( K+1, L )
538* so the K2 - K1 is the column count of the block X( K, L )
539*
540 k1 = (k - 1) * nb + 1
541 k2 = min( k * nb, m ) + 1
542 DO l = 1, nbb
543*
544* L1: column index of the first column in X( K, L )
545* L2: column index of the first column in X( K, L + 1)
546* so that L2 - L1 is the row count of the block X( K, L )
547*
548 l1 = (l - 1) * nb + 1
549 l2 = min( l * nb, n ) + 1
550*
551 CALL ctrsyl( trana, tranb, isgn, k2-k1, l2-l1,
552 $ a( k1, k1 ), lda,
553 $ b( l1, l1 ), ldb,
554 $ c( k1, l1 ), ldc, scaloc, iinfo )
555 info = max( info, iinfo )
556*
557 IF( scaloc * swork( k, l ) .EQ. zero ) THEN
558 IF( scaloc .EQ. zero ) THEN
559* The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
560* is larger than the product of BIGNUM**2 and cannot be
561* represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
562* Mark the computation as pointless.
563 buf = zero
564 ELSE
565* Use second scaling factor to prevent flushing to zero.
566 buf = buf*2.e0**exponent( scaloc )
567 END IF
568 DO jj = 1, nbb
569 DO ll = 1, nba
570* Bound by BIGNUM to not introduce Inf. The value
571* is irrelevant; corresponding entries of the
572* solution will be flushed in consistency scaling.
573 swork( ll, jj ) = min( bignum,
574 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
575 END DO
576 END DO
577 END IF
578 swork( k, l ) = scaloc * swork( k, l )
579 xnrm = clange( 'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
580 $ wnrm )
581*
582 DO i = k + 1, nba
583*
584* C( I, L ) := C( I, L ) - A( K, I )**H * C( K, L )
585*
586 i1 = (i - 1) * nb + 1
587 i2 = min( i * nb, m ) + 1
588*
589* Compute scaling factor to survive the linear update
590* simulating consistent scaling.
591*
592 cnrm = clange( 'I', i2-i1, l2-l1, c( i1, l1 ),
593 $ ldc, wnrm )
594 scamin = min( swork( i, l ), swork( k, l ) )
595 cnrm = cnrm * ( scamin / swork( i, l ) )
596 xnrm = xnrm * ( scamin / swork( k, l ) )
597 anrm = swork( i, awrk + k )
598 scaloc = slarmm( anrm, xnrm, cnrm )
599 IF( scaloc * scamin .EQ. zero ) THEN
600* Use second scaling factor to prevent flushing to zero.
601 buf = buf*2.e0**exponent( scaloc )
602 DO jj = 1, nbb
603 DO ll = 1, nba
604 swork( ll, jj ) = min( bignum,
605 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
606 END DO
607 END DO
608 scamin = scamin / 2.e0**exponent( scaloc )
609 scaloc = scaloc / 2.e0**exponent( scaloc )
610 END IF
611 cnrm = cnrm * scaloc
612 xnrm = xnrm * scaloc
613*
614* Simultaneously apply the robust update factor and the
615* consistency scaling factor to to C( I, L ) and C( K, L).
616*
617 scal = ( scamin / swork( k, l ) ) * scaloc
618 IF( scal .NE. one ) THEN
619 DO ll = l1, l2-1
620 CALL csscal( k2-k1, scal, c( k1, ll ), 1 )
621 END DO
622 ENDIF
623*
624 scal = ( scamin / swork( i, l ) ) * scaloc
625 IF( scal .NE. one ) THEN
626 DO ll = l1, l2-1
627 CALL csscal( i2-i1, scal, c( i1, ll ), 1 )
628 END DO
629 ENDIF
630*
631* Record current scaling factor
632*
633 swork( k, l ) = scamin * scaloc
634 swork( i, l ) = scamin * scaloc
635*
636 CALL cgemm( 'C', 'N', i2-i1, l2-l1, k2-k1, -cone,
637 $ a( k1, i1 ), lda, c( k1, l1 ), ldc,
638 $ cone, c( i1, l1 ), ldc )
639 END DO
640*
641 DO j = l + 1, nbb
642*
643* C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( L, J )
644*
645 j1 = (j - 1) * nb + 1
646 j2 = min( j * nb, n ) + 1
647*
648* Compute scaling factor to survive the linear update
649* simulating consistent scaling.
650*
651 cnrm = clange( 'I', k2-k1, j2-j1, c( k1, j1 ),
652 $ ldc, wnrm )
653 scamin = min( swork( k, j ), swork( k, l ) )
654 cnrm = cnrm * ( scamin / swork( k, j ) )
655 xnrm = xnrm * ( scamin / swork( k, l ) )
656 bnrm = swork( l, bwrk + j )
657 scaloc = slarmm( bnrm, xnrm, cnrm )
658 IF( scaloc * scamin .EQ. zero ) THEN
659* Use second scaling factor to prevent flushing to zero.
660 buf = buf*2.e0**exponent( scaloc )
661 DO jj = 1, nbb
662 DO ll = 1, nba
663 swork( ll, jj ) = min( bignum,
664 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
665 END DO
666 END DO
667 scamin = scamin / 2.e0**exponent( scaloc )
668 scaloc = scaloc / 2.e0**exponent( scaloc )
669 END IF
670 cnrm = cnrm * scaloc
671 xnrm = xnrm * scaloc
672*
673* Simultaneously apply the robust update factor and the
674* consistency scaling factor to to C( K, J ) and C( K, L).
675*
676 scal = ( scamin / swork( k, l ) ) * scaloc
677 IF( scal .NE. one ) THEN
678 DO ll = l1, l2-1
679 CALL csscal( k2-k1, scal, c( k1, ll ), 1 )
680 END DO
681 ENDIF
682*
683 scal = ( scamin / swork( k, j ) ) * scaloc
684 IF( scal .NE. one ) THEN
685 DO jj = j1, j2-1
686 CALL csscal( k2-k1, scal, c( k1, jj ), 1 )
687 END DO
688 ENDIF
689*
690* Record current scaling factor
691*
692 swork( k, l ) = scamin * scaloc
693 swork( k, j ) = scamin * scaloc
694*
695 CALL cgemm( 'N', 'N', k2-k1, j2-j1, l2-l1, -csgn,
696 $ c( k1, l1 ), ldc, b( l1, j1 ), ldb,
697 $ cone, c( k1, j1 ), ldc )
698 END DO
699 END DO
700 END DO
701 ELSE IF( .NOT.notrna .AND. .NOT.notrnb ) THEN
702*
703* Solve A**H *X + ISGN*X*B**H = scale*C.
704*
705* The (K,L)th block of X is determined starting from
706* top-right corner column by column by
707*
708* A(K,K)**H*X(K,L) + ISGN*X(K,L)*B(L,L)**H = C(K,L) - R(K,L)
709*
710* Where
711* K-1 N
712* R(K,L) = SUM [A(I,K)**H*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)**H].
713* I=1 J=L+1
714*
715* Start loop over block rows (index = K) and block columns (index = L)
716*
717 DO k = 1, nba
718*
719* K1: row index of the first row in X( K, L )
720* K2: row index of the first row in X( K+1, L )
721* so the K2 - K1 is the column count of the block X( K, L )
722*
723 k1 = (k - 1) * nb + 1
724 k2 = min( k * nb, m ) + 1
725 DO l = nbb, 1, -1
726*
727* L1: column index of the first column in X( K, L )
728* L2: column index of the first column in X( K, L + 1)
729* so that L2 - L1 is the row count of the block X( K, L )
730*
731 l1 = (l - 1) * nb + 1
732 l2 = min( l * nb, n ) + 1
733*
734 CALL ctrsyl( trana, tranb, isgn, k2-k1, l2-l1,
735 $ a( k1, k1 ), lda,
736 $ b( l1, l1 ), ldb,
737 $ c( k1, l1 ), ldc, scaloc, iinfo )
738 info = max( info, iinfo )
739*
740 IF( scaloc * swork( k, l ) .EQ. zero ) THEN
741 IF( scaloc .EQ. zero ) THEN
742* The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
743* is larger than the product of BIGNUM**2 and cannot be
744* represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
745* Mark the computation as pointless.
746 buf = zero
747 ELSE
748* Use second scaling factor to prevent flushing to zero.
749 buf = buf*2.e0**exponent( scaloc )
750 END IF
751 DO jj = 1, nbb
752 DO ll = 1, nba
753* Bound by BIGNUM to not introduce Inf. The value
754* is irrelevant; corresponding entries of the
755* solution will be flushed in consistency scaling.
756 swork( ll, jj ) = min( bignum,
757 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
758 END DO
759 END DO
760 END IF
761 swork( k, l ) = scaloc * swork( k, l )
762 xnrm = clange( 'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
763 $ wnrm )
764*
765 DO i = k + 1, nba
766*
767* C( I, L ) := C( I, L ) - A( K, I )**H * C( K, L )
768*
769 i1 = (i - 1) * nb + 1
770 i2 = min( i * nb, m ) + 1
771*
772* Compute scaling factor to survive the linear update
773* simulating consistent scaling.
774*
775 cnrm = clange( 'I', i2-i1, l2-l1, c( i1, l1 ),
776 $ ldc, wnrm )
777 scamin = min( swork( i, l ), swork( k, l ) )
778 cnrm = cnrm * ( scamin / swork( i, l ) )
779 xnrm = xnrm * ( scamin / swork( k, l ) )
780 anrm = swork( i, awrk + k )
781 scaloc = slarmm( anrm, xnrm, cnrm )
782 IF( scaloc * scamin .EQ. zero ) THEN
783* Use second scaling factor to prevent flushing to zero.
784 buf = buf*2.e0**exponent( scaloc )
785 DO jj = 1, nbb
786 DO ll = 1, nba
787 swork( ll, jj ) = min( bignum,
788 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
789 END DO
790 END DO
791 scamin = scamin / 2.e0**exponent( scaloc )
792 scaloc = scaloc / 2.e0**exponent( scaloc )
793 END IF
794 cnrm = cnrm * scaloc
795 xnrm = xnrm * scaloc
796*
797* Simultaneously apply the robust update factor and the
798* consistency scaling factor to C( I, L ) and C( K, L).
799*
800 scal = ( scamin / swork( k, l ) ) * scaloc
801 IF( scal .NE. one ) THEN
802 DO ll = l1, l2-1
803 CALL csscal( k2-k1, scal, c( k1, ll ), 1 )
804 END DO
805 ENDIF
806*
807 scal = ( scamin / swork( i, l ) ) * scaloc
808 IF( scal .NE. one ) THEN
809 DO ll = l1, l2-1
810 CALL csscal( i2-i1, scal, c( i1, ll ), 1 )
811 END DO
812 ENDIF
813*
814* Record current scaling factor
815*
816 swork( k, l ) = scamin * scaloc
817 swork( i, l ) = scamin * scaloc
818*
819 CALL cgemm( 'C', 'N', i2-i1, l2-l1, k2-k1, -cone,
820 $ a( k1, i1 ), lda, c( k1, l1 ), ldc,
821 $ cone, c( i1, l1 ), ldc )
822 END DO
823*
824 DO j = 1, l - 1
825*
826* C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( J, L )**H
827*
828 j1 = (j - 1) * nb + 1
829 j2 = min( j * nb, n ) + 1
830*
831* Compute scaling factor to survive the linear update
832* simulating consistent scaling.
833*
834 cnrm = clange( 'I', k2-k1, j2-j1, c( k1, j1 ),
835 $ ldc, wnrm )
836 scamin = min( swork( k, j ), swork( k, l ) )
837 cnrm = cnrm * ( scamin / swork( k, j ) )
838 xnrm = xnrm * ( scamin / swork( k, l ) )
839 bnrm = swork( l, bwrk + j )
840 scaloc = slarmm( bnrm, xnrm, cnrm )
841 IF( scaloc * scamin .EQ. zero ) THEN
842* Use second scaling factor to prevent flushing to zero.
843 buf = buf*2.e0**exponent( scaloc )
844 DO jj = 1, nbb
845 DO ll = 1, nba
846 swork( ll, jj ) = min( bignum,
847 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
848 END DO
849 END DO
850 scamin = scamin / 2.e0**exponent( scaloc )
851 scaloc = scaloc / 2.e0**exponent( scaloc )
852 END IF
853 cnrm = cnrm * scaloc
854 xnrm = xnrm * scaloc
855*
856* Simultaneously apply the robust update factor and the
857* consistency scaling factor to C( K, J ) and C( K, L).
858*
859 scal = ( scamin / swork( k, l ) ) * scaloc
860 IF( scal .NE. one ) THEN
861 DO ll = l1, l2-1
862 CALL csscal( k2-k1, scal, c( k1, ll ), 1)
863 END DO
864 ENDIF
865*
866 scal = ( scamin / swork( k, j ) ) * scaloc
867 IF( scal .NE. one ) THEN
868 DO jj = j1, j2-1
869 CALL csscal( k2-k1, scal, c( k1, jj ), 1 )
870 END DO
871 ENDIF
872*
873* Record current scaling factor
874*
875 swork( k, l ) = scamin * scaloc
876 swork( k, j ) = scamin * scaloc
877*
878 CALL cgemm( 'N', 'C', k2-k1, j2-j1, l2-l1, -csgn,
879 $ c( k1, l1 ), ldc, b( j1, l1 ), ldb,
880 $ cone, c( k1, j1 ), ldc )
881 END DO
882 END DO
883 END DO
884 ELSE IF( notrna .AND. .NOT.notrnb ) THEN
885*
886* Solve A*X + ISGN*X*B**H = scale*C.
887*
888* The (K,L)th block of X is determined starting from
889* bottom-right corner column by column by
890*
891* A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L)**H = C(K,L) - R(K,L)
892*
893* Where
894* M N
895* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)**H].
896* I=K+1 J=L+1
897*
898* Start loop over block rows (index = K) and block columns (index = L)
899*
900 DO k = nba, 1, -1
901*
902* K1: row index of the first row in X( K, L )
903* K2: row index of the first row in X( K+1, L )
904* so the K2 - K1 is the column count of the block X( K, L )
905*
906 k1 = (k - 1) * nb + 1
907 k2 = min( k * nb, m ) + 1
908 DO l = nbb, 1, -1
909*
910* L1: column index of the first column in X( K, L )
911* L2: column index of the first column in X( K, L + 1)
912* so that L2 - L1 is the row count of the block X( K, L )
913*
914 l1 = (l - 1) * nb + 1
915 l2 = min( l * nb, n ) + 1
916*
917 CALL ctrsyl( trana, tranb, isgn, k2-k1, l2-l1,
918 $ a( k1, k1 ), lda,
919 $ b( l1, l1 ), ldb,
920 $ c( k1, l1 ), ldc, scaloc, iinfo )
921 info = max( info, iinfo )
922*
923 IF( scaloc * swork( k, l ) .EQ. zero ) THEN
924 IF( scaloc .EQ. zero ) THEN
925* The magnitude of the largest entry of X(K1:K2-1, L1:L2-1)
926* is larger than the product of BIGNUM**2 and cannot be
927* represented in the form (1/SCALE)*X(K1:K2-1, L1:L2-1).
928* Mark the computation as pointless.
929 buf = zero
930 ELSE
931* Use second scaling factor to prevent flushing to zero.
932 buf = buf*2.e0**exponent( scaloc )
933 END IF
934 DO jj = 1, nbb
935 DO ll = 1, nba
936* Bound by BIGNUM to not introduce Inf. The value
937* is irrelevant; corresponding entries of the
938* solution will be flushed in consistency scaling.
939 swork( ll, jj ) = min( bignum,
940 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
941 END DO
942 END DO
943 END IF
944 swork( k, l ) = scaloc * swork( k, l )
945 xnrm = clange( 'I', k2-k1, l2-l1, c( k1, l1 ), ldc,
946 $ wnrm )
947*
948 DO i = 1, k - 1
949*
950* C( I, L ) := C( I, L ) - A( I, K ) * C( K, L )
951*
952 i1 = (i - 1) * nb + 1
953 i2 = min( i * nb, m ) + 1
954*
955* Compute scaling factor to survive the linear update
956* simulating consistent scaling.
957*
958 cnrm = clange( 'I', i2-i1, l2-l1, c( i1, l1 ),
959 $ ldc, wnrm )
960 scamin = min( swork( i, l ), swork( k, l ) )
961 cnrm = cnrm * ( scamin / swork( i, l ) )
962 xnrm = xnrm * ( scamin / swork( k, l ) )
963 anrm = swork( i, awrk + k )
964 scaloc = slarmm( anrm, xnrm, cnrm )
965 IF( scaloc * scamin .EQ. zero ) THEN
966* Use second scaling factor to prevent flushing to zero.
967 buf = buf*2.e0**exponent( scaloc )
968 DO jj = 1, nbb
969 DO ll = 1, nba
970 swork( ll, jj ) = min( bignum,
971 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
972 END DO
973 END DO
974 scamin = scamin / 2.e0**exponent( scaloc )
975 scaloc = scaloc / 2.e0**exponent( scaloc )
976 END IF
977 cnrm = cnrm * scaloc
978 xnrm = xnrm * scaloc
979*
980* Simultaneously apply the robust update factor and the
981* consistency scaling factor to C( I, L ) and C( K, L).
982*
983 scal = ( scamin / swork( k, l ) ) * scaloc
984 IF( scal .NE. one ) THEN
985 DO ll = l1, l2-1
986 CALL csscal( k2-k1, scal, c( k1, ll ), 1 )
987 END DO
988 ENDIF
989*
990 scal = ( scamin / swork( i, l ) ) * scaloc
991 IF( scal .NE. one ) THEN
992 DO ll = l1, l2-1
993 CALL csscal( i2-i1, scal, c( i1, ll ), 1 )
994 END DO
995 ENDIF
996*
997* Record current scaling factor
998*
999 swork( k, l ) = scamin * scaloc
1000 swork( i, l ) = scamin * scaloc
1001*
1002 CALL cgemm( 'N', 'N', i2-i1, l2-l1, k2-k1, -cone,
1003 $ a( i1, k1 ), lda, c( k1, l1 ), ldc,
1004 $ cone, c( i1, l1 ), ldc )
1005*
1006 END DO
1007*
1008 DO j = 1, l - 1
1009*
1010* C( K, J ) := C( K, J ) - SGN * C( K, L ) * B( J, L )**H
1011*
1012 j1 = (j - 1) * nb + 1
1013 j2 = min( j * nb, n ) + 1
1014*
1015* Compute scaling factor to survive the linear update
1016* simulating consistent scaling.
1017*
1018 cnrm = clange( 'I', k2-k1, j2-j1, c( k1, j1 ),
1019 $ ldc, wnrm )
1020 scamin = min( swork( k, j ), swork( k, l ) )
1021 cnrm = cnrm * ( scamin / swork( k, j ) )
1022 xnrm = xnrm * ( scamin / swork( k, l ) )
1023 bnrm = swork( l, bwrk + j )
1024 scaloc = slarmm( bnrm, xnrm, cnrm )
1025 IF( scaloc * scamin .EQ. zero ) THEN
1026* Use second scaling factor to prevent flushing to zero.
1027 buf = buf*2.e0**exponent( scaloc )
1028 DO jj = 1, nbb
1029 DO ll = 1, nba
1030 swork( ll, jj ) = min( bignum,
1031 $ swork( ll, jj ) / 2.e0**exponent( scaloc ) )
1032 END DO
1033 END DO
1034 scamin = scamin / 2.e0**exponent( scaloc )
1035 scaloc = scaloc / 2.e0**exponent( scaloc )
1036 END IF
1037 cnrm = cnrm * scaloc
1038 xnrm = xnrm * scaloc
1039*
1040* Simultaneously apply the robust update factor and the
1041* consistency scaling factor to C( K, J ) and C( K, L).
1042*
1043 scal = ( scamin / swork( k, l ) ) * scaloc
1044 IF( scal .NE. one ) THEN
1045 DO jj = l1, l2-1
1046 CALL csscal( k2-k1, scal, c( k1, jj ), 1 )
1047 END DO
1048 ENDIF
1049*
1050 scal = ( scamin / swork( k, j ) ) * scaloc
1051 IF( scal .NE. one ) THEN
1052 DO jj = j1, j2-1
1053 CALL csscal( k2-k1, scal, c( k1, jj ), 1 )
1054 END DO
1055 ENDIF
1056*
1057* Record current scaling factor
1058*
1059 swork( k, l ) = scamin * scaloc
1060 swork( k, j ) = scamin * scaloc
1061*
1062 CALL cgemm( 'N', 'C', k2-k1, j2-j1, l2-l1, -csgn,
1063 $ c( k1, l1 ), ldc, b( j1, l1 ), ldb,
1064 $ cone, c( k1, j1 ), ldc )
1065 END DO
1066 END DO
1067 END DO
1068*
1069 END IF
1070*
1071* Reduce local scaling factors
1072*
1073 scale = swork( 1, 1 )
1074 DO k = 1, nba
1075 DO l = 1, nbb
1076 scale = min( scale, swork( k, l ) )
1077 END DO
1078 END DO
1079 IF( scale .EQ. zero ) THEN
1080*
1081* The magnitude of the largest entry of the solution is larger
1082* than the product of BIGNUM**2 and cannot be represented in the
1083* form (1/SCALE)*X if SCALE is REAL. Set SCALE to
1084* zero and give up.
1085*
1086 swork(1,1) = real( max( nba, nbb ) )
1087 swork(2,1) = real( 2 * nbb + nba )
1088 RETURN
1089 END IF
1090*
1091* Realize consistent scaling
1092*
1093 DO k = 1, nba
1094 k1 = (k - 1) * nb + 1
1095 k2 = min( k * nb, m ) + 1
1096 DO l = 1, nbb
1097 l1 = (l - 1) * nb + 1
1098 l2 = min( l * nb, n ) + 1
1099 scal = scale / swork( k, l )
1100 IF( scal .NE. one ) THEN
1101 DO ll = l1, l2-1
1102 CALL csscal( k2-k1, scal, c( k1, ll ), 1 )
1103 END DO
1104 ENDIF
1105 END DO
1106 END DO
1107*
1108 IF( buf .NE. one .AND. buf.GT.zero ) THEN
1109*
1110* Decrease SCALE as much as possible.
1111*
1112 scaloc = min( scale / smlnum, one / buf )
1113 buf = buf * scaloc
1114 scale = scale / scaloc
1115 END IF
1116*
1117 IF( buf.NE.one .AND. buf.GT.zero ) THEN
1118*
1119* In case of overly aggressive scaling during the computation,
1120* flushing of the global scale factor may be prevented by
1121* undoing some of the scaling. This step is to ensure that
1122* this routine flushes only scale factors that TRSYL also
1123* flushes and be usable as a drop-in replacement.
1124*
1125* How much can the normwise largest entry be upscaled?
1126*
1127 scal = max( abs( real( c( 1, 1 ) ) ),
1128 $ abs( aimag( c( 1, 1 ) ) ) )
1129 DO k = 1, m
1130 DO l = 1, n
1131 scal = max( scal, abs( real( c( k, l ) ) ),
1132 $ abs( aimag( c( k, l ) ) ) )
1133 END DO
1134 END DO
1135*
1136* Increase BUF as close to 1 as possible and apply scaling.
1137*
1138 scaloc = min( bignum / scal, one / buf )
1139 buf = buf * scaloc
1140 CALL clascl( 'G', -1, -1, one, scaloc, m, n, c, ldc, iinfo )
1141 END IF
1142*
1143* Combine with buffer scaling factor. SCALE will be flushed if
1144* BUF is less than one here.
1145*
1146 scale = scale * buf
1147*
1148* Restore workspace dimensions
1149*
1150 swork(1,1) = real( max( nba, nbb ) )
1151 swork(2,1) = real( 2 * nbb + nba )
1152*
1153 RETURN
1154*
1155* End of CTRSYL3
1156*
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine cgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
CGEMM
Definition cgemm.f:188
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
Definition ilaenv.f:160
real function slamch(cmach)
SLAMCH
Definition slamch.f:68
real function clange(norm, m, n, a, lda, work)
CLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
Definition clange.f:113
real function slarmm(anorm, bnorm, cnorm)
SLARMM
Definition slarmm.f:61
subroutine clascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
CLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition clascl.f:142
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
subroutine csscal(n, sa, cx, incx)
CSSCAL
Definition csscal.f:78
subroutine ctrsyl(trana, tranb, isgn, m, n, a, lda, b, ldb, c, ldc, scale, info)
CTRSYL
Definition ctrsyl.f:155
Here is the call graph for this function:
Here is the caller graph for this function: