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
502 DO 40 m = 1, nsize - 1
503 DO 30 n = 1, nsize - m
505 weight = one / weight
513 CALL dlaset(
'Full', mplusn, mplusn, zero, zero, ai,
515 CALL dlaset(
'Full', mplusn, mplusn, zero, zero, bi,
518 CALL dlatm5( prtype, m, n, ai, lda, ai( m+1, m+1 ),
519 $ lda, ai( 1, m+1 ), lda, bi, lda,
520 $ bi( m+1, m+1 ), lda, bi( 1, m+1 ), lda,
521 $ q, lda, z, lda, weight, qba, qbb )
528 IF( ifunc.EQ.0 )
THEN
530 ELSE IF( ifunc.EQ.1 )
THEN
532 ELSE IF( ifunc.EQ.2 )
THEN
534 ELSE IF( ifunc.EQ.3 )
THEN
538 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, a, lda )
539 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda, b, lda )
541 CALL dggesx(
'V',
'V',
'S', dlctsx, sense, mplusn, ai,
542 $ lda, bi, lda, mm, alphar, alphai, beta,
543 $ q, lda, z, lda, pl, difest, work, lwork,
544 $ iwork, liwork, bwork, linfo )
546 IF( linfo.NE.0 .AND. linfo.NE.mplusn+2 )
THEN
548 WRITE( nout, fmt = 9999 )
'DGGESX', linfo, mplusn,
556 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, work,
558 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda,
559 $ work( mplusn*mplusn+1 ), mplusn )
560 abnrm = dlange(
'Fro', mplusn, 2*mplusn, work, mplusn,
565 CALL dget51( 1, mplusn, a, lda, ai, lda, q, lda, z,
566 $ lda, work, result( 1 ) )
567 CALL dget51( 1, mplusn, b, lda, bi, lda, q, lda, z,
568 $ lda, work, result( 2 ) )
569 CALL dget51( 3, mplusn, b, lda, bi, lda, q, lda, q,
570 $ lda, work, result( 3 ) )
571 CALL dget51( 3, mplusn, b, lda, bi, lda, z, lda, z,
572 $ lda, work, result( 4 ) )
584 IF( alphai( j ).EQ.zero )
THEN
585 temp2 = ( abs( alphar( j )-ai( j, j ) ) /
586 $ max( smlnum, abs( alphar( j ) ),
587 $ abs( ai( j, j ) ) )+
588 $ abs( beta( j )-bi( j, j ) ) /
589 $ max( smlnum, abs( beta( j ) ),
590 $ abs( bi( j, j ) ) ) ) / ulp
591 IF( j.LT.mplusn )
THEN
592 IF( ai( j+1, j ).NE.zero )
THEN
598 IF( ai( j, j-1 ).NE.zero )
THEN
604 IF( alphai( j ).GT.zero )
THEN
609 IF( i1.LE.0 .OR. i1.GE.mplusn )
THEN
611 ELSE IF( i1.LT.mplusn-1 )
THEN
612 IF( ai( i1+2, i1+1 ).NE.zero )
THEN
616 ELSE IF( i1.GT.1 )
THEN
617 IF( ai( i1, i1-1 ).NE.zero )
THEN
622 IF( .NOT.ilabad )
THEN
623 CALL dget53( ai( i1, i1 ), lda, bi( i1, i1 ),
624 $ lda, beta( j ), alphar( j ),
625 $ alphai( j ), temp2, iinfo )
626 IF( iinfo.GE.3 )
THEN
627 WRITE( nout, fmt = 9997 )iinfo, j,
635 temp1 = max( temp1, temp2 )
637 WRITE( nout, fmt = 9996 )j, mplusn, prtype
646 IF( linfo.EQ.mplusn+3 )
THEN
648 ELSE IF( mm.NE.n )
THEN
657 mn2 = mm*( mplusn-mm )*2
658 IF( ifunc.GE.2 .AND. mn2.LE.ncmax*ncmax )
THEN
663 CALL dlakf2( mm, mplusn-mm, ai, lda,
664 $ ai( mm+1, mm+1 ), bi,
665 $ bi( mm+1, mm+1 ), c, ldc )
667 CALL dgesvd(
'N',
'N', mn2, mn2, c, ldc, s, work,
668 $ 1, work( 2 ), 1, work( 3 ), lwork-2,
672 IF( difest( 2 ).EQ.zero )
THEN
673 IF( diftru.GT.abnrm*ulp )
674 $ result( 8 ) = ulpinv
675 ELSE IF( diftru.EQ.zero )
THEN
676 IF( difest( 2 ).GT.abnrm*ulp )
677 $ result( 8 ) = ulpinv
678 ELSE IF( ( diftru.GT.thrsh2*difest( 2 ) ) .OR.
679 $ ( diftru*thrsh2.LT.difest( 2 ) ) )
THEN
680 result( 8 ) = max( diftru / difest( 2 ),
681 $ difest( 2 ) / diftru )
689 IF( linfo.EQ.( mplusn+2 ) )
THEN
690 IF( diftru.GT.abnrm*ulp )
691 $ result( 9 ) = ulpinv
692 IF( ( ifunc.GT.1 ) .AND. ( difest( 2 ).NE.zero ) )
693 $ result( 9 ) = ulpinv
694 IF( ( ifunc.EQ.1 ) .AND. ( pl( 1 ).NE.zero ) )
695 $ result( 9 ) = ulpinv
699 ntestt = ntestt + ntest
704 IF( result( j ).GE.thresh )
THEN
709 IF( nerrs.EQ.0 )
THEN
710 WRITE( nout, fmt = 9995 )
'DGX'
714 WRITE( nout, fmt = 9993 )
718 WRITE( nout, fmt = 9992 )
'orthogonal',
'''',
719 $
'transpose', (
'''', i = 1, 4 )
723 IF( result( j ).LT.10000.0d0 )
THEN
724 WRITE( nout, fmt = 9991 )mplusn, prtype,
725 $ weight, m, j, result( j )
727 WRITE( nout, fmt = 9990 )mplusn, prtype,
728 $ weight, m, j, result( j )
748 READ( nin, fmt = *,
END = 140 )mplusn
751 READ( nin, fmt = *,
END = 140 )n
753 READ( nin, fmt = * )( ai( i, j ), j = 1, mplusn )
756 READ( nin, fmt = * )( bi( i, j ), j = 1, mplusn )
758 READ( nin, fmt = * )pltru, diftru
765 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, a, lda )
766 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda, b, lda )
771 CALL dggesx(
'V',
'V',
'S',
dlctsx,
'B', mplusn, ai, lda, bi, lda,
772 $ mm, alphar, alphai, beta, q, lda, z, lda, pl, difest,
773 $ work, lwork, iwork, liwork, bwork, linfo )
775 IF( linfo.NE.0 .AND. linfo.NE.mplusn+2 )
THEN
777 WRITE( nout, fmt = 9998 )
'DGGESX', linfo, mplusn, nptknt
784 CALL dlacpy(
'Full', mplusn, mplusn, ai, lda, work, mplusn )
785 CALL dlacpy(
'Full', mplusn, mplusn, bi, lda,
786 $ work( mplusn*mplusn+1 ), mplusn )
787 abnrm =
dlange(
'Fro', mplusn, 2*mplusn, work, mplusn, work )
791 CALL dget51( 1, mplusn, a, lda, ai, lda, q, lda, z, lda, work,
793 CALL dget51( 1, mplusn, b, lda, bi, lda, q, lda, z, lda, work,
795 CALL dget51( 3, mplusn, b, lda, bi, lda, q, lda, q, lda, work,
797 CALL dget51( 3, mplusn, b, lda, bi, lda, z, lda, z, lda, work,
810 IF( alphai( j ).EQ.zero )
THEN
811 temp2 = ( abs( alphar( j )-ai( j, j ) ) /
812 $ max( smlnum, abs( alphar( j ) ), abs( ai( j,
813 $ j ) ) )+abs( beta( j )-bi( j, j ) ) /
814 $ max( smlnum, abs( beta( j ) ), abs( bi( j, j ) ) ) )
816 IF( j.LT.mplusn )
THEN
817 IF( ai( j+1, j ).NE.zero )
THEN
823 IF( ai( j, j-1 ).NE.zero )
THEN
829 IF( alphai( j ).GT.zero )
THEN
834 IF( i1.LE.0 .OR. i1.GE.mplusn )
THEN
836 ELSE IF( i1.LT.mplusn-1 )
THEN
837 IF( ai( i1+2, i1+1 ).NE.zero )
THEN
841 ELSE IF( i1.GT.1 )
THEN
842 IF( ai( i1, i1-1 ).NE.zero )
THEN
847 IF( .NOT.ilabad )
THEN
848 CALL dget53( ai( i1, i1 ), lda, bi( i1, i1 ), lda,
849 $ beta( j ), alphar( j ), alphai( j ), temp2,
851 IF( iinfo.GE.3 )
THEN
852 WRITE( nout, fmt = 9997 )iinfo, j, mplusn, nptknt
859 temp1 = max( temp1, temp2 )
861 WRITE( nout, fmt = 9996 )j, mplusn, nptknt
870 IF( linfo.EQ.mplusn+3 )
871 $ result( 7 ) = ulpinv
877 IF( difest( 2 ).EQ.zero )
THEN
878 IF( diftru.GT.abnrm*ulp )
879 $ result( 8 ) = ulpinv
880 ELSE IF( diftru.EQ.zero )
THEN
881 IF( difest( 2 ).GT.abnrm*ulp )
882 $ result( 8 ) = ulpinv
883 ELSE IF( ( diftru.GT.thrsh2*difest( 2 ) ) .OR.
884 $ ( diftru*thrsh2.LT.difest( 2 ) ) )
THEN
885 result( 8 ) = max( diftru / difest( 2 ), difest( 2 ) / diftru )
892 IF( linfo.EQ.( mplusn+2 ) )
THEN
893 IF( diftru.GT.abnrm*ulp )
894 $ result( 9 ) = ulpinv
895 IF( ( ifunc.GT.1 ) .AND. ( difest( 2 ).NE.zero ) )
896 $ result( 9 ) = ulpinv
897 IF( ( ifunc.EQ.1 ) .AND. ( pl( 1 ).NE.zero ) )
898 $ result( 9 ) = ulpinv
905 IF( pl( 1 ).EQ.zero )
THEN
906 IF( pltru.GT.abnrm*ulp )
907 $ result( 10 ) = ulpinv
908 ELSE IF( pltru.EQ.zero )
THEN
909 IF( pl( 1 ).GT.abnrm*ulp )
910 $ result( 10 ) = ulpinv
911 ELSE IF( ( pltru.GT.thresh*pl( 1 ) ) .OR.
912 $ ( pltru*thresh.LT.pl( 1 ) ) )
THEN
913 result( 10 ) = ulpinv
916 ntestt = ntestt + ntest
921 IF( result( j ).GE.thresh )
THEN
926 IF( nerrs.EQ.0 )
THEN
927 WRITE( nout, fmt = 9995 )
'DGX'
931 WRITE( nout, fmt = 9994 )
935 WRITE( nout, fmt = 9992 )
'orthogonal',
'''',
936 $
'transpose', (
'''', i = 1, 4 )
940 IF( result( j ).LT.10000.0d0 )
THEN
941 WRITE( nout, fmt = 9989 )nptknt, mplusn, j, result( j )
943 WRITE( nout, fmt = 9988 )nptknt, mplusn, j, result( j )
957 CALL alasvm(
'DGX', nout, nerrs, ntestt, 0 )
963 9999
FORMAT(
' DDRGSX: ', a,
' returned INFO=', i6,
'.', / 9x,
'N=',
964 $ i6,
', JTYPE=', i6,
')' )
966 9998
FORMAT(
' DDRGSX: ', a,
' returned INFO=', i6,
'.', / 9x,
'N=',
967 $ i6,
', Input Example #', i2,
')' )
969 9997
FORMAT(
' DDRGSX: DGET53 returned INFO=', i1,
' for eigenvalue ',
970 $ i6,
'.', / 9x,
'N=', i6,
', JTYPE=', i6,
')' )
972 9996
FORMAT(
' DDRGSX: S not in Schur form at eigenvalue ', i6,
'.',
973 $ / 9x,
'N=', i6,
', JTYPE=', i6,
')' )
975 9995
FORMAT( / 1x, a3,
' -- Real Expert Generalized Schur form',
976 $
' problem driver' )
978 9994
FORMAT(
'Input Example' )
980 9993
FORMAT(
' Matrix types: ', /
981 $
' 1: A is a block diagonal matrix of Jordan blocks ',
982 $
'and B is the identity ', /
' matrix, ',
983 $ /
' 2: A and B are upper triangular matrices, ',
984 $ /
' 3: A and B are as type 2, but each second diagonal ',
985 $
'block in A_11 and ', /
986 $
' each third diagonal block in A_22 are 2x2 blocks,',
987 $ /
' 4: A and B are block diagonal matrices, ',
988 $ /
' 5: (A,B) has potentially close or common ',
989 $
'eigenvalues.', / )
991 9992
FORMAT( /
' Tests performed: (S is Schur, T is triangular, ',
992 $
'Q and Z are ', a,
',', / 19x,
993 $
' a is alpha, b is beta, and ', a,
' means ', a,
'.)',
994 $ /
' 1 = | A - Q S Z', a,
995 $
' | / ( |A| n ulp ) 2 = | B - Q T Z', a,
996 $
' | / ( |B| n ulp )', /
' 3 = | I - QQ', a,
997 $
' | / ( n ulp ) 4 = | I - ZZ', a,
998 $
' | / ( n ulp )', /
' 5 = 1/ULP if A is not in ',
999 $
'Schur form S', /
' 6 = difference between (alpha,beta)',
1000 $
' and diagonals of (S,T)', /
1001 $
' 7 = 1/ULP if SDIM is not the correct number of ',
1002 $
'selected eigenvalues', /
1003 $
' 8 = 1/ULP if DIFEST/DIFTRU > 10*THRESH or ',
1004 $
'DIFTRU/DIFEST > 10*THRESH',
1005 $ /
' 9 = 1/ULP if DIFEST <> 0 or DIFTRU > ULP*norm(A,B) ',
1006 $
'when reordering fails', /
1007 $
' 10 = 1/ULP if PLEST/PLTRU > THRESH or ',
1008 $
'PLTRU/PLEST > THRESH', /
1009 $
' ( Test 10 is only for input examples )', / )
1010 9991
FORMAT(
' Matrix order=', i2,
', type=', i2,
', a=', d10.3,
1011 $
', order(A_11)=', i2,
', result ', i2,
' is ', 0p, f8.2 )
1012 9990
FORMAT(
' Matrix order=', i2,
', type=', i2,
', a=', d10.3,
1013 $
', order(A_11)=', i2,
', result ', i2,
' is ', 0p, d10.3 )
1014 9989
FORMAT(
' Input example #', i2,
', matrix order=', i4,
',',
1015 $
' result ', i2,
' is', 0p, f8.2 )
1016 9988
FORMAT(
' Input example #', i2,
', matrix order=', i4,
',',
1017 $
' result ', i2,
' is', 1p, d10.3 )
subroutine alasvm(type, nout, nfail, nrun, nerrs)
ALASVM
subroutine xerbla(srname, info)
subroutine ddrgsx(nsize, ncmax, thresh, nin, nout, a, lda, b, ai, bi, z, q, alphar, alphai, beta, c, ldc, s, work, lwork, iwork, liwork, bwork, info)
DDRGSX
subroutine dget51(itype, n, a, lda, b, ldb, u, ldu, v, ldv, work, result)
DGET51
subroutine dget53(a, lda, b, ldb, scale, wr, wi, result, info)
DGET53
subroutine dlakf2(m, n, a, lda, b, d, e, z, ldz)
DLAKF2
subroutine dlatm5(prtype, m, n, a, lda, b, ldb, c, ldc, d, ldd, e, lde, f, ldf, r, ldr, l, ldl, alpha, qblcka, qblckb)
DLATM5
logical function dlctsx(ar, ai, beta)
DLCTSX
subroutine dgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, info)
DGESVD computes the singular value decomposition (SVD) for GE matrices
subroutine dggesx(jobvsl, jobvsr, sort, selctg, sense, n, a, lda, b, ldb, sdim, alphar, alphai, beta, vsl, ldvsl, vsr, ldvsr, rconde, rcondv, work, lwork, iwork, liwork, bwork, info)
DGGESX computes the eigenvalues, the Schur form, and, optionally, the matrix of Schur vectors for GE ...
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
double precision function dlange(norm, m, n, a, lda, work)
DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.