1 SUBROUTINE pcstein( 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_ ),
'PCSTEIN', -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 pclaevswp( 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