1      SUBROUTINE pssepsubtst( 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,
 
   15      CHARACTER          JOBZ, RANGE, UPLO
 
   16      INTEGER            IA, IL, IPOSTPAD, IPREPAD, IU, JA, LIWORK,
 
   17     $                   LWORK, LWORK1, N, NOUT, RESULT
 
   18      REAL               ABSTOL, QTQNRM, THRESH, TSTNRM, VL, VU
 
   21      INTEGER            DESCA( * ), ICLUSTR( * ), IFAIL( * ),
 
   23      REAL               A( * ), COPYA( * ), GAP( * ), WIN( * ),
 
   24     $                   WNEW( * ), WORK( * ), Z( * )
 
  196      INTEGER            BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
 
  197     $                   MB_, NB_, RSRC_, CSRC_, LLD_
 
  198      PARAMETER          ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
 
  199     $                   ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
 
  200     $                   rsrc_ = 7, csrc_ = 8, lld_ = 9 )
 
  201      REAL               PADVAL, FIVE, NEGONE
 
  202      PARAMETER          ( PADVAL = 13.5285e+0, five = 5.0e+0,
 
  205      PARAMETER          ( IPADVAL = 927 )
 
  208      INTEGER            I, IAM, INDIWRK, INFO, ISIZESUBTST, ISIZESYEVX,
 
  209     $                   isizetst, j, m, maxeigs, maxil, maxiu, maxsize,
 
  210     $                   minil, mq, mycol, myil, myrow, nclusters, np,
 
  211     $                   npcol, nprow, nq, nz, oldil, oldiu, oldnz, res,
 
  212     $                   sizechk, sizemqrleft, sizemqrright, sizeqrf,
 
  213     $                   sizeqtq, sizesubtst, sizesyevx, sizetms,
 
  214     $                   sizetst, valsize, vecsize
 
  215      REAL               EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
 
  216     $                   MINERROR, MINVL, NORMWIN, OLDVL, OLDVU, ORFAC,
 
  220      INTEGER            DESCZ( DLEN_ ), DSEED( 4 ), ITMP( 2 )
 
  226      REAL               PSLAMCH, PSLANSY
 
  227      EXTERNAL           LSAME, NUMROC, PSLAMCH, PSLANSY
 
  230      EXTERNAL           blacs_gridinfo, 
descinit, igamn2d, igamx2d,
 
  237      INTRINSIC          abs, 
max, 
min, mod
 
  241      IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
 
  243      CALL pslasizesep( desca, iprepad, ipostpad, sizemqrleft,
 
  244     $                  sizemqrright, sizeqrf, sizetms, sizeqtq,
 
  245     $                  sizechk, sizesyevx, isizesyevx, sizesubtst,
 
  246     $                  isizesubtst, sizetst, isizetst )
 
  250      eps = pslamch( desca( ctxt_ ), 
'Eps' )
 
  251      safmin = pslamch( desca( ctxt_ ), 
'Safe min' )
 
  252      normwin = safmin / eps
 
  254     $   normwin = 
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
 
  266      DO 10 i = 1, lwork1, 1
 
  267         work( i+iprepad ) = 14.3e+0
 
  269      DO 20 i = 1, liwork, 1
 
  270         iwork( i+iprepad ) = 14
 
  274         wnew( i+iprepad ) = 3.14159e+0
 
  277      iclustr( 1+iprepad ) = 139
 
  279      IF( lsame( jobz, 
'N' ) ) 
THEN 
  282         IF( lsame( range, 
'A' ) ) 
THEN 
  284         ELSE IF( lsame( range, 
'I' ) ) 
THEN 
  285            maxeigs = iu - il + 1
 
  287            minvl = vl - normwin*five*eps - abstol
 
  288            maxvu = vu + normwin*five*eps + abstol
 
  292               IF( win( i ).LT.minvl )
 
  294               IF( win( i ).LE.maxvu )
 
  298            maxeigs = maxiu - minil + 1
 
  303      CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
 
  304     $               desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
 
  305     $               desca( ctxt_ ), desca( lld_ ), info )
 
  307      CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
 
  308      indiwrk = 1 + iprepad + nprow*npcol + 1
 
  311      IF( myrow.EQ.0 .AND. mycol.EQ.0 )
 
  317      IF( myrow.GE.nprow .OR. myrow.LT.0 )
 
  328     $                    dseed, win, maxsize, vecsize, valsize )
 
  330      np = numroc( n, desca( mb_ ), myrow, 0, nprow )
 
  331      nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
 
  332      mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
 
  334      CALL slacpy( 
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
 
  337      CALL psfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
 
  340      CALL psfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
 
  341     $                ipostpad, padval+1.0e+0 )
 
  343      CALL psfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
 
  346      CALL psfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
 
  347     $                iprepad, ipostpad, padval+3.0e+0 )
 
  349      CALL psfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
 
  350     $                ipostpad, padval+4.0e+0 )
 
  352      CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
 
  353     $                ipostpad, ipadval )
 
  355      CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
 
  358      CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
 
  359     $                2*nprow*npcol, iprepad, ipostpad, ipadval )
 
  365         DO 50 j = 1, maxeigs, 1
 
  366            CALL pselset( z( 1+iprepad ), i, j, desca, 13.0e+0 )
 
  375      CALL pssyevx( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
 
  376     $              vl, vu, il, iu, abstol, m, nz, wnew( 1+iprepad ),
 
  377     $              orfac, z( 1+iprepad ), ia, ja, desca,
 
  378     $              work( 1+iprepad ), lwork1, iwork( 1+iprepad ),
 
  379     $              liwork, ifail( 1+iprepad ), iclustr( 1+iprepad ),
 
  380     $              gap( 1+iprepad ), info )
 
  384      IF( thresh.LE.0 ) 
