1 SUBROUTINE pcheevr( JOBZ, RANGE, UPLO, N, A, IA, JA,
2 $ DESCA, VL, VU, IL, IU, M, NZ, W, Z, IZ,
4 $ WORK, LWORK, RWORK, LRWORK, IWORK, LIWORK,
14 CHARACTER JOBZ, RANGE, UPLO
16 INTEGER IA, IL, INFO, IU, IZ, JA, JZ, LIWORK, LRWORK,
21 INTEGER DESCA( * ), DESCZ( * ), IWORK( * )
22 REAL W( * ), RWORK( * )
23 COMPLEX A( * ), WORK( * ), Z( * )
321 INTEGER CTXT_, M_, N_,
322 $ MB_, NB_, RSRC_, CSRC_
323 PARAMETER ( CTXT_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
324 $ rsrc_ = 7, csrc_ = 8 )
326 PARAMETER ( ZERO = 0.0e0 )
329 LOGICAL ALLEIG, COLBRT, DOBCST, FINISH, FIRST, INDEIG,
330 $ lower, lquery, valeig, vstart, wantz
331 INTEGER ANB, DOL, DOU, DSTCOL, DSTROW, EIGCNT, FRSTCL,
332 $ I, IAROW, ICTXT, IIL, IINDERR, IINDWLC, IINFO,
333 $ iiu, im, indd, indd2, inde, inde2, inderr,
334 $ indilu, indrtau, indrw, indrwork, indtau,
335 $ indwlc, indwork, ipil, ipiu, iproc, izrow,
336 $ lastcl, lengthi, lengthi2, liwmin, llrwork,
337 $ llwork, lrwmin, lrwopt, lwmin, lwopt, maxcls,
338 $ mq00, mycol, myil, myiu, myproc, myrow, mz, nb,
339 $ ndepth, needil, neediu, nhetrd_lwopt, nnp,
340 $ np00, npcol, nprocs, nprow, nps, nsplit,
341 $ offset, parity, rlengthi, rlengthi2, rstarti,
342 $ size1, size2, sqnpc, srccol, srcrow, starti,
345 REAL PIVMIN, SAFMIN, SCALE, VLL, VUU, WL,
349 INTEGER IDUM1( 4 ), IDUM2( 4 )
353 INTEGER ICEIL, INDXG2P, NUMROC, PJLAENV
355 EXTERNAL ICEIL, INDXG2P, LSAME, NUMROC, PJLAENV,
359 EXTERNAL blacs_gridinfo,
chk1mat, igebr2d, igebs2d,
363 $ sgerv2d, sgesd2d, slarrc,
slasrt2,
367 INTRINSIC abs,
cmplx, ichar, int,
max,
min, mod, real,
380 wantz = lsame( jobz,
'V' )
381 lower = lsame( uplo,
'L' )
382 alleig = lsame( range,
'A' )
383 valeig = lsame( range,
'V' )
384 indeig = lsame( range,
'I' )
385 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 .OR. liwork.EQ.-1 )
392 ictxt = desca( ctxt_ )
393 safmin = pslamch( ictxt,
'Safe minimum' )
402 llwork = lwork - indwork + 1
415 llrwork = lrwork - indrwork + 1
422 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
425 nprocs = nprow * npcol
426 myproc = myrow * npcol + mycol
427 IF( nprow.EQ.-1 )
THEN
428 info = -( 800+ctxt_ )
429 ELSE IF( wantz )
THEN
430 IF( ictxt.NE.descz( ctxt_ ) )
THEN
431 info = -( 2100+ctxt_ )
442 ELSE IF ( indeig )
THEN
450 np00 = numroc( n, nb, 0, 0, nprow )
451 mq00 = numroc( mz, nb, 0, 0, npcol )
453 indrw = indrwork +
max(18*n, np00*mq00 + 2*nb*nb)
454 lrwmin = indrw - 1 + (iceil(mz, nprocs) + 2)*n
455 lwmin = n +
max((np00 + mq00 + nb) * nb, 3 * nb)
457 indrw = indrwork + 12*n
459 lwmin = n +
max( nb*( np00 + 1 ), 3 * nb )
463 lrwmin =
max(3, lrwmin)
465 lwmin =
max(3, lwmin)
468 anb = pjlaenv( ictxt, 3,
'PCHETTRD',
'L', 0, 0, 0, 0 )
469 sqnpc = int( sqrt( real( nprocs ) ) )
470 nps =
max( numroc( n, 1, 0, 0, sqnpc ), 2*anb )
471 nhetrd_lwopt = 2*( anb+1 )*( 4*nps+2 ) + ( nps+4 )*nps
472 lwopt =
max( lwopt, n+nhetrd_lwopt )
474 size1 = indrw - indrwork
481 nnp =
max( n, nprocs+1, 4 )
483 liwmin = 12*nnp + 2*n
485 liwmin = 10*nnp + 2*n
494 indilu = liwmin - 2*nprocs + 1
504 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
506 $
CALL chk1mat( n, 4, n, 4, iz, jz, descz, 21, info )
509 IF( .NOT.( wantz .OR. lsame( jobz,
'N' ) ) )
THEN
511 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) )
THEN
513 ELSE IF( .NOT.( lower .OR. lsame( uplo,
'U' ) ) )
THEN
515 ELSE IF( mod( ia-1, desca( mb_ ) ).NE.0 )
THEN
517 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl )
THEN
519 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
522 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ))
525 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery )
THEN
527 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery )
THEN
529 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery )
THEN
531 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
535 iarow = indxg2p( 1, desca( nb_ ), myrow,
536 $ desca( rsrc_ ), nprow )
537 izrow = indxg2p( 1, desca( nb_ ), myrow,
538 $ descz( rsrc_ ), nprow )
539 IF( iarow.NE.izrow )
THEN
541 ELSE IF( mod( ia-1, desca( mb_ ) ).NE.
542 $ mod( iz-1, descz( mb_ ) ) )
THEN
544 ELSE IF( desca( m_ ).NE.descz( m_ ) )
THEN
546 ELSE IF( desca( n_ ).NE.descz( n_ ) )
THEN
548 ELSE IF( desca( mb_ ).NE.descz( mb_ ) )
THEN
550 ELSE IF( desca( nb_ ).NE.descz( nb_ ) )
THEN
552 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) )
THEN
553 info = -( 2100+rsrc_ )
554 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) )
THEN
555 info = -( 2100+csrc_ )
556 ELSE IF( ictxt.NE.descz( ctxt_ ) )
THEN
557 info = -( 2100+ctxt_ )
563 idum1( 2 ) = ichar(
'L' )
565 idum1( 2 ) = ichar(
'U' )
569 idum1( 3 ) = ichar(
'A' )
570 ELSE IF( indeig )
THEN
571 idum1( 3 ) = ichar(
'I' )
573 idum1( 3 ) = ichar(
'V' )
583 idum1( 1 ) = ichar(
'V' )
584 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 8, n, 4, n, 4,iz,
585 $ jz, descz, 21, 4, idum1, idum2, info )
587 idum1( 1 ) = ichar(
'N' )
588 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 4, idum1,
591 work( 1 ) =
cmplx( lwopt )
592 rwork( 1 ) = real( lrwopt )
597 CALL pxerbla( ictxt,
'PCHEEVR', -info )
599 ELSE IF( lquery )
THEN
613 work( 1 ) =
cmplx( lwopt )
614 rwork( 1 ) = real( lrwopt )
637 CALL pchentrd( uplo, n, a, ia, ja, desca, rwork( indd ),
638 $ rwork( inde ), work( indtau ), work( indwork ),
639 $ llwork, rwork( indrwork ), llrwork,iinfo )
642 IF (iinfo .NE. 0)
THEN
643 CALL pxerbla( ictxt,
'PCHENTRD', -iinfo )
653 IF( ia.EQ.1 .AND. ja.EQ.1 .AND.
654 $ desca( rsrc_ ).EQ.0 .AND. desca( csrc_ ).EQ.0 )
656 CALL pslared1d( n, ia, ja, desca, rwork( indd ),
657 $ rwork( indd2 ), rwork( indrwork ), llrwork )
659 CALL pslared1d( n, ia, ja, desca, rwork( inde ),
660 $ rwork( inde2 ), rwork( indrwork ), llrwork )
665 CALL pcelget(
'A',
' ', work( indwork ), a,
666 $ i+ia-1, i+ja-1, desca )
667 rwork( indd2+i-1 ) = real( work( indwork ) )
669 IF( lsame( uplo,
'U' ) )
THEN
671 CALL pcelget(
'A',
' ', work( indwork ), a,
672 $ i+ia-1, i+ja, desca )
673 rwork( inde2+i-1 ) = real( work( indwork ) )
677 CALL pcelget(
'A',
' ', work( indwork ), a,
678 $ i+ia, i+ja-1, desca )
679 rwork( inde2+i-1 ) = real( work( indwork ) )
695 ELSE IF ( indeig )
THEN
698 ELSE IF ( valeig )
THEN
699 CALL slarrc(
'T', n, vll, vuu, rwork( indd2 ),
700 $ rwork( inde2 + offset ), safmin, eigcnt, iil, iiu, info)
711 work( 1 ) = real( lwopt )
730 CALL pmpim2( iil, iiu, nprocs,
731 $ iwork(indilu), iwork(indilu+nprocs) )
735 myil = iwork(indilu+myproc)
736 myiu = iwork(indilu+nprocs+myproc)
739 zoffset =
max(0, myil - iil - 1)
740 first = ( myil .EQ. iil )
753 IF ( myil.GT.0 )
THEN
755 dou = myiu - myil + 1
756 CALL sstegr2( jobz,
'I', n, rwork( indd2 ),
757 $ rwork( inde2+offset ), vll, vuu, myil, myiu,
758 $ im, w( 1 ), rwork( indrw ), n,
760 $ iwork( 1 ), rwork( indrwork ), size1,
761 $ iwork( 2*n+1 ), size2,
762 $ dol, dou, zoffset, iinfo )
767 w( myil-iil+i ) = w( i )
772 IF (iinfo .NE. 0)
THEN
773 CALL pxerbla( ictxt,
'SSTEGR2', -iinfo )
776 ELSEIF ( wantz .AND. nprocs.EQ.1 )
THEN
781 IF ( myil.GT.0 )
THEN
784 CALL sstegr2( jobz,
'I', n, rwork( indd2 ),
785 $ rwork( inde2+offset ), vll, vuu, iil, iiu,
786 $ im, w( 1 ), rwork( indrw ), n,
788 $ iwork( 1 ), rwork( indrwork ), size1,
789 $ iwork( 2*n+1 ), size2, dol, dou,
792 IF (iinfo .NE. 0)
THEN
793 CALL pxerbla( ictxt,
'SSTEGR2', -iinfo )
796 ELSEIF ( wantz )
THEN
802 IF ( myil.GT.0 )
THEN
805 CALL sstegr2a( jobz,
'I', n, rwork( indd2 ),
806 $ rwork( inde2+offset ), vll, vuu, iil, iiu,
807 $ im, w( 1 ), rwork( indrw ), n,
808 $ n, rwork( indrwork ), size1,
809 $ iwork( 2*n+1 ), size2, dol,
810 $ dou, needil, neediu,
811 $ inderr, nsplit, pivmin, scale, wl, wu,
814 IF (iinfo .NE. 0)
THEN
815 CALL pxerbla( ictxt,
'SSTEGR2A', -iinfo )
827 iinderr = indrwork + inderr - 1
847 IF (myproc .EQ. (i - 1))
THEN
853 lengthi = myiu - myil + 1
858 CALL igesd2d( ictxt, 2, 1, iwork, 2,
860 IF (( starti.GE.1 ) .AND. ( lengthi.GE.1 ))
THEN
863 CALL scopy(lengthi,w( starti ),1,
866 CALL scopy(lengthi,rwork(iinderr+starti-1),1,
867 $ rwork( indd+lengthi ), 1)
869 CALL sgesd2d( ictxt, lengthi2,
870 $ 1, rwork( indd ), lengthi2,
873 ELSE IF (myproc .EQ. 0)
THEN
874 srcrow = (i-1) / npcol
875 srccol = mod(i-1, npcol)
876 CALL igerv2d( ictxt, 2, 1, iwork, 2,
880 IF (( starti.GE.1 ) .AND. ( lengthi.GE.1 ))
THEN
883 CALL sgerv2d( ictxt, lengthi2, 1,
884 $ rwork(indd), lengthi2, srcrow, srccol )
886 CALL scopy( lengthi, rwork(indd), 1,
889 CALL scopy(lengthi,rwork(indd+lengthi),1,
890 $ rwork( iinderr+starti-1 ), 1)
894 lengthi = iiu - iil + 1
895 lengthi2 = lengthi * 2
896 IF (myproc .EQ. 0)
THEN
898 CALL scopy(lengthi,w ,1, rwork( indd ), 1)
899 CALL scopy(lengthi,rwork( iinderr ),1,
900 $ rwork( indd+lengthi ), 1)
901 CALL sgebs2d( ictxt,
'A',
' ', lengthi2, 1,
902 $ rwork(indd), lengthi2 )
906 CALL sgebr2d( ictxt,
'A',
' ', lengthi2, 1,
907 $ rwork(indd), lengthi2, srcrow, srccol )
908 CALL scopy( lengthi, rwork(indd), 1, w, 1)
909 CALL scopy(lengthi,rwork(indd+lengthi),1,
910 $ rwork( iinderr ), 1)
916 IF( (nprocs.GT.1).AND.(myil.GT.0) )
THEN
917 CALL pmpcol( myproc, nprocs, iil, needil, neediu,
918 $ iwork(indilu), iwork(indilu+nprocs),
919 $ colbrt, frstcl, lastcl )
927 DO 47 iproc = frstcl, lastcl
928 IF (myproc .EQ. iproc)
THEN
931 lengthi = myiu - myil + 1
934 IF ((starti.GE.1) .AND. (lengthi.GE.1))
THEN
936 CALL scopy(lengthi,w( starti ),1,
940 $ rwork( iinderr+starti-1 ),1,
941 $ rwork(indd+lengthi), 1)
944 DO 46 i = frstcl, lastcl
945 IF(i.EQ.myproc)
GOTO 46
947 dstcol = mod(i, npcol)
948 CALL igesd2d( ictxt, 2, 1, iwork, 2,
950 IF ((starti.GE.1) .AND. (lengthi.GE.1))
THEN
953 CALL sgesd2d( ictxt, lengthi2,
954 $ 1, rwork(indd), lengthi2,
959 srcrow = iproc / npcol
960 srccol = mod(iproc, npcol)
961 CALL igerv2d( ictxt, 2, 1, iwork, 2,
965 IF ((rstarti.GE.1 ) .AND. (rlengthi.GE.1 ))
THEN
966 rlengthi2 = 2*rlengthi
967 CALL sgerv2d( ictxt, rlengthi2, 1,
968 $ rwork(inde), rlengthi2,
971 CALL scopy( rlengthi,rwork(inde), 1,
974 CALL scopy(rlengthi,rwork(inde+rlengthi),1,
975 $ rwork( iinderr+rstarti-1 ), 1)
989 IF ( myil.GT.0 )
THEN
990 CALL sstegr2b( jobz, n, rwork( indd2 ),
991 $ rwork( inde2+offset ),
992 $ im, w( 1 ), rwork( indrw ), n, n,
993 $ iwork( 1 ), rwork( indrwork ), size1,
994 $ iwork( 2*n+1 ), size2, dol,
995 $ dou, needil, neediu, indwlc,
996 $ pivmin, scale, wl, wu,
998 $ maxcls, ndepth, parity, zoffset, iinfo )
999 iindwlc = indrwork + indwlc - 1
1000 IF(.NOT.finish)
THEN
1001 IF((needil.LT.dol).OR.(neediu.GT.dou))
THEN
1002 CALL pmpcol( myproc, nprocs, iil, needil, neediu,
1003 $ iwork(indilu), iwork(indilu+nprocs),
1004 $ colbrt, frstcl, lastcl )
1015 DO 147 iproc = frstcl, lastcl
1016 IF (myproc .EQ. iproc)
THEN
1020 lengthi = myiu - myil + 1
1025 IF ((starti.GE.1).AND.(lengthi.GE.1))
THEN
1028 $ rwork( iindwlc+starti-1 ),1,
1032 $ rwork( iinderr+starti-1 ),1,
1033 $ rwork(indd+lengthi), 1)
1036 DO 146 i = frstcl, lastcl
1037 IF(i.EQ.myproc)
GOTO 146
1039 dstcol = mod(i, npcol)
1040 CALL igesd2d( ictxt, 2, 1, iwork, 2,
1042 IF ((starti.GE.1).AND.(lengthi.GE.1))
THEN
1043 lengthi2 = 2*lengthi
1045 CALL sgesd2d( ictxt, lengthi2,
1046 $ 1, rwork(indd), lengthi2,
1051 srcrow = iproc / npcol
1052 srccol = mod(iproc, npcol)
1053 CALL igerv2d( ictxt, 2, 1, iwork, 2,
1057 IF ((rstarti.GE.1).AND.(rlengthi.GE.1))
THEN
1058 rlengthi2 = 2*rlengthi
1059 CALL sgerv2d( ictxt,rlengthi2, 1,
1060 $ rwork(inde),rlengthi2,
1063 CALL scopy(rlengthi,rwork(inde), 1,
1064 $ rwork( iindwlc+rstarti-1 ), 1)
1066 CALL scopy(rlengthi,rwork(inde+rlengthi),
1067 $ 1,rwork( iinderr+rstarti-1 ), 1)
1075 IF (iinfo .NE. 0)
THEN
1076 CALL pxerbla( ictxt,
'SSTEGR2B', -iinfo )
1098 IF (myproc .EQ. (i - 1))
THEN
1101 starti = myil - iil + 1
1104 lengthi = myiu - myil + 1
1109 CALL igesd2d( ictxt, 2, 1, iwork, 2,
1111 IF ((starti.GE.1).AND.(lengthi.GE.1))
THEN
1112 CALL sgesd2d( ictxt, lengthi,
1113 $ 1, w( starti ), lengthi,
1116 ELSE IF (myproc .EQ. 0)
THEN
1117 srcrow = (i-1) / npcol
1118 srccol = mod(i-1, npcol)
1119 CALL igerv2d( ictxt, 2, 1, iwork, 2,
1123 IF ((starti.GE.1).AND.(lengthi.GE.1))
THEN
1124 CALL sgerv2d( ictxt, lengthi, 1,
1125 $ w( starti ), lengthi, srcrow, srccol )
1132 CALL igsum2d( ictxt,
'A',
' ', 1, 1, m, 1, -1, -1 )
1135 IF (myproc .EQ. 0)
THEN
1137 CALL sgebs2d( ictxt,
'A',
' ', m, 1, w, m )
1141 CALL sgebr2d( ictxt,
'A',
' ', m, 1,
1142 $ w, m, srcrow, srccol )
1149 iwork( nprocs+1+i ) = i
1151 CALL slasrt2(
'I', m, w, iwork( nprocs+2 ), iinfo )
1152 IF (iinfo.NE.0)
THEN
1153 CALL pxerbla( ictxt,
'SLASRT2', -iinfo )
1164 iwork( m+nprocs+1+iwork( nprocs+1+i ) ) = i
1168 DO 180 i = 1, nprocs
1171 ipil = iwork(indilu+i-1)
1172 ipiu = iwork(indilu+nprocs+i-1)
1173 IF (ipil .EQ. 0)
THEN
1174 iwork( i + 1 ) = iwork( i )
1176 iwork( i + 1 ) = iwork( i ) + ipiu - ipil + 1
1181 CALL pclaevswp(n, rwork( indrw ), n, z, iz, jz,
1182 $ descz, iwork( 1 ), iwork( nprocs+m+2 ), rwork( indrwork ),
1185 CALL pclaevswp(n, rwork( indrw + n ), n, z, iz, jz,
1186 $ descz, iwork( 1 ), iwork( nprocs+m+2 ), rwork( indrwork ),
1199 CALL pcunmtr(
'L', uplo,
'N', n, nz, a, ia, ja, desca,
1200 $ work( indtau ), z, iz, jz, descz,
1201 $ work( indwork ), llwork, iinfo )
1203 IF (iinfo.NE.0)
THEN
1204 CALL pxerbla( ictxt,
'PCUNMTR', -iinfo )
1211 work( 1 ) =
cmplx( lwopt )
1212 rwork( 1 ) = real( lrwopt )