1 SUBROUTINE pssyevx( 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 REAL ABSTOL, ORFAC, VL, VU
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
19 $ IFAIL( * ), IWORK( * )
20 REAL 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 REAL ZERO, ONE, TEN, FIVE
470 PARAMETER ( ZERO = 0.0e+0, one = 1.0e+0, ten = 10.0e+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 REAL 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 REAL PSLAMCH, PSLANSY
499 EXTERNAL lsame, iceil, indxg2p, numroc, pjlaenv,
506 $ sgebs2d, slasrt, sscal
509 INTRINSIC abs, dble, ichar, int,
max,
min, mod, real,
514 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
517 quickreturn = ( n.EQ.0 )
521 ictxt = desca( ctxt_ )
522 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
525 wantz = lsame( jobz,
'V' )
526 IF( nprow.EQ.-1 )
THEN
527 info = -( 800+ctxt_ )
528 ELSE IF( wantz )
THEN
529 IF( ictxt.NE.descz( ctxt_ ) )
THEN
530 info = -( 2100+ctxt_ )
534 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
536 $
CALL chk1mat( n, 4, n, 4, iz, jz, descz, 21, info )
542 safmin = pslamch( ictxt,
'Safe minimum' )
543 eps = pslamch( ictxt,
'Precision' )
544 smlnum = safmin / eps
545 bignum = one / smlnum
546 rmin = sqrt( smlnum )
547 rmax =
min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
550 lower = lsame( uplo,
'L' )
551 alleig = lsame( range,
'A' )
552 valeig = lsame( range,
'V' )
553 indeig = lsame( range,
'I' )
563 llwork = lwork - indwork + 1
567 isizestein = 3*n + nprocs + 1
568 isizestebz =
max( 4*n, 14, nprocs )
569 indibl = (
max( isizestein, isizestebz ) ) + 1
575 IF( lwork.EQ.-1 .OR. liwork.EQ.-1 )
578 nnp =
max( n, nprocs+1, 4 )
587 rsrc_a = desca( rsrc_ )
588 csrc_a = desca( csrc_ )
589 iroffa = mod( ia-1, mb_a )
590 icoffa = mod( ja-1, nb_a )
591 iarow = indxg2p( 1, nb_a, myrow, rsrc_a, nprow )
592 np0 = numroc( n+iroffa, nb, 0, 0, nprow )
593 mq0 = numroc( n+icoffa, nb, 0, 0, npcol )
595 rsrc_z = descz( rsrc_ )
596 iroffz = mod( iz-1, mb_a )
597 izrow = indxg2p( 1, nb_a, myrow, rsrc_z, nprow )
603 IF( ( .NOT.wantz ) .OR. ( valeig .AND. ( .NOT.lquery ) ) )
605 lwmin = 5*n +
max( 5*nn, nb*( np0+1 ) )
607 mq0 = numroc(
max( n, nb, 2 ), nb, 0, 0, npcol )
608 lwopt = 5*n +
max( 5*nn, np0*mq0+2*nb*nb )
614 IF( alleig .OR. valeig )
THEN
616 ELSE IF( indeig )
THEN
619 mq0 = numroc(
max( neig, nb, 2 ), nb, 0, 0, npcol )
620 lwmin = 5*n +
max( 5*nn, np0*mq0+2*nb*nb ) +
621 $ iceil( neig, nprow*npcol )*nn
629 anb = pjlaenv( ictxt, 3,
'PSSYTTRD',
'L', 0, 0, 0, 0 )
630 sqnpc = int( sqrt( dble( nprow*npcol ) ) )
631 nps =
max( numroc( n, 1, 0, 0, sqnpc ), 2*anb )
632 nsytrd_lwopt = 2*( anb+1 )*( 4*nps+2 ) + ( nps+4 )*nps
633 lwopt =
max( lwopt, 5*n+nsytrd_lwopt )
637 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
THEN
646 CALL sgebs2d( ictxt,
'ALL',
' ', 3, 1, work, 3 )
648 CALL sgebr2d( ictxt,
'ALL',
' ', 3, 1, work, 3, 0, 0 )
650 IF( .NOT.( wantz .OR. lsame( jobz,
'N' ) ) )
THEN
652 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) )
THEN
654 ELSE IF( .NOT.( lower .OR. lsame( uplo,
'U' ) ) )
THEN
656 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl )
THEN
658 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
661 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
664 ELSE IF( lwork.LT.lwmin .AND. lwork.NE.-1 )
THEN
666 ELSE IF( liwork.LT.liwmin .AND. liwork.NE.-1 )
THEN
668 ELSE IF( valeig .AND. ( abs( work( 2 )-vl ).GT.five*eps*
671 ELSE IF( valeig .AND. ( abs( work( 3 )-vu ).GT.five*eps*
674 ELSE IF( abs( work( 1 )-abstol ).GT.five*eps*abs( abstol ) )
677 ELSE IF( iroffa.NE.0 )
THEN
679 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
683 IF( iroffa.NE.iroffz )
THEN
685 ELSE IF( iarow.NE.izrow )
THEN
687 ELSE IF( desca( m_ ).NE.descz( m_ ) )
THEN
689 ELSE IF( desca( n_ ).NE.descz( n_ ) )
THEN
691 ELSE IF( desca( mb_ ).NE.descz( mb_ ) )
THEN
693 ELSE IF( desca( nb_ ).NE.descz( nb_ ) )
THEN
695 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) )
THEN
696 info = -( 2100+rsrc_ )
697 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) )
THEN
698 info = -( 2100+csrc_ )
699 ELSE IF( ictxt.NE.descz( ctxt_ ) )
THEN
700 info = -( 2100+ctxt_ )
705 idum1( 1 ) = ichar(
'V' )
707 idum1( 1 ) = ichar(
'N' )
711 idum1( 2 ) = ichar(
'L' )
713 idum1( 2 ) = ichar(
'U' )
717 idum1( 3 ) = ichar(
'A' )
718 ELSE IF( indeig )
THEN
719 idum1( 3 ) = ichar(
'I' )
721 idum1( 3 ) = ichar(
'V' )
731 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 8, n, 4, n, 4, iz,
732 $ jz, descz, 21, 4, idum1, idum2, info )
734 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 4, idum1,
737 work( 1 ) = real( lwopt )
742 CALL pxerbla( ictxt,
'PSSYEVX', -info )
744 ELSE IF( lquery )
THEN
750 IF( quickreturn )
THEN
756 work( 1 ) = real( lwopt )
773 anrm = pslansy(
'M', uplo, n, a, ia, ja, desca, work( indwork ) )
775 IF( anrm.GT.zero .AND. anrm.LT.rmin )
THEN
779 ELSE IF( anrm.GT.rmax )
THEN
785 IF( iscale.EQ.1 )
THEN
786 CALL pslascl( uplo, one, sigma, n, n, a, ia, ja, desca, iinfo )
788 $ abstll = abstol*sigma
792 IF( vuu.EQ.vll )
THEN
793 vuu = vuu + 2*
max( abs( vuu )*eps, safmin )
802 CALL pssyntrd( uplo, n, a, ia, ja, desca, work( indd ),
803 $ work( inde ), work( indtau ), work( indwork ),
814 IF( ia.EQ.1 .AND. ja.EQ.1 .AND. rsrc_a.EQ.0 .AND. csrc_a.EQ.0 )
816 CALL pslared1d( n, ia, ja, desca, work( indd ), work( indd2 ),
817 $ work( indwork ), llwork )
819 CALL pslared1d( n, ia, ja, desca, work( inde ), work( inde2 ),
820 $ work( indwork ), llwork )
825 CALL pselget(
'A',
' ', work( indd2+i-1 ), a, i+ia-1,
828 IF( lsame( uplo,
'U' ) )
THEN
830 CALL pselget(
'A',
' ', work( inde2+i-1 ), a, i+ia-1,
835 CALL pselget(
'A',
' ', work( inde2+i-1 ), a, i+ia,
849 CALL psstebz( ictxt, range, order, n, vll, vuu, il, iu, abstll,
850 $ work( indd2 ), work( inde2+offset ), m, nsplit, w,
851 $ iwork( indibl ), iwork( indisp ), work( indwork ),
852 $ llwork, iwork( 1 ), isizestebz, iinfo )
862 IF( iinfo.NE.0 )
THEN
863 info = info + ierrebz
865 iwork( indibl+i-1 ) = abs( iwork( indibl+i-1 ) )
882 CALL igamn2d( ictxt,
'A',
' ', 1, 1, lallwork, 1, 1, 1, -1,
885 maxeigs = descz( n_ )
887 DO 50 nz =
min( maxeigs, m ), 0, -1
888 mq0 = numroc( nz, nb, 0, 0, npcol )
889 sizestein = iceil( nz, nprocs )*n +
max( 5*n, np0*mq0 )
890 sizeormtr =
max( ( nb*( nb-1 ) ) / 2, ( mq0+np0 )*nb ) +
893 sizesyevx =
max( sizestein, sizeormtr )
894 IF( sizesyevx.LE.lallwork )
903 info = info + ierrspc
918 IF( nsplit.GT.1 )
THEN
919 CALL slasrt(
'I', m, w, iinfo )
923 vuu = w( nz ) - ten*( eps*anrm+safmin )
924 IF( vll.GE.vuu )
THEN
927 CALL psstebz( ictxt, range, order, n, vll, vuu, il,
928 $ iu, abstll, work( indd2 ),
929 $ work( inde2+offset ), nzz, nsplit, w,
930 $ iwork( indibl ), iwork( indisp ),
931 $ work( indwork ), llwork, iwork( 1 ),
932 $ isizestebz, iinfo )
935 IF( mod( info / ierrebz, 1 ).EQ.0 )
THEN
936 IF( nzz.GT.nz .OR. iinfo.NE.0 )
THEN
937 info = info + ierrebz
945 CALL psstein( n, work( indd2 ), work( inde2+offset ), nz, w,
946 $ iwork( indibl ), iwork( indisp ), orfac, z, iz,
947 $ jz, descz, work( indwork ), lallwork, iwork( 1 ),
948 $ isizestein, ifail, iclustr, gap, iinfo )
951 $ info = info + ierrcls
952 IF( mod( iinfo, nz+1 ).NE.0 )
953 $ info = info + ierrein
959 CALL psormtr(
'L', uplo,
'N', n, nz, a, ia, ja, desca,
960 $ work( indtau ), z, iz, jz, descz,
961 $ work( indwork ), llwork, iinfo )
968 IF( iscale.EQ.1 )
THEN
969 CALL sscal( m, one / sigma, w, 1 )
972 work( 1 ) = real( lwopt )