1 SUBROUTINE pzheevx( JOBZ, RANGE, UPLO, N, A, IA, JA, DESCA, VL,
2 $ VU, IL, IU, ABSTOL, M, NZ, W, ORFAC, Z, IZ,
3 $ JZ, DESCZ, WORK, LWORK, RWORK, LRWORK, IWORK,
4 $ LIWORK, IFAIL, ICLUSTR, GAP, INFO )
12 CHARACTER JOBZ, RANGE, UPLO
13 INTEGER IA, IL, INFO, IU, IZ
15DOUBLE PRECISION ABSTOL, ORFAC, , VU
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
19 $ IFAIL( * ), IWORK( * )
20 DOUBLE PRECISION GAP( * ), RWORK( * ), W( * )
21 COMPLEX*16 A( * ), WORK( * ), Z( * )
470 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_
472 PARAMETER ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
473 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
474 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
475 DOUBLE PRECISION ZERO, ONE, TEN, FIVE
476 PARAMETER ( ZERO = 0.0d+0, one = 1.0d+0, ten = 10.0d+0,
478 INTEGER IERREIN, IERRCLS, IERRSPC, IERREBZ
479 parameter( ierrein = 1, ierrcls = 2, ierrspc = 4,
483 LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, QUICKRETURN,
486 INTEGER ANB, CSRC_A, I, IAROW, ICOFFA, ICTXT, IINFO,
487 $ INDD, INDD2, , INDE2, INDIBL, INDISP,
488 $ indrwork, indtau, indwork, iroffa, iroffz,
489 $ iscale, isizestebz, isizestein, izrow,
490 $ lallwork, liwmin, llrwork, llwork, lrwmin,
491 $ lrwopt, lwmin, lwopt, maxeigs, mb_a, mq0,
492 $ mycol, myrow, nb, nb_a, neig, nhetrd_lwopt, nn,
493 $ nnp, np0, npcol, nprocs, nprow, nps, nq0,
496 DOUBLE PRECISION ABSTLL, , BIGNUM, EPS, RMAX, RMIN, SAFMIN,
497 $ SIGMA, SMLNUM, VLL, VUU
500 INTEGER ( 4 ), IDUM2( 4 )
504 INTEGER ICEIL, INDXG2P, NUMROC, PJLAENV
505 DOUBLE PRECISION PDLAMCH, PZLANHE
506 EXTERNAL lsame, iceil, indxg2p, numroc, pjlaenv,
516 INTRINSIC abs, dble, dcmplx, ichar, int,
max,
min, mod,
521 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_
524 quickreturn = ( n.EQ.0 )
528 ictxt = desca( ctxt_ )
532 wantz = lsame( jobz,
'V' )
533 IF( nprow.EQ.-1 )
THEN
534 info = -( 800+ctxt_ )
535 ELSE IF( wantz )
THEN
536 IF( ictxt.NE.descz( ctxt_ ) )
THEN
537 info = -( 2100+ctxt_ )
541 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
543 $
CALL chk1mat( n, 4, n, 4, iz, jz, descz, 21, info )
549 safmin = pdlamch( ictxt,
'Safe minimum' )
550 eps = pdlamch( ictxt,
'Precision' )
551 smlnum = safmin / eps
552 bignum = one / smlnum
553 rmin = sqrt( smlnum )
554 rmax =
min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
557 lower = lsame( uplo,
'L' )
558 alleig = lsame( range,
'A' )
559 valeig = lsame( range,
'V' )
560 indeig = lsame( range,
'I' )
566 llwork = lwork - indwork + 1
575 llrwork = lrwork - indrwork + 1
579 isizestein = 3*n + nprocs + 1
580 isizestebz =
max( 4*n, 14, nprocs )
581 indibl = (
max( isizestein, isizestebz ) ) + 1
587 IF( lwork.EQ.-1 .OR. liwork.EQ.-1 .OR. lrwork.EQ.-1 )
590 nnp =
max( n, nprocs+1, 4 )
599 rsrc_a = desca( rsrc_ )
600 csrc_a = desca( csrc_ )
601 iroffa = mod( ia-1, mb_a )
602 icoffa = mod( ja-1, nb_a )
603 iarow = indxg2p( 1, nb_a, myrow, rsrc_a, nprow )
604 np0 = numroc( n+iroffa, nb, 0, 0, nprow )
605 mq0 = numroc( n+icoffa, nb, 0, 0, npcol )
607 rsrc_z = descz( rsrc_ )
608 iroffz = mod( iz-1, mb_a )
609 izrow = indxg2p( 1, nb_a, myrow, rsrc_z, nprow )
615 IF( ( .NOT.wantz ) .OR. ( valeig .AND. ( .NOT.lquery ) ) )
617 lwmin = n +
max( nb*( np0+1 ), 3 )
621 mq0 = numroc(
max( n, nb, 2 ), nb, 0, 0, npcol )
622 lrwopt = 4*n +
max( 5*nn, np0*mq0 ) +
623 $ iceil( n, nprow*npcol )*nn
629 IF( alleig .OR. valeig )
THEN
631 ELSE IF( indeig )
THEN
634 mq0 = numroc(
max( neig, nb, 2 ), nb, 0, 0, npcol )
635 nq0 = numroc( nn, nb,
636 lwmin = n + ( np0+nq0+nb )*nb
637 lrwmin = 4*n +
max( 5*nn, np0*mq0 ) +
638 $ iceil( neig, nprow*npcol )*nn
647 anb = pjlaenv( ictxt, 3,
'PZHETTRD',
'L', 0, 0, 0, 0 )
648 sqnpc = int( sqrt( dble( nprow*npcol ) ) )
649 nps =
max( numroc( n, 1, 0, 0, sqnpc ), 2*anb )
650 nhetrd_lwopt = 2*( anb+1 )*( 4*nps+2 ) + ( nps+2 )*nps
651 lwopt =
max( lwopt, n+nhetrd_lwopt )
655 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
THEN
664 CALL dgebs2d( ictxt,
'ALL',
' ', 3, 1, rwork, 3 )
666 CALL dgebr2d( ictxt,
'ALL',
' ', 3, 1, rwork, 3, 0, 0 )
668 IF( .NOT.( wantz .OR. lsame( jobz,
'N' ) ) )
THEN
670 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) )
THEN
672 ELSE IF( .NOT.( lower .OR. lsame( uplo,
'U' ) ) )
THEN
674 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl )
THEN
676 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
679 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
682 ELSE IF( lwork.LT.lwmin .AND. lwork.NE.-1 )
THEN
684 ELSE IF( lrwork.LT.lrwmin .AND. lrwork.NE.-1 )
THEN
686 ELSE IF( liwork.LT.liwmin .AND. liwork.NE.-1 )
THEN
688 ELSE IF( valeig .AND. ( abs( rwork( 2 )-vl ).GT.five*eps*
691 ELSE IF( valeig .AND. ( abs( rwork( 3 )-vu ).GT.five*eps*
694 ELSE IF( abs( rwork( 1 )-abstol ).GT.five*eps*
695 $ abs( abstol ) )
THEN
697 ELSE IF( iroffa.NE.0 )
THEN
699 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
703 IF( iroffa.NE.iroffz )
THEN
705 ELSE IF( iarow.NE.izrow )
THEN
707 ELSE IF( desca( m_ ).NE.descz( m_ ) )
THEN
709 ELSE IF( desca( n_ ).NE.descz( n_ ) )
THEN
711 ELSE IF( desca( mb_ ).NE.descz( mb_ ) )
THEN
713 ELSE IF( desca( nb_ ).NE.descz( nb_ ) )
THEN
715 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) )
THEN
716 info = -( 2100+rsrc_ )
717 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) )
THEN
718 info = -( 2100+csrc_ )
719 ELSE IF( ictxt.NE.descz( ctxt_ ) )
THEN
720 info = -( 2100+ctxt_ )
725 idum1( 1 ) = ichar(
'V' )
727 idum1( 1 ) = ichar(
'N' )
731 idum1( 2 ) = ichar(
'L' )
733 idum1( 2 ) = ichar(
'U' )
737 idum1( 3 ) = ichar(
'A' )
738 ELSE IF( indeig )
THEN
739 idum1( 3 ) = ichar(
'I' )
741 idum1( 3 ) = ichar(
'V' )
751 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 8, n, 4, n, 4, iz,
752 $ jz, descz, 21, 4, idum1, idum2, info )
754 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 4, idum1,
757 work( 1 ) = dcmplx( lwopt )
758 rwork( 1 ) = dble( lrwopt )
763 CALL pxerbla( ictxt,
'PZHEEVX', -info )
765 ELSE IF( lquery )
THEN
771 IF( quickreturn )
THEN
777 work( 1 ) = dcmplx( lwopt )
778 rwork( 1 ) = dble( lrwmin )
795 anrm = pzlanhe(
'M', uplo, n, a, ia, ja, desca,
796 $ rwork( indrwork ) )
798 IF( anrm.GT.zero .AND. anrm.LT.rmin )
THEN
802 ELSE IF( anrm.GT.rmax )
THEN
808 IF( iscale.EQ.1 )
THEN
809 CALL pzlascl( uplo, one, sigma, n, n, a, ia, ja, desca, iinfo )
811 $ abstll = abstol*sigma
815 IF( vuu.EQ.vll )
THEN
816 vuu = vuu + 2*
max( abs( vuu )*eps, safmin )
826 $ rwork( inde ), work( indtau ), work( indwork ),
827 $ llwork, rwork( indrwork ), llrwork, iinfo )
837 IF( ia.EQ.1 .AND. ja.EQ.1 .AND. rsrc_a.EQ.0 .AND. csrc_a.EQ.
839 CALL pdlared1d( n, ia, ja, desca, rwork( indd ),
840 $ rwork( indd2 ), rwork( indrwork ), llrwork )
842 CALL pdlared1d( n, ia, ja, desca, rwork( inde ),
843 $ rwork( inde2 ), rwork( indrwork ), llrwork )
848 CALL pzelget(
'A',
' ', work( indd2+i-1 ), a, i+ia-1,
850 rwork( indd2+i-1 ) = dble( work( indd2+i-1
852 IF( lsame( uplo,
'U' ) )
THEN
854 CALL pzelget(
'A',
' ', work( inde2+i-1 ), a, i+ia-1,
856 rwork( inde2+i-1 ) = dble( work( inde2+i-1 ) )
860 CALL pzelget(
'A',
' ', work( inde2+i-1 ), a, i+ia,
862 rwork( inde2+i-1 ) = dble( work( inde2+i-1 ) )
875 CALL pdstebz( ictxt, range, order, n, vll, vuu, il, iu, abstll,
876 $ rwork( indd2 ), rwork
877 $ iwork( indibl ), iwork( indisp ), rwork( indrwork ),
878 $ llrwork, iwork( 1 ), isizestebz, iinfo )
888 IF( iinfo.NE.0 )
THEN
889 info = info + ierrebz
908 CALL igamn2d( ictxt,
'A',
' ', 1, 1, lallwork, 1, 1, 1, -1,
911 maxeigs = descz( n_ )
913 DO 50 nz =
min( maxeigs, m ), 0, -1
914 mq0 = numroc( nz, nb, 0, 0, npcol )
915 sizestein = iceil( nz, nprocs )*n +
max( 5*n, np0*mq0 )
916 sizeheevx = sizestein
917 IF( sizeheevx.LE.lallwork )
926 info = info + ierrspc
941 IF( nsplit.GT.1 )
THEN
942 CALL dlasrt(
'I', m, w, iinfo )
946 vuu = w( nz ) - ten*( eps*anrm+safmin )
947 IF( vll.GE.vuu )
THEN
950 CALL pdstebz( ictxt, range, order, n, vll, vuu, il,
951 $ iu, abstll, rwork( indd2 ),
952 $ rwork( inde2+offset ), nzz, nsplit,
953 $ w, iwork( indibl ), iwork( indisp ),
954 $ rwork( indrwork ), llrwork,
955 $ iwork( 1 ), isizestebz, iinfo )
958 IF( mod( info / ierrebz, 1 ).EQ.0 )
THEN
959 IF( nzz.GT.nz .OR. iinfo.NE.0 )
THEN
960 info = info + ierrebz
968 CALL pzstein( n, rwork( indd2 ), rwork( inde2+offset ), nz, w,
969 $ iwork( indibl ), iwork( indisp ), orfac, z, iz,
970 $ jz, descz, rwork( indrwork ), lallwork,
971 $ iwork( 1 ), isizestein, ifail, iclustr, gap,
975 $ info = info + ierrcls
976 IF( mod( iinfo, nz+1 ).NE.0 )
977 $ info = info + ierrein
983 CALL pzunmtr(
'L', uplo,
'N', n, nz, a, ia, ja, desca,
984 $ work( indtau ), z, iz, jz, descz,
985 $ work( indwork ), llwork, iinfo )
992 IF( iscale.EQ.1 )
THEN
993 CALL dscal( m, one / sigma, w, 1 )
996 work( 1 ) = dcmplx( lwopt )
997 rwork( 1 ) = dble( lrwopt )