376 SUBROUTINE dtgsna( 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 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), DIF( * ), S( * ),
392 $ vl( ldvl, * ), vr( ldvr, * ), work( * )
399 PARAMETER ( DIFDRI = 3 )
400 DOUBLE PRECISION ZERO, ONE, TWO, FOUR
401 parameter( zero = 0.0d+0, one = 1.0d+0, two = 2.0d+0,
405 LOGICAL LQUERY, PAIR, SOMCON, WANTBH, WANTDF, WANTS
406 INTEGER I, IERR, IFST, ILST, IZ, K, KS, LWMIN, N1, N2
407 DOUBLE PRECISION ALPHAI, ALPHAR, ALPRQT, BETA, C1, C2, COND,
408 $ eps, lnrm, rnrm, root1, root2, scale, smlnum,
409 $ tmpii, tmpir, tmpri, tmprr, uhav, uhavi, uhbv,
413 DOUBLE PRECISION DUMMY( 1 ), DUMMY1( 1 )
417 DOUBLE PRECISION DDOT, DLAMCH, DLAPY2, DNRM2
418 EXTERNAL lsame, ddot, dlamch, dlapy2, dnrm2
425 INTRINSIC max, min, sqrt
431 wantbh = lsame( job,
'B' )
432 wants = lsame( job,
'E' ) .OR. wantbh
433 wantdf = lsame( job,
'V' ) .OR. wantbh
435 somcon = lsame( howmny,
'S' )
438 lquery = ( lwork.EQ.-1 )
440 IF( .NOT.wants .AND. .NOT.wantdf )
THEN
442 ELSE IF( .NOT.lsame( howmny,
'A' ) .AND. .NOT.somcon )
THEN
444 ELSE IF( n.LT.0 )
THEN
446 ELSE IF( lda.LT.max( 1, n ) )
THEN
448 ELSE IF( ldb.LT.max( 1, n ) )
THEN
450 ELSE IF( wants .AND. ldvl.LT.n )
THEN
452 ELSE IF( wants .AND. ldvr.LT.n )
THEN
467 IF( a( k+1, k ).EQ.zero )
THEN
472 IF(
SELECT( k ) .OR.
SELECT( k+1 ) )
487 ELSE IF( lsame( job,
'V' ) .OR. lsame( job,
'B' ) )
THEN
488 lwmin = 2*n*( n + 2 ) + 16
496 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery )
THEN
502 CALL xerbla(
'DTGSNA', -info )
504 ELSE IF( lquery )
THEN
516 smlnum = dlamch(
'S' ) / eps
529 $ pair = a( k+1, k ).NE.zero
537 IF( .NOT.
SELECT( k ) .AND. .NOT.
SELECT( k+1 ) )
540 IF( .NOT.
SELECT( k ) )
556 rnrm = dlapy2( dnrm2( n, vr( 1, ks ), 1 ),
557 $ dnrm2( n, vr( 1, ks+1 ), 1 ) )
558 lnrm = dlapy2( dnrm2( n, vl( 1, ks ), 1 ),
559 $ dnrm2( n, vl( 1, ks+1 ), 1 ) )
560 CALL dgemv(
'N', n, n, one, a, lda, vr( 1, ks ), 1,
563 tmprr = ddot( n, work, 1, vl( 1, ks ), 1 )
564 tmpri = ddot( n, work, 1, vl( 1, ks+1 ), 1 )
565 CALL dgemv(
'N', n, n, one, a, lda, vr( 1, ks+1 ), 1,
567 tmpii = ddot( n, work, 1, vl( 1, ks+1 ), 1 )
568 tmpir = ddot( n, work, 1, vl( 1, ks ), 1 )
570 uhavi = tmpir - tmpri
571 CALL dgemv(
'N', n, n, one, b, ldb, vr( 1, ks ), 1,
574 tmprr = ddot( n, work, 1, vl( 1, ks ), 1 )
575 tmpri = ddot( n, work, 1, vl( 1, ks+1 ), 1 )
576 CALL dgemv(
'N', n, n, one, b, ldb, vr( 1, ks+1 ), 1,
578 tmpii = ddot( n, work, 1, vl( 1, ks+1 ), 1 )
579 tmpir = ddot( n, work, 1, vl( 1, ks ), 1 )
581 uhbvi = tmpir - tmpri
582 uhav = dlapy2( uhav, uhavi )
583 uhbv = dlapy2( uhbv, uhbvi )
584 cond = dlapy2( uhav, uhbv )
585 s( ks ) = cond / ( rnrm*lnrm )
592 rnrm = dnrm2( n, vr( 1, ks ), 1 )
593 lnrm = dnrm2( n, vl( 1, ks ), 1 )
594 CALL dgemv(
'N', n, n, one, a, lda, vr( 1, ks ), 1,
597 uhav = ddot( n, work, 1, vl( 1, ks ), 1 )
598 CALL dgemv(
'N', n, n, one, b, ldb, vr( 1, ks ), 1,
601 uhbv = ddot( n, work, 1, vl( 1, ks ), 1 )
602 cond = dlapy2( uhav, uhbv )
603 IF( cond.EQ.zero )
THEN
606 s( ks ) = cond / ( rnrm*lnrm )
613 dif( ks ) = dlapy2( a( 1, 1 ), b( 1, 1 ) )
624 work( 1 ) = a( k, k )
625 work( 2 ) = a( k+1, k )
626 work( 3 ) = a( k, k+1 )
627 work( 4 ) = a( k+1, k+1 )
628 work( 5 ) = b( k, k )
629 work( 6 ) = b( k+1, k )
630 work( 7 ) = b( k, k+1 )
631 work( 8 ) = b( k+1, k+1 )
632 CALL dlag2( work, 2, work( 5 ), 2, smlnum*eps, beta,
633 $ dummy1( 1 ), alphar, dummy( 1 ), alphai )
635 c1 = two*( alphar*alphar+alphai*alphai+beta*beta )
636 c2 = four*beta*beta*alphai*alphai
637 root1 = c1 + sqrt( c1*c1-4.0d0*c2 )
640 cond = min( sqrt( root1 ), sqrt( root2 ) )
646 CALL dlacpy(
'Full', n, n, a, lda, work, n )
647 CALL dlacpy(
'Full', n, n, b, ldb, work( n*n+1 ), n )
651 CALL dtgexc( .false., .false., n, work, n, work( n*n+1 ),
653 $ dummy, 1, dummy1, 1, ifst, ilst,
654 $ work( n*n*2+1 ), lwork-2*n*n, ierr )
670 IF( work( 2 ).NE.zero )
678 CALL dtgsyl(
'N', difdri, n2, n1,
680 $ n, work, n, work( n1+1 ), n,
681 $ work( n*n1+n1+i ), n, work( i ), n,
682 $ work( n1+i ), n, scale, dif( ks ),
683 $ work( iz+1 ), lwork-2*n*n, iwork, ierr )
686 $ dif( ks ) = min( max( one, alprqt )*dif( ks ),
691 $ dif( ks+1 ) = dif( ks )