1      SUBROUTINE pdseprsubtst( WKNOWN, JOBZ, RANGE, UPLO, N, VL, VU, IL,
 
    2     $                         IU, THRESH, ABSTOL, A, COPYA, Z, IA, JA,
 
    3     $                         DESCA, WIN, WNEW, IFAIL, ICLUSTR, GAP,
 
    4     $                         IPREPAD, IPOSTPAD, WORK, LWORK, LWORK1,
 
    5     $                         IWORK, LIWORK, RESULT, TSTNRM, QTQNRM,
 
   17      CHARACTER          JOBZ, RANGE, UPLO
 
   18      INTEGER            IA, IL, IPOSTPAD, IPREPAD, IU, JA, LIWORK,
 
   19     $                   LWORK, LWORK1, N, NOUT, RESULT
 
   20      DOUBLE PRECISION   ABSTOL, QTQNRM, THRESH, TSTNRM, VL, VU
 
   23      INTEGER            DESCA( * ), ICLUSTR( * ), IFAIL( * ),
 
   25      DOUBLE PRECISION   A( * ), COPYA( * ), GAP( * ), WIN( * ),
 
   26     $                   WNEW( * ), WORK( * ), Z( * )
 
  187      INTEGER            DLEN_, CTXT_, M_, N_,
 
  188     $                   MB_, NB_, RSRC_, CSRC_, LLD_
 
  189      PARAMETER          ( DLEN_ = 9, 
 
  190     $                   ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
 
  191     $                   rsrc_ = 7, csrc_ = 8, lld_ = 9 )
 
  192      DOUBLE PRECISION   PADVAL, FIVE, NEGONE
 
  193      PARAMETER          ( PADVAL = 13.5285d0, five = 5.0d0,
 
  196      PARAMETER          ( IPADVAL = 927 )
 
  199      LOGICAL            MISSLARGEST, MISSSMALLEST
 
  200      INTEGER            I, IAM, INDIWRK, INFO, ISIZESUBTST, ISIZEEVR,
 
  201     $                   isizetst, j, m, maxeigs, maxil, maxiu, maxsize,
 
  202     $                   minil, mq, mycol, myil, myrow, nclusters, np,
 
  203     $                   npcol, nprow, nq, nz, oldil, oldiu, oldnz, res,
 
  204     $                   sizechk, sizemqrleft, sizemqrright, sizeqrf,
 
  205     $                   sizeqtq, sizesubtst, sizeevr, sizetms,
 
  206     $                   sizetst, valsize, vecsize
 
  207      DOUBLE PRECISION   EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
 
  208     $                   MINERROR, MINVL, NORMWIN, OLDVL, OLDVU, 
 
  212      INTEGER            DESCZ( DLEN_ ), ISEED( 4 ), ITMP( 2 )
 
  218      DOUBLE PRECISION   PDLAMCH, PDLANSY
 
  219      EXTERNAL           LSAME, NUMROC, PDLAMCH, PDLANSY
 
  222      EXTERNAL           blacs_gridinfo, 
descinit, dgamn2d, dgamx2d,
 
  229      INTRINSIC          abs, 
max, 
min, mod
 
  233      CALL pdlasizesepr( desca, iprepad, ipostpad, sizemqrleft,
 
  234     $                   sizemqrright, sizeqrf, sizetms, sizeqtq,
 
  235     $                   sizechk, sizeevr, isizeevr, sizesubtst,
 
  236     $                   isizesubtst, sizetst, isizetst )
 
  240      eps = pdlamch( desca( ctxt_ ), 
'Eps' )
 
  241      safmin = pdlamch( desca( ctxt_ ), 
'Safe min' )
 
  243      normwin = safmin / eps
 
  245     $   normwin = 
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
 
  256      DO 10 i = 1, lwork1, 1
 
  257         work( i+iprepad ) = 14.3d0
 
  260      DO 20 i = 1, liwork, 1
 
  261         iwork( i+iprepad ) = 14
 
  265         wnew( i+iprepad ) = 3.14159d0
 
  268      iclustr( 1+iprepad ) = 139
 
  270      IF (lsame( range, 
'V' ) ) 
THEN 
  274      IF( lsame( jobz, 
'N' ) ) 
THEN 
  277         IF( lsame( range, 
'A' ) ) 
THEN 
  279         ELSE IF( lsame( range, 
'I' ) ) 
THEN 
  280            maxeigs = iu - il + 1
 
  282            minvl = vl - normwin*five*eps - abstol
 
  283            maxvu = vu + normwin*five*eps + abstol
 
  289               IF( win( i ).LT.minvl )
 
  291               IF( win( i ).LE.maxvu )
 
  295            maxeigs = maxiu - minil + 1
 
  300      CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
 
  301     $               desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
 
  302     $               desca( ctxt_ ), desca( lld_ ), info )
 
  304      CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
 
  305      indiwrk = 1 + iprepad + nprow*npcol + 1
 
  308      IF( myrow.EQ.0 .AND. mycol.EQ.0 )
 
  314      IF( myrow.GE.nprow .OR. myrow.LT.0 )
 
  321     $                    iseed, win, maxsize, vecsize, valsize )
 
  323      np = numroc( n, desca( mb_ ), myrow, 0, nprow )
 
  324      nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
 
  325      mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
 
  327      CALL dlacpy( 
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
 
  330      CALL pdfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
 
  333      CALL pdfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
 
  334     $                ipostpad, padval+1.0d0 )
 
  342      CALL pdfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
 
  345      CALL pdfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
 
  346     $                iprepad, ipostpad, padval+3.0d0 )
 
  348      CALL pdfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
 
  349     $                ipostpad, padval+4.0d0 )
 
  351      CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
 
  352     $                ipostpad, ipadval )
 
  354      CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
 
  357      CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
 
  358     $                2*nprow*npcol, iprepad, ipostpad, ipadval )
 
  364         DO 50 j = 1, maxeigs, 1
 
  365            CALL pdelset( z( 1+iprepad ), i, j, desca, 13.0d0 )
 
  379      CALL pdsyevr( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
 
  380     $              vl, vu, il, iu, m, nz, wnew( 1+iprepad ),
 
  381     $              z( 1+iprepad ), ia, ja, desca,
 
  382     $              work( 1+iprepad ), lwork1, iwork( 1+iprepad ),
 
  396      iclustr( 1+iprepad ) = 0
 
  398      IF( thresh.LE.0 ) 
THEN     
  401         CALL pdchekpad( desca( ctxt_ ), 
'PDSYEVR-A', np, nq, a,
 
  402     $                   desca( lld_ ), iprepad, ipostpad, padval )
 
  404         CALL pdchekpad( descz( ctxt_ ), 
'PDSYEVR-Z', np, mq, z,
 
  405     $                   descz( lld_ ), iprepad, ipostpad,
 
  408         CALL pdchekpad( desca( ctxt_ ), 
'PDSYEVR-WNEW', n, 1, wnew, n,
 
  409     $                   iprepad, ipostpad, padval+2.0d0 )
 
  411         CALL pdchekpad( desca( ctxt_ ), 
'PDSYEVR-GAP', nprow*npcol, 1,
 
  412     $                   gap, nprow*npcol, iprepad, ipostpad,
 
  415         CALL pdchekpad( desca( ctxt_ ), 
'PDSYEVR-WORK', lwork1, 1,
 
  416     $                   work, lwork1, iprepad, ipostpad,
 
  419         CALL pichekpad( desca( ctxt_ ), 
'PDSYEVR-IWORK', liwork, 1,
 
  420     $                   iwork, liwork, iprepad, ipostpad, ipadval )
 
  422        CALL pichekpad( desca( ctxt_ ), 
'PDSYEVR-IFAIL', n, 1, ifail,
 
  423     $                   n, iprepad, ipostpad, ipadval )
 
  425         CALL pichekpad( desca( ctxt_ ), 
'PDSYEVR-ICLUSTR',
 
  426     $                   2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
 
  427     $                   iprepad, ipostpad, ipadval )
 
  431         IF( lsame( range, 
'A' ) ) 
THEN 
  433     $                          iseed, wnew( 1+iprepad ), maxsize,
 
  443         CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp, 1, 1, 1,
 
  445         CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp( 2 ), 1, 1,
 
  449         IF( itmp( 1 ).NE.itmp( 2 ) ) 
THEN 
  451     $         
WRITE( nout, fmt = * )
 
  452     $         
'Different processes return different INFO' 
  454         ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
 
  457     $         
WRITE( nout, fmt = 9999 )info
 
  459         ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize ) 
THEN 
  461     $         
WRITE( nout, fmt = 9996 )info
 
  463         ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize ) 
THEN 
  465     $         
WRITE( nout, fmt = 9996 )info
 
  469         IF( lsame( jobz, 
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
 
  470     $       0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) ) 
THEN 
  472     $         
WRITE( nout, fmt = 9995 )
 
  478         IF( ( m.LT.0 ) .OR. ( m.GT.n ) ) 
THEN 
  480     $         
WRITE( nout, fmt = 9994 )
 
  481               WRITE( nout,*) 
'M = ', m, 
'\n', 
'N = ', n
 
  483         ELSE IF( lsame( range, 
'A' ) .AND. ( m.NE.n ) ) 
THEN 
  485     $         
WRITE( nout, fmt = 9993 )
 
  487         ELSE IF( lsame( range, 
'I' ) .AND. ( m.NE.iu-il+1 ) ) 
THEN 
  489               WRITE( nout, fmt = 9992 )
 
  490               WRITE( nout,*) 
'IL = ', il, 
' IU = ', iu, 
' M = ', m
 
  493         ELSE IF( lsame( jobz, 
'V' ) .AND.
 
  494     $            ( .NOT.( lsame( range, 
'V' ) ) ) .AND. ( m.NE.nz ) )
 
  497     $         
WRITE( nout, fmt = 9991 )
 
  503         IF( lsame( jobz, 
'V' ) ) 
THEN 
  504            IF( lsame( range, 
'V' ) ) 
THEN 
  507     $               
WRITE( nout, fmt = 9990 )
 
  510               IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 ) 
THEN 
  512     $               
WRITE( nout, fmt = 9989 )
 
  518     $               
WRITE( nout, fmt = 9988 )
 
  523         IF( result.EQ.0 ) 
THEN 
  530            CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp, 1, 1, 1,
 
  532            CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp( 2 ), 1,
 
  535            IF( itmp( 1 ).NE.itmp( 2 ) ) 
THEN 
  537     $            
WRITE( nout, fmt = 9987 )
 
  544                  work( i ) = wnew( i+iprepad )
 
  545                  work( i+m ) = wnew( i+iprepad )
 
  548               CALL dgamn2d( desca( ctxt_ ), 
'a', 
' ', m, 1, work, m, 1,
 
  550               CALL dgamx2d( desca( ctxt_ ), 
'a', 
' ', m, 1,
 
  551     $                       work( 1+m ), m, 1, 1, -1, -1, 0 )
 
  554                  IF( result.EQ.0 .AND. ( abs( work( i )-work( m+
 
  555     $                i ) ).GT.five*eps*abs( work( i ) ) ) ) 
THEN 
  557     $                  
WRITE( nout, fmt = 9986 )
 
  566         IF( lsame( jobz, 
'V' ) ) 
THEN 
  568            DO 90 i = 0, nprow*npcol - 1
 
  569               IF( iclustr( 1+iprepad+2*i ).EQ.0 )
 
  571               nclusters = nclusters + 1
 
  574            itmp( 1 ) = nclusters
 
  575            itmp( 2 ) = nclusters
 
  577            CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp, 1, 1, 1,
 
  579            CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp( 2 ), 1,
 
  582            IF( itmp( 1 ).NE.itmp( 2 ) ) 
THEN 
  584     $            
WRITE( nout, fmt = 9985 )
 
  590               DO 110 i = 1, nclusters
 
  591                  iwork( indiwrk+i ) = iclustr( i+iprepad )
 
  592                  iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
 
  594               CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', nclusters*2+1, 1,
 
  595     $                       iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
 
  597               CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', nclusters*2+1, 1,
 
  598     $                       iwork( indiwrk+1+nclusters ),
 
  599     $                       nclusters*2+1, 1, 1, -1, -1, 0 )
 
  601               DO 120 i = 1, nclusters
 
  602                  IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
 
  603     $                iwork( indiwrk+nclusters+i ) ) 