THEN 
  387         CALL pschekpad( desca( ctxt_ ), 
'PSSYEVX-A', np, nq, a,
 
  388     $                   desca( lld_ ), iprepad, ipostpad, padval )
 
  390         CALL pschekpad( descz( ctxt_ ), 
'PSSYEVX-Z', np, mq, z,
 
  391     $                   descz( lld_ ), iprepad, ipostpad,
 
  394         CALL pschekpad( desca( ctxt_ ), 
'PSSYEVX-WNEW', n, 1, wnew, n,
 
  395     $                   iprepad, ipostpad, padval+2.0e+0 )
 
  397         CALL pschekpad( desca( ctxt_ ), 
'PSSYEVX-GAP', nprow*npcol, 1,
 
  398     $                   gap, nprow*npcol, iprepad, ipostpad,
 
  401         CALL pschekpad( desca( ctxt_ ), 
'PSSYEVX-WORK', lwork1, 1,
 
  402     $                   work, lwork1, iprepad, ipostpad,
 
  405         CALL pichekpad( desca( ctxt_ ), 
'PSSYEVX-IWORK', liwork, 1,
 
  406     $                   iwork, liwork, iprepad, ipostpad, ipadval )
 
  408         CALL pichekpad( desca( ctxt_ ), 
'PSSYEVX-IFAIL', n, 1, ifail,
 
  409     $                   n, iprepad, ipostpad, ipadval )
 
  411         CALL pichekpad( desca( ctxt_ ), 
'PSSYEVX-ICLUSTR',
 
  412     $                   2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
 
  413     $                   iprepad, ipostpad, ipadval )
 
  418         IF( lsame( range, 
'A' ) ) 
THEN 
  420     $                          dseed, wnew( 1+iprepad ), maxsize,
 
  433         CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp, 1, 1, 1,
 
  435         CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp( 2 ), 1, 1,
 
  439         IF( itmp( 1 ).NE.itmp( 2 ) ) 
THEN 
  441     $         
WRITE( nout, fmt = * )
 
  442     $         
'Different processes return different INFO' 
  444         ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
 
  447     $         
WRITE( nout, fmt = 9999 )info
 
  449         ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize ) 
THEN 
  451     $         
WRITE( nout, fmt = 9996 )info
 
  453         ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize ) 
THEN 
  455     $         
WRITE( nout, fmt = 9996 )info
 
  460         IF( lsame( jobz, 
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
 
  461     $       0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) ) 
THEN 
  463     $         
WRITE( nout, fmt = 9995 )
 
  469         IF( ( m.LT.0 ) .OR. ( m.GT.n ) ) 
THEN 
  471     $         
WRITE( nout, fmt = 9994 )
 
  473         ELSE IF( lsame( range, 
'A' ) .AND. ( m.NE.n ) ) 
THEN 
  475     $         
WRITE( nout, fmt = 9993 )
 
  477         ELSE IF( lsame( range, 
'I' ) .AND. ( m.NE.iu-il+1 ) ) 
THEN 
  479     $         
WRITE( nout, fmt = 9992 )
 
  481         ELSE IF( lsame( jobz, 
'V' ) .AND.
 
  482     $           ( .NOT.( lsame( range, 
'V' ) ) ) .AND. ( m.NE.nz ) )
 
  485     $         
WRITE( nout, fmt = 9991 )
 
  491         IF( lsame( jobz, 
'V' ) ) 
THEN 
  492            IF( lsame( range, 
'V' ) ) 
THEN 
  495     $               
WRITE( nout, fmt = 9990 )
 
  498               IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 ) 
