1      SUBROUTINE psstein( N, D, E, M, W, IBLOCK, ISPLIT, ORFAC, Z, IZ,
 
    2     $                    JZ, DESCZ, WORK, LWORK, IWORK, LIWORK, IFAIL,
 
   11      INTEGER            INFO, IZ, JZ, LIWORK, LWORK, M, N
 
   15      INTEGER            DESCZ( * ), IBLOCK( * ), ICLUSTR( * ),
 
   16     $                   IFAIL( * ), ISPLIT( * ), IWORK( * )
 
   17      REAL               D( * ), E( * ), GAP( * ), W( * ), WORK( * ),
 
  264      INTRINSIC          abs, 
max, 
min, mod, real
 
  267      INTEGER            ICEIL, NUMROC
 
  268      EXTERNAL           ICEIL, NUMROC
 
  271      EXTERNAL           blacs_gridinfo, 
chk1mat, igamn2d, igebr2d,
 
  276      INTEGER            BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
 
  277     $                   MB_, NB_, RSRC_, CSRC_, LLD_
 
  278      parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
 
  279     $                   ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
 
  280     $                   rsrc_ = 7, csrc_ = 8, lld_ = 9 )
 
  281      REAL               ZERO, NEGONE, ODM1, FIVE, ODM3, ODM18
 
  282      PARAMETER          ( ZERO = 0.0e+0, negone = -1.0e+0,
 
  283     $                   odm1 = 1.0e-1, five = 5.0e+0, odm3 = 1.0e-3,
 
  287      LOGICAL            LQUERY, SORTED
 
  288      INTEGER            B1, BN, BNDRY, CLSIZ, COL, I, IFIRST, IINFO,
 
  289     $                   ilast, im, indrw, itmp, j, k, lgclsiz, llwork,
 
  290     $                   load, locinfo, maxvec, mq00, mycol, myrow,
 
  291     $                   nblk, nerr, next, np00, npcol, nprow, nvs,
 
  292     $                   olnblk, p, row, self, till, toterr
 
  293      REAL               DIFF, MINGAP, ONENRM, ORGFAC, ORTOL, TMPFAC
 
  296      INTEGER            IDUM1( 1 ), IDUM2( 1 )
 
  300      IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
 
  303      CALL blacs_gridinfo( descz( ctxt_ ), nprow, npcol, myrow, mycol )
 
  304      self = myrow*npcol + mycol
 
  309      IF( nprow.EQ.-1 ) 
THEN 
  310         info = -( 1200+ctxt_ )
 
  315         CALL chk1mat( n, 1, n, 1, iz, jz, descz, 12, info )
 
  321            np00 = numroc( n, descz( mb_ ), 0, 0, nprow )
 
  322            mq00 = numroc( m, descz( nb_ ), 0, 0, npcol )
 
  328            CALL igamn2d( descz( ctxt_ ), 
'A', 
' ', 1, 1, llwork, 1, 1,
 
  330            indrw = 
max( 5*n, np00*mq00 )
 
  332     $         maxvec = ( llwork-indrw ) / n
 
  334            IF( myrow.EQ.0 .AND. mycol.EQ.0 ) 
THEN 
  336               CALL sgebs2d( descz( ctxt_ ), 
'ALL', 
' ', 1, 1, tmpfac,
 
  339               CALL sgebr2d( descz( ctxt_ ), 
'ALL', 
' ', 1, 1, tmpfac,
 
  343            lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
 
  344            IF( m.LT.0 .OR. m.GT.n ) 
THEN 
  346            ELSE IF( maxvec.LT.load .AND. .NOT.lquery ) 
THEN 
  348            ELSE IF( liwork.LT.3*n+p+1 .AND. .NOT.lquery ) 
THEN 
  352                  IF( iblock( i ).LT.iblock( i-1 ) ) 
THEN 
  356                  IF( iblock( i ).EQ.iblock( i-1 ) .AND. w( i ).LT.
 
  364                  IF( abs( tmpfac-orfac ).GT.five*abs( tmpfac ) )
 
  372         CALL pchk1mat( n, 1, n, 1, iz, jz, descz, 12, 1, idum1, idum2,
 
  374         work( 1 ) = real( 
max( 5*n, np00*mq00 )+iceil( m, p )*n )
 
  375         iwork( 1 ) = 3*n + p + 1
 
  378         CALL pxerbla( descz( ctxt_ ), 
'PSSTEIN', -info )
 
  380      ELSE IF( lwork.EQ.-1 .OR. liwork.EQ.-1 ) 
THEN 
  399      IF( n.EQ.0 .OR. m.EQ.0 )
 
  402      IF( orfac.GE.zero ) 
THEN 
  412      IF( mod( m, load ).EQ.0 )
 
  419      DO 100 i = 0, ilast - 1
 
  423            nblk = iblock( next )
 
  424            IF( nblk.EQ.iblock( next-1 ) .AND. nblk.NE.olnblk ) 
THEN 
  431                  b1 = isplit( nblk-1 ) + 1
 
  435               onenrm = abs( d( b1 ) ) + abs( e( b1 ) )
 
  436               onenrm = 
max( onenrm, abs( d( bn ) )+abs( e( bn-1 ) ) )
 
  437               DO 60 j = b1 + 1, bn - 1
 
  438                  onenrm = 
max( onenrm, abs( d( j ) )+abs( e( j-1 ) )+
 
  446            IF( tmpfac.GT.odm18 ) 
THEN 
  447               ortol = tmpfac*onenrm
 
  448               DO 80 j = next - 1, 
min( till, m-1 )
 
  449                  IF( iblock( j+1 ).NE.iblock( j ) .OR. w( j+1 )-
 
  450     $                w( j ).GE.ortol ) 
THEN 
  454               IF( j.EQ.m .AND. till.GE.m )
 
  463     $      im = 
max( 0, j-nvs )
 
  470      iwork( ilast+1 ) = nvs
 
  471      DO 110 i = ilast + 2, p + 1
 
  482         IF( iblock( i ).NE.nblk ) 
THEN 
  487               b1 = isplit( nblk-1 ) + 1
 
  491            onenrm = abs( d( b1 ) ) + abs( e( b1 ) )
 
  492            onenrm = 
max( onenrm, abs( d( bn ) )+abs( e( bn-1 ) ) )
 
  493            DO 120 j = b1 + 1, bn - 1
 
  494               onenrm = 
max( onenrm, abs( d( j ) )+abs( e( j-1 ) )+
 
  500            diff = w( i ) - w( i-1 )
 
  501            IF( iblock( i ).NE.iblock( i-1 ) .OR. i.EQ.m .OR. diff.GT.
 
  502     $          orgfac*onenrm ) 
THEN 
  505                  IF( iblock( m ).NE.iblock( m-1 ) .OR. diff.GT.orgfac*
 
  514               clsiz = ilast - ifirst
 
  515               IF( clsiz.GT.1 ) 
THEN 
  516                  IF( lgclsiz.LT.clsiz )
 
  522                  IF( iwork( bndry ).GT.ifirst .AND. iwork( bndry ).LT.
 
  524                     mingap = 
min( w( iwork( bndry )+1 )-
 
  525     $                        w( iwork( bndry ) ), mingap )
 
  526                  ELSE IF( iwork( bndry ).GE.ilast ) 
THEN 
  527                     IF( mingap.LT.onenrm ) 
THEN 
  528                        iclustr( 2*k-1 ) = ifirst + 1
 
  529                        iclustr( 2*k ) = ilast
 
  530                        gap( k ) = mingap / onenrm
 
  542      info = ( k-1 )*( m+1 )
 
  546      CALL sstein2( n, d, e, im, w( iwork( self+1 )+1 ),
 
  547     $              iblock( iwork( self+1 )+1 ), isplit, orgfac,
 
  548     $              work( indrw+1 ), n, work, iwork( p+2 ),
 
  549     $              ifail( iwork( self+1 )+1 ), locinfo )
 
  559      CALL slasrt2( 
'I', m, w, iwork( p+2 ), iinfo )
 
  562         iwork( m+p+1+iwork( p+1+i ) ) = i
 
  566      DO 180 i = 1, locinfo
 
  567         itmp = iwork( self+1 ) + i
 
  568         ifail( itmp ) = ifail( itmp ) + itmp - i
 
  569         ifail( itmp ) = iwork( m+p+1+ifail( itmp ) )
 
  573         iclustr( 2*i-1 ) = iwork( m+p+1+iclustr( 2*i-1 ) )
 
  574         iclustr( 2*i ) = iwork( m+p+1+iclustr( 2*i ) )
 
  583         IF( self.EQ.i-1 ) 
THEN 
  584            CALL igebs2d( descz( ctxt_ ), 
'ALL', 
' ', 1, 1, locinfo, 1 )
 
  585            IF( locinfo.NE.0 ) 
THEN 
  586               CALL igebs2d( descz( ctxt_ ), 
'ALL', 
' ', locinfo, 1,
 
  587     $                       ifail( iwork( i )+1 ), locinfo )
 
  588               DO 200 j = 1, locinfo
 
  589                  ifail( toterr+j ) = ifail( iwork( i )+j )
 
  591               toterr = toterr + locinfo
 
  595            row = ( i-1 ) / npcol
 
  596            col = mod( i-1, npcol )
 
  598            CALL igebr2d( descz( ctxt_ ), 
'ALL', 
' ', 1, 1, nerr, 1,
 
  601               CALL igebr2d( descz( ctxt_ ), 
'ALL', 
' ', nerr, 1,
 
  602     $                       ifail( toterr+1 ), nerr, row, col )
 
  603               toterr = toterr + nerr
 
  610      CALL pslaevswp( n, work( indrw+1 ), n, z, iz, jz, descz, iwork,
 
  611     $                iwork( m+p+2 ), work, indrw )
 
  614         iwork( i ) = iwork( m+p+1+iwork( i ) )
 
  624         IF( iwork( i ).GT.iwork( i+1 ) ) 
THEN 
  626            iwork( i+1 ) = iwork( i )
 
  634      DO 250 i = p + 1, 1, -1
 
  635         iwork( i+1 ) = iwork( i )
 
  638      work( 1 ) = ( lgclsiz+load-1 )*n + indrw
 
  639      iwork( 1 ) = 3*n + p + 1