346 SUBROUTINE zdrgsx( NSIZE, NCMAX, THRESH, NIN, NOUT, A, LDA, B, AI,
347 $ BI, Z, Q, ALPHA, BETA, C, LDC, S, WORK, LWORK,
348 $ RWORK, IWORK, LIWORK, BWORK, INFO )
355 INTEGER INFO, LDA, LDC, LIWORK, LWORK, NCMAX, NIN,
357 DOUBLE PRECISION THRESH
362 DOUBLE PRECISION RWORK( * ), S( * )
363 COMPLEX*16 A( LDA, * ), AI( LDA, * ), ALPHA( * ),
364 $ b( lda, * ), beta( * ), bi( lda, * ),
365 $ c( ldc, * ), q( lda, * ), work( * ),
372 DOUBLE PRECISION ZERO, ONE, TEN
373 PARAMETER ( ZERO = 0.0d+0, one = 1.0d+0, ten = 1.0d+1 )
375 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
380 INTEGER BDSPAC, I, IFUNC, J, LINFO, MAXWRK, MINWRK, MM,
381 $ mn2, nerrs, nptknt, ntest, ntestt, prtype, qba,
383 DOUBLE PRECISION ABNRM, BIGNUM, DIFTRU, PLTRU, SMLNUM, TEMP1,
384 $ TEMP2, THRSH2, ULP, ULPINV, WEIGHT
388 DOUBLE PRECISION DIFEST( 2 ), PL( 2 ), RESULT( 10 )
393 DOUBLE PRECISION DLAMCH, ZLANGE
394 EXTERNAL zlctsx, ilaenv, dlamch, zlange
402 INTEGER K, M, MPLUSN, N
405 COMMON / mn / m, n, mplusn, k, fs
408 INTRINSIC abs, dble, dimag, max, sqrt
411 DOUBLE PRECISION ABS1
414 abs1( x ) = abs( dble( x ) ) + abs( dimag( x ) )
421 IF( nsize.LT.0 )
THEN
423 ELSE IF( thresh.LT.zero )
THEN
425 ELSE IF( nin.LE.0 )
THEN
427 ELSE IF( nout.LE.0 )
THEN
429 ELSE IF( lda.LT.1 .OR. lda.LT.nsize )
THEN
431 ELSE IF( ldc.LT.1 .OR. ldc.LT.nsize*nsize / 2 )
THEN
433 ELSE IF( liwork.LT.nsize+2 )
THEN
445 IF( info.EQ.0 .AND. lwork.GE.1 )
THEN
446 minwrk = 3*nsize*nsize / 2
450 maxwrk = nsize*( 1+ilaenv( 1,
'ZGEQRF',
' ', nsize, 1, nsize,
452 maxwrk = max( maxwrk, nsize*( 1+ilaenv( 1,
'ZUNGQR',
' ',
453 $ nsize, 1, nsize, -1 ) ) )
457 bdspac = 3*nsize*nsize / 2
458 maxwrk = max( maxwrk, nsize*nsize*
459 $ ( 1+ilaenv( 1,
'ZGEBRD',
' ', nsize*nsize / 2,
460 $ nsize*nsize / 2, -1, -1 ) ) )
461 maxwrk = max( maxwrk, bdspac )
463 maxwrk = max( maxwrk, minwrk )
468 IF( lwork.LT.minwrk )
472 CALL xerbla(
'ZDRGSX', -info )
480 smlnum = dlamch(
'S' ) / ulp
481 bignum = one / smlnum
482 CALL dlabad( smlnum, bignum )
504 DO 40 m = 1, nsize - 1
505 DO 30 n = 1, nsize - m
507 weight = one / weight
515 CALL zlaset(
'Full', mplusn, mplusn, czero, czero, ai,
517 CALL zlaset(
'Full', mplusn, mplusn, czero, czero, bi,
520 CALL zlatm5( prtype, m, n, ai, lda, ai( m+1, m+1 ),
521 $ lda, ai( 1, m+1 ), lda, bi, lda,
522 $ bi( m+1, m+1 ), lda, bi( 1, m+1 ), lda,
523 $ q, lda, z, lda, weight, qba, qbb )
530 IF( ifunc.EQ.0 )
THEN
532 ELSE IF( ifunc.EQ.1 )
THEN
534 ELSE IF( ifunc.EQ.2 )
THEN
536 ELSE IF( ifunc.EQ.3 )
THEN
540 CALL zlacpy(
'Full', mplusn, mplusn, ai, lda, a, lda )
541 CALL zlacpy(
'Full', mplusn, mplusn, bi, lda, b, lda )
543 CALL zggesx(
'V',
'V',
'S', zlctsx, sense, mplusn, ai,
544 $ lda, bi, lda, mm, alpha, beta, q, lda, z,
545 $ lda, pl, difest, work, lwork, rwork,
546 $ iwork, liwork, bwork, linfo )
548 IF( linfo.NE.0 .AND. linfo.NE.mplusn+2 )
THEN
550 WRITE( nout, fmt = 9999 )
'ZGGESX', linfo, mplusn,
558 CALL zlacpy(
'Full', mplusn, mplusn, ai, lda, work,
560 CALL zlacpy(
'Full', mplusn, mplusn, bi, lda,
561 $ work( mplusn*mplusn+1 ), mplusn )
562 abnrm = zlange(
'Fro', mplusn, 2*mplusn, work, mplusn,
568 CALL zget51( 1, mplusn, a, lda, ai, lda, q, lda, z,
569 $ lda, work, rwork, result( 1 ) )
570 CALL zget51( 1, mplusn, b, lda, bi, lda, q, lda, z,
571 $ lda, work, rwork, result( 2 ) )
572 CALL zget51( 3, mplusn, b, lda, bi, lda, q, lda, q,
573 $ lda, work, rwork, result( 3 ) )
574 CALL zget51( 3, mplusn, b, lda, bi, lda, z, lda, z,
575 $ lda, work, rwork, result( 4 ) )
587 temp2 = ( abs1( alpha( j )-ai( j, j ) ) /
588 $ max( smlnum, abs1( alpha( j ) ),
589 $ abs1( ai( j, j ) ) )+
590 $ abs1( beta( j )-bi( j, j ) ) /
591 $ max( smlnum, abs1( beta( j ) ),
592 $ abs1( bi( j, j ) ) ) ) / ulp
593 IF( j.LT.mplusn )
THEN
594 IF( ai( j+1, j ).NE.zero )
THEN
600 IF( ai( j, j-1 ).NE.zero )
THEN
605 temp1 = max( temp1, temp2 )
607 WRITE( nout, fmt = 9997 )j, mplusn, prtype
616 IF( linfo.EQ.mplusn+3 )
THEN
618 ELSE IF( mm.NE.n )
THEN
627 mn2 = mm*( mplusn-mm )*2
628 IF( ifunc.GE.2 .AND. mn2.LE.ncmax*ncmax )
THEN
633 CALL zlakf2( mm, mplusn-mm, ai, lda,
634 $ ai( mm+1, mm+1 ), bi,
635 $ bi( mm+1, mm+1 ), c, ldc )
637 CALL zgesvd(
'N',
'N', mn2, mn2, c, ldc, s, work,
638 $ 1, work( 2 ), 1, work( 3 ), lwork-2,
642 IF( difest( 2 ).EQ.zero )
THEN
643 IF( diftru.GT.abnrm*ulp )
644 $ result( 8 ) = ulpinv
645 ELSE IF( diftru.EQ.zero )
THEN
646 IF( difest( 2 ).GT.abnrm*ulp )
647 $ result( 8 ) = ulpinv
648 ELSE IF( ( diftru.GT.thrsh2*difest( 2 ) ) .OR.
649 $ ( diftru*thrsh2.LT.difest( 2 ) ) )
THEN
650 result( 8 ) = max( diftru / difest( 2 ),
651 $ difest( 2 ) / diftru )
659 IF( linfo.EQ.( mplusn+2 ) )
THEN
660 IF( diftru.GT.abnrm*ulp )
661 $ result( 9 ) = ulpinv
662 IF( ( ifunc.GT.1 ) .AND. ( difest( 2 ).NE.zero ) )
663 $ result( 9 ) = ulpinv
664 IF( ( ifunc.EQ.1 ) .AND. ( pl( 1 ).NE.zero ) )
665 $ result( 9 ) = ulpinv
669 ntestt = ntestt + ntest
674 IF( result( j ).GE.thresh )
THEN
679 IF( nerrs.EQ.0 )
THEN
680 WRITE( nout, fmt = 9996 )
'ZGX'
684 WRITE( nout, fmt = 9994 )
688 WRITE( nout, fmt = 9993 )
'unitary',
'''',
689 $
'transpose', (
'''', i = 1, 4 )
693 IF( result( j ).LT.10000.0d0 )
THEN
694 WRITE( nout, fmt = 9992 )mplusn, prtype,
695 $ weight, m, j, result( j )
697 WRITE( nout, fmt = 9991 )mplusn, prtype,
698 $ weight, m, j, result( j )
718 READ( nin, fmt = *,
END = 140 )mplusn
721 READ( nin, fmt = *,
END = 140 )n
723 READ( nin, fmt = * )( ai( i, j ), j = 1, mplusn )
726 READ( nin, fmt = * )( bi( i, j ), j = 1, mplusn )
728 READ( nin, fmt = * )pltru, diftru
735 CALL zlacpy(
'Full', mplusn, mplusn, ai, lda, a, lda )
736 CALL zlacpy(
'Full', mplusn, mplusn, bi, lda, b, lda )
741 CALL zggesx(
'V',
'V',
'S',
zlctsx,
'B', mplusn, ai, lda, bi, lda,
742 $ mm, alpha, beta, q, lda, z, lda, pl, difest, work,
743 $ lwork, rwork, iwork, liwork, bwork, linfo )
745 IF( linfo.NE.0 .AND. linfo.NE.mplusn+2 )
THEN
747 WRITE( nout, fmt = 9998 )
'ZGGESX', linfo, mplusn, nptknt
754 CALL zlacpy(
'Full', mplusn, mplusn, ai, lda, work, mplusn )
755 CALL zlacpy(
'Full', mplusn, mplusn, bi, lda,
756 $ work( mplusn*mplusn+1 ), mplusn )
757 abnrm =
zlange(
'Fro', mplusn, 2*mplusn, work, mplusn, rwork )
761 CALL zget51( 1, mplusn, a, lda, ai, lda, q, lda, z, lda, work,
762 $ rwork, result( 1 ) )
763 CALL zget51( 1, mplusn, b, lda, bi, lda, q, lda, z, lda, work,
764 $ rwork, result( 2 ) )
765 CALL zget51( 3, mplusn, b, lda, bi, lda, q, lda, q, lda, work,
766 $ rwork, result( 3 ) )
767 CALL zget51( 3, mplusn, b, lda, bi, lda, z, lda, z, lda, work,
768 $ rwork, result( 4 ) )
780 temp2 = ( abs1( alpha( j )-ai( j, j ) ) /
781 $ max( smlnum, abs1( alpha( j ) ), abs1( ai( j, j ) ) )+
782 $ abs1( beta( j )-bi( j, j ) ) /
783 $ max( smlnum, abs1( beta( j ) ), abs1( bi( j, j ) ) ) )
785 IF( j.LT.mplusn )
THEN
786 IF( ai( j+1, j ).NE.zero )
THEN
792 IF( ai( j, j-1 ).NE.zero )
THEN
797 temp1 = max( temp1, temp2 )
799 WRITE( nout, fmt = 9997 )j, mplusn, nptknt
808 IF( linfo.EQ.mplusn+3 )
809 $ result( 7 ) = ulpinv
815 IF( difest( 2 ).EQ.zero )
THEN
816 IF( diftru.GT.abnrm*ulp )
817 $ result( 8 ) = ulpinv
818 ELSE IF( diftru.EQ.zero )
THEN
819 IF( difest( 2 ).GT.abnrm*ulp )
820 $ result( 8 ) = ulpinv
821 ELSE IF( ( diftru.GT.thrsh2*difest( 2 ) ) .OR.
822 $ ( diftru*thrsh2.LT.difest( 2 ) ) )
THEN
823 result( 8 ) = max( diftru / difest( 2 ), difest( 2 ) / diftru )
830 IF( linfo.EQ.( mplusn+2 ) )
THEN
831 IF( diftru.GT.abnrm*ulp )
832 $ result( 9 ) = ulpinv
833 IF( ( ifunc.GT.1 ) .AND. ( difest( 2 ).NE.zero ) )
834 $ result( 9 ) = ulpinv
835 IF( ( ifunc.EQ.1 ) .AND. ( pl( 1 ).NE.zero ) )
836 $ result( 9 ) = ulpinv
843 IF( pl( 1 ).EQ.zero )
THEN
844 IF( pltru.GT.abnrm*ulp )
845 $ result( 10 ) = ulpinv
846 ELSE IF( pltru.EQ.zero )
THEN
847 IF( pl( 1 ).GT.abnrm*ulp )
848 $ result( 10 ) = ulpinv
849 ELSE IF( ( pltru.GT.thresh*pl( 1 ) ) .OR.
850 $ ( pltru*thresh.LT.pl( 1 ) ) )
THEN
851 result( 10 ) = ulpinv
854 ntestt = ntestt + ntest
859 IF( result( j ).GE.thresh )
THEN
864 IF( nerrs.EQ.0 )
THEN
865 WRITE( nout, fmt = 9996 )
'ZGX'
869 WRITE( nout, fmt = 9995 )
873 WRITE( nout, fmt = 9993 )
'unitary',
'''',
'transpose',
878 IF( result( j ).LT.10000.0d0 )
THEN
879 WRITE( nout, fmt = 9990 )nptknt, mplusn, j, result( j )
881 WRITE( nout, fmt = 9989 )nptknt, mplusn, j, result( j )
895 CALL alasvm(
'ZGX', nout, nerrs, ntestt, 0 )
901 9999
FORMAT(
' ZDRGSX: ', a,
' returned INFO=', i6,
'.', / 9x,
'N=',
902 $ i6,
', JTYPE=', i6,
')' )
904 9998
FORMAT(
' ZDRGSX: ', a,
' returned INFO=', i6,
'.', / 9x,
'N=',
905 $ i6,
', Input Example #', i2,
')' )
907 9997
FORMAT(
' ZDRGSX: S not in Schur form at eigenvalue ', i6,
'.',
908 $ / 9x,
'N=', i6,
', JTYPE=', i6,
')' )
910 9996
FORMAT( / 1x, a3,
' -- Complex Expert Generalized Schur form',
911 $
' problem driver' )
913 9995
FORMAT(
'Input Example' )
915 9994
FORMAT(
' Matrix types: ', /
916 $
' 1: A is a block diagonal matrix of Jordan blocks ',
917 $
'and B is the identity ', /
' matrix, ',
918 $ /
' 2: A and B are upper triangular matrices, ',
919 $ /
' 3: A and B are as type 2, but each second diagonal ',
920 $
'block in A_11 and ', /
921 $
' each third diaongal block in A_22 are 2x2 blocks,',
922 $ /
' 4: A and B are block diagonal matrices, ',
923 $ /
' 5: (A,B) has potentially close or common ',
924 $
'eigenvalues.', / )
926 9993
FORMAT( /
' Tests performed: (S is Schur, T is triangular, ',
927 $
'Q and Z are ', a,
',', / 19x,
928 $
' a is alpha, b is beta, and ', a,
' means ', a,
'.)',
929 $ /
' 1 = | A - Q S Z', a,
930 $
' | / ( |A| n ulp ) 2 = | B - Q T Z', a,
931 $
' | / ( |B| n ulp )', /
' 3 = | I - QQ', a,
932 $
' | / ( n ulp ) 4 = | I - ZZ', a,
933 $
' | / ( n ulp )', /
' 5 = 1/ULP if A is not in ',
934 $
'Schur form S', /
' 6 = difference between (alpha,beta)',
935 $
' and diagonals of (S,T)', /
936 $
' 7 = 1/ULP if SDIM is not the correct number of ',
937 $
'selected eigenvalues', /
938 $
' 8 = 1/ULP if DIFEST/DIFTRU > 10*THRESH or ',
939 $
'DIFTRU/DIFEST > 10*THRESH',
940 $ /
' 9 = 1/ULP if DIFEST <> 0 or DIFTRU > ULP*norm(A,B) ',
941 $
'when reordering fails', /
942 $
' 10 = 1/ULP if PLEST/PLTRU > THRESH or ',
943 $
'PLTRU/PLEST > THRESH', /
944 $
' ( Test 10 is only for input examples )', / )
945 9992
FORMAT(
' Matrix order=', i2,
', type=', i2,
', a=', d10.3,
946 $
', order(A_11)=', i2,
', result ', i2,
' is ', 0p, f8.2 )
947 9991
FORMAT(
' Matrix order=', i2,
', type=', i2,
', a=', d10.3,
948 $
', order(A_11)=', i2,
', result ', i2,
' is ', 0p, d10.3 )
949 9990
FORMAT(
' Input example #', i2,
', matrix order=', i4,
',',
950 $
' result ', i2,
' is', 0p, f8.2 )
951 9989
FORMAT(
' Input example #', i2,
', matrix order=', i4,
',',
952 $
' result ', i2,
' is', 1p, d10.3 )
subroutine dlabad(SMALL, LARGE)
DLABAD
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine alasvm(TYPE, NOUT, NFAIL, NRUN, NERRS)
ALASVM
subroutine zget51(ITYPE, N, A, LDA, B, LDB, U, LDU, V, LDV, WORK, RWORK, RESULT)
ZGET51
subroutine zdrgsx(NSIZE, NCMAX, THRESH, NIN, NOUT, A, LDA, B, AI, BI, Z, Q, ALPHA, BETA, C, LDC, S, WORK, LWORK, RWORK, IWORK, LIWORK, BWORK, INFO)
ZDRGSX
logical function zlctsx(ALPHA, BETA)
ZLCTSX
subroutine zlatm5(PRTYPE, M, N, A, LDA, B, LDB, C, LDC, D, LDD, E, LDE, F, LDF, R, LDR, L, LDL, ALPHA, QBLCKA, QBLCKB)
ZLATM5
subroutine zlakf2(M, N, A, LDA, B, D, E, Z, LDZ)
ZLAKF2
double precision function zlange(NORM, M, N, A, LDA, WORK)
ZLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine zggesx(JOBVSL, JOBVSR, SORT, SELCTG, SENSE, N, A, LDA, B, LDB, SDIM, ALPHA, BETA, VSL, LDVSL, VSR, LDVSR, RCONDE, RCONDV, WORK, LWORK, RWORK, IWORK, LIWORK, BWORK, INFO)
ZGGESX computes the eigenvalues, the Schur form, and, optionally, the matrix of Schur vectors for GE ...
subroutine zgesvd(JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, RWORK, INFO)
ZGESVD computes the singular value decomposition (SVD) for GE matrices
subroutine zlacpy(UPLO, M, N, A, LDA, B, LDB)
ZLACPY copies all or part of one two-dimensional array to another.
subroutine zlaset(UPLO, M, N, ALPHA, BETA, A, LDA)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.