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, LIWORK, LRWORK,
15 REAL ABSTOL, ORFAC, VL, VU
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
19 $ IFAIL( * ), IWORK( * )
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, ten = 10.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,
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,
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,
513 $ sgebs2d, slasrt, sscal
516 INTRINSIC abs,
cmplx, dble, 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_ )
529 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
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 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
THEN
664 CALL sgebs2d( ictxt,
'ALL',
' ', 3, 1, rwork, 3 )
666 CALL sgebr2d( 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 ) =
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 )