THEN 
  500     $               
WRITE( nout, fmt = 9989 )
 
  506     $               
WRITE( nout, fmt = 9988 )
 
  511         IF( result.EQ.0 ) 
THEN 
  518            CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp, 1, 1, 1,
 
  520            CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp( 2 ), 1,
 
  523            IF( itmp( 1 ).NE.itmp( 2 ) ) 
THEN 
  525     $            
WRITE( nout, fmt = 9987 )
 
  532                  work( i ) = wnew( i+iprepad )
 
  533                  work( i+m ) = wnew( i+iprepad )
 
  536               CALL sgamn2d( desca( ctxt_ ), 
'a', 
' ', m, 1, work, m, 1,
 
  538               CALL sgamx2d( desca( ctxt_ ), 
'a', 
' ', m, 1,
 
  539     $                       work( 1+m ), m, 1, 1, -1, -1, 0 )
 
  542                  IF( result.EQ.0 .AND. work( i ).NE.work( m+i ) ) 
THEN 
  544     $                  
WRITE( nout, fmt = 9986 )
 
  553         IF( lsame( jobz, 
'V' ) ) 
THEN 
  555            DO 90 i = 0, nprow*npcol - 1
 
  556               IF( iclustr( 1+iprepad+2*i ).EQ.0 )
 
  558               nclusters = nclusters + 1
 
  561            itmp( 1 ) = nclusters
 
  562            itmp( 2 ) = nclusters
 
  564            CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp, 1, 1, 1,
 
  566            CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, itmp( 2 ), 1,
 
  569            IF( itmp( 1 ).NE.itmp( 2 ) ) 
THEN 
  571     $            
WRITE( nout, fmt = 9985 )
 
  577               DO 110 i = 1, nclusters
 
  578                  iwork( indiwrk+i ) = iclustr( i+iprepad )
 
  579                  iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
 
  581               CALL igamn2d( desca( ctxt_ ), 
'a', 
' ', nclusters*2+1, 1,
 
  582     $                       iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
 
  584               CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', nclusters*2+1, 1,
 
  585     $                       iwork( indiwrk+1+nclusters ),
 
  586     $                       nclusters*2+1, 1, 1, -1, -1, 0 )
 
  589               DO 120 i = 1, nclusters
 
  590                  IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
 
  591     $                iwork( indiwrk+nclusters+i ) ) 
THEN 
  593     $                  
WRITE( nout, fmt = 9984 )
 
  598               IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 ) 
THEN 
  600     $               
WRITE( nout, fmt = 9983 )
 
  607         CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, result, 1, 1, 1,
 
  617            epsnorma = pslansy( 
'I', uplo, n, copya, ia, ja, desca,
 
  631         IF( lsame( jobz, 
'V' ) ) 
THEN 
  635            CALL psfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
 
  636     $                      iprepad, ipostpad, 4.3e+0 )
 
  638            CALL pssepchk( n, nz, copya, ia, ja, desca,
 
  639     $                     
max( abstol+epsnorma, safmin ), thresh,
 
  640     $                     z( 1+iprepad ), ia, ja, descz,
 
  641     $                     a( 1+iprepad ), ia, ja, desca,
 
  642     $                     wnew( 1+iprepad ), work( 1+iprepad ),
 
  643     $                     sizechk, tstnrm, res )
 
  645            CALL pschekpad( desca( ctxt_ ), 
'PSSEPCHK-WORK', sizechk, 1,
 
  646     $                      work, sizechk, iprepad, ipostpad, 4.3e+0 )
 
  653            CALL psfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
 
  654     $                      iprepad, ipostpad, 4.3e+0 )
 
  657            CALL pssepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
 
  658     $                     a( 1+iprepad ), ia, ja, desca,
 
  659     $                     iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
 
  660     $                     gap( 1+iprepad ), work( iprepad+1 ), sizeqtq,
 
  661     $                     qtqnrm, info, res )
 
  663            CALL pschekpad( desca( ctxt_ ), 
'PSSEPQTQ-WORK', sizeqtq, 1,
 
  664     $                      work, sizeqtq, iprepad, ipostpad, 4.3e+0 )
 
  671     $            
