376 SUBROUTINE stgsna( JOB, HOWMNY, SELECT, N, A, LDA, B, LDB, VL,
377 $ LDVL, VR, LDVR, S, DIF, MM, M, WORK, LWORK,
385 CHARACTER HOWMNY, JOB
386 INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, M, MM, N
391 REAL A( LDA, * ), B( LDB, * ), DIF( * ), S( * ),
392 $ vl( ldvl, * ), vr( ldvr, * ), work( * )
399 PARAMETER ( DIFDRI = 3 )
400 REAL ZERO, ONE, TWO, FOUR
401 parameter( zero = 0.0e+0, one = 1.0e+0, two = 2.0e+0,
405 LOGICAL LQUERY, PAIR, SOMCON, WANTBH, WANTDF, WANTS
406 INTEGER I, IERR, IFST, ILST, IZ, K, KS, LWMIN, N1, N2
407 REAL ALPHAI, ALPHAR, ALPRQT, BETA, C1, C2, COND,
408 $ eps, lnrm, rnrm, root1, root2, scale, smlnum,
409 $ tmpii, tmpir, tmpri, tmprr, uhav, uhavi, uhbv,
413 REAL DUMMY( 1 ), DUMMY1( 1 )
417 REAL SDOT, SLAMCH, SLAPY2,
419 EXTERNAL lsame, sdot, slamch,
428 INTRINSIC max, min, sqrt
434 wantbh = lsame( job,
'B' )
435 wants = lsame( job,
'E' ) .OR. wantbh
436 wantdf = lsame( job,
'V' ) .OR. wantbh
438 somcon = lsame( howmny,
'S' )
441 lquery = ( lwork.EQ.-1 )
443 IF( .NOT.wants .AND. .NOT.wantdf )
THEN
445 ELSE IF( .NOT.lsame( howmny,
'A' ) .AND. .NOT.somcon )
THEN
447 ELSE IF( n.LT.0 )
THEN
449 ELSE IF( lda.LT.max( 1, n ) )
THEN
451 ELSE IF( ldb.LT.max( 1, n ) )
THEN
453 ELSE IF( wants .AND. ldvl.LT.n )
THEN
455 ELSE IF( wants .AND. ldvr.LT.n )
THEN
470 IF( a( k+1, k ).EQ.zero )
THEN
475 IF(
SELECT( k ) .OR.
SELECT( k+1 ) )
490 ELSE IF( lsame( job,
'V' ) .OR. lsame( job,
'B' ) )
THEN
491 lwmin = 2*n*( n + 2 ) + 16
499 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery )
THEN
505 CALL xerbla(
'STGSNA', -info )
507 ELSE IF( lquery )
THEN
519 smlnum = slamch(
'S' ) / eps
532 $ pair = a( k+1, k ).NE.zero
540 IF( .NOT.
SELECT( k ) .AND. .NOT.
SELECT( k+1 ) )
543 IF( .NOT.
SELECT( k ) )
559 rnrm = slapy2(
snrm2( n, vr( 1, ks ), 1 ),
560 $
snrm2( n, vr( 1, ks+1 ), 1 ) )
561 lnrm = slapy2(
snrm2( n, vl( 1, ks ), 1 ),
562 $
snrm2( n, vl( 1, ks+1 ), 1 ) )
563 CALL sgemv(
'N', n, n, one, a, lda, vr( 1, ks ), 1,
566 tmprr = sdot( n, work, 1, vl( 1, ks ), 1 )
567 tmpri = sdot( n, work, 1, vl( 1, ks+1 ), 1 )
568 CALL sgemv(
'N', n, n, one, a, lda, vr( 1, ks+1 ), 1,
570 tmpii = sdot( n, work, 1, vl( 1, ks+1 ), 1 )
571 tmpir = sdot( n, work, 1, vl( 1, ks ), 1 )
573 uhavi = tmpir - tmpri
574 CALL sgemv(
'N', n, n, one, b, ldb, vr( 1, ks ), 1,
577 tmprr = sdot( n, work, 1, vl( 1, ks ), 1 )
578 tmpri = sdot( n, work, 1, vl( 1, ks+1 ), 1 )
579 CALL sgemv(
'N', n, n, one, b, ldb, vr( 1, ks+1 ), 1,
581 tmpii = sdot( n, work, 1, vl( 1, ks+1 ), 1 )
582 tmpir = sdot( n, work, 1, vl( 1, ks ), 1 )
584 uhbvi = tmpir - tmpri
585 uhav = slapy2( uhav, uhavi )
586 uhbv = slapy2( uhbv, uhbvi )
587 cond = slapy2( uhav, uhbv )
588 s( ks ) = cond / ( rnrm*lnrm )
595 rnrm =
snrm2( n, vr( 1, ks ), 1 )
596 lnrm =
snrm2( n, vl( 1, ks ), 1 )
597 CALL sgemv(
'N', n, n, one, a, lda, vr( 1, ks ), 1,
600 uhav = sdot( n, work, 1, vl( 1, ks ), 1 )
601 CALL sgemv(
'N', n, n, one, b, ldb, vr( 1, ks ), 1,
604 uhbv = sdot( n, work, 1, vl( 1, ks ), 1 )
605 cond = slapy2( uhav, uhbv )
606 IF( cond.EQ.zero )
THEN
609 s( ks ) = cond / ( rnrm*lnrm )
616 dif( ks ) = slapy2( a( 1, 1 ), b( 1, 1 ) )
627 work( 1 ) = a( k, k )
628 work( 2 ) = a( k+1, k )
629 work( 3 ) = a( k, k+1 )
630 work( 4 ) = a( k+1, k+1 )
631 work( 5 ) = b( k, k )
632 work( 6 ) = b( k+1, k )
633 work( 7 ) = b( k, k+1 )
634 work( 8 ) = b( k+1, k+1 )
635 CALL slag2( work, 2, work( 5 ), 2, smlnum*eps, beta,
636 $ dummy1( 1 ), alphar, dummy( 1 ), alphai )
638 c1 = two*( alphar*alphar+alphai*alphai+beta*beta )
639 c2 = four*beta*beta*alphai*alphai
640 root1 = c1 + sqrt( c1*c1-4.0*c2 )
643 cond = min( sqrt( root1 ), sqrt( root2 ) )
649 CALL slacpy(
'Full', n, n, a, lda, work, n )
650 CALL slacpy(
'Full', n, n, b, ldb, work( n*n+1 ), n )
654 CALL stgexc( .false., .false., n, work, n, work( n*n+1 ),
656 $ dummy, 1, dummy1, 1, ifst, ilst,
657 $ work( n*n*2+1 ), lwork-2*n*n, ierr )
673 IF( work( 2 ).NE.zero )
681 CALL stgsyl(
'N', difdri, n2, n1,
683 $ n, work, n, work( n1+1 ), n,
684 $ work( n*n1+n1+i ), n, work( i ), n,
685 $ work( n1+i ), n, scale, dif( ks ),
686 $ work( iz+1 ), lwork-2*n*n, iwork, ierr )
689 $ dif( ks ) = min( max( one, alprqt )*dif( ks ),
694 $ dif( ks+1 ) = dif( ks )