THEN 
  605     $                  
WRITE( nout, fmt = 9984 )
 
  610               IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 ) 
THEN 
  612     $               
WRITE( nout, fmt = 9983 )
 
  618         CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, result, 1, 1, 1,
 
  628            epsnorma = pdlansy( 
'I', uplo, n, copya, ia, ja, desca,
 
  632         IF( lsame( jobz, 
'V' ) ) 
THEN 
  636            CALL pdfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
 
  637     $                      iprepad, ipostpad, 4.3d0 )
 
  639            CALL pdsepchk( n, nz, copya, ia, ja, desca,
 
  640     $                     
max( abstol+epsnorma, safmin ), thresh,
 
  641     $                     z( 1+iprepad ), ia, ja, descz,
 
  642     $                     a( 1+iprepad ), ia, ja, desca,
 
  643     $                     wnew( 1+iprepad ), work( 1+iprepad ),
 
  644     $                     sizechk, tstnrm, res )
 
  646            CALL pdchekpad( desca( ctxt_ ), 
'PDSEPCHK-WORK', sizechk, 1,
 
  647     $                      work, sizechk, iprepad, ipostpad, 4.3d0 )
 
  654            CALL pdfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
 
  655     $                      iprepad, ipostpad, 4.3d0 )
 
  658            CALL pdsepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
 
  659     $                     a( 1+iprepad ), ia, ja, desca,
 
  660     $                     iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
 
  661     $                     gap( 1+iprepad ), work( iprepad+1 ), sizeqtq,
 
  662     $                     qtqnrm, info, res )
 
  664            CALL pdchekpad( desca( ctxt_ ), 
'PDSEPQTQ-WORK', sizeqtq, 1,
 
  665     $                      work, sizeqtq, iprepad, ipostpad, 4.3d0 )
 
  672     $            
