1 SUBROUTINE pcheevx( 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, JA, JZ, , LRWORK,
15 REAL ABSTOL, ORFAC, VL, VU
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
20 REAL GAP( * ), RWORK( * ), W( * )
21 COMPLEX A( * ), WORK( * ), Z( * )
470 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
471 $ MB_, NB_, RSRC_, CSRC_, LLD_
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 REAL ZERO, ONE, TEN, FIVE
476 PARAMETER ( ZERO = 0.0e+0, one = 1.0e+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, INDE, INDE2, INDIBL, INDISP,
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,
494 $ nsplit, nzz, offset, rsrc_a, rsrc_z, sizeheevx,
496 REAL ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,
497 $ SIGMA, SMLNUM, VLL, VUU
500 INTEGER IDUM1( 4 ), IDUM2( 4 )
504 INTEGER ICEIL, INDXG2P, NUMROC, PJLAENV
505 REAL PCLANHE, PSLAMCH
506 EXTERNAL lsame, iceil, indxg2p, numroc, pjlaenv,
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 = pslamch( ictxt,
'Safe minimum' )
550 eps = pslamch( 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, 0, 0, npcol )
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, '
pchettrd', '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.EQ..AND..EQ.
IF( MYROW0 MYCOL0 ) THEN
664 CALL SGEBS2D( ICTXT, 'all
', ' ', 3, 1, RWORK, 3 )
666 CALL SGEBR2D( ICTXT, 'all
', ' ', 3, 1, RWORK, 3, 0, 0 )
668.NOT..OR.
IF( ( WANTZ LSAME( JOBZ, 'n
' ) ) ) THEN
670.NOT..OR..OR.
ELSE IF( ( ALLEIG VALEIG INDEIG ) ) THEN
672.NOT..OR.
ELSE IF( ( LOWER LSAME( UPLO, 'u
' ) ) ) THEN
674.AND..GT..AND..LE.
ELSE IF( VALEIG N0 VUVL ) THEN
676.AND..LT..OR..GT.
ELSE IF( INDEIG ( IL1 ILMAX( 1, N ) ) )
679.AND..LT..OR..GT.
ELSE IF( INDEIG ( IUMIN( N, IL ) IUN ) )
682.LT..AND..NE.
ELSE IF( LWORKLWMIN LWORK-1 ) THEN
684.LT..AND..NE.
ELSE IF( LRWORKLRWMIN LRWORK-1 ) THEN
686.LT..AND..NE.
ELSE IF( LIWORKLIWMIN LIWORK-1 ) THEN
688.AND..GT.
ELSE IF( VALEIG ( ABS( RWORK( 2 )-VL )FIVE*EPS*
691.AND..GT.
ELSE IF( VALEIG ( ABS( RWORK( 3 )-VU )FIVE*EPS*
694.GT.
ELSE IF( ABS( RWORK( 1 )-ABSTOL )FIVE*EPS*
695 $ ABS( ABSTOL ) ) THEN
697.NE.
ELSE IF( IROFFA0 ) THEN
699.NE.
ELSE IF( DESCA( MB_ )DESCA( NB_ ) ) THEN
703.NE.
IF( IROFFAIROFFZ ) THEN
705.NE.
ELSE IF( IAROWIZROW ) THEN
707.NE.
ELSE IF( DESCA( M_ )DESCZ( M_ ) ) THEN
709.NE.
ELSE IF( DESCA( N_ )DESCZ( N_ ) ) THEN
711.NE.
ELSE IF( DESCA( MB_ )DESCZ( MB_ ) ) THEN
713.NE.
ELSE IF( DESCA( NB_ )DESCZ( NB_ ) ) THEN
715.NE.
ELSE IF( DESCA( RSRC_ )DESCZ( RSRC_ ) ) THEN
716 INFO = -( 2100+RSRC_ )
717.NE.
ELSE IF( DESCA( CSRC_ )DESCZ( CSRC_ ) ) THEN
718 INFO = -( 2100+CSRC_ )
719.NE.
ELSE IF( ICTXTDESCZ( 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 ) =
cmplx( lwopt )
758 rwork( 1 ) = real( lrwopt )
763 CALL pxerbla( ictxt,
'PCHEEVX', -info )
765 ELSE IF( lquery )
THEN
771 IF( quickreturn )
THEN
777 work( 1 ) =
cmplx( lwopt )
778 rwork( 1 ) = real( lrwmin )
795 anrm = pclanhe(
'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 pclascl( 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 )
825 CALL pchentrd( uplo, n, a, ia, ja, desca, rwork( indd ),
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.0 )
839 CALL pslared1d( n, ia, ja, desca, rwork( indd ),
840 $ rwork( indd2 ), rwork( indrwork ), llrwork )
842 CALL pslared1d( n, ia, ja, desca, rwork( inde ),
843 $ rwork( inde2 ), rwork( indrwork ), llrwork )
848 CALL pcelget(
'A',
' ', work( indd2+i-1 ), a, i+ia-1,
850 rwork( indd2+i-1 ) = real( work( indd2+i-1 ) )
852 IF( lsame( uplo,
'U' ) )
THEN
854 CALL pcelget(
'A',
' ', work( inde2+i-1 ), a, i+ia-1,
856 rwork( inde2+i-1 ) = real( work( inde2+i-1 ) )
860 CALL pcelget(
'A',
' ', work( inde2+i-1 ), a, i+ia,
862 rwork( inde2+i-1 ) = real( work( inde2+i-1 ) )
875 CALL psstebz( ictxt, range, order, n, vll, vuu, il, iu, abstll,
876 $ rwork( indd2 ), rwork( inde2+offset ), m, nsplit, w,
877 $ iwork( indibl ), iwork( indisp ), rwork( indrwork ),
878 $ llrwork, iwork( 1 ), isizestebz, iinfo )
888 IF( iinfo.NE.0 )
THEN
889 info = info + ierrebz
891 iwork( indibl+i-1 ) = abs( iwork( indibl+i-1 ) )
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 slasrt(
'I', m, w, iinfo )
946 vuu = w( nz ) - ten*( eps*anrm+safmin )
947 IF( vll.GE.vuu )
THEN
950 CALL psstebz( 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 pcstein( 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 pcunmtr(
'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 sscal( m, one / sigma, w, 1 )
996 work( 1 ) =
cmplx( lwopt )
997 rwork( 1 ) = real( lrwopt )