356 SUBROUTINE ddrgsx( NSIZE, NCMAX, THRESH, NIN, NOUT, A, LDA, B, AI,
357 $ BI, Z, Q, ALPHAR, ALPHAI, BETA, C, LDC, S,
358 $ WORK, LWORK, IWORK, LIWORK, BWORK, INFO )
365 INTEGER INFO, LDA, LDC, LIWORK, LWORK, NCMAX, NIN,
367 DOUBLE PRECISION THRESH
372 DOUBLE PRECISION A( LDA, * ), AI( LDA, * ), ALPHAI( * ),
373 $ alphar( * ), b( lda, * ), beta( * ),
374 $ bi( lda, * ), c( ldc, * ), q( lda, * ), s( * ),
375 $ work( * ), z( lda, * )
381 DOUBLE PRECISION ZERO, ONE, TEN
382 PARAMETER ( ZERO = 0.0d+0, one = 1.0d+0, ten = 1.0d+1 )
387 INTEGER BDSPAC, I, I1, IFUNC, IINFO, J, LINFO, MAXWRK,
388 $ minwrk, mm, mn2, nerrs, nptknt, ntest, ntestt,
390 DOUBLE PRECISION ABNRM, BIGNUM, DIFTRU, PLTRU, SMLNUM, TEMP1,
391 $ TEMP2, THRSH2, ULP, ULPINV, WEIGHT
394 DOUBLE PRECISION DIFEST( 2 ), PL( 2 ), RESULT( 10 )
399 DOUBLE PRECISION DLAMCH, DLANGE
400 EXTERNAL dlctsx, ilaenv, dlamch, dlange
407 INTRINSIC abs,
max, sqrt
411 INTEGER K, M, MPLUSN, N
414 COMMON / mn / m, n, mplusn, k, fs
420 IF( nsize.LT.0 )
THEN
422 ELSE IF( thresh.LT.zero )
THEN
424 ELSE IF( nin.LE.0 )
THEN
426 ELSE IF( nout.LE.0 )
THEN
428 ELSE IF( lda.LT.1 .OR. lda.LT.nsize )
THEN
430 ELSE IF( ldc.LT.1 .OR. ldc.LT.nsize*nsize / 2 )
THEN
432 ELSE IF( liwork.LT.nsize+6 )
THEN
444 IF( info.EQ.0 .AND. lwork.GE.1 )
THEN
445 minwrk =
max( 10*( nsize+1 ), 5*nsize*nsize / 2 )
449 maxwrk = 9*( nsize+1 ) + nsize*
450 $ ilaenv( 1,
'DGEQRF',
' ', nsize, 1, nsize, 0 )
451 maxwrk =
max( maxwrk, 9*( nsize+1 )+nsize*
452 $ ilaenv( 1,
'DORGQR',
' ', nsize, 1, nsize, -1 ) )
456 bdspac = 5*nsize*nsize / 2
457 maxwrk =
max( maxwrk, 3*nsize*nsize / 2+nsize*nsize*
458 $ ilaenv( 1,
'DGEBRD',
' ', nsize*nsize / 2,
459 $ nsize*nsize / 2, -1, -1 ) )
460 maxwrk =
max( maxwrk, bdspac )
462 maxwrk =
max( maxwrk, minwrk )
467 IF( lwork.LT.minwrk )
471 CALL xerbla(
'DDRGSX', -info )
479 smlnum = dlamch(
'S' ) / ulp
480 bignum = one / smlnum
481 CALL dlabad( smlnum, bignum )
503 DO 40 m = 1, nsize - 1
504 DO 30 n = 1, nsize - m
506 weight = one / weight
514 CALL dlaset(
'Full', mplusn, mplusn, zero, zero, ai,
516 CALL dlaset(
'Full', mplusn, mplusn, zero, zero, bi,
519 CALL dlatm5( prtype, m, n, ai, lda, ai( m+1, m+1 ),
520 $ lda, ai( 1, m+1 ), lda, bi, lda,
521 $ bi( m+1, m+1 ), lda, bi( 1, m+1 ), lda,
522 $ q, lda, z, lda, weight, qba, qbb )
529 IF( ifunc.EQ.0 )
THEN
531 ELSE IF( ifunc.EQ.1 )
THEN
533 ELSE IF( ifunc.EQ.2 )
THEN
535 ELSE IF( ifunc.EQ.3 )
THEN
539 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, a, lda )
540 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda, b, lda )
542 CALL dggesx(
'V',
'V',
'S', dlctsx, sense, mplusn, ai,
543 $ lda, bi, lda, mm, alphar, alphai, beta,
544 $ q, lda, z, lda, pl, difest, work, lwork,
545 $ iwork, liwork, bwork, linfo )
547 IF( linfo.NE.0 .AND. linfo.NE.mplusn+2 )
THEN
549 WRITE( nout, fmt = 9999 )
'DGGESX', linfo, mplusn,
557 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, work,
559 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda,
560 $ work( mplusn*mplusn+1 ), mplusn )
561 abnrm = dlange(
'Fro', mplusn, 2*mplusn, work, mplusn,
566 CALL dget51( 1, mplusn, a, lda, ai, lda, q, lda, z,
567 $ lda, work, result( 1 ) )
568 CALL dget51( 1, mplusn, b, lda, bi, lda, q, lda, z,
569 $ lda, work, result( 2 ) )
570 CALL dget51( 3, mplusn, b, lda, bi, lda, q, lda, q,
571 $ lda, work, result( 3 ) )
572 CALL dget51( 3, mplusn, b, lda, bi, lda, z, lda, z,
573 $ lda, work, result( 4 ) )
585 IF( alphai( j ).EQ.zero )
THEN
586 temp2 = ( abs( alphar( j )-ai( j, j ) ) /
587 $
max( smlnum, abs( alphar( j ) ),
588 $ abs( ai( j, j ) ) )+
589 $ abs( beta( j )-bi( j, j ) ) /
590 $
max( smlnum, abs( beta( j ) ),
591 $ abs( bi( j, j ) ) ) ) / ulp
592 IF( j.LT.mplusn )
THEN
593 IF( ai( j+1, j ).NE.zero )
THEN
599 IF( ai( j, j-1 ).NE.zero )
THEN
605 IF( alphai( j ).GT.zero )
THEN
610 IF( i1.LE.0 .OR. i1.GE.mplusn )
THEN
612 ELSE IF( i1.LT.mplusn-1 )
THEN
613 IF( ai( i1+2, i1+1 ).NE.zero )
THEN
617 ELSE IF( i1.GT.1 )
THEN
618 IF( ai( i1, i1-1 ).NE.zero )
THEN
623 IF( .NOT.ilabad )
THEN
624 CALL dget53( ai( i1, i1 ), lda, bi( i1, i1 ),
625 $ lda, beta( j ), alphar( j ),
626 $ alphai( j ), temp2, iinfo )
627 IF( iinfo.GE.3 )
THEN
628 WRITE( nout, fmt = 9997 )iinfo, j,
636 temp1 =
max( temp1, temp2 )
638 WRITE( nout, fmt = 9996 )j, mplusn, prtype
647 IF( linfo.EQ.mplusn+3 )
THEN
649 ELSE IF( mm.NE.n )
THEN
658 mn2 = mm*( mplusn-mm )*2
659 IF( ifunc.GE.2 .AND. mn2.LE.ncmax*ncmax )
THEN
664 CALL dlakf2( mm, mplusn-mm, ai, lda,
665 $ ai( mm+1, mm+1 ), bi,
666 $ bi( mm+1, mm+1 ), c, ldc )
668 CALL dgesvd(
'N',
'N', mn2, mn2, c, ldc, s, work,
669 $ 1, work( 2 ), 1, work( 3 ), lwork-2,
673 IF( difest( 2 ).EQ.zero )
THEN
674 IF( diftru.GT.abnrm*ulp )
675 $ result( 8 ) = ulpinv
676 ELSE IF( diftru.EQ.zero )
THEN
677 IF( difest( 2 ).GT.abnrm*ulp )
678 $ result( 8 ) = ulpinv
679 ELSE IF( ( diftru.GT.thrsh2*difest( 2 ) ) .OR.
680 $ ( diftru*thrsh2.LT.difest( 2 ) ) )
THEN
681 result( 8 ) =
max( diftru / difest( 2 ),
690 IF( linfo.EQ.( mplusn+2 ) )
THEN
691 IF( diftru.GT.abnrm*ulp )
693 IF( ( ifunc.GT.1 ) .AND. ( difest( 2 ).NE.zero ) )
694 $ result( 9 ) = ulpinv
695 IF( ( ifunc.EQ.1 ) .AND. ( pl( 1 ).NE.zero ) )
696 $ result( 9 ) = ulpinv
700 ntestt = ntestt + ntest
705 IF( result( j ).GE.thresh )
THEN
710 IF( nerrs.EQ.0 )
THEN
711 WRITE( nout, fmt = 9995 )
'DGX'
715 WRITE( nout, fmt = 9993 )
719 WRITE( nout, fmt = 9992 )
'orthogonal',
'''',
720 $
'transpose', (
'''', i = 1, 4 )
724 IF( result( j ).LT.10000.0d0 )
THEN
725 WRITE( nout, fmt = 9991 )mplusn, prtype,
726 $ weight, m, j, result( j )
728 WRITE( nout, fmt = 9990 )mplusn, prtype,
729 $ weight, m, j, result( j )
749 READ( nin, fmt = *,
END = 140 )mplusn
752 READ( nin, fmt = *,
END = 140 )n
754 READ( nin, fmt = * )( ai( i, j ), j = 1, mplusn )
757 READ( nin, fmt = * )( bi( i, j ), j = 1, mplusn )
759 READ( nin, fmt = * )pltru, diftru
766 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, a, lda )
767 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda, b, lda )
772 CALL dggesx(
'V',
'V',
'S',
dlctsx,
'B', mplusn, ai, lda, bi, lda,
773 $ mm, alphar, alphai, beta, q, lda, z, lda, pl, difest,
774 $ work, lwork, iwork, liwork, bwork, linfo )
776 IF( linfo.NE.0 .AND. linfo.NE.mplusn+2 )
THEN
778 WRITE( nout, fmt = 9998 )
'DGGESX', linfo, mplusn, nptknt
785 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, work, mplusn )
786 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda,
787 $ work( mplusn*mplusn+1 ), mplusn )
788 abnrm =
dlange(
'Fro', mplusn, 2*mplusn, work, mplusn, work )
792 CALL dget51( 1, mplusn, a, lda, ai, lda, q, lda, z, lda, work,
794 CALL dget51( 1, mplusn, b, lda, bi, lda, q, lda, z, lda, work,
796 CALL dget51( 3, mplusn, b, lda, bi, lda, q, lda, q, lda, work,
811 IF( alphai( j ).EQ.zero )
THEN
812 temp2 = ( abs( alphar( j )-ai( j, j ) ) /
813 $
max( smlnum, abs( alphar( j ) ), abs( ai( j,
814 $ j ) ) )+abs( beta( j )-bi( j, j ) ) /
815 $
max( smlnum, abs( beta( j ) ), abs( bi( j, j ) ) ) )
817 IF( j.LT.mplusn )
THEN
818 IF( ai( j+1, j ).NE.zero )
THEN
830 IF( alphai( j ).GT.zero )
THEN
835 IF( i1.LE.0 .OR. i1.GE.mplusn )
THEN
837 ELSE IF( i1.LT.mplusn-1 )
THEN
838 IF( ai( i1+2, i1+1 ).NE.zero )
THEN
842 ELSE IF( i1.GT.1 )
THEN
843 IF( ai( i1, i1-1 ).NE.zero )
THEN
848 IF( .NOT.ilabad )
THEN
849 CALL dget53( ai( i1, i1 ), lda, bi( i1, i1 ), lda,
850 $ beta( j ), alphar( j ), alphai( j ), temp2,
852 IF( iinfo.GE.3 )
THEN
853 WRITE( nout, fmt = 9997 )iinfo, j, mplusn, nptknt
860 temp1 =
max( temp1, temp2 )
862 WRITE( nout, fmt = 9996 )j, mplusn, nptknt
871 IF( linfo.EQ.mplusn+3 )
872 $ result( 7 ) = ulpinv
878 IF( difest( 2 ).EQ.zero )
THEN
879 IF( diftru.GT.abnrm*ulp )
880 $ result( 8 ) = ulpinv
881 ELSE IF( diftru.EQ.zero )
THEN
882 IF( difest( 2 ).GT.abnrm*ulp )
883 $ result( 8 ) = ulpinv
884 ELSE IF( ( diftru.GT.thrsh2*difest( 2 ) ) .OR.
886 result( 8 ) =
max( diftru / difest( 2 ), difest( 2 ) / diftru )
893 IF( linfo.EQ.( mplusn+2 ) )
THEN
894 IF( diftru.GT.abnrm*ulp )
896 IF( ( ifunc.GT.1 ) .AND. ( difest( 2 ).NE.zero ) )
897 $ result( 9 ) = ulpinv
898 IF( ( ifunc.EQ.1 ) .AND. ( pl( 1 ).NE.zero ) )
899 $ result( 9 ) = ulpinv
906 IF( pl( 1 ).EQ.zero )
THEN
907 IF( pltru.GT.abnrm*ulp )
908 $ result( 10 ) = ulpinv
909 ELSE IF( pltru.EQ.zero )
THEN
910 IF( pl( 1 ).GT.abnrm*ulp )
911 $ result( 10 ) = ulpinv
912 ELSE IF( ( pltru.GT.thresh*pl( 1 ) ) .OR.
913 $ ( pltru*thresh.LT.pl( 1 ) ) )
THEN
914 result( 10 ) = ulpinv
917 ntestt = ntestt + ntest
922 IF( result( j ).GE.thresh )
THEN
927 IF( nerrs.EQ.0 )
THEN
928 WRITE( nout, fmt = 9995 )
'DGX'
932 WRITE( nout, fmt = 9994 )
936 WRITE( nout, fmt = 9992 )
'orthogonal',
'''',
937 $
'transpose', (
'''', i = 1, 4 )
941 IF( result( j ).LT.10000.0d0 )
THEN
942 WRITE( nout, fmt = 9989 )nptknt, mplusn, j, result( j )
944 WRITE( nout, fmt = 9988 )nptknt, mplusn, j, result( j )
958 CALL alasvm(
'DGX', nout, nerrs, ntestt, 0 )
964 9999
FORMAT(
' DDRGSX: ', a,
' returned INFO=', i6,
'.', / 9x,
'N=',
965 $ i6,
', JTYPE=', i6,
')' )
967 9998
FORMAT(
' DDRGSX: ', a,
' returned INFO=', i6,
'.', / 9x,
'N=',
968 $ i6,
', Input Example #', i2,
')' )
970 9997
FORMAT(
' DDRGSX: DGET53 returned INFO=', i1,
' for eigenvalue ',
971 $ i6,
'.', / 9x,
'N=', i6,
', JTYPE=', i6,
')' )
973 9996
FORMAT(
' DDRGSX: S not in Schur form at eigenvalue ', i6,
'.',
974 $ / 9x,
'N=', i6,
', JTYPE=', i6,
')' )
976 9995
FORMAT( / 1x, a3,
' -- Real Expert Generalized Schur form',
977 $
' problem driver' )
979 9994
FORMAT(
'Input Example' )
981 9993
FORMAT(
' Matrix types: ', /
982 $
' 1: A is a block diagonal matrix of Jordan blocks ',
983 $
'and B is the identity ', /
' matrix, ',
984 $ /
' 2: A and B are upper triangular matrices, ',
985 $ /
' 3: A and B are as type 2, but each second diagonal ',
986 $
'block in A_11 and ', /
987 $
' each third diaongal block in A_22 are 2x2 blocks,',
988 $ /
' 4: A and B are block diagonal matrices, ',
989 $ /
' 5: (A,B) has potentially close or common ',
990 $
'eigenvalues.', / )
992 9992
FORMAT( /
' Tests performed: (S is Schur, T is triangular, ',
993 $
'Q and Z are ', a,
',', / 19x,
994 $
' a is alpha, b is beta, and ', a,
' means ', a,
'.)',
995 $ /
' 1 = | A - Q S Z', a,
996 $
' | / ( |A| n ulp ) 2 = | B - Q T Z', a,
997 $
' | / ( |B| n ulp )', /
' 3 = | I - QQ', a,
998 $
' | / ( n ulp ) 4 = | I - ZZ', a,
999 $
' | / ( n ulp )', /
' 5 = 1/ULP if A is not in ',
1000 $
'Schur form S', /
' 6 = difference between (alpha,beta)',
1001 $
' and diagonals of (S,T)', /
1002 $
' 7 = 1/ULP if SDIM is not the correct number of ',
1003 $
'selected eigenvalues', /
1004 $
' 8 = 1/ULP if DIFEST/DIFTRU > 10*THRESH or ',
1005 $
'DIFTRU/DIFEST > 10*THRESH',
1006 $ /
' 9 = 1/ULP if DIFEST <> 0 or DIFTRU > ULP*norm(A,B) ',
1007 $
'when reordering fails', /
1008 $
' 10 = 1/ULP if PLEST/PLTRU > THRESH or ',
1009 $
'PLTRU/PLEST > THRESH', /
1010 $
' ( Test 10 is only for input examples )', / )
1011 9991
FORMAT(
' Matrix order=', i2,
', type=', i2,
', a=', d10.3,
1012 $
', order(A_11)=', i2,
', result ', i2,
' is ', 0p, f8.2 )
1013 9990
FORMAT( ' matrix order=
', I2, ', type=
', I2, ', a=
', D10.3,
1014 $ ', order(a_11)=
', I2, ', result
', I2, ' is
', 0P, D10.3 )
1015 9989 FORMAT( ' input example
#', I2, ', matrix order=', I4, ',',
1016 $
' result ', i2,
' is', 0p, f8.2 )
1017 9988
FORMAT(
' Input example #', i2,
', matrix order=', i4,
',',
1018 $ ' result
', I2, ' is
', 1P, D10.3 )