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
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
19 $ IFAIL( * ), IWORK( * )
20 DOUBLE PRECISION A( * ), GAP( * ), W( * ), WORK(
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, , 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,
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 )
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.EQ..AND..EQ.
IF( MYROW0 MYCOL0 ) THEN
645 CALL DGEBS2D( ICTXT, 'all
', ' ', 3, 1, WORK, 3 )
647 CALL DGEBR2D( ICTXT, 'all
', ' ', 3, 1, WORK, 3, 0, 0 )
649.NOT..OR.
IF( ( WANTZ LSAME( JOBZ, 'n
' ) ) ) THEN
651.NOT..OR..OR.
ELSE IF( ( ALLEIG VALEIG INDEIG ) ) THEN
653.NOT..OR.
ELSE IF( ( LOWER LSAME( UPLO, 'u
' ) ) ) THEN
655.AND..GT..AND..LE.
ELSE IF( VALEIG N0 VUVL ) THEN
657.AND..LT..OR..GT.
ELSE IF( INDEIG ( IL1 ILMAX( 1, N ) ) )
660.AND..LT..OR..GT.
ELSE IF( INDEIG ( IUMIN( N, IL ) IUN ) )
663.LT..AND..NE.
ELSE IF( LWORKLWMIN LWORK-1 ) THEN
665.LT..AND..NE.
ELSE IF( LIWORKLIWMIN LIWORK-1 ) THEN
667.AND..GT.
ELSE IF( VALEIG ( ABS( WORK( 2 )-VL )FIVE*EPS*
670.AND..GT.
ELSE IF( VALEIG ( ABS( WORK( 3 )-VU )FIVE*EPS*
673.GT.
ELSE IF( ABS( WORK( 1 )-ABSTOL )FIVE*EPS*ABS( ABSTOL ) )
676.NE.
ELSE IF( IROFFA0 ) THEN
678.NE.
ELSE IF( DESCA( MB_ )DESCA( NB_ ) ) THEN
682.NE.
IF( IROFFAIROFFZ ) THEN
684.NE.
ELSE IF( IAROWIZROW ) THEN
686.NE.
ELSE IF( DESCA( M_ )DESCZ( M_ ) ) THEN
688.NE.
ELSE IF( DESCA( N_ )DESCZ( N_ ) ) THEN
690.NE.
ELSE IF( DESCA( MB_ )DESCZ( MB_ ) ) THEN
692.NE.
ELSE IF( DESCA( NB_ )DESCZ( NB_ ) ) THEN
694.NE.
ELSE IF( DESCA( RSRC_ )DESCZ( RSRC_ ) ) THEN
695 INFO = -( 2100+RSRC_ )
696.NE.
ELSE IF( DESCA( CSRC_ )DESCZ( CSRC_ ) ) THEN
697 INFO = -( 2100+CSRC_ )
698.NE.
ELSE IF( ICTXTDESCZ( 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 )
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 )