1 SUBROUTINE pdsyevx( 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, IWORK, LIWORK, IFAIL,
12 CHARACTER JOBZ, RANGE, UPLO
13 INTEGER IA, IL, INFO, IU, IZ, JA, JZ, LIWORK, LWORK, M,
15 DOUBLE PRECISION ABSTOL, ORFAC, VL, VU
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
19 $ IFAIL( * ), IWORK( * )
20 DOUBLE PRECISION A( * ), GAP( * ), W( * ), WORK( * ), Z( * )
464 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
465 $ MB_, NB_, RSRC_, CSRC_, LLD_
466 PARAMETER ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
467 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
468 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
469 DOUBLE PRECISION ZERO, ONE, TEN, FIVE
470 PARAMETER ( ZERO = 0.0d+0, one = 1.0d+0, ten = 10.0d+0,
472 INTEGER IERREIN, IERRCLS, IERRSPC, IERREBZ
473 parameter( ierrein = 1, ierrcls = 2, ierrspc = 4,
477 LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, QUICKRETURN,
480 INTEGER ANB, CSRC_A, I, IAROW, ICOFFA, ICTXT, IINFO,
481 $ INDD, INDD2, INDE, INDE2, INDIBL, INDISP,
482 $ indtau, indwork, iroffa, iroffz, iscale,
483 $ isizestebz, isizestein, izrow, lallwork,
484 $ liwmin, llwork, lwmin, lwopt, maxeigs, mb_a,
485 $ mq0, mycol, myrow, nb, nb_a, neig, nn, nnp,
486 $ np0, npcol, nprocs, nprow, nps, nsplit,
487 $ nsytrd_lwopt, nzz, offset, rsrc_a, rsrc_z,
488 $ sizeormtr, sizestein, sizesyevx, sqnpc
489 DOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,
490 $ SIGMA, SMLNUM, VLL, VUU
493 INTEGER IDUM1( 4 ), IDUM2( 4 )
497 INTEGER ICEIL, INDXG2P, NUMROC, PJLAENV
498 DOUBLE PRECISION PDLAMCH, PDLANSY
499 EXTERNAL lsame, iceil, indxg2p, numroc, pjlaenv,
503 EXTERNAL blacs_gridinfo,
chk1mat, dgebr2d, dgebs2d,
509 INTRINSIC abs, dble, ichar, int,
max,
min, mod, sqrt
513 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
516 quickreturn = ( n.EQ.0 )
520 ictxt = desca( ctxt_ )
521 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
524 wantz = lsame( jobz,
'V' )
525 IF( nprow.EQ.-1 )
THEN
526 info = -( 800+ctxt_ )
527 ELSE IF( wantz )
THEN
528 IF( ictxt.NE.descz( ctxt_ ) )
THEN
529 info = -( 2100+ctxt_ )
533 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
535 $
CALL chk1mat( n, 4, n, 4, iz, jz, descz, 21, info )
541 safmin = pdlamch( ictxt,
'Safe minimum' )
542 eps = pdlamch( ictxt,
'Precision' )
543 smlnum = safmin / eps
544 bignum = one / smlnum
545 rmin = sqrt( smlnum )
546 rmax =
min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
549 lower = lsame( uplo,
'L' )
550 alleig = lsame( range,
'A' )
551 valeig = lsame( range,
'V' )
552 indeig = lsame( range,
'I' )
562 llwork = lwork - indwork + 1
566 isizestein = 3*n + nprocs + 1
567 isizestebz =
max( 4*n, 14, nprocs )
568 indibl = (
max( isizestein, isizestebz ) ) + 1
574 IF( lwork.EQ.-1 .OR. liwork.EQ.-1 )
577 nnp =
max( n, nprocs+1, 4 )
586 rsrc_a = desca( rsrc_ )
587 csrc_a = desca( csrc_ )
588 iroffa = mod( ia-1, mb_a )
589 icoffa = mod( ja-1, nb_a )
590 iarow = indxg2p( 1, nb_a, myrow, rsrc_a, nprow )
591 np0 = numroc( n+iroffa, nb, 0, 0, nprow )
592 mq0 = numroc( n+icoffa, nb, 0, 0, npcol )
594 rsrc_z = descz( rsrc_ )
595 iroffz = mod( iz-1, mb_a )
596 izrow = indxg2p( 1, nb_a, myrow, rsrc_z, nprow )
602 IF( ( .NOT.wantz ) .OR. ( valeig .AND. ( .NOT.lquery ) ) )
604 lwmin = 5*n +
max( 5*nn, nb*( np0+1 ) )
606 mq0 = numroc(
max( n, nb, 2 ), nb, 0, 0, npcol )
607 lwopt = 5*n +
max( 5*nn, np0*mq0+2*nb*nb )
613 IF( alleig .OR. valeig )
THEN
615 ELSE IF( indeig )
THEN
618 mq0 = numroc(
max( neig, nb, 2 ), nb, 0, 0, npcol )
619 lwmin = 5*n +
max( 5*nn, np0*mq0+2*nb*nb ) +
620 $ iceil( neig, nprow*npcol )*nn
628 anb = pjlaenv( ictxt, 3,
'PDSYTTRD',
'L', 0, 0, 0, 0 )
629 sqnpc = int( sqrt( dble( nprow*npcol ) ) )
630 nps =
max( numroc( n, 1, 0, 0, sqnpc ), 2*anb )
631 nsytrd_lwopt = 2*( anb+1 )*( 4*nps+2 ) + ( nps+4 )*nps
632 lwopt =
max( lwopt, 5*n+nsytrd_lwopt )
636 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
THEN
645 CALL dgebs2d( ictxt,
'ALL',
' ', 3, 1, work, 3 )
647 CALL dgebr2d( ictxt,
'ALL',
' ', 3, 1, work, 3, 0, 0 )
649 IF( .NOT.( wantz .OR. lsame( jobz,
'N' ) ) )
THEN
651 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) )
THEN
653 ELSE IF( .NOT.( lower .OR. lsame( uplo,
'U' ) ) )
THEN
655 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl )
THEN
657 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
660 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
663 ELSE IF( lwork.LT.lwmin .AND. lwork.NE.-1 )
THEN
665 ELSE IF( liwork.LT.liwmin .AND. liwork.NE.-1 )
THEN
667 ELSE IF( valeig .AND. ( abs( work( 2 )-vl ).GT.five*eps*
670 ELSE IF( valeig .AND. ( abs( work( 3 )-vu ).GT.five*eps*
673 ELSE IF( abs( work( 1 )-abstol ).GT.five*eps*abs( abstol ) )
676 ELSE IF( iroffa.NE.0 )
THEN
678 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
682 IF( iroffa.NE.iroffz )
THEN
684 ELSE IF( iarow.NE.izrow )
THEN
686 ELSE IF( desca( m_ ).NE.descz( m_ ) )
THEN
688 ELSE IF( desca( n_ ).NE.descz( n_ ) )
THEN
690 ELSE IF( desca( mb_ ).NE.descz( mb_ ) )
THEN
692 ELSE IF( desca( nb_ ).NE.descz( nb_ ) )
THEN
694 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) )
THEN
695 info = -( 2100+rsrc_ )
696 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) )
THEN
697 info = -( 2100+csrc_ )
698 ELSE IF( ictxt.NE.descz( ctxt_ ) )
THEN
699 info = -( 2100+ctxt_ )
704 idum1( 1 ) = ichar(
'V' )
706 idum1( 1 ) = ichar(
'N' )
710 idum1( 2 ) = ichar(
'L' )
712 idum1( 2 ) = ichar(
'U' )
716 idum1( 3 ) = ichar(
'A' )
717 ELSE IF( indeig )
THEN
718 idum1( 3 ) = ichar(
'I' )
720 idum1( 3 ) = ichar(
'V' )
730 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 8, n, 4, n, 4, iz,
731 $ jz, descz, 21, 4, idum1, idum2, info )
733 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 4, idum1,
736 work( 1 ) = dble( lwopt )
741 CALL pxerbla( ictxt,
'PDSYEVX', -info )
743 ELSE IF( lquery )
THEN
749 IF( quickreturn )
THEN
755 work( 1 ) = dble( lwopt )
772 anrm = pdlansy(
'M', uplo, n, a, ia, ja, desca, work( indwork ) )
774 IF( anrm.GT.zero .AND. anrm.LT.rmin )
THEN
778 ELSE IF( anrm.GT.rmax )
THEN
784 IF( iscale.EQ.1 )
THEN
785 CALL pdlascl( uplo, one, sigma, n, n, a, ia, ja, desca, iinfo )
787 $ abstll = abstol*sigma
791 IF( vuu.EQ.vll )
THEN
792 vuu = vuu + 2*
max( abs( vuu )*eps, safmin )
801 CALL pdsyntrd( uplo, n, a, ia, ja, desca, work( indd ),
802 $ work( inde ), work( indtau ), work( indwork ),
813 IF( ia.EQ.1 .AND. ja.EQ.1 .AND. rsrc_a.EQ.0 .AND. csrc_a.EQ.0 )
815 CALL pdlared1d( n, ia, ja, desca, work( indd ), work( indd2 ),
816 $ work( indwork ), llwork )
818 CALL pdlared1d( n, ia, ja, desca, work( inde ), work( inde2 ),
819 $ work( indwork ), llwork )
824 CALL pdelget(
'A',
' ', work( indd2+i-1 ), a, i+ia-1,
827 IF( lsame( uplo,
'U' ) )
THEN
829 CALL pdelget(
'A',
' ', work( inde2+i-1 ), a, i+ia-1,
834 CALL pdelget(
'A',
' ', work( inde2+i-1 ), a, i+ia,
848 CALL pdstebz( ictxt, range, order, n, vll, vuu, il, iu, abstll,
849 $ work( indd2 ), work( inde2+offset ), m, nsplit, w,
850 $ iwork( indibl ), iwork( indisp ), work( indwork ),
851 $ llwork, iwork( 1 ), isizestebz, iinfo )
861 IF( iinfo.NE.0 )
THEN
862 info = info + ierrebz
864 iwork( indibl+i-1 ) = abs( iwork( indibl+i-1 ) )
881 CALL igamn2d( ictxt,
'A',
' ', 1, 1, lallwork, 1, 1, 1, -1,
884 maxeigs = descz( n_ )
886 DO 50 nz =
min( maxeigs, m ), 0, -1
887 mq0 = numroc( nz, nb, 0, 0, npcol )
888 sizestein = iceil( nz, nprocs )*n +
max( 5*n, np0*mq0 )
889 sizeormtr =
max( ( nb*( nb-1 ) ) / 2, ( mq0+np0 )*nb ) +
892 sizesyevx =
max( sizestein, sizeormtr )
893 IF( sizesyevx.LE.lallwork )
902 info = info + ierrspc
917 IF( nsplit.GT.1 )
THEN
918 CALL dlasrt(
'I', m, w, iinfo )
922 vuu = w( nz ) - ten*( eps*anrm+safmin )
923 IF( vll.GE.vuu )
THEN
926 CALL pdstebz( ictxt, range, order, n, vll, vuu, il,
927 $ iu, abstll, work( indd2 ),
928 $ work( inde2+offset ), nzz, nsplit, w,
929 $ iwork( indibl ), iwork( indisp ),
930 $ work( indwork ), llwork, iwork( 1 ),
931 $ isizestebz, iinfo )
934 IF( mod( info / ierrebz, 1 ).EQ.0 )
THEN
935 IF( nzz.GT.nz .OR. iinfo.NE.0 )
THEN
936 info = info + ierrebz
944 CALL pdstein( n, work( indd2 ), work( inde2+offset ), nz, w,
945 $ iwork( indibl ), iwork( indisp ), orfac, z, iz,
946 $ jz, descz, work( indwork ), lallwork, iwork( 1 ),
947 $ isizestein, ifail, iclustr, gap, iinfo )
950 $ info = info + ierrcls
951 IF( mod( iinfo, nz+1 ).NE.0 )
952 $ info = info + ierrein
958 CALL pdormtr(
'L', uplo,
'N', n, nz, a, ia, ja, desca,
959 $ work( indtau ), z, iz, jz, descz,
960 $ work( indwork ), llwork, iinfo )
967 IF( iscale.EQ.1 )
THEN
968 CALL dscal( m, one / sigma, w, 1 )
971 work( 1 ) = dble( lwopt )