WRITE( nout, fmt = 9998 )info
 
  683            IF( lsame( range, 
'V' ) ) 
THEN 
  688               IF( lsame( range, 
'A' ) ) 
THEN 
  700            DO 140 myil = minil, maxil
 
  705               misssmallest = .true.
 
  706               IF( .NOT.lsame( range, 
'V' ) .OR. ( myil.EQ.1 ) )
 
  707     $            misssmallest = .false.
 
  708               IF( misssmallest .AND. ( win( myil-1 ).LT.vl+normwin*
 
  709     $             five*thresh*eps ) )misssmallest = .false.
 
  711               IF( .NOT.lsame( range, 
'V' ) .OR. ( myil.EQ.maxil ) )
 
  712     $            misslargest = .false.
 
  713               IF( misslargest .AND. ( win( myil+m ).GT.vu-normwin*five*
 
  714     $             thresh*eps ) )misslargest = .false.
 
  715               IF( .NOT.misssmallest ) 
THEN 
  716                  IF( .NOT.misslargest ) 
THEN 
  723                        error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
 
  724                        maxerror = 
max( maxerror, error )
 
  727                     minerror = 
min( maxerror, minerror )
 
  737            IF( lsame( jobz, 
'V' ) .AND. lsame( range, 
'A' ) ) 
THEN 
  738               IF( minerror.GT.normwin*five*five*thresh*eps ) 