WRITE( nout, fmt = 9998 )info
 
  684            IF( lsame( range, 
'V' ) ) 
THEN 
  689               IF( lsame( range, 
'A' ) ) 
THEN 
  701            DO 140 myil = minil, maxil
 
  706               IF( .NOT.lsame( range, 
'V' ) .OR.
 
  707     $             ( myil.EQ.1 .OR. ( win( myil-1 ).LT.vl+normwin*five*
 
  708     $             thresh*eps ) ) ) 
THEN 
  709                  IF( .NOT.lsame( range, 
'V' ) .OR.
 
  710     $                ( myil.EQ.n-m+1 .OR. ( win( myil+m ).GT.vu-
 
  711     $                normwin*five*thresh*eps ) ) ) 
THEN 
  716                        error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
 
  717                        maxerror = 
max( maxerror, error )
 
  720                     minerror = 
min( maxerror, minerror )
 
  731            IF( lsame( jobz, 
'V' ) .AND. lsame( range, 
'A' ) ) 
THEN 
  732               IF( minerror.GT.normwin*five*five*thresh*eps ) 
THEN 
  734     $               
WRITE( nout, fmt = 9997 )minerror, normwin
 
  738               IF( minerror.GT.normwin*five*thresh*eps ) 
THEN 
  740     $               
WRITE( nout, fmt = 9997 )minerror, normwin
 
  749         IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
 
  752     $         
WRITE( nout, fmt = 9982 )
 
  756         IF( lsame( jobz, 
'N' ) .AND. ( nz.NE.oldnz ) ) 
THEN 
  758     $         
WRITE( nout, fmt = 9981 )
 
  766      CALL igamx2d( desca( ctxt_ ), 
'a', 
' ', 1, 1, result, 1, 1, 1, -1,
 
  774 9999 
FORMAT( 
'PSSYEVX returned INFO=', i7 )
 
  775 9998 
FORMAT( 
'PSSEPQTQ returned INFO=', i7 )
 
  776 9997 
FORMAT( 
'PSSEPSUBTST minerror =', d11.2, 
' normwin=', d11.2 )
 
  777 9996 
FORMAT( 
'PSSYEVX returned INFO=', i7,
 
  778     $      
' despite adequate workspace' )
 
  779 9995 
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
 
  780 9994 
FORMAT( 
'M not in the range 0 to N' )
 
  781 9993 
FORMAT( 
'M not equal to N' )
 
  782 9992 
FORMAT( 
'M not equal to IU-IL+1' )
 
  783 9991 
FORMAT( 
'M not equal to NZ' )
 
  784 9990 
FORMAT( 
'NZ > M' )
 
  785 9989 
FORMAT( 
'NZ < M' )
 
  786 9988 
FORMAT( 
'NZ not equal to M' )
 
  787 9987 
FORMAT( 
'Different processes return different values for M' )
 
  788 9986 
FORMAT( 
'Different processes return different eigenvalues' )
 
  789 9985 
FORMAT( 
'Different processes return ',
 
  790     $      
'different numbers of clusters' )
 
  791 9984 
FORMAT( 
'Different processes return different clusters' )
 
  792 9983 
FORMAT( 
'ICLUSTR not zero terminated' )
 
  793 9982 
FORMAT( 
'IL, IU, VL or VU altered by PSSYEVX' )
 
  794 9981 
FORMAT( 
'NZ altered by PSSYEVX with JOBZ=N' )