THEN 
  740     $               
WRITE( nout, fmt = 9997 )minerror, normwin
 
  744               IF( minerror.GT.normwin*five*thresh*eps ) 
THEN 
  746     $               
WRITE( nout, fmt = 9997 )minerror, normwin
 
  754         IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
 
  757     $         
WRITE( nout, fmt = 9982 )
 
  761         IF( lsame( jobz, 
'N' ) .AND. ( nz.NE.oldnz ) ) 
THEN 
  763     $         
WRITE( nout, fmt = 9981 )
 
  771      CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, result, 1, 1, 1, -1,
 
  778 9999 
FORMAT( 
'PDSYEVR returned INFO=', i7 )
 
  779 9998 
FORMAT( 
'PDSEPQTQ returned INFO=', i7 )
 
  780 9997 
FORMAT( 
'PDSEPRSUBTST minerror =', d11.2, 
' normwin=', d11.2 )
 
  781 9996 
FORMAT( 
'PDSYEVR returned INFO=', i7,
 
  782     $      
' despite adequate workspace' )
 
  783 9995 
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
 
  784 9994 
FORMAT( 
'M not in the range 0 to N' )
 
  785 9993 
FORMAT( 
'M not equal to N' )
 
  786 9992 
FORMAT( 
'M not equal to IU-IL+1' )
 
  787 9991 
FORMAT( 
'M not equal to NZ' )
 
  788 9990 
FORMAT( 
'NZ > M' )
 
  789 9989 
FORMAT( 
'NZ < M' )
 
  790 9988 
FORMAT( 
'NZ not equal to M' )
 
  791 9987 
FORMAT( 
'Different processes return different values for M' )
 
  792 9986 
FORMAT( 
'Different processes return different eigenvalues' )
 
  793 9985 
FORMAT( 
'Different processes return ',
 
  794     $      
'different numbers of clusters' )
 
  795 9984 
FORMAT( 
'Different processes return different clusters' )
 
  796 9983 
FORMAT( 
'ICLUSTR not zero terminated' )
 
  797 9982 
FORMAT( 
'IL, IU, VL or VU altered by PDSYEVR' )
 
  798 9981 
FORMAT( 
'NZ altered by PDSYEVR with JOBZ=N' )